Compare commits

..

No commits in common. "f7b3ac4930cf0ef6d1e5fea36fa3beb242dbb149" and "cbeb28a0dd0c6462cb8c25237339ffac6d6bceda" have entirely different histories.

185 changed files with 2171 additions and 5796 deletions

View file

@ -87,24 +87,12 @@ forgejo.org/modules/eventsource
Event.String
forgejo.org/modules/forgefed
NewForgeFollowFromAp
NewForgeFollow
ForgeFollow.MarshalJSON
ForgeFollow.UnmarshalJSON
ForgeFollow.Validate
NewForgeUndoLike
ForgeUndoLike.UnmarshalJSON
ForgeUndoLike.Validate
NewForgeUserActivityFromAp
NewForgeUserActivity
ForgeUserActivity.Validate
NewPersonIDFromModel
GetItemByType
JSONUnmarshalerFn
NotEmpty
NewForgeUserActivityNoteFromAp
newNote
ForgeUserActivityNote.Validate
ToRepository
OnRepository

View file

@ -28,7 +28,7 @@ jobs:
runs-on: docker
container:
image: data.forgejo.org/renovate/renovate:40.48.4
image: data.forgejo.org/renovate/renovate:40.31.0
steps:
- name: Load renovate repo cache

View file

@ -37,18 +37,19 @@ endif
XGO_VERSION := go-1.21.x
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.3.0 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.1 # renovate: datasource=go
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 # renovate: datasource=go
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.34.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.2 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.32.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.1 # renovate: datasource=go
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
RENOVATE_NPM_PACKAGE ?= renovate@40.48.4 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
RENOVATE_NPM_PACKAGE ?= renovate@40.31.0 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
@ -923,6 +924,7 @@ deps-tools:
$(GO) install $(GOFUMPT_PACKAGE)
$(GO) install $(GOLANGCI_LINT_PACKAGE)
$(GO) install $(GXZ_PACKAGE)
$(GO) install $(MISSPELL_PACKAGE)
$(GO) install $(SWAGGER_PACKAGE)
$(GO) install $(XGO_PACKAGE)
$(GO) install $(GO_LICENSES_PACKAGE)

View file

@ -18,7 +18,6 @@ func subcmdUser() *cli.Command {
microcmdUserDelete(),
microcmdUserGenerateAccessToken(),
microcmdUserMustChangePassword(),
microcmdUserResetMFA(),
},
}
}

View file

@ -1,73 +0,0 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"fmt"
auth_model "forgejo.org/models/auth"
user_model "forgejo.org/models/user"
"github.com/urfave/cli/v3"
)
func microcmdUserResetMFA() *cli.Command {
return &cli.Command{
Name: "reset-mfa",
Usage: "Remove all two-factor authentication configurations for a user",
Action: runResetMFA,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "username",
Aliases: []string{"u"},
Value: "",
Usage: "The user to update",
},
},
}
}
func runResetMFA(ctx context.Context, c *cli.Command) error {
if err := argsSet(c, "username"); err != nil {
return err
}
ctx, cancel := installSignals(ctx)
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
user, err := user_model.GetUserByName(ctx, c.String("username"))
if err != nil {
return err
}
webAuthnList, err := auth_model.GetWebAuthnCredentialsByUID(ctx, user.ID)
if err != nil {
return err
}
for _, credential := range webAuthnList {
if _, err := auth_model.DeleteCredential(ctx, credential.ID, user.ID); err != nil {
return err
}
}
tfaModes, err := auth_model.GetTwoFactorByUID(ctx, user.ID)
if err == nil && tfaModes != nil {
if err := auth_model.DeleteTwoFactorByID(ctx, tfaModes.ID, user.ID); err != nil {
return err
}
} else {
if _, is := err.(auth_model.ErrTwoFactorNotEnrolled); !is {
return err
}
}
fmt.Printf("%s's two-factor authentication settings have been removed!\n", user.Name)
return nil
}

View file

@ -159,7 +159,7 @@ func NewMainApp(version, versionExtra string) *cli.Command {
func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command, globalFlagsArgs func() []cli.Flag) *cli.Command {
app := &cli.Command{}
app.Name = "forgejo"
app.Name = "Forgejo"
app.Usage = "Beyond coding. We forge."
app.Description = `By default, forgejo will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
app.Version = version + versionExtra

View file

@ -408,7 +408,7 @@ local addIssueLabelsOverrides(labels) =
regex: '',
type: 'query',
multi: true,
allValue: '.+',
allValue: '.+'
},
)
.addTemplate(
@ -423,7 +423,7 @@ local addIssueLabelsOverrides(labels) =
regex: '',
type: 'query',
multi: true,
allValue: '.+',
allValue: '.+'
},
)
.addTemplate(

View file

@ -183,7 +183,7 @@ RUN_USER = ; git
;;
;; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
;; for system SSH this setting has no effect
;SSH_SERVER_KEY_EXCHANGES = mlkem768x25519-sha256, curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1
;SSH_SERVER_KEY_EXCHANGES = curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1
;;
;; For the built-in SSH server, choose the MACs to support for SSH connections,
;; for system SSH this setting has no effect
@ -1025,10 +1025,6 @@ LEVEL = Info
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
;DEFAULT_FORK_REPO_UNITS = repo.code,repo.pulls
;;
;; Comma separated list of default mirror repo units.
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
;DEFAULT_MIRROR_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.wiki,repo.projects,repo.packages
;;
;; Prefix archive files by placing them in a directory named after the repository
;PREFIX_ARCHIVE_FILES = true
;;

26
go.mod
View file

@ -2,10 +2,10 @@ module forgejo.org
go 1.24
toolchain go1.24.4
toolchain go1.24.3
require (
code.forgejo.org/f3/gof3/v3 v3.11.0
code.forgejo.org/f3/gof3/v3 v3.10.8
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
code.forgejo.org/forgejo/go-rpmutils v1.0.0
code.forgejo.org/forgejo/levelqueue v1.0.0
@ -17,7 +17,7 @@ require (
code.gitea.io/actions-proto-go v0.4.0
code.gitea.io/sdk/gitea v0.21.0
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
connectrpc.com/connect v1.18.1
connectrpc.com/connect v1.17.0
github.com/42wim/httpsig v1.2.3
github.com/42wim/sshsig v0.0.0-20250502153856-5100632e8920
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
@ -26,7 +26,7 @@ require (
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
github.com/alecthomas/chroma/v2 v2.18.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.5.2
github.com/blevesearch/bleve/v2 v2.5.1
github.com/buildkite/terminal-to-html/v3 v3.16.8
github.com/caddyserver/certmagic v0.23.0
github.com/chi-middleware/proxy v1.1.1
@ -87,8 +87,8 @@ require (
github.com/prometheus/client_golang v1.21.1
github.com/redis/go-redis/v9 v9.8.0
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/sergi/go-diff v1.4.0
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
github.com/stretchr/testify v1.10.0
github.com/syndtr/goleveldb v1.0.0
@ -101,13 +101,13 @@ require (
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
gitlab.com/gitlab-org/api/client-go v0.129.0
go.uber.org/mock v0.5.2
golang.org/x/crypto v0.39.0
golang.org/x/crypto v0.38.0
golang.org/x/image v0.27.0
golang.org/x/net v0.41.0
golang.org/x/net v0.40.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.15.0
golang.org/x/sync v0.14.0
golang.org/x/sys v0.33.0
golang.org/x/text v0.26.0
golang.org/x/text v0.25.0
google.golang.org/protobuf v1.36.4
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
@ -146,7 +146,7 @@ require (
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
github.com/blevesearch/zapx/v16 v16.2.3 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
@ -237,9 +237,9 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.uber.org/zap/exp v0.3.0 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.34.0 // indirect
golang.org/x/tools v0.31.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

48
go.sum
View file

@ -1,7 +1,7 @@
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
code.forgejo.org/f3/gof3/v3 v3.11.0 h1:f/xToKwqTgxG6PYxvewywjDQyCcyHEEJ6sZqUitFsAE=
code.forgejo.org/f3/gof3/v3 v3.11.0/go.mod h1:4FaRUNSQGBiD1M0DuB0yNv+Z2wMtlOeckgygHSSq4KQ=
code.forgejo.org/f3/gof3/v3 v3.10.8 h1:cL5XgOcKffqMdKDOqGCXfMc2OBX89xYvGSj2mz3E/VQ=
code.forgejo.org/f3/gof3/v3 v3.10.8/go.mod h1:ovgb7R8o7k6poQKQ+KWXHOD9uIoanB6tNSmA3kKOMCI=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
code.forgejo.org/forgejo/act v1.26.0 h1:6mTmoaw7d/WpYiw/Pw6AaypxFdgJog5OFi/PMEgEbxs=
@ -32,8 +32,8 @@ code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
@ -87,8 +87,8 @@ github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCk
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blevesearch/bleve/v2 v2.5.2 h1:Ab0r0MODV2C5A6BEL87GqLBySqp/s9xFgceCju6BQk8=
github.com/blevesearch/bleve/v2 v2.5.2/go.mod h1:5Dj6dUQxZM6aqYT3eutTD/GpWKGFSsV8f7LDidFbwXo=
github.com/blevesearch/bleve/v2 v2.5.1 h1:cc/O++W2Hcjp1SU5ETHeE+QYWv2oV88ldYEPowdmg8M=
github.com/blevesearch/bleve/v2 v2.5.1/go.mod h1:9g/wnbWKm9AgXrU8Ecqi+IDdqjUHWymwkQRDg+5tafU=
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
github.com/blevesearch/geo v0.2.3 h1:K9/vbGI9ehlXdxjxDRJtoAMt7zGAsMIzc6n8zWcwnhg=
@ -121,8 +121,8 @@ github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
github.com/blevesearch/zapx/v16 v16.2.3 h1:7Y0r+a3diEvlazsncexq1qoFOcBd64xwMS7aDm4lo1s=
github.com/blevesearch/zapx/v16 v16.2.3/go.mod h1:wVJ+GtURAaRG9KQAMNYyklq0egV+XJlGcXNCE0OFjjA=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@ -499,11 +499,11 @@ github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@ -591,8 +591,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
@ -603,8 +603,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -620,8 +620,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -633,8 +633,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -684,8 +684,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -695,8 +695,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -1,38 +0,0 @@
;;; Copyright 2025 The Forgejo Authors. All rights reserved.
;;; SPDX-License-Identifier: MIT
;;;
;;; Commentary:
;;;
;;; This is a GNU Guix manifest that can be used to create a
;;; development environment to build and test Forgejo.
;;;
;;; The following is a usage example to create a containerized
;;; environment, with HOME shared for the Go cache and the network
;;; made available to fetch required Go and Node dependencies.
;;;
#|
guix shell -CNF --share=$HOME -m manifest.scm
export GOTOOLCHAIN=local # to use the Go binary from Guix
export CC=gcc CGO_ENABLED=1
export TAGS="timetzdata sqlite sqlite_unlock_notify"
make clean
make -j$(nproc)
make test -j$(nproc) # run unit tests
make test-sqlite -j$(nproc) # run integration tests
make watch # run an instance/rebuild on changes
|#
(specifications->manifest
(list "bash-minimal"
"coreutils"
"findutils"
"gcc-toolchain"
"git" ;libpcre support is required
"git-lfs"
"gnupg"
"go"
"grep"
"make"
"node"
"nss-certs"
"openssh"
"sed"))

View file

@ -54,8 +54,6 @@ type FindRunJobOptions struct {
CommitSHA string
Statuses []Status
UpdatedBefore timeutil.TimeStamp
Events []string // []webhook_module.HookEventType
RunNumber int64
}
func (opts FindRunJobOptions) ToConds() builder.Cond {
@ -78,11 +76,5 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
if opts.UpdatedBefore > 0 {
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
}
if len(opts.Events) > 0 {
cond = cond.And(builder.In("event", opts.Events))
}
if opts.RunNumber > 0 {
cond = cond.And(builder.Eq{"`index`": opts.RunNumber})
}
return cond
}

View file

@ -16,7 +16,6 @@ import (
repo_model "forgejo.org/models/repo"
"forgejo.org/models/shared/types"
user_model "forgejo.org/models/user"
"forgejo.org/modules/log"
"forgejo.org/modules/optional"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/translation"
@ -354,53 +353,3 @@ func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
}
return res.RowsAffected()
}
func DeleteOfflineRunners(ctx context.Context, olderThan timeutil.TimeStamp, globalOnly bool) error {
log.Info("Doing: DeleteOfflineRunners")
if olderThan.AsTime().After(timeutil.TimeStampNow().AddDuration(-RunnerOfflineTime).AsTime()) {
return fmt.Errorf("invalid `cron.cleanup_offline_runners.older_than`value: must be at least %q", RunnerOfflineTime)
}
cond := builder.Or(
// never online
builder.And(builder.Eq{"last_online": 0}, builder.Lt{"created": olderThan}),
// was online but offline
builder.And(builder.Gt{"last_online": 0}, builder.Lt{"last_online": olderThan}),
)
if globalOnly {
cond = builder.And(cond, builder.Eq{"owner_id": 0}, builder.Eq{"repo_id": 0})
}
if err := db.Iterate(
ctx,
cond,
func(ctx context.Context, r *ActionRunner) error {
if err := DeleteRunner(ctx, r); err != nil {
return fmt.Errorf("DeleteOfflineRunners: %w", err)
}
lastOnline := r.LastOnline.AsTime()
olderThanTime := olderThan.AsTime()
if !lastOnline.IsZero() && lastOnline.Before(olderThanTime) {
log.Info(
"Deleted runner [ID: %d, Name: %s], last online %s ago",
r.ID, r.Name, olderThanTime.Sub(lastOnline).String(),
)
} else {
log.Info(
"Deleted runner [ID: %d, Name: %s], unused since %s ago",
r.ID, r.Name, olderThanTime.Sub(r.Created.AsTime()).String(),
)
}
return nil
},
); err != nil {
return err
}
log.Info("Finished: DeleteOfflineRunners")
return nil
}

View file

@ -6,12 +6,10 @@ import (
"encoding/binary"
"fmt"
"testing"
"time"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
"forgejo.org/models/unittest"
"forgejo.org/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -75,68 +73,3 @@ func TestDeleteRunner(t *testing.T) {
idAsBinary[6], idAsBinary[7])
assert.Equal(t, idAsHexadecimal, after.UUID[19:])
}
func TestDeleteOfflineRunnersRunnerGlobalOnly(t *testing.T) {
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
timeutil.MockSet(baseTime)
defer timeutil.MockUnset()
require.NoError(t, unittest.PrepareTestDatabase())
olderThan := timeutil.TimeStampNow().Add(-timeutil.Hour)
require.NoError(t, DeleteOfflineRunners(db.DefaultContext, olderThan, true))
// create at test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 12345678})
// last_online test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000001})
// created one month ago but a repo
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000002})
// last online one hour ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000003})
// last online 10 seconds ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000004})
// created 1 month ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000005})
// created 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000006})
// last online 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000007})
}
func TestDeleteOfflineRunnersAll(t *testing.T) {
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
timeutil.MockSet(baseTime)
defer timeutil.MockUnset()
require.NoError(t, unittest.PrepareTestDatabase())
olderThan := timeutil.TimeStampNow().Add(-timeutil.Hour)
require.NoError(t, DeleteOfflineRunners(db.DefaultContext, olderThan, false))
// create at test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 12345678})
// last_online test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000001})
// created one month ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000002})
// last online one hour ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000003})
// last online 10 seconds ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000004})
// created 1 month ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000005})
// created 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000006})
// last online 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000007})
}
func TestDeleteOfflineRunnersErrorOnInvalidOlderThanValue(t *testing.T) {
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
timeutil.MockSet(baseTime)
defer timeutil.MockUnset()
require.Error(t, DeleteOfflineRunners(db.DefaultContext, timeutil.TimeStampNow(), false))
}

View file

@ -34,15 +34,6 @@ var statusNames = map[Status]string{
StatusBlocked: "blocked",
}
var nameToStatus = make(map[string]Status, len(statusNames))
func init() {
// Populate name to status lookup map
for status, name := range statusNames {
nameToStatus[name] = status
}
}
// String returns the string name of the Status
func (s Status) String() string {
return statusNames[s]
@ -111,8 +102,3 @@ func (s Status) AsResult() runnerv1.Result {
}
return runnerv1.Result_RESULT_UNSPECIFIED
}
func StatusFromString(name string) (Status, bool) {
status, exists := nameToStatus[name]
return status, exists
}

View file

@ -227,7 +227,7 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
// The ssh library can parse the key, so next we find out what key exactly we have.
switch pkeyType {
case ssh.KeyAlgoDSA: //nolint:staticcheck
case ssh.KeyAlgoDSA:
rawPub := struct {
Name string
P, Q, G, Y *big.Int

View file

@ -471,64 +471,3 @@
need_approval: 0
approved_by: 0
event_payload: '{"head_commit":{"id":"5f22f7d0d95d614d25a5b68592adb345a4b5c7fd"}}'
# GET action run(s) test
-
id: 892
title: "successful push run"
repo_id: 63
owner_id: 2
workflow_id: "success.yaml"
index: 1
trigger_user_id: 2
ref: "refs/heads/main"
commit_sha: "97f29ee599c373c729132a5c46a046978311e0ee"
event: "push"
is_fork_pull_request: 0
status: 1 # success
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 893
title: "failed pull_request run"
repo_id: 63
owner_id: 2
workflow_id: "failed.yaml"
index: 2
trigger_user_id: 2
ref: "refs/heads/bugfix-1"
commit_sha: "35c5cddfc19397501ec8f4f7bb808a7c8f04445f"
event: "pull_request"
is_fork_pull_request: 0
status: 2 # failure
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 894
title: "running workflow_dispatch run"
repo_id: 63
owner_id: 2
workflow_id: "running.yaml"
index: 3
trigger_user_id: 2
ref: "refs/heads/main"
commit_sha: "97f29ee599c373c729132a5c46a046978311e0ee"
event: "workflow_dispatch"
is_fork_pull_request: 0
status: 6 # running
started: 1683636528
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0

View file

@ -18,122 +18,3 @@
created: 1716104432
updated: 1716104432
deleted: ~
- id: 10000001
uuid: 10d3b248-6460-4bf5-b819-1f5b3109e10f
name: global-online
version: v6.3.1+7-gc4c0ca0
owner_id: 0
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: 7e9ed71f64e98ce1f70e94c63f3cb6c41a8cb0b90de3e1daf7ec5c35361d60ed44da67c5ac393b7aaf443dcfc766007dc828
token_salt: WUcgZWl7mW
last_online: 1716104422
last_active: 0
agent_labels: '["docker"]'
created: 1716104431
updated: 1716104422
deleted: ~
- id: 10000002
uuid: 1d188484-dd97-4a70-b707-5e87b578ab6b
name: repo-never-used
version: v6.3.1+7-gc4c0ca0
owner_id: 0
repo_id: 1
description: ""
base: 0
repo_range: ""
token_hash: 51e88c17ac8b54dd101dc2e4f530a71643c703adba7170f4b1a28f1cb483b4cfb107798c521e0532ef3c6480b64518a5c6a5
token_salt: 4rh8ncXYIO
last_online: 0
last_active: 0
agent_labels: '["docker"]'
created: 1713512432
updated: 1713512432
deleted: ~
- id: 10000003
uuid: 7a039c6b-b0b2-4cf5-a93d-715d617f99e2
name: global-offline
version: v6.3.1+7-gc4c0ca0
owner_id: 0
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: c76960c56bc6069f0d1648991ec626500abe8c15286f5c355d565c3b5ba945d7d6f1272a6c77849e592528179511b94f5d69
token_salt: TFMe2jhOkB
last_online: 1715499632
last_active: 0
agent_labels: '["docker"]'
created: 1715499632
updated: 1715499632
deleted: ~
- id: 10000004
uuid: 93ca7fdd-faca-4df6-a474-8345263ef10b
name: user-online
version: v6.3.1+7-gc4c0ca0
owner_id: 1
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: 6ddf7f0f2301d2b3f66418145dc497a6d09fa6586e659afcb5ae2a0c5b639561d795aff8062537db9df73b396842ea826134
token_salt: QcdGuReAp4
last_online: 1716104422
last_active: 0
agent_labels: '["docker"]'
created: 1716104431
updated: 1716104422
deleted: ~
- id: 10000005
uuid: a8534df6-c4be-40f4-9714-903b69d973d9
name: user-never-used
version: v6.3.1+7-gc4c0ca0
owner_id: 1
repo_id: 0
description: desc
base: 0
repo_range: ""
token_hash: 4441de7defcfc3d21baa608dec66a562cf23307abddaabdbb836907ac5f48c8780c354891916c525b79ec7af8e95be7a09b4
token_salt: ONNqIOnj3t
last_online: 0
last_active: 0
agent_labels: '["docker"]'
created: 1713512433
updated: 1713512433
deleted: ~
- id: 10000006
uuid: e1c5bb6c-de68-4335-8955-5192f76708ac
name: orga-fresh-created
version: v6.3.1+7-gc4c0ca0
owner_id: 35
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: a61f9ee48c6847d243ace0a8936efe80af9277c7bc46d6da6e03d1d406608b8023ee66600ad24f0effaa8e3338f92ac97ac9
token_salt: fZJKjrFGWA
last_online: 0
last_active: 0
agent_labels: '["docker"]'
created: 1716100832
updated: 1716100832
deleted: ~
- id: 10000007
uuid: ff755f06-948e-479b-8031-5b3e9f123e32
name: orga-offline
version: v6.3.1+7-gc4c0ca0
owner_id: 35
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: 9372efb38f9b64efe65065380abe2f24ef34a59d9619f4cdc08f1151e9849f0b6e722aa10538e8730288de6e2f09acdac695
token_salt: TnU7iiIdCb
last_online: 1716100832
last_active: 0
agent_labels: '["docker"]'
created: 1736085520
updated: 1716100832
deleted: ~

View file

@ -795,10 +795,3 @@
type: 10
config: "{}"
created_unix: 946684810
-
id: 115
repo_id: 63
type: 10
config: "{}"
created_unix: 946684810

View file

@ -1889,35 +1889,3 @@
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
topics: '[]'
-
id: 63
owner_id: 2
owner_name: user2
lower_name: test_action_run_search
name: test_action_run_search
default_branch: main
num_watches: 0
num_stars: 0
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 0
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
num_projects: 0
num_closed_projects: 0
is_private: true
is_empty: false
is_archived: false
is_mirror: false
status: 0
is_fork: false
fork_id: 0
is_template: false
template_id: 0
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
topics: '[]'

View file

@ -239,15 +239,3 @@
num_members: 2
includes_all_repositories: false
can_create_org_repo: false
-
id: 25
org_id: 17
lower_name: super-user
name: super-user
description: ""
authorize: 3
num_repos: 0
num_members: 0
includes_all_repositories: 0
can_create_org_repo: 0

View file

@ -329,10 +329,3 @@
team_id: 22
type: 3
access_mode: 1
-
id: 84
org_id: 17
team_id: 25
type: 3
access_mode: 3

View file

@ -70,7 +70,7 @@
num_followers: 2
num_following: 1
num_stars: 2
num_repos: 18
num_repos: 17
num_teams: 0
num_members: 0
visibility: 0
@ -642,7 +642,7 @@
num_following: 0
num_stars: 0
num_repos: 2
num_teams: 4
num_teams: 3
num_members: 4
visibility: 0
repo_admin_change_team_access: false

View file

@ -10,45 +10,16 @@ import (
func SetTopicsAsEmptySlice(x *xorm.Engine) error {
var err error
switch x.Dialect().URI().DBType {
case schemas.MYSQL:
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics = 'null'")
case schemas.SQLITE:
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics = 'null'")
case schemas.POSTGRES:
if x.Dialect().URI().DBType == schemas.POSTGRES {
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics::text = 'null'")
} else {
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL")
}
if err != nil {
return err
}
if x.Dialect().URI().DBType == schemas.SQLITE {
sessMigration := x.NewSession()
defer sessMigration.Close()
if err := sessMigration.Begin(); err != nil {
return err
}
_, err = sessMigration.Exec("ALTER TABLE `repository` RENAME COLUMN `topics` TO `topics_backup`")
if err != nil {
return err
}
_, err = sessMigration.Exec("ALTER TABLE `repository` ADD COLUMN `topics` TEXT NOT NULL DEFAULT '[]'")
if err != nil {
return err
}
_, err = sessMigration.Exec("UPDATE `repository` SET `topics` = `topics_backup`")
if err != nil {
return err
}
_, err = sessMigration.Exec("ALTER TABLE `repository` DROP COLUMN `topics_backup`")
if err != nil {
return err
}
return sessMigration.Commit()
}
type Repository struct {
ID int64 `xorm:"pk autoincr"`
Topics []string `xorm:"TEXT JSON NOT NULL"`

View file

@ -1,5 +0,0 @@
-
id: 1000
uid: 4
org_id: 22
is_public: true

View file

@ -26,7 +26,6 @@ type SearchOrganizationsOptions struct {
type FindOrgOptions struct {
db.ListOptions
UserID int64
IncludeLimited bool
IncludePrivate bool
}
@ -44,11 +43,7 @@ func (opts FindOrgOptions) ToConds() builder.Cond {
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
}
if !opts.IncludePrivate {
if !opts.IncludeLimited {
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
} else {
cond = cond.And(builder.In("`user`.visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
}
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
}
return cond
}

View file

@ -27,7 +27,6 @@ func TestCountOrganizations(t *testing.T) {
}
func TestFindOrgs(t *testing.T) {
defer unittest.OverrideFixtures("models/organization/TestFindOrgs")()
require.NoError(t, unittest.PrepareTestDatabase())
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
@ -35,14 +34,8 @@ func TestFindOrgs(t *testing.T) {
IncludePrivate: true,
})
require.NoError(t, err)
if assert.Len(t, orgs, 2) {
if orgs[0].ID == 22 {
assert.EqualValues(t, 22, orgs[0].ID)
assert.EqualValues(t, 3, orgs[1].ID)
} else {
assert.EqualValues(t, 3, orgs[0].ID)
assert.EqualValues(t, 22, orgs[1].ID)
}
if assert.Len(t, orgs, 1) {
assert.EqualValues(t, 3, orgs[0].ID)
}
orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
@ -57,14 +50,6 @@ func TestFindOrgs(t *testing.T) {
IncludePrivate: true,
})
require.NoError(t, err)
assert.EqualValues(t, 2, total)
total, err = db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
UserID: 4,
IncludePrivate: false,
IncludeLimited: true,
})
require.NoError(t, err)
assert.EqualValues(t, 1, total)
}

View file

@ -235,7 +235,7 @@ func UpdateAttachmentByUUID(ctx context.Context, attach *Attachment, cols ...str
if attach.UUID == "" {
return errors.New("attachment uuid should be not blank")
}
if attach.ExternalURL != "" && !validation.IsValidReleaseAssetURL(attach.ExternalURL) {
if attach.ExternalURL != "" && !validation.IsValidExternalURL(attach.ExternalURL) {
return ErrInvalidExternalURL{ExternalURL: attach.ExternalURL}
}
_, err := db.GetEngine(ctx).Where("uuid=?", attach.UUID).Cols(cols...).Update(attach)
@ -244,7 +244,7 @@ func UpdateAttachmentByUUID(ctx context.Context, attach *Attachment, cols ...str
// UpdateAttachment updates the given attachment in database
func UpdateAttachment(ctx context.Context, atta *Attachment) error {
if atta.ExternalURL != "" && !validation.IsValidReleaseAssetURL(atta.ExternalURL) {
if atta.ExternalURL != "" && !validation.IsValidExternalURL(atta.ExternalURL) {
return ErrInvalidExternalURL{ExternalURL: atta.ExternalURL}
}
sess := db.GetEngine(ctx).Cols("name", "issue_id", "release_id", "comment_id", "download_count")

View file

@ -1,5 +1,4 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package unit
@ -70,7 +69,7 @@ func (u Type) LogString() string {
}
var (
// AllRepoUnitTypes contains all units
// AllRepoUnitTypes contains all the unit types
AllRepoUnitTypes = []Type{
TypeCode,
TypeIssues,
@ -84,7 +83,7 @@ var (
TypeActions,
}
// DefaultRepoUnits contains default units for regular repos
// DefaultRepoUnits contains the default unit types
DefaultRepoUnits = []Type{
TypeCode,
TypeIssues,
@ -96,22 +95,12 @@ var (
TypeActions,
}
// ForkRepoUnits contains default units for forks
// ForkRepoUnits contains the default unit types for forks
DefaultForkRepoUnits = []Type{
TypeCode,
TypePullRequests,
}
// DefaultMirrorRepoUnits contains default units for mirrors
DefaultMirrorRepoUnits = []Type{
TypeCode,
TypeIssues,
TypeReleases,
TypeWiki,
TypeProjects,
TypePackages,
}
// NotAllowedDefaultRepoUnits contains units that can't be default
NotAllowedDefaultRepoUnits = []Type{
TypeExternalWiki,
@ -183,8 +172,6 @@ func LoadUnitConfig() error {
if len(DefaultRepoUnits) == 0 {
return errors.New("no default repository units found")
}
// Default fork repo units
setDefaultForkRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultForkRepoUnits...)
if len(invalidKeys) > 0 {
log.Warn("Invalid keys in default fork repo units: %s", strings.Join(invalidKeys, ", "))
@ -194,16 +181,6 @@ func LoadUnitConfig() error {
return errors.New("no default fork repository units found")
}
// Default mirror repo units
setDefaultMirrorRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultMirrorRepoUnits...)
if len(invalidKeys) > 0 {
log.Warn("Invalid keys in default mirror repo units: %s", strings.Join(invalidKeys, ", "))
}
DefaultMirrorRepoUnits = validateDefaultRepoUnits(DefaultMirrorRepoUnits, setDefaultMirrorRepoUnits)
if len(DefaultMirrorRepoUnits) == 0 {
return errors.New("no default mirror repository units found")
}
// Collect the allowed repo unit groups. Mutually exclusive units are
// grouped together.
AllowedRepoUnitGroups = [][]Type{}

View file

@ -299,24 +299,6 @@ func (w *Webhook) HasPackageEvent() bool {
(w.ChooseEvents && w.Package)
}
// HasActionRunFailureEvent returns if hook enabled action failure event.
func (w *Webhook) HasActionRunFailureEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.ActionRunFailure)
}
// HasActionRunRecoverEvent returns if hook enabled action recover event.
func (w *Webhook) HasActionRunRecoverEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.ActionRunRecover)
}
// HasActionRunSuccessEvent returns if hook enabled action success event.
func (w *Webhook) HasActionRunSuccessEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.ActionRunSuccess)
}
// HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event.
func (w *Webhook) HasPullRequestReviewRequestEvent() bool {
return w.SendEverything ||
@ -355,9 +337,6 @@ func (w *Webhook) EventCheckers() []struct {
{w.HasReleaseEvent, webhook_module.HookEventRelease},
{w.HasPackageEvent, webhook_module.HookEventPackage},
{w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest},
{w.HasActionRunFailureEvent, webhook_module.HookEventActionRunFailure},
{w.HasActionRunRecoverEvent, webhook_module.HookEventActionRunRecover},
{w.HasActionRunSuccessEvent, webhook_module.HookEventActionRunSuccess},
}
}

View file

@ -74,8 +74,7 @@ func TestWebhook_EventsArray(t *testing.T) {
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
"package", "pull_request_review_request", "action_run_failure",
"action_run_recover", "action_run_success",
"package", "pull_request_review_request",
},
(&Webhook{
HookEvent: &webhook_module.HookEvent{SendEverything: true},
@ -90,78 +89,15 @@ func TestWebhook_EventsArray(t *testing.T) {
}
func TestCreateWebhook(t *testing.T) {
t.Run("Some chosen events 1", func(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"create":false,"push":true,"pull_request":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
hookFromDb := unittest.AssertExistsAndLoadBean(t, hook)
assert.Equal(t, []string{
string(webhook_module.HookEventPush),
string(webhook_module.HookEventPullRequest),
}, hookFromDb.EventsArray())
})
t.Run("Some chosen events 2", func(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"action_run_recover":false,"action_run_success":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
hookFromDb := unittest.AssertExistsAndLoadBean(t, hook)
assert.Equal(t, []string{string(webhook_module.HookEventActionRunSuccess)}, hookFromDb.EventsArray())
})
t.Run("All events", func(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"create":true,"delete":true,"fork":true,"issues":true,"issue_assign":true,"issue_label":true,"issue_milestone":true,"issue_comment":true,"push":true,"pull_request":true,"pull_request_assign":true,"pull_request_label":true,"pull_request_milestone":true,"pull_request_comment":true,"pull_request_review":true,"pull_request_sync":true,"pull_request_review_request":true,"wiki":true,"repository":true,"release":true,"package":true,"action_run_failure":true,"action_run_recover":true,"action_run_success":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
hookFromDb := unittest.AssertExistsAndLoadBean(t, hook)
assert.Equal(t, []string{
string(webhook_module.HookEventCreate),
string(webhook_module.HookEventDelete),
string(webhook_module.HookEventFork),
string(webhook_module.HookEventPush),
string(webhook_module.HookEventIssues),
string(webhook_module.HookEventIssueAssign),
string(webhook_module.HookEventIssueLabel),
string(webhook_module.HookEventIssueMilestone),
string(webhook_module.HookEventIssueComment),
string(webhook_module.HookEventPullRequest),
string(webhook_module.HookEventPullRequestAssign),
string(webhook_module.HookEventPullRequestLabel),
string(webhook_module.HookEventPullRequestMilestone),
string(webhook_module.HookEventPullRequestComment),
string(webhook_module.HookEventPullRequestReviewApproved),
string(webhook_module.HookEventPullRequestReviewRejected),
string(webhook_module.HookEventPullRequestReviewComment),
string(webhook_module.HookEventPullRequestSync),
string(webhook_module.HookEventWiki),
string(webhook_module.HookEventRepository),
string(webhook_module.HookEventRelease),
string(webhook_module.HookEventPackage),
string(webhook_module.HookEventPullRequestReviewRequest),
// these aren't webhook event types
// string(webhook_module.HookEventSchedule),
// string(webhook_module.HookEventWorkflowDispatch),
string(webhook_module.HookEventActionRunFailure),
string(webhook_module.HookEventActionRunRecover),
string(webhook_module.HookEventActionRunSuccess),
},
hookFromDb.EventsArray())
})
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
unittest.AssertExistsAndLoadBean(t, hook)
}
func TestGetWebhookByRepoID(t *testing.T) {

View file

@ -1,57 +0,0 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
"github.com/google/uuid"
)
// ForgeFollow activity data type
// swagger:model
type ForgeFollow struct {
// swagger:ignore
ap.Activity
}
func NewForgeFollowFromAp(activity ap.Activity) (ForgeFollow, error) {
result := ForgeFollow{}
result.Activity = activity
if valid, err := validation.IsValid(result); !valid {
return ForgeFollow{}, err
}
return result, nil
}
func NewForgeFollow(actor, object string) (ForgeFollow, error) {
result := ForgeFollow{}
result.Type = ap.FollowType
result.ID = ap.IRI(actor + "/follows/" + uuid.New().String())
result.Actor = ap.IRI(actor)
result.Object = ap.IRI(object)
if valid, err := validation.IsValid(result); !valid {
return ForgeFollow{}, err
}
return result, nil
}
func (follow ForgeFollow) MarshalJSON() ([]byte, error) {
return follow.Activity.MarshalJSON()
}
func (follow *ForgeFollow) UnmarshalJSON(data []byte) error {
return follow.Activity.UnmarshalJSON(data)
}
func (follow ForgeFollow) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(follow.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(follow.Type), []any{"Follow"}, "type")...)
result = append(result, validation.ValidateIDExists(follow.Actor, "actor")...)
result = append(result, validation.ValidateIDExists(follow.Object, "object")...)
return result
}

View file

@ -1,31 +0,0 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func Test_NewForgeFollowValidation(t *testing.T) {
sut := ForgeFollow{}
sut.Type = "Follow"
sut.Actor = ap.IRI("example.org/alice")
sut.Object = ap.IRI("example.org/bob")
if err, _ := validation.IsValid(sut); !err {
t.Errorf("sut is invalid: %v\n", err)
}
sut = ForgeFollow{}
sut.Actor = ap.IRI("example.org/alice")
sut.Object = ap.IRI("example.org/bob")
if err, _ := validation.IsValid(sut); err {
t.Errorf("sut is valid: %v\n", err)
}
}

View file

@ -1,77 +0,0 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"fmt"
"time"
user_model "forgejo.org/models/user"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ForgeFollow activity data type
// swagger:model
type ForgeUserActivity struct {
ap.Activity
Note ForgeUserActivityNote
}
func NewForgeUserActivityFromAp(activity ap.Activity) (ForgeUserActivity, error) {
result := ForgeUserActivity{}
result.Activity = activity
note, err := NewForgeUserActivityNoteFromAp(activity.Object)
if err != nil {
return ForgeUserActivity{}, err
}
result.Note = note
if valid, err := validation.IsValid(result); !valid {
return ForgeUserActivity{}, err
}
return result, nil
}
func NewForgeUserActivity(doer *user_model.User, actionID int64, content string) (ForgeUserActivity, error) {
id := fmt.Sprintf("%s/activities/%d", doer.APActorID(), actionID)
published := time.Now()
result := ForgeUserActivity{}
result.ID = ap.IRI(id + "/activity")
result.Type = ap.CreateType
result.Actor = ap.IRI(doer.APActorID())
result.Published = published
result.To = ap.ItemCollection{
ap.IRI("https://www.w3.org/ns/activitystreams#Public"),
}
result.CC = ap.ItemCollection{
ap.IRI(doer.APActorID() + "/followers"),
}
note, err := newNote(doer, content, id, published)
if err != nil {
return ForgeUserActivity{}, err
}
result.Object = note
return result, nil
}
func (userActivity ForgeUserActivity) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(userActivity.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(userActivity.Type), []any{"Create"}, "type")...)
result = append(result, validation.ValidateIDExists(userActivity.Actor, "actor")...)
if len(userActivity.To) == 0 {
result = append(result, "Missing to")
}
if len(userActivity.CC) == 0 {
result = append(result, "Missing cc")
}
result = append(result, userActivity.Note.Validate()...)
return result
}

View file

@ -1,40 +0,0 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func Test_ForgeUserActivityValidation(t *testing.T) {
note := ForgeUserActivityNote{}
note.Type = "Note"
note.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
}
note.URL = ap.IRI("example.org/user-id/57")
sut := ForgeUserActivity{}
sut.Type = "Create"
sut.Actor = ap.IRI("example.org/user-id/23")
sut.CC = ap.ItemCollection{
ap.IRI("example.org/registration/public#2nd"),
}
sut.To = ap.ItemCollection{
ap.IRI("example.org/registration/public"),
}
sut.Note = note
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}

View file

@ -10,6 +10,8 @@ import (
"strings"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ----------------------------- ActorID --------------------------------------------
@ -39,18 +41,12 @@ func NewActorID(uri string) (ActorID, error) {
}
func (id ActorID) AsURI() string {
var result, path string
if id.Path == "" {
path = id.ID
} else {
path = fmt.Sprintf("%s/%s", id.Path, id.ID)
}
var result string
if id.IsPortSupplemented {
result = fmt.Sprintf("%s://%s/%s", id.HostSchema, id.Host, path)
result = fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID)
} else {
result = fmt.Sprintf("%s://%s:%d/%s", id.HostSchema, id.Host, id.HostPort, path)
result = fmt.Sprintf("%s://%s:%d/%s/%s", id.HostSchema, id.Host, id.HostPort, id.Path, id.ID)
}
return result
@ -58,7 +54,8 @@ func (id ActorID) AsURI() string {
func (id ActorID) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(id.ID, "ID")...)
result = append(result, validation.ValidateNotEmpty(id.ID, "userId")...)
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
result = append(result, validation.ValidateNotEmpty(id.Host, "host")...)
result = append(result, validation.ValidateNotEmpty(id.HostPort, "hostPort")...)
result = append(result, validation.ValidateNotEmpty(id.HostSchema, "hostSchema")...)
@ -71,6 +68,115 @@ func (id ActorID) Validate() []string {
return result
}
// ----------------------------- PersonID --------------------------------------------
type PersonID struct {
ActorID
}
// Factory function for PersonID. Created struct is asserted to be valid
func NewPersonID(uri, source string) (PersonID, error) {
result, err := newActorID(uri)
if err != nil {
return PersonID{}, err
}
result.Source = source
// validate Person specific path
personID := PersonID{result}
if valid, err := validation.IsValid(personID); !valid {
return PersonID{}, err
}
return personID, nil
}
func (id PersonID) AsWebfinger() string {
result := fmt.Sprintf("@%s@%s", strings.ToLower(id.ID), strings.ToLower(id.Host))
return result
}
func (id PersonID) AsLoginName() string {
result := fmt.Sprintf("%s%s", strings.ToLower(id.ID), id.HostSuffix())
return result
}
func (id PersonID) HostSuffix() string {
result := fmt.Sprintf("-%s", strings.ToLower(id.Host))
return result
}
func (id PersonID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...)
switch id.Source {
case "forgejo", "gitea":
if strings.ToLower(id.Path) != "api/v1/activitypub/user-id" && strings.ToLower(id.Path) != "api/activitypub/user-id" {
result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path))
}
}
return result
}
// ----------------------------- RepositoryID --------------------------------------------
type RepositoryID struct {
ActorID
}
// Factory function for RepositoryID. Created struct is asserted to be valid.
func NewRepositoryID(uri, source string) (RepositoryID, error) {
result, err := newActorID(uri)
if err != nil {
return RepositoryID{}, err
}
result.Source = source
// validate Person specific
repoID := RepositoryID{result}
if valid, err := validation.IsValid(repoID); !valid {
return RepositoryID{}, err
}
return repoID, nil
}
func (id RepositoryID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...)
switch id.Source {
case "forgejo", "gitea":
if strings.ToLower(id.Path) != "api/v1/activitypub/repository-id" && strings.ToLower(id.Path) != "api/activitypub/repository-id" {
result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", id.Path))
}
}
return result
}
func containsEmptyString(ar []string) bool {
for _, elem := range ar {
if elem == "" {
return true
}
}
return false
}
func removeEmptyStrings(ls []string) []string {
var rs []string
for _, str := range ls {
if str != "" {
rs = append(rs, str)
}
}
return rs
}
// ----------------------------- newActorID --------------------------------------------
func newActorID(uri string) (ActorID, error) {
validatedURI, err := url.ParseRequestURI(uri)
if err != nil {
@ -106,21 +212,28 @@ func newActorID(uri string) (ActorID, error) {
return result, nil
}
func containsEmptyString(ar []string) bool {
for _, elem := range ar {
if elem == "" {
return true
}
}
return false
// ----------------------------- ForgePerson -------------------------------------
// ForgePerson activity data type
// swagger:model
type ForgePerson struct {
// swagger:ignore
ap.Actor
}
func removeEmptyStrings(ls []string) []string {
var rs []string
for _, str := range ls {
if str != "" {
rs = append(rs, str)
}
}
return rs
func (s ForgePerson) MarshalJSON() ([]byte, error) {
return s.Actor.MarshalJSON()
}
func (s *ForgePerson) UnmarshalJSON(data []byte) error {
return s.Actor.UnmarshalJSON(data)
}
func (s ForgePerson) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...)
result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...)
return result
}

View file

@ -1,122 +0,0 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"fmt"
"strings"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ----------------------------- PersonID --------------------------------------------
type PersonID struct {
ActorID
}
const (
personIDapiPathV1 = "api/v1/activitypub/user-id"
personIDapiPathV1Latest = "api/activitypub/user-id"
)
// Factory function for PersonID. Created struct is asserted to be valid
func NewPersonID(uri, source string) (PersonID, error) {
result, err := newActorID(uri)
if err != nil {
return PersonID{}, err
}
result.Source = source
// validate Person specific path
personID := PersonID{result}
if valid, err := validation.IsValid(personID); !valid {
return PersonID{}, err
}
return personID, nil
}
func NewPersonIDFromModel(host, schema string, port uint16, softwareName, id string) (PersonID, error) {
result := PersonID{}
result.ID = id
result.Source = softwareName
result.Host = host
result.HostSchema = schema
result.HostPort = port
result.IsPortSupplemented = false
if softwareName == "forgejo" {
result.Path = personIDapiPathV1
}
result.UnvalidatedInput = result.AsURI()
// validate Person specific path
if valid, err := validation.IsValid(result); !valid {
return PersonID{}, err
}
return result, nil
}
func (id PersonID) AsWebfinger() string {
result := fmt.Sprintf("@%s@%s", strings.ToLower(id.ID), strings.ToLower(id.Host))
return result
}
func (id PersonID) AsLoginName() string {
result := fmt.Sprintf("%s%s", strings.ToLower(id.ID), id.HostSuffix())
return result
}
func (id PersonID) HostSuffix() string {
var result string
if !id.IsPortSupplemented {
result = fmt.Sprintf("-%s-%d", strings.ToLower(id.Host), id.HostPort)
} else {
result = fmt.Sprintf("-%s", strings.ToLower(id.Host))
}
return result
}
func (id PersonID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea", "mastodon", "gotosocial"}, "Source")...)
if id.Source == "forgejo" {
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
if strings.ToLower(id.Path) != personIDapiPathV1 && strings.ToLower(id.Path) != personIDapiPathV1Latest {
result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path))
}
}
return result
}
// ----------------------------- ForgePerson -------------------------------------
// ForgePerson activity data type
// swagger:model
type ForgePerson struct {
// swagger:ignore
ap.Actor
}
func (s ForgePerson) MarshalJSON() ([]byte, error) {
return s.Actor.MarshalJSON()
}
func (s *ForgePerson) UnmarshalJSON(data []byte) error {
return s.Actor.UnmarshalJSON(data)
}
func (s ForgePerson) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...)
result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...)
return result
}

View file

@ -1,268 +0,0 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"reflect"
"strings"
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewPersonIdFromModel(t *testing.T) {
expected := PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ := NewPersonIDFromModel("an.other.host", "https", 443, "forgejo", "1")
assert.Equal(t, expected, sut)
}
func TestNewPersonId(t *testing.T) {
var sut, expected PersonID
var err error
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = true
expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
sut, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
require.NoError(t, err)
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 80
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://an.other.host:80/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("http://an.other.host:80/api/v1/activitypub/user-id/1", "forgejo")
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("HTTPS://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "@me"
expected.Source = "gotosocial"
expected.HostSchema = "https"
expected.Path = ""
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = true
expected.UnvalidatedInput = "https://an.other.host/@me"
sut, err = NewPersonID("https://an.other.host/@me", "gotosocial")
require.NoError(t, err)
assert.Equal(t, expected, sut)
}
func TestPersonIdValidation(t *testing.T) {
sut := PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = ""
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/1"
result, err := validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: path should not be empty\npath: \"\" has to be a person specific api path")
sut = PersonID{}
sut.ID = "1"
sut.Source = "mastodon"
sut.HostSchema = "https"
sut.Path = ""
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/1"
result, err = validation.IsValid(sut)
assert.True(t, result)
require.NoError(t, err)
sut = PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "path"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/path/1"
result, err = validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: path: \"path\" has to be a person specific api path")
sut = PersonID{}
sut.ID = "1"
sut.Source = "forgejox"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
result, err = validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: Field Source contains the value forgejox, which is not in allowed subset [forgejo gitea mastodon gotosocial]")
}
func TestWebfingerId(t *testing.T) {
sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
assert.Equal(t, "@12345@codeberg.org", sut.AsWebfinger())
}
func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
var err any
_, err = NewPersonID("", "forgejo")
if err == nil {
t.Errorf("empty input should be invalid.")
}
_, err = NewPersonID("http://localhost:3000/api/v1/something", "forgejo")
if err == nil {
t.Errorf("localhost uris are not external")
}
_, err = NewPersonID("./api/v1/something", "forgejo")
if err == nil {
t.Errorf("relative uris are not allowed")
}
_, err = NewPersonID("http://1.2.3.4/api/v1/something", "forgejo")
if err == nil {
t.Errorf("uri may not be ip-4 based")
}
_, err = NewPersonID("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo")
if err == nil {
t.Errorf("uri may not be ip-6 based")
}
_, err = NewPersonID("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo")
if err == nil {
t.Errorf("uri may not contain relative path elements")
}
_, err = NewPersonID("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err == nil {
t.Errorf("uri may not contain unparsed elements")
}
_, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err != nil {
t.Errorf("this uri should be valid but was: %v", err)
}
}
func Test_PersonMarshalJSON(t *testing.T) {
sut := ForgePerson{}
sut.Type = "Person"
sut.PreferredUsername = ap.NaturalLanguageValuesNew()
sut.PreferredUsername.Set("en", ap.Content("MaxMuster"))
result, _ := sut.MarshalJSON()
assert.JSONEq(t, `{"type":"Person","preferredUsername":"MaxMuster"}`, string(result), "Expected string is not equal")
}
func Test_PersonUnmarshalJSON(t *testing.T) {
expected := &ForgePerson{
Actor: ap.Actor{
Type: "Person",
PreferredUsername: ap.NaturalLanguageValues{
ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")},
},
},
}
sut := new(ForgePerson)
err := sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
x, _ := expected.MarshalJSON()
y, _ := sut.MarshalJSON()
if !reflect.DeepEqual(x, y) {
t.Errorf("UnmarshalJSON() expected: %q got: %q", x, y)
}
expectedStr := strings.ReplaceAll(strings.ReplaceAll(`{
"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"type":"Person",
"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatar/fa7f9c4af2a64f41b1bef292bf872614"},
"url":"https://federated-repo.prod.meissa.de/stargoose9",
"inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/inbox",
"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/outbox",
"preferredUsername":"stargoose9",
"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10#main-key",
"owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBoj...XAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`,
"\n", ""),
"\t", "")
err = sut.UnmarshalJSON([]byte(expectedStr))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
result, _ := sut.MarshalJSON()
assert.JSONEq(t, expectedStr, string(result), "Expected string is not equal")
}
func TestForgePersonValidation(t *testing.T) {
sut := new(ForgePerson)
sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}
func TestAsloginName(t *testing.T) {
sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
assert.Equal(t, "12345-codeberg.org", sut.AsLoginName())
sut, _ = NewPersonID("https://codeberg.org:443/api/v1/activitypub/user-id/12345", "forgejo")
assert.Equal(t, "12345-codeberg.org-443", sut.AsLoginName())
}

View file

@ -1,52 +0,0 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"fmt"
"strings"
"forgejo.org/modules/validation"
)
// ----------------------------- RepositoryID --------------------------------------------
type RepositoryID struct {
ActorID
}
const (
repositoryIDapiPathV1 = "api/v1/activitypub/repository-id"
repositoryIDapiPathV1Latest = "api/activitypub/repository-id"
)
// Factory function for RepositoryID. Created struct is asserted to be valid.
func NewRepositoryID(uri, source string) (RepositoryID, error) {
result, err := newActorID(uri)
if err != nil {
return RepositoryID{}, err
}
result.Source = source
// validate Person specific
repoID := RepositoryID{result}
if valid, err := validation.IsValid(repoID); !valid {
return RepositoryID{}, err
}
return repoID, nil
}
func (id RepositoryID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...)
if id.Source == "forgejo" {
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
if strings.ToLower(id.Path) != repositoryIDapiPathV1 && strings.ToLower(id.Path) != repositoryIDapiPathV1Latest {
result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", id.Path))
}
}
return result
}

View file

@ -1,45 +0,0 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewRepositoryId(t *testing.T) {
var sut, expected RepositoryID
var err error
setting.AppURL = "http://localhost:3000/"
expected = RepositoryID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = ""
expected.Host = "localhost"
expected.HostPort = 3000
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://localhost:3000/1"
_, err = NewRepositoryID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
require.EqualError(t, err, "Validation Error: forgefed.RepositoryID: path: \"api/v1/activitypub/user-id\" has to be a repo specific api path")
expected = RepositoryID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/activitypub/repository-id"
expected.Host = "localhost"
expected.HostPort = 3000
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://localhost:3000/api/activitypub/repository-id/1"
sut, err = NewRepositoryID("http://localhost:3000/api/activitypub/repository-id/1", "forgejo")
require.NoError(t, err)
assert.Equal(t, expected, sut)
}

View file

@ -4,71 +4,258 @@
package forgefed
import (
"reflect"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"forgejo.org/modules/setting"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func TestActorNew(t *testing.T) {
sut, err := NewActorID("https://an.other.forgejo.host/api/v1/activitypub/user-id/5")
require.NoError(t, err)
assert.Equal(t, ActorID{
ID: "5",
HostSchema: "https",
Path: "api/v1/activitypub/user-id",
Host: "an.other.forgejo.host",
HostPort: 443,
UnvalidatedInput: "https://an.other.forgejo.host/api/v1/activitypub/user-id/5",
IsPortSupplemented: true,
}, sut)
func TestNewPersonId(t *testing.T) {
expected := PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = true
expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
sut, err = NewActorID("https://an.other.forgejo.host/api/v1/activitypub/actor")
require.NoError(t, err)
assert.Equal(t, ActorID{
ID: "actor",
HostSchema: "https",
Path: "api/v1/activitypub",
Host: "an.other.forgejo.host",
HostPort: 443,
UnvalidatedInput: "https://an.other.forgejo.host/api/v1/activitypub/actor",
IsPortSupplemented: true,
}, sut)
sut, _ := NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
sut, err = NewActorID("https://an.other.gts.host/users/me")
require.NoError(t, err)
assert.Equal(t, ActorID{
ID: "me",
HostSchema: "https",
Path: "users",
Host: "an.other.gts.host",
HostPort: 443,
UnvalidatedInput: "https://an.other.gts.host/users/me",
IsPortSupplemented: true,
}, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 80
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://an.other.host:80/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("http://an.other.host:80/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("HTTPS://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
}
func TestNewRepositoryId(t *testing.T) {
setting.AppURL = "http://localhost:3000/"
expected := RepositoryID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/activitypub/repository-id"
expected.Host = "localhost"
expected.HostPort = 3000
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://localhost:3000/api/activitypub/repository-id/1"
sut, _ := NewRepositoryID("http://localhost:3000/api/activitypub/repository-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
}
func TestActorIdValidation(t *testing.T) {
sut := ActorID{}
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/"
result := sut.Validate()
assert.Len(t, result, 1)
assert.Equal(t, "ID should not be empty", result[0])
if sut.Validate()[0] != "userId should not be empty" {
t.Errorf("validation error expected but was: %v\n", sut.Validate())
}
sut = ActorID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action"
result = sut.Validate()
assert.Len(t, result, 1)
assert.Equal(t, "not all input was parsed, \nUnvalidated Input:\"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" \nParsed URI: \"https://an.other.host/api/v1/activitypub/user-id/1\"", result[0])
if sut.Validate()[0] != "not all input was parsed, \nUnvalidated Input:\"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" \nParsed URI: \"https://an.other.host/api/v1/activitypub/user-id/1\"" {
t.Errorf("validation error expected but was: %v\n", sut.Validate()[0])
}
}
func TestPersonIdValidation(t *testing.T) {
sut := PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "path"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/path/1"
_, err := validation.IsValid(sut)
if validation.IsErrNotValid(err) && strings.Contains(err.Error(), "path: \"path\" has to be a person specific api path\n") {
t.Errorf("validation error expected but was: %v\n", err)
}
sut = PersonID{}
sut.ID = "1"
sut.Source = "forgejox"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
if sut.Validate()[0] != "Field Source contains the value forgejox, which is not in allowed subset [forgejo gitea]" {
t.Errorf("validation error expected but was: %v\n", sut.Validate()[0])
}
}
func TestWebfingerId(t *testing.T) {
sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
if sut.AsWebfinger() != "@12345@codeberg.org" {
t.Errorf("wrong webfinger: %v", sut.AsWebfinger())
}
sut, _ = NewPersonID("https://Codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
if sut.AsWebfinger() != "@12345@codeberg.org" {
t.Errorf("wrong webfinger: %v", sut.AsWebfinger())
}
}
func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
var err any
_, err = NewPersonID("", "forgejo")
if err == nil {
t.Error("empty input should be invalid.")
}
_, err = NewPersonID("http://localhost:3000/api/v1/something", "forgejo")
if err == nil {
t.Error("localhost uris are not external")
}
_, err = NewPersonID("./api/v1/something", "forgejo")
if err == nil {
t.Error("relative uris are not allowed")
}
_, err = NewPersonID("http://1.2.3.4/api/v1/something", "forgejo")
if err == nil {
t.Error("uri may not be ip-4 based")
}
_, err = NewPersonID("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo")
if err == nil {
t.Error("uri may not be ip-6 based")
}
_, err = NewPersonID("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo")
if err == nil {
t.Error("uri may not contain relative path elements")
}
_, err = NewPersonID("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err == nil {
t.Error("uri may not contain unparsed elements")
}
_, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err != nil {
t.Errorf("this uri should be valid but was: %v", err)
}
}
func Test_PersonMarshalJSON(t *testing.T) {
sut := ForgePerson{}
sut.Type = "Person"
sut.PreferredUsername = ap.NaturalLanguageValuesNew()
sut.PreferredUsername.Set("en", ap.Content("MaxMuster"))
result, _ := sut.MarshalJSON()
if string(result) != "{\"type\":\"Person\",\"preferredUsername\":\"MaxMuster\"}" {
t.Errorf("MarshalJSON() was = %q", result)
}
}
func Test_PersonUnmarshalJSON(t *testing.T) {
expected := &ForgePerson{
Actor: ap.Actor{
Type: "Person",
PreferredUsername: ap.NaturalLanguageValues{
ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")},
},
},
}
sut := new(ForgePerson)
err := sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
x, _ := expected.MarshalJSON()
y, _ := sut.MarshalJSON()
if !reflect.DeepEqual(x, y) {
t.Errorf("UnmarshalJSON() expected: %q got: %q", x, y)
}
expectedStr := strings.ReplaceAll(strings.ReplaceAll(`{
"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"type":"Person",
"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatar/fa7f9c4af2a64f41b1bef292bf872614"},
"url":"https://federated-repo.prod.meissa.de/stargoose9",
"inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/inbox",
"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/outbox",
"preferredUsername":"stargoose9",
"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10#main-key",
"owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBoj...XAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`,
"\n", ""),
"\t", "")
err = sut.UnmarshalJSON([]byte(expectedStr))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
result, _ := sut.MarshalJSON()
if expectedStr != string(result) {
t.Errorf("UnmarshalJSON() expected: %q got: %q", expectedStr, result)
}
}
func TestForgePersonValidation(t *testing.T) {
sut := new(ForgePerson)
sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}

View file

@ -1,4 +1,4 @@
// Copyright 2023, 2025 The Forgejo Authors. All rights reserved.
// Copyright 2023 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed

View file

@ -1,68 +0,0 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"time"
user_model "forgejo.org/models/user"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ForgeFollow activity data type
// swagger:model
type ForgeUserActivityNote struct {
// swagger.ignore
ap.Object
}
func NewForgeUserActivityNoteFromAp(item ap.Item) (ForgeUserActivityNote, error) {
result := ForgeUserActivityNote{}
object := item.(*ap.Object)
result.Object = *object
if valid, err := validation.IsValid(result); !valid {
return ForgeUserActivityNote{}, err
}
return result, nil
}
// TODO: Unused - might be removed
func newNote(doer *user_model.User, content, id string, published time.Time) (ForgeUserActivityNote, error) {
note := ForgeUserActivityNote{}
note.Type = ap.NoteType
note.AttributedTo = ap.IRI(doer.APActorID())
note.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content(content),
},
}
note.ID = ap.IRI(id)
note.Published = published
note.URL = ap.IRI(id)
note.To = ap.ItemCollection{
ap.IRI("https://www.w3.org/ns/activitystreams#Public"),
}
note.CC = ap.ItemCollection{
ap.IRI(doer.APActorID() + "/followers"),
}
if valid, err := validation.IsValid(note); !valid {
return ForgeUserActivityNote{}, err
}
return note, nil
}
func (note ForgeUserActivityNote) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(note.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(note.Type), []any{"Note"}, "type")...)
result = append(result, validation.ValidateNotEmpty(note.Content.String(), "content")...)
result = append(result, validation.ValidateIDExists(note.URL, "url")...)
return result
}

View file

@ -1,28 +0,0 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func Test_UserActivityNoteValidation(t *testing.T) {
sut := ForgeUserActivityNote{}
sut.Type = "Note"
sut.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
}
sut.URL = ap.IRI("example.org/user-id/57")
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}

View file

@ -35,8 +35,6 @@ type ServeHeaderOptions struct {
Filename string
CacheDuration time.Duration // defaults to 5 minutes
LastModified time.Time
AdditionalHeaders http.Header
RedirectStatusCode int
}
// ServeSetHeaders sets necessary content serve headers
@ -84,12 +82,6 @@ func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
}
if opts.AdditionalHeaders != nil {
for k, v := range opts.AdditionalHeaders {
header[k] = v
}
}
}
// ServeData download file from io.Reader

View file

@ -260,11 +260,11 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
if opts.Mode == internal.CodeSearchModeUnion {
query := bleve.NewDisjunctionQuery()
for _, field := range strings.Fields(opts.Keyword) {
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false, 1.0))
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false))
}
keywordQuery = query
} else {
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false, 1.0)
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false)
}
if len(opts.RepoIDs) > 0 {

View file

@ -29,12 +29,11 @@ func MatchQuery(matchTerm, field, analyzer string, fuzziness int) *query.MatchQu
}
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool, boost float64) *query.MatchPhraseQuery {
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool) *query.MatchPhraseQuery {
q := bleve.NewMatchPhraseQuery(matchPhrase)
q.FieldVal = field
q.Analyzer = analyzer
q.SetAutoFuzziness(autoFuzzy)
q.SetBoost(boost)
return q
}

View file

@ -23,7 +23,7 @@ import (
const (
issueIndexerAnalyzer = "issueIndexer"
issueIndexerDocType = "issueIndexerDocType"
issueIndexerLatestVersion = 5
issueIndexerLatestVersion = 4
)
const unicodeNormalizeName = "unicodeNormalize"
@ -69,7 +69,6 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
docMapping.AddFieldMappingsAt("is_public", boolFieldMapping)
docMapping.AddFieldMappingsAt("index", numberFieldMapping)
docMapping.AddFieldMappingsAt("title", textFieldMapping)
docMapping.AddFieldMappingsAt("content", textFieldMapping)
docMapping.AddFieldMappingsAt("comments", textFieldMapping)
@ -164,15 +163,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
q := bleve.NewBooleanQuery()
for _, token := range tokens {
innerQ := bleve.NewDisjunctionQuery(
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy, 2.0),
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy, 1.0),
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, token.Fuzzy, 1.0))
if issueID, err := token.ParseIssueReference(); err == nil {
idQuery := inner_bleve.NumericEqualityQuery(issueID, "index")
idQuery.SetBoost(5.0)
innerQ.AddQuery(idQuery)
}
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy),
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy),
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, token.Fuzzy))
switch token.Kind {
case internal.BoolOptMust:

View file

@ -5,7 +5,6 @@ package db
import (
"context"
"strconv"
"forgejo.org/models/db"
issue_model "forgejo.org/models/issues"
@ -72,17 +71,6 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
)),
),
)
term := options.Keyword
if term[0] == '#' || term[0] == '!' {
term = term[1:]
}
if issueID, err := strconv.ParseInt(term, 10, 64); err == nil {
cond = builder.Or(
builder.Eq{"`index`": issueID},
cond,
)
}
}
opt, err := ToDBOptions(ctx, options)

View file

@ -18,7 +18,7 @@ import (
)
const (
issueIndexerLatestVersion = 2
issueIndexerLatestVersion = 1
// multi-match-types, currently only 2 types are used
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
esMultiMatchTypeBestFields = "best_fields"
@ -56,8 +56,7 @@ const (
"repo_id": { "type": "long", "index": true },
"is_public": { "type": "boolean", "index": true },
"index": { "type": "long", "index": true },
"title": { "type": "text", "index": true },
"title": { "type": "text", "index": true },
"content": { "type": "text", "index": true },
"comments": { "type" : "text", "index": true },
@ -156,25 +155,21 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
return nil, err
}
for _, token := range tokens {
innerQ := elastic.NewMultiMatchQuery(token.Term, "content", "comments").FieldWithBoost("title", 2.0).TieBreaker(0.5)
innerQ := elastic.NewMultiMatchQuery(token.Term, "title", "content", "comments")
if token.Fuzzy {
// If the term is not a phrase use fuzziness set to AUTO
innerQ = innerQ.Type(esMultiMatchTypeBestFields).Fuzziness(esFuzzyAuto)
} else {
innerQ = innerQ.Type(esMultiMatchTypePhrasePrefix)
}
var eitherQ elastic.Query = innerQ
if issueID, err := token.ParseIssueReference(); err == nil {
indexQ := elastic.NewTermQuery("index", issueID).Boost(15.0)
eitherQ = elastic.NewDisMaxQuery().Query(indexQ).Query(innerQ).TieBreaker(0.5)
}
switch token.Kind {
case internal.BoolOptMust:
q.Must(eitherQ)
q.Must(innerQ)
case internal.BoolOptShould:
q.Should(eitherQ)
q.Should(innerQ)
case internal.BoolOptNot:
q.MustNot(eitherQ)
q.MustNot(innerQ)
}
}
query.Must(q)

View file

@ -14,7 +14,6 @@ type IndexerData struct {
ID int64 `json:"id"`
RepoID int64 `json:"repo_id"`
IsPublic bool `json:"is_public"` // If the repo is public
Index int64 `json:"index"`
// Fields used for keyword searching
Title string `json:"title"`

View file

@ -5,7 +5,6 @@ package internal
import (
"io"
"strconv"
"strings"
)
@ -23,14 +22,6 @@ type Token struct {
Fuzzy bool
}
func (tk *Token) ParseIssueReference() (int64, error) {
term := tk.Term
if term[0] == '#' || term[0] == '!' {
term = term[1:]
}
return strconv.ParseInt(term, 10, 64)
}
type Tokenizer struct {
in *strings.Reader
}

View file

@ -549,55 +549,6 @@ var cases = []*testIndexerCase{
}), result.Total)
},
},
{
Name: "Index",
SearchOptions: &internal.SearchOptions{
Keyword: "13",
SortBy: internal.SortByScore,
RepoIDs: []int64{5},
},
ExpectedIDs: []int64{93}, // 93 = #13 in repo 5
ExpectedTotal: 1,
},
{
Name: "Index with prefix",
SearchOptions: &internal.SearchOptions{
Keyword: "#13",
SortBy: internal.SortByScore,
RepoIDs: []int64{5},
},
ExpectedIDs: []int64{93},
ExpectedTotal: 1,
},
{
Name: "Index and title boost",
ExtraData: []*internal.IndexerData{
{ID: 1001, Title: "re #13", RepoID: 5},
{ID: 1002, Title: "re #1001", Content: "leave 13 alone. - 13", RepoID: 5},
},
SearchOptions: &internal.SearchOptions{
Keyword: "!13",
SortBy: internal.SortByScore,
RepoIDs: []int64{5},
},
ExpectedIDs: []int64{93, 1001, 1002},
ExpectedTotal: 3,
},
{
Name: "Index exclude",
ExtraData: []*internal.IndexerData{
{ID: 1001, Index: 101, Title: "Brrr", RepoID: 5},
{ID: 1002, Index: 102, Title: "Brrr", Content: "Brrr", RepoID: 5},
{ID: 1003, Index: 103, Title: "Brrr", RepoID: 5},
{ID: 1004, Index: 104, Title: "Brrr", RepoID: 5},
},
SearchOptions: &internal.SearchOptions{
Keyword: "Brrr -101 -103",
SortBy: internal.SortByScore,
},
ExpectedIDs: []int64{1002, 1004},
ExpectedTotal: 2,
},
{
Name: "SortByCreatedDesc",
SearchOptions: &internal.SearchOptions{
@ -790,7 +741,6 @@ func generateDefaultIndexerData() []*internal.IndexerData {
data = append(data, &internal.IndexerData{
ID: id,
Index: issueIndex,
RepoID: repoID,
IsPublic: repoID%2 == 0,
Title: fmt.Sprintf("issue%d of repo%d", issueIndex, repoID),

View file

@ -95,7 +95,6 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
return &internal.IndexerData{
ID: issue.ID,
RepoID: issue.RepoID,
Index: issue.Index,
IsPublic: !issue.Repo.IsPrivate,
Title: issue.Title,
Content: issue.Content,

View file

@ -84,13 +84,6 @@ func ParseImageConfig(mt string, r io.Reader) (*Metadata, error) {
func parseOCIImageConfig(r io.Reader) (*Metadata, error) {
var image oci.Image
if err := json.NewDecoder(r).Decode(&image); err != nil {
// Handle empty config blobs (common in OCI artifacts)
if err == io.EOF {
return &Metadata{
Type: TypeOCI,
Platform: DefaultPlatform,
}, nil
}
return nil, err
}

View file

@ -4,7 +4,6 @@
package container
import (
"io"
"strings"
"testing"
@ -61,49 +60,3 @@ func TestParseImageConfig(t *testing.T) {
assert.Equal(t, projectURL, metadata.ProjectURL)
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
}
func TestParseImageConfigEmptyBlob(t *testing.T) {
t.Run("Empty config blob (EOF)", func(t *testing.T) {
// Test empty reader (simulates empty config blob common in OCI artifacts)
metadata, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader(""))
require.NoError(t, err)
assert.Equal(t, TypeOCI, metadata.Type)
assert.Equal(t, DefaultPlatform, metadata.Platform)
assert.Empty(t, metadata.Description)
assert.Empty(t, metadata.Authors)
assert.Empty(t, metadata.Labels)
assert.Empty(t, metadata.Manifests)
})
t.Run("Empty JSON object", func(t *testing.T) {
// Test minimal valid JSON config
metadata, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader("{}"))
require.NoError(t, err)
assert.Equal(t, TypeOCI, metadata.Type)
assert.Equal(t, DefaultPlatform, metadata.Platform)
assert.Empty(t, metadata.Description)
assert.Empty(t, metadata.Authors)
})
t.Run("Invalid JSON still returns error", func(t *testing.T) {
// Test that actual JSON errors (not EOF) are still returned
_, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader("{invalid json"))
require.Error(t, err)
assert.NotEqual(t, io.EOF, err)
})
t.Run("OCI artifact with empty config", func(t *testing.T) {
// Test OCI artifact scenario with minimal config
configOCI := `{"config": {}}`
metadata, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader(configOCI))
require.NoError(t, err)
assert.Equal(t, TypeOCI, metadata.Type)
assert.Equal(t, DefaultPlatform, metadata.Platform)
assert.Empty(t, metadata.Description)
assert.Empty(t, metadata.Authors)
assert.Empty(t, metadata.ImageLayers)
})
}

View file

@ -69,11 +69,8 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
// insert units for repo
defaultUnits := unit.DefaultRepoUnits
switch {
case isFork:
if isFork {
defaultUnits = unit.DefaultForkRepoUnits
case repo.IsMirror:
defaultUnits = unit.DefaultMirrorRepoUnits
}
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
for _, tp := range defaultUnits {

View file

@ -1,5 +1,4 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
@ -53,7 +52,6 @@ var (
DisabledRepoUnits []string
DefaultRepoUnits []string
DefaultForkRepoUnits []string
DefaultMirrorRepoUnits []string
PrefixArchiveFiles bool
DisableMigrations bool
DisableStars bool
@ -177,7 +175,6 @@ var (
DisabledRepoUnits: []string{},
DefaultRepoUnits: []string{},
DefaultForkRepoUnits: []string{},
DefaultMirrorRepoUnits: []string{},
PrefixArchiveFiles: true,
DisableMigrations: false,
DisableStars: false,

View file

@ -56,7 +56,7 @@ var SSH = struct {
Domain: "",
Port: 22,
ServerCiphers: []string{"chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"},
ServerKeyExchanges: []string{"mlkem768x25519-sha256", "curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
ServerMACs: []string{"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1"},
KeygenPath: "",
MinimumKeySizeCheck: true,

View file

@ -3,10 +3,6 @@
package structs
import (
"time"
)
// ActionRunJob represents a job of a run
// swagger:model
type ActionRunJob struct {
@ -27,54 +23,3 @@ type ActionRunJob struct {
// the action run job status
Status string `json:"status"`
}
// ActionRun represents an action run
// swagger:model
type ActionRun struct {
// the action run id
ID int64 `json:"id"`
// the action run's title
Title string `json:"title"`
// the repo this action is part of
Repo *Repository `json:"repository"`
// the name of workflow file
WorkflowID string `json:"workflow_id"`
// a unique number for each run of a repository
Index int64 `json:"index_in_repo"`
// the user that triggered this action run
TriggerUser *User `json:"trigger_user"`
// the cron id for the schedule trigger
ScheduleID int64
// the commit/tag/… the action run ran on
PrettyRef string `json:"prettyref"`
// has the commit/tag/… the action run ran on been deleted
IsRefDeleted bool `json:"is_ref_deleted"`
// the commit sha the action run ran on
CommitSHA string `json:"commit_sha"`
// If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow.
IsForkPullRequest bool `json:"is_fork_pull_request"`
// may need approval if it's a fork pull request
NeedApproval bool `json:"need_approval"`
// who approved this action run
ApprovedBy int64 `json:"approved_by"`
// the webhook event that causes the workflow to run
Event string `json:"event"`
// the payload of the webhook event that causes the workflow to run
EventPayload string `json:"event_payload"`
// the trigger event defined in the `on` configuration of the triggered workflow
TriggerEvent string `json:"trigger_event"`
// the current status of this run
Status string `json:"status"`
// when the action run was started
Started time.Time `json:"started,omitempty"`
// when the action run was stopped
Stopped time.Time `json:"stopped,omitempty"`
// when the action run was created
Created time.Time `json:"created,omitempty"`
// when the action run was last updated
Updated time.Time `json:"updated,omitempty"`
// how long the action run ran for
Duration time.Duration `json:"duration,omitempty"`
// the url of this action run
HTMLURL string `json:"html_url"`
}

View file

@ -119,7 +119,6 @@ var (
_ Payloader = &RepositoryPayload{}
_ Payloader = &ReleasePayload{}
_ Payloader = &PackagePayload{}
_ Payloader = &ActionPayload{}
)
// _________ __
@ -485,36 +484,3 @@ type PackagePayload struct {
func (p *PackagePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// _ _ _
// / \ ___| |_(_) ___ _ __
// / _ \ / __| __| |/ _ \| '_ \
// / ___ \ (__| |_| | (_) | | | |
// /_/ \_\___|\__|_|\___/|_| |_|
// this name is ridiculous, yes
// it's the sub-type of hook that has something to do with Forgejo Actions
type HookActionAction string
const (
HookActionFailure HookActionAction = "failure"
HookActionRecover HookActionAction = "recover"
HookActionSuccess HookActionAction = "success"
)
// ActionPayload payload for action webhooks
type ActionPayload struct {
Action HookActionAction `json:"action"`
Run *ActionRun `json:"run"`
// the status of this run before it completed
// this must be a not done status
PriorStatus string `json:"prior_status"`
// the last run for the same workflow
// could be nil when Run is the first for it's workflow
LastRun *ActionRun `json:"last_run,omitempty"`
}
// JSONPayload return payload information
func (p *ActionPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}

View file

@ -32,23 +32,3 @@ type ActionTaskResponse struct {
Entries []*ActionTask `json:"workflow_runs"`
TotalCount int64 `json:"total_count"`
}
// ActionRun represents an ActionRun
type RepoActionRun struct {
ID int64 `json:"id"`
Name string `json:"name"`
RunNumber int64 `json:"run_number"`
Event string `json:"event"`
Status string `json:"status"`
HeadBranch string `json:"head_branch"`
HeadSHA string `json:"head_sha"`
WorkflowID string `json:"workflow_id"`
URL string `json:"url"`
TriggeringActor *User `json:"triggering_actor"`
}
// ListActionRunResponse return a list of ActionRun
type ListRepoActionRunResponse struct {
Entries []*RepoActionRun `json:"workflow_runs"`
TotalCount int64 `json:"total_count"`
}

View file

@ -75,11 +75,6 @@ func IsValidExternalURL(uri string) bool {
return true
}
// IsValidReleaseAssetURL checks if the URL is valid for external release assets
func IsValidReleaseAssetURL(uri string) bool {
return IsValidURL(uri)
}
// IsValidExternalTrackerURLFormat checks if URL matches required syntax for external trackers
func IsValidExternalTrackerURLFormat(uri string) bool {
if !IsValidExternalURL(uri) {

View file

@ -4,7 +4,6 @@
package webhook
// HookEvents is a set of web hook events
// update TestCreateWebhook in models/webhook/webhook_test.go when adding or changing values here
type HookEvents struct {
Create bool `json:"create"`
Delete bool `json:"delete"`
@ -27,12 +26,9 @@ type HookEvents struct {
Repository bool `json:"repository"`
Release bool `json:"release"`
Package bool `json:"package"`
ActionRunFailure bool `json:"action_run_failure"`
ActionRunRecover bool `json:"action_run_recover"`
ActionRunSuccess bool `json:"action_run_success"`
}
// HookEvent represents events that will deliver a hook.
// HookEvent represents events that will delivery hook.
type HookEvent struct {
PushOnly bool `json:"push_only"`
SendEverything bool `json:"send_everything"`

View file

@ -7,7 +7,6 @@ package webhook
type HookEventType string
// Types of hook events
// update TestCreateWebhook in models/webhook/webhook_test.go when adding or changing values here
const (
HookEventCreate HookEventType = "create"
HookEventDelete HookEventType = "delete"
@ -34,9 +33,6 @@ const (
HookEventPackage HookEventType = "package"
HookEventSchedule HookEventType = "schedule"
HookEventWorkflowDispatch HookEventType = "workflow_dispatch"
HookEventActionRunFailure HookEventType = "action_run_failure"
HookEventActionRunRecover HookEventType = "action_run_recover"
HookEventActionRunSuccess HookEventType = "action_run_success"
)
// Event returns the HookEventType as an event string
@ -69,12 +65,6 @@ func (h HookEventType) Event() string {
return "repository"
case HookEventRelease:
return "release"
case HookEventActionRunFailure:
return "action_run_failure"
case HookEventActionRunRecover:
return "action_run_recover"
case HookEventActionRunSuccess:
return "action_run_success"
}
return ""
}

View file

@ -2915,13 +2915,6 @@ comment.blocked_by_user = Komentování není možné, protože jste byli zablok
sync_fork.branch_behind_few = Tato větev je %[1]d revizí pozadu za %[2]s
sync_fork.button = Synchronizovat
sync_fork.branch_behind_one = Tato větev je %[1]d revizi pozadu za %[2]s
settings.event_action_failure = Selhání
settings.event_action_failure_desc = Běh akce selhal.
settings.event_action_recover = Obnovit
settings.event_action_success = Úspěch
settings.event_action_success_desc = Běh akce byl úspěšný.
settings.event_header_action = Události běhu akce
settings.event_action_recover_desc = Běh akce byl úspěšný, předchozí běh akce ve stejném workflow selhal.
[graphs]
component_loading_info = Tohle může chvíli trvat…

View file

@ -10,7 +10,7 @@ logo = Logo
sign_in = Login
sign_in_with_provider = Login med %s
sign_in_or = eller
sign_out = Log ud
sign_out = Logud
sign_up = Register
return_to_forgejo = Vend tilbage til Forgejo
new_repo.title = Ny repository
@ -1432,7 +1432,7 @@ issues.new.no_items = Ingen elementer
issues.new.milestone = Milepæl
issues.new.no_milestone = Ingen milepæl
issues.filter_assignees = Filter tildelt
issues.filter_milestones = Filter milepæl
issues.filter_milestones = Filter Milepæl
issues.filter_projects = Filter projekt
issues.filter_labels = Filter etiket
issues.filter_reviewers = Filter anmelder
@ -2018,7 +2018,7 @@ settings.lfs_pointers.inRepo = i depot
settings.lfs_pointers.exists = Eksisterer i lager
settings.lfs_pointers.accessible = Tilgængeligt for bruger
signing.wont_sign.not_signed_in = Du er ikke logget ind.
wiki.welcome = Velkommen til wikien
wiki.welcome = Velkommen til Wikien
milestones.modify = Opdater milepæl
milestones.edit_success = Milepæl "%s" er blevet opdateret.
milestones.filter_sort.least_issues = Mindst problemer
@ -2262,7 +2262,7 @@ settings.wiki_delete_notices_1 = - Dette vil permanent slette og deaktivere depo
settings.wiki_branch_rename_failure = Det lykkedes ikke at normalisere depotwikiens filialnavn.
settings.add_collaborator_duplicate = Samarbejdspartneren er allerede føjet til dette depot.
settings.add_collaborator_owner = Kan ikke tilføje en ejer som samarbejdspartner.
settings.collaborator_deletion = Fjern samarbejdspartner
settings.collaborator_deletion = Fjern Samarbejdspartner
settings.collaborator_deletion_desc = Fjernelse af en samarbejdspartner vil tilbagekalde deres adgang til dette depot. Vil du fortsætte?
settings.add_team_duplicate = Teamet har allerede depotet
settings.add_collaborator_blocked_our = Samarbejdspartneren kan ikke tilføjes, fordi depots ejer har blokeret dem.
@ -2728,13 +2728,6 @@ comment.blocked_by_user = Det er ikke muligt at kommentere, fordi du er blokeret
sync_fork.branch_behind_few = Denne gren er %[1]d commits bag %[2]s
sync_fork.button = Sync
sync_fork.branch_behind_one = Denne gren er %[1]d commit bag %[2]s
settings.event_header_action = Handling Run-begivenheder
settings.event_action_failure = Mislykket
settings.event_action_success_desc = Handlingen blev udført.
settings.event_action_success = Success
settings.event_action_recover_desc = Handlingskørsel lykkedes efter at den sidste handlingskørsel i samme arbejdsgang mislykkedes.
settings.event_action_failure_desc = Handlingskørsel sluttede som en fejl.
settings.event_action_recover = Gendan
[notification]
watching = Overvåger
@ -3536,8 +3529,8 @@ composer.install = For at installere pakken ved hjælp af Composer skal du køre
container.multi_arch = OS / Arch
rubygems.required.ruby = Kræver Ruby version
swift.install = Tilføj pakken i din <code>Package.swift</code>-fil:
settings.link.select = Vælg depot
settings.link.button = Opdater depot link
settings.link.select = Vælg Depot
settings.link.button = Opdater Depot Link
settings.link.error = Kunne ikke opdatere depotlinket.
owner.settings.cargo.initialize.success = Cargo-indekset blev oprettet.
owner.settings.cargo.rebuild.description = Genopbygning kan være nyttig, hvis indekset ikke er synkroniseret med de lagrede Cargo-pakker.

View file

@ -745,7 +745,7 @@ social=Soziale Konten
applications=Anwendungen
orgs=Organisationen
repos=Repositorys
delete=Account löschen
delete=Konto löschen
twofa=Zwei-Faktor-Authentifizierung (TOTP)
account_link=Verknüpfte Benutzerkonten
organization=Organisationen
@ -1511,7 +1511,7 @@ projects.card_type.images_and_text=Bilder und Text
projects.card_type.text_only=Nur Text
issues.desc=Verwalte Bug-Reports, Aufgaben und Meilensteine.
issues.filter_assignees=Verantwortliche filtern
issues.filter_assignees=Filter
issues.filter_milestones=Meilenstein filtern
issues.filter_projects=Projekt filtern
issues.filter_labels=Label filtern
@ -4031,7 +4031,7 @@ repo_kind = Repos suchen …
user_kind = Benutzer suchen …
org_kind = Orgs suchen …
team_kind = Teams suchen …
code_kind = Code durchsuchen
code_kind = Code suchen…
package_kind = Pakete suchen …
project_kind = Projekte suchen …
branch_kind = Branches suchen …

View file

@ -2486,13 +2486,6 @@ settings.event_pull_request_review_request_desc = Pull request review requested
settings.event_pull_request_approvals = Pull request approvals
settings.event_pull_request_merge = Pull request merge
settings.event_pull_request_enforcement = Enforcement
settings.event_header_action = Action Run events
settings.event_action_failure = Failure
settings.event_action_failure_desc = Action Run ended as failure.
settings.event_action_recover = Recover
settings.event_action_recover_desc = Action Run succeeded after last Action Run in the same workflow failed.
settings.event_action_success = Success
settings.event_action_success_desc = Action Run succeeded.
settings.event_package = Package
settings.event_package_desc = Package created or deleted in a repository.
settings.branch_filter = Branch filter
@ -2985,6 +2978,8 @@ teams.invite_team_member.list = Pending invitations
teams.delete_team_title = Delete team
teams.delete_team_desc = Deleting a team revokes repository access from its members. Continue?
teams.delete_team_success = The team has been deleted.
teams.read_permission_desc = This team grants <strong>Read</strong> access: members can view and clone team repositories.
teams.write_permission_desc = This team grants <strong>Write</strong> access: members can read from and push to team repositories.
teams.admin_permission_desc = This team grants <strong>Administrator</strong> access: members can read from, push to and add collaborators to team repositories.
teams.create_repo_permission_desc = Additionally, this team grants <strong>Create repository</strong> permission: members can create new repositories in organization.
teams.repositories = Team repositories

View file

@ -103,7 +103,7 @@ ok = Bone
download_logs = Elsuti protokolojn
unknown = Nekonata
issues = Eraroj
error404 = Aŭ tiu ĉi paĝo <strong>ne ekzistas</strong>, <strong>estis forigita</strong> aŭ <strong>vi ne rajtas</strong> vidi ĝin.
error404 = Aŭ tiu ĉi paĝo <strong>ne ekzistas</strong> aŭ <strong>vi ne rajtas</strong> vidi ĝin.
retry = Reprovi
activities = Aktivecoj
confirm_delete_selected = Konfirmi forigon de ĉiu elektito?
@ -171,7 +171,6 @@ table_modal.placeholder.header = Kapo
table_modal.placeholder.content = Enhavo
table_modal.label.rows = Horizontaloj
table_modal.label.columns = Vertikaloj
link_modal.description = Priskribo
[aria]
navbar = Esplora breto
@ -524,7 +523,6 @@ totp_enrolled.text_1.has_webauthn = Vi ĵus aktivigis TOTP-n por via konto. Tio
totp_enrolled.text_1.no_webauthn = Vi ĵus aktivigis TOTP-n por via konto. Tio volas diri ke por ĉiuj venontaj salutoj al via konto, vi devos uzi TOTP-n kiel 2FA metodo.
removed_security_key.no_2fa = Ne estas aliaj 2FA agorditaj metodoj, tio estas ke ne plus necesas uzi 2FA-n por saluti.
totp_disabled.no_2fa = Ne estas plu aliaj 2FA agorditaj metodoj, tio estas ke ne plus necesas uzi 2FA-n por saluti.
account_security_caution.text_1 = Se tio estis vi, vi povas sekure ignori ĉi tiun retmesaĝon.
[form]
TeamName = Gruponomo
@ -863,30 +861,30 @@ npm.details.tag = Etikedo
[search]
search = Serĉi
search = Serĉi...
regexp = RegEsp
milestone_kind = Serĉi celojn...
code_search_by_git_grep = Nunaj rezultoj de kodoserĉo estas provizitaj de "git grep". Eble estas plibonaj rezultoj se la retejestro aktivigas la indeksilon de kodo.
code_search_unavailable = Kodoserĉo ne haveblas nune. Bonvolu kontakti la retejestron.
package_kind = Serĉi pakojn
package_kind = Serĉi pakojn...
type_tooltip = Serĉotipo
user_kind = Serĉi uzantojn
user_kind = Serĉi uzantojn...
fuzzy_tooltip = Inkluzivas rezultojn proksime kongruantajn kun la serĉoterminoj
repo_kind = Serĉi deponejojn
org_kind = Serĉi organizaĵojn
code_kind = Serĉi kodon
project_kind = Serĉi projektojn
team_kind = Serĉi teamojn
repo_kind = Serĉi deponejojn...
org_kind = Serĉi organizaĵojn...
code_kind = Serĉi kodon...
project_kind = Serĉi projektojn...
team_kind = Serĉi teamojn...
keyword_search_unavailable = Serĉo per ŝlosilvortoj ne haveblas nune. Bonvolu kontakti la retejestron.
union = Ŝlosilvortoj
union_tooltip = Inkluzivas rezultojn kongruantajn kun la ajnaj blankaspacitaj ŝlosilvortoj
commit_kind = Serĉi enmetojn
commit_kind = Serĉi enmetojn...
no_results = Ne trovis kongruantajn rezultojn.
exact = Ĝusta
exact_tooltip = Inkluzivas nur rezultojn kongruantajn kun la ĝustaj serĉoterminoj
issue_kind = Serĉi erarojn...
regexp_tooltip = Interpretas la serĉoterminoj kiel regulesprimo
fuzzy = Svaga
branch_kind = Serĉi disbranĉigojn
branch_kind = Serĉi disbranĉigojn...
runner_kind = Serĉi rulantojn...
pull_kind = Serĉi tirpetojn...

View file

@ -8,7 +8,7 @@ sign_in=Kirjaudu sisään
sign_in_or=tai
sign_out=Kirjaudu ulos
sign_up=Rekisteröidy
link_account=Linkitä tili
link_account=Yhdistä tili
register=Rekisteröidy
version=Versio
powered_by=Voimanlähteenä %s
@ -23,7 +23,7 @@ toc=Sisällysluettelo
licenses=Lisenssit
return_to_forgejo=Palaa Forgejohon
username=Käyttäjänimi
username=Käyttäjätunnus
email=Sähköpostiosoite
password=Salasana
access_token=Pääsypoletti
@ -31,7 +31,7 @@ re_type=Vahvista salasana
captcha=CAPTCHA
twofa=Kaksivaiheinen todennus
twofa_scratch=Kaksivaiheinen kertakäyttöinen koodi
passcode=Pääsykoodi
passcode=Tunnuskoodi
webauthn_insert_key=Aseta turva-avaimesi
webauthn_sign_in=Paina turva-avaimesi painiketta. Jos turva-avaimessasi ei ole painiketta, irrota se ja aseta uudelleen.
@ -40,7 +40,7 @@ webauthn_use_twofa=Käytä kaksivaihesta todennusta puhelimestasi
webauthn_error=Turva-avainta ei voitu lukea.
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen.
webauthn_error_insecure=WebAuthn tukee vain suojattuja yhteyksiä. Testatessa HTTP-yhteydellä 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 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_empty=Sinun täytyy asettaa nimi tälle avaimelle.
@ -228,22 +228,22 @@ report_message = Jos uskot tämän olevan Forgejon virhe, etsi ongelmia <a href=
app_desc=Kivuton, itsehostattu Git-palvelu
install=Helppo asentaa
platform=Alustariippumaton
platform_desc=Forgejo on mahdollista suorittaa Linuxin ja FreeBSD:n kaltaisissa vapaissa käyttöjärjestelmissä, ja se toimii eri suoritinarkkitehtuureilla. Valitse omasi!
platform_desc=Forgejo on mahdollista suorittaa vapaissa käyttöjärjestelmissä kuten Linux ja FreeBSD, ja se toimii eri suoritinarkkitehtuureilla. Valitse omasi!
lightweight=Kevyt
lightweight_desc=Forgejolla on vähäiset vähimmäisvaatimukset, joten se toimii jopa halvassa Raspberry Pi:ssä. Säästä koneesi energiaa!
license=Avoin lähdekoodi
license_desc=Mene ja lataa <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Liity tekemään <a target="_blank" rel="noopener noreferrer" href="%[2]s">projektista</a> entistäkin parempi. Älä ujostele avustamista!
install_desc = <a target="_blank" rel="noopener noreferrer" href="%[1]s">Suorita alustallesi tarkoitettu binääritiedosto</a>, <a target="_blank" rel="noopener noreferrer" href="%[2]s">kontita se</a>, tai <a target="_blank" rel="noopener noreferrer" href="%[3]s">hanki se paketoituna</a>.
install_desc = <a target="_blank" rel="noopener noreferrer" href="%[1]s">Suorita alustallesi sopiva binääritiedosto</a>, <a target="_blank" rel="noopener noreferrer" href="%[2]s">kontita se</a>, tai <a target="_blank" rel="noopener noreferrer" href="%[3]s">hanki se paketoituna</a>.
[install]
install=Asennus
title=Aloitusasetukset
docker_helper=Jos suoritat Forgejoa kontitettuna, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a>, ennen kuin muutat yhtäkään asetusta.
docker_helper=Jos ajat Forgejoa Dockerin sisällä, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a> ennen minkään asetuksen muuttamista.
require_db_desc=Forgejo tarvitsee toimiakseen MySQL-, PostgreSQL-, SQLite3- tai TiDB- (MySQL-protokolla) tietokannan.
db_title=Tietokannan asetukset
db_type=Tietokannan tyyppi
host=Isäntä
user=Käyttäjänimi
user=Käyttäjätunnus
password=Salasana
db_name=Tietokannan nimi
db_schema=Skeema
@ -259,8 +259,8 @@ err_empty_db_path=SQLite3-tietokannan polku ei voi olla tyhjä.
no_admin_and_disable_registration=Et voi kytkeä rekisteröintiä pois luomatta sitä ennen ylläpitotiliä.
err_empty_admin_password=Ylläpitäjän salasana ei voi olla tyhjä.
err_empty_admin_email=Ylläpitäjän sähköpostiosoite ei voi olla tyhjä.
err_admin_name_is_reserved=Ylläpitäjän käyttäjänimi on virheellinen; käyttäjänimi on varattu
err_admin_name_is_invalid=Ylläpitäjän käyttäjänimi on virheellinen
err_admin_name_is_reserved=Ylläpitäjän käyttäjätunnus on virheellinen; käyttäjätunnus on varattu
err_admin_name_is_invalid=Ylläpitäjän käyttäjätunnus on virheellinen
general_title=Yleiset asetukset
app_name=Instanssin otsikko
@ -286,7 +286,7 @@ smtp_addr=SMTP-isäntä
smtp_port=SMTP-portti
smtp_from=Lähetä sähköpostit osoitteella
smtp_from_helper=Sähköpostiosoite, jota Forgejo käyttää. Kirjoita pelkkä sähköpostiosoite tai "Nimi” <email@example.com> -muodossa.
mailer_user=SMTP-käyttäjänimi
mailer_user=SMTP-käyttäjätunnus
mailer_password=SMTP-salasana
register_confirm=Vaadi sähköpostinvahvistus rekisteröinnin edellytykseksi
mail_notify=Ota sähköposti-ilmoitukset käyttöön
@ -326,7 +326,7 @@ default_keep_email_private.description=Piilota oletusarvoisesti uusien käyttäj
default_enable_timetracking=Ota ajanseuranta oletusarvoisesti käyttöön
default_enable_timetracking.description=Salli ajanseuranta-ominaisuuden käyttöönotto oletuksena uusille tietovarastoille.
no_reply_address=Piilotetun sähköpostin toimialue
no_reply_address_helper=Verkkotunnuksen nimi käyttäjille, joilla on piilotettu sähköpostiosoite. Esimerkiksi käyttäjänimi 'joe' kirjataan Git-palveluun nimellä 'joe@noreply.example.org' jos piilotetun sähköpostiosoitteen arvoksi on asetettu 'noreply.example.org'.
no_reply_address_helper=Verkkotunnuksen nimi käyttäjille, joilla on piilotettu sähköpostiosoite. Esimerkiksi käyttäjätunnus 'joe' kirjataan Git-palveluun nimellä 'joe@noreply.example.org' jos piilotetun sähköpostiosoitteen arvoksi on asetettu 'noreply.example.org'.
password_algorithm=Salasanan hajautusalgoritmi
enable_update_checker_helper_forgejo = Se tarkistaa väliajoin uusia Forgejo-versioita tutkimalla TXT DNS -tietueen osoitteesta release.forgejo.org .
invalid_admin_setting = Ylläpitotilin asetukset eivät kelpaa: %v
@ -354,7 +354,7 @@ smtp_from_invalid = "Lähetä sähköpostit osoitteella"-osoite on epäkelvollin
err_admin_name_pattern_not_allowed = Ylläpitäjän käyttäjänimi on epäkelpo, se vastaa varattua kaavaa
[home]
uname_holder=käyttäjänimi tai sähköpostiosoite
uname_holder=Käyttäjätunnus tai sähköpostiosoite
password_holder=Salasana
switch_dashboard_context=Vaihda kojelaudan kontekstia
my_repos=Tietovarastot
@ -410,10 +410,10 @@ remember_me=Muista tämä laite
forgot_password_title=Unohtuiko salasana
forgot_password=Unohtuiko salasana?
sign_up_now=Tarvitsetko tilin? Rekisteröidy nyt.
confirmation_mail_sent_prompt=Uusi vahvistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa saamaasi linkkiä seuraavan %s aikana viimeistelläksesi rekisteröinnin. Mikäli annettu sähköpostiosoite on väärin, voit kirjautua sisään ja pyytää uutta vahvistussähköpostia toiseen osoitteeseen.
confirmation_mail_sent_prompt=Uusi varmistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa saamaasi linkkiä seuraavan %s aikana viimeistelläksesi rekisteröinnin. Mikäli annettu sähköpostiosoite on väärin, voit kirjautua sisään ja pyytää uutta varmistussähköpostia toiseen osoitteeseen.
must_change_password=Vaihda salasanasi
allow_password_change=Vaadi käyttäjää vaihtamaan salasanansa (suositeltava)
reset_password_mail_sent_prompt=Vahvistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa annettua linkkiä seuraavan %s aikana saadaksesi tilin palauttamisen valmiiksi.
reset_password_mail_sent_prompt=Varmistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa annettua linkkiä seuraavan %s aikana saadaksesi tilin palauttamisen valmiiksi.
active_your_account=Aktivoi tilisi
account_activated=Tili on aktivoitu
prohibit_login=Tili on jäädytetty
@ -431,7 +431,7 @@ verify=Vahvista
scratch_code=Kertakäyttökoodi
use_scratch_code=Käytä kertakäyttökoodia
twofa_scratch_used=Olet käyttänyt kertakäyttökoodisi. Sinut on uudelleenohjattu kaksivaiheisen kirjautumisen asetussivulle, jotta voit kytkeä sen pois tai luoda uuden kertakäyttökoodin.
twofa_passcode_incorrect=Pääsykoodi on väärä. Jos olet hukannut laitteesi, käytäthän kertakäyttökoodia sisäänkirjautumiseen.
twofa_passcode_incorrect=Salasanasi on väärä. Jos olet hukannut laitteesi, käytäthän kertakäyttökoodia sisäänkirjautumiseen.
twofa_scratch_token_incorrect=Kertakäyttökoodisi on virheellinen.
login_userpass=Kirjaudu sisään
tab_openid=OpenID
@ -440,7 +440,7 @@ oauth_signup_title=Viimeistele uusi tili
oauth_signup_submit=Viimeistele tili
oauth_signin_tab=Linkitä olemassa olevaan tiliin
oauth_signin_title=Kirjaudu sisään valtuuttaaksesi linkitetyn tilin
oauth_signin_submit=Linkitä tili
oauth_signin_submit=Yhdistä tiliin
oauth.signin.error.access_denied=Valtuutuspyyntö on evätty.
openid_connect_submit=Yhdistä
openid_connect_title=Yhdistä olemassa olevaan tiliin
@ -483,7 +483,7 @@ prohibit_login_desc = Tilisi käyttö instanssin kanssa on estetty. Ota yhteytt
[mail]
view_it_on=Näytä %s
link_not_working_do_paste=Eikö linkki toimi? Kopioi ja liitä se selaimesi osoiteriville.
link_not_working_do_paste=Eikö linkki toimi? Yritä kopioida ja liittää se selaimesi osoitepalkkiin.
hi_user_x=Hei <b>%s</b>,
activate_account=Ole hyvä ja aktivoi tilisi
@ -491,7 +491,7 @@ activate_account=Ole hyvä ja aktivoi tilisi
activate_email=Vahvista sähköpostiosoitteesi
register_notify=Tervetuloa %s-palveluun
register_notify.text_2=Voit nyt kirjautua tilillesi käyttäjänimellä: %s
register_notify.text_2=Voit nyt kirjautua tilillesi käyttäjätunnuksella: %s
reset_password=Palauta käyttäjätili
reset_password.title=%s, olet pyytänyt tilisi palauttamista
@ -517,7 +517,7 @@ removed_security_key.subject = Turva-avain on poistettu
removed_security_key.text_1 = Turva-avain "%[1]s" on poistettu tililtäsi.
team_invite.text_2 = Napsauta seuraavaa linkkiä liittyäksesi tiimiin:
activate_account.text_1 = Hei <b>%[1]s</b>, kiitos kun rekisteröidyit palveluun %[2]s!
activate_account.text_2 = Aktivoi tilisi napsauttamalla alla olevaa linkkiä aikaikkunan <b>%s</b> sisällä:
activate_account.text_2 = Aktivoidaksesi tilin, napsauta alla olevaa linkkiä aikaikkunan <b>%s</b> sisällä:
totp_disabled.subject = TOTP on poistettu käytöstä
primary_mail_change.subject = Ensisijainen sähköpostiosoitteesi on vaihdettu
admin.new_user.user_info = Käyttäjätiedot
@ -570,7 +570,7 @@ modify=Päivitä
confirm = Vahvista
[form]
UserName=Käyttäjänimi
UserName=Käyttäjätunnus
RepoName=Tietovaraston nimi
Email=Sähköpostiosoite
Password=Salasana
@ -601,14 +601,14 @@ captcha_incorrect=CAPTCHA-koodi on virheellinen.
password_not_match=Salasanat eivät täsmää.
lang_select_error=Valitse kieli listalta.
username_been_taken=Käyttäjänimi on jo varattu.
username_been_taken=Käyttäjätunnus on jo varattu.
repo_name_been_taken=Tietovaraston nimi on jo käytössä.
repository_force_private=Pakotettu yksityisyys käytössä: yksityisiä tietovarastoja ei voida muuttaa julkisiksi.
org_name_been_taken=Organisaation nimi on jo käytössä.
team_name_been_taken=Tiimin nimi on jo varattu.
email_been_used=Sähköpostiosoite on jo käytössä.
email_invalid=Sähköpostiosoite on virheellinen.
username_password_incorrect=Käyttäjänimi tai salasana on virheellinen.
username_password_incorrect=Käyttäjätunnus tai salasana on virheellinen.
password_lowercase_one=Ainakin yksi pieni kirjan
password_uppercase_one=Ainakin yksi iso kirjain
password_digit_one=Ainakin yksi numero
@ -663,10 +663,6 @@ org_still_own_repo = Organisaatio omistaa yhden tai useamman tietovaraston. Pois
org_still_own_packages = Organisaatio omistaa yhden tai useamman paketin. Poista ne ensin.
team_no_units_error = Salli pääsy vähintään yhteen tietovaraston osioon.
repository_files_already_exist.adopt_or_delete = Tässä tietovarastossa on jo tiedostoja. Omaksu ne itsellesi tai poista ne.
username_change_not_local_user = Ei-paikallisten käyttäjien ei sallita vaihtaa käyttäjänimeä.
admin_cannot_delete_self = Et voi poistaa itseäsi, kun olet ylläpitäjä. Poista ensin ylläpito-oikeudet itseltäsi.
username_claiming_cooldown = Käyttäjänimeä ei voi ottaa käyttöön, koska siihen kohdistuva suojaamisjakso ei ole vielä päättynyt. Käyttäjänimen voi ottaa käyttöön %[1]s.
email_domain_is_not_allowed = Käyttäjän sähköpostiosoitteen <b>%s</b> verkkotunnus on ristiriidassa EMAIL_DOMAIN_ALLOWLIST:in tai EMAIL_DOMAIN_BLOCKLIST:in kanssa. Varmista, että olen asettanut sähköpostiosoitteen oikein.
[user]
@ -698,11 +694,11 @@ unblock = Poista esto
following_one = %d seurataan
block_user.detail = Huomaa, että käyttäjän estämisellä on muita vaikutuksia, kuten:
show_on_map = Näytä paikka kartalla
form.name_chars_not_allowed = Käyttäjänimi "%s" sisältää virheellisiä merkkejä.
form.name_chars_not_allowed = Käyttäjätunnus "%s" sisältää virheellisiä merkkejä.
follow_blocked_user = Et voi seurata tätä käyttäjää, koska olet estänyt kyseisen käyttäjän tai kyseinen käyttäjä on estänyt sinut.
disabled_public_activity = Käyttäjä on poistanut käytöstä toiminnan julkisen näkyvyyden.
form.name_reserved = Käyttäjänimi "%s" on varattu.
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu käyttäjänimessä.
form.name_reserved = Käyttäjätunnus "%s" on varattu.
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu käyttäjätunnuksessa.
public_activity.visibility_hint.admin_private = Aktiivisuus on näkyvissä sinulle, koska olet ylläpitäjä, mutta käyttäjä haluaa pitää aktiivisuutensa yksityisenä.
public_activity.visibility_hint.self_private_profile = Aktiivisuutesi on näkyvissä vain sinulle ja instanssin ylläpitäjille, koska profiilisi on yksityinen. <a href="%s">Määritä</a>.
watched = Tarkaillut tietovarastot
@ -731,7 +727,7 @@ organization=Organisaatiot
webauthn=Kaksivaiheinen todennus (Turva-avaimet)
public_profile=Julkinen profiili
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjänimeään. Ota yhteys sivuston ylläpitoon 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
website=Verkkosivusto
location=Sijainti
@ -740,14 +736,14 @@ update_profile=Päivitä profiili
update_language=Vaihda kieli
update_language_success=Kieli on päivitetty.
update_profile_success=Profiilisi on päivitetty.
change_username=Käyttäjänimesi on muutettu.
change_username=Käyttäjätunnuksesi on muutettu.
continue=Jatka
cancel=Peruuta
language=Kieli
ui=Teema
hidden_comment_types=Piilotetut kommenttityypit
comment_type_group_reference=Viittaus
comment_type_group_label=Nimilappu
comment_type_group_label=Tunniste
comment_type_group_milestone=Merkkipaalu
comment_type_group_assignee=Osoitettu henkilölle
comment_type_group_title=Otsikko
@ -892,10 +888,10 @@ twofa_enrolled=Tiliisi on otettu käyttöön kaksivaiheinen todennus. Ota kertak
webauthn_nickname=Nimimerkki
manage_account_links=Linkitetyt tilit
manage_account_links=Yhdistetyt tilit
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo-tiliisi.
link_account=Linkitä tili
remove_account_link=Poista linkitetty tili
link_account=Yhdistä tili
remove_account_link=Poista yhdistetty tili
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tilin kautta. Jatketaanko?
remove_account_link_success=Linkitetty tili on poistettu.
@ -972,14 +968,14 @@ webauthn_alternative_tip = Saatat haluta määrittää lisätodennusmenetelmän.
twofa_disable = Poista kaksivaiheinen todennus käytöstä
twofa_disable_desc = Kaksivaiheisen todennuksen poistaminen asettaa tilisi aiempaa suurempaan uhkaan. Jatketaanko?
update_language_not_found = Kieli "%s" ei ole käytettävissä.
change_username_prompt = Huomio: Käyttäjänimen vaihtaminen muuttaa myös tilisi URL-osoitteen.
change_username_prompt = Huomio: Käyttäjätunnuksen vaihtaminen muuttaa myös tilisi URL-osoitteen.
oauth2_client_secret_hint = Tätä salaisuutta ei näytetä uudelleen, kun olet poistunut sivulta tai päivittänyt sivun. Varmista, että olet ottanut salaisuuden talteen.
blocked_since = Estetty %s lähtien
user_unblock_success = Käyttäjän esto on poistettu.
oauth2_redirect_uris = Uudelleenohjaus-URI:t. Käytä uutta riviä (newline) jokaista URI:a kohden.
oauth2_client_secret = Asiakkaan salaisuus
verify_ssh_key_success = SSH-avain "%s" on vahvistettu.
change_username_redirect_prompt = Vanha käyttäjänimi uudelleenohjaa, kunnes joku muu ottaa käyttäjänimen käyttöönsä.
change_username_redirect_prompt = Vanha käyttäjätunnus uudelleenohjaa, kunnes joku muu ottaa käyttäjätunnuksen käyttönsä.
uploaded_avatar_is_too_big = Lähetetyn tiedoston koko (%d KiB) ylittää enimmäiskoon (%d KiB).
ssh_key_been_used = Tämä SSH-avain on jo lisätty palvelimelle.
verify_gpg_key_success = GPG-avain "%s" on vahvistettu.
@ -1027,16 +1023,9 @@ keep_pronouns_private = Näytä pronominit vain tunnistautuneille käyttäjille
keep_pronouns_private.description = Tämä piilottaa pronominisi käyttäjiltä, jotka eivät ole kirjautuneet sisään.
comment_type_group_issue_ref = Ongelmaviittaus
twofa_scratch_token_regenerated = Kertakäyttöinen palautusavaimesi on nyt %s. Talleta se turvalliseen sijaintiin, koska sitä ei näytetä uudelleen.
change_username_redirect_prompt.with_cooldown.few = Vanha käyttäjänimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjänimen itsellesi suojaamisjakson aikana.
change_username_redirect_prompt.with_cooldown.few = Vanha käyttäjätunnus on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjätunnuksen itsellesi suojaamisjakson aikana.
additional_repo_units_hint_description = Näytä "Ota lisää käyttöön"-vihje tietovarastoissa, missä kaikki saatavilla olevat yksiköt eivät ole käytössä.
change_username_redirect_prompt.with_cooldown.one = Vanha käyttäjänimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjänimen itsellesi suojaamisjakson aikana.
gpg_key_matched_identities = Vastaavat identiteetit:
delete_token_success = Pääsypoletti on poistettu. Sitä käyttävillä sovelluksilla ei ole enää pääsyä tilillesi.
ssh_externally_managed = Tämän käyttäjän SSH-avainta hallitaan ulkoisesti
passcode_invalid = Virheellinen pääsykoodi. Yritä uudelleen.
then_enter_passcode = Kirjoita sovelluksessa näkyvä pääsykoodi:
gpg_key_matched_identities_long = Tähän avaimeen upotetut identiteetit vastaavat tämän käyttäjän seuraavia aktivoituja sähköpostiosoitteita. Kommitit, jotka vastaavat näitä sähköpostiosoitteita, voidaan vahvistaa tällä avaimella.
twofa_failed_get_secret = Salaisuuden saaminen epäonnistui.
change_username_redirect_prompt.with_cooldown.one = Vanha käyttäjätunnus on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjätunnuksen itsellesi suojaamisjakson aikana.
[repo]
owner=Omistaja
@ -1059,8 +1048,8 @@ download_tar=Lataa TAR.GZ
repo_desc=Kuvaus
repo_lang=Kieli
repo_gitignore_helper=Valitse .gitignore-mallit
issue_labels=Nimilaput
issue_labels_helper=Valitse nimilappujoukko
issue_labels=Tunnisteet
issue_labels_helper=Valitse tunnistejoukko
license=Lisenssi
license_helper=Valitse lisenssitiedosto
readme=README
@ -1085,14 +1074,14 @@ template.git_hooks=Git-koukut
template.webhooks=Webkoukut
template.topics=Aiheet
template.avatar=Profiilikuva
template.issue_labels=Ongelmanimilaput
template.issue_labels=Ongelmatunnisteet
migrate_items=Migraation kohteet
migrate_items_wiki=Wiki
migrate_items_milestones=Merkkipaalut
migrate_items_labels=Nimilaput
migrate_items_labels=Tunnisteet
migrate_items_issues=Ongelmat
migrate_items_pullrequests=Vetopyynnöt
migrate_items_releases=Julkaisut
@ -1129,7 +1118,7 @@ issues=Ongelmat
pulls=Vetopyynnöt
project_board=Projektit
packages=Paketit
labels=Nimilaput
labels=Tunnisteet
milestones=Merkkipaalut
commits=Kommitit
@ -1140,7 +1129,7 @@ released_this=julkaisi tämän
file_raw=Raaka
file_history=Historia
file_view_raw=Näytä raaka
file_permalink=Pysyväislinkki
file_permalink=Pysyvä linkki
video_not_supported_in_browser=Selaimesi ei tue HTML5:n video-tagia.
audio_not_supported_in_browser=Selaimesi ei tue HTML5:n audio-tagia.
@ -1212,9 +1201,9 @@ issues.desc=Ongelmien, tehtävien ja merkkipaalujen hallinta.
issues.filter_assignees=Suodata käyttäjiä
issues.filter_milestones=Suodata merkkipaalu
issues.new=Uusi ongelma
issues.new.labels=Nimilaput
issues.new.no_label=Ei nimilappuja
issues.new.clear_labels=Tyhjennä nimilaput
issues.new.labels=Tunnisteet
issues.new.no_label=Ei tunnisteita
issues.new.clear_labels=Tyhjennä tunnisteet
issues.new.projects=Projektit
issues.new.no_items=Ei kohteita
issues.new.milestone=Merkkipaalu
@ -1229,11 +1218,11 @@ issues.choose.open_external_link=Avaa
issues.choose.blank=Oletus
issues.no_ref=Haaraa/tagia ei määritelty
issues.create=Luo ongelma
issues.new_label=Uusi nimilappu
issues.new_label_placeholder=Nimilapun nimi
issues.new_label=Uusi tunniste
issues.new_label_placeholder=Tunnisteen nimi
issues.new_label_desc_placeholder=Kuvaus
issues.create_label=Luo nimilappu
issues.label_templates.helper=Valitse nimilapun esiasetus
issues.create_label=Luo tunniste
issues.label_templates.helper=Valitse tunnisteen esiasetus
issues.add_milestone_at=`lisäsi tämän merkkipaaluun <b>%s</b> %s`
issues.change_milestone_at=`vaihtoi merkkipaalun <b>%s</b> merkkipaaluun <b>%s</b> %s`
issues.remove_milestone_at=`poisti tämän <b>%s</b> merkkipaalusta %s`
@ -1243,9 +1232,9 @@ issues.deleted_project=`(poistettu)`
issues.self_assign_at=`itse otti tämän käsittelyyn %s`
issues.change_title_at=`muutti otsikon <b><strike>%s</strike></b> otsikoksi <b>%s</b> %s`
issues.delete_branch_at=`poisti haaran <b>%s</b> %s`
issues.filter_label=Nimilappu
issues.filter_label_exclude=`Käytä <code>alt</code> + <code>napsautus/rivinvaihto</code> poissulkeaksesi nimilappuja`
issues.filter_label_no_select=Kaikki nimilaput
issues.filter_label=Tunniste
issues.filter_label_exclude=`Käytä <code>alt</code> + <code>klikkaus/rivinvaihto</code> poissulkeaksesi tunnisteita`
issues.filter_label_no_select=Kaikki tunnisteet
issues.filter_milestone=Merkkipaalu
issues.filter_project=Projekti
issues.filter_assignee=Käsittelijä
@ -1263,15 +1252,15 @@ issues.filter_sort.recentupdate=Äskettäin päivitetty
issues.filter_sort.leastupdate=Kauiten aikaa sitten päivitetty
issues.filter_sort.mostcomment=Eniten kommentoidut
issues.filter_sort.leastcomment=Vähiten kommentoidut
issues.filter_sort.nearduedate=Lähin eräpäivä
issues.filter_sort.farduedate=Kaukaisin eräpäivä
issues.filter_sort.nearduedate=Lähin määräpäivä
issues.filter_sort.farduedate=Kaukaisin määräpäivä
issues.filter_sort.moststars=Eniten tähtiä
issues.filter_sort.feweststars=Vähiten tähtiä
issues.filter_sort.mostforks=Eniten forkattu
issues.filter_sort.fewestforks=Vähiten forkattu
issues.action_open=Avaa
issues.action_close=Sulje
issues.action_label=Nimilappu
issues.action_label=Tunniste
issues.action_milestone=Merkkipaalu
issues.action_milestone_no_select=Ei merkkipaalua
issues.action_assignee=Osoitettu henkilölle
@ -1302,15 +1291,15 @@ issues.role.member=Jäsen
issues.edit=Muokkaa
issues.cancel=Peruuta
issues.save=Tallenna
issues.label_title=Nimi
issues.label_title=Tunnisteen nimi
issues.label_description=Kuvaus
issues.label_color=Väri
issues.label_count=%d nimilappua
issues.label_color=Tunnisteen väri
issues.label_count=%d tunnistetta
issues.label_open_issues=%d avointa ongelmaa/vetopyyntöä
issues.label_edit=Muokkaa
issues.label_delete=Poista
issues.label_modify=Muokkaa nimilappua
issues.label_deletion=Poista nimilappu
issues.label_modify=Muokkaa tunnistetta
issues.label_deletion=Poista tunniste
issues.label.filter_sort.alphabetically=Aakkosjärjestyksessä
issues.label.filter_sort.reverse_alphabetically=Käänteisessä aakkosjärjestyksessä
issues.label.filter_sort.by_size=Pienin koko
@ -1345,13 +1334,13 @@ issues.add_time_hours=Tuntia
issues.add_time_minutes=Minuuttia
issues.add_time_sum_to_small=Aikaa ei syötetty.
issues.time_spent_from_all_authors=`Käytetty kokonaisaika: %s`
issues.due_date=Eräpäivä
issues.due_date=Määräpäivä
issues.push_commit_1=lisäsi %d kommitin %s
issues.push_commits_n=lisäsi %d kommittia %s
issues.due_date_form=vvvv-kk-pp
issues.due_date_form_edit=Muokkaa
issues.due_date_form_remove=Poista
issues.due_date_not_set=Eräpäivää ei ole asetettu.
issues.due_date_not_set=Määräpäivää ei ole asetettu.
issues.due_date_overdue=Myöhässä
issues.dependency.title=Riippuvuudet
issues.dependency.issue_no_dependencies=Riippuvuuksia ei ole asetettu.
@ -1405,13 +1394,13 @@ pulls.can_auto_merge_desc=Tämä vetopyyntö voidaan yhdistää automaattisesti.
milestones.new=Uusi merkkipaalu
milestones.closed=Suljettu %s
milestones.no_due_date=Ei eräpäivää
milestones.no_due_date=Ei määräpäivää
milestones.open=Avaa uudelleen
milestones.close=Sulje
milestones.create=Luo merkkipaalu
milestones.title=Otsikko
milestones.desc=Kuvaus
milestones.due_date=Eräpäivä (valinnainen)
milestones.due_date=Määräpäivä (valinnainen)
milestones.clear=Tyhjennä
milestones.edit=Muokkaa merkkipaalua
milestones.cancel=Peruuta
@ -1422,7 +1411,7 @@ milestones.filter_sort.least_issues=Vähiten ongelmia
wiki=Wiki
wiki.welcome=Tervetuloa wikiin.
wiki.welcome=Tervetuloa Wikiin.
wiki.welcome_desc=Wikissä voit kirjoittaa ja jakaa dokumentaatiota käyttäjien kesken.
wiki.create_first_page=Luo ensimmäinen sivu
wiki.page=Sivu
@ -1533,9 +1522,9 @@ settings.update_githook=Päivitä koukku
settings.payload_url=Kohde-URL
settings.http_method=HTTP-menetelmä
settings.secret=Salaisuus
settings.slack_username=Käyttäjänimi
settings.slack_username=Käyttäjätunnus
settings.slack_icon_url=Kuvakkeen URL-osoite
settings.discord_username=Käyttäjänimi
settings.discord_username=Käyttäjätunnus
settings.event_desc=Laukaisu päällä:
settings.event_send_everything=Kaikki tapahtumat
settings.event_choose=Mukautetut tapahtumat…
@ -1555,7 +1544,7 @@ settings.event_issues=Muokkaus
settings.event_issues_desc=Ongelma avattu, suljettu, avattu uudelleen tai muokattu.
settings.event_issue_assign=Toimeksianto
settings.event_issue_assign_desc=Ongelma osoitettu tai osoitus poistettu.
settings.event_issue_label_desc=Ongelmanimilaput lisätty tai poistettu.
settings.event_issue_label_desc=Ongelmatunnisteet lisätty tai poistettu.
settings.event_issue_milestone_desc=Merkkipaalu lisätty, poistettu tai muokattu.
settings.event_issue_comment_desc=Ongelman kommentti luotu, muokattu tai poistettu.
settings.event_header_pull_request=Vetopyyntöjen tapahtumat
@ -1755,7 +1744,7 @@ release.detail = Julkaisun tiedot
diff.hide_file_tree = Piilota tiedostopuu
issues.role.owner_helper = Tämä käyttäjä on tämän tietovaraston omistaja.
issues.all_title = Kaikki
issues.label_archived_filter = Näytä arkistoidut nimilaput
issues.label_archived_filter = Näytä arkistoidut tunnisteet
pulls.close = Sulje vetopyyntö
branch.already_exists = Haara nimellä "%s" on jo olemassa.
diff.show_file_tree = Näytä tiedostopuu
@ -1804,7 +1793,7 @@ milestones.deletion_success = Merkkipaalu on poistettu.
project = Projektit
pulls.delete.title = Poistetaanko tämä vetopyyntö?
activity.title.issues_1 = %d ongelma
contributors.contribution_type.filter_label = Kontribuution tyyppi:
contributors.contribution_type.filter_label = Avustuksen tyyppi:
settings.protected_branch.delete_rule = Poista sääntö
settings.archive.success = Tietovarasto arkistoitiin onnistuneesti.
diff.comment.placeholder = Jätä kommentti
@ -1908,7 +1897,7 @@ pulls.expand_files = Laajenna kaikki tiedostot
issues.content_history.delete_from_history = Poista historiasta
milestones.filter_sort.name = Nimi
issues.filter_milestone_all = Kaikki merkkipaalut
issues.filter_label_select_no_label = Ei nimilappua
issues.filter_label_select_no_label = Ei tunnistetta
projects.column.set_default = Aseta oletukseksi
projects.edit_success = Projekti "%s" on päivitetty.
desc.sha256 = SHA256
@ -1953,7 +1942,7 @@ settings.branches.update_default_branch = Päivitä oletushaara
settings.transfer.success = Tietovaraston siirto onnistui.
settings.transfer_abort = Peru siirto
settings.sync_mirror = Synkronoi nyt
settings.mirror_settings.docs.doc_link_title = Kuinka peilaan tietovarastoja?
settings.mirror_settings.docs.doc_link_title = Kuinka peilaan tietovarastot?
tag.create_tag_operation = Luo tagi
branch.rename = Nimeä haara "%s" uudelleen
branch.download = Lataa haara "%s"
@ -2027,9 +2016,9 @@ migrate.git.description = Suorita tietovaraston migraatio mistä tahansa Git-pal
migrate.gitlab.description = Tee migraatio gitlab.comista tai muista GitLab-instansseista.
migrate.gitea.description = Tee migraatio gitea.comista tai muista Gitea-instansseista.
repo_gitignore_helper_desc = Valitse mitä tiedostoja ei seurata yleisimpien kielten mallipohjista. Tyypilliset artefaktit, joita eri kielten koostamistyökalut tuottavat, lisätään .gitignore-tiedostoon oletusarvoisesti.
milestones.filter_sort.latest_due_date = Kaukaisin eräpäivä
milestones.filter_sort.latest_due_date = Kaukaisin määräpäivä
license_helper_desc = Lisenssi määrää, mitä muut voivat ja eivät voi tehdä koodillasi. Etkö ole varma, mikä lisenssi soveltuu projektillesi? Lue <a target="_blank" rel="noopener noreferrer" href="%s">ohje lisenssin valinnasta</a>.
milestones.filter_sort.earliest_due_data = Lähin eräpäivä
milestones.filter_sort.earliest_due_data = Lähin määräpäivä
issues.filter_type.reviewed_by_you = Katselmoitu toimestasi
settings.units.overview = Yleisnäkymä
settings.remove_team_success = Tiimin pääsy tietovarastoon on poistettu.
@ -2196,21 +2185,21 @@ transfer.no_permission_to_accept = Sinulla ei ole oikeutta hyväksyä tätä sii
settings.web_hook_name_feishu = Feishu / Lark Suite
issues.review.reviewers = Katselmoijat
issues.new.no_reviewers = Ei katselmoijia
issues.add_label = lisäsi nimilapun %s %s
issues.due_date_added = lisäsi eräpäivän %s %s
issues.add_label = lisäsi tunnisteen %s %s
issues.due_date_added = lisäsi määräpäivän %s %s
issues.review.add_review_request = pyysi katselmointia käyttäjältä %[1]s %[2]s
issues.ref_pull_from = `<a href="%[3]s">viittasi tähän vetopyyntöön %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
pulls.commit_ref_at = `viittasi tähän vetopyyntöön kommitista <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.review.comment = katselmoi %s
issues.add_labels = lisäsi nimilaput %s %s
issues.add_labels = lisäsi tunnisteet %s %s
issues.review.add_review_requests = pyysi katselmointeja käyttäjiltä %[1]s %[2]s
pulls.blocked_by_official_review_requests = Tämä vetopyyntö on estetty, koska siltä puuttuu hyväksyntä yhdeltä tai useammalta viralliselta katselmoijalta.
issues.author.tooltip.issue = Tämä käyttäjä on tämän ongelman tekijä.
issues.author.tooltip.pr = Tämä käyttäjä on tämän vetopyynnön tekijä.
issues.role.contributor_helper = Tämä käyttäjä on aiemmin kommitoinut tähän tietovarastoon.
settings.event_pull_request_label = Nimilaput
issues.due_date_remove = poisti eräpäivän %s %s
settings.event_issue_label = Nimilaput
settings.event_pull_request_label = Tunnisteet
issues.due_date_remove = poisti määräpäivän %s %s
settings.event_issue_label = Tunnisteet
settings.authorization_header = Authorization-otsake
diff.has_escaped = Tällä rivillä on piilotettuja Unicode-merkkejä
issues.max_pinned = Et voi kiinnittää enempää ongelmia
@ -2222,8 +2211,8 @@ issues.num_reviews_few = %d katselmointia
issues.filter_no_results = Ei tuloksia
issues.filter_no_results_placeholder = Kokeile määrittää eri hakusuodattimet.
projects.edit_subheader = Projektit organisoivat ongelmia ja seuraavat edistymistä.
issues.label_templates.title = Lataa nimilapun esiasetus
issues.label_deletion_desc = Nimilapun poistaminen poistaa sen kaikista ongelmista. Jatketaanko?
issues.label_templates.title = Lataa tunnisteen esiasetus
issues.label_deletion_desc = Tunnisteen poistaminen poistaa sen kaikista ongelmista. Jatketaanko?
issues.attachment.download = `Napsauta ladataksesi "%s"`
issues.review.option.hide_outdated_comments = Piilota vanhentuneet kommentit
issues.review.show_outdated = Näytä vanhentuneet
@ -2234,8 +2223,8 @@ issues.unpin_issue = Poista ongelman kiinnitys
issues.review.outdated_description = Sisältö on muuttunut siitä ajanhetkestä, kun tämä kommentti luotiin
issues.review.option.show_outdated_comments = Näytä vanhentuneet kommentit
issues.review.outdated = Vanhentunut
issues.label_templates.use = Käytä nimilapun esiasetusta
issues.label_deletion_success = Nimilappu on poistettu.
issues.label_templates.use = Käytä tunnisteen esiasetusta
issues.label_deletion_success = Tunniste on poistettu.
issues.cancel_tracking = Hylkää
issues.choose.get_started = Aloitetaan
settings.event_fork = Forkkaus
@ -2250,7 +2239,7 @@ pulls.no_merge_wip = Tätä vetopyyntöä ei voida yhdistää, koska se on merki
pulls.clear_merge_message = Tyhjennä yhdistämisviesti
activity.title.prs_merged_by = %s yhdisti %s
settings.protect_status_check_patterns_desc = Syötä kaavat määrittääksesi, mitkä tilatarkistukset on läpäistävä, ennen kuin haarat voidaan yhdistää tätä sääntöä vastaavaan haaraan. Jokainen rivi määrittää kaavan. Kaavat eivät saa olla tyhjiä.
adopt_search = Syötä käyttäjänimi etsiäksesi omaksumattomia tietovarastoja (jätä tyhjäksi löytääksesi kaikki)
adopt_search = Syötä käyttäjänimi etsiäksesi omaksumattomia tietovarastoja (jätä tyhjäksi löytääksesi kaikki)
pulls.cmd_instruction_merge_warning = <b>Varoitus:</b> Asetusta ”Tunnista manuaalinen yhdistäminen automaattisesti” ei ole otettu käyttöön tässä tietovarastossa. Sinun on merkittävä tämä vetopyyntö manuaalisesti yhdistetyksi jälkikäteen.
pulls.cmd_instruction_merge_desc = Yhdistä muutokset ja päivitä Forgejossa.
pulls.cannot_auto_merge_desc = Tätä vetopyyntöä ei voida yhdistää automaattisesti ristiriitojen vuoksi.
@ -2327,13 +2316,13 @@ migrate_options_lfs = Tee migraatio LFS-tiedostoille
migrate_options_lfs_endpoint.label = LFS-päätepiste
commits.browse_further = Selaa kauemmas
issues.filter_projects = Suodata projekti
issues.filter_labels = Suodata nimilappu
issues.filter_labels = Suodata tunniste
commits.no_commits = Ei yhteisiä kommitteja. "%s" ja "%s" omaavat täysin eri historiat.
projects.column.deletion_desc = Projektin sarakkeen poistaminen siirtää kaikki siihen liittyvät ongelmat oletussarakkeeseen. Jatketaanko?
issues.del_time = Poista tämä aikaloki
migrated_from_fake = Suoritettu migraatio lähteestä %[1]s
migrate.migrate = Tee migraatio lähteestä %s
migrate.migrating_labels = Suoritetaan nimilappujen migraatiota
migrate.migrating_labels = Suoritetaan tunnisteiden migraatiota
file_view_rendered = Näytä renderöitynä
editor.invalid_commit_mail = Virheellinen sähköposti kommitin luomista varten.
sync_fork.branch_behind_one = Tämä haara on %[1]d kommitin jäljessä %[2]s
@ -2371,7 +2360,7 @@ pulls.is_ancestor = Tämä haara on jo sisällytetty kohdehaaraan. Yhdistettäv
pulls.blocked_by_rejection = Tämä vetopyyntö sisältää virallisen katselmoijan vaatimisia muutoksia.
pulls.status_checks_success = Kaikki tarkistukset onnistuivat
pulls.agit_explanation = Luotu käyttäen AGit-työnkulkua. AGit antaa avustajien ehdottaa muutoksia käyttämällä "git push" ilman, että uutta forkkia tai uutta haaraa luodaan.
milestones.invalid_due_date_format = Eräpäivän muodon tulee olla "yyyy-mm-dd".
milestones.invalid_due_date_format = Määräpäivän muodon tulee olla "yyyy-mm-dd".
wiki.original_git_entry_tooltip = Näytä alkuperäinen Git-tiedosto sen sijaan, että ystävällistä linkkiä käytetään.
pulls.blocked_by_approvals = Tällä vetopyynnöllä ei ole riittävästi hyväksyntöjä. %d/%d hyväksyntää myönnetty.
pulls.status_checks_hide_all = Piilota kaikki tarkistukset
@ -2404,7 +2393,7 @@ settings.trust_model.collaborator.desc = Tämän tietovaraston avustajien kelvol
settings.confirm_wiki_branch_rename = Nimeä uudelleen wikin haara
settings.event_pull_request_assign = Toimeksianto
settings.event_pull_request_assign_desc = Vetopyynnön toimeksianto luotu tai toimeksiannon osoitus poistettu.
settings.event_pull_request_label_desc = Vetopyynnön nimilappuja lisätty tai poistettu.
settings.event_pull_request_label_desc = Vetopyynnön tunnisteita lisätty tai poistettu.
settings.active = Aktiivinen
settings.packagist_api_token = API-poletti
settings.protect_whitelist_committers = Sallittujen listalla rajoitettu työntö
@ -2442,7 +2431,7 @@ settings.event_pull_request_review_request_desc = Vetopyynnön katselmointi pyyd
settings.event_pull_request_merge = Vetopyynnön yhdistäminen
settings.protect_approvals_whitelist_enabled = Rajoita hyväksynnät vain sallittujen käyttäjien tai tiimien listoilla oleviin
settings.packagist_package_url = Packagist-paketin URL-osoite
settings.packagist_username = Packagist-käyttäjänimi
settings.packagist_username = Packagist-käyttäjätunnus
settings.sourcehut_builds.manifest_path = Koontimanifestin polku
settings.event_pull_request_sync_desc = Haara päivitetty automaattisesti kohdehaaralla.
settings.trust_model.committer = Kommitoija
@ -2550,33 +2539,6 @@ form.reach_limit_of_creation_n = Omistajan %d tietovaraston rajoitus on jo täyn
form.string_too_long = Merkkijono on pidempi kuin %d merkkiä.
mirror_address_protocol_invalid = Määritetty URL-osoite on virheellinen. Vain http(s):// tai git:// -sijainteja voi käyttää peilaukseen.
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu tietovaraston nimessä.
migrate_options_lfs_endpoint.description.local = Paikallinen palvelinpolku on myös tuettu.
pulls.showing_only_single_commit = Näytetään vain kommitin %[1]s muutokset
pulls.invalid_merge_option = Et voi käyttää tätä yhdistämisvalintaa tälle vetopyynnölle.
pulls.squash_merge_pull_request = Luo squash-kommitti
issues.label_templates.info = Nimilappuja ei ole. Luo nimilappu napsauttamalla "Uusi nimilappu" tai käytä nimilapun esiasetusta:
issues.label_archive = Arkistoi nimilappu
mirror_lfs_desc = Aktivoi LFS-datan peilaaminen.
editor.directory_is_a_file = Hakemiston nimi "%s" on jo käytössä tiedoston nimenä tässä tietovarastossa.
projects.desc = Hallitse ongelmia ja vetoja projektitauluilla.
ext_issues = Ulkoiset ongelmat
issues.label_archive_tooltip = Arkistoidut nimilaput on suljettu pois ehdotuksista oletusarvoisesti, kun haku suoritetaan nimilapulla.
issues.ref_reopened_from = `<a href="%[3]s">avasi uudelleen tämän ongelman %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_closed_from = `<a href="%[3]s">sulki tämän ongelman %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
migrate_options_lfs_endpoint.description = Migraatio yrittää käyttää Git-etätietovarastoasi <a target="_blank" rel="noopener noreferrer" href="%s">LFS-palvelimen määrittämiseen</a>. Voit määrittää omavalintaisen päätepisteen, jos tietovarastosi LFS-data on talletettu jonnekin muualle.
settings.mirror_settings.docs.pull_mirror_instructions = Vetopeilin määrittämiseksi konsultoi:
issues.archived_label_description = (Arkistoitu) %s
editor.filename_is_a_directory = Tiedoston nimi "%s" on jo käytössä hakemiston nimenä tässä tietovarastossa.
pulls.fast_forward_only_merge_pull_request = Pelkkä fast-forward
pulls.rebase_merge_commit_pull_request = Rebase, luo sitten yhdistämiskommitti
pulls.rebase_merge_pull_request = Rebase, sitten fast-forward
admin.enabled_flags = Tässä tietovarastossa käytössä olevat liput:
admin.update_flags = Päivitä liput
admin.failed_to_replace_flags = Tietovaraston lippujen korvaaminen epäonnistui
admin.flags_replaced = Tietovaraston liput korvattu
admin.manage_flags = Hallitse lippuja
editor.file_is_a_symlink = `"%s" on symbolinen linkki. Symbolisia linkkejä ei voi muokata selainkäyttöliittymän editorissa`
rss.must_be_on_branch = Sinun täytyy olla haarassa saadaksesi RSS-syötteen.
@ -2705,7 +2667,6 @@ teams.add_nonexistent_repo = Tietovarasto, jota yrität lisätä, ei ole olemass
teams.repos.none = Tällä tiimillä ei ole pääsyä tietovarastoihin.
settings.change_orgname_redirect_prompt.with_cooldown.one = Vanha organisaation nimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa organisaation nimen itsellesi suojaamisjakson aikana.
settings.change_orgname_redirect_prompt.with_cooldown.few = Vanha organisaation nimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa organisaation nimen itsellesi suojaamisjakson aikana.
teams.all_repositories_helper = Tiimillä on pääsy kaikkiin tietovarastoihin. Tämän valitseminen <strong>lisää kaikki olemassa olevat</strong> tietovarastot tiimiin.
[admin]
dashboard=Kojelauta
@ -2759,7 +2720,7 @@ dashboard.gc_times=Roskienkeruuajat
users.user_manage_panel=Käyttäjätilien hallinta
users.new_account=Luo käyttäjätili
users.name=Käyttäjänimi
users.name=Käyttäjätunnus
users.full_name=Koko nimi
users.activated=Aktivoitu
users.admin=Ylläpito
@ -2893,7 +2854,7 @@ config.db_config=Tietokannan asetukset
config.db_type=Tyyppi
config.db_host=Isäntä
config.db_name=Nimi
config.db_user=Käyttäjänimi
config.db_user=Käyttäjätunnus
config.db_ssl_mode=SSL
config.db_path=Polku
@ -3396,8 +3357,6 @@ alt.repository = Tietovaraston tiedot
arch.version.replaces = Korvaa
debian.repository = Tietovaraston tiedot
conda.registry = Määritä tämä rekisteri Conda-tietovarastoksi <code>.condarc</code>-tiedostossa:
container.labels = Nimilaput
settings.link.description = Jos linkität paketin tietovarastoon, paketti listataan tietovaraston pakettilistalla.
[secrets]
creation.failed = Salaisuuden lisääminen epäonnistui.
@ -3412,7 +3371,6 @@ deletion.description = Salaisuuden poistaminen on pysyvä toimenpide, eikä sit
deletion.success = Salaisuus on poistettu.
description = Salaisuudet välitetään tietyille toimenpiteille, eikä niitä voi muuten lukea.
creation.name_placeholder = kirjoinkoolla ei merkitystä, vain aakkosnumeerisia merkkejä ja alaviivoja, ei voi alkaa GITEA_ tai GITHUB_
creation.value_placeholder = Syötä mitä tahansa sisältöä. Tyhjätila alussa ja lopussa jätetään huomiotta.
[actions]
runners.name=Nimi
@ -3447,7 +3405,7 @@ workflow.dispatch.input_required = Arvo syötteelle "%s" vaadittu.
runners.status.active = Aktiivinen
runs.no_workflows.documentation = Katso lisätietoja Forgejo Actions -ohjelmistosta <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaatiosta</a>.
variables.description = Muuttujat asetetaan tietyille toiminnoille eikä niitä voida lukea muutoin.
runners.labels = Nimilaput
runners.labels = Tunnisteet
runners.delete_runner_failed = Testinajajan poisto epäonnistui
runners.delete_runner_header = Varmista testinajajan poisto
runners.task_list.status = Tila
@ -3460,7 +3418,7 @@ runners.task_list.no_tasks = Tehtäviä ei ole vielä määritelty.
runners.last_online = Viimeisin käynnissäoloajankohta
runners.runner_title = Testinajaja
runners.task_list.done_at = Valmistunut ajankohtana
runs.no_matching_online_runner_helper = Testiajajaa nimilapulla %s ei löytynyt
runs.no_matching_online_runner_helper = Testiajajaa tunnisteella %s ei löytynyt
runs.no_results = Ei tuloksia.
runners.delete_runner = Poista testinajaja
variables.deletion.description = Muuttujan poistaminen on lopullista, eikä sitä voi perua. Jatketaanko?
@ -3507,7 +3465,6 @@ runners.status.offline = Ei-verkkotilassa
runs.no_job_without_needs = Työnkulun tulee sisältää vähintään yksi työ ilman riippuvuuksia.
runs.no_runs = Työnkululla ei ole vielä suorituksia.
variables.not_found = Muuttujaa ei löytynyt.
runs.no_workflows.help_write_access = Etkö tiedä, miten aloittaa Forgejo Actionsin käyttö? Lue <a target="_blank" rel="noopener noreferrer" href="%s">pikaopas</a> kirjoittaaksesi ensimmäisen työnkulun, sen jälkeen <a target="_blank" rel="noopener noreferrer" href="%s">määritä Forgejo-ajaja</a> suorittamaan asettamiasi töitä.
@ -3563,12 +3520,4 @@ issues.read = <b>Lue:</b> Lue ja luo ongelmia ja kommentteja.
releases.read = <b>Lue:</b> Katsele ja lataa julkaisuja.
pulls.read = <b>Lue:</b> Vetopyyntöjen lukeminen ja luominen.
ext_issues = Pääsy ulkoisen ongelmanseurannan linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
ext_wiki = Pääsy ulkoisen wikin linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
projects.read = <b>Lue:</b> Pääsy tietovaraston projektitauluille.
wiki.write = <b>Kirjoita:</b> Luo, päivitä ja poista integroidun wikin sivuja.
[markup]
filepreview.truncated = Esikatselu on typistetty
[translation_meta]
test = This is a test string. It is not displayed in Forgejo UI but is used for testing purposes. Feel free to enter "ok" to save time (or a fun fact of your choice) to hit that sweet 100% completion mark :) :) :)
ext_wiki = Pääsy ulkoisen wikin linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.

View file

@ -38,9 +38,9 @@ logo = Logo
sign_in = Mag-sign in
sign_in_with_provider = Mag-sign in gamit ang %s
sign_in_or = o
sign_out = Mag-sign out
sign_out = Mag-Sign Out
sign_up = Magrehistro
link_account = Mag-link ng account
link_account = Mag-link ng Account
template = Template
tracked_time_summary = Buod ng mga nakasubaybay na oras base sa filter ng listahan ng isyu
webauthn_sign_in = Pindutin ang button ng iyong security key. Kung walang button ang iyong security key, ilagay muli.
@ -701,7 +701,7 @@ ssh_gpg_keys = Mga SSH / GPG key
applications = Mga Aplikasyon
orgs = Ipamahala ang mga organisasyon
repos = Mga Repositoryo
delete = Burahin ang account
delete = Burahin ang Account
twofa = Authentikasyong two-factor (TOTP)
account_link = Mga naka-link na account
uid = UID
@ -1674,10 +1674,10 @@ issues.new_label = Bagong label
issues.label_templates.title = Mag-load ng isang label preset
issues.new.clear_milestone = I-clear ang milestone
issues.new.open_milestone = Mga bukas na milestone
issues.filter_milestones = I-filter ang milestone
issues.filter_projects = I-filter ang proyekto
issues.filter_labels = I-filter ang label
issues.filter_reviewers = I-filter ang tagasuri
issues.filter_milestones = I-filter ang Milestone
issues.filter_projects = I-filter ang Proyekto
issues.filter_labels = I-filter ang Label
issues.filter_reviewers = I-filter ang Tagasuri
issues.remove_labels = tinanggal ang mga label na %s %s
issues.add_remove_labels = idinagdag ang %s at tinanggal ang %s na mga label %s
issues.add_milestone_at = `idinagdag ito sa <b>%s</b> na milestone %s`
@ -1688,7 +1688,7 @@ issues.add_label = idinagdag ang %s na label %s
issues.add_labels = idinagdag ang mga label na %s %s
issues.remove_label = tinanggal ang %s na label %s
issues.desc = Ayusin ang mga ulat ng bug, gawain, at milestone.
issues.filter_assignees = I-filter ang mangangasiwa
issues.filter_assignees = I-filter ang Mangangasiwa
issues.new.labels = Mga label
issues.new.no_label = Walang mga label
issues.new.clear_labels = I-clear ang mga label
@ -1893,7 +1893,7 @@ settings.collaboration.owner = May-ari
pulls.showing_only_single_commit = Ipinapakita lamang ang mga pagbago ng commit na %[1]s
comments.edit.already_changed = Hindi maimbak ang mga pagbabago sa komento. Mukhang nabago na ng ibang tagagamit ang nilalaman. Mangyaring i-refresh ang pahina at subukang baguhin muli upang maiwasang ma-overwrite ang kanilang pagbago
milestones.completeness = <strong>%d%%</strong> nakumpleto
wiki.welcome = Maligayang pagdating sa wiki.
wiki.welcome = Maligayang pagdating sa Wiki.
wiki.create_first_page = Gawin ang unang pahina
pulls.switch_comparison_type = Ilipat ang uri ng pagkumpara
settings.collaboration.read = Basahin
@ -2278,7 +2278,7 @@ settings.add_collaborator = Magdagdag ng katulong
settings.add_collaborator_duplicate = Nadagdag na ang tagatulong na ito sa repositoryo.
settings.add_collaborator_blocked_our = Hindi madagdag ang tagatulong, dahil hinarang siya ng may-ari ng repositoryo.
settings.add_collaborator_blocked_them = Hindi madagdag ang tagatulong, dahil hinarang niya ang may-ari ng repositoryo.
settings.collaborator_deletion = Tanggalin ang tagatulong
settings.collaborator_deletion = Tanggalin ang Tagatulong
settings.team_not_in_organization = Ang koponan ay hindi nasa katulad na organisasyon sa repositoryo
settings.teams = Mga Koponan
settings.add_team_success = May access na ang koponan sa repositoryo na ito.
@ -3568,8 +3568,8 @@ npm.details.tag = Tag
swift.install = Idagdag ang package sa iyong <code>Package.swift</code> na file:
vagrant.install = Para magdagdag ng Vagrant box, patakbuhin ang sumusunod na command:
settings.link = I-link ang package na ito sa repository
settings.link.select = Pumili ng repositoryo
settings.link.button = I-update ang link ng repositoryo
settings.link.select = Pumili ng Repositoryo
settings.link.button = I-update ang Link ng Repositoryo
settings.link.error = Nabigong i-update ang link ng repositoryo.
settings.delete = Burahin ang package
owner.settings.cargo.initialize = I-initialize ang index
@ -3712,7 +3712,7 @@ runners.reset_registration_token = I-reset ang token ng pagrehistro
runners.status.offline = Offline
workflow.dispatch.invalid_input_type = Hindi wastong input type "%s".
runners.task_list.commit = Commit
runners.task_list.done_at = Natapos sa
runners.task_list.done_at = Natapos Sa
runners.reset_registration_token_success = Matagumpay na na-reset ang token ng pagrehistro ng runner
workflow.dispatch.input_required = Kumailangan ng value para sa input na "%s".
workflow.dispatch.warn_input_limit = Pinapakita lamang ang unang %d na mga input.
@ -3830,7 +3830,7 @@ deletion.success = Natanggal na ang lihim.
deletion.failed = Nabigong tanggalin ang lihim.
creation.failed = Nabigong idagdag ang lihim.
deletion = Tanggalin ang lihim
creation = Idagdag ang lihim
creation = Idagdag ang Lihim
description = Ang mga sikreto ay ipapasa sa ilang mga aksyon at hindi mababasa kung hindi.
none = Wala pang mga sikreto sa ngayon.
creation.name_placeholder = case-insensitive, alphanumeric character o underscore lamang, hindi dapat magsimula sa GITEA_ o GITHUB_
@ -3844,7 +3844,7 @@ filepreview.truncated = Na-truncate ang preview
filepreview.lines = Mga linya %[1]d hanggang %[2]d sa %[3]s
[projects]
deleted.display_name = Binurang proyekto
deleted.display_name = Binurang Proyekto
type-2.display_name = Proyekto ng repositoryo
type-1.display_name = Indibidwal na proyekto
type-3.display_name = Proyekto ng organisasyon

View file

@ -2044,7 +2044,7 @@ ext_wiki=Wiki externe
ext_wiki.desc=Lier un wiki externe.
wiki=Wiki
wiki.welcome=Bienvenue sur le wiki.
wiki.welcome=Bienvenue sur le Wiki.
wiki.welcome_desc=Le wiki vous permet d'écrire ou de partager de la documentation avec vos collaborateurs.
wiki.desc=Écrire et partager de la documentation avec vos collaborateurs.
wiki.create_first_page=Créer la première page
@ -2913,13 +2913,6 @@ pulls.editable_explanation = Cette pull request peut être éditée par les main
sync_fork.branch_behind_one = Cette branche a %[1]d commits de retard sur %[2]s
sync_fork.branch_behind_few = Cettte branche a %[1]d commits de retard sur %[2]s
sync_fork.button = Sync
settings.event_action_failure = Échec
settings.event_action_recover = Récupérer
settings.event_action_success = Réussite
settings.event_header_action = Événements d'exécution d'action
settings.event_action_success_desc = L'exécution de l'action a réussi.
settings.event_action_failure_desc = L'exécution de l'action a échoué.
settings.event_action_recover_desc = L'exécution de l'action a réussi après l'échec de la dernière exécution de l'action dans le même workflow.
[graphs]
component_loading = Chargement %s…
@ -2928,7 +2921,7 @@ component_loading_failed = Échec de chargement de %s
component_loading_info = Cela peut prendre du temps…
component_failed_to_load = Une erreur inattendue s'est produite.
contributors.what = contributions
code_frequency.what = fquence de code
code_frequency.what = fŕequence de code
recent_commits.what = commits récents
@ -4011,7 +4004,7 @@ variables.not_found = La variable n'a pas été trouvée.
type-1.display_name=Projet personnel
type-2.display_name=Projet du dépôt
type-3.display_name=Projet de l'organisation
deleted.display_name = Projet supprimé
deleted.display_name = Projet Supprimé
[git.filemode]
changed_filemode=%[1]s → %[2]s

View file

@ -190,7 +190,6 @@ table_modal.placeholder.header = Cabeceira
link_modal.header = Engadir ligazón
link_modal.url = Url
link_modal.description = Descrición
link_modal.paste_reminder = Consello: Coa URL no portapapeis, podes pegala directamente no editor para crear unha ligazón.
[search]
@ -226,8 +225,6 @@ app_desc = Um servizo Git autoxestionado e fácil de usar
install = Fácil de instalar
install_desc = Simplemente <a target="_blank" rel="noopener noreferrer" href="%[1]s">executa o binario</a> para a túa plataforma, envíao con <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> ou consígueo <a target="_blank" rel="noopener noreferrer" href="%[3]s">empaquetado</a>.
license = Código aberto
lightweight_desc = Forgejo precisa duns requerimentos mínimos e pode funcionar nunha Raspberry Pi barata. Aforra enerxía na túa máquina!
lightweight = Lixeiro
[error]
occurred = Ocorreu un erro
@ -294,7 +291,6 @@ app_slogan = Slogan da instancia
app_slogan_helper = Escribe o slogan da túa instancia aqui. Ou deixao baleiro para desabilitala.
domain = Dominio do servidor
ssh_port = Porto do servidor SSH
require_db_desc = Forgejo precisa MySQL, PostgreSQL, SQLite3 ou TiDB (protocolo MySQL).
[repo]
sync_fork.branch_behind_few = Esta rama ten %d achegas por detrás de %s

View file

@ -8,7 +8,7 @@ sign_in=Accedi
sign_in_or=o
sign_out=Esci
sign_up=Registrati
link_account=Collega profilo
link_account=Collega Profilo
register=Registrati
version=Versione
powered_by=Gestito da %s
@ -99,7 +99,7 @@ preview=Anteprima
loading=Caricamento…
error=Errore
error404=La pagina che stai cercando di raggiungere <strong>non esiste</strong>, <strong>è stata rimossa</strong> oppure <strong>non sei autorizzato</strong> a visualizzarla.
error404=La pagina che stai cercando di raggiungere <strong>non esiste</strong> oppure <strong>non sei autorizzato</strong> a visualizzarla.
never=Mai
@ -3869,7 +3869,7 @@ changed_filemode = %[1]s → %[2]s
[search]
type_tooltip = Tipo ricerca
search = Cerca
search = Cerca...
fuzzy = Approssimativa
match = Precisa
org_kind = Cerca organizzazioni...

View file

@ -1,5 +0,0 @@
[common]
home = zdani

View file

@ -312,7 +312,7 @@ default_allow_create_organization=조직 생성 허용을 기본값으로 설정
default_allow_create_organization.description=신규 사용자에게 기본적으로 조직 생성 권한을 부여합니다. 이 옵션이 꺼져있다면, 관리자가 신규 사용자에게 조직 생성 권한을 부여해야합니다.
default_enable_timetracking=시간 기록 기능을 기본적으로 사용
default_enable_timetracking.description=신규 저장소가 시간기록 기능을 기본적으로 사용할 수 있습니다.
no_reply_address=숨겨진 이메일 도메인
no_reply_address=가려진 이메일 도메인
no_reply_address_helper=이메일을 가린 사용자에게 적용될 이메일 도메인입니다. 예를 들어, 사용자명 'joe'가 도메인'noreply.example.org'로 이메일을 가리면 Git에 'joe@noreply.example.org'로 로그인 하게 됩니다.
db_schema_helper = 데이터베이스 기본값 ("공개")를 사용하려면 빈 칸으로 두세요.
require_db_desc = Forgejo를 사용하려면 MySQL, PostgreSQL, SQLite3 또는 TiDB (MySQL 프로토콜) 이 설치되어 있어야 합니다.
@ -330,12 +330,6 @@ app_slogan_helper = 인스턴스의 슬로건을 입력하세요. 비워두면
reinstall_confirm_check_1 = app.ini의 SECRET_KEY로 암호화 되어있는 데이터를 잃을 수 있습니다: 2FA/OTP를 통해 로그인 할 수 없으며 & 미러가 제대로 작동하지 않게됩니다. app.ini 파일에 정확한 SECRET_KEY가 있는것이 확실하다면 체크하세요.
run_user_helper = Forgejo를 구동하는 운영체제의 사용자명입니다. 이 사용자는 저장소 루트 경로에 접근권한이 있어야 합니다.
reinstall_confirm_check_2 = 저장소와 설정에 재동기화가 요구될 수 있습니다. 이 박스에 체크하면 저장소의 훅과 authorized_key 들을 수동으로 재동기화해야 한다는 것을 인지한다는 것을 의미합니다. 저장소와 미러의 설정이 올바른지 확인하세요.
password_algorithm = 암호 해시 알고리즘
enable_update_checker = 업데이트 확인 활성화
secret_key_failed = 비밀 키 생성 실패: %v
env_config_keys = 환경 설정
invalid_password_algorithm = 올바르지 않은 암호 해시 알고리즘
invalid_db_table = 데이터베이스 테이블 "%s"이(가) 올바르지 않습니다: %v
[home]
uname_holder=사용자명 또는 이메일 주소
@ -353,8 +347,6 @@ search_repos=저장소 찾기..
show_private=비공개
issues.in_your_repos=당신의 저장소에
feed_of = "%s"의 피드
filter = 다른 필터
[explore]
repos=저장소

View file

@ -162,7 +162,7 @@ filter.not_archived = Nav arhivētas
filter.is_fork = Atzarojumi
filter.not_fork = Nav atzarojumi
filter.is_mirror = Spoguļglabātavas
filter.public = Publiskas
filter.public = Atklātas
filter.private = Privātas
filter.clear = Notīrīt atlasi
confirm_delete_artifact = Vai tiešām izdzēst artefaktu '%s'?
@ -374,9 +374,9 @@ show_only_archived=Attēlot tikai arhivētos
show_only_unarchived=Attēlot tikai nearhivētos
show_private=Privāts
show_both_private_public=Rāda gan publiskās, gan privātās
show_both_private_public=Rāda gan atklātās, gan privātās
show_only_private=Attēlot tikai privātos
show_only_public=Tiek rādītas tikai publiskās
show_only_public=Attēlo tikai atklātās
issues.in_your_repos=Manās glabātavās
@ -690,7 +690,7 @@ email_domain_is_not_allowed = Lietotāja e-pasta adreses <b>%s</b> domēna vārd
change_avatar=Mainīt profila attēlu…
joined_on=Pievienojās %s
repositories=Glabātavas
activity=Publiskas darbības
activity=Atklāti notikumi
followers_few=%d sekotāji
starred=Izlasei pievienotās glabātavas
watched=Vērotās glabātavas
@ -701,7 +701,7 @@ following_few=%d seko
follow=Sekot
unfollow=Pārtraukt sekot
user_bio=Apraksts par sevi
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību citiem.
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību visiem.
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
show_on_map=Rādīt šo vietu kartē
@ -749,7 +749,7 @@ organization=Apvienības
uid=UID
webauthn=Divpakāpju pieteikšanās (drošības atslēgas)
public_profile=Publiskais profils
public_profile=Visiem pieejamais profils
biography_placeholder=Pastāsti citiem mazliet par sevi! (Tiek atbalstīts Markdown)
location_placeholder=Kopīgot savu aptuveno atrašanās vietu ar citiem
profile_desc=Par Tevi
@ -940,8 +940,8 @@ access_token_deletion_confirm_action=Dzēst
access_token_deletion_desc=Pilnvaras izdzēšana atsauks lietotņu, kas to izmanto, piekļuvi kontam. Šo darbību nevar atsaukt. Turpināt?
delete_token_success=Pilnvara tika izdzēsta. Lietotnēm, kas to izmanto, vairs nav piekļuves kontam.
repo_and_org_access=Glabātavas un apvienības piekļuve
permissions_public_only=Tikai publiskās
permissions_access_all=Visas (publiskās, privātās un ierobežotās)
permissions_public_only=Tikai atklātās
permissions_access_all=Visas (atklātās, privātās un ierobežotās)
select_permissions=Atlasīt atļaujas
permission_no_access=Nav piekļuves
permission_read=Lasīt
@ -1035,14 +1035,14 @@ email_notifications.submit=Iestatīt e-pasta iestatījumus
email_notifications.andyourown=Un manus paziņojumus
visibility=Lietotāja redzamība
visibility.public=Publiska
visibility.public=Atklāta
visibility.public_tooltip=Redzams ikvienam
visibility.limited=Ierobežota
visibility.limited_tooltip=Redzams tikai lietotājiem, kuri ir pieteikušies
visibility.private=Privāta
visibility.private_tooltip=Redzams tikai apvienību, kurās pievienojies, dalībniekiem
change_password = Mainīt paroli
keep_activity_private.description = Tavas <a href="%s">publiskās darbības</a> būs redzamas tikai Tev un servera pārvaldītājiem.
keep_activity_private.description = Tavas <a href="%s">atklātās darbības</a> būs redzamas tikai Tev un servera pārvaldītājiem.
update_hints = Atjaunināt norādes
update_hints_success = Norādes tika atjauninātas.
user_block_success = Lietotājs tika sekmīgi liegts.
@ -1083,7 +1083,7 @@ quota.applies_to_org = Uz apvienību attiecas zemāk esošās ierobežojuma kār
quota.rule.no_limit = Neierobežots
quota.sizes.all = Viss
quota.sizes.repos.all = Glabātavas
quota.sizes.repos.public = Publiskās glabātavas
quota.sizes.repos.public = Atklātās glabātavas
quota.sizes.repos.private = Privātās glabātavas
regenerate_token = Izveidot no jauna
access_token_regeneration = Izveidot piekļuves pilnvaru no jauna
@ -1195,7 +1195,7 @@ transfer.no_permission_to_accept=Nav atļaujas pieņemt šo nodošanu.
transfer.no_permission_to_reject=Nav atļaujas noraidīt šo nodošanu.
desc.private=Privāts
desc.public=Publisks
desc.public=Atklāts
desc.template=Sagatave
desc.internal=Iekšējs
desc.archived=Arhivēts
@ -1464,7 +1464,7 @@ commit.cherry-pick-content=Atlasīt zaru, uz kuru izlasīt:
commitstatus.error=Kļūda
commitstatus.failure=Atteice
commitstatus.pending=Nav iesūtīts
commitstatus.success=Sekmīgs
commitstatus.success=Pabeigts
ext_issues=Ārēji pieteikumi
ext_issues.desc=Saite uz ārējo problēmu sekotāju.
@ -1515,7 +1515,7 @@ issues.filter_assignees=Atlasīt pēc atbildīgajiem
issues.filter_milestones=Atlasīt pēc atskaites punkta
issues.filter_projects=Atlasīt pēc projekta
issues.filter_labels=Atlasīt pēc iezīmes
issues.filter_reviewers=Atlasīt pēc izskatītājiem
issues.filter_reviewers=Atlasīt izskatītājus
issues.new=Jauns pieteikums
issues.new.title_empty=Nosaukums nevar būt tukšs
issues.new.labels=Iezīmes
@ -2041,7 +2041,7 @@ ext_wiki=Ārēja vikivietne
ext_wiki.desc=Ārējā vikivietne norāda uz ārējo vikivietnes adresi.
wiki=Vikivietne
wiki.welcome=Laipni lūdzam vikivietnē!
wiki.welcome=Laipni lūdzam vikivietnē.
wiki.welcome_desc=Vikivietne ļauj rakstīt un kopīgot dokumentāciju ar līdzdalībniekiem.
wiki.desc=Dokumentācijas rakstīšana un kopīgošana ar līdzdalībniekiem.
wiki.create_first_page=Izveidot pirmo lapu
@ -2769,7 +2769,7 @@ no_eol.text = Nav EOL
size_format = %[1]s: %[2]s; %[3]s: %[4]s
mirror_public_key = Publiskā SSH atslēga
mirror_use_ssh.text = Izmantot SSH autentificēšanos
mirror_use_ssh.helper = Forgejo spoguļos glabātavu ar Git un SSH un izveidos atslēgu pāri, kad tiks atlasīta šī iespēja. Jānodrošina, ka izveidotā publiskāš atslēga ir pilnvarota aizgādāt mērķa glabātavā. Nevarēs izmantot pilnvarošanu ar paroli, kad šis tiek atlasīts.
mirror_use_ssh.helper = Forgejo spoguļos glabātavu ar Git un SSH un izveidos atslēgu pāri, kad tiks atlasīta šī iespēja. Jānodrošina, ka izveidotais atslēgu pāris ir pilnvarots aizgādāt mērķa glabātavā. Nevarēs izmantot pilnvarošanu ar paroli, kad šis tiek atlasīts.
mirror_use_ssh.not_available = SSH autentificēšanās nav pieejama.
mirror_denied_combination = Nevar izmantot autentificēšanos ar publiskās atslēgas un paroles apvienojumu.
migrate.forgejo.description = Pārcelt datus no codeberg.org vai citiem Fogejo serveriem.
@ -2959,7 +2959,7 @@ settings.location=Atrašanās vieta
settings.permission=Tiesības
settings.repoadminchangeteam=Glabātavas pārvaldītājs var pievienot un noņemt komandu piekļuvi
settings.visibility=Redzamība
settings.visibility.public=Publiska
settings.visibility.public=Atklāta
settings.visibility.limited=Ierobežota (redzama tikai lietotājiem, kuri ir pieteikušies)
settings.visibility.limited_shortname=Ierobežota
settings.visibility.private=Privāta (redzama tikai apvienības dalībniekiem)
@ -3594,7 +3594,7 @@ self_check.database_collation_mismatch = Sagaidīt, ka datubāzē tiek izmantota
self_check.database_fix_mysql = MySQL/MariaDB lietotāji var izmantot komandu "forgejo doctor convert", lai novērstu salīdzināšanas sarežģījumus, vai arī tos var pašrocīgi novērst ar "ALTER ... COLLATE ..." vaicājumiem.
config.app_slogan = Servera sauklis
config.allow_dots_in_usernames = Ļaut lietotājiem izmantot punktus savā lietotājvārdā. Neietekmē esošos kontus.
users.restricted.description = Ļaut mijiedarbību tikai ar glabātavām un apvienībām, kurās šis lietotājs ir pievienots kā līdzdalībnieks. Tas neļauj piekļūt šī servera publiskajām glabātavām.
users.restricted.description = Ļaut mijiedarbību tikai ar glabātavām un apvienībām, kurās šis lietotājs ir pievienots kā līdzdalībnieks. Tas neļauj piekļūt šī servera atklātajām glabātavām.
dashboard.sync_tag.started = Uzsākta birku sinhronizēšana
users.organization_creation.description = Ļaut jaunu apvienību izveidošanu.
users.block.description = Liegt šī lietotāja mijiedarbību ar šo serveri caur tā kontu un neļaut pieteikšanos.
@ -3925,7 +3925,7 @@ runners.task_list.run=Izpildījums
runners.task_list.status=Stāvoklis
runners.task_list.repository=Glabātava
runners.task_list.commit=Iesūtījums
runners.task_list.done_at=Pabeigts
runners.task_list.done_at=Beigu laiks
runners.edit_runner=Labot izpildītāju
runners.update_runner=Atjaunināt izmaiņas
runners.update_runner_success=Izpildītājs sekmīgi atjaunināts

View file

@ -1439,7 +1439,7 @@ issues.comment_manually_pull_merged_at = hett Kommitteren %[1]s in %[2]s %[3]s v
issues.reopen_issue = Weer opmaken
issues.closed_at = `hett deeses Gefall <a id="%[1]s" href="#%[1]s">%[2]s</a> dichtmaakt`
issues.commit_ref_at = `hett deeses Gefall <a id="%[1]s" href="#%[1]s">%[2]s</a> vun eenem Kommitteren benöömt`
issues.ref_closing_from = `<a href="%[3]s">hett deeses Gefall</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s"> vun eenem Haalvörslag, wat t %[4]s dichtmaken word, benöömt</a>`
issues.ref_closing_from = `<a href="%[3]s">hett deeses Gefall vun eenem Haalvörslag, wat t %[4]s dichtmaken word,</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s">benöömt</a>`
issues.ref_closed_from = `<a href="%[3]s">hett deeses Gefall %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s">dichtmaakt</a>`
issues.ref_reopened_from = `<a href="%[3]s">hett deeses Gefall %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s">weer opmaakt</a>`
issues.ref_from = `vun %[1]s`
@ -2614,13 +2614,6 @@ archive.nocomment = Kommenteren gaht hier nich, denn dat Repositorium is archive
sync_fork.button = Vernejen
sync_fork.branch_behind_one = Deeser Twieg is %[1]d Kommitteren achter %[2]s
sync_fork.branch_behind_few = Deeser Twieg is %[1]d Kommitterens achter %[2]s
settings.event_action_failure = Fehlslagen
settings.event_action_success = Daankregen
settings.event_action_success_desc = Aktioons-Loop is all daankregen worden.
settings.event_action_recover = Verhaalt
settings.event_header_action = Aktioons-Loop-Vörfallen
settings.event_action_failure_desc = Aktioons-Loop is as fehlslagen ennt.
settings.event_action_recover_desc = Aktioons-Loop is daankregen worden, nadeem de leste Aktioons-Loop in de sülven Warkwies fehlslagen is.
[repo.permissions]
code.read = <b>Lesen:</b> De Quelltext vun deesem Repositorium ankieken un klonen.

View file

@ -8,7 +8,7 @@ sign_in=Aanmelden
sign_in_or=of
sign_out=Uitloggen
sign_up=Registreren
link_account=Account koppelen
link_account=Account Koppelen
register=Registreren
version=Versie
powered_by=Mogelijk gemaakt door %s
@ -2031,7 +2031,7 @@ settings.add_collaborator_success=De medewerker is toegevoegd.
settings.add_collaborator_inactive_user=Kan geen inactieve gebruiker toevoegen als medewerker.
settings.add_collaborator_duplicate=De collaborator is al toegevoegd aan deze repository.
settings.delete_collaborator=Verwijder
settings.collaborator_deletion=Verwijder samenwerker
settings.collaborator_deletion=Verwijder medewerker
settings.collaborator_deletion_desc=Het verwijderen van een collaborator zal hun toegang tot deze repository intrekken. Doorgaan?
settings.remove_collaborator_success=De medewerker is verwijderd.
settings.search_user_placeholder=Zoek gebruiker…
@ -3914,7 +3914,7 @@ runners.task_list.no_tasks = Er is nog geen taak.
runners.labels = Labels
runners.last_online = Laatste online tijd
runners.task_list.status = Status
runners.task_list.done_at = Gedaan op
runners.task_list.done_at = Gedaan Op
runners.id = ID
runs.actor = Acteur
actions = Actions

View file

@ -1503,11 +1503,11 @@ projects.card_type.images_and_text=Imagens e texto
projects.card_type.text_only=Somente texto
issues.desc=Organize relatórios de bugs, tarefas e marcos.
issues.filter_assignees=Filtrar atribuição
issues.filter_milestones=Filtrar marco
issues.filter_projects=Filtrar projeto
issues.filter_labels=Filtrar rótulo
issues.filter_reviewers=Filtrar revisor
issues.filter_assignees=Filtrar Atribuição
issues.filter_milestones=Filtrar Marco
issues.filter_projects=Filtrar Projeto
issues.filter_labels=Filtrar Rótulo
issues.filter_reviewers=Filtrar Revisor
issues.new=Novo issue
issues.new.title_empty=Título não pode ser em branco
issues.new.labels=Etiquetas
@ -2013,7 +2013,7 @@ ext_wiki=Wiki Externa
ext_wiki.desc=Link para uma wiki externa.
wiki=Wiki
wiki.welcome=Bem-vindo à wiki.
wiki.welcome=Bem-vindo a wiki.
wiki.welcome_desc=A wiki permite que você escreva e compartilhe a documentação com os colaboradores.
wiki.desc=Escrever e compartilhar a documentação com os colaboradores.
wiki.create_first_page=Criar a primeira página
@ -3808,8 +3808,8 @@ swift.install2=e execute o seguinte comando:
vagrant.install=Para adicionar uma Vagrant box, execute o seguinte comando:
settings.link=Vincular este pacote a um repositório
settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório.
settings.link.select=Selecionar repositório
settings.link.button=Atualizar link do repositório
settings.link.select=Selecionar Repositório
settings.link.button=Atualizar Link do Repositório
settings.link.success=Link do repositório foi atualizado com sucesso.
settings.link.error=Falha ao atualizar o link do repositório.
settings.delete=Excluir o pacote
@ -4004,7 +4004,7 @@ variables.not_found = Não foi possível encontrar a variável.
type-1.display_name=Projeto individual
type-2.display_name=Projeto do repositório
type-3.display_name=Projeto da organização
deleted.display_name = Projeto apagado
deleted.display_name = Projeto Apagado
[git.filemode]
symbolic_link=Ligação simbólica

View file

@ -9,7 +9,7 @@ sign_in_with_provider=Iniciar sessão com %s
sign_in_or=ou
sign_out=Terminar sessão
sign_up=Fazer inscrição
link_account=Associar conta
link_account=Vincular conta
register=Inscrição
version=Versão
powered_by=Implementado com %s
@ -20,12 +20,12 @@ notifications=Notificações
active_stopwatch=Cronómetro em andamento
tracked_time_summary=Resumo do tempo rastreado com base em filtros da lista de questões
create_new=Criar…
user_profile_and_more=Perfil e definições…
user_profile_and_more=Perfil e configurações…
signed_in_as=Sessão iniciada como
enable_javascript=Este sítio Web requer JavaScript.
toc=Índice
licenses=Licenças
return_to_forgejo=Voltar ao Forgejo
return_to_forgejo=Retornar ao Forgejo
username=Nome de utilizador
email=Endereço de email
@ -59,10 +59,10 @@ new_migrate=Nova migração
new_mirror=Nova réplica
new_fork=Nova derivação do repositório
new_org=Nova organização
new_project=Novo projeto
new_project=Novo planeamento
new_project_column=Nova coluna
manage_org=Gerir organizações
admin_panel=Administração do site
admin_panel=Administração do sítio
account_settings=Configurações da conta
settings=Configurações
your_profile=Perfil
@ -155,7 +155,7 @@ invalid_data = Dados inválidos: %v
filter.clear = Retirar filtros
filter.is_archived = Arquivado
filter.not_template = Não modelos
toggle_menu = Alternar menu
toggle_menu = Comutar menu
filter = Filtrar
copy_generic = Copiar para a área de transferência
test = Teste
@ -233,7 +233,7 @@ platform_desc=Está confirmado que Forgejo corre em sistemas operativos livres,
lightweight=Leve
lightweight_desc=Forgejo requer poucos recursos e pode correr num simples Raspberry Pi. Economize a energia da sua máquina!
license=Código aberto
license_desc=Todas as fontes estão disponíveis no <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Junte-se a nós e <a target="_blank" rel="noopener noreferrer" href="%[2]s">contribua</a> para tornar este projeto ainda melhor. Não receie tornar-se colaborador!
license_desc=Vá buscá-lo em <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Junte-se a nós dando a <a target="_blank" rel="noopener noreferrer" href="%[2]s">sua contribuição</a> para tornar este programa ainda melhor. Não se acanhe e contribua!
[install]
install=Instalação
@ -291,7 +291,7 @@ smtp_port=Porto do SMTP
smtp_from=Email do remetente
smtp_from_helper=Endereço de email que o Forgejo vai usar. Insira um endereço de email simples ou use o formato "Nome" <email@exemplo.com>.
mailer_user=Nome de utilizador do SMTP
mailer_password=Palavra-passe do SMTP
mailer_password=Senha do SMTP
register_confirm=Exigir confirmação de email para se inscrever
mail_notify=Habilitar notificações por email
server_service_title=Configurações do servidor e de terceiros
@ -316,7 +316,7 @@ admin_setting.description=A criação de uma conta de administração é opciona
admin_title=Configurações da conta de administração
admin_name=Nome de utilizador do administrador
admin_password=Senha
confirm_password=Confirme a palavra-passe
confirm_password=Confirme a senha
admin_email=Endereço de email
install_btn_confirm=Instalar Forgejo
test_git_failed=Não foi possível testar o comando "git": %v
@ -339,7 +339,7 @@ default_enable_timetracking=Habilitar, por norma, a contagem do tempo
default_enable_timetracking.description=Habilitar, por norma, a contagem do tempo nos novos repositórios.
no_reply_address=Domínio dos emails ocultos
no_reply_address_helper=Nome de domínio para utilizadores com um endereço de email oculto. Por exemplo, o nome de utilizador "silva" será registado no Git como "silva@semresposta.exemplo.org" se o domínio de email oculto estiver definido como "semresposta.exemplo.org".
password_algorithm=Algoritmo de Hash da palavra-passe
password_algorithm=Algoritmo de Hash da Senha
invalid_password_algorithm=Algoritmo de hash da senha inválido
password_algorithm_helper=Definir o algoritmo de hash da senha. Os algoritmos têm requisitos e resistência distintos. `argon2` é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas pequenos.
enable_update_checker=Habilitar verificador de novidades
@ -415,7 +415,7 @@ disable_register_mail=A confirmação por email da inscrição está desabilitad
manual_activation_only=Contacte o administrador para completar a habilitação.
remember_me=Memorizar este dispositivo
remember_me.compromised=O identificador da sessão já não é válido, o que pode indicar uma conta comprometida. Verifique se a sua conta apresenta operações pouco habituais.
forgot_password_title=Esqueci-me da palavra-passe
forgot_password_title=Esqueci-me da senha
forgot_password=Esqueceu a sua senha?
sign_up_now=Precisa de uma conta? Inscreva-se agora.
sign_up_successful=A conta foi criada com sucesso. Bem-vindo/a!
@ -744,7 +744,7 @@ social=Contas sociais
applications=Aplicações
orgs=Organizações
repos=Repositórios
delete=Eliminar conta
delete=Eliminar a conta
twofa=Autenticação em dois passos (TOTP)
account_link=Contas vinculadas
organization=Organizações
@ -1060,7 +1060,7 @@ user_unblock_success = O utilizador foi desbloqueado com sucesso.
language.title = Idioma predefinido
keep_activity_private.description = O seu <a href="%s">trabalho público</a> apenas estará visível para si e para os administradores da instância.
language.description = Este idioma vai ser guardado na sua conta e ser usado como o predefinido depois de iniciar sessão.
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! <a href="%s">Ler mais</a>.
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! <a href="%s">Saiba mais</a>.
pronouns_custom_label = Pronomes personalizados
user_block_yourself = Não se pode bloquear a si próprio.
change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
@ -1093,7 +1093,7 @@ regenerate_token = Regenerar
access_token_regeneration_desc = A regeneração de um código irá revogar o acesso à sua conta para as aplicações que o utilizam. Isto não pode ser anulado. Continuar?
[repo]
new_repo_helper=Um repositório contém todos os ficheiros do projeto, incluindo o histórico das revisões. Já tem um hospedado noutro sítio? <a href="%s">Migre o repositório</a>.
new_repo_helper=Um repositório contém todos os ficheiros do trabalho, incluindo o histórico das revisões. Já tem um hospedado noutro sítio? <a href="%s">Migre o repositório</a>.
owner=Proprietário(a)
owner_helper=Algumas organizações podem não aparecer na lista suspensa devido a um limite máximo de contagem de repositórios.
repo_name=Nome do repositório
@ -1133,7 +1133,7 @@ issue_labels=Rótulos
issue_labels_helper=Escolha um conjunto de rótulos
license=Licença
license_helper=Escolha um ficheiro de licença
license_helper_desc=Uma licença rege o que os outros podem, ou não, fazer com o seu código fonte. Não tem a certeza sobre qual a mais indicada para o seu projeto? Veja: <a target="_blank" rel="noopener noreferrer" href="%s">Escolher uma licença</a>.
license_helper_desc=Uma licença rege o que os outros podem, ou não, fazer com o seu código fonte. Não tem a certeza sobre qual a mais indicada para o seu trabalho? Veja: <a target="_blank" rel="noopener noreferrer" href="%s">Escolher uma licença</a>.
object_format=Formato dos elementos
object_format_helper=Formato dos elementos do repositório. Não poderá ser alterado mais tarde. SHA1 é o mais compatível.
readme=README
@ -1479,23 +1479,23 @@ projects=Planeamentos
projects.desc=Gerir questões e integrações nos quadros do planeamento.
projects.description=Descrição (opcional)
projects.description_placeholder=Descrição
projects.create=Criar projeto
projects.create=Criar planeamento
projects.title=Título
projects.new=Novo projeto
projects.new=Novo planeamento
projects.new_subheader=Coordene, acompanhe e modifique o seu trabalho num só lugar, para que os planeamentos se mantenham transparentes e cumpram o calendário.
projects.create_success=O planeamento "%s" foi criado.
projects.deletion=Eliminar projeto
projects.deletion=Eliminar planeamento
projects.deletion_desc=Eliminar um planeamento remove-o de todas as questões relacionadas. Continuar?
projects.deletion_success=O planeamento foi eliminado.
projects.edit=Editar projeto
projects.edit=Editar planeamentos
projects.edit_subheader=Planeamentos organizam questões e acompanham o progresso.
projects.modify=Editar projeto
projects.modify=Editar planeamento
projects.edit_success=O planeamento "%s" foi modificado.
projects.type.none=Nenhum
projects.type.basic_kanban=Kanban básico
projects.type.bug_triage=Triagem de erros
projects.template.desc=Modelo
projects.template.desc_helper=Escolha um modelo de projeto para começar
projects.template.desc_helper=Escolha um modelo de planeamento para começar
projects.type.uncategorized=Sem categoria
projects.column.edit=Editar coluna
projects.column.edit_title=Nome
@ -1507,7 +1507,7 @@ projects.column.set_default_desc=Definir esta coluna como a predefinida para que
projects.column.unset_default=Deixar de ser a predefinida
projects.column.unset_default_desc=Faz com que esta coluna deixe de ser a predefinida
projects.column.delete=Eliminar coluna
projects.column.deletion_desc=Eliminar uma coluna de um projeto faz com que todas as questões que nela constam sejam movidas para a coluna padrão. Continuar?
projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna padrão. Continuar?
projects.column.color=Colorido
projects.open=Abrir
projects.close=Fechar
@ -1519,7 +1519,7 @@ projects.card_type.text_only=Apenas texto
issues.desc=Organize relatórios de erros, tarefas e etapas.
issues.filter_assignees=Filtrar encarregado
issues.filter_milestones=Filtrar etapa
issues.filter_projects=Filtrar projeto
issues.filter_projects=Filtrar planeamento
issues.filter_labels=Filtrar rótulo
issues.filter_reviewers=Filtrar revisor
issues.new=Questão nova
@ -1530,8 +1530,8 @@ issues.new.clear_labels=Retirar rótulos
issues.new.projects=Planeamentos
issues.new.clear_projects=Limpar planeamentos
issues.new.no_projects=Nenhum planeamento
issues.new.open_projects=Projetos abertos
issues.new.closed_projects=Projetos fechados
issues.new.open_projects=Planeamentos abertos
issues.new.closed_projects=Planeamentos fechados
issues.new.no_items=Sem itens
issues.new.milestone=Etapa
issues.new.no_milestone=Sem etapa
@ -2049,7 +2049,7 @@ ext_wiki=Wiki externo
ext_wiki.desc=Ligação para um wiki externo.
wiki=Wiki
wiki.welcome=Bem-vindo(a) à wiki.
wiki.welcome=Bem-vindo(a) ao Wiki.
wiki.welcome_desc=O wiki permite escrever e partilhar documentação com os colaboradores.
wiki.desc=Escrever e partilhar documentação com os colaboradores.
wiki.create_first_page=Criar a primeira página
@ -2236,7 +2236,7 @@ settings.pulls.default_delete_branch_after_merge=Eliminar, por norma, o ramo do
settings.pulls.default_allow_edits_from_maintainers=Permitir, por norma, que os responsáveis editem
settings.releases_desc=Habilitar lançamentos no repositório
settings.packages_desc=Habilitar o registo de pacotes do repositório
settings.projects_desc=Habilitar projetos no repositório
settings.projects_desc=Habilitar planeamentos no repositório
settings.actions_desc=Habilitar sequências CI/CD integradas com Forgejo Actions
settings.admin_settings=Configurações do administrador
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
@ -2834,7 +2834,7 @@ form.string_too_long = O texto fornecido é mais comprido do que %d caracteres.
settings.federation_settings = Configurações da federação
settings.federation_apapiurl = URL de federação deste repositório. Copie e cole nas configurações de federação de outro repositório como um URL de um repositório que está a ser seguido.
issues.edit.already_changed = Não foi possível guardar as modificações desta questão. O conteúdo parece ter sido modificado por outro utilizador. Refresque a página e tente editar novamente para evitar sobrescrever as modificações que fizeram
project = Projetos
project = Planeamentos
pulls.edit.already_changed = Não foi possível guardar as modificações do pedido de integração. O conteúdo parece ter sido modificado por outro utilizador. Refresque a página e tente editar novamente para evitar sobrescrever as modificações que fizeram
subscribe.issue.guest.tooltip = Inicie sessão para subscrever esta questão.
subscribe.pull.guest.tooltip = Inicie sessão para subscrever este pedido de integração.
@ -3811,7 +3811,7 @@ swift.install2=e execute o seguinte comando:
vagrant.install=Para adicionar uma máquina virtual Vagrant, execute o seguinte comando:
settings.link=Vincular este pacote a um repositório
settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório.
settings.link.select=Escolher repositório
settings.link.select=Escolha o repositório
settings.link.button=Modificar vínculo ao repositório
settings.link.success=O vínculo ao repositório foi modificado com sucesso.
settings.link.error=Falhou a modificação do vínculo ao repositório.
@ -4002,10 +4002,10 @@ runs.no_workflows.help_write_access = Não sabe como começar com o Forgejo Acti
variables.not_found = Não foi possível encontrar a variável.
[projects]
type-1.display_name=Projeto individual
type-2.display_name=Projeto do repositório
type-3.display_name=Projeto da organização
deleted.display_name = Projeto eliminado
type-1.display_name=Planeamento individual
type-2.display_name=Planeamento do repositório
type-3.display_name=Planeamento da organização
deleted.display_name = Planeamento eliminado
[git.filemode]
changed_filemode=%[1]s → %[2]s
@ -4024,7 +4024,7 @@ code_search_by_git_grep = Os resultados da pesquisa no código-fonte neste momen
no_results = Não foram encontrados resultados correspondentes.
package_kind = Pesquisar pacotes…
runner_kind = Pesquisar executores…
project_kind = Pesquisar projetos…
project_kind = Pesquisar planeamentos…
branch_kind = Pesquisar ramos…
commit_kind = Pesquisar cometimentos…
search = Procurar…
@ -4068,8 +4068,8 @@ test = ok :)
[repo.permissions]
code.read = <b>Ler:</b> Aceder e clonar o código-fonte do repositório.
releases.read = <b>Ler:</b> Ver e descarregar lançamentos.
projects.read = <b>Ler:</b> Aceder aos quadros de projeto do repositório.
projects.write = <b>Escrever:</b> Criar projetos e colunas e editá-las.
projects.read = <b>Ler:</b> Aceder aos quadros de planeamento do repositório.
projects.write = <b>Escrever:</b> Criar planeamentos e colunas e editá-las.
packages.read = <b>Ler:</b> Ver e descarregar pacotes atribuídos ao repositório.
packages.write = <b>Escrever:</b> Publicar e eliminar pacotes atribuídos ao repositório.
actions.read = <b>Ler:</b> Ver sequências CI/CD integrados e os seus registos.

View file

@ -296,7 +296,7 @@ federated_avatar_lookup.description=Libravatar kullanarak federe profil resmi ar
disable_registration=Kendi Kendine Kaydolmayı Devre Dışı Bırak
disable_registration.description=Kullanıcının kendi kendine kaydolmasını devre dışı bırak. Yalnızca yöneticiler yeni hesaplar oluşturabilecek.
allow_only_external_registration.description=Sadece belirlenen dış hizmetler aracılığıyla kullanıcı kaydına izin ver.
openid_signin=OpenID Oturum Açmayı Etkinleştir
openid_signin=OpenID Oturum Açmayı Etkinleştiriniz
openid_signin.description=OpenID ile kullanıcı girişini etkinleştir.
openid_signup=OpenID ile Kendi Kendine Kaydı Etkinleştir
openid_signup.description=OpenID Tabanlı Kendi Kendi Kullanıcı Kaydını Etkinleştir.
@ -3061,13 +3061,13 @@ packages.repository=Depo
packages.size=Boyut
packages.published=Yayınlandı
defaulthooks=Varsayılan web kancaları
defaulthooks.desc=Web Kancaları, belirli Forgejo olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web kancaları varsayılandır ve tüm yeni depolara kopyalanır. <a target="_blank" rel="noopener" href="%s">web kancaları kılavuzunda</a> daha fazla bilgi edinin.
defaulthooks=Varsayılan Web İstemcileri
defaulthooks.desc=Web İstemcileri, belirli Forgejo olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web İstemcileri varsayılandır ve tüm yeni depolara kopyalanır. <a target="_blank" rel="noopener" href="%s">web istemcileri kılavuzunda</a> daha fazla bilgi edinin.
defaulthooks.add_webhook=Varsayılan Web İstemcisi Ekle
defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle
systemhooks=Sistem web kancaları
systemhooks.desc=Belirli Forgejo olayları tetiklendiğinde Web kancaları otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web kancaları sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. <a target="_blank" rel="noopener" href="%s">web kancaları kılavuzunda</a> daha fazla bilgi edinin.
systemhooks=Sistem Web İstemcileri
systemhooks.desc=Belirli Forgejo olayları tetiklendiğinde Web istemcileri otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web istemcileri sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. <a target="_blank" rel="noopener" href="%s">web istemcileri kılavuzunda</a> daha fazla bilgi edinin.
systemhooks.add_webhook=Sistem Web İstemcisi Ekle
systemhooks.update_webhook=Sistem Web İstemcisi Güncelle
@ -3241,7 +3241,7 @@ config.disable_register=Kullanıcı Kaydını Devre Dışı Bırak
config.allow_only_internal_registration=Kayda Sadece Forgejo'nın Kendisi Üzerinden İzin Ver
config.allow_only_external_registration=Sadece Dış Hizmetler Aracılığıyla Kullanıcı Kaydına İzin Ver
config.enable_openid_signup=OpenID Kendinden Kaydı'nı Etkinleştir
config.enable_openid_signin=OpenID Oturum Açmayı Etkinleştir
config.enable_openid_signin=OpenID Oturum Açmayı Etkinleştiriniz
config.show_registration_button=Kaydolma Düğmesini Göster
config.require_sign_in_view=Sayfaları Görüntülemek için Giriş Yapmaya Zorla
config.mail_notify=E-Posta Bildirimlerini Etkinleştir

View file

@ -1780,7 +1780,7 @@ milestones.filter_sort.least_issues=Найменш задач
ext_wiki.desc=Посилання на зовнішню вікі.
wiki=Вікі
wiki.welcome=Ласкаво просимо до вікі.
wiki.welcome=Ласкаво просимо до Вікі.
wiki.welcome_desc=Wiki дозволяє писати та ділитися документацією з співавторами.
wiki.desc=Пишіть та обмінюйтеся документацією із співавторами.
wiki.create_first_page=Створити першу сторінку
@ -2663,11 +2663,6 @@ sync_fork.button = Синхронізувати
sync_fork.branch_behind_one = Ця гілка на %[1]d коміт позаду %[2]s
sync_fork.branch_behind_few = Ця гілка на %[1]d комітів позаду %[2]s
issues.role.first_time_contributor = Новий учасник
settings.event_action_failure = Помилка
settings.event_action_success = Успіх
settings.event_action_recover = Відновлено
commitstatus.success = Успіх
commitstatus.failure = Збій
[graphs]
contributors.what = внески

View file

@ -7,9 +7,9 @@ logo=徽标
sign_in=登录
sign_in_with_provider=使用 %s 登录
sign_in_or=
sign_out=
sign_out=退
sign_up=注册
link_account=链接账
link_account=链接账
register=注册
version=当前版本
powered_by=由 %s 提供支持
@ -743,7 +743,7 @@ social=社交帐号
applications=应用
orgs=组织
repos=仓库列表
delete=删除账号
delete=删除帐户
twofa=两步验证TOTP
account_link=已绑定的帐户
organization=组织
@ -1515,7 +1515,7 @@ projects.card_type.images_and_text=图标和文字
projects.card_type.text_only=仅文本
issues.desc=组织 bug 报告、任务和里程碑。
issues.filter_assignees=筛选指派成员
issues.filter_assignees=筛选指派
issues.filter_milestones=筛选里程碑
issues.filter_projects=筛选项目
issues.filter_labels=筛选标签
@ -1653,7 +1653,7 @@ issues.comment_pull_merged_at=已合并提交 %[1]s 到 %[2]s %[3]s
issues.comment_manually_pull_merged_at=手动合并提交 %[1]s 到 %[2]s %[3]s
issues.close_comment_issue=评论并关闭
issues.reopen_issue=重新开放
issues.reopen_comment_issue=重新打开评论
issues.reopen_comment_issue=重新打开评论
issues.create_comment=评论
issues.closed_at=`于<a id="%[1]s" href="#%[1]s">%[2]s</a>关闭此议题`
issues.reopened_at=`重新打开此问题 <a id="%[1]s" href="#%[1]s">%[2]s</a>`
@ -2304,7 +2304,7 @@ settings.add_collaborator_inactive_user=无法添加未激活的用户作为合
settings.add_collaborator_owner=不能将所有者添加为协作者。
settings.add_collaborator_duplicate=合作者已经被添加到本仓库。
settings.delete_collaborator=删除
settings.collaborator_deletion=除协作者
settings.collaborator_deletion=除协作者
settings.collaborator_deletion_desc=删除协作者后他将无法再对此仓库的访问。继续?
settings.remove_collaborator_success=已成功删除协作者。
settings.search_user_placeholder=搜索用户...

View file

@ -2570,8 +2570,8 @@ tree_path_not_found_tag = 路徑 %[1]s 不存在於標籤 %[2]s 中
tree_path_not_found_commit = 路徑 %[1]s 不存在於提交 %[2]s 中
tree_path_not_found_branch = 路徑 %[1]s 不存在於分支 %[2]s 中
transfer.no_permission_to_accept = 您沒有權限接受這項轉讓。
archive.title = 這個儲存庫已被封存。您可以檢視其中的檔案或拓製儲存庫,但您無法提交推送和創建新議題、合併請求或評論
archive.title_date = 這個儲存庫在 %s 被封存了。您可以檢視其中的檔案或拓製儲存庫,但您無法提交推送和創建新議題、合併請求或評論
archive.title = 這個儲存庫被封存了。您可以檢視其中的檔案或是 Clone 它,但您無法推送提交,提出問題或合併請求
archive.title_date = 這個儲存庫在 %s 被封存了。您可以檢視其中的檔案或 clone 它,但您無法推送提交,提出問題或合併請求
migrate.forgejo.description = 從 codeberg.org 或其他 Forgejo 站點遷移資料。
migrate.cancel_migrating_title = 取消遷移
executable_file = 可執行檔

View file

@ -98,7 +98,5 @@
"followers.incoming.list.none": "Tohoto uživatele nikdo nesleduje.",
"followers.outgoing.list.none": "%s nikoho nesleduje.",
"stars.list.none": "Tento repozitář si nikdo nepřidal do oblíbených.",
"followers.outgoing.list.self.none": "Nikoho nesledujete.",
"editor.textarea.tab_hint": "Řádek je již odsazen. Pro opuštění editoru stiskněte znovu <kbd>Tab</kbd> nebo <kbd>Escape</kbd>.",
"editor.textarea.shift_tab_hint": "Na tomto řádku není žádné odsazení. Pro opuštění editoru stiskněte znovu <kbd>Shift</kbd> + <kbd>Tab</kbd> nebo <kbd>Escape</kbd>."
"followers.outgoing.list.self.none": "Nikoho nesledujete."
}

View file

@ -84,13 +84,5 @@
"moderation.report_remarks.placeholder": "Angiv venligst nogle detaljer vedrørende det misbrug, du anmelder.",
"moderation.submit_report": "Indsend rapport",
"moderation.reporting_failed": "Den nye misbrugsrapport kunne ikke indsendes: %v",
"moderation.reported_thank_you": "Tak for din rapport. Administrationen er blevet gjort opmærksom på den.",
"stars.list.none": "Ingen har markeret dette depot med en stjerne.",
"watch.list.none": "Ingen ser dette depot.",
"followers.incoming.list.self.none": "Ingen følger din profil.",
"followers.incoming.list.none": "Ingen følger denne bruger.",
"followers.outgoing.list.self.none": "Du følger ikke nogen.",
"followers.outgoing.list.none": "%s følger ikke nogen.",
"editor.textarea.tab_hint": "Linjen er allerede indrykket. Tryk på <kbd>Tab</kbd> igen eller <kbd>Escape</kbd> for at forlade editoren.",
"editor.textarea.shift_tab_hint": "Ingen indrykning på denne linje. Tryk på <kbd>Shift</kbd> + <kbd>Tab</kbd> igen eller <kbd>Escape</kbd> for at forlade editoren."
"moderation.reported_thank_you": "Tak for din rapport. Administrationen er blevet gjort opmærksom på den."
}

View file

@ -90,7 +90,5 @@
"followers.outgoing.list.self.none": "Du folgst niemanden.",
"followers.outgoing.list.none": "%s folgt niemanden.",
"stars.list.none": "Niemand hat dieses Repo favorisiert.",
"followers.incoming.list.none": "Niemand folgt diesem Benutzer.",
"editor.textarea.tab_hint": "Zeile bereits eingerückt. Drücke nochmals <kbd>Tab</kbd> oder <kbd>Escape</kbd> um den Editor zu verlassen.",
"editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals <kbd>Shift</kbd> + <kbd>Tab</kbd> oder <kbd>Escape</kbd> um den Editor zu verlassen."
"followers.incoming.list.none": "Niemand folgt diesem Benutzer."
}

View file

@ -92,6 +92,5 @@
"discussion.locked": "This discussion has been locked. Commenting is limited to contributors.",
"editor.textarea.tab_hint": "Line already indented. Press <kbd>Tab</kbd> again or <kbd>Escape</kbd> to leave the editor.",
"editor.textarea.shift_tab_hint": "No indentation on this line. Press <kbd>Shift</kbd> + <kbd>Tab</kbd> again or <kbd>Escape</kbd> to leave the editor.",
"admin.dashboard.cleanup_offline_runners": "Cleanup offline runners",
"meta.last_line": "Thank you for translating Forgejo! This line isn't seen by the users but it serves other purposes in the translation management. You can place a fun fact in the translation instead of translating it."
}

View file

@ -83,14 +83,5 @@
"moderation.submit_report": "I-submit ang ulat",
"moderation.reporting_failed": "Hindi ma-submit ang bagong ulat sa pang aabuso: %v",
"moderation.reported_thank_you": "Salamat sa iyong ulat. Naipaalam na ito sa administrasyon.",
"repo.form.cannot_create": "Naabot na ng lahat ng mga espasyo kung saan ka makakagawa ng mga repositoryo ang limitasyon ng mga repositoryo.",
"stars.list.none": "Wala pang nag-star ng repositoryong ito.",
"followers.incoming.list.self.none": "Walang sumusubaybay sa iyong profile.",
"repo.issue_indexer.title": "Indexer ng Isyu",
"watch.list.none": "Wala pang nanonood sa repositoryong ito.",
"followers.incoming.list.none": "Wala pang sumusunod sa user na ito.",
"followers.outgoing.list.self.none": "Hindi ka sumusunod ng anumang tao.",
"followers.outgoing.list.none": "Hindi sinusundan ni %s ang sinuman.",
"editor.textarea.tab_hint": "Naka-indent na ang linya. Pindutin ulit ang <kbd>Tab</kbd> o <kbd>Escape</kbd> para umalis sa editor.",
"editor.textarea.shift_tab_hint": "Walang indentation sa linyang ito. Pindutin ang <kbd>Shift</kbd> + <kbd>Tab</kbd> ulit o <kbd>Escape</kbd> para umalis sa editor."
"repo.form.cannot_create": "Naabot na ng lahat ng mga espasyo kung saan ka makakagawa ng mga repositoryo ang limitasyon ng mga repositoryo."
}

View file

@ -89,13 +89,5 @@
"moderation.report_remarks": "Remarques",
"moderation.report_remarks.placeholder": "S'il vous plaît fournissez quelques détails en rapport avec l'abus que vous signalez.",
"moderation.submit_report": "Soumettre le signalement",
"moderation.reporting_failed": "Impossible de soumettre le nouveau signalement : %v",
"followers.incoming.list.self.none": "Personne ne suit votre profile.",
"followers.incoming.list.none": "Personne ne suit cet utilisateur.",
"followers.outgoing.list.self.none": "Vous ne suivez personne.",
"followers.outgoing.list.none": "%s ne vous suit plus.",
"repo.issue_indexer.title": "Indexeur de problèmes",
"stars.list.none": "Personne n'a mis d'étoiles sur ce dépôt.",
"watch.list.none": "Personne ne consulte ce dépôt.",
"repo.form.cannot_create": "Tous les espaces dans lesquels vous pouvez créer des dépôts ont atteint la limite de dépôts."
"moderation.reporting_failed": "Impossible de soumettre le nouveau signalement : %v"
}

View file

@ -98,7 +98,5 @@
"followers.outgoing.list.self.none": "Tu nevienam neseko.",
"followers.outgoing.list.none": "%s nevienam neseko.",
"stars.list.none": "Neviens šo glabātavu nav atzīmējis ar zvaigzni.",
"followers.incoming.list.self.none": "Neviens neseko Tavam profilam.",
"editor.textarea.tab_hint": "Rinda jau ir ar atkāpi. Spied <kbd>Tab</kbd> vēlreiz vai <kbd>Escape</kbd>, lai izietu no redaktora!",
"editor.textarea.shift_tab_hint": "Šajā rindā nav atkāpes. Spied <kbd>Shift</kbd> + <kbd>Tab</kbd> vēlreiz vai <kbd>Escape</kbd>, lai izietu no redaktora!"
"followers.incoming.list.self.none": "Neviens neseko Tavam profilam."
}

View file

@ -1,11 +1,11 @@
{
"repo.pulls.merged_title_desc": {
"one": "heeft %[1]d commit van <code>%[2]s</code> samengevoegd in <code>%[3]s</code> %[4]s",
"other": "heeft %[1]d commits van <code>%[2]s</code> samengevoegd in <code>%[3]s</code> %[4]s"
"other": "heeft %[1]d commits samengevoegd van <code>%[2]s</code> naar <code>%[3]s</code> %[4]s"
},
"repo.pulls.title_desc": {
"one": "wil %[1]d commit van <code>%[2]s</code> samenvoegen in <code id=\"%[4]s\">%[3]s</code>",
"other": "wil %[1]d commits van <code>%[2]s</code> samenvoegen in <code id=\"%[4]s\">%[3]s</code>"
"other": "wil %[1]d commits van <code>%[2]s</code> samenvoegen met <code id=\"%[4]s\">%[3]s</code>"
},
"search.milestone_kind": "Zoek mijlpalen…",
"home.welcome.no_activity": "Geen activiteit",
@ -13,27 +13,27 @@
"home.explore_repos": "Verken repositories",
"home.explore_users": "Verken gebruikers",
"home.explore_orgs": "Verken organisaties",
"incorrect_root_url": "Deze Forgejo-instantie is geconfigureerd om bereikbaar te zijn op \"%s\". U bekijkt Forgejo momenteel via een andere URL, waardoor onderdelen van de applicatie kunnen breken. De canonieke URL kan worden gewijzigd door Forgejo admins via de ROOT_URL instelling in de app.ini.",
"incorrect_root_url": "Deze Forgejo-instantie is geconfigureerd om geserveerd te worden op \"%s\". U bekijkt Forgejo momenteel via een andere URL, waardoor onderdelen van de applicatie kunnen breken. De canonieke URL kan worden gewijzigd door Forgejo admins via de ROOT_URL instelling in de app.ini.",
"themes.names.forgejo-auto": "Forgejo (volg het systeemthema)",
"themes.names.forgejo-light": "Forgejo licht",
"themes.names.forgejo-dark": "Forgejo donker",
"error.not_found.title": "Pagina niet gevonden",
"alert.asset_load_failed": "Het laden van hulp-bestanden vanuit {path} is mislukt. Controleer of de hulp-bestanden toegankelijk zijn.",
"install.invalid_lfs_path": "Kan de LFS-root niet aanmaken op de opgegeven locatie: %[1]s",
"alert.asset_load_failed": "Het laden van asset-bestanden van {path} is mislukt. Controleer of de asset-bestanden toegankelijk zijn.",
"install.invalid_lfs_path": "Kan de LFS-root niet aanmaken op het opgegeven pad: %[1]s",
"alert.range_error": " moet een getal zijn tussen %[1]s en %[2]s.",
"meta.last_line": "Wist je dat de paprika, behalve in de bekende kleuren rood, geel, oranje en groen, ook in de kleuren wit, paars, lila, muntgroen en bruin voorkomt.",
"mail.actions.successful_run_after_failure_subject": "Werkstroom %[1]s hersteld in repositorie %[2]s",
"mail.actions.not_successful_run_subject": "Werkstroom %[1]s mislukt in repositorie %[2]s",
"mail.actions.successful_run_after_failure": "Werkstroom %[1]s hersteld in repositorie %[2]s",
"mail.actions.not_successful_run": "Werkstroom %[1]s mislukt in repositorie %[2]s",
"mail.actions.successful_run_after_failure_subject": "Werkstroom %[1]s hersteld in repository %[2]s",
"mail.actions.not_successful_run_subject": "Werkstroom %[1]s mislukt in repository %[2]s",
"mail.actions.successful_run_after_failure": "Werkstroom %[1]s hersteld in repository %[2]s",
"mail.actions.not_successful_run": "Werkstroom %[1]s mislukt in repository %[2]s",
"mail.actions.run_info_cur_status": "De status van deze run: %[1]s (zojuist bijgewerkt van %[2]s)",
"mail.actions.run_info_previous_status": "Status vorige run: %[1]s",
"mail.actions.run_info_ref": "Branch: %[1]s (%[2]s)",
"mail.actions.run_info_trigger": "Getriggerd omdat: %[1]s door: %[2]s",
"discussion.locked": "Deze discussie is afgesloten. Commentaar is alleen mogelijk voor bijdragers.",
"discussion.locked": "Deze discussie is gesloten. Commentaar is beperkt tot bijdragers.",
"relativetime.now": "nu",
"relativetime.future": "in de toekomst",
"repo.form.cannot_create": "Alle ruimtes waarin u repositories kan maken hebben hun maximum aantal repositories bereikt.",
"repo.form.cannot_create": "Alle spaces waarin u repositories kan maken hebben hun maximum aantal repositories bereikt.",
"moderation.report_content": "Meldt content",
"moderation.report_abuse_form.header": "Meld misbruik bij de beheerder",
"moderation.report_abuse_form.invalid": "Ongeldige argumenten",
@ -86,11 +86,5 @@
"relativetime.hours": {
"one": "%d uur geleden",
"other": "%d uren geleden"
},
"repo.issue_indexer.title": "Issue indexer",
"stars.list.none": "Niemand heeft deze repo een ster gegeven.",
"watch.list.none": "Niemand houdt deze repo in de gaten.",
"followers.incoming.list.self.none": "Niemand volgt uw profiel.",
"followers.incoming.list.none": "Deze gebruiker wordt door niemand gevolgd.",
"followers.outgoing.list.self.none": "U volgt niemand."
}
}

View file

@ -98,7 +98,5 @@
"followers.incoming.list.none": "Ninguém está seguindo este perfil.",
"followers.outgoing.list.none": "%s não está seguindo ninguém.",
"stars.list.none": "Ninguém favoritou este repositório.",
"followers.outgoing.list.self.none": "Você não está seguindo ninguém.",
"editor.textarea.tab_hint": "Linha já indentada. Pressione <kbd>Tab</kbd> novamente ou <kbd>Esc</kbd> para sair do editor.",
"editor.textarea.shift_tab_hint": "Sem indentação nesta linha. Pressione <kbd>Shift</kbd> + <kbd>Tab</kbd> novamente ou <kbd>Esc</kbd> para sair do editor."
"followers.outgoing.list.self.none": "Você não está seguindo ninguém."
}

View file

@ -98,7 +98,5 @@
"moderation.reported_thank_you": "Спасибо за ваше сообщение. Администрация оповещена.",
"moderation.report_abuse_form.details": "Через эту форму можно жаловаться на пользователей, распространяющих спам или ведущих себя неадекватно.",
"moderation.report_abuse_form.invalid": "Невалидные аргументы",
"moderation.report_abuse_form.header": "Жалоба администрации",
"editor.textarea.tab_hint": "Отступ уже добавлен. Нажмите <kbd>Tab</kbd> снова или <kbd>Escape</kbd>, чтобы покинуть редактор.",
"editor.textarea.shift_tab_hint": "В строке нет отступов. Нажмите <kbd>Shift</kbd> + <kbd>Tab</kbd> снова или <kbd>Escape</kbd>, чтобы покинуть редактор."
"moderation.report_abuse_form.header": "Жалоба администрации"
}

View file

@ -66,7 +66,5 @@
"followers.outgoing.list.self.none": "你没有关注任何人。",
"followers.outgoing.list.none": "%s 没有关注任何人。",
"stars.list.none": "没有人点赞这个仓库。",
"followers.incoming.list.self.none": "没有人关注你的个人资料。",
"editor.textarea.tab_hint": "此行已缩进。再次按 <kbd>Tab</kbd> 或按 <kbd>Escape</kbd> 退出编辑器。",
"editor.textarea.shift_tab_hint": "此行无缩进。再次按 <kbd>Shift</kbd> + <kbd>Tab</kbd> 或按 <kbd>Escape</kbd> 退出编辑器。"
"followers.incoming.list.self.none": "没有人关注你的个人资料。"
}

View file

@ -1,71 +1,5 @@
{
"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>",
"search.milestone_kind": "搜尋里程碑…",
"home.welcome.no_activity": "沒有活動",
"home.welcome.activity_hint": "您的動態摘要目前沒有任何內容。 您對關注的儲存庫所做的操作與活動將會顯示在這裡。",
"stars.list.none": "沒有人標星這個儲存庫。",
"watch.list.none": "沒有人關注這個儲存庫。",
"home.explore_repos": "探索儲存庫",
"home.explore_users": "探索使用者",
"home.explore_orgs": "探索組織",
"alert.range_error": " 必須是一個介於 %[1]s 和 %[2]s 之間的數字。",
"install.invalid_lfs_path": "無法在指定路徑建立 LFS 根目錄:%[1]s",
"relativetime.now": "現在",
"relativetime.future": "未來",
"repo.form.cannot_create": "您可以建立儲存庫的所有空間都已達到儲存庫上限。",
"repo.issue_indexer.title": "問題索引器",
"moderation.abuse_category": "分類",
"moderation.abuse_category.placeholder": "選擇分類",
"moderation.abuse_category.spam": "垃圾訊息",
"moderation.abuse_category.malware": "惡意軟體",
"moderation.abuse_category.illegal_content": "違法內容",
"moderation.report_remarks.placeholder": "請提供您所檢舉濫用行為的相關細節。",
"moderation.report_remarks": "備註",
"moderation.submit_report": "提交檢舉",
"moderation.reporting_failed": "無法提交新的濫用回報:%v",
"moderation.reported_thank_you": "感謝您的回報,管理團隊已收到相關通知。",
"mail.actions.successful_run_after_failure_subject": "儲存庫 %[2]s 中的工作流程 %[1]s 已恢復",
"error.not_found.title": "找不到頁面",
"incorrect_root_url": "這個 Forgejo 實例設定為在 \"%s\" 上提供服務。您目前是透過不同的 URL 存取 Forgejo這可能會導致部分功能無法正常運作。正式的 URL 是由 Forgejo 管理員透過 app.ini 中的 ROOT_URL 設定所控制。",
"themes.names.forgejo-auto": "Forgejo遵循系統主題",
"themes.names.forgejo-light": "Forgejo 淺色",
"themes.names.forgejo-dark": "Forgejo 深色",
"followers.incoming.list.self.none": "沒有人關注您的個人資料。",
"followers.incoming.list.none": "沒有人關注這位使用者。",
"followers.outgoing.list.none": "%s 沒有追蹤任何人。",
"followers.outgoing.list.self.none": "您沒有追蹤任何人。",
"relativetime.mins": "%d 分鐘前",
"relativetime.hours": "%d 小時前",
"relativetime.days": "%d 天前",
"relativetime.weeks": "%d 周前",
"relativetime.months": "%d 個月前",
"relativetime.years": "%d 年前",
"relativetime.1day": "昨天",
"relativetime.2days": "兩天前",
"relativetime.1week": "上週",
"relativetime.2weeks": "兩週前",
"relativetime.1month": "上個月",
"relativetime.2months": "兩個月前",
"relativetime.1year": "去年",
"relativetime.2years": "兩年前",
"moderation.abuse_category.other_violations": "其他違反平台規則的行為",
"mail.actions.not_successful_run_subject": "儲存庫 %[2]s 中的工作流程 %[1]s 已失敗",
"mail.actions.successful_run_after_failure": "儲存庫 %[2]s 中的工作流程 %[1]s 已恢復",
"mail.actions.not_successful_run": "儲存庫 %[2]s 中的工作流程 %[1]s 已失敗",
"mail.actions.run_info_cur_status": "本次執行狀態:%[1]s剛從 %[2]s 更新)",
"mail.actions.run_info_previous_status": "前一次執行狀態:%[1]s",
"mail.actions.run_info_ref": "分支:%[1]s (%[2]s)",
"mail.actions.run_info_trigger": "觸發原因:%[1]s由 %[2]s 執行",
"discussion.locked": "此討論已被鎖定。僅限貢獻者留言。",
"alert.asset_load_failed": "無法從 {path} 載入資源檔案。請確保這些資源檔案可以被存取。",
"editor.textarea.tab_hint": "此行已縮排。再次按下 <kbd>Tab</kbd> 鍵或按下 <kbd>Escape</kbd> 鍵以離開編輯器。",
"editor.textarea.shift_tab_hint": "此行未縮排。請再次按下 <kbd>Shift</kbd> + <kbd>Tab</kbd>,或按下 <kbd>Escape</kbd> 鍵以離開編輯器。",
"admin.config.moderation_config": "審核設定",
"moderation.report_abuse": "回報濫用行為",
"moderation.report_content": "檢舉內容",
"moderation.report_abuse_form.header": "向管理員回報濫用",
"moderation.report_abuse_form.details": "這個表單是用來檢舉用戶建立垃圾帳號、儲存庫、問題、留言,或其他不當行為。",
"moderation.report_abuse_form.invalid": "無效參數",
"moderation.report_abuse_form.already_reported": "您已檢舉此內容"
"search.milestone_kind": "搜尋里程碑…"
}

1726
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@
"monaco-editor": "0.52.2",
"monaco-editor-webpack-plugin": "7.1.0",
"pdfobject": "2.3.0",
"postcss": "8.5.4",
"postcss": "8.5.2",
"postcss-loader": "8.1.1",
"postcss-nesting": "13.0.1",
"pretty-ms": "9.0.0",
@ -50,7 +50,7 @@
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
"vanilla-colorful": "0.7.2",
"vue": "3.5.16",
"vue": "3.5.14",
"vue-chartjs": "5.3.1",
"vue-loader": "17.4.2",
"vue3-calendar-heatmap": "2.0.5",
@ -59,46 +59,47 @@
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@axe-core/playwright": "4.10.2",
"@axe-core/playwright": "4.10.1",
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
"@playwright/test": "1.52.0",
"@stoplight/spectral-cli": "6.15.0",
"@stylistic/eslint-plugin-js": "4.4.1",
"@stylistic/eslint-plugin-js": "4.2.0",
"@stylistic/stylelint-plugin": "3.1.2",
"@vitejs/plugin-vue": "5.2.4",
"@vitest/coverage-v8": "3.2.3",
"@vitest/eslint-plugin": "1.2.1",
"@typescript-eslint/parser": "8.31.1",
"@vitejs/plugin-vue": "5.2.3",
"@vitest/coverage-v8": "3.1.2",
"@vitest/eslint-plugin": "1.1.43",
"@vue/test-utils": "2.4.6",
"eslint": "9.28.0",
"eslint-import-resolver-typescript": "4.4.3",
"eslint": "9.25.1",
"eslint-import-resolver-typescript": "4.3.4",
"eslint-plugin-array-func": "5.0.2",
"eslint-plugin-import-x": "4.15.1",
"eslint-plugin-import-x": "4.11.0",
"eslint-plugin-no-jquery": "3.1.1",
"eslint-plugin-no-use-extend-native": "0.7.2",
"eslint-plugin-playwright": "2.2.0",
"eslint-plugin-regexp": "2.9.0",
"eslint-plugin-regexp": "2.7.0",
"eslint-plugin-sonarjs": "3.0.2",
"eslint-plugin-unicorn": "59.0.1",
"eslint-plugin-unicorn": "59.0.0",
"eslint-plugin-toml": "0.12.0",
"eslint-plugin-vitest-globals": "1.5.0",
"eslint-plugin-vue": "10.2.0",
"eslint-plugin-vue-scoped-css": "2.10.0",
"eslint-plugin-vue": "10.1.0",
"eslint-plugin-vue-scoped-css": "2.9.0",
"eslint-plugin-wc": "2.2.1",
"globals": "16.1.0",
"happy-dom": "17.6.3",
"happy-dom": "17.4.6",
"license-checker-rseidelsohn": "4.4.2",
"markdownlint-cli": "0.45.0",
"markdownlint-cli": "0.44.0",
"postcss-html": "1.8.0",
"sharp": "0.34.2",
"stylelint": "16.20.0",
"stylelint": "16.19.1",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.11",
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.2.0",
"typescript": "5.8.3",
"typescript-eslint": "8.33.1",
"typescript-eslint": "8.31.1",
"vite-string-plugin": "1.3.4",
"vitest": "3.2.3"
"vitest": "3.1.2"
},
"browserslist": [
"defaults"

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