Compare commits

..

72 commits

Author SHA1 Message Date
Matthias Riße
941978ccd6 fix: set committer identity for p2phttp processes (#76)
Some checks failed
/ release (push) Waiting to run
/ build-oci-image (rootful) (push) Failing after 1m30s
/ build-oci-image (rootless) (push) Failing after 1m28s
testing / backend-checks (push) Successful in 30m42s
testing / frontend-checks (push) Successful in 3m25s
testing / test-unit (push) Has been skipped
testing / test-e2e (push) Has been skipped
testing / test-mysql (push) Failing after 46m55s
testing / test-pgsql (push) Failing after 1h1m39s
testing / test-sqlite (push) Failing after 1h21m26s
testing / test-remote-cacher (redis) (push) Has been skipped
testing / security-check (push) Has been skipped
testing / test-remote-cacher (valkey) (push) Has been skipped
testing / test-remote-cacher (garnet) (push) Has been skipped
testing / test-remote-cacher (redict) (push) Has been skipped
Just setting GIT_AUTHOR_{NAME,EMAIL} wasn't enough,
GIT_COMMITTER_{NAME,EMAIL} is also required.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/76
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
matrss
8dfc054035 Forgejo-aneksajo branding (#71)
The original logo was created by Caesar Schinas and is licensed under
the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA
4.0) license.

This implies permission to remix.

Source: https://codeberg.org/forgejo/governance/src/branch/main/branding#logo

The git-annex logo is covered by

```
Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>
           2010 Joey Hess <id@joeyh.name>
           2013 John Lawrence
           2024 Yann Büchau <nobodyinperson at posteo de>
License: other
  Free to modify and redistribute with due credit, and obviously free to use.
```

Source: https://git-annex.branchable.com/logo/
Co-authored-by: Michael Hanke <michael.hanke@gmail.com>
Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/71
2025-06-12 15:16:47 +02:00
Matthias Riße
c38d65118b fix: set git identity for p2phttp processes (#70)
In some situations it could happen that `git annex p2phttp` needs some
kind of maintenance work resulting in a commit, but without a configured
git identity p2phttp would refuse to run. This could break p2phttp
support.

Setting `GIT_AUTHOR_{NAME,EMAIL}` should remedy this issue.

Fixes #69.

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/70
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
1eefa7e461 feat: copy annexed files on pull request merge (#62)
This changes the PR merge process such that annexed files contained in the to-be-merged commits are copied from the head repository to the base repository as part of the merge, similar to how it is done for LFS files.

Fixes #11.

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/62
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
243aa534b5 fix: improve git-annex UUID cache update times (#65)
Globbing for the config files is marginally faster than walking the
directory and checking for config files. Replacing the expensive calls
to `git config` for each repository with reading the repository's config
as an ini file is two orders of magnitude faster.

All in all this reduces the required time initializing the cache for
approx. 3000 repositories from approx. 5s to 50ms.

The server startup now also logs how long the cache update took and the
cache update is only done if p2phttp support is not disabled, because
p2phttp support is currently the only feature that requires the UUID
cache.

Fixes #63, fixes #64.

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/65
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
2bce84f4e6 Use annexed content for comparison in diffs (#57)
This makes it such that annexed files are treated like plain git files
in comparisons (e.g. the diff of a commit).

It also changes the image diff viewer to show a more reasonable error
message when one of the annexed files under comparison is missing.

Fixes #56.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/57
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
382c22b9fd Invalidate outdated annex UUID cache entries (#60)
The previous implementation could lead to errors e.g. when a repository
was removed and a new one with a new UUID was created under the same
name. This now checks the validity of the retrieved cache entry every
time and invalidates the cache if necessary.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/60
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
9642986bc3 Pre-populate the git-annex UUID cache at startup (#59)
This eliminates the wait time for the first p2phttp connection since
server startup at the cost of adding that time to the startup itself.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/59
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
63bf28d641 Cache git-annex UUID to repository path mappings (#54)
Always walking the filesystem and searching for UUIDs slowed p2phttp
operations down significantly on a production server with more than a
handful of repositories. This caching strategy ensures that only the
first call is rather slow, and subsequent ones should be much faster.

This should better be implemented as a background job, but for now this
is a simple solution to the problem.

Fixes #53.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/54
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
864ff830de Explicitly set http(s) default ports in annex.url (#55)
Otherwise, git-annex tries to use its own default port (9417) and fails.

Fixes #52.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/55
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
8d026ef459 Fix Forgejo version in published OCI images (#51)
The Forgejo version is derived from the git history, so the image build
needs to happen in the context of a full repository clone.

Also, the post-processing of the version string needs to remove the
second occurrence of "-g", as the first one is now part of the added
"-git-annex" part.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/51
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
b3f59b8104 Add an OCI image build and publish workflow (#50)
Fixes #49.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/50
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
9044e035e7 Simplify git blob to annex key lookup (#43)
Fixes #27.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/43
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
a0671027f6 Add git-annex p2phttp support (#42)
This adds a new endpoint under `/git-annex-p2phttp` which acts as an
authenticating proxy to git-annex' p2phttp server. This makes it
possible to set `annex+<server-url>/git-annex-p2phttp` as
`remote.<name>.annexurl` and use git-annex fully over http(s) with the
normal credentials and access tokens provided by Forgejo.

Fixes #25.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/42
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
70db833e76 Add tests for git annex drop (#47)
This adds some rudimentary tests that drop files in a repository's clone
as well as from a repository on Forgejo.

Fixes #4.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/47
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
fd300fd235 Add git-annex' testremote to the test suite (#48)
The `git annex testremote` command runs a built-in set of tests against
a remote. It cannot hurt to check our implementation of a git-annex
remote against it too.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/48
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
e608b7fac4 Only upload to annex in doAnnexUploadTest (#46)
The previous implementation both uploaded to the annex and pushed to the
git repository. This meant that the tests checking that uploads without
permission fail actually could pass when the git push failed but the
git-annex upload didn't. The tests didn't catch the situation where
unauthorized users could modify the annex.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/46
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
69d42f2f81 Use PATH when looking for git commands (#44)
This fixes some issues when using a git-annex that is installed in a
different location than where git is installed, e.g. when using the
git-annex-standalone release or one installed with nix.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/44
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Michael Hanke
ac4b8e579c Elevate external markup renderer interface for annexed file content (#36)
Previously, an external renderer that matched on an annexed file would
only see its content streamed via `STDIN`, or a temporary file with a copy
of its content would be generated and passed-by-filepath (with
`IS_INPUT_FILE=true`). Whether that happens, is also subject to
`MAX_DISPLAY_FILE_SIZE` (which defaults to 8MB).

This was problematic, because annexed files tend to be large. Moreover,
if present, they already exist as write-protected files on the
file-system. Creating a copy is both expensive and serves no particular
purpose.

This commit changes how external renderers are called.

1) With `IS_INPUT_FILE=true`, the renderer is passed the true location
   of an annex key, if present, and an empty path, if not.
2) The original, repository-relative path of the rendering target is
   made available to the renderer via the `GITEA_RELATIVE_PATH`
   environment variable.

To achieve a lean implementation, the `Blob` of the rendering target
is passed on to the `RenderContext` (because the implementation of
the annex-related functionality is centered on this dtype.

This change makes it less costly to increase `MAX_DISPLAY_FILE_SIZE`,
in order to make large, annexed files eligible for markup rendering,
because no content copies will be made any longer.

External renderers can now use the original file path, with the full
original filename, including extensions, for decision making. For
example, to detect particular compression formats based in a file name
extension, or to alter the rendering based on contextual information
encoded in the file path (e.g., a multi-file data structure with a
particular organization pattern).

Apart from the additional environment variable, there is no change to
the handling of renderers that take their input via `STDIN` (i.e.,
`IS_INPUT_FILE=false`).

Fixes #35.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/36
Reviewed-by: matrss <matrss@noreply.codeberg.org>
Co-authored-by: Michael Hanke <michael.hanke@gmail.com>
Co-committed-by: Michael Hanke <michael.hanke@gmail.com>
2025-06-12 15:16:46 +02:00
Matthias Riße
945d723776 Change the icon for annexed files to file-binary (#29)
Fixes #26.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/29
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
e3cb0ebfd0 Improve views for annexed but missing files (#28)
Previously, trying to view files that were annexed, but missing, just
led to an uninformative error 500. This was rather confusing.

With these changes it now shows the pointer target instead of the
(missing) content of the file, and also indicates this situation in the
"stored with git-annex" message. For semantic correctness views for
missing files return a 404 instead of a 200, as they would with the
content present.

Fixes #7, fixes #13.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/28
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Michael Hanke
8edbc40475 Add git-annex also to the rootless container (#24)
Same as 89f8aa0bf5, but for the rootless container.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/24
Reviewed-by: matrss <matrss@noreply.codeberg.org>
Co-authored-by: Michael Hanke <michael.hanke@gmail.com>
Co-committed-by: Michael Hanke <michael.hanke@gmail.com>
2025-06-12 15:16:46 +02:00
Matthias Riße
36d2cdeab8 Git-annex web uploads (#21)
This implements support for uploading files into the annex using the web
interface.

If a repository is a git-annex-enabled repository all files will be
added to it using git annex add. This means that the repository's
configuration for what to put into the annex (annex.largefiles in
gitattributes) will be respected.

Plain git repositories without git-annex will work as before, directly
uploading to git.

Fixes #5.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/21
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
a57a7df088 Error if git-annex is enabled but missing (#16)
Copied from https://github.com/neuropoly/gitea/pull/47

This adds a check so that if `setting.Annex.Enabled` is true and git-annex is not in the PATH Forgejo will abort on startup with a reasonable error message.

Fixes #15.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/16
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
4d537d3399 Add git-annex to docker image 2025-06-12 15:16:46 +02:00
Matthias Riße
ae1c051cd0 Adapt patch to upstream changes
Test with different objectFormats.
2025-06-12 15:16:46 +02:00
Nick
227f0c0c7c git-annex: views for annex files
This updates the repo index/file view endpoints so annex files match the way
LFS files are rendered, making annexed files accessible via the web instead of
being black boxes only accessible by git clone.

This mostly just duplicates the existing LFS logic. It doesn't try to combine itself
with the existing logic, to make merging with upstream easier. If upstream ever
decides to accept, I would like to try to merge the redundant logic.

The one bit that doesn't directly copy LFS is my choice to hide annex-symlinks.
LFS files are always _pointer files_ and therefore always render with the "file"
icon and no special label, but annex files come in two flavours: symlinks or
pointer files. I've conflated both kinds to try to give a consistent experience.

The tests in here ensure the correct download link (/media, from the last PR)
renders in both the toolbar and, if a binary file (like most annexed files will be),
in the main pane, but it also adds quite a bit of code to make sure text files
that happen to be annexed are dug out and rendered inline like LFS files are.
2025-06-12 15:16:46 +02:00
Matthias Riße
8f7583454c Adapt patch to upstream changes
Use tests.FileCmp instead of util.FileCmp.
2025-06-12 15:16:46 +02:00
Matthias Riße
5326357578 Adapt patch to upstream changes
Test with different objectFormats.
2025-06-12 15:16:46 +02:00
Nick
3091d08359 git-annex: make /media/ download annexed content
Previously, Gitea's LFS support allowed direct-downloads of LFS content,
via http://$HOSTNAME:$PORT/$USER/$REPO/media/branch/$BRANCH/$FILE
Expand that grace to git-annex too. Now /media should provide the
relevant *content* from the .git/annex/objects/ folder.

This adds tests too. And expands the tests to try symlink-based annexing,
since /media implicitly supports both that and pointer-file-based annexing.
2025-06-12 15:16:45 +02:00
Matthias Riße
f7e27e2c61 Adapt patch to upstream changes
The git repository must be closed after using it. Without this change
some tests started to fail due to the lingering repository running into
a timeout.
2025-06-12 15:16:45 +02:00
Nick
8f5e08da72 git-annex: create modules/annex
This moves the `annexObjectPath()` helper out of the tests and into a
dedicated sub-package as `annex.ContentLocation()`, and expands it with
`.Pointer()` (which validates using `git annex examinekey`),
`.IsAnnexed()` and `.Content()` to make it a more useful module.

The tests retain their own wrapper version of `ContentLocation()`
because I tried to follow close to the API modules/lfs uses, which in
terms of abstract `git.Blob` and `git.TreeEntry` objects, not in terms
of `repoPath string`s which are more convenient for the tests.
2025-06-12 15:16:45 +02:00
Matthias Riße
7cc829b466 Adapt patch to upstream changes
The "context_service" import was changed to use the default name of just
"context". The patch set had to be adapted for that.
2025-06-12 15:16:45 +02:00
Matthias Riße
257dd3a241 Adapt patch to upstream changes
Usage of `path` was replaced by `path/filepath` in upstream forgejo, and
it made sense to use that as well where `path` was previously used. The
`setHeaderCacheForever` function and the `sendFile` method had their
signature changed.
2025-06-12 15:16:45 +02:00
Matthias Riße
d52b0beb04 Fix exit code check for git command
The err.IsExitCode method was changed to a function IsErrorExitCode
taking err as its first argument in
1e7a6483b8.
2025-06-12 15:16:45 +02:00
Matthias Riße
709a2b1032 Replace m.GetOptions with m.Methods
This applies the same changes that were done in
265cd70bdb to the git-annex specific
routes as well.
2025-06-12 15:16:45 +02:00
Nick
96639554a1 git-annex: support downloading over HTTP
This makes HTTP symmetric with SSH clone URLs.

This gives us the fancy feature of _anonymous_ downloads,
so people can access datasets without having to set up an
account or manage ssh keys.

Previously, to access "open access" data shared this way,
users would need to:

  1. Create an account on gitea.example.com
  2. Create ssh keys
  3. Upload ssh keys (and make sure to find and upload the correct file)
  4. `git clone git@gitea.example.com:user/dataset.git`
  5. `cd dataset`
  6. `git annex get`

This cuts that down to just the last three steps:

  1. `git clone https://gitea.example.com/user/dataset.git`
  2. `cd dataset`
  3. `git annex get`

This is significantly simpler for downstream users, especially for those
unfamiliar with the command line.

Unfortunately there's no uploading. While git-annex supports uploading
over HTTP to S3 and some other special remotes, it seems to fail on a
_plain_ HTTP remote. See https://github.com/neuropoly/gitea/issues/7
and https://git-annex.branchable.com/forum/HTTP_uploads/#comment-ce28adc128fdefe4c4c49628174d9b92.

This is not a major loss since no one wants uploading to be anonymous anyway.

To support private repos, I had to hunt down and patch a secret extra security
corner that Gitea only applies to HTTP for some reason (services/auth/basic.go).

This was guided by https://git-annex.branchable.com/tips/setup_a_public_repository_on_a_web_site/

Fixes https://github.com/neuropoly/gitea/issues/3

Co-authored-by: Mathieu Guay-Paquet <mathieu.guaypaquet@polymtl.ca>
2025-06-12 15:16:45 +02:00
Nick
4eef1f0299 git-annex: add configuration setting [annex].ENABLED
Fixes https://github.com/neuropoly/gitea/issues/8

Co-authored-by: Mathieu Guay-Paquet <mathieu.guaypaquet@gmail.com>
2025-06-12 15:16:45 +02:00
Matthias Riße
108ceba1f8 Fix failing tests
Multiple tests that worked fine on v1.20.4-1 started to fail after the
rebase onto v1.20.5-1. These tests are:
- TestGitAnnexPermissions/Private/Owner/HTTP/Init
- TestGitAnnexPermissions/Private/Owner/HTTP/Download
- TestGitAnnexPermissions/Private/Writer/HTTP/Init
- TestGitAnnexPermissions/Private/Writer/HTTP/Download
- TestGitAnnexPermissions/Private/Reader/HTTP/Init
- TestGitAnnexPermissions/Private/Reader/HTTP/Download

What these tests have in common is that they all operate on a private
repository via http with authentication.

They broke at some point between v1.20.4-1 and v1.20.5-1, so I did a
bisect between these two points running the offending tests. This
brought me to the conclusion that
ee48c0d5ea introduced the issue.

The thing is, this commit does not change any code, it only changes the
test environment. Among other things that didn't look as suspicious, it
changes the container image from a bespoke test_env image based on
debian bullseye to a node image based on debian bookworm. Obviously,
this means that there are many version differences between the two.

The first one I looked at was git. The previous bullseye image used a
manually installed git version 2.40.0, while the bookworm image has
2.39.2 installed. Updating git in the new image did not fix the issue,
however.

The next thing I looked at was the git-annex version. Bullseye had
8.20210223 installed and worked, while bookworm used 10.20230126 when
the tests broke. So I tried my luck upgrading to a more recent version
via neurodebian (10.20240227-1~ndall+1). This still worked fine on
bullseye and now also works fine on bookworm.

I have no idea why this specific version of git-annex broke the tests,
but at least there was a commit to pinpoint this to, which isn't always
the case with docker images silently changing beneath you...

Below are the versions as they are reported by git and git-annex:

bullseye (works):

    git version 2.30.2
    git-annex version: 8.20210223
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22 bloomfilter-2.0.1.0 cryptonite-0.26 DAV-1.3.4 feed-1.3.0.1 ghc-8.8.4 http-client-0.6.4.1 persistent-sqlite-2.10.6.2 torrent-10000.1.1 uuid-1.3.13 yesod-1.6.1.0
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7

bullseye + git-annex from neurodebian (works):

    git version 2.30.2
    git-annex version: 10.20240227-1~ndall+1
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Benchmark Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.13.1 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2.1
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8 9 10
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7 8 9 10

bookworm (fails):

    git version 2.39.2
    git-annex version: 10.20230126
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Benchmark Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.13.1 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2.1
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8 9 10
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7 8 9 10

bookworm + git-annex from neurodebian (works):

    git version 2.39.2
    git-annex version: 10.20240227-1~ndall+1
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Benchmark Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.13.1 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2.1
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8 9 10
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7 8 9 10
2025-06-12 15:16:45 +02:00
Matthias Riße
fb1ebf705d Install git-annex in the testing workflow 2025-06-12 15:16:45 +02:00
Matthias Riße
d588b9e0d3 Adapt patch to upstream changes 2025-06-12 15:16:45 +02:00
Matthias Riße
2834de417c Adapt patch to upstream changes
A dead code check started to complain because FileCmp was only used in
tests. Moved the function to test_utils.
2025-06-12 15:16:45 +02:00
Matthias Riße
75ae8a96bb Adapt patch to upstream changes
Repository creation now expects an objectFormat to be specified for git.
2025-06-12 15:16:45 +02:00
Nick
f69784d5c1 git-annex tests
Fixes https://github.com/neuropoly/gitea/issues/11

Tests:

* `git annex init`
* `git annex copy --from origin`
* `git annex copy --to origin`

over:

* ssh

for:

* the owner
* a collaborator
* a read-only collaborator
* a stranger

in a

* public repo
* private repo

And then confirms:

* Deletion of the remote repo (to ensure lockdown isn't messing with us: https://git-annex.branchable.com/internals/lockdown/#comment-0cc5225dc5abe8eddeb843bfd2fdc382)

------

To support all this:

* Add util.FileCmp()
* Patch withKeyFile() so it can be nested in other copies of itself

-------

Many thanks to Mathieu for giving style tips and catching several bugs,
including a subtle one in util.filecmp() which neutered it.

Co-authored-by: Mathieu Guay-Paquet <mathieu.guay-paquet@polymtl.ca>
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:45 +02:00
Nick Guenther
d3dbd61e14 git-annex support
[git-annex](https://git-annex.branchable.com/) is a more complicated cousin to
git-lfs, storing large files in an optional-download side content.  Unlike lfs,
it allows mixing and matching storage remotes, so the content remote(s) doesn't
need to be on the same server as the git remote, making it feasible to scatter
a collection across cloud storage, old harddrives, or anywhere else storage can
be scavenged.  Since this can get complicated, fast, it has a content-tracking
database (`git annex whereis`) to help find everything later.

The use-case we imagine for including it in Gitea is just the simple case, where
we're primarily emulating git-lfs: each repo has its large content at the same URL.

Our motivation is so we can self-host https://www.datalad.org/ datasets, which
currently are only hostable by fragilely scrounging together cloud storage --
and having to manage all the credentials associated with all the pieces -- or at
https://openneuro.org which is fragile in its own ways.

Supporting git-annex also allows multiple Gitea instance to be annex remotes for
each other, mirroring the content or otherwise collaborating the split up the
hosting costs.

Enabling
--------

TODO

HTTP
----

TODO

Permission Checking
-------------------

This tweaks the API in routers/private/serv.go to expose the calling user's
computed permission, instead of just returning HTTP 403.

This doesn't fit in super well. It's the opposite from how the git-lfs support is
done, where there's a complete list of possible subcommands and their matching
permission levels, and then the API compares the requested with the actual level
and returns HTTP 403 if the check fails.

But it's necessary. The main git-annex verbs, 'git-annex-shell configlist' and
'git-annex-shell p2pstdio' are both either read-only or read-write operations,
depending on the state on disk on either end of the connection and what the user
asked it to ask for, with no way to know before git-annex examines the situation.
So tell the level via GIT_ANNEX_READONLY and trust it to handle itself.

In the older Gogs version, the permission was directly read in cmd/serv.go:

```
mode, err = db.UserAccessMode(user.ID, repo)
```
- 966e925cf3/internal/cmd/serv.go (L334)

but in Gitea permission enforcement has been centralized in the API layer.
(perhaps so the cmd layer can avoid making direct DB connections?)

Deletion
--------

git-annex has this "lockdown" feature where it tries
really quite very hard to prevent you deleting its
data, to the point that even an rm -rf won't do it:
each file in annex/objects/ is nested inside a
folder with read-only permissions.

The recommended workaround is to run chmod -R +w when
you're sure you actually want to delete a repo. See
https://git-annex.branchable.com/internals/lockdown

So we edit util.RemoveAll() to do just that, so now
it's `chmod -R +w && rm -rf` instead of just `rm -rf`.
2025-06-12 15:16:45 +02:00
Matthias Riße
d82022e992 Fix name in package-lock.json
The frontend-checks job started failing because the declared name does
not match the repository name.
2025-06-12 15:16:45 +02:00
Matthias Riße
d8168eb42f Run testing workflow unconditionally 2025-06-12 15:16:45 +02:00
Earl Warren
661028623c [v11.0/forgejo] fix(sec): consider webauthn for external login (#7756)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7756
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-05-02 06:26:31 +00:00
Earl Warren
5a54ce0fbc [v11.0/forgejo] fix(sec): only degrade permission check for git push (#7753)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7753
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-05-02 06:26:18 +00:00
Gusted
5bb61cf6c2
fix(sec): add tests for OAuth2 signup
Test two scenarios:
1. Account linking is set to `auto` and tries to link against a user who
is enrolled into Webauthn should show 2FA screen.
2. User is already linked and logins via OAuth2 and is enrolled into
WebAuthn should show 2FA screen.

(cherry picked from commit aa4ae81fe0)
2025-05-02 07:33:33 +02:00
Gusted
5d7953def4
fix(sec): consider webauthn for external login
- Currently during external login (such as OAuth2), if the user is
enrolled into Webauthn and not enrolled into TOTP then no 2FA is being
done during external login and when account linking is set to `auto` then
also during automatic linking. This results in bypassing the 2FA of the
user.
- Create a new unified function that checks if the user is enrolled into
2FA and use this when necessary. Rename the old `HasTwoFactorByUID`
function to `HasTOTPByUID` which is a more appropiate naming.

(cherry picked from commit df5d656827)

Conflicts:
  the original commit was trimmed down to be fit for backport
2025-05-02 07:31:20 +02:00
Gusted
5816106de5
fix(sec): only degrade permission check for git push
- A permission check is done when incoming SSH connections are handled (this is
run before git hooks). If this check is for write access and AGit flow
is supported, then this check is degraded to a read check. The
motivation behind this is that for AGit flow the user does not need
write permissions but only read permissions.
- The `if` condition cannot check if this is for AGit flow, as the Git
protocol has not run yet and thus has to delay this permission check.
This `if` condition failed to consider that this also might be run for
LFS which does not care about AGit flow and would not do a delayed
permission check, so ensure that this degradition only happens when the
`git-receive-pack` command is being run (which roughly equals to `git
push`).
- Clarify code comment.
- Added integration test.

(cherry picked from commit 60c1af244a)
2025-05-02 07:05:38 +02:00
0ko
c5601e9399 [v11.0/forgejo] (merge commit) i18n: backport of translation updates (#7743)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7743
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-05-01 11:24:07 +00:00
0ko
1d15e243e4 [v11.0/forgejo] i18n: update of translations from Codeberg Translate
Translation updates that are applicable to v11 strings were picked from this commit: 4a51a1f360

Changes to strings that are only present in the v12 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to being v12-only.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Dirk <dirk@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Miguel P.L <miguel_pl@noreply.codeberg.org>
Co-authored-by: Panagiotis \"Ivory\" Vasilopoulos <git@n0toose.net>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Yushu <yushu@noreply.codeberg.org>
Co-authored-by: aleksi <aleksi@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: docudoc <docudoc@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: hugoalh <hugoalh@noreply.codeberg.org>
Co-authored-by: mimsee <mimsee@noreply.codeberg.org>
Co-authored-by: pixelcode <pixelcode@noreply.codeberg.org>
Co-authored-by: tacaly <frederick@tacaly.com>
Co-authored-by: xtex <xtexchooser@duck.com>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/nds/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hant/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/da/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/el/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ru/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/sv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-05-01 15:39:19 +05:00
0ko
97220d1ce9 [v11.0/forgejo] i18n: update of translations from Codeberg Translate
Translation updates that are applicable to v11 strings were picked from this commit: 8958dee86e

Changes to strings that are only present in the v12 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to being v12-only.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Caesar Schinas <caesar@caesarschinas.com>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Dirk <dirk@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Juno Takano <jutty@noreply.codeberg.org>
Co-authored-by: Kita Ikuyo <kitakita@disroot.org>
Co-authored-by: Miguel P.L <miguel_pl@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: alperen <alperen@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: mengzhuo <mengzhuo@noreply.codeberg.org>
Co-authored-by: neighborsbear <neighborsbear@noreply.codeberg.org>
Co-authored-by: otf31 <otf31@noreply.codeberg.org>
Co-authored-by: pboguslawski <pboguslawski@noreply.codeberg.org>
Co-authored-by: whytf <whytf@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: yurtpage <yurtpage@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/ko/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/sk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fil/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ko/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nds/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ru/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/sk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/tr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-05-01 15:38:05 +05:00
0ko
44a5cd3b7a [v11.0/forgejo] i18n: update of translations from Codeberg Translate
Translation updates that are applicable to v11 strings were picked from this commit: 4fe172e4b2

Changes to strings that are only present in the v12 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to being v12-only.

Co-authored-by: Caesar Schinas <caesar@caesarschinas.com>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Miguel P.L <miguel_pl@noreply.codeberg.org>
Co-authored-by: PeterDaveHello <peterdavehello@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: antaanimosity <antaanimosity@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: lucasmz.dev <git@lucasmz.dev>
Co-authored-by: oscarotero <oscarotero@noreply.codeberg.org>
Co-authored-by: otf31 <otf31@noreply.codeberg.org>
Co-authored-by: themandalorian <themandalorian@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: zerica <zerica@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/gl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-05-01 15:36:39 +05:00
Gusted
6a9fb3dbbc [v11.0/forgejo] chore: replace github.com/go-testfixtures/testfixtures (#7729)
**Backport:** #7715

- Replaces `github.com/go-testfixtures/testfixtures` with a homebrew solution that is fully compatible.
- The reason to replace this library is that it pulls in a lot of other libraries which is causing issues: (1) the test binary becomes bigger than necessary which really shows in incremental build times (this patch removes 27.6MiB of the integration test binary) (2) it pulls in libraries (mainly database drivers) that are not used and are not easy to upgrade in case of a security vulnerability, causing CI failures.

(cherry picked from commit 32e64ccd34)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7729
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2025-04-30 13:21:04 +00:00
forgejo-backport-action
fe07c90636 [v11.0/forgejo] chore(release): next-digest moved to invisible.forgejo.org (#7723)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7720

In order to improve the security of the Forgejo infrastructure the next-digest repository was moved to a private instance.

## Testing

- After the merge, trigger a mirror to build a new v12.0-test release
- Verify in experimental that the workflows works as expected
- Verify v12.next.forgejo.org is upgraded with the latest commit
- Once the test completes
    - Tag for backport to v11 & v7
    - Manual backport to v7 because it conflicts

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7723
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-29 18:10:53 +00:00
forgejo-backport-action
4215476cee [v11.0/forgejo] chore: tune down remote user promotion debug message shown as error (#7691)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7687

It is not an error for a remote user to not be promoted: this is the case for all users created via OAuth. Displaying an error is confusing to the admin when seen in the logs.

Refs: https://codeberg.org/forgejo/forgejo/issues/7681

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7691
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-29 13:31:36 +00:00
forgejo-backport-action
e837350319 [v11.0/forgejo] fix: use linguist-generated for language stats (#7694)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7685

- Adds code comment to explain behavior of the `linguist-generated` gitattribute.
- Adjusts the code to ignore the file if `linguist-generated` is true.
- Resolves forgejo/forgejo#7677
- Adds unit testing.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7694): <!--number 7694 --><!--line 0 --><!--description Zml4OiB1c2UgYGxpbmd1aXN0LWdlbmVyYXRlZGAgZm9yIGxhbmd1YWdlIHN0YXRz-->fix: use `linguist-generated` for language stats<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7694
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-28 06:52:28 +00:00
forgejo-backport-action
bc6c0b610b [v11.0/forgejo] fix: set default restricted for OAuth2 user (#7688)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7683

- The OAuthCallback code that is responsible for creating a new user, if one does not exist yet, did not use `[service].ALLOW_ONLY_EXTERNAL_REGISTRATION` as default value for the restricted field of a user.
- Resolves forgejo/forgejo#7681
- Add integration test.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7688
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-27 21:25:42 +00:00
forgejo-backport-action
b067d0df6e [v11.0/forgejo] fix: display the list of tasks in the runner edit page (#7652)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7650

A regression was introduced in Forgejo v11.0 that caused the edit page of a runner (e.g. https://example.org/admin/actions/runners/434) to no longer display the tasks associated with the runner.

Fixes https://codeberg.org/forgejo/forgejo/issues/7643

---

When the fix is absent, the tests fail like so:

```
--- FAIL: TestRunnerDetails (0.03s)
    --- FAIL: TestRunnerDetails/first_page (0.00s)
        runners_test.go:36:
            	Error Trace:	/home/earl-warren/software/forgejo/routers/web/shared/actions/runners_test.go:36
            	Error:      	"[]" should have 30 item(s), but has 0
            	Test:       	TestRunnerDetails/first_page
    --- FAIL: TestRunnerDetails/second_and_last_page (0.00s)
        runners_test.go:43:
            	Error Trace:	/home/earl-warren/software/forgejo/routers/web/shared/actions/runners_test.go:43
            	Error:      	"[]" should have 10 item(s), but has 0
            	Test:       	TestRunnerDetails/second_and_last_page
FAIL
FAIL	forgejo.org/routers/web/shared/actions	0.170s
```

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- User Interface bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7650): <!--number 7650 --><!--line 0 --><!--description ZGlzcGxheSB0aGUgbGlzdCBvZiB0YXNrcyBpbiB0aGUgcnVubmVyIGVkaXQgcGFnZQ==-->display the list of tasks in the runner edit page<!--description-->
<!--end release-notes-assistant-->

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- User Interface bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7650): <!--number 7650 --><!--line 0 --><!--description ZGlzcGxheSB0aGUgbGlzdCBvZiB0YXNrcyBpbiB0aGUgcnVubmVyIGVkaXQgcGFnZQ==-->display the list of tasks in the runner edit page<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7652
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-25 12:38:14 +00:00
forgejo-backport-action
c5bfe77873 [v11.0/forgejo] chore: merge tests.AddFixtures and unittest.OverrideFixtures (#7649)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7648

The only parameter that is ever used is a single directory, make it that only instead of a more complex option structure.

Remove tests.AddFixtures that was the simpler form because it is now redundant.

---

Backporting to v11.0 will help with automated backporting of bug fixes in need of custom made fixtures.

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7649
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-25 09:59:30 +00:00
Otto
b2241c3939 [v11.0/forgejo] fix(ui): make pagination labels always visible to screenreader (#7642)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7642
Reviewed-by: Otto <otto@codeberg.org>
2025-04-24 23:13:15 +00:00
Gusted
a4396782b5 fix(ui): make pagination labels always visible to screenreader
- The pagination labels 'First', 'Previous', 'Next' and 'Last' are
hidden away when the screen width becomes smaller. However this also
hides them from the screen reader. Instead of using `display: none`, use
some well-known tricks to still make them visible to the screen reader.
- Add E2E test.
- Resolves Codeberg/Community#1858

(cherry picked from commit b6072496d4)
2025-04-24 22:37:46 +00:00
forgejo-backport-action
55cff9cfb4 [v11.0/forgejo] fix(i18n): prevent incorrect logging on strings missing in JSON locales (#7599)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7594

Fixes https://codeberg.org/forgejo/forgejo/issues/7591
Followup to https://codeberg.org/forgejo/forgejo/pulls/6203

Without the 3rd commit, when this test runs, an error message appears in the logs:
```
[E] Missing translation "incorrect_root_url"
```

With it, it does not. No changes to the actual locale handling are expected and I'm hoping there's enough other testing in place for that.

Reported-by: Paweł Bogusławski <pboguslawski@noreply.codeberg.org>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7599
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-23 13:44:16 +00:00
forgejo-backport-action
5ffe4e54e1 [v11.0/forgejo] fix: delay-write trace.dat for forgejo diagnosis (#7601)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7597

- Delay the writing of `trace.dat` to the forgejo diagnosis zip file. It's not possible to write `cpu-profile.dat` and `trace.dat` at the same time. This caused the implemention to prematurely close `cpu-profile.dat` and leave it as an empty file.
- Regression of forgejo/forgejo#6470

## Testing
1. Go to `/admin/monitor`
2. Click on "Download diagnosis report"
3. Open the zip file and check that all files are non-empty.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7601
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-23 13:40:51 +00:00
forgejo-backport-action
9147665e2c [v11.0/forgejo] fix(ui): use gap in switch items (#7589)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7581

Followup to _many PRs_ where the old switches were converted to this one.

The main change here is to the switch with counter. It was missing a gap.

Additionally, it removes tailwind helpers the other switches retained from before switch refactors, because they are now using gap.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7589
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-21 09:42:23 +00:00
0ko
5395eea338 [v11.0/forgejo] fix(ui): rescope menu height patch to overflow menu (#7583)
Followup to https://codeberg.org/forgejo/forgejo/pulls/7108
v11-specific backport of https://codeberg.org/forgejo/forgejo/pulls/7578, see details here (change 2)

Preview:
https://codeberg.org/attachments/661c50be-7673-4970-a78b-5852b1138417)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7583
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-04-21 07:20:28 +00:00
forgejo-backport-action
973bc33a5f [v11.0/forgejo] fix(ui/pr): use eye icon for reviews (#7585)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7584

Followup to #6523
Reverts icon change introduced in #5695

It went unnoticed since v10 and was likely caused by bad copy paste and I don't think it's really worth a test.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7585
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-20 21:18:49 +00:00
Beowulf
722ea4179c [v11.0/forgejo] fix(ui): show commit icon in branch dropdown button when viewing a commit (#7576)
Backport: https://codeberg.org/forgejo/forgejo/pulls/7571
Replaces https://codeberg.org/forgejo/forgejo/pulls/7574

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7576
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Beowulf <beowulf@beocode.eu>
Co-committed-by: Beowulf <beowulf@beocode.eu>
2025-04-19 07:03:09 +00:00
Renovate Bot
9ebdc09939 Update module github.com/mattn/go-sqlite3 to v1.14.28 (v11.0/forgejo) (#7563)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) | require | patch | `v1.14.24` -> `v1.14.28` |

---

### Release Notes

<details>
<summary>mattn/go-sqlite3 (github.com/mattn/go-sqlite3)</summary>

### [`v1.14.28`](https://github.com/mattn/go-sqlite3/compare/v1.14.27...v1.14.28)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.27...v1.14.28)

### [`v1.14.27`](https://github.com/mattn/go-sqlite3/compare/v1.14.26...v1.14.27)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.26...v1.14.27)

### [`v1.14.26`](https://github.com/mattn/go-sqlite3/compare/v1.14.25...v1.14.26)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.25...v1.14.26)

### [`v1.14.25`](https://github.com/mattn/go-sqlite3/compare/v1.14.24...v1.14.25)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.24...v1.14.25)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - "* 0-3 * * *" (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNDAuMSIsInVwZGF0ZWRJblZlciI6IjM5LjI0MC4xIiwidGFyZ2V0QnJhbmNoIjoidjExLjAvZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7563
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-04-17 06:34:55 +00:00
114 changed files with 1125 additions and 1996 deletions

View file

@ -2,6 +2,8 @@
# #
# See also https://forgejo.org/docs/next/contributor/release/#stable-release-process # See also https://forgejo.org/docs/next/contributor/release/#stable-release-process
# #
# TOKEN_NEXT_DIGEST is a token with write repository access to https://invisible.forgejo.org/infrastructure/next-digest issued by https://invisible.forgejo.org/forgejo-next-digest
#
# https://codeberg.org/forgejo-experimental/forgejo # https://codeberg.org/forgejo-experimental/forgejo
# #
# Copies a release from codeberg.org/forgejo-integration to codeberg.org/forgejo-experimental # Copies a release from codeberg.org/forgejo-integration to codeberg.org/forgejo-experimental
@ -14,7 +16,7 @@
# vars.DOER: forgejo-experimental-ci # vars.DOER: forgejo-experimental-ci
# secrets.TOKEN: <generated from codeberg.org/forgejo-experimental-ci> # secrets.TOKEN: <generated from codeberg.org/forgejo-experimental-ci>
# #
# http://private.forgejo.org/forgejo/forgejo # http://invisible.forgejo.org/forgejo/forgejo
# #
# Copies & sign a release from codeberg.org/forgejo-integration to codeberg.org/forgejo # Copies & sign a release from codeberg.org/forgejo-integration to codeberg.org/forgejo
# #
@ -80,7 +82,7 @@ jobs:
- name: upgrade v*.next.forgejo.org - name: upgrade v*.next.forgejo.org
uses: https://data.forgejo.org/infrastructure/next-digest@v1.1.0 uses: https://data.forgejo.org/infrastructure/next-digest@v1.1.0
with: with:
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@code.forgejo.org/infrastructure/next-digest url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@invisible.forgejo.org/infrastructure/next-digest
ref_name: '${{ github.ref_name }}' ref_name: '${{ github.ref_name }}'
image: 'codeberg.org/forgejo-experimental/forgejo' image: 'codeberg.org/forgejo-experimental/forgejo'
tag_suffix: '-rootless' tag_suffix: '-rootless'

47
go.mod
View file

@ -48,7 +48,6 @@ require (
github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-openapi/spec v0.20.14 github.com/go-openapi/spec v0.20.14
github.com/go-sql-driver/mysql v1.9.1 github.com/go-sql-driver/mysql v1.9.1
github.com/go-testfixtures/testfixtures/v3 v3.14.0
github.com/go-webauthn/webauthn v0.12.2 github.com/go-webauthn/webauthn v0.12.2
github.com/gobwas/glob v0.2.3 github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
@ -72,7 +71,7 @@ require (
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/markbates/goth v1.80.0 github.com/markbates/goth v1.80.0
github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.24 github.com/mattn/go-sqlite3 v1.14.28
github.com/meilisearch/meilisearch-go v0.31.0 github.com/meilisearch/meilisearch-go v0.31.0
github.com/mholt/archiver/v3 v3.5.1 github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.27 github.com/microcosm-cc/bluemonday v1.0.27
@ -118,21 +117,11 @@ require (
) )
require ( require (
cel.dev/expr v0.19.1 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.9.9 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.2.1 // indirect
cloud.google.com/go/longrunning v0.6.1 // indirect
cloud.google.com/go/monitoring v1.21.1 // indirect
cloud.google.com/go/spanner v1.73.0 // indirect
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
github.com/DataDog/zstd v1.5.5 // indirect github.com/DataDog/zstd v1.5.5 // indirect
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/RoaringBitmap/roaring v1.9.3 // indirect github.com/RoaringBitmap/roaring v1.9.3 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect github.com/andybalholm/brotli v1.1.1 // indirect
@ -164,7 +153,6 @@ require (
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.3.8 // indirect github.com/cloudflare/circl v1.3.8 // indirect
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // indirect github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@ -173,11 +161,8 @@ require (
github.com/dlclark/regexp2 v1.11.4 // indirect github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/emirpasic/gods v1.18.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/fatih/color v1.16.0 // indirect github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-enry/go-oniguruma v1.2.1 // indirect github.com/go-enry/go-oniguruma v1.2.1 // indirect
@ -185,12 +170,10 @@ require (
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-ini/ini v1.67.0 // indirect github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/swag v0.22.7 // indirect github.com/go-openapi/swag v0.22.7 // indirect
github.com/go-webauthn/x v0.1.19 // indirect github.com/go-webauthn/x v0.1.20 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.5 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
@ -201,10 +184,6 @@ require (
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.3 // indirect github.com/google/go-tpm v0.9.3 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/googleapis/go-sql-spanner v1.7.4 // indirect
github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect
@ -235,13 +214,13 @@ require (
github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/rhysd/actionlint v1.6.27 // indirect github.com/rhysd/actionlint v1.6.27 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/rs/xid v1.6.0 // indirect github.com/rs/xid v1.6.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
@ -252,18 +231,9 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/zeebo/assert v1.3.0 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect github.com/zeebo/blake3 v0.2.4 // indirect
go.etcd.io/bbolt v1.3.9 // indirect go.etcd.io/bbolt v1.4.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect go.uber.org/zap v1.27.0 // indirect
@ -271,11 +241,6 @@ require (
golang.org/x/mod v0.24.0 // indirect golang.org/x/mod v0.24.0 // indirect
golang.org/x/time v0.10.0 // indirect golang.org/x/time v0.10.0 // indirect
golang.org/x/tools v0.31.0 // indirect golang.org/x/tools v0.31.0 // indirect
google.golang.org/api v0.203.0 // indirect
google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.71.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
) )

1539
go.sum

File diff suppressed because it is too large Load diff

View file

@ -4,14 +4,12 @@
package auth_test package auth_test
import ( import (
"path/filepath"
"slices" "slices"
"testing" "testing"
auth_model "forgejo.org/models/auth" auth_model "forgejo.org/models/auth"
"forgejo.org/models/db" "forgejo.org/models/db"
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
"forgejo.org/modules/setting"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -275,13 +273,7 @@ func TestBuiltinApplicationsClientIDs(t *testing.T) {
} }
func TestOrphanedOAuth2Applications(t *testing.T) { func TestOrphanedOAuth2Applications(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("models/auth/TestOrphanedOAuth2Applications")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/auth/TestOrphanedOAuth2Applications/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
count, err := auth_model.CountOrphanedOAuth2Applications(db.DefaultContext) count, err := auth_model.CountOrphanedOAuth2Applications(db.DefaultContext)

21
models/auth/two_factor.go Normal file
View file

@ -0,0 +1,21 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth
import (
"context"
)
// HasTwoFactorByUID returns true if the user has TOTP or WebAuthn enabled for
// their account.
func HasTwoFactorByUID(ctx context.Context, userID int64) (bool, error) {
hasTOTP, err := HasTOTPByUID(ctx, userID)
if err != nil {
return false, err
}
if hasTOTP {
return true, nil
}
return HasWebAuthnRegistrationsByUID(ctx, userID)
}

View file

@ -0,0 +1,34 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth
import (
"testing"
"forgejo.org/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHasTwoFactorByUID(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
t.Run("No twofactor", func(t *testing.T) {
ok, err := HasTwoFactorByUID(t.Context(), 2)
require.NoError(t, err)
assert.False(t, ok)
})
t.Run("WebAuthn credential", func(t *testing.T) {
ok, err := HasTwoFactorByUID(t.Context(), 32)
require.NoError(t, err)
assert.True(t, ok)
})
t.Run("TOTP", func(t *testing.T) {
ok, err := HasTwoFactorByUID(t.Context(), 24)
require.NoError(t, err)
assert.True(t, ok)
})
}

View file

@ -139,9 +139,9 @@ func GetTwoFactorByUID(ctx context.Context, uid int64) (*TwoFactor, error) {
return twofa, nil return twofa, nil
} }
// HasTwoFactorByUID returns the two-factor authentication token associated with // HasTOTPByUID returns the TOTP authentication token associated with
// the user, if any. // the user, if the user has TOTP enabled for their account.
func HasTwoFactorByUID(ctx context.Context, uid int64) (bool, error) { func HasTOTPByUID(ctx context.Context, uid int64) (bool, error) {
return db.GetEngine(ctx).Where("uid=?", uid).Exist(&TwoFactor{}) return db.GetEngine(ctx).Where("uid=?", uid).Exist(&TwoFactor{})
} }

View file

@ -5,7 +5,6 @@ package git
import ( import (
"context" "context"
"path/filepath"
"testing" "testing"
"forgejo.org/models/db" "forgejo.org/models/db"
@ -18,13 +17,7 @@ import (
) )
func TestIterateRepositoryIDsWithLFSMetaObjects(t *testing.T) { func TestIterateRepositoryIDsWithLFSMetaObjects(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("models/git/TestIterateRepositoryIDsWithLFSMetaObjects")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/git/TestIterateRepositoryIDsWithLFSMetaObjects/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
type repocount struct { type repocount struct {

View file

@ -20,7 +20,7 @@ import (
) )
func TestPrivateIssueProjects(t *testing.T) { func TestPrivateIssueProjects(t *testing.T) {
defer tests.AddFixtures("models/fixtures/PrivateIssueProjects/")() defer unittest.OverrideFixtures("models/fixtures/PrivateIssueProjects")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@ -119,7 +119,7 @@ func TestPrivateIssueProjects(t *testing.T) {
} }
func TestPrivateRepoProjects(t *testing.T) { func TestPrivateRepoProjects(t *testing.T) {
defer tests.AddFixtures("models/fixtures/TestPrivateRepoProjects/")() defer unittest.OverrideFixtures("models/fixtures/TestPrivateRepoProjects")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})

View file

@ -14,7 +14,6 @@ import (
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
user_model "forgejo.org/models/user" user_model "forgejo.org/models/user"
"forgejo.org/modules/setting" "forgejo.org/modules/setting"
"forgejo.org/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -161,7 +160,7 @@ func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
} }
func TestGetUnmergedPullRequestsByHeadInfoMax(t *testing.T) { func TestGetUnmergedPullRequestsByHeadInfoMax(t *testing.T) {
defer tests.AddFixtures("models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax/")() defer unittest.OverrideFixtures("models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
repoID := int64(1) repoID := int64(1)

View file

@ -4,14 +4,12 @@
package issues_test package issues_test
import ( import (
"path/filepath"
"testing" "testing"
"forgejo.org/models/db" "forgejo.org/models/db"
issues_model "forgejo.org/models/issues" issues_model "forgejo.org/models/issues"
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
user_model "forgejo.org/models/user" user_model "forgejo.org/models/user"
"forgejo.org/modules/setting"
"forgejo.org/modules/timeutil" "forgejo.org/modules/timeutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -81,13 +79,7 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) {
} }
func TestGetUIDsAndStopwatch(t *testing.T) { func TestGetUIDsAndStopwatch(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("models/issues/TestGetUIDsAndStopwatch")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/issues/TestGetUIDsAndStopwatch/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
uidStopwatches, err := issues_model.GetUIDsAndStopwatch(db.DefaultContext) uidStopwatches, err := issues_model.GetUIDsAndStopwatch(db.DefaultContext)

View file

@ -4,14 +4,12 @@
package organization_test package organization_test
import ( import (
"path/filepath"
"testing" "testing"
"forgejo.org/models/db" "forgejo.org/models/db"
"forgejo.org/models/organization" "forgejo.org/models/organization"
"forgejo.org/models/perm" "forgejo.org/models/perm"
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
"forgejo.org/modules/setting"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -189,13 +187,7 @@ func TestHasTeamRepo(t *testing.T) {
} }
func TestInconsistentOwnerTeam(t *testing.T) { func TestInconsistentOwnerTeam(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("models/organization/TestInconsistentOwnerTeam")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/organization/TestInconsistentOwnerTeam/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, TeamID: 1000, AccessMode: perm.AccessModeNone}) unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, TeamID: 1000, AccessMode: perm.AccessModeNone})

View file

@ -4,11 +4,9 @@
package packages package packages
import ( import (
"path/filepath"
"testing" "testing"
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
"forgejo.org/modules/setting"
_ "forgejo.org/models" _ "forgejo.org/models"
_ "forgejo.org/models/actions" _ "forgejo.org/models/actions"
@ -16,16 +14,6 @@ import (
_ "forgejo.org/models/forgefed" _ "forgejo.org/models/forgefed"
) )
func AddFixtures(dirs ...string) func() {
return unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: dirs,
},
)
}
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
unittest.MainTest(m) unittest.MainTest(m)
} }

View file

@ -13,7 +13,7 @@ import (
) )
func TestPackagesGetOrInsertBlob(t *testing.T) { func TestPackagesGetOrInsertBlob(t *testing.T) {
defer AddFixtures("models/fixtures/TestPackagesGetOrInsertBlob/")() defer unittest.OverrideFixtures("models/fixtures/TestPackagesGetOrInsertBlob")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
blake2bIsSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 1}) blake2bIsSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 1})

View file

@ -4,7 +4,6 @@
package repo_test package repo_test
import ( import (
"path/filepath"
"slices" "slices"
"strings" "strings"
"testing" "testing"
@ -14,7 +13,6 @@ import (
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
"forgejo.org/models/user" "forgejo.org/models/user"
"forgejo.org/modules/optional" "forgejo.org/modules/optional"
"forgejo.org/modules/setting"
"forgejo.org/modules/structs" "forgejo.org/modules/structs"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -410,13 +408,7 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
} }
func TestSearchRepositoryIDsByCondition(t *testing.T) { func TestSearchRepositoryIDsByCondition(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("models/repo/TestSearchRepositoryIDsByCondition")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/repo/TestSearchRepositoryIDsByCondition/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
// Sanity check of the database // Sanity check of the database
limitedUser := unittest.AssertExistsAndLoadBean(t, &user.User{ID: 33, Visibility: structs.VisibleTypeLimited}) limitedUser := unittest.AssertExistsAndLoadBean(t, &user.User{ID: 33, Visibility: structs.VisibleTypeLimited})

View file

@ -0,0 +1,198 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package unittest
import (
"database/sql"
"encoding/hex"
"encoding/json" //nolint:depguard
"fmt"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
type insertSQL struct {
statement string
values []any
}
type fixtureFile struct {
name string
insertSQLs []insertSQL
}
type loader struct {
db *sql.DB
dialect string
fixtureFiles []*fixtureFile
}
func newFixtureLoader(db *sql.DB, dialect string, fixturePaths []string) (*loader, error) {
l := &loader{
db: db,
dialect: dialect,
fixtureFiles: []*fixtureFile{},
}
// Load fixtures
for _, fixturePath := range fixturePaths {
stat, err := os.Stat(fixturePath)
if err != nil {
return nil, err
}
// If fixture path is a directory, then read read the files of the directory
// and use those as fixture files.
if stat.IsDir() {
files, err := os.ReadDir(fixturePath)
if err != nil {
return nil, err
}
for _, file := range files {
if !file.IsDir() {
fixtureFile, err := l.buildFixtureFile(filepath.Join(fixturePath, file.Name()))
if err != nil {
return nil, err
}
l.fixtureFiles = append(l.fixtureFiles, fixtureFile)
}
}
} else {
fixtureFile, err := l.buildFixtureFile(fixturePath)
if err != nil {
return nil, err
}
l.fixtureFiles = append(l.fixtureFiles, fixtureFile)
}
}
return l, nil
}
// quoteKeyword returns the quoted string of keyword.
func (l *loader) quoteKeyword(keyword string) string {
switch l.dialect {
case "sqlite3":
return `"` + keyword + `"`
case "mysql":
return "`" + keyword + "`"
case "postgres":
parts := strings.Split(keyword, ".")
for i, p := range parts {
parts[i] = `"` + p + `"`
}
return strings.Join(parts, ".")
default:
return "invalid"
}
}
// placeholder returns the placeholder string.
func (l *loader) placeholder(index int) string {
if l.dialect == "postgres" {
return fmt.Sprintf("$%d", index)
}
return "?"
}
func (l *loader) buildFixtureFile(fixturePath string) (*fixtureFile, error) {
f, err := os.Open(fixturePath)
if err != nil {
return nil, err
}
defer f.Close()
var records []map[string]any
if err := yaml.NewDecoder(f).Decode(&records); err != nil {
return nil, err
}
fixture := &fixtureFile{
name: filepath.Base(strings.TrimSuffix(f.Name(), filepath.Ext(f.Name()))),
insertSQLs: []insertSQL{},
}
for _, record := range records {
columns := []string{}
sqlValues := []string{}
values := []any{}
i := 1
for key, value := range record {
columns = append(columns, l.quoteKeyword(key))
switch v := value.(type) {
case string:
// Try to decode hex.
if strings.HasPrefix(v, "0x") {
value, err = hex.DecodeString(strings.TrimPrefix(v, "0x"))
if err != nil {
return nil, err
}
}
case []any:
// Decode array.
var bytes []byte
bytes, err = json.Marshal(v)
if err != nil {
return nil, err
}
value = string(bytes)
}
values = append(values, value)
sqlValues = append(sqlValues, l.placeholder(i))
i++
}
// Construct the insert SQL.
fixture.insertSQLs = append(fixture.insertSQLs, insertSQL{
statement: fmt.Sprintf(
"INSERT INTO %s (%s) VALUES (%s)",
l.quoteKeyword(fixture.name),
strings.Join(columns, ", "),
strings.Join(sqlValues, ", "),
),
values: values,
})
}
return fixture, nil
}
func (l *loader) Load() error {
// Start transaction.
tx, err := l.db.Begin()
if err != nil {
return err
}
defer func() {
_ = tx.Rollback()
}()
// Clean the table and re-insert the fixtures.
tableDeleted := map[string]struct{}{}
for _, fixture := range l.fixtureFiles {
if _, ok := tableDeleted[fixture.name]; !ok {
if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", l.quoteKeyword(fixture.name))); err != nil {
return fmt.Errorf("cannot delete table %s: %w", fixture.name, err)
}
tableDeleted[fixture.name] = struct{}{}
}
for _, insertSQL := range fixture.insertSQLs {
if _, err := tx.Exec(insertSQL.statement, insertSQL.values...); err != nil {
return fmt.Errorf("cannot insert %q with values %q: %w", insertSQL.statement, insertSQL.values, err)
}
}
}
return tx.Commit()
}

View file

@ -6,7 +6,6 @@ package unittest
import ( import (
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"time" "time"
@ -14,12 +13,11 @@ import (
"forgejo.org/modules/auth/password/hash" "forgejo.org/modules/auth/password/hash"
"forgejo.org/modules/setting" "forgejo.org/modules/setting"
"github.com/go-testfixtures/testfixtures/v3"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/schemas" "xorm.io/xorm/schemas"
) )
var fixturesLoader *testfixtures.Loader var fixturesLoader *loader
// GetXORMEngine gets the XORM engine // GetXORMEngine gets the XORM engine
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) { func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
@ -29,11 +27,18 @@ func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
return db.DefaultContext.(*db.Context).Engine().(*xorm.Engine) return db.DefaultContext.(*db.Context).Engine().(*xorm.Engine)
} }
func OverrideFixtures(opts FixturesOptions, engine ...*xorm.Engine) func() { func OverrideFixtures(dir string) func() {
old := fixturesLoader old := fixturesLoader
if err := InitFixtures(opts, engine...); err != nil {
opts := FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{dir},
}
if err := InitFixtures(opts); err != nil {
panic(err) panic(err)
} }
return func() { return func() {
fixturesLoader = old fixturesLoader = old
} }
@ -42,19 +47,19 @@ func OverrideFixtures(opts FixturesOptions, engine ...*xorm.Engine) func() {
// InitFixtures initialize test fixtures for a test database // InitFixtures initialize test fixtures for a test database
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) { func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
e := GetXORMEngine(engine...) e := GetXORMEngine(engine...)
var fixtureOptionFiles func(*testfixtures.Loader) error fixturePaths := []string{}
if opts.Dir != "" { if opts.Dir != "" {
fixtureOptionFiles = testfixtures.Directory(opts.Dir) fixturePaths = append(fixturePaths, opts.Dir)
} else { } else {
fixtureOptionFiles = testfixtures.Files(opts.Files...) fixturePaths = append(fixturePaths, opts.Files...)
} }
var fixtureOptionDirs []func(*testfixtures.Loader) error
if opts.Dirs != nil { if opts.Dirs != nil {
for _, dir := range opts.Dirs { for _, dir := range opts.Dirs {
fixtureOptionDirs = append(fixtureOptionDirs, testfixtures.Directory(filepath.Join(opts.Base, dir))) fixturePaths = append(fixturePaths, filepath.Join(opts.Base, dir))
} }
} }
dialect := "unknown"
var dialect string
switch e.Dialect().URI().DBType { switch e.Dialect().URI().DBType {
case schemas.POSTGRES: case schemas.POSTGRES:
dialect = "postgres" dialect = "postgres"
@ -63,22 +68,10 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
case schemas.SQLITE: case schemas.SQLITE:
dialect = "sqlite3" dialect = "sqlite3"
default: default:
fmt.Println("Unsupported RDBMS for integration tests") panic("Unsupported RDBMS for test")
os.Exit(1)
}
loaderOptions := []func(loader *testfixtures.Loader) error{
testfixtures.Database(e.DB().DB),
testfixtures.Dialect(dialect),
testfixtures.DangerousSkipTestDatabaseCheck(),
fixtureOptionFiles,
}
loaderOptions = append(loaderOptions, fixtureOptionDirs...)
if e.Dialect().URI().DBType == schemas.POSTGRES {
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
} }
fixturesLoader, err = testfixtures.New(loaderOptions...) fixturesLoader, err = newFixtureLoader(e.DB().DB, dialect, fixturePaths)
if err != nil { if err != nil {
return err return err
} }

View file

@ -11,6 +11,7 @@ import (
_ "forgejo.org/models" _ "forgejo.org/models"
_ "forgejo.org/models/actions" _ "forgejo.org/models/actions"
_ "forgejo.org/models/activities" _ "forgejo.org/models/activities"
_ "forgejo.org/models/forgefed"
_ "forgejo.org/models/user" _ "forgejo.org/models/user"
) )

View file

@ -25,7 +25,6 @@ import (
"forgejo.org/modules/timeutil" "forgejo.org/modules/timeutil"
"forgejo.org/modules/util" "forgejo.org/modules/util"
"forgejo.org/modules/validation" "forgejo.org/modules/validation"
"forgejo.org/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -73,7 +72,7 @@ func TestGetUserFromMap(t *testing.T) {
} }
func TestGetUserByName(t *testing.T) { func TestGetUserByName(t *testing.T) {
defer tests.AddFixtures("models/user/fixtures/")() defer unittest.OverrideFixtures("models/user/fixtures")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
{ {
@ -120,7 +119,7 @@ func TestCanCreateOrganization(t *testing.T) {
} }
func TestGetAllUsers(t *testing.T) { func TestGetAllUsers(t *testing.T) {
defer tests.AddFixtures("models/user/fixtures/")() defer unittest.OverrideFixtures("models/user/fixtures")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
users, err := user_model.GetAllUsers(db.DefaultContext) users, err := user_model.GetAllUsers(db.DefaultContext)
@ -145,7 +144,7 @@ func TestAPActorID(t *testing.T) {
} }
func TestSearchUsers(t *testing.T) { func TestSearchUsers(t *testing.T) {
defer tests.AddFixtures("models/user/fixtures/")() defer unittest.OverrideFixtures("models/user/fixtures")()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
testSuccess := func(opts *user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) { testSuccess := func(opts *user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) {
users, _, err := user_model.SearchUsers(db.DefaultContext, opts) users, _, err := user_model.SearchUsers(db.DefaultContext, opts)

View file

@ -204,7 +204,13 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return nil, err return nil, err
} }
} }
if !isTrue(isGenerated) && enry.IsGenerated(f.Name(), content) {
// We consider three cases:
// 1. linguist-generated=true, then we ignore the file.
// 2. linguist-generated=false, we don't ignore the file.
// 3. linguist-generated is not set, then `enry.IsGenerated` determines if the file is generated.
if isTrue(isGenerated) || !isFalse(isGenerated) && enry.IsGenerated(f.Name(), content) {
log.Trace("Ignore %q for language stats, because it is generated", f.Name())
continue continue
} }

View file

@ -25,6 +25,15 @@ func TestRepository_GetLanguageStats(t *testing.T) {
"Python": 134, "Python": 134,
"Java": 112, "Java": 112,
}, stats) }, stats)
stats, err = gitRepo.GetLanguageStats("95d3505f2db273e40be79f84416051ae85e9ea0d")
require.NoError(t, err)
assert.Equal(t, map[string]int64{
"Cobra": 67,
"Python": 67,
"Java": 112,
}, stats)
} }
func TestMergeLanguageStats(t *testing.T) { func TestMergeLanguageStats(t *testing.T) {

View file

@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 8fee858da5796dfb37704761701bb8e800ad9ef3 Andrew Thornton <art27@cantab.net> 1632140318 +0100 commit (initial): Add some test files for GetLanguageStats
8fee858da5796dfb37704761701bb8e800ad9ef3 341fca5b5ea3de596dc483e54c2db28633cd2f97 oliverpool <git@olivier.pfad.fr> 1711278775 +0100 push

View file

@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 8fee858da5796dfb37704761701bb8e800ad9ef3 Andrew Thornton <art27@cantab.net> 1632140318 +0100 commit (initial): Add some test files for GetLanguageStats
8fee858da5796dfb37704761701bb8e800ad9ef3 341fca5b5ea3de596dc483e54c2db28633cd2f97 oliverpool <git@olivier.pfad.fr> 1711278775 +0100 push

View file

@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
95d3505f2db273e40be79f84416051ae85e9ea0d refs/heads/master

View file

@ -1 +0,0 @@
341fca5b5ea3de596dc483e54c2db28633cd2f97

View file

@ -1,4 +1,5 @@
// Copyright 2022 The Gitea Authors. All rights reserved. // Copyright 2022 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package i18n package i18n
@ -239,6 +240,7 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
if defaultLang, ok := l.store.localeMap[l.store.defaultLang]; ok { if defaultLang, ok := l.store.localeMap[l.store.defaultLang]; ok {
if msg := defaultLang.LookupNewStyleMessage(trKey); msg != "" { if msg := defaultLang.LookupNewStyleMessage(trKey); msg != "" {
format = msg format = msg
found = true
} else if foundIndex { } else if foundIndex {
// Third fallback: old-style default language // Third fallback: old-style default language
if msg, ok := defaultLang.idxToMsgMap[idx]; ok { if msg, ok := defaultLang.idxToMsgMap[idx]; ok {

View file

@ -939,7 +939,7 @@ access_token_deletion=Odstranit přístupový token
access_token_deletion_cancel_action=Zrušit access_token_deletion_cancel_action=Zrušit
access_token_deletion_confirm_action=Smazat access_token_deletion_confirm_action=Smazat
access_token_deletion_desc=Smazání tokenu zruší přístup k vašemu účtu pro aplikace, které jej používají. Tuto akci nelze vrátit. Pokračovat? access_token_deletion_desc=Smazání tokenu zruší přístup k vašemu účtu pro aplikace, které jej používají. Tuto akci nelze vrátit. Pokračovat?
delete_token_success=Token byl odstraněn. Aplikace, které jej používají již nemají přístup k vašemu účtu. delete_token_success=Token byl odstraněn. Aplikace, které jej používají, již nemají přístup k vašemu účtu.
repo_and_org_access=Přístup k repozitářům a organizacím repo_and_org_access=Přístup k repozitářům a organizacím
permissions_public_only=Pouze veřejné permissions_public_only=Pouze veřejné
permissions_access_all=Vše (veřejné, soukromé a omezené) permissions_access_all=Vše (veřejné, soukromé a omezené)

View file

@ -229,7 +229,7 @@ app_desc=Ein einfacher, selbst gehosteter Git-Service
install=Einfach zu installieren install=Einfach zu installieren
install_desc=Starte einfach <a target="_blank" rel="noopener noreferrer" href="%[1]s">die Anwendung</a> für deine Plattform oder nutze <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a>. Es existieren auch <a target="_blank" rel="noopener noreferrer" href="%[3]s">paketierte Versionen</a>. install_desc=Starte einfach <a target="_blank" rel="noopener noreferrer" href="%[1]s">die Anwendung</a> für deine Plattform oder nutze <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a>. Es existieren auch <a target="_blank" rel="noopener noreferrer" href="%[3]s">paketierte Versionen</a>.
platform=Plattformübergreifend platform=Plattformübergreifend
platform_desc=Forgejo läuft auf freien Betriebssystemen wie Linux und FreeBSD, sowie auf verschiedenen CPU-Architekturen. Wähle das System, das du magst! platform_desc=Forgejo läuft auf freien Betriebssystemen wie Linux und FreeBSD sowie auf verschiedenen CPU-Architekturen. Wähle das System, das du magst!
lightweight=Leichtgewichtig lightweight=Leichtgewichtig
lightweight_desc=Forgejo hat minimale Systemanforderungen und kann selbst auf einem günstigen und stromsparenden Raspberry Pi betrieben werden! lightweight_desc=Forgejo hat minimale Systemanforderungen und kann selbst auf einem günstigen und stromsparenden Raspberry Pi betrieben werden!
license=Quelloffen license=Quelloffen
@ -339,7 +339,7 @@ default_enable_timetracking=Zeiterfassung standardmäßig aktivieren
default_enable_timetracking.description=Zeiterfassung standardmäßig für neue Repositorys aktivieren. default_enable_timetracking.description=Zeiterfassung standardmäßig für neue Repositorys aktivieren.
no_reply_address=Versteckte E-Mail-Domain no_reply_address=Versteckte E-Mail-Domain
no_reply_address_helper=Domain-Name für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername „Joe“ in Git als „joe@noreply.example.org“ protokolliert, wenn die versteckte E-Mail-Domain „noreply.example.org“ festgelegt ist. no_reply_address_helper=Domain-Name für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername „Joe“ in Git als „joe@noreply.example.org“ protokolliert, wenn die versteckte E-Mail-Domain „noreply.example.org“ festgelegt ist.
password_algorithm=Passwort Hashing Algorithmus password_algorithm=Passwort-Hashing-Algorithmus
invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus
password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein. password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein.
enable_update_checker=Aktualisierungsprüfung aktivieren enable_update_checker=Aktualisierungsprüfung aktivieren
@ -347,11 +347,11 @@ env_config_keys=Umgebungskonfiguration
env_config_keys_prompt=Die folgenden Umgebungsvariablen werden auch auf Ihre Konfigurationsdatei angewendet: env_config_keys_prompt=Die folgenden Umgebungsvariablen werden auch auf Ihre Konfigurationsdatei angewendet:
allow_dots_in_usernames = Erlaubt Benutzern die Verwendung von Punkten in ihren Benutzernamen. Hat keine Auswirkungen auf bestehende Konten. allow_dots_in_usernames = Erlaubt Benutzern die Verwendung von Punkten in ihren Benutzernamen. Hat keine Auswirkungen auf bestehende Konten.
enable_update_checker_helper_forgejo = Prüft regelmäßig auf neue Forgejo-Versionen, indem ein DNS-TXT-Eintrag unter release.forgejo.org überprüft wird. enable_update_checker_helper_forgejo = Prüft regelmäßig auf neue Forgejo-Versionen, indem ein DNS-TXT-Eintrag unter release.forgejo.org überprüft wird.
smtp_from_invalid = Die „Sende E-Mail Als“-Adresse ist ungültig smtp_from_invalid = Die „Sende E-Mail als“-Adresse ist ungültig
config_location_hint = Diese Konfigurationsoptionen werden gespeichert in: config_location_hint = Diese Konfigurationsoptionen werden gespeichert in:
allow_only_external_registration = Registrierung nur mittels externer Dienste zulassen allow_only_external_registration = Registrierung nur mittels externer Dienste zulassen
app_slogan = Instanz-Slogan app_slogan = Instanz-Slogan
app_slogan_helper = Instanz-Slogan hier eingeben. Leer lassen zum deaktivieren. app_slogan_helper = Instanz-Slogan hier eingeben. Leer lassen zum Deaktivieren.
[home] [home]
uname_holder=Benutzername oder E-Mail-Adresse uname_holder=Benutzername oder E-Mail-Adresse
@ -418,7 +418,7 @@ forgot_password_title=Passwort vergessen
forgot_password=Passwort vergessen? forgot_password=Passwort vergessen?
sign_up_now=Noch kein Konto? Jetzt registrieren. sign_up_now=Noch kein Konto? Jetzt registrieren.
sign_up_successful=Konto wurde erfolgreich erstellt. Willkommen! sign_up_successful=Konto wurde erfolgreich erstellt. Willkommen!
confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Registrierungsprozess abzuschließen, überprüf bitte deinen Posteingang und folg dem angegebenen Link innerhalb von: %s. Falls die E-Mail inkorrekt sein sollte, kannst du dich einloggen und anfragen, eine weitere Bestätigungs-E-Mail an eine andere Adresse zu senden. confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Registrierungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von: %s. Falls die E-Mail inkorrekt sein sollte, kannst du dich einloggen und anfragen, eine weitere Bestätigungs-E-Mail an eine andere Adresse zu senden.
must_change_password=Aktualisiere dein Passwort must_change_password=Aktualisiere dein Passwort
allow_password_change=Verlange vom Benutzer das Passwort zu ändern (empfohlen) allow_password_change=Verlange vom Benutzer das Passwort zu ändern (empfohlen)
reset_password_mail_sent_prompt=Eine Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Kontowiederherstellungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von %s. reset_password_mail_sent_prompt=Eine Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Kontowiederherstellungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von %s.
@ -451,7 +451,7 @@ oauth_signup_tab=Neues Konto registrieren
oauth_signup_title=Neues Konto fertigstellen oauth_signup_title=Neues Konto fertigstellen
oauth_signup_submit=Konto vervollständigen oauth_signup_submit=Konto vervollständigen
oauth_signin_tab=Mit einem existierenden Konto verbinden oauth_signin_tab=Mit einem existierenden Konto verbinden
oauth_signin_title=Anmelden um verbundenes Konto zu autorisieren oauth_signin_title=Anmelden, um verbundenes Konto zu autorisieren
oauth_signin_submit=Konto verbinden oauth_signin_submit=Konto verbinden
oauth.signin.error=Beim Verarbeiten der Autorisierungsanfrage ist ein Fehler aufgetreten. Wenn dieser Fehler weiterhin besteht, wende dich bitte an deinen Administrator. oauth.signin.error=Beim Verarbeiten der Autorisierungsanfrage ist ein Fehler aufgetreten. Wenn dieser Fehler weiterhin besteht, wende dich bitte an deinen Administrator.
oauth.signin.error.access_denied=Die Autorisierungsanfrage wurde abgelehnt. oauth.signin.error.access_denied=Die Autorisierungsanfrage wurde abgelehnt.
@ -562,7 +562,7 @@ password_change.subject = Dein Passwort wurde geändert
password_change.text_1 = Das Passwort für deinen Account wurde soeben geändert. password_change.text_1 = Das Passwort für deinen Account wurde soeben geändert.
primary_mail_change.subject = Deine primäre E-Mail-Adresse wurde geändert primary_mail_change.subject = Deine primäre E-Mail-Adresse wurde geändert
totp_disabled.subject = TOTP wurde deaktiviert totp_disabled.subject = TOTP wurde deaktiviert
totp_disabled.text_1 = TOTP (Time-based one-time password [Zeitbasiertes Einmalpasswort]) wurde auf deinem Account soeben deaktiviert. totp_disabled.text_1 = TOTP (Time-based one-time password [zeitbasiertes Einmalpasswort]) wurde auf deinem Account soeben deaktiviert.
totp_disabled.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen. totp_disabled.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen.
removed_security_key.subject = Ein Sicherheitsschlüssel wurde entfernt removed_security_key.subject = Ein Sicherheitsschlüssel wurde entfernt
removed_security_key.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen. removed_security_key.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen.
@ -572,7 +572,7 @@ reset_password.text_1 = Das Passwort für deinen Account wurde soeben geändert.
primary_mail_change.text_1 = Die primäre E-Mail-Adresse deines Account wurde soeben zu %[1]s geändert. Das bedeutet, dass diese E-Mail-Adresse keine E-Mail-Benachrichtigungen für deinen Account erhalten wird. primary_mail_change.text_1 = Die primäre E-Mail-Adresse deines Account wurde soeben zu %[1]s geändert. Das bedeutet, dass diese E-Mail-Adresse keine E-Mail-Benachrichtigungen für deinen Account erhalten wird.
account_security_caution.text_2 = Wenn du das nicht warst, wurde dein Account kompromittiert. Bitte kontaktiere die Admins dieser Webseite. account_security_caution.text_2 = Wenn du das nicht warst, wurde dein Account kompromittiert. Bitte kontaktiere die Admins dieser Webseite.
totp_enrolled.subject = Du hast TOTP als 2FA-Methode aktiviert totp_enrolled.subject = Du hast TOTP als 2FA-Methode aktiviert
totp_enrolled.text_1.has_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode benutzen könntest, oder einen deiner Sicherheitsschlüssel. totp_enrolled.text_1.has_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode oder einen deiner Sicherheitsschlüssel benutzen könntest.
totp_enrolled.text_1.no_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode benutzen musst. totp_enrolled.text_1.no_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode benutzen musst.
[modal] [modal]
@ -661,8 +661,8 @@ organization_leave_success=Du hast die Organisation %s erfolgreich verlassen.
invalid_ssh_key=Dein SSH-Key kann nicht überprüft werden: %s invalid_ssh_key=Dein SSH-Key kann nicht überprüft werden: %s
invalid_gpg_key=Dein GPG-Key kann nicht überprüft werden: %s invalid_gpg_key=Dein GPG-Key kann nicht überprüft werden: %s
invalid_ssh_principal=Ungültige Identität: %s invalid_ssh_principal=Ungültige Identität: %s
must_use_public_key=Der von dir bereitgestellte Key ist ein privater Key. Bitte lade deinen privaten Key nirgendwo hoch. Verwende stattdessen deinen öffentlichen Key. must_use_public_key=Der von dir bereitgestellte Schlüssel ist ein privater. Bitte lade deinen privaten Schlüssel nirgendwo hoch, sondern verwende stattdessen deinen öffentlichen.
unable_verify_ssh_key=Der SSH-Key kann nicht verifiziert werden, überprüfe ihn auf Fehler. unable_verify_ssh_key=Der SSH-Schlüssel kann nicht verifiziert werden, überprüfe ihn auf Fehler.
auth_failed=Authentifizierung fehlgeschlagen: %v auth_failed=Authentifizierung fehlgeschlagen: %v
still_own_repo=Dein Konto besitzt ein oder mehrere Repositorys. Diese müssen erst gelöscht oder übertragen werden. still_own_repo=Dein Konto besitzt ein oder mehrere Repositorys. Diese müssen erst gelöscht oder übertragen werden.
@ -700,7 +700,7 @@ watched=Beobachtete Repositorys
code=Quelltext code=Quelltext
projects=Projekte projects=Projekte
overview=Übersicht overview=Übersicht
following_few=%d Folge ich following_few=%d folge ich
follow=Folgen follow=Folgen
unfollow=Nicht mehr folgen unfollow=Nicht mehr folgen
user_bio=Biografie user_bio=Biografie
@ -722,7 +722,7 @@ follow_blocked_user = Du kannst diesen Benutzer nicht folgen, weil du ihn blocki
block_user.detail_3 = Ihr werdet nicht mehr in der Lage sein, euch gegenseitig als Repository-Mitarbeiter hinzuzufügen. block_user.detail_3 = Ihr werdet nicht mehr in der Lage sein, euch gegenseitig als Repository-Mitarbeiter hinzuzufügen.
unblock = Nicht mehr blockieren unblock = Nicht mehr blockieren
followers_one = %d Follower followers_one = %d Follower
following_one = %d Folge ich following_one = %d folge ich
followers.title.few = Follower followers.title.few = Follower
following.title.one = Folgt following.title.one = Folgt
following.title.few = Folgt following.title.few = Folgt
@ -774,7 +774,7 @@ cancel=Abbrechen
language=Sprache language=Sprache
ui=Theme ui=Theme
hidden_comment_types=Ausgeblendete Kommentartypen hidden_comment_types=Ausgeblendete Kommentartypen
hidden_comment_types_description=Die hier markierten Kommentartypen werden nicht innerhalb der Issue-Seiten angezeigt. Die Markierung von „Label“ zum Beispiel entfernt alle Kommentare der Form „<Benutzer> hat <Label> hinzugefügt/entfernt“. hidden_comment_types_description=Die hier markierten Kommentartypen werden innerhalb der Issue-Seiten nicht angezeigt. Beispielsweise entfernt das Ankreuzen von „Label“ alle Kommentare der Form „<Benutzer> hat <Label> hinzugefügt/entfernt“.
hidden_comment_types.ref_tooltip=Kommentare, in denen dieses Issue von einem anderen Issue/Commit/… referenziert wurde hidden_comment_types.ref_tooltip=Kommentare, in denen dieses Issue von einem anderen Issue/Commit/… referenziert wurde
hidden_comment_types.issue_ref_tooltip=Kommentare, bei denen der Benutzer den Branch/Tag des Issues ändert hidden_comment_types.issue_ref_tooltip=Kommentare, bei denen der Benutzer den Branch/Tag des Issues ändert
comment_type_group_reference=Verweis auf Mitglieder comment_type_group_reference=Verweis auf Mitglieder
@ -853,9 +853,9 @@ manage_ssh_keys=SSH-Schlüssel verwalten
manage_ssh_principals=SSH-Zertifikats-Principals verwalten manage_ssh_principals=SSH-Zertifikats-Principals verwalten
manage_gpg_keys=GPG-Schlüssel verwalten manage_gpg_keys=GPG-Schlüssel verwalten
add_key=Schlüssel hinzufügen add_key=Schlüssel hinzufügen
ssh_desc=Diese öffentlichen SSH-Keys sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Keys geben dir vollen Zugriff auf deine Repositorys. Verifizierte SSH-Key können verwendet werden, um SSH-signierte Git-Commits zu signieren. ssh_desc=Diese öffentlichen SSH-Schlüssel sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Schlüssel geben dir vollen Zugriff auf deine Repositorys. Verifizierte SSH-Schlüssel können verwendet werden, um SSH-signierte Git-Commits zu signieren.
principal_desc=Diese SSH-Zertifikat-Principals sind mit deinem Konto verknüpft und erlauben den vollen Zugriff auf deine Repositorys. principal_desc=Diese SSH-Zertifikat-Principals sind mit deinem Konto verknüpft und erlauben den vollen Zugriff auf deine Repositorys.
gpg_desc=Diese öffentlichen GPG-Keys sind mit deinem Account verbunden und werden benutzt um deine Commits zu verifizieren. Halte die dazugehörigen privaten GPG-Keys geheim, da diese deine Commits signieren. gpg_desc=Diese öffentlichen GPG-Schlüssel sind mit deinem Account verbunden und werden benutzt, um deine Commits zu verifizieren. Halte die dazugehörigen privaten GPG-Schlüssel geheim, da diese deine Commits signieren.
ssh_helper=<strong>Brauchst du Hilfe?</strong> Sieh dir die Anleitung zum <a href="%s">Erzeugen deiner eigenen SSH-Schlüssel</a> an oder zum Lösen <a href="%s">häufiger Probleme</a>, denen du bei der Arbeit mit SSH begegnen kannst. ssh_helper=<strong>Brauchst du Hilfe?</strong> Sieh dir die Anleitung zum <a href="%s">Erzeugen deiner eigenen SSH-Schlüssel</a> an oder zum Lösen <a href="%s">häufiger Probleme</a>, denen du bei der Arbeit mit SSH begegnen kannst.
gpg_helper=<strong>Brauchst du Hilfe?</strong> Sieh dir die Anleitung <a href="%s">über GPG</a> an. gpg_helper=<strong>Brauchst du Hilfe?</strong> Sieh dir die Anleitung <a href="%s">über GPG</a> an.
add_new_key=SSH-Schlüssel hinzufügen add_new_key=SSH-Schlüssel hinzufügen
@ -896,7 +896,7 @@ key_id=Schlüssel-ID
key_name=Schlüsselname key_name=Schlüsselname
key_content=Inhalt key_content=Inhalt
principal_content=Inhalt principal_content=Inhalt
add_key_success=Der SSH-Key „%s“ wurde hinzugefügt. add_key_success=Der SSH-Schlüssel „%s“ wurde hinzugefügt.
add_gpg_key_success=Der GPG-Schlüssel „%s“ wurde hinzugefügt. add_gpg_key_success=Der GPG-Schlüssel „%s“ wurde hinzugefügt.
add_principal_success=Die SSH-Zertifikatsidentität „%s“ wurde hinzugefügt. add_principal_success=Die SSH-Zertifikatsidentität „%s“ wurde hinzugefügt.
delete_key=Entfernen delete_key=Entfernen
@ -968,8 +968,8 @@ oauth2_confidential_client=Vertraulicher Client. Für Anwendungen aktivieren, di
oauth2_redirect_uris=URIs für die Weiterleitung. Bitte verwende eine neue Zeile für jede URI. oauth2_redirect_uris=URIs für die Weiterleitung. Bitte verwende eine neue Zeile für jede URI.
save_application=Speichern save_application=Speichern
oauth2_client_id=Client-ID oauth2_client_id=Client-ID
oauth2_client_secret=Client-Secret oauth2_client_secret=Client-Geheimnis
oauth2_regenerate_secret=Secret neu generieren oauth2_regenerate_secret=Geheimnis neu generieren
oauth2_regenerate_secret_hint=Secret verloren? oauth2_regenerate_secret_hint=Secret verloren?
oauth2_client_secret_hint=Das Secret wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast. oauth2_client_secret_hint=Das Secret wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast.
oauth2_application_edit=Bearbeiten oauth2_application_edit=Bearbeiten
@ -984,7 +984,7 @@ revoke_oauth2_grant=Autorisierung widerrufen
revoke_oauth2_grant_description=Wenn du die Autorisierung widerrufst, kann die Anwendung nicht mehr auf deine Daten zugreifen. Bist du dir sicher? revoke_oauth2_grant_description=Wenn du die Autorisierung widerrufst, kann die Anwendung nicht mehr auf deine Daten zugreifen. Bist du dir sicher?
revoke_oauth2_grant_success=Zugriff erfolgreich widerrufen. revoke_oauth2_grant_success=Zugriff erfolgreich widerrufen.
twofa_desc=Um dein Konto gegen Passwortdiebstahl zu schützen, kannst du eine Smartphone oder ein anderes Gerät verwenden, um Time-Based One-Time Passwords („TOTP“) zu erhalten. twofa_desc=Um dein Konto gegen Passwortdiebstahl zu schützen, kannst du eine Smartphone oder ein anderes Gerät verwenden, um zeitbasierte Einmalpasswörter („TOTP“) zu erhalten.
twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung <strong>eingeschaltet</strong>. twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung <strong>eingeschaltet</strong>.
twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet. twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet.
twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren
@ -1028,7 +1028,7 @@ confirm_delete_account=Löschen bestätigen
delete_account_title=Benutzerkonto löschen delete_account_title=Benutzerkonto löschen
delete_account_desc=Bist du sicher, dass du diesen Account dauerhaft löschen möchtest? delete_account_desc=Bist du sicher, dass du diesen Account dauerhaft löschen möchtest?
email_notifications.enable=E-Mail Benachrichtigungen aktivieren email_notifications.enable=E-Mail-Benachrichtigungen aktivieren
email_notifications.onmention=Nur E-Mail bei Erwähnung email_notifications.onmention=Nur E-Mail bei Erwähnung
email_notifications.disable=E-Mail-Benachrichtigungen deaktivieren email_notifications.disable=E-Mail-Benachrichtigungen deaktivieren
email_notifications.submit=E-Mail-Einstellungen festlegen email_notifications.submit=E-Mail-Einstellungen festlegen
@ -1045,7 +1045,7 @@ user_block_success = Dieser Benutzer wurde erfolgreich blockiert.
twofa_recovery_tip = Falls du dein Gerät verlierst, wirst du in der Lage sein, einen einmalig verwendbaren Wiederherstellungsschlüssel zu verwenden, um den auf dein Konto wiederherzustellen. twofa_recovery_tip = Falls du dein Gerät verlierst, wirst du in der Lage sein, einen einmalig verwendbaren Wiederherstellungsschlüssel zu verwenden, um den auf dein Konto wiederherzustellen.
webauthn_alternative_tip = Du möchtest vielleicht eine zusätzliche Authentifizierungsmethode einrichten. webauthn_alternative_tip = Du möchtest vielleicht eine zusätzliche Authentifizierungsmethode einrichten.
blocked_users_none = Keine Benutzer blockiert. blocked_users_none = Keine Benutzer blockiert.
webauthn_key_loss_warning = Falls du deine Security-Keys verlierst, wirst du Zugang zu deinem Konto verlieren. webauthn_key_loss_warning = Falls du deine Sicherheitsschlüssel verlierst, wirst du Zugang zu deinem Konto verlieren.
user_unblock_success = Die Blockierung dieses Benutzers wurde erfolgreich zurückgenommen. user_unblock_success = Die Blockierung dieses Benutzers wurde erfolgreich zurückgenommen.
blocked_users = Blockierte Benutzer blocked_users = Blockierte Benutzer
blocked_since = Blockiert seit %s blocked_since = Blockiert seit %s
@ -1054,7 +1054,7 @@ hints = Hinweise
additional_repo_units_hint = Aktivierung zusätzlicher Repository-Einheiten vorschlagen additional_repo_units_hint = Aktivierung zusätzlicher Repository-Einheiten vorschlagen
update_hints = Hinweise aktualisieren update_hints = Hinweise aktualisieren
update_hints_success = Hinweise wurden aktualisiert. update_hints_success = Hinweise wurden aktualisiert.
additional_repo_units_hint_description = Einen „Mehr aktivieren“-Hinweis für Repositories, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen. additional_repo_units_hint_description = Einen „Mehr aktivieren“-Hinweis für Repositorys, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen.
pronouns = Pronomen pronouns = Pronomen
pronouns_custom = Eigene pronouns_custom = Eigene
pronouns_unspecified = Nicht spezifiziert pronouns_unspecified = Nicht spezifiziert
@ -1064,10 +1064,10 @@ language.localization_project = Hilf uns, Forgejo in deine Sprache zu übersetze
language.description = Diese Sprache wird in deinem Konto gespeichert und standardmäßig nach dem Anmelden benutzt. language.description = Diese Sprache wird in deinem Konto gespeichert und standardmäßig nach dem Anmelden benutzt.
user_block_yourself = Du kannst dich nicht selbst blockieren. user_block_yourself = Du kannst dich nicht selbst blockieren.
pronouns_custom_label = Individuelle Pronomen pronouns_custom_label = Individuelle Pronomen
change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen. change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen. change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
keep_pronouns_private = Pronomen nur angemeldeten Nutzern anzeigen keep_pronouns_private = Pronomen nur angemeldeten Nutzern anzeigen
keep_pronouns_private.description = Dies verbirgt deine Pronomen von Besuchern die nicht angemeldet sind. keep_pronouns_private.description = Dies verbirgt deine Pronomen von Besuchern, die nicht angemeldet sind.
quota.sizes.assets.artifacts = Artefakte quota.sizes.assets.artifacts = Artefakte
quota.applies_to_user = Die folgenden Quota-Regeln greifen für deinen Account quota.applies_to_user = Die folgenden Quota-Regeln greifen für deinen Account
quota.sizes.assets.attachments.issues = Issue-Anhänge quota.sizes.assets.attachments.issues = Issue-Anhänge
@ -1088,9 +1088,9 @@ quota.sizes.assets.all = Assets
quota.sizes.assets.attachments.all = Anhänge quota.sizes.assets.attachments.all = Anhänge
quota.sizes.assets.packages.all = Pakete quota.sizes.assets.packages.all = Pakete
quota.sizes.wiki = Wiki quota.sizes.wiki = Wiki
regenerate_token_success = Der Token wurde regeneriert. Anwendungen die ihn benutzen haben nicht länger Zugriff auf deinen Account und müssen mit dem neuen Token aktualisiert werden. regenerate_token_success = Der Token wurde regeneriert. Anwendungen, die ihn benutzen, haben nicht länger Zugriff auf deinen Account und müssen mit dem neuen Token aktualisiert werden.
access_token_regeneration = Zugangstoken regenerieren access_token_regeneration = Zugangstoken regenerieren
access_token_regeneration_desc = Einen Token zu regenerieren wird den Zugriff auf deinen Account von Anwendungen die ihn nutzen zurückziehen. Dies kann nicht rückgängig gemacht werden. Fortsetzen? access_token_regeneration_desc = Einen Token zu regenerieren, wird den Zugriff auf deinen Account von Anwendungen, die ihn nutzen, zurückziehen. Dies kann nicht rückgängig gemacht werden. Fortsetzen?
regenerate_token = Regenerieren regenerate_token = Regenerieren
[repo] [repo]
@ -1133,7 +1133,7 @@ issue_labels=Labels
issue_labels_helper=Wähle eine Label-Sammlung issue_labels_helper=Wähle eine Label-Sammlung
license=Lizenz license=Lizenz
license_helper=Wähle eine Lizenz license_helper=Wähle eine Lizenz
license_helper_desc=Eine Lizenz regelt, was andere mit deinem Code tun (oder nicht tun) können. Unsicher, welches für dein Projekt die Richtige ist? Siehe <a target="_blank" rel="noopener noreferrer" href="%s">Choose a license</a>. license_helper_desc=Eine Lizenz regelt, was andere mit deinem Code tun (oder nicht tun) können. Unsicher, welche für dein Projekt die richtige ist? Siehe <a target="_blank" rel="noopener noreferrer" href="%s">Choose a license</a>.
readme=README readme=README
readme_helper=Wähle eine README-Vorlage readme_helper=Wähle eine README-Vorlage
readme_helper_desc=Hier kannst du eine komplette Beschreibung für dein Projekt schreiben. readme_helper_desc=Hier kannst du eine komplette Beschreibung für dein Projekt schreiben.
@ -1189,9 +1189,9 @@ tree_path_not_found_commit=Pfad %[1]s existiert nicht in Commit%[2]s
tree_path_not_found_branch=Pfad %[1]s existiert nicht in Branch %[2]s tree_path_not_found_branch=Pfad %[1]s existiert nicht in Branch %[2]s
tree_path_not_found_tag=Pfad %[1]s existiert nicht in Tag %[2]s tree_path_not_found_tag=Pfad %[1]s existiert nicht in Tag %[2]s
transfer.accept=Übertragung Akzeptieren transfer.accept=Übertragung akzeptieren
transfer.accept_desc=Übertragung nach „%s“ transfer.accept_desc=Übertragung nach „%s“
transfer.reject=Übertragung Ablehnen transfer.reject=Übertragung ablehnen
transfer.reject_desc=Übertragung nach„%s“ abbrechen transfer.reject_desc=Übertragung nach„%s“ abbrechen
transfer.no_permission_to_accept=Du hast keine Berechtigung, diesen Transfer anzunehmen. transfer.no_permission_to_accept=Du hast keine Berechtigung, diesen Transfer anzunehmen.
transfer.no_permission_to_reject=Du hast keine Berechtigung, diesen Transfer abzulehnen. transfer.no_permission_to_reject=Du hast keine Berechtigung, diesen Transfer abzulehnen.
@ -1241,7 +1241,7 @@ migrate_items_pullrequests=Pull-Requests
migrate_items_merge_requests=Merge-Requests migrate_items_merge_requests=Merge-Requests
migrate_items_releases=Releases migrate_items_releases=Releases
migrate_repo=Repository migrieren migrate_repo=Repository migrieren
migrate.clone_address=Migrations- / Klon-URL migrate.clone_address=Migrations-/Klon-URL
migrate.clone_address_desc=Die HTTP(S)- oder „git clone“-URL eines bereits existierenden Repositorys migrate.clone_address_desc=Die HTTP(S)- oder „git clone“-URL eines bereits existierenden Repositorys
migrate.github_token_desc=Du kannst hier ein oder mehrere Token durch Komma getrennt eintippen, um die Migration aufgrund der GitHub-API-Ratenlimitierung zu beschleunigen. WARNUNG: Der Missbrauch dieser Funktion kann gegen die Richtlinien des Diensteanbieters verstoßen und zur Kontosperrung führen. migrate.github_token_desc=Du kannst hier ein oder mehrere Token durch Komma getrennt eintippen, um die Migration aufgrund der GitHub-API-Ratenlimitierung zu beschleunigen. WARNUNG: Der Missbrauch dieser Funktion kann gegen die Richtlinien des Diensteanbieters verstoßen und zur Kontosperrung führen.
migrate.clone_local_path=oder ein lokaler Serverpfad migrate.clone_local_path=oder ein lokaler Serverpfad
@ -1259,7 +1259,7 @@ migrate.migrating_failed=Migrieren von <b>%s</b> fehlgeschlagen.
migrate.migrating_failed.error=Migration fehlgeschlagen: %s migrate.migrating_failed.error=Migration fehlgeschlagen: %s
migrate.migrating_failed_no_addr=Migration fehlgeschlagen. migrate.migrating_failed_no_addr=Migration fehlgeschlagen.
migrate.github.description=Daten von github.com oder GitHub-Enterprise-Server migrieren. migrate.github.description=Daten von github.com oder GitHub-Enterprise-Server migrieren.
migrate.git.description=Ein Repository von einem beliebigen Git-Service klonen. migrate.git.description=Ein Repository von einem beliebigen Git-Dienst klonen.
migrate.gitlab.description=Daten von gitlab.com oder anderen GitLab-Instanzen migrieren. migrate.gitlab.description=Daten von gitlab.com oder anderen GitLab-Instanzen migrieren.
migrate.gitea.description=Daten von gitea.com oder anderen Gitea-Instanzen migrieren. migrate.gitea.description=Daten von gitea.com oder anderen Gitea-Instanzen migrieren.
migrate.gogs.description=Daten von notabug.org oder anderen Gogs-Instanzen migrieren. migrate.gogs.description=Daten von notabug.org oder anderen Gogs-Instanzen migrieren.
@ -1422,8 +1422,8 @@ editor.commit_empty_file_text=Die Datei, die du commiten willst, ist leer. Fortf
editor.no_changes_to_show=Keine Änderungen vorhanden. editor.no_changes_to_show=Keine Änderungen vorhanden.
editor.fail_to_update_file=Fehler beim Aktualisieren/Erstellen der Datei „%s“. editor.fail_to_update_file=Fehler beim Aktualisieren/Erstellen der Datei „%s“.
editor.fail_to_update_file_summary=Fehlermeldung: editor.fail_to_update_file_summary=Fehlermeldung:
editor.push_rejected_no_message=Die Änderung wurde vom Server ohne Nachricht abgelehnt. Bitte überprüfe die Git Hooks. editor.push_rejected_no_message=Die Änderung wurde vom Server ohne Nachricht abgelehnt. Bitte überprüfe die Git-Hooks.
editor.push_rejected=Die Änderung wurde vom Server abgelehnt. Bitte überprüfe die Git Hooks. editor.push_rejected=Die Änderung wurde vom Server abgelehnt. Bitte überprüfe die Git-Hooks.
editor.push_rejected_summary=Vollständige Ablehnungsmeldung: editor.push_rejected_summary=Vollständige Ablehnungsmeldung:
editor.add_subdir=Verzeichnis erstellen … editor.add_subdir=Verzeichnis erstellen …
editor.unable_to_upload_files=Fehler beim Hochladen der Dateien nach „%s“. Fehler: %v editor.unable_to_upload_files=Fehler beim Hochladen der Dateien nach „%s“. Fehler: %v
@ -1453,7 +1453,7 @@ commits.signed_by=Signiert von
commits.signed_by_untrusted_user=Signiert von nicht vertrauenswürdigen Benutzern commits.signed_by_untrusted_user=Signiert von nicht vertrauenswürdigen Benutzern
commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigen Benutzern, der nicht mit dem Committer übereinstimmt commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigen Benutzern, der nicht mit dem Committer übereinstimmt
commits.gpg_key_id=GPG-Schlüssel-ID commits.gpg_key_id=GPG-Schlüssel-ID
commits.ssh_key_fingerprint=SSH-Key-Fingerabdruck commits.ssh_key_fingerprint=SSH-Schlüssel-Fingerabdruck
commits.view_path=An diesem Punkt im Verlauf anzeigen commits.view_path=An diesem Punkt im Verlauf anzeigen
commit.operations=Operationen commit.operations=Operationen
@ -1500,7 +1500,7 @@ projects.column.new_title=Name
projects.column.new_submit=Spalte erstellen projects.column.new_submit=Spalte erstellen
projects.column.new=Neue Spalte projects.column.new=Neue Spalte
projects.column.set_default=Als Standard verwenden projects.column.set_default=Als Standard verwenden
projects.column.set_default_desc=Diese Spalte als Standard für nicht kategorisierte Issues und Pull Requests festlegen projects.column.set_default_desc=Diese Spalte als Standard für nicht kategorisierte Issues und Pull-Requests festlegen
projects.column.unset_default=Standard entfernen projects.column.unset_default=Standard entfernen
projects.column.unset_default_desc=Diese Spalte nicht als Standard verwenden projects.column.unset_default_desc=Diese Spalte nicht als Standard verwenden
projects.column.delete=Spalte löschen projects.column.delete=Spalte löschen
@ -2019,7 +2019,7 @@ milestones.filter_sort.most_complete=Vollständigste
milestones.filter_sort.most_issues=Meiste Issues milestones.filter_sort.most_issues=Meiste Issues
milestones.filter_sort.least_issues=Wenigste Issues milestones.filter_sort.least_issues=Wenigste Issues
signing.will_sign=Dieser Commit wird mit dem Key „%s“ signiert werden. signing.will_sign=Dieser Commit wird mit dem Schlüssel „%s“ signiert werden.
signing.wont_sign.error=Es gab einen Fehler bei der Prüfung, ob der Commit signiert werden kann. signing.wont_sign.error=Es gab einen Fehler bei der Prüfung, ob der Commit signiert werden kann.
signing.wont_sign.nokey=Diese Instanz hat keinen Schlüssel, um diesen Commit zu signieren. signing.wont_sign.nokey=Diese Instanz hat keinen Schlüssel, um diesen Commit zu signieren.
signing.wont_sign.never=Commits werden nie signiert. signing.wont_sign.never=Commits werden nie signiert.
@ -2216,7 +2216,7 @@ settings.pulls.allow_rebase_update=Update von Pull-Request-Branches per Rebase e
settings.pulls.default_delete_branch_after_merge=Standardmäßig bei Pull-Requests den Branch nach dem Zusammenführen löschen settings.pulls.default_delete_branch_after_merge=Standardmäßig bei Pull-Requests den Branch nach dem Zusammenführen löschen
settings.pulls.default_allow_edits_from_maintainers=Änderungen von Maintainern standardmäßig erlauben settings.pulls.default_allow_edits_from_maintainers=Änderungen von Maintainern standardmäßig erlauben
settings.releases_desc=Repository-Releases aktivieren settings.releases_desc=Repository-Releases aktivieren
settings.packages_desc=Repository Packages Registry aktivieren settings.packages_desc=Repository-Paket-Registry aktivieren
settings.projects_desc=Repository-Projekte aktivieren settings.projects_desc=Repository-Projekte aktivieren
settings.actions_desc=Aktiviere integrierte CI/CD-Pipelines mit Forgejo-Actions settings.actions_desc=Aktiviere integrierte CI/CD-Pipelines mit Forgejo-Actions
settings.admin_settings=Administratoreinstellungen settings.admin_settings=Administratoreinstellungen
@ -2791,7 +2791,7 @@ pulls.made_using_agit = AGit
settings.confirmation_string = Bestätigungsstring settings.confirmation_string = Bestätigungsstring
pulls.agit_explanation = Mittels AGit-Workflow erstellt. AGit erlaubt Mitwirkenden, Änderungen mittels „git push“ vorzuschlagen, ohne einen Fork oder neuen Branch zu erstellen. pulls.agit_explanation = Mittels AGit-Workflow erstellt. AGit erlaubt Mitwirkenden, Änderungen mittels „git push“ vorzuschlagen, ohne einen Fork oder neuen Branch zu erstellen.
activity.navbar.recent_commits = Neueste Commits activity.navbar.recent_commits = Neueste Commits
activity.navbar.code_frequency = Code-Frequenz activity.navbar.code_frequency = Code-Häufigkeit
file_follow = Symlink folgen file_follow = Symlink folgen
error.broken_git_hook = Die Git-Hooks des Repositorys scheinen kaputt zu sein. Bitte folge der <a target="_blank" rel="noreferrer" href="%s">Dokumentation</a> um sie zu reparieren, dann pushe einige Commits um den Status zu aktualisieren. error.broken_git_hook = Die Git-Hooks des Repositorys scheinen kaputt zu sein. Bitte folge der <a target="_blank" rel="noreferrer" href="%s">Dokumentation</a> um sie zu reparieren, dann pushe einige Commits um den Status zu aktualisieren.
pulls.merged_title_desc_one = hat %[1]d Commit von <code>%[2]s</code> nach <code>%[3]s</code> %[4]s zusammengeführt pulls.merged_title_desc_one = hat %[1]d Commit von <code>%[2]s</code> nach <code>%[3]s</code> %[4]s zusammengeführt
@ -2897,7 +2897,7 @@ pulls.sign_in_require = <a href="%s">Anmelden</a>, um einen neuen Pull-Request z
new_from_template = Eine Vorlage benutzen new_from_template = Eine Vorlage benutzen
new_from_template_description = Du kannst eine existierende Repository-Vorlage auf dieser Instanz benutzen und ihre Einstellungen anwenden. new_from_template_description = Du kannst eine existierende Repository-Vorlage auf dieser Instanz benutzen und ihre Einstellungen anwenden.
auto_init_description = Die Git-Historie mit einer README-Datei und optional einer Lizenz- und .gitignore-Datei starten. auto_init_description = Die Git-Historie mit einer README-Datei und optional einer Lizenz- und .gitignore-Datei starten.
issues.context.menu = Kommentar Menü issues.context.menu = Kommentarmenü
issues.reaction.add = Reaktion hinzufügen issues.reaction.add = Reaktion hinzufügen
issues.reaction.alt_many = %[1]s und %[2]d mehr reagierten %[3]s. issues.reaction.alt_many = %[1]s und %[2]d mehr reagierten %[3]s.
issues.reaction.alt_few = %[1]s reagierten %[2]s. issues.reaction.alt_few = %[1]s reagierten %[2]s.
@ -2922,7 +2922,7 @@ component_failed_to_load = Ein unerwarteter Fehler ist aufgetreten.
component_loading = Lade %s … component_loading = Lade %s …
contributors.what = Beiträge contributors.what = Beiträge
recent_commits.what = neueste Commits recent_commits.what = neueste Commits
code_frequency.what = Code-Frequenz code_frequency.what = Code-Häufigkeit
[org] [org]

View file

@ -207,6 +207,10 @@ table_modal.label.rows = Σειρές
table_modal.label.columns = Στήλες table_modal.label.columns = Στήλες
buttons.new_table.tooltip = Προσθήκη πίνακα buttons.new_table.tooltip = Προσθήκη πίνακα
link_modal.header = Προσθήκη υπερσυνδέσμου
link_modal.url = URL
link_modal.description = Περιγραφή
[filter] [filter]
string.asc=A - Z string.asc=A - Z
string.desc=Z - A string.desc=Z - A

View file

@ -20,7 +20,7 @@ notifications=Notificaciones
active_stopwatch=Rastreador de tiempo activo active_stopwatch=Rastreador de tiempo activo
create_new=Crear… create_new=Crear…
user_profile_and_more=Perfil y configuración… user_profile_and_more=Perfil y configuración…
signed_in_as=Identificado como signed_in_as=Conectado como
enable_javascript=Este sitio web requiere JavaScript. enable_javascript=Este sitio web requiere JavaScript.
toc=Tabla de contenidos toc=Tabla de contenidos
licenses=Licencias licenses=Licencias
@ -38,12 +38,12 @@ passcode=Código de acceso
webauthn_insert_key=Introduzca su clave de seguridad webauthn_insert_key=Introduzca su clave de seguridad
webauthn_sign_in=Presione el botón en su clave de seguridad. Si su clave de seguridad no tiene ningún botón, vuelva a insertarla. webauthn_sign_in=Presione el botón en su clave de seguridad. Si su clave de seguridad no tiene ningún botón, vuelva a insertarla.
webauthn_press_button=Por favor, presione el botón de su llave de seguridad… webauthn_press_button=Por favor, presione el botón en su clave de seguridad…
webauthn_use_twofa=Utilice un código de doble factor desde su teléfono móvil 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_error=No se pudo leer su llave de seguridad.
webauthn_unsupported_browser=Su navegador no soporta actualmente WebAuthn. webauthn_unsupported_browser=Actualmente su navegador no soporta WebAuthn.
webauthn_error_unknown=Ha ocurrido un error desconocido. Por favor, inténtelo de nuevo. 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_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_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. webauthn_error_empty=Debe establecer un nombre para esta clave.
@ -72,7 +72,7 @@ all=Todos
sources=Propios sources=Propios
mirrors=Réplica mirrors=Réplica
collaborative=Colaborativo collaborative=Colaborativo
forks=Forks forks=Bifurcaciones
activities=Actividades activities=Actividades
pull_requests=Solicitudes de incorporación de cambios pull_requests=Solicitudes de incorporación de cambios
@ -301,7 +301,7 @@ offline_mode.description=Deshabilitar redes de distribución de contenido de ter
disable_gravatar=Desactivar Gravatar disable_gravatar=Desactivar Gravatar
disable_gravatar.description=Desactivar el Gravatar y otros fuentes de avatares de terceros. Se utilizará un avatar por defecto a menos que un usuario suba un avatar localmente. disable_gravatar.description=Desactivar el Gravatar y otros fuentes de avatares de terceros. Se utilizará un avatar por defecto a menos que un usuario suba un avatar localmente.
federated_avatar_lookup=Habilitar avatares federados federated_avatar_lookup=Habilitar avatares federados
federated_avatar_lookup.description=Buscar de avatares con Libravatar. federated_avatar_lookup.description=Busca avatares con Libravatar.
disable_registration=Deshabilitar auto-registro disable_registration=Deshabilitar auto-registro
disable_registration.description=Sólo los administradores de la instancia podrán crear nuevas cuentas. Es muy recomendable mantener deshabilitado el registro a menos que pretenda alojar una instancia pública para todo el mundo y esté preparado para lidiar con grandes cantidades de cuentas de spam. disable_registration.description=Sólo los administradores de la instancia podrán crear nuevas cuentas. Es muy recomendable mantener deshabilitado el registro a menos que pretenda alojar una instancia pública para todo el mundo y esté preparado para lidiar con grandes cantidades de cuentas de spam.
allow_only_external_registration.description=Los usuarios sólo podrán crear nuevas cuentas utilizando servicios externos configurados. allow_only_external_registration.description=Los usuarios sólo podrán crear nuevas cuentas utilizando servicios externos configurados.
@ -669,7 +669,7 @@ still_own_packages=Tu cuenta posee uno o más paquetes, elimínalos primero.
org_still_own_repo=Esta organización todavía posee uno o más repositorios, elimínalos o transfiérelos primero. org_still_own_repo=Esta organización todavía posee uno o más repositorios, elimínalos o transfiérelos primero.
org_still_own_packages=Esta organización todavía posee uno o más paquetes, elimínalos primero. org_still_own_packages=Esta organización todavía posee uno o más paquetes, elimínalos primero.
target_branch_not_exist=La rama de destino no existe target_branch_not_exist=La rama de destino no existe.
admin_cannot_delete_self = No puedes eliminarte a ti mismo cuando eres un admin (administrador). Por favor, elimina primero tus privilegios de administrador. admin_cannot_delete_self = No puedes eliminarte a ti mismo cuando eres un admin (administrador). Por favor, elimina primero tus privilegios de administrador.
username_error_no_dots = ` solo puede contener carácteres alfanuméricos ("0-9","a-z","A-Z"), guiones ("-"), y guiones bajos ("_"). No puede empezar o terminar con carácteres no alfanuméricos y también están prohibidos los carácteres no alfanuméricos consecutivos.` username_error_no_dots = ` solo puede contener carácteres alfanuméricos ("0-9","a-z","A-Z"), guiones ("-"), y guiones bajos ("_"). No puede empezar o terminar con carácteres no alfanuméricos y también están prohibidos los carácteres no alfanuméricos consecutivos.`
unsupported_login_type = No se admite el tipo de inicio de sesión para eliminar la cuenta. unsupported_login_type = No se admite el tipo de inicio de sesión para eliminar la cuenta.
@ -844,7 +844,7 @@ add_email_success=La nueva dirección de correo electrónico ha sido añadida.
email_preference_set_success=La preferencia de correo electrónico se ha establecido correctamente. email_preference_set_success=La preferencia de correo electrónico se ha establecido correctamente.
add_openid_success=La nueva dirección OpenID ha sido añadida. add_openid_success=La nueva dirección OpenID ha sido añadida.
keep_email_private=Ocultar dirección de correo electrónico keep_email_private=Ocultar dirección de correo electrónico
keep_email_private_popup=Esto ocultará tu dirección de correo electrónico de tu perfil. Ya no será la dirección predeterminada para los confirmaciones realizadas a través de la interfaz web, como las subidas y ediciones de archivos, y no se utilizará para las confirmaciones de fusión. En su lugar, se utilizará una dirección especial %s para asociar las confirmaciones a tu cuenta. Ten en cuenta que cambiar esta opción no afectará a las confirmaciones existentes. keep_email_private_popup=Su dirección de correo electrónico no se mostrará en su perfil y no será la predeterminada para las confirmaciones realizadas a través de la interfaz web, como las subidas de archivos, las ediciones y las confirmaciones de fusión. En su lugar, se utilizará una dirección especial %s para vincular las confirmaciones a tu cuenta. Esta opción no afectará a las confirmaciones existentes.
openid_desc=OpenID le permite delegar la autenticación a un proveedor externo. openid_desc=OpenID le permite delegar la autenticación a un proveedor externo.
manage_ssh_keys=Gestionar claves SSH manage_ssh_keys=Gestionar claves SSH
@ -997,7 +997,7 @@ scan_this_image=Escanee esta imagen con su aplicación de autenticación:
or_enter_secret=O introduzca el secreto: %s or_enter_secret=O introduzca el secreto: %s
then_enter_passcode=E introduzca el código de acceso mostrado en la aplicación: then_enter_passcode=E introduzca el código de acceso mostrado en la aplicación:
passcode_invalid=El código de acceso es incorrecto. Vuelva a intentarlo. passcode_invalid=El código de acceso es incorrecto. Vuelva a intentarlo.
twofa_enrolled=Su cuenta ha sido inscrita en la autenticación de doble factor. ¡Guarde su código de respaldo (%s) en un lugar seguro, ya que sólo se muestra una vez! twofa_enrolled=Su cuenta ha sido inscrita en la autenticación de doble factor. Guarde su código de respaldo (%s) en un lugar seguro, ya que no se mostrará nuevamente.
twofa_failed_get_secret=No se pudo obtener el secreto. twofa_failed_get_secret=No se pudo obtener el secreto.
webauthn_desc=Las claves de seguridad son dispositivos hardware que contienen claves criptográficas. Pueden ser usados para la autenticación de doble factor. Las claves de seguridad deben soportar el estándar <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a>. webauthn_desc=Las claves de seguridad son dispositivos hardware que contienen claves criptográficas. Pueden ser usados para la autenticación de doble factor. Las claves de seguridad deben soportar el estándar <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a>.
@ -1084,6 +1084,12 @@ quota.rule.exceeded = Excedido
quota.rule.no_limit = Ilimitado quota.rule.no_limit = Ilimitado
quota.sizes.assets.all = Activos quota.sizes.assets.all = Activos
access_token_regeneration = Regenerar token de acceso
quota.sizes.git.lfs = Git LFS
quota.sizes.assets.attachments.issues = Archivos adjuntos de incidencia
keep_pronouns_private.description = Esto ocultará sus pronombres a los visitantes que no hayan iniciado sesión.
[repo] [repo]
owner=Propietario owner=Propietario
owner_helper=Algunas organizaciones pueden no aparecer en el menú desplegable debido a un límite máximo de recuento de repositorios. owner_helper=Algunas organizaciones pueden no aparecer en el menú desplegable debido a un límite máximo de recuento de repositorios.
@ -1103,8 +1109,8 @@ clone_helper=¿Necesita ayuda para clonar? Visite <a target="_blank" rel="noopen
fork_repo=Hacer una bifurcación del repositorio fork_repo=Hacer una bifurcación del repositorio
fork_from=Crear una bifurcación desde fork_from=Crear una bifurcación desde
already_forked=Ya ha forkeado %s already_forked=Ya ha forkeado %s
fork_to_different_account=Forkear a una cuenta diferente fork_to_different_account=Bifurcar a una cuenta diferente
fork_visibility_helper=La visibilidad de un repositorio del cual se ha hecho fork no puede ser cambiada. fork_visibility_helper=No se puede cambiar la visibilidad de un repositorio bifurcado.
fork_branch=Rama a clonar en la bifurcación fork_branch=Rama a clonar en la bifurcación
all_branches=Todas las ramas all_branches=Todas las ramas
fork_no_valid_owners=Este repositorio no puede ser bifurcado porque no hay propietarios válidos. fork_no_valid_owners=Este repositorio no puede ser bifurcado porque no hay propietarios válidos.
@ -1158,7 +1164,7 @@ mirror_password_help=Cambie el nombre de usario para eliminar una contraseña al
watchers=Seguidores watchers=Seguidores
stargazers=Fans stargazers=Fans
stars_remove_warning=Esto eliminará todas las estrellas de este repositorio. stars_remove_warning=Esto eliminará todas las estrellas de este repositorio.
forks=Forks forks=Bifurcaciones
reactions_more=y %d más reactions_more=y %d más
unit_disabled=El administrador del sitio ha deshabilitado esta sección del repositorio. unit_disabled=El administrador del sitio ha deshabilitado esta sección del repositorio.
language_other=Otros language_other=Otros
@ -1228,8 +1234,8 @@ migrate_items_wiki=Wiki
migrate_items_milestones=Hitos migrate_items_milestones=Hitos
migrate_items_labels=Etiquetas migrate_items_labels=Etiquetas
migrate_items_issues=Incidencias migrate_items_issues=Incidencias
migrate_items_pullrequests=Pull requests migrate_items_pullrequests=Solicitudes de extracción
migrate_items_merge_requests=Merge requests migrate_items_merge_requests=Solicitudes de fusión
migrate_items_releases=Lanzamientos migrate_items_releases=Lanzamientos
migrate_repo=Migrar repositorio migrate_repo=Migrar repositorio
migrate.clone_address=Migrar / Clonar desde URL migrate.clone_address=Migrar / Clonar desde URL
@ -1268,17 +1274,17 @@ migrate.cancel_migrating_title=Cancelar la migración
migrate.cancel_migrating_confirm=¿Quiere cancelar esta migración? migrate.cancel_migrating_confirm=¿Quiere cancelar esta migración?
mirror_from=réplica de mirror_from=réplica de
forked_from=forkeado de forked_from=bifurcado de
generated_from=generado desde generated_from=generado desde
fork_from_self=No puede hacer fork a un repositorio que ya es suyo. fork_from_self=No puede bifurcar un repositorio que ya es suyo.
fork_guest_user=Regístrate para forkear este repositorio. fork_guest_user=Iniciar sesión para bifurcar este repositorio.
watch_guest_user=Iniciar sesión para seguir este repositorio. watch_guest_user=Iniciar sesión para seguir este repositorio.
star_guest_user=Iniciar sesión para destacar este repositorio. star_guest_user=Iniciar sesión para destacar este repositorio.
unwatch=Dejar de seguir unwatch=Dejar de seguir
watch=Seguir watch=Seguir
unstar=Eliminar de favoritos unstar=Eliminar de favoritos
star=Destacar star=Destacar
fork=Fork fork=Bifurcar
download_archive=Descargar repositorio download_archive=Descargar repositorio
more_operations=Más operaciones more_operations=Más operaciones
@ -1520,7 +1526,7 @@ issues.new.no_projects=Ningún proyecto
issues.new.open_projects=Proyectos abiertos issues.new.open_projects=Proyectos abiertos
issues.new.closed_projects=Proyectos cerrados issues.new.closed_projects=Proyectos cerrados
issues.new.no_items=No hay elementos issues.new.no_items=No hay elementos
issues.new.milestone=Milestone issues.new.milestone=Hito
issues.new.no_milestone=Sin hito issues.new.no_milestone=Sin hito
issues.new.clear_milestone=Limpiar Milestone issues.new.clear_milestone=Limpiar Milestone
issues.new.open_milestone=Hitos abiertos issues.new.open_milestone=Hitos abiertos
@ -1568,12 +1574,12 @@ issues.change_title_at=`cambió el título de <b><strike>%s</strike></b> a <b>%s
issues.change_ref_at=`cambió referencia de <b><strike>%s</strike></b> a <b>%s</b> %s` issues.change_ref_at=`cambió referencia de <b><strike>%s</strike></b> a <b>%s</b> %s`
issues.remove_ref_at=`eliminó la referencia <b>%s</b> %s` issues.remove_ref_at=`eliminó la referencia <b>%s</b> %s`
issues.add_ref_at=`añadió la referencia <b>%s</b> %s` issues.add_ref_at=`añadió la referencia <b>%s</b> %s`
issues.delete_branch_at=`rama eliminada <b>%s</b> %s` issues.delete_branch_at=`eliminó la rama <b>%s</b> %s`
issues.filter_label=Etiqueta issues.filter_label=Etiqueta
issues.filter_label_exclude=`Usa <code>alt</code> + <code>clic/enter</code> para excluir etiquetas` issues.filter_label_exclude=`Usa <code>alt</code> + <code>clic/enter</code> para excluir etiquetas`
issues.filter_label_no_select=Todas las etiquetas issues.filter_label_no_select=Todas las etiquetas
issues.filter_label_select_no_label=Sin etiqueta issues.filter_label_select_no_label=Sin etiqueta
issues.filter_milestone=Milestone issues.filter_milestone=Hito
issues.filter_milestone_all=Todos los hitos issues.filter_milestone_all=Todos los hitos
issues.filter_milestone_none=Sin hitos issues.filter_milestone_none=Sin hitos
issues.filter_milestone_open=Abrir hitos issues.filter_milestone_open=Abrir hitos
@ -1604,8 +1610,8 @@ issues.filter_sort.nearduedate=Fecha de vencimiento más cercana
issues.filter_sort.farduedate=Fecha de vencimiento más lejana issues.filter_sort.farduedate=Fecha de vencimiento más lejana
issues.filter_sort.moststars=Mas estrellas issues.filter_sort.moststars=Mas estrellas
issues.filter_sort.feweststars=Menor número de estrellas issues.filter_sort.feweststars=Menor número de estrellas
issues.filter_sort.mostforks=La mayoría de forks issues.filter_sort.mostforks=La mayoría de bifurcaciones
issues.filter_sort.fewestforks=Menor número de forks issues.filter_sort.fewestforks=Menor número de bifurcaciones
issues.keyword_search_unavailable=La búsqueda por palabra clave no está disponible actualmente. Por favor, contacte con el administrador de su sitio. issues.keyword_search_unavailable=La búsqueda por palabra clave no está disponible actualmente. Por favor, contacte con el administrador de su sitio.
issues.action_open=Abrir issues.action_open=Abrir
issues.action_close=Cerrar issues.action_close=Cerrar
@ -1629,7 +1635,7 @@ issues.closed_title=Cerrada
issues.draft_title=Borrador issues.draft_title=Borrador
issues.num_comments_1=%d comentario issues.num_comments_1=%d comentario
issues.num_comments=%d comentarios issues.num_comments=%d comentarios
issues.commented_at=`comentado <a href="#%s">%s</a>` issues.commented_at=`comentó <a href="#%s">%s</a>`
issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario? issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario?
issues.context.copy_link=Copiar enlace issues.context.copy_link=Copiar enlace
issues.context.quote_reply=Citar respuesta issues.context.quote_reply=Citar respuesta
@ -1639,7 +1645,7 @@ issues.context.delete=Eliminar
issues.no_content=No se ha proporcionado una descripción. issues.no_content=No se ha proporcionado una descripción.
issues.close=Cerrar incidencia issues.close=Cerrar incidencia
issues.comment_pull_merged_at=commit fusionado %[1]s en %[2]s %[3]s issues.comment_pull_merged_at=commit fusionado %[1]s en %[2]s %[3]s
issues.comment_manually_pull_merged_at=commit manualmente fusionado %[1]s en %[2]s %[3]s issues.comment_manually_pull_merged_at=commit %[1]s manualmente fusionado en %[2]s %[3]s
issues.close_comment_issue=Cerrar con comentario issues.close_comment_issue=Cerrar con comentario
issues.reopen_issue=Reabrir issues.reopen_issue=Reabrir
issues.reopen_comment_issue=Reabrir con comentario issues.reopen_comment_issue=Reabrir con comentario
@ -1664,7 +1670,7 @@ issues.role.collaborator=Colaborador
issues.role.collaborator_helper=Este usuario ha sido invitado a colaborar en el repositorio. issues.role.collaborator_helper=Este usuario ha sido invitado a colaborar en el repositorio.
issues.role.first_time_contributor=Contribuyente por primera vez issues.role.first_time_contributor=Contribuyente por primera vez
issues.role.first_time_contributor_helper=Esta es la primera contribución de este usuario al repositorio. issues.role.first_time_contributor_helper=Esta es la primera contribución de este usuario al repositorio.
issues.role.contributor=Colaborador issues.role.contributor=Contribuidor
issues.role.contributor_helper=Este usuario ha realizado commit previamente en este repositorio. issues.role.contributor_helper=Este usuario ha realizado commit previamente en este repositorio.
issues.re_request_review=Solicitar revisión de nuevo issues.re_request_review=Solicitar revisión de nuevo
issues.is_stale=Ha habido cambios en este PR desde esta revisión issues.is_stale=Ha habido cambios en este PR desde esta revisión
@ -1755,7 +1761,7 @@ issues.error_modifying_due_date=Fallo al modificar la fecha de vencimiento.
issues.error_removing_due_date=Fallo al eliminar la fecha de vencimiento. issues.error_removing_due_date=Fallo al eliminar la fecha de vencimiento.
issues.push_commit_1=añadió %d commit %s issues.push_commit_1=añadió %d commit %s
issues.push_commits_n=añadió %d commits %s issues.push_commits_n=añadió %d commits %s
issues.force_push_codes=`hizo push forzado %[1]s de <a class="%[7]s" href="%[3]s"><code>%[2]s</code></a> a <a class="%[7]s" href="%[5]s"><code>%[4]s</code></a> %[6]s` issues.force_push_codes=`empujó forzosamente %[1]s de <a class="%[7]s" href="%[3]s"><code>%[2]s</code></a> a <a class="%[7]s" href="%[5]s"><code>%[4]s</code></a> %[6]s`
issues.force_push_compare=Comparar issues.force_push_compare=Comparar
issues.due_date_form=aaaa-mm-dd issues.due_date_form=aaaa-mm-dd
issues.due_date_form_add=Añadir fecha de vencimiento issues.due_date_form_add=Añadir fecha de vencimiento
@ -1874,7 +1880,7 @@ pulls.title_desc_few=quiere fusionar %[1]d commits de <code>%[2]s</code> en <cod
pulls.merged_title_desc_few=fusionó %[1]d commits de <code>%[2]s</code> en <code>%[3]s</code> %[4]s pulls.merged_title_desc_few=fusionó %[1]d commits de <code>%[2]s</code> en <code>%[3]s</code> %[4]s
pulls.change_target_branch_at=`cambió la rama objetivo de <b>%s</b> a <b>%s</b> %s` pulls.change_target_branch_at=`cambió la rama objetivo de <b>%s</b> a <b>%s</b> %s`
pulls.tab_conversation=Conversación pulls.tab_conversation=Conversación
pulls.tab_commits=Commits pulls.tab_commits=Confirmaciones
pulls.tab_files=Archivos modificados pulls.tab_files=Archivos modificados
pulls.reopen_to_merge=Vuelva a abrir este Pull Request para realizar una fusión. pulls.reopen_to_merge=Vuelva a abrir este Pull Request para realizar una fusión.
pulls.cant_reopen_deleted_branch=Este pull request no se puede reabrir porque la rama fue eliminada. pulls.cant_reopen_deleted_branch=Este pull request no se puede reabrir porque la rama fue eliminada.
@ -1975,7 +1981,7 @@ pulls.auto_merge_canceled_schedule_comment=`canceló la fusión automática de e
pulls.delete.title=¿Borrar este pull request? pulls.delete.title=¿Borrar este pull request?
pulls.delete.text=¿Realmente quieres eliminar esta pull request? (Esto eliminará permanentemente todo el contenido. Considera cerrarlo si simplemente deseas archivarlo) pulls.delete.text=¿Realmente quieres eliminar esta pull request? (Esto eliminará permanentemente todo el contenido. Considera cerrarlo si simplemente deseas archivarlo)
pulls.recently_pushed_new_branches=Has realizado push en la rama <strong>%[1]s</strong> %[2]s pulls.recently_pushed_new_branches=Empujaste en la rama <a href="%[3]s"><strong>%[1]s</strong></a> %[2]s
pull.deleted_branch=(eliminado):%s pull.deleted_branch=(eliminado):%s
@ -1986,7 +1992,7 @@ milestones.no_due_date=Sin fecha límite
milestones.open=Abrir milestones.open=Abrir
milestones.close=Cerrar milestones.close=Cerrar
milestones.new_subheader=Los hitos pueden ayudarle a organizar los problemas y monitorizar su progreso. milestones.new_subheader=Los hitos pueden ayudarle a organizar los problemas y monitorizar su progreso.
milestones.completeness=%d%% Completado milestones.completeness=<strong>%d%%</strong> Completado
milestones.create=Crear hito milestones.create=Crear hito
milestones.title=Título milestones.title=Título
milestones.desc=Descripción milestones.desc=Descripción
@ -2027,7 +2033,7 @@ ext_wiki=Wiki externa
ext_wiki.desc=Enlace a una wiki externa. ext_wiki.desc=Enlace a una wiki externa.
wiki=Wiki wiki=Wiki
wiki.welcome=¡Bienvenidos a la Wiki! wiki.welcome=Bienvenido a la Wiki.
wiki.welcome_desc=Esta wiki le permite escribir y compartir documentación con otros colaboradores. wiki.welcome_desc=Esta wiki le permite escribir y compartir documentación con otros colaboradores.
wiki.desc=Escriba y comparta documentación con colaboradores. wiki.desc=Escriba y comparta documentación con colaboradores.
wiki.create_first_page=Crear la primera página wiki.create_first_page=Crear la primera página
@ -2104,7 +2110,7 @@ activity.git_stats_author_n=%d autores
activity.git_stats_pushed_1=ha hecho push activity.git_stats_pushed_1=ha hecho push
activity.git_stats_pushed_n=han hecho push activity.git_stats_pushed_n=han hecho push
activity.git_stats_commit_1=%d commit activity.git_stats_commit_1=%d commit
activity.git_stats_commit_n=%d commits activity.git_stats_commit_n=%d confirmaciones
activity.git_stats_push_to_branch=a %s y activity.git_stats_push_to_branch=a %s y
activity.git_stats_push_to_all_branches=en todas las ramas. activity.git_stats_push_to_all_branches=en todas las ramas.
activity.git_stats_on_default_branch=En %s, activity.git_stats_on_default_branch=En %s,
@ -2254,7 +2260,7 @@ settings.trust_model.default.desc=Utilice el modelo de confianza de repositorio
settings.trust_model.collaborator=Colaborador settings.trust_model.collaborator=Colaborador
settings.trust_model.collaborator.long=Colaborador: Confiar en firmas de colaboradores settings.trust_model.collaborator.long=Colaborador: Confiar en firmas de colaboradores
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.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=Confirmador
settings.trust_model.committer.long=Committer: Firmas de confianza que coinciden con los committers (Esto coincide con GitHub y obligará a Forgejo a firmar los commits a tener a Forgejo como el committer) settings.trust_model.committer.long=Committer: Firmas de confianza que coinciden con los committers (Esto coincide con GitHub y obligará a Forgejo a firmar los commits a tener a Forgejo como el committer)
settings.trust_model.committer.desc=Las firmas válidas sólo se marcarán como "confiables" si coinciden con el committer, de lo contrario se marcarán como "no confiable". Esto obliga a Forgejo a ser el committer en commits firmados con el commit real marcado como Co-autorizado por: y Co-commited por: en el tráiler. La clave de Forgejo por defecto debe coincidir con un usuario en la base de datos. settings.trust_model.committer.desc=Las firmas válidas sólo se marcarán como "confiables" si coinciden con el committer, de lo contrario se marcarán como "no confiable". Esto obliga a Forgejo a ser el committer en commits firmados con el commit real marcado como Co-autorizado por: y Co-commited por: en el tráiler. La clave de Forgejo por defecto debe coincidir con un usuario en la base de datos.
settings.trust_model.collaboratorcommitter=Colaborador+Comitter settings.trust_model.collaboratorcommitter=Colaborador+Comitter
@ -2336,7 +2342,7 @@ settings.event_create=Crear
settings.event_create_desc=Rama o etiqueta creada. settings.event_create_desc=Rama o etiqueta creada.
settings.event_delete=Eliminar settings.event_delete=Eliminar
settings.event_delete_desc=Rama o etiqueta eliminada. settings.event_delete_desc=Rama o etiqueta eliminada.
settings.event_fork=Fork settings.event_fork=Bifurcación
settings.event_fork_desc=Repositorio forkeado. settings.event_fork_desc=Repositorio forkeado.
settings.event_wiki=Wiki settings.event_wiki=Wiki
settings.event_wiki_desc=Página de la Wiki creada, renombrada, editada o eliminada. settings.event_wiki_desc=Página de la Wiki creada, renombrada, editada o eliminada.
@ -2524,7 +2530,7 @@ settings.archive.branchsettings_unavailable=Los ajustes de rama no están dispon
settings.archive.tagsettings_unavailable=Los ajustes de las etiquetas no están disponibles si el repositorio está archivado. settings.archive.tagsettings_unavailable=Los ajustes de las etiquetas no están disponibles si el repositorio está archivado.
settings.unarchive.button=Desarchivar repositorio settings.unarchive.button=Desarchivar repositorio
settings.unarchive.header=Desarchivar este repositorio settings.unarchive.header=Desarchivar este repositorio
settings.unarchive.text=La desarchivación del repositorio restablecerá su capacidad de recibir confirmaciones y subidos, así como nuevas incidencias y solicitudes de incorporación de cambios. settings.unarchive.text=La desarchivación del repositorio restablecerá su capacidad de recibir confirmaciones y empujes, así como nuevas incidencias y solicitudes de incorporación de cambios.
settings.unarchive.success=El repositorio se ha desarchivado correctamente. settings.unarchive.success=El repositorio se ha desarchivado correctamente.
settings.unarchive.error=Ocurrió un error mientras se trataba de des-archivar el repositorio. Revisa el registro para más detalles. settings.unarchive.error=Ocurrió un error mientras se trataba de des-archivar el repositorio. Revisa el registro para más detalles.
settings.update_avatar_success=El avatar del repositorio ha sido actualizado. settings.update_avatar_success=El avatar del repositorio ha sido actualizado.
@ -2647,7 +2653,7 @@ release.cancel=Cancelar
release.publish=Publicar lanzamiento release.publish=Publicar lanzamiento
release.save_draft=Guardar borrador release.save_draft=Guardar borrador
release.edit_release=Actualizar Lanzamiento release.edit_release=Actualizar Lanzamiento
release.delete_release=Eliminar Lanzamiento release.delete_release=Eliminar lanzamiento
release.delete_tag=Eliminar tag release.delete_tag=Eliminar tag
release.deletion=Eliminar lanzamiento release.deletion=Eliminar lanzamiento
release.deletion_desc=Eliminar un lanzamiento sólo lo elimina de Forgejo. No afectará la etiqueta Git, el contenido de su repositorio o su historial. ¿Continuar? release.deletion_desc=Eliminar un lanzamiento sólo lo elimina de Forgejo. No afectará la etiqueta Git, el contenido de su repositorio o su historial. ¿Continuar?
@ -2673,7 +2679,7 @@ branch.delete_html=Eliminar rama
branch.delete_desc=Eliminar una rama es permanente. Aunque la rama eliminada puede continuar existiendo durante un corto tiempo antes de que sea eliminada, en la mayoría de los casos NO PUEDE deshacerse. ¿Continuar? branch.delete_desc=Eliminar una rama es permanente. Aunque la rama eliminada puede continuar existiendo durante un corto tiempo antes de que sea eliminada, en la mayoría de los casos NO PUEDE deshacerse. ¿Continuar?
branch.deletion_success=La rama "%s" ha sido eliminada. branch.deletion_success=La rama "%s" ha sido eliminada.
branch.deletion_failed=Error al eliminar la rama "%s". branch.deletion_failed=Error al eliminar la rama "%s".
branch.delete_branch_has_new_commits=La rama "%s" no se puede eliminar porque se han añadido nuevos commits después de la fusión. branch.delete_branch_has_new_commits=La rama "%s" no se puede eliminar porque se han añadido nuevas confirmaciones después de la fusión.
branch.create_branch=Crear rama %s branch.create_branch=Crear rama %s
branch.create_from=`de "%s"` branch.create_from=`de "%s"`
branch.create_success=La rama "%s" ha sido creada. branch.create_success=La rama "%s" ha sido creada.
@ -2876,6 +2882,11 @@ issues.filter_no_results = No hay resultados
release.type_attachment = Archivo adjunto release.type_attachment = Archivo adjunto
issues.reaction.alt_few = %[1]s reaccionado con %[2]s.
settings.event_pull_request_enforcement = Aplicación
settings.sourcehut_builds.visibility = Visibilidad de trabajo
settings.ignore_stale_approvals = Ignorar las aprobaciones obsoletas
[graphs] [graphs]
component_loading = Cargando %s… component_loading = Cargando %s…
component_loading_failed = No se pudo cargar %s component_loading_failed = No se pudo cargar %s
@ -2942,11 +2953,11 @@ settings.hooks_desc=Añadir webhooks que serán ejecutados para <strong>todos lo
settings.labels_desc=Añadir etiquetas que pueden ser utilizadas en problemas para <strong>todos los repositorios</strong> bajo esta organización. settings.labels_desc=Añadir etiquetas que pueden ser utilizadas en problemas para <strong>todos los repositorios</strong> bajo esta organización.
members.membership_visibility=Visibilidad de Membresía: members.membership_visibility=Visibilidad de membresía:
members.public=Público members.public=Público
members.public_helper=hacer oculto members.public_helper=Hacer oculto
members.private=Oculto members.private=Oculto
members.private_helper=hacer público members.private_helper=Hacer público
members.member_role=Rol del miembro: members.member_role=Rol del miembro:
members.owner=Propietario members.owner=Propietario
members.member=Miembro members.member=Miembro
@ -2955,7 +2966,7 @@ members.remove.detail=¿Destituir a %[1]s de %[2]s?
members.leave=Abandonar members.leave=Abandonar
members.leave.detail=¿Irse de %s? members.leave.detail=¿Irse de %s?
members.invite_desc=Añadir un miembro nuevo a %s: members.invite_desc=Añadir un miembro nuevo a %s:
members.invite_now=Invitar members.invite_now=Invitar ahora
teams.join=Unirse teams.join=Unirse
teams.leave=Abandonar teams.leave=Abandonar
@ -2964,7 +2975,7 @@ teams.can_create_org_repo=Crear repositorios
teams.can_create_org_repo_helper=Los miembros pueden crear nuevos repositorios en la organización. El creador obtendrá acceso al administrador del nuevo repositorio. teams.can_create_org_repo_helper=Los miembros pueden crear nuevos repositorios en la organización. El creador obtendrá acceso al administrador del nuevo repositorio.
teams.none_access=Sin acceso teams.none_access=Sin acceso
teams.none_access_helper=Los miembros no pueden ver o hacer ninguna otra acción en esta unidad. teams.none_access_helper=Los miembros no pueden ver o hacer ninguna otra acción en esta unidad.
teams.general_access=Acceso general teams.general_access=Acceso personalizado
teams.general_access_helper=Los permisos de los miembros se decidirán por debajo de la tabla de permisos. teams.general_access_helper=Los permisos de los miembros se decidirán por debajo de la tabla de permisos.
teams.read_access=Leer teams.read_access=Leer
teams.read_access_helper=Los miembros pueden ver y clonar los repositorios del equipo. teams.read_access_helper=Los miembros pueden ver y clonar los repositorios del equipo.
@ -3554,6 +3565,10 @@ emails.delete_desc = ¿Estás seguro que quieres eliminar esta dirección de cor
monitor.duration = Duración (es) monitor.duration = Duración (es)
self_check = Autocomprobación
dashboard.sync_tag.started = Sincronización de etiquetas iniciada
config.app_slogan = Eslogan de la instancia
[action] [action]
create_repo=creó el repositorio <a href="%s">%s</a> create_repo=creó el repositorio <a href="%s">%s</a>
rename_repo=repositorio renombrado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a> rename_repo=repositorio renombrado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
@ -3816,6 +3831,13 @@ alt.repository.multiple_groups = Este paquete está disponible en múltiples gru
arch.version.description = Descripción arch.version.description = Descripción
arch.version.provides = Proveedores arch.version.provides = Proveedores
arch.version.optdepends = Dependencias opcionales
arch.version.makedepends = Construir dependencias
arch.version.checkdepends = Comprobar dependencias
npm.dependencies.bundle = Empaquetar dependencias
arch.pacman.helper.gpg = Añade el certificado de confianza para pacman:
[secrets] [secrets]
secrets=Secretos secrets=Secretos
description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo. description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo.
@ -3862,7 +3884,7 @@ runners.task_list.no_tasks=Todavía no hay tarea.
runners.task_list.run=Ejecutar runners.task_list.run=Ejecutar
runners.task_list.status=Estado runners.task_list.status=Estado
runners.task_list.repository=Repositorio runners.task_list.repository=Repositorio
runners.task_list.commit=Commit runners.task_list.commit=Confirmación
runners.task_list.done_at=Hecho en runners.task_list.done_at=Hecho en
runners.edit_runner=Editar nodo runners.edit_runner=Editar nodo
runners.update_runner=Actualizar cambios runners.update_runner=Actualizar cambios
@ -3922,6 +3944,13 @@ runs.expire_log_message = Los registros han sido eliminados porque eran demasiad
runs.workflow = Flujo de trabajo runs.workflow = Flujo de trabajo
workflow.dispatch.use_from = Usar el flujo de trabajo de
workflow.dispatch.run = Correr flujo de trabajo
runs.no_workflows = Aún no hay flujos de trabajo.
workflow.dispatch.success = La ejecución del flujo de trabajo se ha solicitado correctamente.
workflow.dispatch.invalid_input_type = Tipo de entrada inválida "%s".
[projects] [projects]
type-1.display_name=Proyecto individual type-1.display_name=Proyecto individual
type-2.display_name=Proyecto de repositorio type-2.display_name=Proyecto de repositorio
@ -3963,7 +3992,7 @@ exact = Exacto
exact_tooltip = Incluir sólo los resultados que corresponden al término de búsqueda exacto exact_tooltip = Incluir sólo los resultados que corresponden al término de búsqueda exacto
issue_kind = Buscar incidencias… issue_kind = Buscar incidencias…
fuzzy = Difusa fuzzy = Difusa
runner_kind = Buscar ejecutores… runner_kind = Buscar corredores…
regexp_tooltip = Interpretar los términos de búsqueda como una expresión regular regexp_tooltip = Interpretar los términos de búsqueda como una expresión regular
regexp = Expresión Regular regexp = Expresión Regular

View file

@ -2,7 +2,7 @@
home=Etusivu home=Etusivu
dashboard=Kojelauta dashboard=Kojelauta
explore=Tutki explore=Tutki
help=Apua help=Ohje
logo=Logo logo=Logo
sign_in=Kirjaudu sisään sign_in=Kirjaudu sisään
sign_in_or=tai sign_in_or=tai
@ -41,7 +41,7 @@ webauthn_error=Turva-avainta ei voitu lukea.
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia. webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen. 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_unable_to_process=Palvelin ei pystynyt käsittelemään pyyntöä.
webauthn_error_duplicated=Turva-avainta ei ole sallittu tässä pyynnössä. Varmista, ettei avainta ole jo rekisteröity. 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. webauthn_error_empty=Sinun täytyy asettaa nimi tälle avaimelle.
webauthn_error_timeout=Aikakatkaisu saavutettu ennenkuin avaintasi on voitu lukea. Lataa tämä sivu uudelleen ja yritä uudelleen. webauthn_error_timeout=Aikakatkaisu saavutettu ennenkuin avaintasi on voitu lukea. Lataa tämä sivu uudelleen ja yritä uudelleen.
@ -98,7 +98,7 @@ preview=Esikatselu
loading=Ladataan… loading=Ladataan…
error=Virhe error=Virhe
error404=Sivu, jota yrität nähdä, joko <strong>ei löydy</strong>, <strong>on poistettu</strong> tai <strong>et ole oikeutettu</strong> katsomaan sitä. error404=Sivu, jota yrität nähdä, joko <strong>ei löydy</strong>, <strong>on poistettu</strong> tai <strong>et ole oikeutettu</strong> katsomaan sitä.
never=Ei koskaan never=Ei koskaan
@ -216,7 +216,7 @@ string.asc = A - Ö
string.desc = Ö - A string.desc = Ö - A
[error] [error]
occurred=Virhe tapahtui occurred=Tapahtui virhe
missing_csrf=Virheellinen pyyntö: CSRF-tunnusta ei ole olemassa missing_csrf=Virheellinen pyyntö: CSRF-tunnusta ei ole olemassa
invalid_csrf=Virheellinen pyyntö: Virheellinen CSRF-tunniste invalid_csrf=Virheellinen pyyntö: Virheellinen CSRF-tunniste
not_found=Kohdetta ei löytynyt. not_found=Kohdetta ei löytynyt.
@ -250,7 +250,7 @@ db_schema=Skeema
ssl_mode=SSL ssl_mode=SSL
path=Polku path=Polku
sqlite_helper=SQLite3-tietokannan tiedostopolku.<br>Syötä absoluuttinen polku, jos ajat Forgejoa palveluna. sqlite_helper=SQLite3-tietokannan tiedostopolku.<br>Syötä absoluuttinen polku, jos ajat Forgejoa palveluna.
reinstall_error=Yrität asentaa olemassa olevaan Forgejo tietokantaan reinstall_error=Yrität asentaa olemassa olevaan Forgejo-tietokantaan
reinstall_confirm_message=Asentaminen uudelleen olemassa olevalla Forgejo-tietokannalla voi aiheuttaa useita ongelmia. Useimmissa tapauksissa sinun pitäisi käyttää olemassa olevia "app.ini" asetuksia Forgejon käyttöön. Jos tiedät mitä teet, vahvista seuraavat seikat: reinstall_confirm_message=Asentaminen uudelleen olemassa olevalla Forgejo-tietokannalla voi aiheuttaa useita ongelmia. Useimmissa tapauksissa sinun pitäisi käyttää olemassa olevia "app.ini" asetuksia Forgejon käyttöön. Jos tiedät mitä teet, vahvista seuraavat seikat:
reinstall_confirm_check_1=Tiedot, jotka on salattu SECRET_KEY:llä app.ini:ssä saatetaan menettää: käyttäjät eivät ehkä voi kirjautua sisään 2FA/OTP:lla ja peilit eivät välttämättä toimi oikein. Ruksaamalla tämän vahvistat, että nykyinen app.ini -tiedosto sisältää oikean SECRET_KEY:n. reinstall_confirm_check_1=Tiedot, jotka on salattu SECRET_KEY:llä app.ini:ssä saatetaan menettää: käyttäjät eivät ehkä voi kirjautua sisään 2FA/OTP:lla ja peilit eivät välttämättä toimi oikein. Ruksaamalla tämän vahvistat, että nykyinen app.ini -tiedosto sisältää oikean SECRET_KEY:n.
reinstall_confirm_check_2=Repot ja asetukset saattaa olla tarpeen uudelleensynkronoida. Valitsemalla tämän vahvistat, että uudelleensynkronoit repojen koukut ja authorized_keys -tiedoston manuaalisesti. Varmistat, että repon ja peilin asetukset ovat oikeat. reinstall_confirm_check_2=Repot ja asetukset saattaa olla tarpeen uudelleensynkronoida. Valitsemalla tämän vahvistat, että uudelleensynkronoit repojen koukut ja authorized_keys -tiedoston manuaalisesti. Varmistat, että repon ja peilin asetukset ovat oikeat.
@ -451,7 +451,7 @@ email_domain_blacklisted=Et voi rekisteröityä sähköpostiosoittellasi.
authorize_application=Valtuuta sovellus authorize_application=Valtuuta sovellus
authorize_redirect_notice=Sinut uudelleen ohjataan osoitteeseen %s jos valtuutat tämän sovelluksen. authorize_redirect_notice=Sinut uudelleen ohjataan osoitteeseen %s jos valtuutat tämän sovelluksen.
authorize_application_created_by=Tämän sovelluksen on luonnut %s. authorize_application_created_by=Tämän sovelluksen on luonnut %s.
authorize_application_description=Jos myönnät valtuuden, sovellus voi käyttää kaikkia tilitietojasi ja kirjoittaa niihin, mukaan lukien yksityiset repot ja organisaatiot. authorize_application_description=Jos myönnät valtuuden, sovellus voi käyttää kaikkia tilitietojasi ja kirjoittaa niihin, mukaan lukien yksityiset repositoriot ja organisaatiot.
authorize_title=Valtuutatko "%s" pääsemään tilillesi? authorize_title=Valtuutatko "%s" pääsemään tilillesi?
authorization_failed=Käyttöoikeuden varmistus epäonnistui authorization_failed=Käyttöoikeuden varmistus epäonnistui
sspi_auth_failed=SSPI todennus epäonnistui sspi_auth_failed=SSPI todennus epäonnistui
@ -550,6 +550,12 @@ totp_disabled.no_2fa = Muita kaksivaiheisen tunnistautumisen menetelmiä ei ole
totp_enrolled.subject = Olet aktivoinut TOTP:in kaksivaiheisen todennuksen menetelmäksi totp_enrolled.subject = Olet aktivoinut TOTP:in kaksivaiheisen todennuksen menetelmäksi
removed_security_key.no_2fa = Yhtään kaksivaiheisen tunnistautumisen menetelmää ei ole määritelty, joten tilillesi ei enää tarvitse kirjautua kaksivaiheisella tunnistautumisella.
totp_enrolled.text_1.no_webauthn = Otit TOTP:n käyttöön tilillesi. Tämä tarkoittaa, että kirjauduttaessa sisään tilillesi sinun täytyy käyttää TOTP menetelmää kaksivaiheisena tunnistautumisena.
totp_enrolled.text_1.has_webauthn = Otit TOTP:n käyttöön tilillesi. Tämä tarkoittaa, että kirjauduttaessa sisään tilillesi voit käyttää TOTP menetelmää kaksivaiheisena tunnistautumisena tai mitä tahansa turva-avaimiasi.
repo.collaborator.added.subject = %s lisäsi sinut %s yhteistyökumppaniksi
team_invite.text_3 = Huomaa: Tämä kutsu on tarkoitettu %[1]s:lle. Jos et odottanut tätä kutsua, voit jättää tämän sähköpostin huomiotta.
[modal] [modal]
yes=Kyllä yes=Kyllä
no=Ei no=Ei
@ -567,7 +573,7 @@ SSHTitle=SSH avain nimi
HttpsUrl=HTTPS-osoite HttpsUrl=HTTPS-osoite
TeamName=Tiimin nimi TeamName=Tiimin nimi
AuthName=Luvan nimi AuthName=Luvan nimi
AdminEmail=Ylläpito sähköposti AdminEmail=Ylläpitäjän sähköposti
NewBranchName=Uuden haaran nimi NewBranchName=Uuden haaran nimi
CommitSummary=Commitin yhteenveto CommitSummary=Commitin yhteenveto
@ -694,7 +700,7 @@ webauthn=Kaksivaiheinen todennus (Turva-avaimet)
public_profile=Julkinen profiili public_profile=Julkinen profiili
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjätunnustaan. Ole hyvä ja ota yhteyttä sivuston ylläpitäjään saadaksesi lisätietoa. password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjätunnustaan. Ole hyvä ja ota yhteyttä sivuston ylläpitäjään saadaksesi lisätietoa.
full_name=Koko nimi full_name=Koko nimi
website=Nettisivut website=Verkkosivusto
location=Sijainti location=Sijainti
update_theme=Vaihda teema update_theme=Vaihda teema
update_profile=Päivitä profiili update_profile=Päivitä profiili
@ -830,7 +836,7 @@ access_token_deletion_cancel_action=Peruuta
access_token_deletion_confirm_action=Poista access_token_deletion_confirm_action=Poista
permission_read=Luettu permission_read=Luettu
edit_oauth2_application=Muokkaa OAuth2 sovellusta edit_oauth2_application=Muokkaa OAuth2-sovellusta
remove_oauth2_application=Poista OAuth2-sovellus remove_oauth2_application=Poista OAuth2-sovellus
remove_oauth2_application_success=Sovellus on poistettu. remove_oauth2_application_success=Sovellus on poistettu.
create_oauth2_application=Luo uusi OAuth2-sovellus create_oauth2_application=Luo uusi OAuth2-sovellus
@ -854,7 +860,7 @@ twofa_enrolled=Tiliisi on otettu käyttöön kaksivaiheinen vahvistus. Ota palau
webauthn_nickname=Nimimerkki webauthn_nickname=Nimimerkki
manage_account_links=Yhdistetyt tilit manage_account_links=Yhdistetyt tilit
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo tiliisi. manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo-tiliisi.
link_account=Yhdistä tili link_account=Yhdistä tili
remove_account_link=Poista yhdistetty tili remove_account_link=Poista yhdistetty tili
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tili kautta. Jatketaanko? remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tili kautta. Jatketaanko?
@ -1042,7 +1048,7 @@ migrate.github_token_desc=Voit laittaa yhden tai useamman pääsymerkin pilkulla
migrate.permission_denied=Sinun ei sallita tuovan paikallisia repoja. migrate.permission_denied=Sinun ei sallita tuovan paikallisia repoja.
migrate.failed=Siirto epäonnistui: %v migrate.failed=Siirto epäonnistui: %v
migrate.migrate_items_options=Pääsymerkki vaaditaan lisäkohteiden siirtämiseen migrate.migrate_items_options=Pääsymerkki vaaditaan lisäkohteiden siirtämiseen
migrate.migrating=Tuodaan kohteesta <b>%s</b> ... migrate.migrating=Tuodaan kohteesta <b>%s</b>
migrate.migrating_failed=Tuonti kohteesta <b>%s</b> epäonnistui. migrate.migrating_failed=Tuonti kohteesta <b>%s</b> epäonnistui.
migrate.migrating_git=Tuodaan Git-tietoja migrate.migrating_git=Tuodaan Git-tietoja
@ -1063,7 +1069,7 @@ code.desc=Pääsy lähdekoodiin, tiedostoihin, committeihin ja haaroihin.
branch=Haara branch=Haara
tree=Puu tree=Puu
filter_branch_and_tag=Suodata haara tai tagi filter_branch_and_tag=Suodata haara tai tagi
branches=Branchit branches=Haarat
tags=Tagit tags=Tagit
issues=Ongelmat issues=Ongelmat
pulls=Vetopyynnöt pulls=Vetopyynnöt
@ -1088,7 +1094,7 @@ blame=Selitys
download_file=Lataa tiedosto download_file=Lataa tiedosto
normal_view=Normaali näkymä normal_view=Normaali näkymä
line=rivi line=rivi
lines=rivejä lines=riviä
editor.new_file=Uusi tiedosto editor.new_file=Uusi tiedosto
editor.upload_file=Lähetä tiedosto editor.upload_file=Lähetä tiedosto
@ -1195,7 +1201,7 @@ issues.filter_type.all_issues=Kaikki ongelmat
issues.filter_type.assigned_to_you=Osoitettu sinulle issues.filter_type.assigned_to_you=Osoitettu sinulle
issues.filter_type.created_by_you=Ilmoittamasi issues.filter_type.created_by_you=Ilmoittamasi
issues.filter_type.mentioning_you=Jotka mainitsee sinut issues.filter_type.mentioning_you=Jotka mainitsee sinut
issues.filter_type.review_requested=Arvostelua pyydetty issues.filter_type.review_requested=Katselmointi pyydetty
issues.filter_sort=Lajittele issues.filter_sort=Lajittele
issues.filter_sort.latest=Uusin issues.filter_sort.latest=Uusin
issues.filter_sort.oldest=Vanhin issues.filter_sort.oldest=Vanhin
@ -1576,7 +1582,7 @@ settings.lfs_locks=Lukot
settings.lfs_invalid_locking_path=Virheellinen polku: %s settings.lfs_invalid_locking_path=Virheellinen polku: %s
settings.lfs_invalid_lock_directory=Hakemistoa ei voida lukita: %s settings.lfs_invalid_lock_directory=Hakemistoa ei voida lukita: %s
settings.lfs_lock_already_exists=Lukitus on jo olemassa: %s settings.lfs_lock_already_exists=Lukitus on jo olemassa: %s
settings.lfs_lock_path=Lukittavan tiedostopolku... settings.lfs_lock_path=Lukittavan tiedostopolku
settings.lfs_locks_no_locks=Ei lukkoja settings.lfs_locks_no_locks=Ei lukkoja
settings.lfs_lock_file_no_exist=Lukittua tiedostoa ei ole olemassa oletushaarassa settings.lfs_lock_file_no_exist=Lukittua tiedostoa ei ole olemassa oletushaarassa
settings.lfs_force_unlock=Pakota lukituksen avaus settings.lfs_force_unlock=Pakota lukituksen avaus
@ -1610,8 +1616,8 @@ diff.comment.add_single_comment=Lisää yksittäinen kommentti
diff.comment.add_review_comment=Lisää kommentti diff.comment.add_review_comment=Lisää kommentti
diff.comment.start_review=Aloita tarkistus diff.comment.start_review=Aloita tarkistus
diff.comment.reply=Vastaa diff.comment.reply=Vastaa
diff.review.header=Lähetä arvio diff.review.header=Lähetä katselmointi
diff.review.placeholder=Tarkistuksen kommentti diff.review.placeholder=Katselmoinnin kommentti
diff.review.comment=Kommentoi diff.review.comment=Kommentoi
diff.review.approve=Hyväksy diff.review.approve=Hyväksy
diff.review.reject=Pyydä muutoksia diff.review.reject=Pyydä muutoksia
@ -2204,7 +2210,7 @@ create_org=Luo organisaatio
repo_updated=Päivitetty %s repo_updated=Päivitetty %s
members=Jäsenet members=Jäsenet
teams=Tiimit teams=Tiimit
lower_members=jäsenet lower_members=jäsentä
lower_repositories=repot lower_repositories=repot
create_new_team=Uusi tiimi create_new_team=Uusi tiimi
create_team=Luo tiimi create_team=Luo tiimi
@ -2316,7 +2322,7 @@ config=Asetukset
notices=Järjestelmän ilmoitukset notices=Järjestelmän ilmoitukset
monitor=Valvonta monitor=Valvonta
first_page=Ensimmäinen first_page=Ensimmäinen
last_page=Viimeisin last_page=Viimeinen
total=Yhteensä: %d total=Yhteensä: %d
dashboard.statistic=Yhteenveto dashboard.statistic=Yhteenveto
@ -2667,7 +2673,7 @@ auths.enable_ldap_groups = Käytä LDAP-ryhmiä
auths.login_source_exist = Todennuslähde "%s" on jo olemassa. auths.login_source_exist = Todennuslähde "%s" on jo olemassa.
[action] [action]
create_repo=luotu repo <a href="%s">%s</a> create_repo=loi repon <a href="%s">%s</a>
rename_repo=uudelleennimetty repo <code>%[1]s</code> nimelle <a href="%[2]s">%[3]s</a> rename_repo=uudelleennimetty repo <code>%[1]s</code> nimelle <a href="%[2]s">%[3]s</a>
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a> transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
push_tag=työnsi tagin <a href="%[2]s">%[3]s</a> kohteeseen <a href="%[1]s">%[4]s</a> push_tag=työnsi tagin <a href="%[2]s">%[3]s</a> kohteeseen <a href="%[1]s">%[4]s</a>

View file

@ -4082,4 +4082,4 @@ issues.write = <b>Écrire :</b> Fermer des tickets et gérer les métadonnées t
pulls.read = <b>Lire :</b> Lire et créer des demandes de tirage. pulls.read = <b>Lire :</b> Lire et créer des demandes de tirage.
[translation_meta] [translation_meta]
test = Ceci est une chaîne de test. Elle n'est pas affichée dans l'interface de Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce doux 100 % de complétion :) test = Ceci est une chaîne de test. Elle n'est pas affichée dans l'interface de Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce doux 100 % de complétion. :-)

View file

@ -128,7 +128,7 @@ copy_success = 복사되었습니다!
copy_error = 복사 실패 copy_error = 복사 실패
copy_type_unsupported = 이 파일 형식은 복사할 수 없습니다 copy_type_unsupported = 이 파일 형식은 복사할 수 없습니다
error = 오류 error = 오류
error404 = 도달하려는 페이지가 <strong>존재하지 않거나</strong> 볼 수 있는 <strong>권한이 없습니다</strong>. error404 = 도달하려는 페이지가 <strong>존재하지 않거나</strong> , <strong>제거 되었거나</strong> 또는 <strong>볼 권한이 없습니다</strong>.
go_back = 돌아가기 go_back = 돌아가기
invalid_data = 유효하지 않는 데이터: %v invalid_data = 유효하지 않는 데이터: %v
unknown = 알 수 없음 unknown = 알 수 없음
@ -176,10 +176,10 @@ footer.software = 이 소프트웨어에 대하여
[heatmap] [heatmap]
number_of_contributions_in_the_last_12_months = 지난 12달간 %s 명의 기여자 number_of_contributions_in_the_last_12_months = 지난 12달간 %s 명의 기여자
contributions_zero = 기여 없음 contributions_zero = 기여 없음
contributions_format = {year}년 {month} {day}일에 {contributions} contributions_format = {year}년 {month}월 {day}일의 기여자 {contributions}
contributions_one = 기여 contributions_one = 기여
contributions_few = 기여 contributions_few = 기여
less = 적은 less = 적은
more = 많은 more = 많은
@ -376,7 +376,7 @@ allow_password_change=사용자에게 비밀번호 변경을 요청 (권장됨)
reset_password_mail_sent_prompt=확인 메일이 <b>%s</b>로 전송되었습니다. 받은 편지함으로 도착한 메일을 %s 안에 확인해서 비밀번호 찾기 절차를 완료하십시오. reset_password_mail_sent_prompt=확인 메일이 <b>%s</b>로 전송되었습니다. 받은 편지함으로 도착한 메일을 %s 안에 확인해서 비밀번호 찾기 절차를 완료하십시오.
active_your_account=계정 활성화 active_your_account=계정 활성화
account_activated=계정이 활성화 되었습니다 account_activated=계정이 활성화 되었습니다
prohibit_login = prohibit_login =
resent_limit_prompt=활성화를 위한 이메일을 이미 전송했습니다. 3분 내로 이메일을 받지 못한 경우 재시도해주세요. resent_limit_prompt=활성화를 위한 이메일을 이미 전송했습니다. 3분 내로 이메일을 받지 못한 경우 재시도해주세요.
has_unconfirmed_mail=안녕하세요 %s, 이메일 주소(<b>%s</b>)가 확인되지 않았습니다. 확인 메일을 받으시지 못하겼거나 새로운 확인 메일이 필요하다면, 아래 버튼을 클릭해 재발송하실 수 있습니다. has_unconfirmed_mail=안녕하세요 %s, 이메일 주소(<b>%s</b>)가 확인되지 않았습니다. 확인 메일을 받으시지 못하겼거나 새로운 확인 메일이 필요하다면, 아래 버튼을 클릭해 재발송하실 수 있습니다.
resend_mail=여기를 눌러 확인 메일 재전송 resend_mail=여기를 눌러 확인 메일 재전송
@ -1897,20 +1897,20 @@ branch_kind = 브랜치 검색...
keyword_search_unavailable = 지금은 키워드로 검색이 지원되지 않습니다. 사이트 관리자에게 문의하십시오. keyword_search_unavailable = 지금은 키워드로 검색이 지원되지 않습니다. 사이트 관리자에게 문의하십시오.
commit_kind = 커밋 검색... commit_kind = 커밋 검색...
no_results = 일치하는 결과를 찾을 수 없습니다. no_results = 일치하는 결과를 찾을 수 없습니다.
search = 검색... search = 검색
type_tooltip = 검색 타입 type_tooltip = 검색 타입
fuzzy_tooltip = 검색어와 밀접하게 일치하는 결과도 포함 fuzzy_tooltip = 검색어와 밀접하게 일치하는 결과도 포함
repo_kind = 저장소 검색... repo_kind = 저장소 검색
user_kind = 사용자 검색... user_kind = 사용자 검색
org_kind = 조직 검색... org_kind = 조직 검색
team_kind = 팀 검색... team_kind = 팀 검색...
code_kind = 코드 검색... code_kind = 코드 검색...
code_search_unavailable = 코드 검색은 현재 허용되지 않았습니다. 사이트 관리자와 연락하세요. code_search_unavailable = 코드 검색은 현재 허용되지 않았습니다. 사이트 관리자와 연락하세요.
package_kind = 패키지 검색... package_kind = 패키지 검색...
project_kind = 프로젝트 검색... project_kind = 프로젝트 검색...
exact_tooltip = 검색어와 정확하게 일치하는 결과만 포함 exact_tooltip = 검색어와 정확하게 일치하는 결과만 포함
issue_kind = 이슈 검색... issue_kind = 이슈 검색
pull_kind = 풀 검색... pull_kind = 풀 검색
milestone_kind = 마일스톤 검색... milestone_kind = 마일스톤 검색...
fuzzy = 모호함 fuzzy = 모호함
union = 통합 검색 union = 통합 검색

View file

@ -228,7 +228,7 @@ server_internal = Iekšēja servera kļūda
app_desc=Pašmitināms Git pakalpojums bez galvassāpēm app_desc=Pašmitināms Git pakalpojums bez galvassāpēm
install=Viegli uzstādīt install=Viegli uzstādīt
install_desc=Vienkārši <a target="_blank" rel="noopener noreferrer" href="%[1]s">jāpalaiž izpildāmā datne</a> vajadzīgajai sistēmai, jāizmanto <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> vai jāiegūst <a target="_blank" rel="noopener noreferrer" href="%[3]s">pakotne</a>. install_desc=Vienkārši <a target="_blank" rel="noopener noreferrer" href="%[1]s">jāpalaiž izpildāmā datne</a> vajadzīgajai sistēmai, jāizmanto <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> vai jāiegūst <a target="_blank" rel="noopener noreferrer" href="%[3]s">pakotne</a>.
platform=Pieejama dažādām platformām platform=Dažādas platformas
lightweight=Viegla lightweight=Viegla
lightweight_desc=Forgejo ir zemas tehniskās prasības, un to var darbināt nedārgā Raspberry Pi datorā. Taupām savas ierīces patērēto enerģiju! lightweight_desc=Forgejo ir zemas tehniskās prasības, un to var darbināt nedārgā Raspberry Pi datorā. Taupām savas ierīces patērēto enerģiju!
license=Atvērtā pirmkoda license=Atvērtā pirmkoda
@ -1557,10 +1557,10 @@ issues.label_templates.helper=Atlasīt priekšiestatītu iezīmju kopu
issues.label_templates.use=Izmantot iezīmju kopu issues.label_templates.use=Izmantot iezīmju kopu
issues.label_templates.fail_to_load_file=Neizdevās ielādēt iezīmju sagataves datni "%s": %v issues.label_templates.fail_to_load_file=Neizdevās ielādēt iezīmju sagataves datni "%s": %v
issues.add_label=pievienoja %s iezīmi %s issues.add_label=pievienoja %s iezīmi %s
issues.add_labels=pievienoja %s iezīmes %s issues.add_labels=pievienoja iezīmes %s %s
issues.remove_label=noņēma %s iezīmi %s issues.remove_label=noņēma %s iezīmi %s
issues.remove_labels=noņēma %s iezīmes %s issues.remove_labels=noņēma iezīmes %s %s
issues.add_remove_labels=pievienoja %s un noņēma %s iezīmes %s issues.add_remove_labels=pievienoja iezīmes %s un noņēma %s %s
issues.add_milestone_at=`pievienoja atskaites punktu <b>%s</b> %s` issues.add_milestone_at=`pievienoja atskaites punktu <b>%s</b> %s`
issues.add_project_at=`pievienoja šo projektam <b>%s</b> %s` issues.add_project_at=`pievienoja šo projektam <b>%s</b> %s`
issues.change_milestone_at=`nomainīja atskaites punktu no <b>%s</b> uz <b>%s</b> %s` issues.change_milestone_at=`nomainīja atskaites punktu no <b>%s</b> uz <b>%s</b> %s`
@ -1581,7 +1581,7 @@ issues.delete_branch_at=`izdzēsa zaru <b>%s</b> %s`
issues.filter_label=Iezīme issues.filter_label=Iezīme
issues.filter_label_exclude=`Jāizmanto <code>alt</code> + <code>klikšķis/Enter</code>, lai neiekļautu iezīmes` issues.filter_label_exclude=`Jāizmanto <code>alt</code> + <code>klikšķis/Enter</code>, lai neiekļautu iezīmes`
issues.filter_label_no_select=Visas iezīmes issues.filter_label_no_select=Visas iezīmes
issues.filter_label_select_no_label=Nav iezīmes issues.filter_label_select_no_label=Bez iezīmes
issues.filter_milestone=Atskaites punkts issues.filter_milestone=Atskaites punkts
issues.filter_milestone_all=Visi atskaites punkti issues.filter_milestone_all=Visi atskaites punkti
issues.filter_milestone_none=Nav atskaites punkta issues.filter_milestone_none=Nav atskaites punkta
@ -2052,7 +2052,7 @@ wiki.filter_page=Meklēt lapu
wiki.new_page=Lapa wiki.new_page=Lapa
wiki.page_title=Lapas virsraksts wiki.page_title=Lapas virsraksts
wiki.page_content=Lapas saturs wiki.page_content=Lapas saturs
wiki.default_commit_message=Rakstīt piezīmes par šīs lapas izmaiņām (izvēles). wiki.default_commit_message=Rakstīt piezīmes par šīs lapas izmaiņām (pēc izvēles).
wiki.save_page=Saglabāt lapu wiki.save_page=Saglabāt lapu
wiki.last_commit_info=%s laboja lapu %s wiki.last_commit_info=%s laboja lapu %s
wiki.edit_page_button=Labot wiki.edit_page_button=Labot
@ -2739,10 +2739,10 @@ error.csv.invalid_field_count=Nevar atveidot šo datni, jo tā satur nepareizu l
n_release_one = %s laidiens n_release_one = %s laidiens
n_release_few = %s laidieni n_release_few = %s laidieni
issues.new.assign_to_me = Piešķirt man issues.new.assign_to_me = Piešķirt man
admin.flags_replaced = Glabātavas iezīmes aizvietotas admin.flags_replaced = Glabātavas karogi aizvietoti
admin.failed_to_replace_flags = Neizdevās aizvietot glabātavas iezīmes admin.failed_to_replace_flags = Neizdevās aizvietot glabātavas karogus
admin.manage_flags = Pārvaldīt iezīmes admin.manage_flags = Pārvaldīt karogus
admin.enabled_flags = Glabātavā iespējotās iezīmes: admin.enabled_flags = Glabātavā iespējotie karogi:
n_commit_one = %s iesūtījums n_commit_one = %s iesūtījums
editor.push_out_of_date = Aizgādājums izskatās novecojis. editor.push_out_of_date = Aizgādājums izskatās novecojis.
file_follow = Sekot simboliskajai saitei file_follow = Sekot simboliskajai saitei
@ -2764,7 +2764,7 @@ n_branch_one = %s zars
object_format_helper = Glabātavas objektu veidols. Vēlak to nevarēs mainīt. SHA1 ir vissaderīgākais. object_format_helper = Glabātavas objektu veidols. Vēlak to nevarēs mainīt. SHA1 ir vissaderīgākais.
commits.renamed_from = Pārdēvēts no %s commits.renamed_from = Pārdēvēts no %s
rss.must_be_on_branch = Jāatrodas zarā, lai iegūtu RSS barotni. rss.must_be_on_branch = Jāatrodas zarā, lai iegūtu RSS barotni.
admin.update_flags = Atjaunināt iezīmes admin.update_flags = Atjaunināt karogus
open_with_editor = Atvērt ar %s open_with_editor = Atvērt ar %s
n_commit_few = %s iesūtījumi n_commit_few = %s iesūtījumi
no_eol.text = Nav EOL no_eol.text = Nav EOL

View file

@ -3618,7 +3618,7 @@ pin=Przypnij powiadomienie
mark_as_read=Oznacz jako przeczytane mark_as_read=Oznacz jako przeczytane
mark_as_unread=Oznacz jak nieprzeczytane mark_as_unread=Oznacz jak nieprzeczytane
mark_all_as_read=Oznacz wszystkie jako przeczytane mark_all_as_read=Oznacz wszystkie jako przeczytane
subscriptions = Subskrybcje subscriptions = Subskrypcje
no_subscriptions = Brak subskrypcji no_subscriptions = Brak subskrypcji
watching = Obserwowane watching = Obserwowane

View file

@ -1407,7 +1407,7 @@ editor.file_is_a_symlink=`"%s" é um link simbólico. Links simbólicos não pod
editor.filename_is_a_directory=O nome do arquivo "%s" já é usado como um nome de diretório neste repositório. editor.filename_is_a_directory=O nome do arquivo "%s" já é usado como um nome de diretório neste repositório.
editor.file_editing_no_longer_exists=O arquivo que está sendo editado, "%s", não existe mais neste repositório. editor.file_editing_no_longer_exists=O arquivo que está sendo editado, "%s", não existe mais neste repositório.
editor.file_deleting_no_longer_exists=O arquivo a ser excluído, "%s", não existe mais neste repositório. editor.file_deleting_no_longer_exists=O arquivo a ser excluído, "%s", não existe mais neste repositório.
editor.file_changed_while_editing=O conteúdo do arquivo mudou desde que você começou a editar. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as diferenças ou <strong>clique em Aplicar commit das alterações novamente</strong> para sobrescrever as alterações com sua versão atual. editor.file_changed_while_editing=O conteúdo do arquivo mudou desde que você abriu o arquivo. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as diferenças ou <strong>clique em Aplicar commit das alterações novamente</strong> para sobrescrever as alterações com sua versão atual.
editor.file_already_exists=Um arquivo com nome "%s" já existe neste repositório. editor.file_already_exists=Um arquivo com nome "%s" já existe neste repositório.
editor.commit_empty_file_header=Fazer commit de um arquivo vazio editor.commit_empty_file_header=Fazer commit de um arquivo vazio
editor.commit_empty_file_text=O arquivo que você está prestes fazer commit está vazio. Continuar? editor.commit_empty_file_text=O arquivo que você está prestes fazer commit está vazio. Continuar?

View file

@ -1420,7 +1420,7 @@ editor.file_is_a_symlink=`"%s" é uma ligação simbólica. Ligações simbólic
editor.filename_is_a_directory=O nome de ficheiro "%s" já está a ser usado como um nome de pasta neste repositório. editor.filename_is_a_directory=O nome de ficheiro "%s" já está a ser usado como um nome de pasta neste repositório.
editor.file_editing_no_longer_exists=O ficheiro que está a ser editado, "%s", já não existe neste repositório. editor.file_editing_no_longer_exists=O ficheiro que está a ser editado, "%s", já não existe neste repositório.
editor.file_deleting_no_longer_exists=O ficheiro que está a ser eliminado, "%s", já não existe neste repositório. editor.file_deleting_no_longer_exists=O ficheiro que está a ser eliminado, "%s", já não existe neste repositório.
editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que começou a editar. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as modificações ou clique em <strong>Cometer modificações novamente</strong> para escrever por cima. editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que abriu o ficheiro. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as modificações ou <strong>Cometer modificações novamente</strong> para escrever por cima.
editor.file_already_exists=Já existe um ficheiro com o nome "%s" neste repositório. editor.file_already_exists=Já existe um ficheiro com o nome "%s" neste repositório.
editor.commit_empty_file_header=Cometer um ficheiro vazio editor.commit_empty_file_header=Cometer um ficheiro vazio
editor.commit_empty_file_text=O ficheiro que está prestes a cometer está vazio. Quer continuar? editor.commit_empty_file_text=O ficheiro que está prestes a cometer está vazio. Quer continuar?

View file

@ -1696,7 +1696,7 @@ issues.num_participants_few=%d участников
issues.attachment.open_tab=`Нажмите, чтобы посмотреть «%s» в новой вкладке` issues.attachment.open_tab=`Нажмите, чтобы посмотреть «%s» в новой вкладке`
issues.attachment.download=`Нажмите, чтобы скачать «%s»` issues.attachment.download=`Нажмите, чтобы скачать «%s»`
issues.subscribe=Подписаться issues.subscribe=Подписаться
issues.unsubscribe=Отказаться от подписки issues.unsubscribe=Отписаться
issues.unpin_issue=Открепить задачу issues.unpin_issue=Открепить задачу
issues.max_pinned=Нельзя закрепить больше задач issues.max_pinned=Нельзя закрепить больше задач
issues.pin_comment=закрепил(а) эту задачу %s issues.pin_comment=закрепил(а) эту задачу %s

View file

@ -145,6 +145,9 @@ issues = Problémy
filter.is_archived = Archivované filter.is_archived = Archivované
filter.private = Súkromný filter.private = Súkromný
toggle_menu = Prepni menu
more_items = Viac vecí
[aria] [aria]
navbar=Navigačná lišta navbar=Navigačná lišta
footer=Päta footer=Päta

View file

@ -2245,15 +2245,15 @@ symbolic_link=Symbolisk länk
milestone_kind = Sök milstolpar... milestone_kind = Sök milstolpar...
exact = Exakt exact = Exakt
exact_tooltip = Inkludera bara resultat som exakt matchar söktermen exact_tooltip = Inkludera bara resultat som exakt matchar söktermen
repo_kind = Sök repon... repo_kind = Sök repon
user_kind = Sök användare... user_kind = Sök användare
code_kind = Sök kod... code_kind = Sök kod...
package_kind = Sök paket... package_kind = Sök paket...
runner_kind = Sök exekutorer... runner_kind = Sök exekutorer...
branch_kind = Sök grenar... branch_kind = Sök grenar...
commit_kind = Sök commiter... commit_kind = Sök commiter...
project_kind = Sök projekt... project_kind = Sök projekt...
search = Sök... search = Sök
type_tooltip = Söktyp type_tooltip = Söktyp
team_kind = Sök lag... team_kind = Sök lag...
org_kind = Sök organisationer... org_kind = Sök organisationer...
@ -2265,7 +2265,7 @@ no_results = Inga matchande resultat hittades.
code_search_by_git_grep = Nuvarande kodsökningsresultat gjordes med "git grep". Det kan finnas bättre resultat om webbplatsadministratören möjliggör indexering av kod. code_search_by_git_grep = Nuvarande kodsökningsresultat gjordes med "git grep". Det kan finnas bättre resultat om webbplatsadministratören möjliggör indexering av kod.
fuzzy = Ungefärlig fuzzy = Ungefärlig
union = Nyckelord union = Nyckelord
union_tooltip = Inkludera resultat som matchar något av de med mellanslag sepererade sökorden union_tooltip = Inkludera resultat som matchar något av de med mellanslag separerade sökorden
pull_kind = Sök ändringsförslag… pull_kind = Sök ändringsförslag…
regexp = RegExp regexp = RegExp
keyword_search_unavailable = Sökning på nyckelord är för närvarande inte tillgängligt. Vänligen kontakta webbplatsadministratören. keyword_search_unavailable = Sökning på nyckelord är för närvarande inte tillgängligt. Vänligen kontakta webbplatsadministratören.

View file

@ -167,6 +167,8 @@ new_migrate.title = Yeni geçiş
new_migrate.link = Yeni geçiş new_migrate.link = Yeni geçiş
copy_path = Dizini kopyala copy_path = Dizini kopyala
confirm_delete_artifact = "%s" adlı öğeyi silmek istediğinizden emin misiniz?
[aria] [aria]
navbar=Gezinti çubuğu navbar=Gezinti çubuğu
footer=Alt Bilgi footer=Alt Bilgi
@ -3772,13 +3774,13 @@ submodule=Alt modül
[search] [search]
project_kind = Projeleri ara... project_kind = Projeleri ara...
org_kind = Organizasyonları ara... org_kind = Organizasyonları ara
team_kind = Takımları ara... team_kind = Takımları ara
search = Ara... search = Ara
code_kind = Kodları ara... code_kind = Kod ara…
type_tooltip = Arama türü type_tooltip = Arama türü
repo_kind = Depoları ara... repo_kind = Depoları ara...
user_kind = Kullanıcıları ara... user_kind = Kullanıcıları ara
milestone_kind = Kilometre taşlarını ara... milestone_kind = Kilometre taşlarını ara...
branch_kind = Dalları ara... branch_kind = Dalları ara...
package_kind = Paketleri ara... package_kind = Paketleri ara...

View file

@ -231,7 +231,7 @@ platform_desc=Forgejo підтверджено працює на вільних
lightweight=Невибагливість lightweight=Невибагливість
lightweight_desc=Forgejo має низькі вимоги до ресурсів та може працювати на недорогому Raspberry Pi. Заощадьте енергію свого комп'ютера! lightweight_desc=Forgejo має низькі вимоги до ресурсів та може працювати на недорогому Raspberry Pi. Заощадьте енергію свого комп'ютера!
license=Відкритий вихідний код license=Відкритий вихідний код
license_desc=Відвідайте <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Приєднайтесь до нас та <a target="_blank" rel="noopener noreferrer" href="%[2]s">зробіть свій внесок</a> до проєкту, щоб зробити його ще краще. Не бійтеся долучитися! license_desc=Відвідайте <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Приєднуйтеся до нас і <a target="_blank" rel="noopener noreferrer" href="%[2]s">зробіть свій внесок</a>, щоб покращити проєкт ще більше. Не бійтеся долучитися!
install_desc = Просто <a target="_blank" rel="noopener noreferrer" href="%[1]s">запустіть уже зібрану програму</a> для своєї платформи, розгорніть її за допомогою <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> або встановіть <a target="_blank" rel="noopener noreferrer" href="%[3]s">пакунок</a>. install_desc = Просто <a target="_blank" rel="noopener noreferrer" href="%[1]s">запустіть уже зібрану програму</a> для своєї платформи, розгорніть її за допомогою <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> або встановіть <a target="_blank" rel="noopener noreferrer" href="%[3]s">пакунок</a>.
[install] [install]
@ -464,7 +464,7 @@ last_admin = Ви не можете видалити останнього адм
oauth.signin.error.access_denied = Запит на авторизацію було відхилено. oauth.signin.error.access_denied = Запит на авторизацію було відхилено.
change_unconfirmed_email_error = Не вдалося змінити електронну адресу: %v change_unconfirmed_email_error = Не вдалося змінити електронну адресу: %v
manual_activation_only = Зв'яжіться з адміністратором сайту, аби завершити активацію. manual_activation_only = Зв'яжіться з адміністратором сайту, аби завершити активацію.
prohibit_login_desc = Ваш обліковий запис було відізвано від взаємодії з екземпляром. Звʼяжіться з адміністратором екземпляру, щоб отримати доступ знову. prohibit_login_desc = Ваш обліковий запис було відізвано від взаємодії з екземпляром. Звʼяжіться з адміністратором екземпляра, щоб отримати доступ знову.
invalid_code_forgot_password = Ваш код підтвердження недійсний. Натисніть <a href="%s">тут</a>, аби почати нову сесію. invalid_code_forgot_password = Ваш код підтвердження недійсний. Натисніть <a href="%s">тут</a>, аби почати нову сесію.
reset_password_wrong_user = Ви ввійшли як %s, але посилання на відновлення було передбачене для %s reset_password_wrong_user = Ви ввійшли як %s, але посилання на відновлення було передбачене для %s
back_to_sign_in = Назад до входу back_to_sign_in = Назад до входу
@ -2366,8 +2366,8 @@ settings.packages_desc = Увімкнути реєстр пакунків реп
issues.role.contributor_helper = У цьому репозиторії є коміти цього користувача. issues.role.contributor_helper = У цьому репозиторії є коміти цього користувача.
contributors.contribution_type.deletions = Видалення contributors.contribution_type.deletions = Видалення
contributors.contribution_type.filter_label = Вид внеску: contributors.contribution_type.filter_label = Вид внеску:
issues.role.contributor = Дописувач issues.role.contributor = Учасник розробки
activity.navbar.contributors = Дописувачі activity.navbar.contributors = Учасники розробки
settings.protected_branch.save_rule = Зберегти правило settings.protected_branch.save_rule = Зберегти правило
release.tags_for = Теги %s release.tags_for = Теги %s
editor.file_is_a_symlink = `«%s» — символьне посилання. Символьні посилання не можна редагувати у вебредакторі` editor.file_is_a_symlink = `«%s» — символьне посилання. Символьні посилання не можна редагувати у вебредакторі`
@ -2521,7 +2521,7 @@ fork_branch = Гілка, яку буде клоновано у форк
already_forked = Ви вже створили форк %s already_forked = Ви вже створили форк %s
fork_to_different_account = Створити форк до іншого облікового запису fork_to_different_account = Створити форк до іншого облікового запису
fork_no_valid_owners = Неможливо створити форк цього репозиторію, оскільки тут немає дійсних власників. fork_no_valid_owners = Неможливо створити форк цього репозиторію, оскільки тут немає дійсних власників.
pulls.agit_explanation = Створено через робочий потік AGit. AGit дозволяє дописувачам пропонувати зміни за допомогою «git push» без створення форку або нової гілки. pulls.agit_explanation = Створено через робочий потік AGit. AGit дозволяє учасникам пропонувати зміни за допомогою «git push» без створення форку або нової гілки.
diff.review.self_approve = Автори запитів на злиття не можуть схвалювати власні запити на злиття diff.review.self_approve = Автори запитів на злиття не можуть схвалювати власні запити на злиття
settings.event_pull_request_approvals = Схвалення запитів на злиття settings.event_pull_request_approvals = Схвалення запитів на злиття
diff.git-notes.add = Додати примітку diff.git-notes.add = Додати примітку
@ -2661,6 +2661,8 @@ release.asset_name = Назва ресурсу
release.add_external_asset = Додати зовнішній ресурс release.add_external_asset = Додати зовнішній ресурс
find_file.no_matching = Не знайдено відповідного файлу find_file.no_matching = Не знайдено відповідного файлу
issues.role.first_time_contributor = Новий учасник
[graphs] [graphs]
contributors.what = внески contributors.what = внески
component_loading_info = Це може зайняти деякий час… component_loading_info = Це може зайняти деякий час…

View file

@ -322,12 +322,12 @@ install_btn_confirm=立即安装
test_git_failed=无法识别 “git” 命令:%v test_git_failed=无法识别 “git” 命令:%v
sqlite3_not_available=当前 Forgejo 版本不支持 SQLite3。请从 %s 下载官方构建版(注:请勿下载标有 “gobuild” 的版本)。 sqlite3_not_available=当前 Forgejo 版本不支持 SQLite3。请从 %s 下载官方构建版(注:请勿下载标有 “gobuild” 的版本)。
invalid_db_setting=数据库设置无效:%v invalid_db_setting=数据库设置无效:%v
invalid_db_table=数据库表 '%s' 无效: %v invalid_db_table=数据库表 '%s' 无效:%v
invalid_repo_path=仓库根目录设置无效:%v invalid_repo_path=仓库根目录设置无效:%v
invalid_app_data_path=应用数据路径无效: %v invalid_app_data_path=应用数据路径无效:%v
run_user_not_match=运行用户名不是当前的用户名:%s -> %s run_user_not_match=运行用户名不是当前的用户名:%s -> %s
internal_token_failed=生成内部令牌失败: %v internal_token_failed=生成内部令牌失败:%v
secret_key_failed=生成密钥失败: %v secret_key_failed=生成密钥失败:%v
save_config_failed=应用配置保存失败:%v save_config_failed=应用配置保存失败:%v
invalid_admin_setting=管理员帐户设置无效:%v invalid_admin_setting=管理员帐户设置无效:%v
invalid_log_root_path=日志路径无效:%v invalid_log_root_path=日志路径无效:%v
@ -479,7 +479,7 @@ password_pwned_err=无法完成对 HaveIBeenPwned 的请求
last_admin=您不能删除最后一个管理员。必须至少保留一个管理员。 last_admin=您不能删除最后一个管理员。必须至少保留一个管理员。
change_unconfirmed_email = 如果您在注册时提供了错误的邮箱地址,您可以在下方修改,激活邮件会发送到修改后的邮箱地址。 change_unconfirmed_email = 如果您在注册时提供了错误的邮箱地址,您可以在下方修改,激活邮件会发送到修改后的邮箱地址。
change_unconfirmed_email_summary = 修改用来接收激活邮件的邮箱地址。 change_unconfirmed_email_summary = 修改用来接收激活邮件的邮箱地址。
change_unconfirmed_email_error = 无法修改邮箱地址: %v change_unconfirmed_email_error = 无法修改邮箱地址:%v
tab_signin = 登录 tab_signin = 登录
tab_signup = 注册 tab_signup = 注册
hint_login = 已经有账户了吗?<a href="%s">立即登录!</a> hint_login = 已经有账户了吗?<a href="%s">立即登录!</a>
@ -537,7 +537,7 @@ issue.in_tree_path=在 %s 中:
release.new.subject=%[2]s 中的 %[1]s 发布了 release.new.subject=%[2]s 中的 %[1]s 发布了
release.new.text=<b>@%[1]s</b> 于 %[3]s 发布了 %[2]s release.new.text=<b>@%[1]s</b> 于 %[3]s 发布了 %[2]s
release.title=标题: %s release.title=标题:%s
release.note=注释: release.note=注释:
release.downloads=下载: release.downloads=下载:
release.download.zip=源代码ZIP release.download.zip=源代码ZIP
@ -617,7 +617,7 @@ include_error=`必须包含子字符串 "%s"。`
glob_pattern_error=`匹配模式无效:%s.` glob_pattern_error=`匹配模式无效:%s.`
regex_pattern_error=`正则表达式无效:%s.` regex_pattern_error=`正则表达式无效:%s.`
username_error=` 只允许包含字母数字字符“0-9”、“a-z”、“A-Z”、破折号“-”、下划线“_”和点“.”)。不能以非字母数字字符开头或结尾,并且不允许连续的非字母数字字符。` username_error=` 只允许包含字母数字字符“0-9”、“a-z”、“A-Z”、破折号“-”、下划线“_”和点“.”)。不能以非字母数字字符开头或结尾,并且不允许连续的非字母数字字符。`
invalid_group_team_map_error=`映射无效: %s` invalid_group_team_map_error=`映射无效:%s`
unknown_error=未知错误: unknown_error=未知错误:
captcha_incorrect=验证码不正确。 captcha_incorrect=验证码不正确。
password_not_match=密码不匹配。 password_not_match=密码不匹配。
@ -659,7 +659,7 @@ organization_leave_success=您已成功离开组织 %s。
invalid_ssh_key=无法验证您的 SSH 密钥:%s invalid_ssh_key=无法验证您的 SSH 密钥:%s
invalid_gpg_key=无法验证您的 GPG 密钥:%s invalid_gpg_key=无法验证您的 GPG 密钥:%s
invalid_ssh_principal=无效的规则: %s invalid_ssh_principal=无效的规则:%s
must_use_public_key=您提供的密钥是私钥。不要在任何地方上传您的私钥,请改用您的公钥。 must_use_public_key=您提供的密钥是私钥。不要在任何地方上传您的私钥,请改用您的公钥。
unable_verify_ssh_key=无法验证 SSH 密钥,请仔细检查是否有错误。 unable_verify_ssh_key=无法验证 SSH 密钥,请仔细检查是否有错误。
auth_failed=授权验证失败:%v auth_failed=授权验证失败:%v
@ -683,7 +683,7 @@ To = 分支名
AccessToken = 访问令牌 AccessToken = 访问令牌
Description = 描述 Description = 描述
Pronouns = 代称 Pronouns = 代称
Biography = Biography =
username_claiming_cooldown = 用户名不能被认领,因为其仍处于保护期。其可以在%[1]s后被认领。 username_claiming_cooldown = 用户名不能被认领,因为其仍处于保护期。其可以在%[1]s后被认领。
email_domain_is_not_allowed = 用户电子邮件地址的域名<b>%s</b>与EMAIL_DOMAIN_ALLOWLIST或EMAIL_DOMAIN_BLOCKLIST冲突。请确保您正确设置了电子邮件地址。 email_domain_is_not_allowed = 用户电子邮件地址的域名<b>%s</b>与EMAIL_DOMAIN_ALLOWLIST或EMAIL_DOMAIN_BLOCKLIST冲突。请确保您正确设置了电子邮件地址。
@ -1461,7 +1461,7 @@ commits.view_path=在历史记录中的此处查看
commit.operations=操作 commit.operations=操作
commit.revert=还原 commit.revert=还原
commit.revert-header=还原: %s commit.revert-header=还原:%s
commit.revert-content=选择要还原的分支: commit.revert-content=选择要还原的分支:
commit.cherry-pick=拣选 commit.cherry-pick=拣选
commit.cherry-pick-header=Cherry-pick%s commit.cherry-pick-header=Cherry-pick%s
@ -2143,7 +2143,7 @@ activity.git_stats_deletion_n=%d 行被删除
contributors.contribution_type.filter_label=贡献类型: contributors.contribution_type.filter_label=贡献类型:
contributors.contribution_type.commits=提交 contributors.contribution_type.commits=提交
contributors.contribution_type.additions=更多 contributors.contribution_type.additions=增加
contributors.contribution_type.deletions=删除 contributors.contribution_type.deletions=删除
search=搜索 search=搜索
@ -2281,7 +2281,7 @@ settings.trust_model.collaborator=协作者
settings.trust_model.collaborator.long=协作者:信任协作者的签名 settings.trust_model.collaborator.long=协作者:信任协作者的签名
settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为「可信」(无论它们是否是提交者),签名只符合提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。 settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为「可信」(无论它们是否是提交者),签名只符合提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。
settings.trust_model.committer=提交者 settings.trust_model.committer=提交者
settings.trust_model.committer.long=提交者: 信任与提交者相符的签名(此特性类似 GitHub这会强制采用 Forgejo 作为提交者和签名者) settings.trust_model.committer.long=提交者:信任与提交者相符的签名(此特性类似 GitHub这会强制采用 Forgejo 作为提交者和签名者)
settings.trust_model.committer.desc=有效签名只有和提交者相匹配才会被标记为“受信任”,否则它们将被标记为“不匹配”。这强制 Forgejo 成为签名提交的提交者,而实际提交者被加上 Co-authored-by和 Co-committed-by的标记。 默认的 Forgejo 密钥必须匹配数据库中的一名用户。 settings.trust_model.committer.desc=有效签名只有和提交者相匹配才会被标记为“受信任”,否则它们将被标记为“不匹配”。这强制 Forgejo 成为签名提交的提交者,而实际提交者被加上 Co-authored-by和 Co-committed-by的标记。 默认的 Forgejo 密钥必须匹配数据库中的一名用户。
settings.trust_model.collaboratorcommitter=协作者+提交者 settings.trust_model.collaboratorcommitter=协作者+提交者
settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名 settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名
@ -2502,9 +2502,9 @@ settings.protect_branch_name_pattern=受保护的分支名称正则
settings.protect_branch_name_pattern_desc=受保护的分支名称正则。语法请参阅<a href="%s">文档</a> 。如main, release/** settings.protect_branch_name_pattern_desc=受保护的分支名称正则。语法请参阅<a href="%s">文档</a> 。如main, release/**
settings.protect_patterns=规则 settings.protect_patterns=规则
settings.protect_protected_file_patterns=受保护的文件模式(使用半角分号“;”分隔) settings.protect_protected_file_patterns=受保护的文件模式(使用半角分号“;”分隔)
settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用半角分号(“;”)分隔多个模式。 见<a href="%[1]s">%[2]s</a>文档了解模式语法。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>。 settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用半角分号(“;”)分隔多个模式。 见<a href="%[1]s">%[2]s</a>文档了解模式语法。例如:<code>.drone.yml</code>, <code>/docs/**/*.txt</code>。
settings.protect_unprotected_file_patterns=不受保护的文件模式(使用半角分号“;”分隔) settings.protect_unprotected_file_patterns=不受保护的文件模式(使用半角分号“;”分隔)
settings.protect_unprotected_file_patterns_desc=在用户有写权限的情况下允许绕过限制,直接修改设为不保护的文件。如有多个匹配模式,则可用半角分号(“;”)分隔开。见 <a href="%[1]s">%[2]s</a> 的文档以了解匹配模式的格式。例子: <code>.drone.yml</code>、<code>/docs/**/*.txt</code>。 settings.protect_unprotected_file_patterns_desc=在用户有写权限的情况下允许绕过限制,直接修改设为不保护的文件。如有多个匹配模式,则可用半角分号(“;”)分隔开。见 <a href="%[1]s">%[2]s</a> 的文档以了解匹配模式的格式。例子:<code>.drone.yml</code>、<code>/docs/**/*.txt</code>。
settings.add_protected_branch=启用保护 settings.add_protected_branch=启用保护
settings.delete_protected_branch=禁用保护 settings.delete_protected_branch=禁用保护
settings.update_protect_branch_success=分支保护规则 %s 更新成功。 settings.update_protect_branch_success=分支保护规则 %s 更新成功。
@ -2545,7 +2545,7 @@ settings.matrix.room_id=房间ID
settings.matrix.message_type=消息类型 settings.matrix.message_type=消息类型
settings.archive.button=存档仓库 settings.archive.button=存档仓库
settings.archive.header=存档此仓库 settings.archive.header=存档此仓库
settings.archive.text=存档仓库将使其完全只读。它将在首页隐藏。没有人(甚至你!)能够进行新的提交,或打开工单及合并请求。 settings.archive.text=存档仓库将使其完全只读。它将在首页隐藏。没有人(甚至包括你!)能够进行新的提交,或打开工单及合并请求。
settings.archive.success=仓库已成功存档。 settings.archive.success=仓库已成功存档。
settings.archive.error=仓库在存档时出现异常。请通过日志获取详细信息。 settings.archive.error=仓库在存档时出现异常。请通过日志获取详细信息。
settings.archive.error_ismirror=不能存档镜像仓库。 settings.archive.error_ismirror=不能存档镜像仓库。
@ -3083,11 +3083,11 @@ dashboard.task.process=任务:%[1]s
dashboard.task.cancelled=任务:%[1]s 已取消:%[3]s dashboard.task.cancelled=任务:%[1]s 已取消:%[3]s
dashboard.task.error=任务中的错误:%[1]s%[3]s dashboard.task.error=任务中的错误:%[1]s%[3]s
dashboard.task.finished=任务:%[2]s 启动的 %[1]s 已完成 dashboard.task.finished=任务:%[2]s 启动的 %[1]s 已完成
dashboard.task.unknown=未知任务: %[1]s dashboard.task.unknown=未知任务:%[1]s
dashboard.cron.started=已开始计划任务:%[1]s dashboard.cron.started=已开始计划任务:%[1]s
dashboard.cron.process=计划任务:%[1]s dashboard.cron.process=计划任务:%[1]s
dashboard.cron.cancelled=定时任务:%[1]s 已取消:%[3]s dashboard.cron.cancelled=定时任务:%[1]s 已取消:%[3]s
dashboard.cron.error=任务中的错误: %s%[3]s dashboard.cron.error=任务中的错误:%s%[3]s
dashboard.cron.finished=任务:%[1]s 已经完成 dashboard.cron.finished=任务:%[1]s 已经完成
dashboard.delete_inactive_accounts=删除所有未激活的帐户 dashboard.delete_inactive_accounts=删除所有未激活的帐户
dashboard.delete_inactive_accounts.started=删除所有未激活的账户任务已启动。 dashboard.delete_inactive_accounts.started=删除所有未激活的账户任务已启动。
@ -3221,7 +3221,7 @@ emails.filter_sort.email_reverse=电子邮件(逆序)
emails.filter_sort.name=用户名 emails.filter_sort.name=用户名
emails.filter_sort.name_reverse=用户名(倒序) emails.filter_sort.name_reverse=用户名(倒序)
emails.updated=电子邮件已更新 emails.updated=电子邮件已更新
emails.not_updated=无法更新请求的电子邮件地址: %v emails.not_updated=无法更新请求的电子邮件地址:%v
emails.duplicate_active=此电子邮件地址已被另一个用户激活使用。 emails.duplicate_active=此电子邮件地址已被另一个用户激活使用。
emails.change_email_header=更新电子邮件属性 emails.change_email_header=更新电子邮件属性
emails.change_email_text=您确定要更新该电子邮件地址吗? emails.change_email_text=您确定要更新该电子邮件地址吗?
@ -3247,7 +3247,7 @@ repos.lfs_size=LFS 大小
packages.package_manage_panel=软件包管理 packages.package_manage_panel=软件包管理
packages.total_size=总大小:%s packages.total_size=总大小:%s
packages.unreferenced_size=未引用大小: %s packages.unreferenced_size=未引用大小:%s
packages.cleanup=清理过期数据 packages.cleanup=清理过期数据
packages.cleanup.success=清理过期数据成功 packages.cleanup.success=清理过期数据成功
packages.owner=所有者 packages.owner=所有者
@ -3344,7 +3344,7 @@ auths.oauth2_group_claim_name=用于提供用户组名称的 Claim 声明名称
auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 - 需要上面的声明名称) auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 - 需要上面的声明名称)
auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 - 需要上面的声明名称) auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 - 需要上面的声明名称)
auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 - 要求在上面填写声明的名字) auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 - 要求在上面填写声明的名字)
auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,同步团队中移除用户 auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,从同步团队中移除用户
auths.enable_auto_register=允许自动注册 auths.enable_auto_register=允许自动注册
auths.sspi_auto_create_users=自动创建用户 auths.sspi_auto_create_users=自动创建用户
auths.sspi_auto_create_users_helper=允许 SSPI 认证在用户第一次登录时自动创建新账号 auths.sspi_auto_create_users_helper=允许 SSPI 认证在用户第一次登录时自动创建新账号
@ -3361,7 +3361,7 @@ auths.tips.oauth2.general=OAuth2 认证
auths.tips.oauth2.general.tip=当注册新的 OAuth2 身份验证时,回调/重定向 URL 应该是: auths.tips.oauth2.general.tip=当注册新的 OAuth2 身份验证时,回调/重定向 URL 应该是:
auths.tip.oauth2_provider=OAuth2 提供程序 auths.tip.oauth2_provider=OAuth2 提供程序
auths.tip.bitbucket=`在 %s auths.tip.bitbucket=`在 %s
auths.tip.nextcloud=使用下面的菜单“设置Settings -> 安全Security -> OAuth 2.0 client”在您的实例上注册一个新的 OAuth 客户端 auths.tip.nextcloud=使用菜单“设置->安全->OAuth 2.0客户端”在您的实例上注册一个新的 OAuth 客户端
auths.tip.dropbox=在 %s 上创建一个新的应用程序 auths.tip.dropbox=在 %s 上创建一个新的应用程序
auths.tip.facebook=`在 %s 注册一个新的应用,并添加产品"Facebook 登录"` auths.tip.facebook=`在 %s 注册一个新的应用,并添加产品"Facebook 登录"`
auths.tip.github=在 %s 注册一个 OAuth 应用程序 auths.tip.github=在 %s 注册一个 OAuth 应用程序
@ -3385,7 +3385,7 @@ auths.still_in_used=认证源仍在使用。请先解除或者删除使用此认
auths.deletion_success=认证源已经更新。 auths.deletion_success=认证源已经更新。
auths.login_source_exist=认证源 '%s' 已经存在。 auths.login_source_exist=认证源 '%s' 已经存在。
auths.login_source_of_type_exist=此类型的认证源已存在。 auths.login_source_of_type_exist=此类型的认证源已存在。
auths.unable_to_initialize_openid=无法初始化 OpenID Connect 提供商: %s auths.unable_to_initialize_openid=无法初始化 OpenID Connect 提供商:%s
auths.invalid_openIdConnectAutoDiscoveryURL=无效的 Auto Discovery URL这必须是一个以 http:// 或 https://开头的有效的 URL auths.invalid_openIdConnectAutoDiscoveryURL=无效的 Auto Discovery URL这必须是一个以 http:// 或 https://开头的有效的 URL
config.server_config=服务器配置 config.server_config=服务器配置
@ -3546,7 +3546,7 @@ monitor.process.cancel_notices=中止:<strong>%s</strong>
monitor.process.children=子进程 monitor.process.children=子进程
monitor.queues=队列 monitor.queues=队列
monitor.queue=队列: %s monitor.queue=队列:%s
monitor.queue.name=名称 monitor.queue.name=名称
monitor.queue.type=类型 monitor.queue.type=类型
monitor.queue.exemplar=数据类型 monitor.queue.exemplar=数据类型
@ -3663,7 +3663,7 @@ raw_minutes=分钟
[dropzone] [dropzone]
default_message=拖放文件或点击此处上传。 default_message=拖放文件或点击此处上传。
invalid_input_type=您不能上传该类型的文件。 invalid_input_type=您不能上传该类型的文件。
file_too_big=文件体积({{filesize}} MB超过了最大允许体积{{maxFilesize}} MB file_too_big=文件体积({{filesize}} MB超过了最大允许体积{{maxFilesize}} MB
remove_file=移除文件 remove_file=移除文件
[notification] [notification]
@ -3694,7 +3694,7 @@ error.probable_bad_default_signature=警告虽然默认密钥拥有此ID
[units] [units]
unit=单元 unit=单元
error.no_unit_allowed_repo=您没有被允许访问此仓库的任何单元。 error.no_unit_allowed_repo=您没有被允许访问此仓库的任何单元。
error.unit_not_allowed=您没有权限访问此仓库单元 error.unit_not_allowed=您没有权限访问此仓库单元
[packages] [packages]
title=软件包 title=软件包
@ -3818,7 +3818,7 @@ settings.delete.error=删除软件包失败。
owner.settings.cargo.title=Cargo 注册中心索引 owner.settings.cargo.title=Cargo 注册中心索引
owner.settings.cargo.initialize=初始化索引 owner.settings.cargo.initialize=初始化索引
owner.settings.cargo.initialize.description=使用 Cargo 注册中心时需要一个特殊索引的 Git 仓库。使用此选项将(重新)创建仓库并自动配置它。 owner.settings.cargo.initialize.description=使用 Cargo 注册中心时需要一个特殊索引的 Git 仓库。使用此选项将(重新)创建仓库并自动配置它。
owner.settings.cargo.initialize.error=初始化Cargo索引失败 %v owner.settings.cargo.initialize.error=初始化Cargo索引失败%v
owner.settings.cargo.initialize.success=Cargo索引已经成功创建。 owner.settings.cargo.initialize.success=Cargo索引已经成功创建。
owner.settings.cargo.rebuild=重建索引 owner.settings.cargo.rebuild=重建索引
owner.settings.cargo.rebuild.description=如果索引与存储的 Cargo 包不同步,重建可能会有用。 owner.settings.cargo.rebuild.description=如果索引与存储的 Cargo 包不同步,重建可能会有用。
@ -3877,11 +3877,11 @@ alt.repository.multiple_groups = 此软件包在多个组中可用。
[secrets] [secrets]
secrets=密钥 secrets=密钥
description=Secrets 将被传给特定的 Actions其它情况将不能读取 description=机密将被传给特定的 Action其它情况将不能被读取。
none=还没有密钥。 none=还没有密钥。
creation=添加密钥 creation=添加密钥
creation.name_placeholder=不区分大小写,只能包含英文字母、数字或下划线,不能以 GITEA_ 或 GITHUB_ 开头 creation.name_placeholder=不区分大小写,只能包含英文字母、数字或下划线,不能以 GITEA_ 或 GITHUB_ 开头
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略 creation.value_placeholder=输入任何内容。开头和结尾的空格都会被省略。
creation.success=您的密钥 '%s' 添加成功。 creation.success=您的密钥 '%s' 添加成功。
creation.failed=添加密钥失败。 creation.failed=添加密钥失败。
deletion=删除密钥 deletion=删除密钥
@ -3916,7 +3916,7 @@ runners.description=组织描述
runners.labels=标签 runners.labels=标签
runners.last_online=上次在线时间 runners.last_online=上次在线时间
runners.runner_title=运行器 runners.runner_title=运行器
runners.task_list=最近在此runner上的任务 runners.task_list=最近在此运行器上的任务
runners.task_list.no_tasks=还没有任务。 runners.task_list.no_tasks=还没有任务。
runners.task_list.run=执行 runners.task_list.run=执行
runners.task_list.status=状态 runners.task_list.status=状态
@ -3932,7 +3932,7 @@ runners.delete_runner_success=运行器删除成功
runners.delete_runner_failed=删除运行器失败 runners.delete_runner_failed=删除运行器失败
runners.delete_runner_header=确认要删除此运行器 runners.delete_runner_header=确认要删除此运行器
runners.delete_runner_notice=如果一个任务正在运行在此运行器上,它将被终止并标记为失败。它可能会打断正在构建的工作流。 runners.delete_runner_notice=如果一个任务正在运行在此运行器上,它将被终止并标记为失败。它可能会打断正在构建的工作流。
runners.none=无可用的 Runner runners.none=无可用的运行器
runners.status.unspecified=未知 runners.status.unspecified=未知
runners.status.idle=空闲 runners.status.idle=空闲
runners.status.active=激活 runners.status.active=激活
@ -3945,8 +3945,8 @@ runs.all_workflows=所有工作流
runs.commit=提交 runs.commit=提交
runs.scheduled=已计划的 runs.scheduled=已计划的
runs.pushed_by=推送者 runs.pushed_by=推送者
runs.invalid_workflow_helper=工作流配置文件无效。请检查您的配置文件: %s runs.invalid_workflow_helper=工作流配置文件无效。请检查您的配置文件:%s
runs.no_matching_online_runner_helper=没有匹配标签的在线 runner %s runs.no_matching_online_runner_helper=没有匹配标签的在线运行器:%s
runs.actor=操作者 runs.actor=操作者
runs.status=状态 runs.status=状态
runs.actors_no_select=所有操作者 runs.actors_no_select=所有操作者
@ -3972,7 +3972,7 @@ variables.creation=添加变量
variables.none=目前还没有变量。 variables.none=目前还没有变量。
variables.deletion=删除变量 variables.deletion=删除变量
variables.deletion.description=删除变量是永久性的,无法撤消。继续吗? variables.deletion.description=删除变量是永久性的,无法撤消。继续吗?
variables.description=变量将被传给特定的 Actions,其它情况将不能读取 variables.description=变量将被传给特定的 Action,其它情况将不能读取
variables.id_not_exist=ID为 %d 的变量不存在。 variables.id_not_exist=ID为 %d 的变量不存在。
variables.edit=编辑变量 variables.edit=编辑变量
variables.deletion.failed=删除变量失败。 variables.deletion.failed=删除变量失败。

View file

@ -105,7 +105,7 @@ preview=預覽
loading=載入中… loading=載入中…
error=錯誤 error=錯誤
error404=您嘗試造訪的頁面 <strong>不存在</strong> 或 <strong>您沒有權限</strong> 檢視該頁面。 error404=您嘗試造訪的頁面<strong>不存在</strong>、<strong>已被移除</strong>,或<strong>您沒有權限</strong>檢視該頁面。
never=從來沒有 never=從來沒有
unknown=未知 unknown=未知
@ -207,6 +207,8 @@ table_modal.header = 新增表格
buttons.indent.tooltip = 使項目縮排一層 buttons.indent.tooltip = 使項目縮排一層
buttons.unindent.tooltip = 使項目取消縮排一層 buttons.unindent.tooltip = 使項目取消縮排一層
link_modal.header = 新增連結
[filter] [filter]
string.asc=A - Z string.asc=A - Z
string.desc=Z - A string.desc=Z - A
@ -1098,7 +1100,7 @@ issue_labels=標籤
issue_labels_helper=選擇標籤集 issue_labels_helper=選擇標籤集
license=授權條款 license=授權條款
license_helper=選擇授權條款檔案 license_helper=選擇授權條款檔案
license_helper_desc=授權條款定義了他人使用您原始碼的允許和禁止事項。不確定哪個適用於您的專案?查看<a target="_blank" rel="noopener noreferrer" href="%s">選擇授權條款</a> license_helper_desc=授權條款定義了他人使用您原始碼的允許和禁止事項。不確定哪個適用於您的專案?查看<a target="_blank" rel="noopener noreferrer" href="%s">選擇授權條款</a>
readme=讀我檔案 readme=讀我檔案
readme_helper=選擇讀我檔案範本 readme_helper=選擇讀我檔案範本
readme_helper_desc=這是您能為專案撰寫完整描述的地方。 readme_helper_desc=這是您能為專案撰寫完整描述的地方。
@ -1204,7 +1206,7 @@ migrate.migrate_items_options=遷移其他項目需要存取符記
migrated_from=已從 <a href="%[1]s">%[2]s</a> 遷移 migrated_from=已從 <a href="%[1]s">%[2]s</a> 遷移
migrated_from_fake=已從 %[1]s 遷移 migrated_from_fake=已從 %[1]s 遷移
migrate.migrate=從 %s 遷移 migrate.migrate=從 %s 遷移
migrate.migrating=正在從 <b>%s</b> 遷移... migrate.migrating=正在從 <b>%s</b> 遷移
migrate.migrating_failed=從 <b>%s</b> 遷移失敗。 migrate.migrating_failed=從 <b>%s</b> 遷移失敗。
migrate.migrating_failed_no_addr=遷移失敗。 migrate.migrating_failed_no_addr=遷移失敗。
migrate.github.description=從 github.com 或 GitHub Enterprise 伺服器遷移資料。 migrate.github.description=從 github.com 或 GitHub Enterprise 伺服器遷移資料。
@ -2377,7 +2379,7 @@ settings.lfs_invalid_locking_path=無效的路徑: %s
settings.lfs_invalid_lock_directory=無法鎖定目錄: %s settings.lfs_invalid_lock_directory=無法鎖定目錄: %s
settings.lfs_lock_already_exists=鎖定已存在:%s settings.lfs_lock_already_exists=鎖定已存在:%s
settings.lfs_lock=鎖定 settings.lfs_lock=鎖定
settings.lfs_lock_path=要鎖定的檔案路徑... settings.lfs_lock_path=要鎖定的檔案路徑
settings.lfs_locks_no_locks=沒有鎖定 settings.lfs_locks_no_locks=沒有鎖定
settings.lfs_lock_file_no_exist=已鎖定的檔案不存在於預設分支 settings.lfs_lock_file_no_exist=已鎖定的檔案不存在於預設分支
settings.lfs_force_unlock=強制解鎖 settings.lfs_force_unlock=強制解鎖
@ -3983,7 +3985,7 @@ commit_kind = 搜尋提交…
code_search_by_git_grep = 目前搜尋結果由「git grep」提供。如果網站管理員啟用程式碼索引可能會有更好的結果。 code_search_by_git_grep = 目前搜尋結果由「git grep」提供。如果網站管理員啟用程式碼索引可能會有更好的結果。
exact = 精確 exact = 精確
milestone_kind = 搜尋里程碑... milestone_kind = 搜尋里程碑...
issue_kind = 搜尋問題... issue_kind = 搜尋問題
exact_tooltip = 只包含與搜尋詞完全相符的結合 exact_tooltip = 只包含與搜尋詞完全相符的結合
pull_kind = 搜尋拉取… pull_kind = 搜尋拉取…
regexp = 正規表示式 regexp = 正規表示式

View file

@ -1,12 +1,15 @@
{ {
"repo.pulls.merged_title_desc": "yhdistetty %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code> %[4]s", "repo.pulls.merged_title_desc": "yhdistetty %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "haluaa yhdistää %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code id=\"%[4]s\">%[3]s</code>", "repo.pulls.title_desc": "haluaa yhdistää %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "Etsi merkkipaaluja...", "search.milestone_kind": "Etsi merkkipaaluja",
"home.welcome.no_activity": "Ei toimintaa", "home.welcome.no_activity": "Ei toimintaa",
"incorrect_root_url": "Tämä Forgejo-instanssi on määritetty toimimaan osoitteessa \"%s\". Tarkastelet tällä hetkellä Forgejoa eri URL-osoitteen kautta, mikä saattaa aiheuttaa sovelluksen osien toimimattomuutta. Virallinen URL-osoite on Forgejo-ylläpitäjien hallinnoima ROOT_URL-asetus app.ini -tiedostossa.", "incorrect_root_url": "Tämä Forgejo-instanssi on määritetty toimimaan osoitteessa \"%s\". Tarkastelet tällä hetkellä Forgejoa eri URL-osoitteen kautta, mikä saattaa aiheuttaa sovelluksen osien toimimattomuutta. Virallinen URL-osoite on Forgejo-ylläpitäjien hallinnoima ROOT_URL-asetus app.ini -tiedostossa.",
"themes.names.forgejo-auto": "Forgejo (käyttöjärjestelmän määrittelemä teema)", "themes.names.forgejo-auto": "Forgejo (käyttöjärjestelmän määrittelemä teema)",
"home.welcome.activity_hint": "Syötteelläsi ei ole vielä mitään. Toimintasi ja toiminta repositorioissa joita seuraat ilmaantuu tälle sivulle.", "home.welcome.activity_hint": "Syötteelläsi ei ole vielä mitään. Toimintasi ja toiminta repositorioissa joita seuraat ilmaantuu tälle sivulle.",
"home.explore_repos": "Tutki repositorioita", "home.explore_repos": "Tutki repositorioita",
"home.explore_users": "Tutki käyttäjiä", "home.explore_users": "Tutki käyttäjiä",
"home.explore_orgs": "Tutki organisaatioita" "home.explore_orgs": "Tutki organisaatioita",
"themes.names.forgejo-light": "Forgejo, vaalea",
"themes.names.forgejo-dark": "Forgejo, tumma",
"install.invalid_lfs_path": "LFS juurta ei voitu luoda polkuun: %[1]s"
} }

View file

@ -1,8 +1,9 @@
{ {
"repo.pulls.merged_title_desc": { "repo.pulls.merged_title_desc": {
"other": "님이 <code>%[2]s</code> 에서 <code>%[3]s</code> 로 %[1]d 커밋을 %[4]s 병합함" "other": "님이 <code>%[2]s</code> 에서 <code>%[3]s</code> 로 %[1]d 커밋을 %[4]s 병합함"
}, },
"repo.pulls.title_desc": { "repo.pulls.title_desc": {
"other": "<code>%[2]s</code> 에서 <code id=\"%[4]s\">%[3]s</code> 로 %[1]d개의 커밋들을 병합하려함" "other": "<code>%[2]s</code> 에서 <code id=\"%[4]s\">%[3]s</code> 로 %[1]d개의 커밋들을 병합하려함"
} },
"home.welcome.no_activity": "활동 없음"
} }

View file

@ -1,5 +1,6 @@
{ {
"repo.pulls.merged_title_desc": "scala %[1]d commity/ów z <code>%[2]s</code> do <code>%[3]s</code> %[4]s", "repo.pulls.merged_title_desc": "scala %[1]d commity/ów z <code>%[2]s</code> do <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "chce scalić %[1]d commity/ów z <code>%[2]s</code> do <code id=\"%[4]s\">%[3]s</code>", "repo.pulls.title_desc": "chce scalić %[1]d commity/ów z <code>%[2]s</code> do <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "Wyszukaj kamienie milowe..." "search.milestone_kind": "Wyszukaj kamienie milowe...",
"incorrect_root_url": "Ta instancja Forgejo jest skonfigurowana do korzystania z \"%s\". Obecnie oglądasz Forgejo za pomocą innego URL, co może powodować błędne działanie tej aplikacji. URL kanoniczny jest kontrolowany przez administratorów Forgejo za pomocą ROOT_URL w app.ini."
} }

View file

@ -18,5 +18,6 @@
"incorrect_root_url": "Esta instância do Forgejo está configurada para o endereço \"%s\". Você está atualmente vendo o Forgejo através de uma URL diferente, o que pode causar erros em algumas partes da aplicação. A URL oficial é controlada pela administração do Forgejo através da configuração ROOT_URL no arquivo app.ini.", "incorrect_root_url": "Esta instância do Forgejo está configurada para o endereço \"%s\". Você está atualmente vendo o Forgejo através de uma URL diferente, o que pode causar erros em algumas partes da aplicação. A URL oficial é controlada pela administração do Forgejo através da configuração ROOT_URL no arquivo app.ini.",
"themes.names.forgejo-auto": "Forgejo (usar o tema do sistema)", "themes.names.forgejo-auto": "Forgejo (usar o tema do sistema)",
"themes.names.forgejo-light": "Forgejo claro", "themes.names.forgejo-light": "Forgejo claro",
"themes.names.forgejo-dark": "Forgejo escuro" "themes.names.forgejo-dark": "Forgejo escuro",
"install.invalid_lfs_path": "Não foi possível criar um root LFS no caminho especificado: %[1]s"
} }

View file

@ -18,5 +18,6 @@
"incorrect_root_url": "Esta instância do Forgejo está configurada para ser servida em “%s”. Atualmente, está a visualizar o Forgejo através de um URL diferente, o que pode causar a quebra de partes da aplicação. O URL official é controlado pelos administradores do Forgejo através da configuração ROOT_URL no ficheiro app.ini.", "incorrect_root_url": "Esta instância do Forgejo está configurada para ser servida em “%s”. Atualmente, está a visualizar o Forgejo através de um URL diferente, o que pode causar a quebra de partes da aplicação. O URL official é controlado pelos administradores do Forgejo através da configuração ROOT_URL no ficheiro app.ini.",
"themes.names.forgejo-auto": "Forgejo (segue o tema do sistema)", "themes.names.forgejo-auto": "Forgejo (segue o tema do sistema)",
"themes.names.forgejo-light": "Forgejo claro", "themes.names.forgejo-light": "Forgejo claro",
"themes.names.forgejo-dark": "Forgejo escuro" "themes.names.forgejo-dark": "Forgejo escuro",
"install.invalid_lfs_path": "Não foi possível criar a raiz LFS no caminho especificado: %[1]s"
} }

View file

@ -1 +1,13 @@
{} {
"home.welcome.no_activity": "Žiadna aktivita",
"home.welcome.activity_hint": "Vo vašom kanáli zatiaľ nič nie je. Tu sa budú zobrazovať vaše akcie a aktivity z repozitárov, ktoré sledujete.",
"home.explore_repos": "Preskúmajte repozitáre",
"home.explore_users": "Preskúmajte používateľov",
"home.explore_orgs": "Preskúmajte organizácie",
"search.milestone_kind": "Hľadať v míľnikoch…",
"incorrect_root_url": "Táto inštancia Forgejo je nakonfigurovaná tak, aby bola obsluhovaná na „%s“. Momentálne zobrazujete Forgejo prostredníctvom inej adresy URL, čo môže spôsobiť poruchu niektorých častí aplikácie. Kanonickú adresu URL kontrolujú správcovia aplikácie Forgejo prostredníctvom nastavenia ROOT_URL v súbore app.ini.",
"themes.names.forgejo-auto": "Forgejo (sleduj systémovú tému)",
"themes.names.forgejo-light": "Forgejo svetlé",
"themes.names.forgejo-dark": "Forgejo tmavé",
"install.invalid_lfs_path": "Nie je možné vytvoriť koreňový systém LFS na zadanej ceste: %[1]s"
}

View file

@ -1,5 +1,5 @@
{ {
"repo.pulls.merged_title_desc": "將 %[1]d 次提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code> %[4]s", "repo.pulls.merged_title_desc": "將 %[1]d 次提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "請求將 %[1]d 次程式碼提交從 <code>%[2]s</code> 合併至 <code id=\"%[4]s\">%[3]s</code>", "repo.pulls.title_desc": "請求將 %[1]d 次程式碼提交從 <code>%[2]s</code> 合併至 <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "搜尋里程碑..." "search.milestone_kind": "搜尋里程碑"
} }

View file

@ -300,8 +300,14 @@ func ServCommand(ctx *context.PrivateContext) {
return return
} }
} else { } else {
// Because of the special ref "refs/for" we will need to delay write permission check // We don't know yet which references the Git client wants to write to,
if git.SupportProcReceive && unitType == unit.TypeCode { // but for AGit flow we have to degrade this check to a read permission.
// So if we support proc-receive (needed for AGit flow) and the unit type
// is code and we know the Git client wants to write to us, then degrade
// the permission check to read. The pre-receive hook will do another
// permission check which ensure for non AGit flow references the write
// permission is checked.
if git.SupportProcReceive && unitType == unit.TypeCode && ctx.FormString("verb") == "git-receive-pack" {
mode = perm.AccessModeRead mode = perm.AccessModeRead
} }

View file

@ -5,7 +5,9 @@ package admin
import ( import (
"archive/zip" "archive/zip"
"bytes"
"fmt" "fmt"
"io"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"runtime/trace" "runtime/trace"
@ -45,14 +47,9 @@ func MonitorDiagnosis(ctx *context.Context) {
_, _ = f.Write([]byte(err.Error())) _, _ = f.Write([]byte(err.Error()))
} }
f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "trace.dat", Method: zip.Deflate, Modified: time.Now()}) traceBuf := &bytes.Buffer{}
if err != nil { if err := trace.Start(traceBuf); err != nil {
ctx.ServerError("Failed to create zip file", err) _, _ = traceBuf.Write([]byte(err.Error()))
return
}
if err := trace.Start(f); err != nil {
_, _ = f.Write([]byte(err.Error()))
} }
select { select {
@ -62,6 +59,17 @@ func MonitorDiagnosis(ctx *context.Context) {
pprof.StopCPUProfile() pprof.StopCPUProfile()
trace.Stop() trace.Stop()
f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "trace.dat", Method: zip.Deflate, Modified: time.Now()})
if err != nil {
ctx.ServerError("Failed to create zip file", err)
return
}
if _, err := io.Copy(f, traceBuf); err != nil {
ctx.ServerError("Failed to create zip file", err)
return
}
f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "goroutine-after.txt", Method: zip.Deflate, Modified: time.Now()}) f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "goroutine-after.txt", Method: zip.Deflate, Modified: time.Now()})
if err != nil { if err != nil {
ctx.ServerError("Failed to create zip file", err) ctx.ServerError("Failed to create zip file", err)

View file

@ -249,7 +249,7 @@ func prepareUserInfo(ctx *context.Context) *user_model.User {
} }
ctx.Data["Sources"] = sources ctx.Data["Sources"] = sources
hasTOTP, err := auth.HasTwoFactorByUID(ctx, u.ID) hasTOTP, err := auth.HasTOTPByUID(ctx, u.ID)
if err != nil { if err != nil {
ctx.ServerError("auth.HasTwoFactorByUID", err) ctx.ServerError("auth.HasTwoFactorByUID", err)
return nil return nil

View file

@ -242,7 +242,7 @@ func SignInPost(ctx *context.Context) {
// If this user is enrolled in 2FA TOTP, we can't sign the user in just yet. // If this user is enrolled in 2FA TOTP, we can't sign the user in just yet.
// Instead, redirect them to the 2FA authentication page. // Instead, redirect them to the 2FA authentication page.
hasTOTPtwofa, err := auth.HasTwoFactorByUID(ctx, u.ID) hasTOTPtwofa, err := auth.HasTOTPByUID(ctx, u.ID)
if err != nil { if err != nil {
ctx.ServerError("UserSignIn", err) ctx.ServerError("UserSignIn", err)
return return

View file

@ -155,15 +155,14 @@ func linkAccount(ctx *context.Context, u *user_model.User, gothUser goth.User, r
// If this user is enrolled in 2FA, we can't sign the user in just yet. // If this user is enrolled in 2FA, we can't sign the user in just yet.
// Instead, redirect them to the 2FA authentication page. // Instead, redirect them to the 2FA authentication page.
// We deliberately ignore the skip local 2fa setting here because we are linking to a previous user here // We deliberately ignore the skip local 2fa setting here because we are linking to a previous user here
_, err := auth.GetTwoFactorByUID(ctx, u.ID) hasTwoFactor, err := auth.HasTwoFactorByUID(ctx, u.ID)
if err != nil { if err != nil {
if !auth.IsErrTwoFactorNotEnrolled(err) { ctx.ServerError("UserLinkAccount", err)
ctx.ServerError("UserLinkAccount", err) return
return }
}
err = externalaccount.LinkAccountToUser(ctx, u, gothUser) if !hasTwoFactor {
if err != nil { if err := externalaccount.LinkAccountToUser(ctx, u, gothUser); err != nil {
ctx.ServerError("UserLinkAccount", err) ctx.ServerError("UserLinkAccount", err)
return return
} }

View file

@ -1079,7 +1079,7 @@ func SignInOAuthCallback(ctx *context.Context) {
isAdmin, isRestricted := getUserAdminAndRestrictedFromGroupClaims(source, &gothUser) isAdmin, isRestricted := getUserAdminAndRestrictedFromGroupClaims(source, &gothUser)
u.IsAdmin = isAdmin.ValueOrDefault(false) u.IsAdmin = isAdmin.ValueOrDefault(false)
u.IsRestricted = isRestricted.ValueOrDefault(false) u.IsRestricted = isRestricted.ValueOrDefault(setting.Service.DefaultUserIsRestricted)
if !createAndHandleCreatedUser(ctx, base.TplName(""), nil, u, overwriteDefault, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) { if !createAndHandleCreatedUser(ctx, base.TplName(""), nil, u, overwriteDefault, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) {
// error already handled // error already handled
@ -1243,12 +1243,11 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
needs2FA := false needs2FA := false
if !source.Cfg.(*oauth2.Source).SkipLocalTwoFA { if !source.Cfg.(*oauth2.Source).SkipLocalTwoFA {
_, err := auth.GetTwoFactorByUID(ctx, u.ID) needs2FA, err = auth.HasTwoFactorByUID(ctx, u.ID)
if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { if err != nil {
ctx.ServerError("UserSignIn", err) ctx.ServerError("UserSignIn", err)
return return
} }
needs2FA = err == nil
} }
oauth2Source := source.Cfg.(*oauth2.Source) oauth2Source := source.Cfg.(*oauth2.Source)

View file

@ -36,7 +36,7 @@ func WebAuthn(ctx *context.Context) {
return return
} }
hasTwoFactor, err := auth.HasTwoFactorByUID(ctx, ctx.Session.Get("twofaUid").(int64)) hasTwoFactor, err := auth.HasTOTPByUID(ctx, ctx.Session.Get("twofaUid").(int64))
if err != nil { if err != nil {
ctx.ServerError("HasTwoFactorByUID", err) ctx.ServerError("HasTwoFactorByUID", err)
return return

View file

@ -0,0 +1,7 @@
-
id: 1004
uuid: "fb857e63-c0ce-4571-a6c9-fde26c128073"
name: "Global runner"
owner_id: 0
repo_id: 0
deleted: 0

View file

@ -0,0 +1,160 @@
-
id: 1
runner_id: 1004
token_hash: a1
-
id: 2
runner_id: 1004
token_hash: a2
-
id: 3
runner_id: 1004
token_hash: a3
-
id: 4
runner_id: 1004
token_hash: a4
-
id: 5
runner_id: 1004
token_hash: a5
-
id: 6
runner_id: 1004
token_hash: a6
-
id: 7
runner_id: 1004
token_hash: a7
-
id: 8
runner_id: 1004
token_hash: a8
-
id: 9
runner_id: 1004
token_hash: a9
-
id: 10
runner_id: 1004
token_hash: a10
-
id: 11
runner_id: 1004
token_hash: a11
-
id: 12
runner_id: 1004
token_hash: a12
-
id: 13
runner_id: 1004
token_hash: a13
-
id: 14
runner_id: 1004
token_hash: a14
-
id: 15
runner_id: 1004
token_hash: a15
-
id: 16
runner_id: 1004
token_hash: a16
-
id: 17
runner_id: 1004
token_hash: a17
-
id: 18
runner_id: 1004
token_hash: a18
-
id: 19
runner_id: 1004
token_hash: a19
-
id: 20
runner_id: 1004
token_hash: a20
-
id: 21
runner_id: 1004
token_hash: a21
-
id: 22
runner_id: 1004
token_hash: a22
-
id: 23
runner_id: 1004
token_hash: a23
-
id: 24
runner_id: 1004
token_hash: a24
-
id: 25
runner_id: 1004
token_hash: a25
-
id: 26
runner_id: 1004
token_hash: a26
-
id: 27
runner_id: 1004
token_hash: a27
-
id: 28
runner_id: 1004
token_hash: a28
-
id: 29
runner_id: 1004
token_hash: a29
-
id: 30
runner_id: 1004
token_hash: a30
-
id: 31
runner_id: 1004
token_hash: a31
-
id: 32
runner_id: 1004
token_hash: a32
-
id: 33
runner_id: 1004
token_hash: a33
-
id: 34
runner_id: 1004
token_hash: a34
-
id: 35
runner_id: 1004
token_hash: a35
-
id: 36
runner_id: 1004
token_hash: a36
-
id: 37
runner_id: 1004
token_hash: a37
-
id: 38
runner_id: 1004
token_hash: a38
-
id: 39
runner_id: 1004
token_hash: a39
-
id: 40
runner_id: 1004
token_hash: a40

View file

@ -0,0 +1,17 @@
// Copyright 2025 The Forgejo Authors.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"testing"
"forgejo.org/models/unittest"
_ "forgejo.org/models"
_ "forgejo.org/models/forgefed"
)
func TestMain(m *testing.M) {
unittest.MainTest(m)
}

View file

@ -79,7 +79,6 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int
Page: page, Page: page,
PageSize: 30, PageSize: 30,
}, },
Status: []actions_model.Status{actions_model.StatusUnknown}, // Unknown means all
RunnerID: runner.ID, RunnerID: runner.ID,
} }

View file

@ -0,0 +1,47 @@
// Copyright 2025 The Forgejo Authors.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"net/http"
"testing"
actions_model "forgejo.org/models/actions"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/services/contexttest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRunnerDetails(t *testing.T) {
defer unittest.OverrideFixtures("routers/web/shared/actions/fixtures/TestRunnerDetails")()
require.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
runner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1004})
t.Run("permission denied", func(t *testing.T) {
ctx, resp := contexttest.MockContext(t, "/admin/actions/runners")
RunnerDetails(ctx, 1, runner.ID, user.ID, 0)
assert.Equal(t, http.StatusNotFound, resp.Code)
})
t.Run("first page", func(t *testing.T) {
ctx, resp := contexttest.MockContext(t, "/admin/actions/runners")
page := 1
RunnerDetails(ctx, page, runner.ID, 0, 0)
require.Equal(t, http.StatusOK, resp.Code)
assert.Len(t, ctx.GetData()["Tasks"], 30)
})
t.Run("second and last page", func(t *testing.T) {
ctx, resp := contexttest.MockContext(t, "/admin/actions/runners")
page := 2
RunnerDetails(ctx, page, runner.ID, 0, 0)
require.Equal(t, http.StatusOK, resp.Code)
assert.Len(t, ctx.GetData()["Tasks"], 10)
})
}

View file

@ -55,7 +55,7 @@ func DeleteAccountLink(ctx *context.Context) {
} }
func loadSecurityData(ctx *context.Context) { func loadSecurityData(ctx *context.Context) {
enrolled, err := auth_model.HasTwoFactorByUID(ctx, ctx.Doer.ID) enrolled, err := auth_model.HasTOTPByUID(ctx, ctx.Doer.ID)
if err != nil { if err != nil {
ctx.ServerError("SettingsTwoFactor", err) ctx.ServerError("SettingsTwoFactor", err)
return return

View file

@ -689,7 +689,7 @@ func SendRemovedSecurityKey(ctx context.Context, u *user_model.User, securityKey
if err != nil { if err != nil {
return err return err
} }
hasTOTP, err := auth_model.HasTwoFactorByUID(ctx, u.ID) hasTOTP, err := auth_model.HasTOTPByUID(ctx, u.ID)
if err != nil { if err != nil {
return err return err
} }

View file

@ -98,7 +98,7 @@ func getRemoteUserToPromote(ctx context.Context, source *auth_model.Source, logi
return nil, NewReason(log.ERROR, ReasonErrorLoginName, "getUserByLoginName('%s') %v", loginName, err), err return nil, NewReason(log.ERROR, ReasonErrorLoginName, "getUserByLoginName('%s') %v", loginName, err), err
} }
if len(users) == 0 { if len(users) == 0 {
return nil, NewReason(log.ERROR, ReasonLoginNameNotExists, "no user with LoginType UserTypeRemoteUser and LoginName '%s'", loginName), nil return nil, NewReason(log.DEBUG, ReasonLoginNameNotExists, "no user with LoginType UserTypeRemoteUser and LoginName '%s'", loginName), nil
} }
reason := ReasonNoSource reason := ReasonNoSource

View file

@ -67,13 +67,7 @@ func TestDeleteUser(t *testing.T) {
} }
func TestPurgeUser(t *testing.T) { func TestPurgeUser(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("services/user/TestPurgeUser")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"services/user/TestPurgeUser/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
defer test.MockVariableValue(&setting.SSH.RootPath, t.TempDir())() defer test.MockVariableValue(&setting.SSH.RootPath, t.TempDir())()
defer test.MockVariableValue(&setting.SSH.CreateAuthorizedKeysFile, true)() defer test.MockVariableValue(&setting.SSH.CreateAuthorizedKeysFile, true)()

View file

@ -4,7 +4,6 @@
package webhook package webhook
import ( import (
"path/filepath"
"testing" "testing"
"forgejo.org/models/db" "forgejo.org/models/db"
@ -56,13 +55,7 @@ func pushCommits() *repository.PushCommits {
} }
func TestSyncPushCommits(t *testing.T) { func TestSyncPushCommits(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("services/webhook/TestPushCommits")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"services/webhook/TestPushCommits"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@ -95,13 +88,7 @@ func TestSyncPushCommits(t *testing.T) {
} }
func TestPushCommits(t *testing.T) { func TestPushCommits(t *testing.T) {
defer unittest.OverrideFixtures( defer unittest.OverrideFixtures("services/webhook/TestPushCommits")()
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"services/webhook/TestPushCommits"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

View file

@ -2,11 +2,11 @@
<div class="tw-flex tw-justify-between tw-mb-4"> <div class="tw-flex tw-justify-between tw-mb-4">
<div class="switch list-header-toggle"> <div class="switch list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?state=open&q={{$.Keyword}}"> <a class="item{{if not .IsShowClosed}} active{{end}}" href="?state=open&q={{$.Keyword}}">
{{svg "octicon-project-symlink" 16 "tw-mr-2"}} {{svg "octicon-project-symlink" 16}}
{{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a> </a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?state=closed&q={{$.Keyword}}"> <a class="item{{if .IsShowClosed}} active{{end}}" href="?state=closed&q={{$.Keyword}}">
{{svg "octicon-check" 16 "tw-mr-2"}} {{svg "octicon-check" 16}}
{{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a> </a>
</div> </div>

View file

@ -77,8 +77,10 @@
{{else}} {{else}}
{{if eq $type "tag"}} {{if eq $type "tag"}}
{{svg "octicon-tag"}} {{svg "octicon-tag"}}
{{else}} {{else if eq $type "branch"}}
{{svg "octicon-git-branch"}} {{svg "octicon-git-branch"}}
{{else}}
{{svg "octicon-git-commit"}}
{{end}} {{end}}
<strong ref="dropdownRefName" class="tw-ml-2 tw-inline-block gt-ellipsis">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong> <strong ref="dropdownRefName" class="tw-ml-2 tw-inline-block gt-ellipsis">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong>
{{end}} {{end}}

View file

@ -48,11 +48,11 @@
</div> </div>
<div class="switch"> <div class="switch">
<button id="flow-color-monochrome" class="{{if eq .Mode "monochrome"}}active {{end}}item" title="{{ctx.Locale.Tr "repo.commit_graph.monochrome"}}"> <button id="flow-color-monochrome" class="{{if eq .Mode "monochrome"}}active {{end}}item" title="{{ctx.Locale.Tr "repo.commit_graph.monochrome"}}">
{{svg "material-invert-colors" 16 "tw-mr-1"}} {{svg "material-invert-colors" 16}}
{{ctx.Locale.Tr "repo.commit_graph.monochrome"}} {{ctx.Locale.Tr "repo.commit_graph.monochrome"}}
</button> </button>
<button id="flow-color-colored" class="{{if ne .Mode "monochrome"}}active {{end}}item" title="{{ctx.Locale.Tr "repo.commit_graph.color"}}"> <button id="flow-color-colored" class="{{if ne .Mode "monochrome"}}active {{end}}item" title="{{ctx.Locale.Tr "repo.commit_graph.color"}}">
{{svg "material-palette" 16 "tw-mr-1"}} {{svg "material-palette" 16}}
{{ctx.Locale.Tr "repo.commit_graph.color"}} {{ctx.Locale.Tr "repo.commit_graph.color"}}
</button> </button>
</div> </div>

View file

@ -1,21 +1,21 @@
<div class="switch"> <div class="switch">
<a class="{{if eq .State "open"}}active {{end}}item" href="{{.OpenLink}}" data-test-name="open-issue-count"> <a class="{{if eq .State "open"}}active {{end}}item" href="{{.OpenLink}}" data-test-name="open-issue-count">
{{if .PageIsMilestones}} {{if .PageIsMilestones}}
{{svg "octicon-milestone" 16 "tw-mr-2"}} {{svg "octicon-milestone" 16}}
{{else if .PageIsPullList}} {{else if .PageIsPullList}}
{{svg "octicon-git-pull-request" 16 "tw-mr-2"}} {{svg "octicon-git-pull-request" 16}}
{{else}} {{else}}
{{svg "octicon-issue-opened" 16 "tw-mr-2"}} {{svg "octicon-issue-opened" 16}}
{{end}} {{end}}
{{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a> </a>
<a class="{{if eq .State "closed"}}active {{end}}item" href="{{.ClosedLink}}" data-test-name="closed-issue-count"> <a class="{{if eq .State "closed"}}active {{end}}item" href="{{.ClosedLink}}" data-test-name="closed-issue-count">
{{svg "octicon-issue-closed" 16 "tw-mr-2"}} {{svg "octicon-issue-closed" 16}}
{{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a> </a>
{{if not .PageIsMilestones}} {{if not .PageIsMilestones}}
<a class="{{if eq .State "all"}}active {{end}}item" href="{{.AllStatesLink}}" data-test-name="all-issue-count"> <a class="{{if eq .State "all"}}active {{end}}item" href="{{.AllStatesLink}}" data-test-name="all-issue-count">
{{svg "octicon-eye" 16 "tw-mr-2"}} {{svg "octicon-eye" 16}}
{{ctx.Locale.PrettyNumber (.AllCount)}}&nbsp;{{ctx.Locale.Tr "repo.issues.all_title"}} {{ctx.Locale.PrettyNumber (.AllCount)}}&nbsp;{{ctx.Locale.Tr "repo.issues.all_title"}}
</a> </a>
{{end}} {{end}}

View file

@ -526,7 +526,7 @@
{{else if eq .Type 27}} {{else if eq .Type 27}}
{{if or .AddedRequestReview .RemovedRequestReview}} {{if or .AddedRequestReview .RemovedRequestReview}}
<div class="timeline-item event" id="{{.HashTag}}"> <div class="timeline-item event" id="{{.HashTag}}">
<span class="badge">{{svg "octicon-tag"}}</span> <span class="badge">{{svg "octicon-eye"}}</span>
{{template "shared/user/avatarlink" dict "user" .Poster}} {{template "shared/user/avatarlink" dict "user" .Poster}}
<span class="text grey muted-links"> <span class="text grey muted-links">
{{if and (eq (len .RemovedRequestReview) 1) (eq (len .AddedRequestReview) 0) (eq ((index .RemovedRequestReview 0).ID) .PosterID) (eq ((index .RemovedRequestReview 0).Type) "user")}} {{if and (eq (len .RemovedRequestReview) 1) (eq (len .AddedRequestReview) 0) (eq ((index .RemovedRequestReview 0).ID) .PosterID) (eq ((index .RemovedRequestReview 0).Type) "user")}}
@ -724,7 +724,7 @@
{{if or .AddedRequestReview .RemovedRequestReview}} {{if or .AddedRequestReview .RemovedRequestReview}}
<li> <li>
<span class="badge">{{svg "octicon-tag" 20}}</span> <span class="badge">{{svg "octicon-eye" 20}}</span>
<span class="text grey muted-links"> <span class="text grey muted-links">
{{if and (eq (len .RemovedRequestReview) 1) (eq (len .AddedRequestReview) 0) (eq ((index .RemovedRequestReview 0).ID) .PosterID) (eq ((index .RemovedRequestReview 0).Type) "user")}} {{if and (eq (len .RemovedRequestReview) 1) (eq (len .AddedRequestReview) 0) (eq ((index .RemovedRequestReview 0).ID) .PosterID) (eq ((index .RemovedRequestReview 0).Type) "user")}}

View file

@ -6,11 +6,11 @@
<div class="list-header"> <div class="list-header">
<div class="switch list-header-toggle"> <div class="switch list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&q={{$.Keyword}}"> <a class="item{{if not .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&q={{$.Keyword}}">
{{svg "octicon-issue-opened" 16 "tw-mr-2"}} {{svg "octicon-issue-opened" 16}}
{{ctx.Locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a> </a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&q={{$.Keyword}}"> <a class="item{{if .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&q={{$.Keyword}}">
{{svg "octicon-issue-closed" 16 "tw-mr-2"}} {{svg "octicon-issue-closed" 16}}
{{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a> </a>
</div> </div>

View file

@ -37,11 +37,11 @@
<div class="list-header"> <div class="list-header">
<div class="switch list-header-toggle"> <div class="switch list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}"> <a class="item{{if not .IsShowClosed}} active{{end}}" href="?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
{{svg "octicon-milestone" 16 "tw-mr-2"}} {{svg "octicon-milestone" 16}}
{{ctx.Locale.PrettyNumber .MilestoneStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .MilestoneStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a> </a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=closed&q={{$.Keyword}}"> <a class="item{{if .IsShowClosed}} active{{end}}" href="?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=closed&q={{$.Keyword}}">
{{svg "octicon-check" 16 "tw-mr-2"}} {{svg "octicon-check" 16}}
{{ctx.Locale.PrettyNumber .MilestoneStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .MilestoneStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a> </a>
</div> </div>

View file

@ -13,6 +13,7 @@ import (
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
user_model "forgejo.org/models/user" user_model "forgejo.org/models/user"
"forgejo.org/modules/git" "forgejo.org/modules/git"
"forgejo.org/modules/indexer/stats"
files_service "forgejo.org/services/repository/files" files_service "forgejo.org/services/repository/files"
"forgejo.org/tests" "forgejo.org/tests"
@ -36,6 +37,10 @@ func DeclareGitRepos(t *testing.T) func() {
Filename: "testfile", Filename: "testfile",
Versions: []string{"hello", "hallo", "hola", "native", "ubuntu-latest", "- runs-on: ubuntu-latest", "- runs-on: debian-latest"}, Versions: []string{"hello", "hallo", "hola", "native", "ubuntu-latest", "- runs-on: ubuntu-latest", "- runs-on: debian-latest"},
}}), }}),
newRepo(t, 2, "language-stats-test", []FileChanges{{
Filename: "main.rs",
Versions: []string{"fn main() {", "println!(\"Hello World!\");", "}"},
}}),
newRepo(t, 2, "mentions-highlighted", []FileChanges{ newRepo(t, 2, "mentions-highlighted", []FileChanges{
{ {
Filename: "history1.md", Filename: "history1.md",
@ -105,5 +110,8 @@ func newRepo(t *testing.T, userID int64, repoName string, fileChanges []FileChan
} }
} }
err := stats.UpdateRepoIndexer(somerepo)
require.NoError(t, err)
return cleanupFunc return cleanupFunc
} }

View file

@ -0,0 +1,15 @@
// @watch start
// template/base/paginate.tmpl
// services/context/pagination.go
// @watch end
import {expect} from '@playwright/test';
import {test} from './utils_e2e.ts';
import {accessibilityCheck} from './shared/accessibility.ts';
test('Pagination a11y', async ({page}) => {
await page.goto('/explore/repos');
await expect(page.locator('.pagination')).toBeVisible();
await accessibilityCheck({page}, ['.pagination'], [], []);
});

View file

@ -1,19 +0,0 @@
// @watch start
// web_src/js/features/common-global.js
// web_src/css/repo.css
// @watch end
import {expect} from '@playwright/test';
import {save_visual, test} from './utils_e2e.ts';
test('Language stats bar', async ({page}) => {
const response = await page.goto('/user2/repo1');
expect(response?.status()).toBe(200);
await expect(page.locator('#language-stats-legend')).toBeVisible();
await save_visual(page);
await page.click('#language-stats-bar');
await expect(page.locator('#language-stats-legend')).toBeHidden();
await save_visual(page);
});

View file

@ -0,0 +1,35 @@
// @watch start
// web_src/js/components/RepoBranchTagSelector.vue
// web_src/js/features/common-global.js
// web_src/css/repo.css
// @watch end
import {expect} from '@playwright/test';
import {save_visual, test} from './utils_e2e.ts';
test('Language stats bar', async ({page}) => {
const response = await page.goto('/user2/language-stats-test');
expect(response?.status()).toBe(200);
await expect(page.locator('#language-stats-legend')).toBeHidden();
await page.click('#language-stats-bar');
await expect(page.locator('#language-stats-legend')).toBeVisible();
await save_visual(page);
await page.click('#language-stats-bar');
await expect(page.locator('#language-stats-legend')).toBeHidden();
await save_visual(page);
});
test('Branch selector commit icon', async ({page}) => {
const response = await page.goto('/user2/repo1');
expect(response?.status()).toBe(200);
await expect(page.locator('.branch-dropdown-button svg.octicon-git-branch')).toBeVisible();
await expect(page.locator('.branch-dropdown-button')).toHaveText('master');
await page.goto('/user2/repo1/src/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d');
await expect(page.locator('.branch-dropdown-button svg.octicon-git-commit')).toBeVisible();
await expect(page.locator('.branch-dropdown-button')).toHaveText('65f1bf27bc');
});

View file

@ -19,7 +19,7 @@ import (
) )
func TestActionVariablesModification(t *testing.T) { func TestActionVariablesModification(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestActionVariablesModification")() defer unittest.OverrideFixtures("tests/integration/fixtures/TestActionVariablesModification")()
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

View file

@ -98,7 +98,7 @@ func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
} }
func TestAdminDeleteUser(t *testing.T) { func TestAdminDeleteUser(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestAdminDeleteUser/")() defer unittest.OverrideFixtures("tests/integration/fixtures/TestAdminDeleteUser")()
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1") session := loginUser(t, "user1")

View file

@ -167,7 +167,7 @@ func TestBlockUserFromOrganization(t *testing.T) {
// and as a blocked user and are handled cleanly after the blocking has taken // and as a blocked user and are handled cleanly after the blocking has taken
// place. // place.
func TestBlockActions(t *testing.T) { func TestBlockActions(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestBlockActions/")() defer unittest.OverrideFixtures("tests/integration/fixtures/TestBlockActions")()
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@ -438,7 +438,7 @@ func TestBlockActions(t *testing.T) {
} }
func TestBlockedNotification(t *testing.T) { func TestBlockedNotification(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestBlockedNotifications")() defer unittest.OverrideFixtures("tests/integration/fixtures/TestBlockedNotifications")()
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

View file

@ -19,7 +19,7 @@ import (
// As it is not possible to do actions as system users, the tests are done using fixtures. // As it is not possible to do actions as system users, the tests are done using fixtures.
func TestSystemCommentRoles(t *testing.T) { func TestSystemCommentRoles(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestSystemCommentRoles/")() defer unittest.OverrideFixtures("tests/integration/fixtures/TestSystemCommentRoles")()
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})

Some files were not shown because too many files have changed in this diff Show more