mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-07-23 19:00:02 +02:00
Compare commits
54 commits
cbeb28a0dd
...
f7b3ac4930
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f7b3ac4930 | ||
![]() |
a1bec15043 | ||
![]() |
9a1c10f92e | ||
![]() |
1d3208898f | ||
![]() |
8d80a9cc01 | ||
![]() |
881cdf88bb | ||
![]() |
d3adaf7574 | ||
![]() |
81c960f0c2 | ||
![]() |
580efedad4 | ||
![]() |
e70f48bd44 | ||
![]() |
bd6f3243ab | ||
![]() |
b2b039b6e7 | ||
![]() |
a8e375eb28 | ||
![]() |
4b6ccbd631 | ||
![]() |
4d44ae39e1 | ||
![]() |
db83b43d8d | ||
![]() |
6d7f5fb41e | ||
![]() |
dc2954f8fe | ||
![]() |
7428edacbe | ||
![]() |
10da5e5609 | ||
![]() |
f476ee2196 | ||
![]() |
1242786324 | ||
![]() |
e0bfacac0b | ||
![]() |
b68f923592 | ||
![]() |
82e4ccc223 | ||
![]() |
8f2c08b8dc | ||
![]() |
dcf1eef9e9 | ||
![]() |
249f1fc17e | ||
![]() |
313504739f | ||
![]() |
7df94ff7b2 | ||
![]() |
60adf59620 | ||
![]() |
805e749a15 | ||
![]() |
e4c43c0cec | ||
![]() |
a24ca6e4b4 | ||
![]() |
534020d0ad | ||
![]() |
39d3e874b0 | ||
![]() |
905a5748a8 | ||
![]() |
2529923dea | ||
![]() |
4dd0514022 | ||
![]() |
d17aa98262 | ||
![]() |
6ce9d764bc | ||
![]() |
549fcff997 | ||
![]() |
bc14ad7da2 | ||
![]() |
48671975f1 | ||
![]() |
240d958c0f | ||
![]() |
ea07f0c0f3 | ||
![]() |
e38e761d5b | ||
![]() |
ac1f1a9cfb | ||
![]() |
dbbd0de860 | ||
![]() |
9ecef99ab9 | ||
![]() |
374def9922 | ||
![]() |
3bb6ed8f19 | ||
![]() |
0ed7237b12 | ||
![]() |
fc35915a28 |
185 changed files with 5797 additions and 2172 deletions
|
@ -87,12 +87,24 @@ forgejo.org/modules/eventsource
|
||||||
Event.String
|
Event.String
|
||||||
|
|
||||||
forgejo.org/modules/forgefed
|
forgejo.org/modules/forgefed
|
||||||
|
NewForgeFollowFromAp
|
||||||
|
NewForgeFollow
|
||||||
|
ForgeFollow.MarshalJSON
|
||||||
|
ForgeFollow.UnmarshalJSON
|
||||||
|
ForgeFollow.Validate
|
||||||
NewForgeUndoLike
|
NewForgeUndoLike
|
||||||
ForgeUndoLike.UnmarshalJSON
|
ForgeUndoLike.UnmarshalJSON
|
||||||
ForgeUndoLike.Validate
|
ForgeUndoLike.Validate
|
||||||
|
NewForgeUserActivityFromAp
|
||||||
|
NewForgeUserActivity
|
||||||
|
ForgeUserActivity.Validate
|
||||||
|
NewPersonIDFromModel
|
||||||
GetItemByType
|
GetItemByType
|
||||||
JSONUnmarshalerFn
|
JSONUnmarshalerFn
|
||||||
NotEmpty
|
NotEmpty
|
||||||
|
NewForgeUserActivityNoteFromAp
|
||||||
|
newNote
|
||||||
|
ForgeUserActivityNote.Validate
|
||||||
ToRepository
|
ToRepository
|
||||||
OnRepository
|
OnRepository
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
|
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: data.forgejo.org/renovate/renovate:40.31.0
|
image: data.forgejo.org/renovate/renovate:40.48.4
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Load renovate repo cache
|
- name: Load renovate repo cache
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -37,19 +37,18 @@ endif
|
||||||
XGO_VERSION := go-1.21.x
|
XGO_VERSION := go-1.21.x
|
||||||
|
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
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.2.1 # renovate: datasource=go
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.3.0 # renovate: datasource=go
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 # 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
|
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
|
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
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go
|
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
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
|
||||||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.32.0 # 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.1 # renovate: datasource=go
|
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.2 # renovate: datasource=go
|
||||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
|
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
|
||||||
RENOVATE_NPM_PACKAGE ?= renovate@40.31.0 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
RENOVATE_NPM_PACKAGE ?= renovate@40.48.4 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||||
|
|
||||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||||
|
@ -924,7 +923,6 @@ deps-tools:
|
||||||
$(GO) install $(GOFUMPT_PACKAGE)
|
$(GO) install $(GOFUMPT_PACKAGE)
|
||||||
$(GO) install $(GOLANGCI_LINT_PACKAGE)
|
$(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||||
$(GO) install $(GXZ_PACKAGE)
|
$(GO) install $(GXZ_PACKAGE)
|
||||||
$(GO) install $(MISSPELL_PACKAGE)
|
|
||||||
$(GO) install $(SWAGGER_PACKAGE)
|
$(GO) install $(SWAGGER_PACKAGE)
|
||||||
$(GO) install $(XGO_PACKAGE)
|
$(GO) install $(XGO_PACKAGE)
|
||||||
$(GO) install $(GO_LICENSES_PACKAGE)
|
$(GO) install $(GO_LICENSES_PACKAGE)
|
||||||
|
|
|
@ -18,6 +18,7 @@ func subcmdUser() *cli.Command {
|
||||||
microcmdUserDelete(),
|
microcmdUserDelete(),
|
||||||
microcmdUserGenerateAccessToken(),
|
microcmdUserGenerateAccessToken(),
|
||||||
microcmdUserMustChangePassword(),
|
microcmdUserMustChangePassword(),
|
||||||
|
microcmdUserResetMFA(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
73
cmd/admin_user_reset_mfa.go
Normal file
73
cmd/admin_user_reset_mfa.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -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 {
|
func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command, globalFlagsArgs func() []cli.Flag) *cli.Command {
|
||||||
app := &cli.Command{}
|
app := &cli.Command{}
|
||||||
app.Name = "Forgejo"
|
app.Name = "forgejo"
|
||||||
app.Usage = "Beyond coding. We forge."
|
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.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
|
app.Version = version + versionExtra
|
||||||
|
|
|
@ -408,7 +408,7 @@ local addIssueLabelsOverrides(labels) =
|
||||||
regex: '',
|
regex: '',
|
||||||
type: 'query',
|
type: 'query',
|
||||||
multi: true,
|
multi: true,
|
||||||
allValue: '.+'
|
allValue: '.+',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.addTemplate(
|
.addTemplate(
|
||||||
|
@ -423,7 +423,7 @@ local addIssueLabelsOverrides(labels) =
|
||||||
regex: '',
|
regex: '',
|
||||||
type: 'query',
|
type: 'query',
|
||||||
multi: true,
|
multi: true,
|
||||||
allValue: '.+'
|
allValue: '.+',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.addTemplate(
|
.addTemplate(
|
||||||
|
|
|
@ -183,7 +183,7 @@ RUN_USER = ; git
|
||||||
;;
|
;;
|
||||||
;; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
|
;; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
|
||||||
;; for system SSH this setting has no effect
|
;; for system SSH this setting has no effect
|
||||||
;SSH_SERVER_KEY_EXCHANGES = curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1
|
;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
|
||||||
;;
|
;;
|
||||||
;; For the built-in SSH server, choose the MACs to support for SSH connections,
|
;; For the built-in SSH server, choose the MACs to support for SSH connections,
|
||||||
;; for system SSH this setting has no effect
|
;; for system SSH this setting has no effect
|
||||||
|
@ -1025,6 +1025,10 @@ LEVEL = Info
|
||||||
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
|
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
|
||||||
;DEFAULT_FORK_REPO_UNITS = repo.code,repo.pulls
|
;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 by placing them in a directory named after the repository
|
||||||
;PREFIX_ARCHIVE_FILES = true
|
;PREFIX_ARCHIVE_FILES = true
|
||||||
;;
|
;;
|
||||||
|
|
26
go.mod
26
go.mod
|
@ -2,10 +2,10 @@ module forgejo.org
|
||||||
|
|
||||||
go 1.24
|
go 1.24
|
||||||
|
|
||||||
toolchain go1.24.3
|
toolchain go1.24.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.forgejo.org/f3/gof3/v3 v3.10.8
|
code.forgejo.org/f3/gof3/v3 v3.11.0
|
||||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
|
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/go-rpmutils v1.0.0
|
||||||
code.forgejo.org/forgejo/levelqueue 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/actions-proto-go v0.4.0
|
||||||
code.gitea.io/sdk/gitea v0.21.0
|
code.gitea.io/sdk/gitea v0.21.0
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||||
connectrpc.com/connect v1.17.0
|
connectrpc.com/connect v1.18.1
|
||||||
github.com/42wim/httpsig v1.2.3
|
github.com/42wim/httpsig v1.2.3
|
||||||
github.com/42wim/sshsig v0.0.0-20250502153856-5100632e8920
|
github.com/42wim/sshsig v0.0.0-20250502153856-5100632e8920
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
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/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||||
github.com/alecthomas/chroma/v2 v2.18.0
|
github.com/alecthomas/chroma/v2 v2.18.0
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||||
github.com/blevesearch/bleve/v2 v2.5.1
|
github.com/blevesearch/bleve/v2 v2.5.2
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
||||||
github.com/caddyserver/certmagic v0.23.0
|
github.com/caddyserver/certmagic v0.23.0
|
||||||
github.com/chi-middleware/proxy v1.1.1
|
github.com/chi-middleware/proxy v1.1.1
|
||||||
|
@ -87,8 +87,8 @@ require (
|
||||||
github.com/prometheus/client_golang v1.21.1
|
github.com/prometheus/client_golang v1.21.1
|
||||||
github.com/redis/go-redis/v9 v9.8.0
|
github.com/redis/go-redis/v9 v9.8.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
github.com/sergi/go-diff v1.4.0
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
|
@ -101,13 +101,13 @@ require (
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
gitlab.com/gitlab-org/api/client-go v0.129.0
|
gitlab.com/gitlab-org/api/client-go v0.129.0
|
||||||
go.uber.org/mock v0.5.2
|
go.uber.org/mock v0.5.2
|
||||||
golang.org/x/crypto v0.38.0
|
golang.org/x/crypto v0.39.0
|
||||||
golang.org/x/image v0.27.0
|
golang.org/x/image v0.27.0
|
||||||
golang.org/x/net v0.40.0
|
golang.org/x/net v0.41.0
|
||||||
golang.org/x/oauth2 v0.30.0
|
golang.org/x/oauth2 v0.30.0
|
||||||
golang.org/x/sync v0.14.0
|
golang.org/x/sync v0.15.0
|
||||||
golang.org/x/sys v0.33.0
|
golang.org/x/sys v0.33.0
|
||||||
golang.org/x/text v0.25.0
|
golang.org/x/text v0.26.0
|
||||||
google.golang.org/protobuf v1.36.4
|
google.golang.org/protobuf v1.36.4
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/ini.v1 v1.67.0
|
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/v13 v13.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v14 v14.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/v15 v15.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v16 v16.2.3 // indirect
|
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.3 // 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/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
go.uber.org/zap/exp v0.3.0 // indirect
|
go.uber.org/zap/exp v0.3.0 // indirect
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
golang.org/x/mod v0.25.0 // indirect
|
||||||
golang.org/x/time v0.11.0 // indirect
|
golang.org/x/time v0.11.0 // indirect
|
||||||
golang.org/x/tools v0.31.0 // indirect
|
golang.org/x/tools v0.34.0 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
)
|
)
|
||||||
|
|
48
go.sum
48
go.sum
|
@ -1,7 +1,7 @@
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||||
code.forgejo.org/f3/gof3/v3 v3.10.8 h1:cL5XgOcKffqMdKDOqGCXfMc2OBX89xYvGSj2mz3E/VQ=
|
code.forgejo.org/f3/gof3/v3 v3.11.0 h1:f/xToKwqTgxG6PYxvewywjDQyCcyHEEJ6sZqUitFsAE=
|
||||||
code.forgejo.org/f3/gof3/v3 v3.10.8/go.mod h1:ovgb7R8o7k6poQKQ+KWXHOD9uIoanB6tNSmA3kKOMCI=
|
code.forgejo.org/f3/gof3/v3 v3.11.0/go.mod h1:4FaRUNSQGBiD1M0DuB0yNv+Z2wMtlOeckgygHSSq4KQ=
|
||||||
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 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
|
||||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
|
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=
|
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=
|
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 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
||||||
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
|
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
|
||||||
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
||||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
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/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 h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||||
github.com/blevesearch/bleve/v2 v2.5.1 h1:cc/O++W2Hcjp1SU5ETHeE+QYWv2oV88ldYEPowdmg8M=
|
github.com/blevesearch/bleve/v2 v2.5.2 h1:Ab0r0MODV2C5A6BEL87GqLBySqp/s9xFgceCju6BQk8=
|
||||||
github.com/blevesearch/bleve/v2 v2.5.1/go.mod h1:9g/wnbWKm9AgXrU8Ecqi+IDdqjUHWymwkQRDg+5tafU=
|
github.com/blevesearch/bleve/v2 v2.5.2/go.mod h1:5Dj6dUQxZM6aqYT3eutTD/GpWKGFSsV8f7LDidFbwXo=
|
||||||
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
|
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/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||||
github.com/blevesearch/geo v0.2.3 h1:K9/vbGI9ehlXdxjxDRJtoAMt7zGAsMIzc6n8zWcwnhg=
|
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/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 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||||
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||||
github.com/blevesearch/zapx/v16 v16.2.3 h1:7Y0r+a3diEvlazsncexq1qoFOcBd64xwMS7aDm4lo1s=
|
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
|
||||||
github.com/blevesearch/zapx/v16 v16.2.3/go.mod h1:wVJ+GtURAaRG9KQAMNYyklq0egV+XJlGcXNCE0OFjjA=
|
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
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 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
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/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 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||||
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
github.com/sergi/go-diff v1.4.0/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 h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
|
||||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
|
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=
|
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.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.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
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/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
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.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.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.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.25.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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
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.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
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.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
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/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=
|
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.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.7.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.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.15.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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.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.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
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=
|
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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
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.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
38
manifest.scm
Normal file
38
manifest.scm
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
;;; 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"))
|
|
@ -54,6 +54,8 @@ type FindRunJobOptions struct {
|
||||||
CommitSHA string
|
CommitSHA string
|
||||||
Statuses []Status
|
Statuses []Status
|
||||||
UpdatedBefore timeutil.TimeStamp
|
UpdatedBefore timeutil.TimeStamp
|
||||||
|
Events []string // []webhook_module.HookEventType
|
||||||
|
RunNumber int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts FindRunJobOptions) ToConds() builder.Cond {
|
func (opts FindRunJobOptions) ToConds() builder.Cond {
|
||||||
|
@ -76,5 +78,11 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
|
||||||
if opts.UpdatedBefore > 0 {
|
if opts.UpdatedBefore > 0 {
|
||||||
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
|
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
|
return cond
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
repo_model "forgejo.org/models/repo"
|
repo_model "forgejo.org/models/repo"
|
||||||
"forgejo.org/models/shared/types"
|
"forgejo.org/models/shared/types"
|
||||||
user_model "forgejo.org/models/user"
|
user_model "forgejo.org/models/user"
|
||||||
|
"forgejo.org/modules/log"
|
||||||
"forgejo.org/modules/optional"
|
"forgejo.org/modules/optional"
|
||||||
"forgejo.org/modules/timeutil"
|
"forgejo.org/modules/timeutil"
|
||||||
"forgejo.org/modules/translation"
|
"forgejo.org/modules/translation"
|
||||||
|
@ -353,3 +354,53 @@ func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
|
||||||
}
|
}
|
||||||
return res.RowsAffected()
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -6,10 +6,12 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
auth_model "forgejo.org/models/auth"
|
auth_model "forgejo.org/models/auth"
|
||||||
"forgejo.org/models/db"
|
"forgejo.org/models/db"
|
||||||
"forgejo.org/models/unittest"
|
"forgejo.org/models/unittest"
|
||||||
|
"forgejo.org/modules/timeutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -73,3 +75,68 @@ func TestDeleteRunner(t *testing.T) {
|
||||||
idAsBinary[6], idAsBinary[7])
|
idAsBinary[6], idAsBinary[7])
|
||||||
assert.Equal(t, idAsHexadecimal, after.UUID[19:])
|
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))
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,15 @@ var statusNames = map[Status]string{
|
||||||
StatusBlocked: "blocked",
|
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
|
// String returns the string name of the Status
|
||||||
func (s Status) String() string {
|
func (s Status) String() string {
|
||||||
return statusNames[s]
|
return statusNames[s]
|
||||||
|
@ -102,3 +111,8 @@ func (s Status) AsResult() runnerv1.Result {
|
||||||
}
|
}
|
||||||
return runnerv1.Result_RESULT_UNSPECIFIED
|
return runnerv1.Result_RESULT_UNSPECIFIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StatusFromString(name string) (Status, bool) {
|
||||||
|
status, exists := nameToStatus[name]
|
||||||
|
return status, exists
|
||||||
|
}
|
||||||
|
|
|
@ -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.
|
// The ssh library can parse the key, so next we find out what key exactly we have.
|
||||||
switch pkeyType {
|
switch pkeyType {
|
||||||
case ssh.KeyAlgoDSA:
|
case ssh.KeyAlgoDSA: //nolint:staticcheck
|
||||||
rawPub := struct {
|
rawPub := struct {
|
||||||
Name string
|
Name string
|
||||||
P, Q, G, Y *big.Int
|
P, Q, G, Y *big.Int
|
||||||
|
|
|
@ -471,3 +471,64 @@
|
||||||
need_approval: 0
|
need_approval: 0
|
||||||
approved_by: 0
|
approved_by: 0
|
||||||
event_payload: '{"head_commit":{"id":"5f22f7d0d95d614d25a5b68592adb345a4b5c7fd"}}'
|
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
|
||||||
|
|
|
@ -18,3 +18,122 @@
|
||||||
created: 1716104432
|
created: 1716104432
|
||||||
updated: 1716104432
|
updated: 1716104432
|
||||||
deleted: ~
|
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: ~
|
||||||
|
|
|
@ -795,3 +795,10 @@
|
||||||
type: 10
|
type: 10
|
||||||
config: "{}"
|
config: "{}"
|
||||||
created_unix: 946684810
|
created_unix: 946684810
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 115
|
||||||
|
repo_id: 63
|
||||||
|
type: 10
|
||||||
|
config: "{}"
|
||||||
|
created_unix: 946684810
|
||||||
|
|
|
@ -1889,3 +1889,35 @@
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
topics: '[]'
|
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: '[]'
|
||||||
|
|
|
@ -239,3 +239,15 @@
|
||||||
num_members: 2
|
num_members: 2
|
||||||
includes_all_repositories: false
|
includes_all_repositories: false
|
||||||
can_create_org_repo: 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
|
||||||
|
|
|
@ -329,3 +329,10 @@
|
||||||
team_id: 22
|
team_id: 22
|
||||||
type: 3
|
type: 3
|
||||||
access_mode: 1
|
access_mode: 1
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 84
|
||||||
|
org_id: 17
|
||||||
|
team_id: 25
|
||||||
|
type: 3
|
||||||
|
access_mode: 3
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
num_followers: 2
|
num_followers: 2
|
||||||
num_following: 1
|
num_following: 1
|
||||||
num_stars: 2
|
num_stars: 2
|
||||||
num_repos: 17
|
num_repos: 18
|
||||||
num_teams: 0
|
num_teams: 0
|
||||||
num_members: 0
|
num_members: 0
|
||||||
visibility: 0
|
visibility: 0
|
||||||
|
@ -642,7 +642,7 @@
|
||||||
num_following: 0
|
num_following: 0
|
||||||
num_stars: 0
|
num_stars: 0
|
||||||
num_repos: 2
|
num_repos: 2
|
||||||
num_teams: 3
|
num_teams: 4
|
||||||
num_members: 4
|
num_members: 4
|
||||||
visibility: 0
|
visibility: 0
|
||||||
repo_admin_change_team_access: false
|
repo_admin_change_team_access: false
|
||||||
|
|
|
@ -10,16 +10,45 @@ import (
|
||||||
|
|
||||||
func SetTopicsAsEmptySlice(x *xorm.Engine) error {
|
func SetTopicsAsEmptySlice(x *xorm.Engine) error {
|
||||||
var err error
|
var err error
|
||||||
if x.Dialect().URI().DBType == schemas.POSTGRES {
|
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:
|
||||||
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics::text = 'null'")
|
_, 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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
type Repository struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
Topics []string `xorm:"TEXT JSON NOT NULL"`
|
Topics []string `xorm:"TEXT JSON NOT NULL"`
|
||||||
|
|
5
models/organization/TestFindOrgs/org_user.yml
Normal file
5
models/organization/TestFindOrgs/org_user.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
-
|
||||||
|
id: 1000
|
||||||
|
uid: 4
|
||||||
|
org_id: 22
|
||||||
|
is_public: true
|
|
@ -26,6 +26,7 @@ type SearchOrganizationsOptions struct {
|
||||||
type FindOrgOptions struct {
|
type FindOrgOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
UserID int64
|
UserID int64
|
||||||
|
IncludeLimited bool
|
||||||
IncludePrivate bool
|
IncludePrivate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +44,11 @@ func (opts FindOrgOptions) ToConds() builder.Cond {
|
||||||
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
|
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
|
||||||
}
|
}
|
||||||
if !opts.IncludePrivate {
|
if !opts.IncludePrivate {
|
||||||
|
if !opts.IncludeLimited {
|
||||||
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
|
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
|
||||||
|
} else {
|
||||||
|
cond = cond.And(builder.In("`user`.visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ func TestCountOrganizations(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindOrgs(t *testing.T) {
|
func TestFindOrgs(t *testing.T) {
|
||||||
|
defer unittest.OverrideFixtures("models/organization/TestFindOrgs")()
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
|
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
|
||||||
|
@ -34,8 +35,14 @@ func TestFindOrgs(t *testing.T) {
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, orgs, 1) {
|
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, 3, orgs[0].ID)
|
||||||
|
assert.EqualValues(t, 22, orgs[1].ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
|
orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
|
||||||
|
@ -50,6 +57,14 @@ func TestFindOrgs(t *testing.T) {
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
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)
|
assert.EqualValues(t, 1, total)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,7 +235,7 @@ func UpdateAttachmentByUUID(ctx context.Context, attach *Attachment, cols ...str
|
||||||
if attach.UUID == "" {
|
if attach.UUID == "" {
|
||||||
return errors.New("attachment uuid should be not blank")
|
return errors.New("attachment uuid should be not blank")
|
||||||
}
|
}
|
||||||
if attach.ExternalURL != "" && !validation.IsValidExternalURL(attach.ExternalURL) {
|
if attach.ExternalURL != "" && !validation.IsValidReleaseAssetURL(attach.ExternalURL) {
|
||||||
return ErrInvalidExternalURL{ExternalURL: attach.ExternalURL}
|
return ErrInvalidExternalURL{ExternalURL: attach.ExternalURL}
|
||||||
}
|
}
|
||||||
_, err := db.GetEngine(ctx).Where("uuid=?", attach.UUID).Cols(cols...).Update(attach)
|
_, 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
|
// UpdateAttachment updates the given attachment in database
|
||||||
func UpdateAttachment(ctx context.Context, atta *Attachment) error {
|
func UpdateAttachment(ctx context.Context, atta *Attachment) error {
|
||||||
if atta.ExternalURL != "" && !validation.IsValidExternalURL(atta.ExternalURL) {
|
if atta.ExternalURL != "" && !validation.IsValidReleaseAssetURL(atta.ExternalURL) {
|
||||||
return ErrInvalidExternalURL{ExternalURL: atta.ExternalURL}
|
return ErrInvalidExternalURL{ExternalURL: atta.ExternalURL}
|
||||||
}
|
}
|
||||||
sess := db.GetEngine(ctx).Cols("name", "issue_id", "release_id", "comment_id", "download_count")
|
sess := db.GetEngine(ctx).Cols("name", "issue_id", "release_id", "comment_id", "download_count")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package unit
|
package unit
|
||||||
|
@ -69,7 +70,7 @@ func (u Type) LogString() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// AllRepoUnitTypes contains all the unit types
|
// AllRepoUnitTypes contains all units
|
||||||
AllRepoUnitTypes = []Type{
|
AllRepoUnitTypes = []Type{
|
||||||
TypeCode,
|
TypeCode,
|
||||||
TypeIssues,
|
TypeIssues,
|
||||||
|
@ -83,7 +84,7 @@ var (
|
||||||
TypeActions,
|
TypeActions,
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultRepoUnits contains the default unit types
|
// DefaultRepoUnits contains default units for regular repos
|
||||||
DefaultRepoUnits = []Type{
|
DefaultRepoUnits = []Type{
|
||||||
TypeCode,
|
TypeCode,
|
||||||
TypeIssues,
|
TypeIssues,
|
||||||
|
@ -95,12 +96,22 @@ var (
|
||||||
TypeActions,
|
TypeActions,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForkRepoUnits contains the default unit types for forks
|
// ForkRepoUnits contains default units for forks
|
||||||
DefaultForkRepoUnits = []Type{
|
DefaultForkRepoUnits = []Type{
|
||||||
TypeCode,
|
TypeCode,
|
||||||
TypePullRequests,
|
TypePullRequests,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultMirrorRepoUnits contains default units for mirrors
|
||||||
|
DefaultMirrorRepoUnits = []Type{
|
||||||
|
TypeCode,
|
||||||
|
TypeIssues,
|
||||||
|
TypeReleases,
|
||||||
|
TypeWiki,
|
||||||
|
TypeProjects,
|
||||||
|
TypePackages,
|
||||||
|
}
|
||||||
|
|
||||||
// NotAllowedDefaultRepoUnits contains units that can't be default
|
// NotAllowedDefaultRepoUnits contains units that can't be default
|
||||||
NotAllowedDefaultRepoUnits = []Type{
|
NotAllowedDefaultRepoUnits = []Type{
|
||||||
TypeExternalWiki,
|
TypeExternalWiki,
|
||||||
|
@ -172,6 +183,8 @@ func LoadUnitConfig() error {
|
||||||
if len(DefaultRepoUnits) == 0 {
|
if len(DefaultRepoUnits) == 0 {
|
||||||
return errors.New("no default repository units found")
|
return errors.New("no default repository units found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default fork repo units
|
||||||
setDefaultForkRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultForkRepoUnits...)
|
setDefaultForkRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultForkRepoUnits...)
|
||||||
if len(invalidKeys) > 0 {
|
if len(invalidKeys) > 0 {
|
||||||
log.Warn("Invalid keys in default fork repo units: %s", strings.Join(invalidKeys, ", "))
|
log.Warn("Invalid keys in default fork repo units: %s", strings.Join(invalidKeys, ", "))
|
||||||
|
@ -181,6 +194,16 @@ func LoadUnitConfig() error {
|
||||||
return errors.New("no default fork repository units found")
|
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
|
// Collect the allowed repo unit groups. Mutually exclusive units are
|
||||||
// grouped together.
|
// grouped together.
|
||||||
AllowedRepoUnitGroups = [][]Type{}
|
AllowedRepoUnitGroups = [][]Type{}
|
||||||
|
|
|
@ -299,6 +299,24 @@ func (w *Webhook) HasPackageEvent() bool {
|
||||||
(w.ChooseEvents && w.Package)
|
(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.
|
// HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event.
|
||||||
func (w *Webhook) HasPullRequestReviewRequestEvent() bool {
|
func (w *Webhook) HasPullRequestReviewRequestEvent() bool {
|
||||||
return w.SendEverything ||
|
return w.SendEverything ||
|
||||||
|
@ -337,6 +355,9 @@ func (w *Webhook) EventCheckers() []struct {
|
||||||
{w.HasReleaseEvent, webhook_module.HookEventRelease},
|
{w.HasReleaseEvent, webhook_module.HookEventRelease},
|
||||||
{w.HasPackageEvent, webhook_module.HookEventPackage},
|
{w.HasPackageEvent, webhook_module.HookEventPackage},
|
||||||
{w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest},
|
{w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest},
|
||||||
|
{w.HasActionRunFailureEvent, webhook_module.HookEventActionRunFailure},
|
||||||
|
{w.HasActionRunRecoverEvent, webhook_module.HookEventActionRunRecover},
|
||||||
|
{w.HasActionRunSuccessEvent, webhook_module.HookEventActionRunSuccess},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,8 @@ func TestWebhook_EventsArray(t *testing.T) {
|
||||||
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
|
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
|
||||||
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
|
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
|
||||||
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
|
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
|
||||||
"package", "pull_request_review_request",
|
"package", "pull_request_review_request", "action_run_failure",
|
||||||
|
"action_run_recover", "action_run_success",
|
||||||
},
|
},
|
||||||
(&Webhook{
|
(&Webhook{
|
||||||
HookEvent: &webhook_module.HookEvent{SendEverything: true},
|
HookEvent: &webhook_module.HookEvent{SendEverything: true},
|
||||||
|
@ -89,15 +90,78 @@ func TestWebhook_EventsArray(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateWebhook(t *testing.T) {
|
func TestCreateWebhook(t *testing.T) {
|
||||||
|
t.Run("Some chosen events 1", func(t *testing.T) {
|
||||||
hook := &Webhook{
|
hook := &Webhook{
|
||||||
RepoID: 3,
|
RepoID: 3,
|
||||||
URL: "https://www.example.com/unit_test",
|
URL: "https://www.example.com/unit_test",
|
||||||
ContentType: ContentTypeJSON,
|
ContentType: ContentTypeJSON,
|
||||||
Events: `{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}`,
|
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"create":false,"push":true,"pull_request":true}}`,
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hook)
|
unittest.AssertNotExistsBean(t, hook)
|
||||||
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
|
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
|
||||||
unittest.AssertExistsAndLoadBean(t, 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())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWebhookByRepoID(t *testing.T) {
|
func TestGetWebhookByRepoID(t *testing.T) {
|
||||||
|
|
57
modules/forgefed/activity_follow.go
Normal file
57
modules/forgefed/activity_follow.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// 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
|
||||||
|
}
|
31
modules/forgefed/activity_follow_test.go
Normal file
31
modules/forgefed/activity_follow_test.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
77
modules/forgefed/activity_user_activity.go
Normal file
77
modules/forgefed/activity_user_activity.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// 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
|
||||||
|
}
|
40
modules/forgefed/activity_user_activity_test.go
Normal file
40
modules/forgefed/activity_user_activity_test.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// 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())
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,8 +10,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"forgejo.org/modules/validation"
|
"forgejo.org/modules/validation"
|
||||||
|
|
||||||
ap "github.com/go-ap/activitypub"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ----------------------------- ActorID --------------------------------------------
|
// ----------------------------- ActorID --------------------------------------------
|
||||||
|
@ -41,12 +39,18 @@ func NewActorID(uri string) (ActorID, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id ActorID) AsURI() string {
|
func (id ActorID) AsURI() string {
|
||||||
var result string
|
var result, path string
|
||||||
|
|
||||||
|
if id.Path == "" {
|
||||||
|
path = id.ID
|
||||||
|
} else {
|
||||||
|
path = fmt.Sprintf("%s/%s", id.Path, id.ID)
|
||||||
|
}
|
||||||
|
|
||||||
if id.IsPortSupplemented {
|
if id.IsPortSupplemented {
|
||||||
result = fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID)
|
result = fmt.Sprintf("%s://%s/%s", id.HostSchema, id.Host, path)
|
||||||
} else {
|
} else {
|
||||||
result = fmt.Sprintf("%s://%s:%d/%s/%s", id.HostSchema, id.Host, id.HostPort, id.Path, id.ID)
|
result = fmt.Sprintf("%s://%s:%d/%s", id.HostSchema, id.Host, id.HostPort, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -54,8 +58,7 @@ func (id ActorID) AsURI() string {
|
||||||
|
|
||||||
func (id ActorID) Validate() []string {
|
func (id ActorID) Validate() []string {
|
||||||
var result []string
|
var result []string
|
||||||
result = append(result, validation.ValidateNotEmpty(id.ID, "userId")...)
|
result = append(result, validation.ValidateNotEmpty(id.ID, "ID")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
|
|
||||||
result = append(result, validation.ValidateNotEmpty(id.Host, "host")...)
|
result = append(result, validation.ValidateNotEmpty(id.Host, "host")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(id.HostPort, "hostPort")...)
|
result = append(result, validation.ValidateNotEmpty(id.HostPort, "hostPort")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(id.HostSchema, "hostSchema")...)
|
result = append(result, validation.ValidateNotEmpty(id.HostSchema, "hostSchema")...)
|
||||||
|
@ -68,115 +71,6 @@ func (id ActorID) Validate() []string {
|
||||||
return result
|
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) {
|
func newActorID(uri string) (ActorID, error) {
|
||||||
validatedURI, err := url.ParseRequestURI(uri)
|
validatedURI, err := url.ParseRequestURI(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -212,28 +106,21 @@ func newActorID(uri string) (ActorID, error) {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------- ForgePerson -------------------------------------
|
func containsEmptyString(ar []string) bool {
|
||||||
|
for _, elem := range ar {
|
||||||
// ForgePerson activity data type
|
if elem == "" {
|
||||||
// swagger:model
|
return true
|
||||||
type ForgePerson struct {
|
}
|
||||||
// swagger:ignore
|
}
|
||||||
ap.Actor
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s ForgePerson) MarshalJSON() ([]byte, error) {
|
func removeEmptyStrings(ls []string) []string {
|
||||||
return s.Actor.MarshalJSON()
|
var rs []string
|
||||||
|
for _, str := range ls {
|
||||||
|
if str != "" {
|
||||||
|
rs = append(rs, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ForgePerson) UnmarshalJSON(data []byte) error {
|
|
||||||
return s.Actor.UnmarshalJSON(data)
|
|
||||||
}
|
}
|
||||||
|
return rs
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
122
modules/forgefed/actor_person.go
Normal file
122
modules/forgefed/actor_person.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
// 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
|
||||||
|
}
|
268
modules/forgefed/actor_person_test.go
Normal file
268
modules/forgefed/actor_person_test.go
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
// 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())
|
||||||
|
}
|
52
modules/forgefed/actor_repository.go
Normal file
52
modules/forgefed/actor_repository.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// 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
|
||||||
|
}
|
45
modules/forgefed/actor_repository_test.go
Normal file
45
modules/forgefed/actor_repository_test.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// 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)
|
||||||
|
}
|
|
@ -4,258 +4,71 @@
|
||||||
package forgefed
|
package forgefed
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"forgejo.org/modules/setting"
|
"github.com/stretchr/testify/assert"
|
||||||
"forgejo.org/modules/validation"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
ap "github.com/go-ap/activitypub"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewPersonId(t *testing.T) {
|
func TestActorNew(t *testing.T) {
|
||||||
expected := PersonID{}
|
sut, err := NewActorID("https://an.other.forgejo.host/api/v1/activitypub/user-id/5")
|
||||||
expected.ID = "1"
|
require.NoError(t, err)
|
||||||
expected.Source = "forgejo"
|
assert.Equal(t, ActorID{
|
||||||
expected.HostSchema = "https"
|
ID: "5",
|
||||||
expected.Path = "api/v1/activitypub/user-id"
|
HostSchema: "https",
|
||||||
expected.Host = "an.other.host"
|
Path: "api/v1/activitypub/user-id",
|
||||||
expected.HostPort = 443
|
Host: "an.other.forgejo.host",
|
||||||
expected.IsPortSupplemented = true
|
HostPort: 443,
|
||||||
expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
|
UnvalidatedInput: "https://an.other.forgejo.host/api/v1/activitypub/user-id/5",
|
||||||
|
IsPortSupplemented: true,
|
||||||
|
}, sut)
|
||||||
|
|
||||||
sut, _ := NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
|
sut, err = NewActorID("https://an.other.forgejo.host/api/v1/activitypub/actor")
|
||||||
if sut != expected {
|
require.NoError(t, err)
|
||||||
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
|
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)
|
||||||
|
|
||||||
expected = PersonID{}
|
sut, err = NewActorID("https://an.other.gts.host/users/me")
|
||||||
expected.ID = "1"
|
require.NoError(t, err)
|
||||||
expected.Source = "forgejo"
|
assert.Equal(t, ActorID{
|
||||||
expected.HostSchema = "https"
|
ID: "me",
|
||||||
expected.Path = "api/v1/activitypub/user-id"
|
HostSchema: "https",
|
||||||
expected.Host = "an.other.host"
|
Path: "users",
|
||||||
expected.HostPort = 443
|
Host: "an.other.gts.host",
|
||||||
expected.IsPortSupplemented = false
|
HostPort: 443,
|
||||||
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
|
UnvalidatedInput: "https://an.other.gts.host/users/me",
|
||||||
|
IsPortSupplemented: true,
|
||||||
sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
|
}, sut)
|
||||||
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) {
|
func TestActorIdValidation(t *testing.T) {
|
||||||
sut := ActorID{}
|
sut := ActorID{}
|
||||||
sut.Source = "forgejo"
|
|
||||||
sut.HostSchema = "https"
|
sut.HostSchema = "https"
|
||||||
sut.Path = "api/v1/activitypub/user-id"
|
sut.Path = "api/v1/activitypub/user-id"
|
||||||
sut.Host = "an.other.host"
|
sut.Host = "an.other.host"
|
||||||
sut.HostPort = 443
|
sut.HostPort = 443
|
||||||
sut.IsPortSupplemented = true
|
sut.IsPortSupplemented = true
|
||||||
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/"
|
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/"
|
||||||
if sut.Validate()[0] != "userId should not be empty" {
|
result := sut.Validate()
|
||||||
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
assert.Len(t, result, 1)
|
||||||
}
|
assert.Equal(t, "ID should not be empty", result[0])
|
||||||
|
|
||||||
sut = ActorID{}
|
sut = ActorID{}
|
||||||
sut.ID = "1"
|
sut.ID = "1"
|
||||||
sut.Source = "forgejo"
|
|
||||||
sut.HostSchema = "https"
|
sut.HostSchema = "https"
|
||||||
sut.Path = "api/v1/activitypub/user-id"
|
sut.Path = "api/v1/activitypub/user-id"
|
||||||
sut.Host = "an.other.host"
|
sut.Host = "an.other.host"
|
||||||
sut.HostPort = 443
|
sut.HostPort = 443
|
||||||
sut.IsPortSupplemented = true
|
sut.IsPortSupplemented = true
|
||||||
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action"
|
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action"
|
||||||
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\"" {
|
result = sut.Validate()
|
||||||
t.Errorf("validation error expected but was: %v\n", sut.Validate()[0])
|
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])
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
// Copyright 2023, 2025 The Forgejo Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package forgefed
|
package forgefed
|
||||||
|
|
68
modules/forgefed/object_user_activity_note.go
Normal file
68
modules/forgefed/object_user_activity_note.go
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// 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
|
||||||
|
}
|
28
modules/forgefed/object_user_activity_note_test.go
Normal file
28
modules/forgefed/object_user_activity_note_test.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// 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())
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ type ServeHeaderOptions struct {
|
||||||
Filename string
|
Filename string
|
||||||
CacheDuration time.Duration // defaults to 5 minutes
|
CacheDuration time.Duration // defaults to 5 minutes
|
||||||
LastModified time.Time
|
LastModified time.Time
|
||||||
|
AdditionalHeaders http.Header
|
||||||
|
RedirectStatusCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeSetHeaders sets necessary content serve headers
|
// ServeSetHeaders sets necessary content serve headers
|
||||||
|
@ -82,6 +84,12 @@ func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
|
||||||
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
// 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))
|
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
|
// ServeData download file from io.Reader
|
||||||
|
|
|
@ -260,11 +260,11 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
||||||
if opts.Mode == internal.CodeSearchModeUnion {
|
if opts.Mode == internal.CodeSearchModeUnion {
|
||||||
query := bleve.NewDisjunctionQuery()
|
query := bleve.NewDisjunctionQuery()
|
||||||
for _, field := range strings.Fields(opts.Keyword) {
|
for _, field := range strings.Fields(opts.Keyword) {
|
||||||
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false))
|
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false, 1.0))
|
||||||
}
|
}
|
||||||
keywordQuery = query
|
keywordQuery = query
|
||||||
} else {
|
} else {
|
||||||
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false)
|
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(opts.RepoIDs) > 0 {
|
if len(opts.RepoIDs) > 0 {
|
||||||
|
|
|
@ -29,11 +29,12 @@ func MatchQuery(matchTerm, field, analyzer string, fuzziness int) *query.MatchQu
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
|
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
|
||||||
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool) *query.MatchPhraseQuery {
|
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool, boost float64) *query.MatchPhraseQuery {
|
||||||
q := bleve.NewMatchPhraseQuery(matchPhrase)
|
q := bleve.NewMatchPhraseQuery(matchPhrase)
|
||||||
q.FieldVal = field
|
q.FieldVal = field
|
||||||
q.Analyzer = analyzer
|
q.Analyzer = analyzer
|
||||||
q.SetAutoFuzziness(autoFuzzy)
|
q.SetAutoFuzziness(autoFuzzy)
|
||||||
|
q.SetBoost(boost)
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
const (
|
const (
|
||||||
issueIndexerAnalyzer = "issueIndexer"
|
issueIndexerAnalyzer = "issueIndexer"
|
||||||
issueIndexerDocType = "issueIndexerDocType"
|
issueIndexerDocType = "issueIndexerDocType"
|
||||||
issueIndexerLatestVersion = 4
|
issueIndexerLatestVersion = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
const unicodeNormalizeName = "unicodeNormalize"
|
const unicodeNormalizeName = "unicodeNormalize"
|
||||||
|
@ -69,6 +69,7 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
|
||||||
|
|
||||||
docMapping.AddFieldMappingsAt("is_public", boolFieldMapping)
|
docMapping.AddFieldMappingsAt("is_public", boolFieldMapping)
|
||||||
|
|
||||||
|
docMapping.AddFieldMappingsAt("index", numberFieldMapping)
|
||||||
docMapping.AddFieldMappingsAt("title", textFieldMapping)
|
docMapping.AddFieldMappingsAt("title", textFieldMapping)
|
||||||
docMapping.AddFieldMappingsAt("content", textFieldMapping)
|
docMapping.AddFieldMappingsAt("content", textFieldMapping)
|
||||||
docMapping.AddFieldMappingsAt("comments", textFieldMapping)
|
docMapping.AddFieldMappingsAt("comments", textFieldMapping)
|
||||||
|
@ -163,9 +164,15 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||||
q := bleve.NewBooleanQuery()
|
q := bleve.NewBooleanQuery()
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
innerQ := bleve.NewDisjunctionQuery(
|
innerQ := bleve.NewDisjunctionQuery(
|
||||||
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy),
|
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy, 2.0),
|
||||||
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy),
|
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy, 1.0),
|
||||||
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, token.Fuzzy))
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
switch token.Kind {
|
switch token.Kind {
|
||||||
case internal.BoolOptMust:
|
case internal.BoolOptMust:
|
||||||
|
|
|
@ -5,6 +5,7 @@ package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"forgejo.org/models/db"
|
"forgejo.org/models/db"
|
||||||
issue_model "forgejo.org/models/issues"
|
issue_model "forgejo.org/models/issues"
|
||||||
|
@ -71,6 +72,17 @@ 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)
|
opt, err := ToDBOptions(ctx, options)
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
issueIndexerLatestVersion = 1
|
issueIndexerLatestVersion = 2
|
||||||
// multi-match-types, currently only 2 types are used
|
// 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
|
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
|
||||||
esMultiMatchTypeBestFields = "best_fields"
|
esMultiMatchTypeBestFields = "best_fields"
|
||||||
|
@ -56,6 +56,7 @@ const (
|
||||||
"repo_id": { "type": "long", "index": true },
|
"repo_id": { "type": "long", "index": true },
|
||||||
"is_public": { "type": "boolean", "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 },
|
"content": { "type": "text", "index": true },
|
||||||
"comments": { "type" : "text", "index": true },
|
"comments": { "type" : "text", "index": true },
|
||||||
|
@ -155,21 +156,25 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
innerQ := elastic.NewMultiMatchQuery(token.Term, "title", "content", "comments")
|
innerQ := elastic.NewMultiMatchQuery(token.Term, "content", "comments").FieldWithBoost("title", 2.0).TieBreaker(0.5)
|
||||||
if token.Fuzzy {
|
if token.Fuzzy {
|
||||||
// If the term is not a phrase use fuzziness set to AUTO
|
// If the term is not a phrase use fuzziness set to AUTO
|
||||||
innerQ = innerQ.Type(esMultiMatchTypeBestFields).Fuzziness(esFuzzyAuto)
|
innerQ = innerQ.Type(esMultiMatchTypeBestFields).Fuzziness(esFuzzyAuto)
|
||||||
} else {
|
} else {
|
||||||
innerQ = innerQ.Type(esMultiMatchTypePhrasePrefix)
|
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 {
|
switch token.Kind {
|
||||||
case internal.BoolOptMust:
|
case internal.BoolOptMust:
|
||||||
q.Must(innerQ)
|
q.Must(eitherQ)
|
||||||
case internal.BoolOptShould:
|
case internal.BoolOptShould:
|
||||||
q.Should(innerQ)
|
q.Should(eitherQ)
|
||||||
case internal.BoolOptNot:
|
case internal.BoolOptNot:
|
||||||
q.MustNot(innerQ)
|
q.MustNot(eitherQ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
query.Must(q)
|
query.Must(q)
|
||||||
|
|
|
@ -14,6 +14,7 @@ type IndexerData struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
RepoID int64 `json:"repo_id"`
|
RepoID int64 `json:"repo_id"`
|
||||||
IsPublic bool `json:"is_public"` // If the repo is public
|
IsPublic bool `json:"is_public"` // If the repo is public
|
||||||
|
Index int64 `json:"index"`
|
||||||
|
|
||||||
// Fields used for keyword searching
|
// Fields used for keyword searching
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
|
|
@ -5,6 +5,7 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,6 +23,14 @@ type Token struct {
|
||||||
Fuzzy bool
|
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 {
|
type Tokenizer struct {
|
||||||
in *strings.Reader
|
in *strings.Reader
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,6 +549,55 @@ var cases = []*testIndexerCase{
|
||||||
}), result.Total)
|
}), 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",
|
Name: "SortByCreatedDesc",
|
||||||
SearchOptions: &internal.SearchOptions{
|
SearchOptions: &internal.SearchOptions{
|
||||||
|
@ -741,6 +790,7 @@ func generateDefaultIndexerData() []*internal.IndexerData {
|
||||||
|
|
||||||
data = append(data, &internal.IndexerData{
|
data = append(data, &internal.IndexerData{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
Index: issueIndex,
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
IsPublic: repoID%2 == 0,
|
IsPublic: repoID%2 == 0,
|
||||||
Title: fmt.Sprintf("issue%d of repo%d", issueIndex, repoID),
|
Title: fmt.Sprintf("issue%d of repo%d", issueIndex, repoID),
|
||||||
|
|
|
@ -95,6 +95,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
|
||||||
return &internal.IndexerData{
|
return &internal.IndexerData{
|
||||||
ID: issue.ID,
|
ID: issue.ID,
|
||||||
RepoID: issue.RepoID,
|
RepoID: issue.RepoID,
|
||||||
|
Index: issue.Index,
|
||||||
IsPublic: !issue.Repo.IsPrivate,
|
IsPublic: !issue.Repo.IsPrivate,
|
||||||
Title: issue.Title,
|
Title: issue.Title,
|
||||||
Content: issue.Content,
|
Content: issue.Content,
|
||||||
|
|
|
@ -84,6 +84,13 @@ func ParseImageConfig(mt string, r io.Reader) (*Metadata, error) {
|
||||||
func parseOCIImageConfig(r io.Reader) (*Metadata, error) {
|
func parseOCIImageConfig(r io.Reader) (*Metadata, error) {
|
||||||
var image oci.Image
|
var image oci.Image
|
||||||
if err := json.NewDecoder(r).Decode(&image); err != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -60,3 +61,49 @@ func TestParseImageConfig(t *testing.T) {
|
||||||
assert.Equal(t, projectURL, metadata.ProjectURL)
|
assert.Equal(t, projectURL, metadata.ProjectURL)
|
||||||
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -69,8 +69,11 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
|
||||||
|
|
||||||
// insert units for repo
|
// insert units for repo
|
||||||
defaultUnits := unit.DefaultRepoUnits
|
defaultUnits := unit.DefaultRepoUnits
|
||||||
if isFork {
|
switch {
|
||||||
|
case isFork:
|
||||||
defaultUnits = unit.DefaultForkRepoUnits
|
defaultUnits = unit.DefaultForkRepoUnits
|
||||||
|
case repo.IsMirror:
|
||||||
|
defaultUnits = unit.DefaultMirrorRepoUnits
|
||||||
}
|
}
|
||||||
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
|
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
|
||||||
for _, tp := range defaultUnits {
|
for _, tp := range defaultUnits {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package setting
|
package setting
|
||||||
|
@ -52,6 +53,7 @@ var (
|
||||||
DisabledRepoUnits []string
|
DisabledRepoUnits []string
|
||||||
DefaultRepoUnits []string
|
DefaultRepoUnits []string
|
||||||
DefaultForkRepoUnits []string
|
DefaultForkRepoUnits []string
|
||||||
|
DefaultMirrorRepoUnits []string
|
||||||
PrefixArchiveFiles bool
|
PrefixArchiveFiles bool
|
||||||
DisableMigrations bool
|
DisableMigrations bool
|
||||||
DisableStars bool
|
DisableStars bool
|
||||||
|
@ -175,6 +177,7 @@ var (
|
||||||
DisabledRepoUnits: []string{},
|
DisabledRepoUnits: []string{},
|
||||||
DefaultRepoUnits: []string{},
|
DefaultRepoUnits: []string{},
|
||||||
DefaultForkRepoUnits: []string{},
|
DefaultForkRepoUnits: []string{},
|
||||||
|
DefaultMirrorRepoUnits: []string{},
|
||||||
PrefixArchiveFiles: true,
|
PrefixArchiveFiles: true,
|
||||||
DisableMigrations: false,
|
DisableMigrations: false,
|
||||||
DisableStars: false,
|
DisableStars: false,
|
||||||
|
|
|
@ -56,7 +56,7 @@ var SSH = struct {
|
||||||
Domain: "",
|
Domain: "",
|
||||||
Port: 22,
|
Port: 22,
|
||||||
ServerCiphers: []string{"chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"},
|
ServerCiphers: []string{"chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"},
|
||||||
ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
|
ServerKeyExchanges: []string{"mlkem768x25519-sha256", "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"},
|
ServerMACs: []string{"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1"},
|
||||||
KeygenPath: "",
|
KeygenPath: "",
|
||||||
MinimumKeySizeCheck: true,
|
MinimumKeySizeCheck: true,
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
package structs
|
package structs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// ActionRunJob represents a job of a run
|
// ActionRunJob represents a job of a run
|
||||||
// swagger:model
|
// swagger:model
|
||||||
type ActionRunJob struct {
|
type ActionRunJob struct {
|
||||||
|
@ -23,3 +27,54 @@ type ActionRunJob struct {
|
||||||
// the action run job status
|
// the action run job status
|
||||||
Status string `json:"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"`
|
||||||
|
}
|
||||||
|
|
|
@ -119,6 +119,7 @@ var (
|
||||||
_ Payloader = &RepositoryPayload{}
|
_ Payloader = &RepositoryPayload{}
|
||||||
_ Payloader = &ReleasePayload{}
|
_ Payloader = &ReleasePayload{}
|
||||||
_ Payloader = &PackagePayload{}
|
_ Payloader = &PackagePayload{}
|
||||||
|
_ Payloader = &ActionPayload{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// _________ __
|
// _________ __
|
||||||
|
@ -484,3 +485,36 @@ type PackagePayload struct {
|
||||||
func (p *PackagePayload) JSONPayload() ([]byte, error) {
|
func (p *PackagePayload) JSONPayload() ([]byte, error) {
|
||||||
return json.MarshalIndent(p, "", " ")
|
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, "", " ")
|
||||||
|
}
|
||||||
|
|
|
@ -32,3 +32,23 @@ type ActionTaskResponse struct {
|
||||||
Entries []*ActionTask `json:"workflow_runs"`
|
Entries []*ActionTask `json:"workflow_runs"`
|
||||||
TotalCount int64 `json:"total_count"`
|
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"`
|
||||||
|
}
|
||||||
|
|
|
@ -75,6 +75,11 @@ func IsValidExternalURL(uri string) bool {
|
||||||
return true
|
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
|
// IsValidExternalTrackerURLFormat checks if URL matches required syntax for external trackers
|
||||||
func IsValidExternalTrackerURLFormat(uri string) bool {
|
func IsValidExternalTrackerURLFormat(uri string) bool {
|
||||||
if !IsValidExternalURL(uri) {
|
if !IsValidExternalURL(uri) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package webhook
|
package webhook
|
||||||
|
|
||||||
// HookEvents is a set of web hook events
|
// 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 {
|
type HookEvents struct {
|
||||||
Create bool `json:"create"`
|
Create bool `json:"create"`
|
||||||
Delete bool `json:"delete"`
|
Delete bool `json:"delete"`
|
||||||
|
@ -26,9 +27,12 @@ type HookEvents struct {
|
||||||
Repository bool `json:"repository"`
|
Repository bool `json:"repository"`
|
||||||
Release bool `json:"release"`
|
Release bool `json:"release"`
|
||||||
Package bool `json:"package"`
|
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 delivery hook.
|
// HookEvent represents events that will deliver a hook.
|
||||||
type HookEvent struct {
|
type HookEvent struct {
|
||||||
PushOnly bool `json:"push_only"`
|
PushOnly bool `json:"push_only"`
|
||||||
SendEverything bool `json:"send_everything"`
|
SendEverything bool `json:"send_everything"`
|
||||||
|
|
|
@ -7,6 +7,7 @@ package webhook
|
||||||
type HookEventType string
|
type HookEventType string
|
||||||
|
|
||||||
// Types of hook events
|
// Types of hook events
|
||||||
|
// update TestCreateWebhook in models/webhook/webhook_test.go when adding or changing values here
|
||||||
const (
|
const (
|
||||||
HookEventCreate HookEventType = "create"
|
HookEventCreate HookEventType = "create"
|
||||||
HookEventDelete HookEventType = "delete"
|
HookEventDelete HookEventType = "delete"
|
||||||
|
@ -33,6 +34,9 @@ const (
|
||||||
HookEventPackage HookEventType = "package"
|
HookEventPackage HookEventType = "package"
|
||||||
HookEventSchedule HookEventType = "schedule"
|
HookEventSchedule HookEventType = "schedule"
|
||||||
HookEventWorkflowDispatch HookEventType = "workflow_dispatch"
|
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
|
// Event returns the HookEventType as an event string
|
||||||
|
@ -65,6 +69,12 @@ func (h HookEventType) Event() string {
|
||||||
return "repository"
|
return "repository"
|
||||||
case HookEventRelease:
|
case HookEventRelease:
|
||||||
return "release"
|
return "release"
|
||||||
|
case HookEventActionRunFailure:
|
||||||
|
return "action_run_failure"
|
||||||
|
case HookEventActionRunRecover:
|
||||||
|
return "action_run_recover"
|
||||||
|
case HookEventActionRunSuccess:
|
||||||
|
return "action_run_success"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -2915,6 +2915,13 @@ 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.branch_behind_few = Tato větev je %[1]d revizí pozadu za %[2]s
|
||||||
sync_fork.button = Synchronizovat
|
sync_fork.button = Synchronizovat
|
||||||
sync_fork.branch_behind_one = Tato větev je %[1]d revizi pozadu za %[2]s
|
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]
|
[graphs]
|
||||||
component_loading_info = Tohle může chvíli trvat…
|
component_loading_info = Tohle může chvíli trvat…
|
||||||
|
|
|
@ -1432,7 +1432,7 @@ issues.new.no_items = Ingen elementer
|
||||||
issues.new.milestone = Milepæl
|
issues.new.milestone = Milepæl
|
||||||
issues.new.no_milestone = Ingen milepæl
|
issues.new.no_milestone = Ingen milepæl
|
||||||
issues.filter_assignees = Filter tildelt
|
issues.filter_assignees = Filter tildelt
|
||||||
issues.filter_milestones = Filter Milepæl
|
issues.filter_milestones = Filter milepæl
|
||||||
issues.filter_projects = Filter projekt
|
issues.filter_projects = Filter projekt
|
||||||
issues.filter_labels = Filter etiket
|
issues.filter_labels = Filter etiket
|
||||||
issues.filter_reviewers = Filter anmelder
|
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.exists = Eksisterer i lager
|
||||||
settings.lfs_pointers.accessible = Tilgængeligt for bruger
|
settings.lfs_pointers.accessible = Tilgængeligt for bruger
|
||||||
signing.wont_sign.not_signed_in = Du er ikke logget ind.
|
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.modify = Opdater milepæl
|
||||||
milestones.edit_success = Milepæl "%s" er blevet opdateret.
|
milestones.edit_success = Milepæl "%s" er blevet opdateret.
|
||||||
milestones.filter_sort.least_issues = Mindst problemer
|
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.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_duplicate = Samarbejdspartneren er allerede føjet til dette depot.
|
||||||
settings.add_collaborator_owner = Kan ikke tilføje en ejer som samarbejdspartner.
|
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.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_team_duplicate = Teamet har allerede depotet
|
||||||
settings.add_collaborator_blocked_our = Samarbejdspartneren kan ikke tilføjes, fordi depots ejer har blokeret dem.
|
settings.add_collaborator_blocked_our = Samarbejdspartneren kan ikke tilføjes, fordi depots ejer har blokeret dem.
|
||||||
|
@ -2728,6 +2728,13 @@ 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.branch_behind_few = Denne gren er %[1]d commits bag %[2]s
|
||||||
sync_fork.button = Sync
|
sync_fork.button = Sync
|
||||||
sync_fork.branch_behind_one = Denne gren er %[1]d commit bag %[2]s
|
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]
|
[notification]
|
||||||
watching = Overvåger
|
watching = Overvåger
|
||||||
|
@ -3529,8 +3536,8 @@ composer.install = For at installere pakken ved hjælp af Composer skal du køre
|
||||||
container.multi_arch = OS / Arch
|
container.multi_arch = OS / Arch
|
||||||
rubygems.required.ruby = Kræver Ruby version
|
rubygems.required.ruby = Kræver Ruby version
|
||||||
swift.install = Tilføj pakken i din <code>Package.swift</code>-fil:
|
swift.install = Tilføj pakken i din <code>Package.swift</code>-fil:
|
||||||
settings.link.select = Vælg Depot
|
settings.link.select = Vælg depot
|
||||||
settings.link.button = Opdater Depot Link
|
settings.link.button = Opdater depot link
|
||||||
settings.link.error = Kunne ikke opdatere depotlinket.
|
settings.link.error = Kunne ikke opdatere depotlinket.
|
||||||
owner.settings.cargo.initialize.success = Cargo-indekset blev oprettet.
|
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.
|
owner.settings.cargo.rebuild.description = Genopbygning kan være nyttig, hvis indekset ikke er synkroniseret med de lagrede Cargo-pakker.
|
||||||
|
|
|
@ -745,7 +745,7 @@ social=Soziale Konten
|
||||||
applications=Anwendungen
|
applications=Anwendungen
|
||||||
orgs=Organisationen
|
orgs=Organisationen
|
||||||
repos=Repositorys
|
repos=Repositorys
|
||||||
delete=Konto löschen
|
delete=Account löschen
|
||||||
twofa=Zwei-Faktor-Authentifizierung (TOTP)
|
twofa=Zwei-Faktor-Authentifizierung (TOTP)
|
||||||
account_link=Verknüpfte Benutzerkonten
|
account_link=Verknüpfte Benutzerkonten
|
||||||
organization=Organisationen
|
organization=Organisationen
|
||||||
|
@ -1511,7 +1511,7 @@ projects.card_type.images_and_text=Bilder und Text
|
||||||
projects.card_type.text_only=Nur Text
|
projects.card_type.text_only=Nur Text
|
||||||
|
|
||||||
issues.desc=Verwalte Bug-Reports, Aufgaben und Meilensteine.
|
issues.desc=Verwalte Bug-Reports, Aufgaben und Meilensteine.
|
||||||
issues.filter_assignees=Filter
|
issues.filter_assignees=Verantwortliche filtern
|
||||||
issues.filter_milestones=Meilenstein filtern
|
issues.filter_milestones=Meilenstein filtern
|
||||||
issues.filter_projects=Projekt filtern
|
issues.filter_projects=Projekt filtern
|
||||||
issues.filter_labels=Label filtern
|
issues.filter_labels=Label filtern
|
||||||
|
@ -4031,7 +4031,7 @@ repo_kind = Repos suchen …
|
||||||
user_kind = Benutzer suchen …
|
user_kind = Benutzer suchen …
|
||||||
org_kind = Orgs suchen …
|
org_kind = Orgs suchen …
|
||||||
team_kind = Teams suchen …
|
team_kind = Teams suchen …
|
||||||
code_kind = Code suchen…
|
code_kind = Code durchsuchen …
|
||||||
package_kind = Pakete suchen …
|
package_kind = Pakete suchen …
|
||||||
project_kind = Projekte suchen …
|
project_kind = Projekte suchen …
|
||||||
branch_kind = Branches suchen …
|
branch_kind = Branches suchen …
|
||||||
|
|
|
@ -2486,6 +2486,13 @@ settings.event_pull_request_review_request_desc = Pull request review requested
|
||||||
settings.event_pull_request_approvals = Pull request approvals
|
settings.event_pull_request_approvals = Pull request approvals
|
||||||
settings.event_pull_request_merge = Pull request merge
|
settings.event_pull_request_merge = Pull request merge
|
||||||
settings.event_pull_request_enforcement = Enforcement
|
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 = Package
|
||||||
settings.event_package_desc = Package created or deleted in a repository.
|
settings.event_package_desc = Package created or deleted in a repository.
|
||||||
settings.branch_filter = Branch filter
|
settings.branch_filter = Branch filter
|
||||||
|
@ -2978,8 +2985,6 @@ teams.invite_team_member.list = Pending invitations
|
||||||
teams.delete_team_title = Delete team
|
teams.delete_team_title = Delete team
|
||||||
teams.delete_team_desc = Deleting a team revokes repository access from its members. Continue?
|
teams.delete_team_desc = Deleting a team revokes repository access from its members. Continue?
|
||||||
teams.delete_team_success = The team has been deleted.
|
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.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.create_repo_permission_desc = Additionally, this team grants <strong>Create repository</strong> permission: members can create new repositories in organization.
|
||||||
teams.repositories = Team repositories
|
teams.repositories = Team repositories
|
||||||
|
|
|
@ -103,7 +103,7 @@ ok = Bone
|
||||||
download_logs = Elsuti protokolojn
|
download_logs = Elsuti protokolojn
|
||||||
unknown = Nekonata
|
unknown = Nekonata
|
||||||
issues = Eraroj
|
issues = Eraroj
|
||||||
error404 = Aŭ tiu ĉi paĝo <strong>ne ekzistas</strong> aŭ <strong>vi ne rajtas</strong> vidi ĝin.
|
error404 = Aŭ tiu ĉi paĝo <strong>ne ekzistas</strong>, <strong>estis forigita</strong> aŭ <strong>vi ne rajtas</strong> vidi ĝin.
|
||||||
retry = Reprovi
|
retry = Reprovi
|
||||||
activities = Aktivecoj
|
activities = Aktivecoj
|
||||||
confirm_delete_selected = Konfirmi forigon de ĉiu elektito?
|
confirm_delete_selected = Konfirmi forigon de ĉiu elektito?
|
||||||
|
@ -171,6 +171,7 @@ table_modal.placeholder.header = Kapo
|
||||||
table_modal.placeholder.content = Enhavo
|
table_modal.placeholder.content = Enhavo
|
||||||
table_modal.label.rows = Horizontaloj
|
table_modal.label.rows = Horizontaloj
|
||||||
table_modal.label.columns = Vertikaloj
|
table_modal.label.columns = Vertikaloj
|
||||||
|
link_modal.description = Priskribo
|
||||||
|
|
||||||
[aria]
|
[aria]
|
||||||
navbar = Esplora breto
|
navbar = Esplora breto
|
||||||
|
@ -523,6 +524,7 @@ 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.
|
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.
|
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.
|
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]
|
[form]
|
||||||
TeamName = Gruponomo
|
TeamName = Gruponomo
|
||||||
|
@ -861,30 +863,30 @@ npm.details.tag = Etikedo
|
||||||
|
|
||||||
|
|
||||||
[search]
|
[search]
|
||||||
search = Serĉi...
|
search = Serĉi…
|
||||||
regexp = RegEsp
|
regexp = RegEsp
|
||||||
milestone_kind = Serĉi celojn...
|
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_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.
|
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
|
type_tooltip = Serĉotipo
|
||||||
user_kind = Serĉi uzantojn...
|
user_kind = Serĉi uzantojn…
|
||||||
fuzzy_tooltip = Inkluzivas rezultojn proksime kongruantajn kun la serĉoterminoj
|
fuzzy_tooltip = Inkluzivas rezultojn proksime kongruantajn kun la serĉoterminoj
|
||||||
repo_kind = Serĉi deponejojn...
|
repo_kind = Serĉi deponejojn…
|
||||||
org_kind = Serĉi organizaĵojn...
|
org_kind = Serĉi organizaĵojn…
|
||||||
code_kind = Serĉi kodon...
|
code_kind = Serĉi kodon…
|
||||||
project_kind = Serĉi projektojn...
|
project_kind = Serĉi projektojn…
|
||||||
team_kind = Serĉi teamojn...
|
team_kind = Serĉi teamojn…
|
||||||
keyword_search_unavailable = Serĉo per ŝlosilvortoj ne haveblas nune. Bonvolu kontakti la retejestron.
|
keyword_search_unavailable = Serĉo per ŝlosilvortoj ne haveblas nune. Bonvolu kontakti la retejestron.
|
||||||
union = Ŝlosilvortoj
|
union = Ŝlosilvortoj
|
||||||
union_tooltip = Inkluzivas rezultojn kongruantajn kun la ajnaj blankaspacitaj ŝ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.
|
no_results = Ne trovis kongruantajn rezultojn.
|
||||||
exact = Ĝusta
|
exact = Ĝusta
|
||||||
exact_tooltip = Inkluzivas nur rezultojn kongruantajn kun la ĝustaj serĉoterminoj
|
exact_tooltip = Inkluzivas nur rezultojn kongruantajn kun la ĝustaj serĉoterminoj
|
||||||
issue_kind = Serĉi erarojn...
|
issue_kind = Serĉi erarojn...
|
||||||
regexp_tooltip = Interpretas la serĉoterminoj kiel regulesprimo
|
regexp_tooltip = Interpretas la serĉoterminoj kiel regulesprimo
|
||||||
fuzzy = Svaga
|
fuzzy = Svaga
|
||||||
branch_kind = Serĉi disbranĉigojn...
|
branch_kind = Serĉi disbranĉigojn…
|
||||||
runner_kind = Serĉi rulantojn...
|
runner_kind = Serĉi rulantojn...
|
||||||
pull_kind = Serĉi tirpetojn...
|
pull_kind = Serĉi tirpetojn...
|
|
@ -8,7 +8,7 @@ sign_in=Kirjaudu sisään
|
||||||
sign_in_or=tai
|
sign_in_or=tai
|
||||||
sign_out=Kirjaudu ulos
|
sign_out=Kirjaudu ulos
|
||||||
sign_up=Rekisteröidy
|
sign_up=Rekisteröidy
|
||||||
link_account=Yhdistä tili
|
link_account=Linkitä tili
|
||||||
register=Rekisteröidy
|
register=Rekisteröidy
|
||||||
version=Versio
|
version=Versio
|
||||||
powered_by=Voimanlähteenä %s
|
powered_by=Voimanlähteenä %s
|
||||||
|
@ -23,7 +23,7 @@ toc=Sisällysluettelo
|
||||||
licenses=Lisenssit
|
licenses=Lisenssit
|
||||||
return_to_forgejo=Palaa Forgejohon
|
return_to_forgejo=Palaa Forgejohon
|
||||||
|
|
||||||
username=Käyttäjätunnus
|
username=Käyttäjänimi
|
||||||
email=Sähköpostiosoite
|
email=Sähköpostiosoite
|
||||||
password=Salasana
|
password=Salasana
|
||||||
access_token=Pääsypoletti
|
access_token=Pääsypoletti
|
||||||
|
@ -31,7 +31,7 @@ re_type=Vahvista salasana
|
||||||
captcha=CAPTCHA
|
captcha=CAPTCHA
|
||||||
twofa=Kaksivaiheinen todennus
|
twofa=Kaksivaiheinen todennus
|
||||||
twofa_scratch=Kaksivaiheinen kertakäyttöinen koodi
|
twofa_scratch=Kaksivaiheinen kertakäyttöinen koodi
|
||||||
passcode=Tunnuskoodi
|
passcode=Pääsykoodi
|
||||||
|
|
||||||
webauthn_insert_key=Aseta turva-avaimesi
|
webauthn_insert_key=Aseta turva-avaimesi
|
||||||
webauthn_sign_in=Paina turva-avaimesi painiketta. Jos turva-avaimessasi ei ole painiketta, irrota se ja aseta uudelleen.
|
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_error=Turva-avainta ei voitu lukea.
|
||||||
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
|
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
|
||||||
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen.
|
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen.
|
||||||
webauthn_error_insecure=`WebAuthn tukee vain suojattuja yhteyksiä. Testaukseen HTTP:n yli, voit käyttää osoitetta "localhost" tai "127.0.0.1"`
|
webauthn_error_insecure=WebAuthn tukee vain suojattuja yhteyksiä. Testatessa HTTP-yhteydellä voit käyttää osoitetta "localhost" tai "127.0.0.1"
|
||||||
webauthn_error_unable_to_process=Palvelin ei pystynyt käsittelemään pyyntöä.
|
webauthn_error_unable_to_process=Palvelin ei pystynyt käsittelemään pyyntöä.
|
||||||
webauthn_error_duplicated=Turva-avainta ei ole sallittu tässä pyynnössä. Varmista, ettei avainta ole jo rekisteröity.
|
webauthn_error_duplicated=Turva-avainta ei ole sallittu tässä pyynnössä. Varmista, ettei avainta ole jo rekisteröity.
|
||||||
webauthn_error_empty=Sinun täytyy asettaa nimi tälle avaimelle.
|
webauthn_error_empty=Sinun täytyy asettaa nimi tälle avaimelle.
|
||||||
|
@ -228,22 +228,22 @@ report_message = Jos uskot tämän olevan Forgejon virhe, etsi ongelmia <a href=
|
||||||
app_desc=Kivuton, itsehostattu Git-palvelu
|
app_desc=Kivuton, itsehostattu Git-palvelu
|
||||||
install=Helppo asentaa
|
install=Helppo asentaa
|
||||||
platform=Alustariippumaton
|
platform=Alustariippumaton
|
||||||
platform_desc=Forgejo on mahdollista suorittaa vapaissa käyttöjärjestelmissä kuten Linux ja FreeBSD, ja se toimii eri suoritinarkkitehtuureilla. Valitse omasi!
|
platform_desc=Forgejo on mahdollista suorittaa Linuxin ja FreeBSD:n kaltaisissa vapaissa käyttöjärjestelmissä, ja se toimii eri suoritinarkkitehtuureilla. Valitse omasi!
|
||||||
lightweight=Kevyt
|
lightweight=Kevyt
|
||||||
lightweight_desc=Forgejolla on vähäiset vähimmäisvaatimukset, joten se toimii jopa halvassa Raspberry Pi:ssä. Säästä koneesi energiaa!
|
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=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!
|
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 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_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]
|
[install]
|
||||||
install=Asennus
|
install=Asennus
|
||||||
title=Aloitusasetukset
|
title=Aloitusasetukset
|
||||||
docker_helper=Jos ajat Forgejoa Dockerin sisällä, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a> ennen minkään asetuksen muuttamista.
|
docker_helper=Jos suoritat Forgejoa kontitettuna, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a>, ennen kuin muutat yhtäkään asetusta.
|
||||||
require_db_desc=Forgejo tarvitsee toimiakseen MySQL-, PostgreSQL-, SQLite3- tai TiDB- (MySQL-protokolla) tietokannan.
|
require_db_desc=Forgejo tarvitsee toimiakseen MySQL-, PostgreSQL-, SQLite3- tai TiDB- (MySQL-protokolla) tietokannan.
|
||||||
db_title=Tietokannan asetukset
|
db_title=Tietokannan asetukset
|
||||||
db_type=Tietokannan tyyppi
|
db_type=Tietokannan tyyppi
|
||||||
host=Isäntä
|
host=Isäntä
|
||||||
user=Käyttäjätunnus
|
user=Käyttäjänimi
|
||||||
password=Salasana
|
password=Salasana
|
||||||
db_name=Tietokannan nimi
|
db_name=Tietokannan nimi
|
||||||
db_schema=Skeema
|
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ä.
|
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_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_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ätunnus on virheellinen; käyttäjätunnus on varattu
|
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ätunnus on virheellinen
|
err_admin_name_is_invalid=Ylläpitäjän käyttäjänimi on virheellinen
|
||||||
|
|
||||||
general_title=Yleiset asetukset
|
general_title=Yleiset asetukset
|
||||||
app_name=Instanssin otsikko
|
app_name=Instanssin otsikko
|
||||||
|
@ -286,7 +286,7 @@ smtp_addr=SMTP-isäntä
|
||||||
smtp_port=SMTP-portti
|
smtp_port=SMTP-portti
|
||||||
smtp_from=Lähetä sähköpostit osoitteella
|
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.
|
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ätunnus
|
mailer_user=SMTP-käyttäjänimi
|
||||||
mailer_password=SMTP-salasana
|
mailer_password=SMTP-salasana
|
||||||
register_confirm=Vaadi sähköpostinvahvistus rekisteröinnin edellytykseksi
|
register_confirm=Vaadi sähköpostinvahvistus rekisteröinnin edellytykseksi
|
||||||
mail_notify=Ota sähköposti-ilmoitukset käyttöön
|
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=Ota ajanseuranta oletusarvoisesti käyttöön
|
||||||
default_enable_timetracking.description=Salli ajanseuranta-ominaisuuden käyttöönotto oletuksena uusille tietovarastoille.
|
default_enable_timetracking.description=Salli ajanseuranta-ominaisuuden käyttöönotto oletuksena uusille tietovarastoille.
|
||||||
no_reply_address=Piilotetun sähköpostin toimialue
|
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ätunnus '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änimi 'joe' kirjataan Git-palveluun nimellä 'joe@noreply.example.org' jos piilotetun sähköpostiosoitteen arvoksi on asetettu 'noreply.example.org'.
|
||||||
password_algorithm=Salasanan hajautusalgoritmi
|
password_algorithm=Salasanan hajautusalgoritmi
|
||||||
enable_update_checker_helper_forgejo = Se tarkistaa väliajoin uusia Forgejo-versioita tutkimalla TXT DNS -tietueen osoitteesta release.forgejo.org .
|
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
|
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
|
err_admin_name_pattern_not_allowed = Ylläpitäjän käyttäjänimi on epäkelpo, se vastaa varattua kaavaa
|
||||||
|
|
||||||
[home]
|
[home]
|
||||||
uname_holder=Käyttäjätunnus tai sähköpostiosoite
|
uname_holder=käyttäjänimi tai sähköpostiosoite
|
||||||
password_holder=Salasana
|
password_holder=Salasana
|
||||||
switch_dashboard_context=Vaihda kojelaudan kontekstia
|
switch_dashboard_context=Vaihda kojelaudan kontekstia
|
||||||
my_repos=Tietovarastot
|
my_repos=Tietovarastot
|
||||||
|
@ -410,10 +410,10 @@ remember_me=Muista tämä laite
|
||||||
forgot_password_title=Unohtuiko salasana
|
forgot_password_title=Unohtuiko salasana
|
||||||
forgot_password=Unohtuiko salasana?
|
forgot_password=Unohtuiko salasana?
|
||||||
sign_up_now=Tarvitsetko tilin? Rekisteröidy nyt.
|
sign_up_now=Tarvitsetko tilin? Rekisteröidy nyt.
|
||||||
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.
|
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.
|
||||||
must_change_password=Vaihda salasanasi
|
must_change_password=Vaihda salasanasi
|
||||||
allow_password_change=Vaadi käyttäjää vaihtamaan salasanansa (suositeltava)
|
allow_password_change=Vaadi käyttäjää vaihtamaan salasanansa (suositeltava)
|
||||||
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.
|
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.
|
||||||
active_your_account=Aktivoi tilisi
|
active_your_account=Aktivoi tilisi
|
||||||
account_activated=Tili on aktivoitu
|
account_activated=Tili on aktivoitu
|
||||||
prohibit_login=Tili on jäädytetty
|
prohibit_login=Tili on jäädytetty
|
||||||
|
@ -431,7 +431,7 @@ verify=Vahvista
|
||||||
scratch_code=Kertakäyttökoodi
|
scratch_code=Kertakäyttökoodi
|
||||||
use_scratch_code=Käytä kertakäyttökoodia
|
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_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=Salasanasi on väärä. Jos olet hukannut laitteesi, käytäthän kertakäyttökoodia sisäänkirjautumiseen.
|
twofa_passcode_incorrect=Pääsykoodi 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.
|
twofa_scratch_token_incorrect=Kertakäyttökoodisi on virheellinen.
|
||||||
login_userpass=Kirjaudu sisään
|
login_userpass=Kirjaudu sisään
|
||||||
tab_openid=OpenID
|
tab_openid=OpenID
|
||||||
|
@ -440,7 +440,7 @@ oauth_signup_title=Viimeistele uusi tili
|
||||||
oauth_signup_submit=Viimeistele tili
|
oauth_signup_submit=Viimeistele tili
|
||||||
oauth_signin_tab=Linkitä olemassa olevaan tiliin
|
oauth_signin_tab=Linkitä olemassa olevaan tiliin
|
||||||
oauth_signin_title=Kirjaudu sisään valtuuttaaksesi linkitetyn tilin
|
oauth_signin_title=Kirjaudu sisään valtuuttaaksesi linkitetyn tilin
|
||||||
oauth_signin_submit=Yhdistä tiliin
|
oauth_signin_submit=Linkitä tili
|
||||||
oauth.signin.error.access_denied=Valtuutuspyyntö on evätty.
|
oauth.signin.error.access_denied=Valtuutuspyyntö on evätty.
|
||||||
openid_connect_submit=Yhdistä
|
openid_connect_submit=Yhdistä
|
||||||
openid_connect_title=Yhdistä olemassa olevaan tiliin
|
openid_connect_title=Yhdistä olemassa olevaan tiliin
|
||||||
|
@ -483,7 +483,7 @@ prohibit_login_desc = Tilisi käyttö instanssin kanssa on estetty. Ota yhteytt
|
||||||
|
|
||||||
[mail]
|
[mail]
|
||||||
view_it_on=Näytä %s
|
view_it_on=Näytä %s
|
||||||
link_not_working_do_paste=Eikö linkki toimi? Yritä kopioida ja liittää se selaimesi osoitepalkkiin.
|
link_not_working_do_paste=Eikö linkki toimi? Kopioi ja liitä se selaimesi osoiteriville.
|
||||||
hi_user_x=Hei <b>%s</b>,
|
hi_user_x=Hei <b>%s</b>,
|
||||||
|
|
||||||
activate_account=Ole hyvä ja aktivoi tilisi
|
activate_account=Ole hyvä ja aktivoi tilisi
|
||||||
|
@ -491,7 +491,7 @@ activate_account=Ole hyvä ja aktivoi tilisi
|
||||||
activate_email=Vahvista sähköpostiosoitteesi
|
activate_email=Vahvista sähköpostiosoitteesi
|
||||||
|
|
||||||
register_notify=Tervetuloa %s-palveluun
|
register_notify=Tervetuloa %s-palveluun
|
||||||
register_notify.text_2=Voit nyt kirjautua tilillesi käyttäjätunnuksella: %s
|
register_notify.text_2=Voit nyt kirjautua tilillesi käyttäjänimellä: %s
|
||||||
|
|
||||||
reset_password=Palauta käyttäjätili
|
reset_password=Palauta käyttäjätili
|
||||||
reset_password.title=%s, olet pyytänyt tilisi palauttamista
|
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.
|
removed_security_key.text_1 = Turva-avain "%[1]s" on poistettu tililtäsi.
|
||||||
team_invite.text_2 = Napsauta seuraavaa linkkiä liittyäksesi tiimiin:
|
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_1 = Hei <b>%[1]s</b>, kiitos kun rekisteröidyit palveluun %[2]s!
|
||||||
activate_account.text_2 = Aktivoidaksesi tilin, napsauta alla olevaa linkkiä aikaikkunan <b>%s</b> sisällä:
|
activate_account.text_2 = Aktivoi tilisi napsauttamalla alla olevaa linkkiä aikaikkunan <b>%s</b> sisällä:
|
||||||
totp_disabled.subject = TOTP on poistettu käytöstä
|
totp_disabled.subject = TOTP on poistettu käytöstä
|
||||||
primary_mail_change.subject = Ensisijainen sähköpostiosoitteesi on vaihdettu
|
primary_mail_change.subject = Ensisijainen sähköpostiosoitteesi on vaihdettu
|
||||||
admin.new_user.user_info = Käyttäjätiedot
|
admin.new_user.user_info = Käyttäjätiedot
|
||||||
|
@ -570,7 +570,7 @@ modify=Päivitä
|
||||||
confirm = Vahvista
|
confirm = Vahvista
|
||||||
|
|
||||||
[form]
|
[form]
|
||||||
UserName=Käyttäjätunnus
|
UserName=Käyttäjänimi
|
||||||
RepoName=Tietovaraston nimi
|
RepoName=Tietovaraston nimi
|
||||||
Email=Sähköpostiosoite
|
Email=Sähköpostiosoite
|
||||||
Password=Salasana
|
Password=Salasana
|
||||||
|
@ -601,14 +601,14 @@ captcha_incorrect=CAPTCHA-koodi on virheellinen.
|
||||||
password_not_match=Salasanat eivät täsmää.
|
password_not_match=Salasanat eivät täsmää.
|
||||||
lang_select_error=Valitse kieli listalta.
|
lang_select_error=Valitse kieli listalta.
|
||||||
|
|
||||||
username_been_taken=Käyttäjätunnus on jo varattu.
|
username_been_taken=Käyttäjänimi on jo varattu.
|
||||||
repo_name_been_taken=Tietovaraston nimi on jo käytössä.
|
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.
|
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ä.
|
org_name_been_taken=Organisaation nimi on jo käytössä.
|
||||||
team_name_been_taken=Tiimin nimi on jo varattu.
|
team_name_been_taken=Tiimin nimi on jo varattu.
|
||||||
email_been_used=Sähköpostiosoite on jo käytössä.
|
email_been_used=Sähköpostiosoite on jo käytössä.
|
||||||
email_invalid=Sähköpostiosoite on virheellinen.
|
email_invalid=Sähköpostiosoite on virheellinen.
|
||||||
username_password_incorrect=Käyttäjätunnus tai salasana on virheellinen.
|
username_password_incorrect=Käyttäjänimi tai salasana on virheellinen.
|
||||||
password_lowercase_one=Ainakin yksi pieni kirjan
|
password_lowercase_one=Ainakin yksi pieni kirjan
|
||||||
password_uppercase_one=Ainakin yksi iso kirjain
|
password_uppercase_one=Ainakin yksi iso kirjain
|
||||||
password_digit_one=Ainakin yksi numero
|
password_digit_one=Ainakin yksi numero
|
||||||
|
@ -663,6 +663,10 @@ org_still_own_repo = Organisaatio omistaa yhden tai useamman tietovaraston. Pois
|
||||||
org_still_own_packages = Organisaatio omistaa yhden tai useamman paketin. Poista ne ensin.
|
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.
|
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.
|
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]
|
[user]
|
||||||
|
@ -694,11 +698,11 @@ unblock = Poista esto
|
||||||
following_one = %d seurataan
|
following_one = %d seurataan
|
||||||
block_user.detail = Huomaa, että käyttäjän estämisellä on muita vaikutuksia, kuten:
|
block_user.detail = Huomaa, että käyttäjän estämisellä on muita vaikutuksia, kuten:
|
||||||
show_on_map = Näytä paikka kartalla
|
show_on_map = Näytä paikka kartalla
|
||||||
form.name_chars_not_allowed = Käyttäjätunnus "%s" sisältää virheellisiä merkkejä.
|
form.name_chars_not_allowed = Käyttäjänimi "%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.
|
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.
|
disabled_public_activity = Käyttäjä on poistanut käytöstä toiminnan julkisen näkyvyyden.
|
||||||
form.name_reserved = Käyttäjätunnus "%s" on varattu.
|
form.name_reserved = Käyttäjänimi "%s" on varattu.
|
||||||
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu käyttäjätunnuksessa.
|
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu käyttäjänimessä.
|
||||||
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.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>.
|
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
|
watched = Tarkaillut tietovarastot
|
||||||
|
@ -727,7 +731,7 @@ organization=Organisaatiot
|
||||||
webauthn=Kaksivaiheinen todennus (Turva-avaimet)
|
webauthn=Kaksivaiheinen todennus (Turva-avaimet)
|
||||||
|
|
||||||
public_profile=Julkinen profiili
|
public_profile=Julkinen profiili
|
||||||
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjätunnustaan. Ole hyvä ja ota yhteyttä sivuston ylläpitäjään saadaksesi lisätietoa.
|
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjänimeään. Ota yhteys sivuston ylläpitoon saadaksesi lisätietoa.
|
||||||
full_name=Koko nimi
|
full_name=Koko nimi
|
||||||
website=Verkkosivusto
|
website=Verkkosivusto
|
||||||
location=Sijainti
|
location=Sijainti
|
||||||
|
@ -736,14 +740,14 @@ update_profile=Päivitä profiili
|
||||||
update_language=Vaihda kieli
|
update_language=Vaihda kieli
|
||||||
update_language_success=Kieli on päivitetty.
|
update_language_success=Kieli on päivitetty.
|
||||||
update_profile_success=Profiilisi on päivitetty.
|
update_profile_success=Profiilisi on päivitetty.
|
||||||
change_username=Käyttäjätunnuksesi on muutettu.
|
change_username=Käyttäjänimesi on muutettu.
|
||||||
continue=Jatka
|
continue=Jatka
|
||||||
cancel=Peruuta
|
cancel=Peruuta
|
||||||
language=Kieli
|
language=Kieli
|
||||||
ui=Teema
|
ui=Teema
|
||||||
hidden_comment_types=Piilotetut kommenttityypit
|
hidden_comment_types=Piilotetut kommenttityypit
|
||||||
comment_type_group_reference=Viittaus
|
comment_type_group_reference=Viittaus
|
||||||
comment_type_group_label=Tunniste
|
comment_type_group_label=Nimilappu
|
||||||
comment_type_group_milestone=Merkkipaalu
|
comment_type_group_milestone=Merkkipaalu
|
||||||
comment_type_group_assignee=Osoitettu henkilölle
|
comment_type_group_assignee=Osoitettu henkilölle
|
||||||
comment_type_group_title=Otsikko
|
comment_type_group_title=Otsikko
|
||||||
|
@ -888,10 +892,10 @@ twofa_enrolled=Tiliisi on otettu käyttöön kaksivaiheinen todennus. Ota kertak
|
||||||
|
|
||||||
webauthn_nickname=Nimimerkki
|
webauthn_nickname=Nimimerkki
|
||||||
|
|
||||||
manage_account_links=Yhdistetyt tilit
|
manage_account_links=Linkitetyt tilit
|
||||||
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo-tiliisi.
|
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo-tiliisi.
|
||||||
link_account=Yhdistä tili
|
link_account=Linkitä tili
|
||||||
remove_account_link=Poista yhdistetty tili
|
remove_account_link=Poista linkitetty tili
|
||||||
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tilin kautta. Jatketaanko?
|
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tilin kautta. Jatketaanko?
|
||||||
remove_account_link_success=Linkitetty tili on poistettu.
|
remove_account_link_success=Linkitetty tili on poistettu.
|
||||||
|
|
||||||
|
@ -968,14 +972,14 @@ webauthn_alternative_tip = Saatat haluta määrittää lisätodennusmenetelmän.
|
||||||
twofa_disable = Poista kaksivaiheinen todennus käytöstä
|
twofa_disable = Poista kaksivaiheinen todennus käytöstä
|
||||||
twofa_disable_desc = Kaksivaiheisen todennuksen poistaminen asettaa tilisi aiempaa suurempaan uhkaan. Jatketaanko?
|
twofa_disable_desc = Kaksivaiheisen todennuksen poistaminen asettaa tilisi aiempaa suurempaan uhkaan. Jatketaanko?
|
||||||
update_language_not_found = Kieli "%s" ei ole käytettävissä.
|
update_language_not_found = Kieli "%s" ei ole käytettävissä.
|
||||||
change_username_prompt = Huomio: Käyttäjätunnuksen vaihtaminen muuttaa myös tilisi URL-osoitteen.
|
change_username_prompt = Huomio: Käyttäjänimen 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.
|
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
|
blocked_since = Estetty %s lähtien
|
||||||
user_unblock_success = Käyttäjän esto on poistettu.
|
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_redirect_uris = Uudelleenohjaus-URI:t. Käytä uutta riviä (newline) jokaista URI:a kohden.
|
||||||
oauth2_client_secret = Asiakkaan salaisuus
|
oauth2_client_secret = Asiakkaan salaisuus
|
||||||
verify_ssh_key_success = SSH-avain "%s" on vahvistettu.
|
verify_ssh_key_success = SSH-avain "%s" on vahvistettu.
|
||||||
change_username_redirect_prompt = Vanha käyttäjätunnus uudelleenohjaa, kunnes joku muu ottaa käyttäjätunnuksen käyttönsä.
|
change_username_redirect_prompt = Vanha käyttäjänimi uudelleenohjaa, kunnes joku muu ottaa käyttäjänimen käyttöönsä.
|
||||||
uploaded_avatar_is_too_big = Lähetetyn tiedoston koko (%d KiB) ylittää enimmäiskoon (%d KiB).
|
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.
|
ssh_key_been_used = Tämä SSH-avain on jo lisätty palvelimelle.
|
||||||
verify_gpg_key_success = GPG-avain "%s" on vahvistettu.
|
verify_gpg_key_success = GPG-avain "%s" on vahvistettu.
|
||||||
|
@ -1023,9 +1027,16 @@ 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.
|
keep_pronouns_private.description = Tämä piilottaa pronominisi käyttäjiltä, jotka eivät ole kirjautuneet sisään.
|
||||||
comment_type_group_issue_ref = Ongelmaviittaus
|
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.
|
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ätunnus on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjätunnuksen itsellesi suojaamisjakson aikana.
|
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.
|
||||||
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ä.
|
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ätunnus on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjätunnuksen itsellesi suojaamisjakson aikana.
|
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.
|
||||||
|
|
||||||
[repo]
|
[repo]
|
||||||
owner=Omistaja
|
owner=Omistaja
|
||||||
|
@ -1048,8 +1059,8 @@ download_tar=Lataa TAR.GZ
|
||||||
repo_desc=Kuvaus
|
repo_desc=Kuvaus
|
||||||
repo_lang=Kieli
|
repo_lang=Kieli
|
||||||
repo_gitignore_helper=Valitse .gitignore-mallit
|
repo_gitignore_helper=Valitse .gitignore-mallit
|
||||||
issue_labels=Tunnisteet
|
issue_labels=Nimilaput
|
||||||
issue_labels_helper=Valitse tunnistejoukko
|
issue_labels_helper=Valitse nimilappujoukko
|
||||||
license=Lisenssi
|
license=Lisenssi
|
||||||
license_helper=Valitse lisenssitiedosto
|
license_helper=Valitse lisenssitiedosto
|
||||||
readme=README
|
readme=README
|
||||||
|
@ -1074,14 +1085,14 @@ template.git_hooks=Git-koukut
|
||||||
template.webhooks=Webkoukut
|
template.webhooks=Webkoukut
|
||||||
template.topics=Aiheet
|
template.topics=Aiheet
|
||||||
template.avatar=Profiilikuva
|
template.avatar=Profiilikuva
|
||||||
template.issue_labels=Ongelmatunnisteet
|
template.issue_labels=Ongelmanimilaput
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
migrate_items=Migraation kohteet
|
migrate_items=Migraation kohteet
|
||||||
migrate_items_wiki=Wiki
|
migrate_items_wiki=Wiki
|
||||||
migrate_items_milestones=Merkkipaalut
|
migrate_items_milestones=Merkkipaalut
|
||||||
migrate_items_labels=Tunnisteet
|
migrate_items_labels=Nimilaput
|
||||||
migrate_items_issues=Ongelmat
|
migrate_items_issues=Ongelmat
|
||||||
migrate_items_pullrequests=Vetopyynnöt
|
migrate_items_pullrequests=Vetopyynnöt
|
||||||
migrate_items_releases=Julkaisut
|
migrate_items_releases=Julkaisut
|
||||||
|
@ -1118,7 +1129,7 @@ issues=Ongelmat
|
||||||
pulls=Vetopyynnöt
|
pulls=Vetopyynnöt
|
||||||
project_board=Projektit
|
project_board=Projektit
|
||||||
packages=Paketit
|
packages=Paketit
|
||||||
labels=Tunnisteet
|
labels=Nimilaput
|
||||||
|
|
||||||
milestones=Merkkipaalut
|
milestones=Merkkipaalut
|
||||||
commits=Kommitit
|
commits=Kommitit
|
||||||
|
@ -1129,7 +1140,7 @@ released_this=julkaisi tämän
|
||||||
file_raw=Raaka
|
file_raw=Raaka
|
||||||
file_history=Historia
|
file_history=Historia
|
||||||
file_view_raw=Näytä raaka
|
file_view_raw=Näytä raaka
|
||||||
file_permalink=Pysyvä linkki
|
file_permalink=Pysyväislinkki
|
||||||
|
|
||||||
video_not_supported_in_browser=Selaimesi ei tue HTML5:n video-tagia.
|
video_not_supported_in_browser=Selaimesi ei tue HTML5:n video-tagia.
|
||||||
audio_not_supported_in_browser=Selaimesi ei tue HTML5:n audio-tagia.
|
audio_not_supported_in_browser=Selaimesi ei tue HTML5:n audio-tagia.
|
||||||
|
@ -1201,9 +1212,9 @@ issues.desc=Ongelmien, tehtävien ja merkkipaalujen hallinta.
|
||||||
issues.filter_assignees=Suodata käyttäjiä
|
issues.filter_assignees=Suodata käyttäjiä
|
||||||
issues.filter_milestones=Suodata merkkipaalu
|
issues.filter_milestones=Suodata merkkipaalu
|
||||||
issues.new=Uusi ongelma
|
issues.new=Uusi ongelma
|
||||||
issues.new.labels=Tunnisteet
|
issues.new.labels=Nimilaput
|
||||||
issues.new.no_label=Ei tunnisteita
|
issues.new.no_label=Ei nimilappuja
|
||||||
issues.new.clear_labels=Tyhjennä tunnisteet
|
issues.new.clear_labels=Tyhjennä nimilaput
|
||||||
issues.new.projects=Projektit
|
issues.new.projects=Projektit
|
||||||
issues.new.no_items=Ei kohteita
|
issues.new.no_items=Ei kohteita
|
||||||
issues.new.milestone=Merkkipaalu
|
issues.new.milestone=Merkkipaalu
|
||||||
|
@ -1218,11 +1229,11 @@ issues.choose.open_external_link=Avaa
|
||||||
issues.choose.blank=Oletus
|
issues.choose.blank=Oletus
|
||||||
issues.no_ref=Haaraa/tagia ei määritelty
|
issues.no_ref=Haaraa/tagia ei määritelty
|
||||||
issues.create=Luo ongelma
|
issues.create=Luo ongelma
|
||||||
issues.new_label=Uusi tunniste
|
issues.new_label=Uusi nimilappu
|
||||||
issues.new_label_placeholder=Tunnisteen nimi
|
issues.new_label_placeholder=Nimilapun nimi
|
||||||
issues.new_label_desc_placeholder=Kuvaus
|
issues.new_label_desc_placeholder=Kuvaus
|
||||||
issues.create_label=Luo tunniste
|
issues.create_label=Luo nimilappu
|
||||||
issues.label_templates.helper=Valitse tunnisteen esiasetus
|
issues.label_templates.helper=Valitse nimilapun esiasetus
|
||||||
issues.add_milestone_at=`lisäsi tämän merkkipaaluun <b>%s</b> %s`
|
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.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`
|
issues.remove_milestone_at=`poisti tämän <b>%s</b> merkkipaalusta %s`
|
||||||
|
@ -1232,9 +1243,9 @@ issues.deleted_project=`(poistettu)`
|
||||||
issues.self_assign_at=`itse otti tämän käsittelyyn %s`
|
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.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.delete_branch_at=`poisti haaran <b>%s</b> %s`
|
||||||
issues.filter_label=Tunniste
|
issues.filter_label=Nimilappu
|
||||||
issues.filter_label_exclude=`Käytä <code>alt</code> + <code>klikkaus/rivinvaihto</code> poissulkeaksesi tunnisteita`
|
issues.filter_label_exclude=`Käytä <code>alt</code> + <code>napsautus/rivinvaihto</code> poissulkeaksesi nimilappuja`
|
||||||
issues.filter_label_no_select=Kaikki tunnisteet
|
issues.filter_label_no_select=Kaikki nimilaput
|
||||||
issues.filter_milestone=Merkkipaalu
|
issues.filter_milestone=Merkkipaalu
|
||||||
issues.filter_project=Projekti
|
issues.filter_project=Projekti
|
||||||
issues.filter_assignee=Käsittelijä
|
issues.filter_assignee=Käsittelijä
|
||||||
|
@ -1252,15 +1263,15 @@ issues.filter_sort.recentupdate=Äskettäin päivitetty
|
||||||
issues.filter_sort.leastupdate=Kauiten aikaa sitten päivitetty
|
issues.filter_sort.leastupdate=Kauiten aikaa sitten päivitetty
|
||||||
issues.filter_sort.mostcomment=Eniten kommentoidut
|
issues.filter_sort.mostcomment=Eniten kommentoidut
|
||||||
issues.filter_sort.leastcomment=Vähiten kommentoidut
|
issues.filter_sort.leastcomment=Vähiten kommentoidut
|
||||||
issues.filter_sort.nearduedate=Lähin määräpäivä
|
issues.filter_sort.nearduedate=Lähin eräpäivä
|
||||||
issues.filter_sort.farduedate=Kaukaisin määräpäivä
|
issues.filter_sort.farduedate=Kaukaisin eräpäivä
|
||||||
issues.filter_sort.moststars=Eniten tähtiä
|
issues.filter_sort.moststars=Eniten tähtiä
|
||||||
issues.filter_sort.feweststars=Vähiten tähtiä
|
issues.filter_sort.feweststars=Vähiten tähtiä
|
||||||
issues.filter_sort.mostforks=Eniten forkattu
|
issues.filter_sort.mostforks=Eniten forkattu
|
||||||
issues.filter_sort.fewestforks=Vähiten forkattu
|
issues.filter_sort.fewestforks=Vähiten forkattu
|
||||||
issues.action_open=Avaa
|
issues.action_open=Avaa
|
||||||
issues.action_close=Sulje
|
issues.action_close=Sulje
|
||||||
issues.action_label=Tunniste
|
issues.action_label=Nimilappu
|
||||||
issues.action_milestone=Merkkipaalu
|
issues.action_milestone=Merkkipaalu
|
||||||
issues.action_milestone_no_select=Ei merkkipaalua
|
issues.action_milestone_no_select=Ei merkkipaalua
|
||||||
issues.action_assignee=Osoitettu henkilölle
|
issues.action_assignee=Osoitettu henkilölle
|
||||||
|
@ -1291,15 +1302,15 @@ issues.role.member=Jäsen
|
||||||
issues.edit=Muokkaa
|
issues.edit=Muokkaa
|
||||||
issues.cancel=Peruuta
|
issues.cancel=Peruuta
|
||||||
issues.save=Tallenna
|
issues.save=Tallenna
|
||||||
issues.label_title=Tunnisteen nimi
|
issues.label_title=Nimi
|
||||||
issues.label_description=Kuvaus
|
issues.label_description=Kuvaus
|
||||||
issues.label_color=Tunnisteen väri
|
issues.label_color=Väri
|
||||||
issues.label_count=%d tunnistetta
|
issues.label_count=%d nimilappua
|
||||||
issues.label_open_issues=%d avointa ongelmaa/vetopyyntöä
|
issues.label_open_issues=%d avointa ongelmaa/vetopyyntöä
|
||||||
issues.label_edit=Muokkaa
|
issues.label_edit=Muokkaa
|
||||||
issues.label_delete=Poista
|
issues.label_delete=Poista
|
||||||
issues.label_modify=Muokkaa tunnistetta
|
issues.label_modify=Muokkaa nimilappua
|
||||||
issues.label_deletion=Poista tunniste
|
issues.label_deletion=Poista nimilappu
|
||||||
issues.label.filter_sort.alphabetically=Aakkosjärjestyksessä
|
issues.label.filter_sort.alphabetically=Aakkosjärjestyksessä
|
||||||
issues.label.filter_sort.reverse_alphabetically=Käänteisessä aakkosjärjestyksessä
|
issues.label.filter_sort.reverse_alphabetically=Käänteisessä aakkosjärjestyksessä
|
||||||
issues.label.filter_sort.by_size=Pienin koko
|
issues.label.filter_sort.by_size=Pienin koko
|
||||||
|
@ -1334,13 +1345,13 @@ issues.add_time_hours=Tuntia
|
||||||
issues.add_time_minutes=Minuuttia
|
issues.add_time_minutes=Minuuttia
|
||||||
issues.add_time_sum_to_small=Aikaa ei syötetty.
|
issues.add_time_sum_to_small=Aikaa ei syötetty.
|
||||||
issues.time_spent_from_all_authors=`Käytetty kokonaisaika: %s`
|
issues.time_spent_from_all_authors=`Käytetty kokonaisaika: %s`
|
||||||
issues.due_date=Määräpäivä
|
issues.due_date=Eräpäivä
|
||||||
issues.push_commit_1=lisäsi %d kommitin %s
|
issues.push_commit_1=lisäsi %d kommitin %s
|
||||||
issues.push_commits_n=lisäsi %d kommittia %s
|
issues.push_commits_n=lisäsi %d kommittia %s
|
||||||
issues.due_date_form=vvvv-kk-pp
|
issues.due_date_form=vvvv-kk-pp
|
||||||
issues.due_date_form_edit=Muokkaa
|
issues.due_date_form_edit=Muokkaa
|
||||||
issues.due_date_form_remove=Poista
|
issues.due_date_form_remove=Poista
|
||||||
issues.due_date_not_set=Määräpäivää ei ole asetettu.
|
issues.due_date_not_set=Eräpäivää ei ole asetettu.
|
||||||
issues.due_date_overdue=Myöhässä
|
issues.due_date_overdue=Myöhässä
|
||||||
issues.dependency.title=Riippuvuudet
|
issues.dependency.title=Riippuvuudet
|
||||||
issues.dependency.issue_no_dependencies=Riippuvuuksia ei ole asetettu.
|
issues.dependency.issue_no_dependencies=Riippuvuuksia ei ole asetettu.
|
||||||
|
@ -1394,13 +1405,13 @@ pulls.can_auto_merge_desc=Tämä vetopyyntö voidaan yhdistää automaattisesti.
|
||||||
|
|
||||||
milestones.new=Uusi merkkipaalu
|
milestones.new=Uusi merkkipaalu
|
||||||
milestones.closed=Suljettu %s
|
milestones.closed=Suljettu %s
|
||||||
milestones.no_due_date=Ei määräpäivää
|
milestones.no_due_date=Ei eräpäivää
|
||||||
milestones.open=Avaa uudelleen
|
milestones.open=Avaa uudelleen
|
||||||
milestones.close=Sulje
|
milestones.close=Sulje
|
||||||
milestones.create=Luo merkkipaalu
|
milestones.create=Luo merkkipaalu
|
||||||
milestones.title=Otsikko
|
milestones.title=Otsikko
|
||||||
milestones.desc=Kuvaus
|
milestones.desc=Kuvaus
|
||||||
milestones.due_date=Määräpäivä (valinnainen)
|
milestones.due_date=Eräpäivä (valinnainen)
|
||||||
milestones.clear=Tyhjennä
|
milestones.clear=Tyhjennä
|
||||||
milestones.edit=Muokkaa merkkipaalua
|
milestones.edit=Muokkaa merkkipaalua
|
||||||
milestones.cancel=Peruuta
|
milestones.cancel=Peruuta
|
||||||
|
@ -1411,7 +1422,7 @@ milestones.filter_sort.least_issues=Vähiten ongelmia
|
||||||
|
|
||||||
|
|
||||||
wiki=Wiki
|
wiki=Wiki
|
||||||
wiki.welcome=Tervetuloa Wikiin.
|
wiki.welcome=Tervetuloa wikiin.
|
||||||
wiki.welcome_desc=Wikissä voit kirjoittaa ja jakaa dokumentaatiota käyttäjien kesken.
|
wiki.welcome_desc=Wikissä voit kirjoittaa ja jakaa dokumentaatiota käyttäjien kesken.
|
||||||
wiki.create_first_page=Luo ensimmäinen sivu
|
wiki.create_first_page=Luo ensimmäinen sivu
|
||||||
wiki.page=Sivu
|
wiki.page=Sivu
|
||||||
|
@ -1522,9 +1533,9 @@ settings.update_githook=Päivitä koukku
|
||||||
settings.payload_url=Kohde-URL
|
settings.payload_url=Kohde-URL
|
||||||
settings.http_method=HTTP-menetelmä
|
settings.http_method=HTTP-menetelmä
|
||||||
settings.secret=Salaisuus
|
settings.secret=Salaisuus
|
||||||
settings.slack_username=Käyttäjätunnus
|
settings.slack_username=Käyttäjänimi
|
||||||
settings.slack_icon_url=Kuvakkeen URL-osoite
|
settings.slack_icon_url=Kuvakkeen URL-osoite
|
||||||
settings.discord_username=Käyttäjätunnus
|
settings.discord_username=Käyttäjänimi
|
||||||
settings.event_desc=Laukaisu päällä:
|
settings.event_desc=Laukaisu päällä:
|
||||||
settings.event_send_everything=Kaikki tapahtumat
|
settings.event_send_everything=Kaikki tapahtumat
|
||||||
settings.event_choose=Mukautetut tapahtumat…
|
settings.event_choose=Mukautetut tapahtumat…
|
||||||
|
@ -1544,7 +1555,7 @@ settings.event_issues=Muokkaus
|
||||||
settings.event_issues_desc=Ongelma avattu, suljettu, avattu uudelleen tai muokattu.
|
settings.event_issues_desc=Ongelma avattu, suljettu, avattu uudelleen tai muokattu.
|
||||||
settings.event_issue_assign=Toimeksianto
|
settings.event_issue_assign=Toimeksianto
|
||||||
settings.event_issue_assign_desc=Ongelma osoitettu tai osoitus poistettu.
|
settings.event_issue_assign_desc=Ongelma osoitettu tai osoitus poistettu.
|
||||||
settings.event_issue_label_desc=Ongelmatunnisteet lisätty tai poistettu.
|
settings.event_issue_label_desc=Ongelmanimilaput lisätty tai poistettu.
|
||||||
settings.event_issue_milestone_desc=Merkkipaalu lisätty, poistettu tai muokattu.
|
settings.event_issue_milestone_desc=Merkkipaalu lisätty, poistettu tai muokattu.
|
||||||
settings.event_issue_comment_desc=Ongelman kommentti luotu, muokattu tai poistettu.
|
settings.event_issue_comment_desc=Ongelman kommentti luotu, muokattu tai poistettu.
|
||||||
settings.event_header_pull_request=Vetopyyntöjen tapahtumat
|
settings.event_header_pull_request=Vetopyyntöjen tapahtumat
|
||||||
|
@ -1744,7 +1755,7 @@ release.detail = Julkaisun tiedot
|
||||||
diff.hide_file_tree = Piilota tiedostopuu
|
diff.hide_file_tree = Piilota tiedostopuu
|
||||||
issues.role.owner_helper = Tämä käyttäjä on tämän tietovaraston omistaja.
|
issues.role.owner_helper = Tämä käyttäjä on tämän tietovaraston omistaja.
|
||||||
issues.all_title = Kaikki
|
issues.all_title = Kaikki
|
||||||
issues.label_archived_filter = Näytä arkistoidut tunnisteet
|
issues.label_archived_filter = Näytä arkistoidut nimilaput
|
||||||
pulls.close = Sulje vetopyyntö
|
pulls.close = Sulje vetopyyntö
|
||||||
branch.already_exists = Haara nimellä "%s" on jo olemassa.
|
branch.already_exists = Haara nimellä "%s" on jo olemassa.
|
||||||
diff.show_file_tree = Näytä tiedostopuu
|
diff.show_file_tree = Näytä tiedostopuu
|
||||||
|
@ -1793,7 +1804,7 @@ milestones.deletion_success = Merkkipaalu on poistettu.
|
||||||
project = Projektit
|
project = Projektit
|
||||||
pulls.delete.title = Poistetaanko tämä vetopyyntö?
|
pulls.delete.title = Poistetaanko tämä vetopyyntö?
|
||||||
activity.title.issues_1 = %d ongelma
|
activity.title.issues_1 = %d ongelma
|
||||||
contributors.contribution_type.filter_label = Avustuksen tyyppi:
|
contributors.contribution_type.filter_label = Kontribuution tyyppi:
|
||||||
settings.protected_branch.delete_rule = Poista sääntö
|
settings.protected_branch.delete_rule = Poista sääntö
|
||||||
settings.archive.success = Tietovarasto arkistoitiin onnistuneesti.
|
settings.archive.success = Tietovarasto arkistoitiin onnistuneesti.
|
||||||
diff.comment.placeholder = Jätä kommentti
|
diff.comment.placeholder = Jätä kommentti
|
||||||
|
@ -1897,7 +1908,7 @@ pulls.expand_files = Laajenna kaikki tiedostot
|
||||||
issues.content_history.delete_from_history = Poista historiasta
|
issues.content_history.delete_from_history = Poista historiasta
|
||||||
milestones.filter_sort.name = Nimi
|
milestones.filter_sort.name = Nimi
|
||||||
issues.filter_milestone_all = Kaikki merkkipaalut
|
issues.filter_milestone_all = Kaikki merkkipaalut
|
||||||
issues.filter_label_select_no_label = Ei tunnistetta
|
issues.filter_label_select_no_label = Ei nimilappua
|
||||||
projects.column.set_default = Aseta oletukseksi
|
projects.column.set_default = Aseta oletukseksi
|
||||||
projects.edit_success = Projekti "%s" on päivitetty.
|
projects.edit_success = Projekti "%s" on päivitetty.
|
||||||
desc.sha256 = SHA256
|
desc.sha256 = SHA256
|
||||||
|
@ -1942,7 +1953,7 @@ settings.branches.update_default_branch = Päivitä oletushaara
|
||||||
settings.transfer.success = Tietovaraston siirto onnistui.
|
settings.transfer.success = Tietovaraston siirto onnistui.
|
||||||
settings.transfer_abort = Peru siirto
|
settings.transfer_abort = Peru siirto
|
||||||
settings.sync_mirror = Synkronoi nyt
|
settings.sync_mirror = Synkronoi nyt
|
||||||
settings.mirror_settings.docs.doc_link_title = Kuinka peilaan tietovarastot?
|
settings.mirror_settings.docs.doc_link_title = Kuinka peilaan tietovarastoja?
|
||||||
tag.create_tag_operation = Luo tagi
|
tag.create_tag_operation = Luo tagi
|
||||||
branch.rename = Nimeä haara "%s" uudelleen
|
branch.rename = Nimeä haara "%s" uudelleen
|
||||||
branch.download = Lataa haara "%s"
|
branch.download = Lataa haara "%s"
|
||||||
|
@ -2016,9 +2027,9 @@ migrate.git.description = Suorita tietovaraston migraatio mistä tahansa Git-pal
|
||||||
migrate.gitlab.description = Tee migraatio gitlab.comista tai muista GitLab-instansseista.
|
migrate.gitlab.description = Tee migraatio gitlab.comista tai muista GitLab-instansseista.
|
||||||
migrate.gitea.description = Tee migraatio gitea.comista tai muista Gitea-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.
|
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 määräpäivä
|
milestones.filter_sort.latest_due_date = Kaukaisin erä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>.
|
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 määräpäivä
|
milestones.filter_sort.earliest_due_data = Lähin eräpäivä
|
||||||
issues.filter_type.reviewed_by_you = Katselmoitu toimestasi
|
issues.filter_type.reviewed_by_you = Katselmoitu toimestasi
|
||||||
settings.units.overview = Yleisnäkymä
|
settings.units.overview = Yleisnäkymä
|
||||||
settings.remove_team_success = Tiimin pääsy tietovarastoon on poistettu.
|
settings.remove_team_success = Tiimin pääsy tietovarastoon on poistettu.
|
||||||
|
@ -2185,21 +2196,21 @@ transfer.no_permission_to_accept = Sinulla ei ole oikeutta hyväksyä tätä sii
|
||||||
settings.web_hook_name_feishu = Feishu / Lark Suite
|
settings.web_hook_name_feishu = Feishu / Lark Suite
|
||||||
issues.review.reviewers = Katselmoijat
|
issues.review.reviewers = Katselmoijat
|
||||||
issues.new.no_reviewers = Ei katselmoijia
|
issues.new.no_reviewers = Ei katselmoijia
|
||||||
issues.add_label = lisäsi tunnisteen %s %s
|
issues.add_label = lisäsi nimilapun %s %s
|
||||||
issues.due_date_added = lisäsi määräpäivän %s %s
|
issues.due_date_added = lisäsi eräpäivän %s %s
|
||||||
issues.review.add_review_request = pyysi katselmointia käyttäjältä %[1]s %[2]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>`
|
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>`
|
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.review.comment = katselmoi %s
|
||||||
issues.add_labels = lisäsi tunnisteet %s %s
|
issues.add_labels = lisäsi nimilaput %s %s
|
||||||
issues.review.add_review_requests = pyysi katselmointeja käyttäjiltä %[1]s %[2]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.
|
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.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.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.
|
issues.role.contributor_helper = Tämä käyttäjä on aiemmin kommitoinut tähän tietovarastoon.
|
||||||
settings.event_pull_request_label = Tunnisteet
|
settings.event_pull_request_label = Nimilaput
|
||||||
issues.due_date_remove = poisti määräpäivän %s %s
|
issues.due_date_remove = poisti eräpäivän %s %s
|
||||||
settings.event_issue_label = Tunnisteet
|
settings.event_issue_label = Nimilaput
|
||||||
settings.authorization_header = Authorization-otsake
|
settings.authorization_header = Authorization-otsake
|
||||||
diff.has_escaped = Tällä rivillä on piilotettuja Unicode-merkkejä
|
diff.has_escaped = Tällä rivillä on piilotettuja Unicode-merkkejä
|
||||||
issues.max_pinned = Et voi kiinnittää enempää ongelmia
|
issues.max_pinned = Et voi kiinnittää enempää ongelmia
|
||||||
|
@ -2211,8 +2222,8 @@ issues.num_reviews_few = %d katselmointia
|
||||||
issues.filter_no_results = Ei tuloksia
|
issues.filter_no_results = Ei tuloksia
|
||||||
issues.filter_no_results_placeholder = Kokeile määrittää eri hakusuodattimet.
|
issues.filter_no_results_placeholder = Kokeile määrittää eri hakusuodattimet.
|
||||||
projects.edit_subheader = Projektit organisoivat ongelmia ja seuraavat edistymistä.
|
projects.edit_subheader = Projektit organisoivat ongelmia ja seuraavat edistymistä.
|
||||||
issues.label_templates.title = Lataa tunnisteen esiasetus
|
issues.label_templates.title = Lataa nimilapun esiasetus
|
||||||
issues.label_deletion_desc = Tunnisteen poistaminen poistaa sen kaikista ongelmista. Jatketaanko?
|
issues.label_deletion_desc = Nimilapun poistaminen poistaa sen kaikista ongelmista. Jatketaanko?
|
||||||
issues.attachment.download = `Napsauta ladataksesi "%s"`
|
issues.attachment.download = `Napsauta ladataksesi "%s"`
|
||||||
issues.review.option.hide_outdated_comments = Piilota vanhentuneet kommentit
|
issues.review.option.hide_outdated_comments = Piilota vanhentuneet kommentit
|
||||||
issues.review.show_outdated = Näytä vanhentuneet
|
issues.review.show_outdated = Näytä vanhentuneet
|
||||||
|
@ -2223,8 +2234,8 @@ issues.unpin_issue = Poista ongelman kiinnitys
|
||||||
issues.review.outdated_description = Sisältö on muuttunut siitä ajanhetkestä, kun tämä kommentti luotiin
|
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.option.show_outdated_comments = Näytä vanhentuneet kommentit
|
||||||
issues.review.outdated = Vanhentunut
|
issues.review.outdated = Vanhentunut
|
||||||
issues.label_templates.use = Käytä tunnisteen esiasetusta
|
issues.label_templates.use = Käytä nimilapun esiasetusta
|
||||||
issues.label_deletion_success = Tunniste on poistettu.
|
issues.label_deletion_success = Nimilappu on poistettu.
|
||||||
issues.cancel_tracking = Hylkää
|
issues.cancel_tracking = Hylkää
|
||||||
issues.choose.get_started = Aloitetaan
|
issues.choose.get_started = Aloitetaan
|
||||||
settings.event_fork = Forkkaus
|
settings.event_fork = Forkkaus
|
||||||
|
@ -2239,7 +2250,7 @@ pulls.no_merge_wip = Tätä vetopyyntöä ei voida yhdistää, koska se on merki
|
||||||
pulls.clear_merge_message = Tyhjennä yhdistämisviesti
|
pulls.clear_merge_message = Tyhjennä yhdistämisviesti
|
||||||
activity.title.prs_merged_by = %s yhdisti %s
|
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ä.
|
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_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.cmd_instruction_merge_desc = Yhdistä muutokset ja päivitä Forgejossa.
|
||||||
pulls.cannot_auto_merge_desc = Tätä vetopyyntöä ei voida yhdistää automaattisesti ristiriitojen vuoksi.
|
pulls.cannot_auto_merge_desc = Tätä vetopyyntöä ei voida yhdistää automaattisesti ristiriitojen vuoksi.
|
||||||
|
@ -2316,13 +2327,13 @@ migrate_options_lfs = Tee migraatio LFS-tiedostoille
|
||||||
migrate_options_lfs_endpoint.label = LFS-päätepiste
|
migrate_options_lfs_endpoint.label = LFS-päätepiste
|
||||||
commits.browse_further = Selaa kauemmas
|
commits.browse_further = Selaa kauemmas
|
||||||
issues.filter_projects = Suodata projekti
|
issues.filter_projects = Suodata projekti
|
||||||
issues.filter_labels = Suodata tunniste
|
issues.filter_labels = Suodata nimilappu
|
||||||
commits.no_commits = Ei yhteisiä kommitteja. "%s" ja "%s" omaavat täysin eri historiat.
|
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?
|
projects.column.deletion_desc = Projektin sarakkeen poistaminen siirtää kaikki siihen liittyvät ongelmat oletussarakkeeseen. Jatketaanko?
|
||||||
issues.del_time = Poista tämä aikaloki
|
issues.del_time = Poista tämä aikaloki
|
||||||
migrated_from_fake = Suoritettu migraatio lähteestä %[1]s
|
migrated_from_fake = Suoritettu migraatio lähteestä %[1]s
|
||||||
migrate.migrate = Tee migraatio lähteestä %s
|
migrate.migrate = Tee migraatio lähteestä %s
|
||||||
migrate.migrating_labels = Suoritetaan tunnisteiden migraatiota
|
migrate.migrating_labels = Suoritetaan nimilappujen migraatiota
|
||||||
file_view_rendered = Näytä renderöitynä
|
file_view_rendered = Näytä renderöitynä
|
||||||
editor.invalid_commit_mail = Virheellinen sähköposti kommitin luomista varten.
|
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
|
sync_fork.branch_behind_one = Tämä haara on %[1]d kommitin jäljessä %[2]s
|
||||||
|
@ -2360,7 +2371,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.blocked_by_rejection = Tämä vetopyyntö sisältää virallisen katselmoijan vaatimisia muutoksia.
|
||||||
pulls.status_checks_success = Kaikki tarkistukset onnistuivat
|
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.
|
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 = Määräpäivän muodon tulee olla "yyyy-mm-dd".
|
milestones.invalid_due_date_format = Erä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.
|
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.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
|
pulls.status_checks_hide_all = Piilota kaikki tarkistukset
|
||||||
|
@ -2393,7 +2404,7 @@ settings.trust_model.collaborator.desc = Tämän tietovaraston avustajien kelvol
|
||||||
settings.confirm_wiki_branch_rename = Nimeä uudelleen wikin haara
|
settings.confirm_wiki_branch_rename = Nimeä uudelleen wikin haara
|
||||||
settings.event_pull_request_assign = Toimeksianto
|
settings.event_pull_request_assign = Toimeksianto
|
||||||
settings.event_pull_request_assign_desc = Vetopyynnön toimeksianto luotu tai toimeksiannon osoitus poistettu.
|
settings.event_pull_request_assign_desc = Vetopyynnön toimeksianto luotu tai toimeksiannon osoitus poistettu.
|
||||||
settings.event_pull_request_label_desc = Vetopyynnön tunnisteita lisätty tai poistettu.
|
settings.event_pull_request_label_desc = Vetopyynnön nimilappuja lisätty tai poistettu.
|
||||||
settings.active = Aktiivinen
|
settings.active = Aktiivinen
|
||||||
settings.packagist_api_token = API-poletti
|
settings.packagist_api_token = API-poletti
|
||||||
settings.protect_whitelist_committers = Sallittujen listalla rajoitettu työntö
|
settings.protect_whitelist_committers = Sallittujen listalla rajoitettu työntö
|
||||||
|
@ -2431,7 +2442,7 @@ settings.event_pull_request_review_request_desc = Vetopyynnön katselmointi pyyd
|
||||||
settings.event_pull_request_merge = Vetopyynnön yhdistäminen
|
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.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_package_url = Packagist-paketin URL-osoite
|
||||||
settings.packagist_username = Packagist-käyttäjätunnus
|
settings.packagist_username = Packagist-käyttäjänimi
|
||||||
settings.sourcehut_builds.manifest_path = Koontimanifestin polku
|
settings.sourcehut_builds.manifest_path = Koontimanifestin polku
|
||||||
settings.event_pull_request_sync_desc = Haara päivitetty automaattisesti kohdehaaralla.
|
settings.event_pull_request_sync_desc = Haara päivitetty automaattisesti kohdehaaralla.
|
||||||
settings.trust_model.committer = Kommitoija
|
settings.trust_model.committer = Kommitoija
|
||||||
|
@ -2539,6 +2550,33 @@ form.reach_limit_of_creation_n = Omistajan %d tietovaraston rajoitus on jo täyn
|
||||||
form.string_too_long = Merkkijono on pidempi kuin %d merkkiä.
|
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.
|
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ä.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2667,6 +2705,7 @@ teams.add_nonexistent_repo = Tietovarasto, jota yrität lisätä, ei ole olemass
|
||||||
teams.repos.none = Tällä tiimillä ei ole pääsyä tietovarastoihin.
|
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.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.
|
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]
|
[admin]
|
||||||
dashboard=Kojelauta
|
dashboard=Kojelauta
|
||||||
|
@ -2720,7 +2759,7 @@ dashboard.gc_times=Roskienkeruuajat
|
||||||
|
|
||||||
users.user_manage_panel=Käyttäjätilien hallinta
|
users.user_manage_panel=Käyttäjätilien hallinta
|
||||||
users.new_account=Luo käyttäjätili
|
users.new_account=Luo käyttäjätili
|
||||||
users.name=Käyttäjätunnus
|
users.name=Käyttäjänimi
|
||||||
users.full_name=Koko nimi
|
users.full_name=Koko nimi
|
||||||
users.activated=Aktivoitu
|
users.activated=Aktivoitu
|
||||||
users.admin=Ylläpito
|
users.admin=Ylläpito
|
||||||
|
@ -2854,7 +2893,7 @@ config.db_config=Tietokannan asetukset
|
||||||
config.db_type=Tyyppi
|
config.db_type=Tyyppi
|
||||||
config.db_host=Isäntä
|
config.db_host=Isäntä
|
||||||
config.db_name=Nimi
|
config.db_name=Nimi
|
||||||
config.db_user=Käyttäjätunnus
|
config.db_user=Käyttäjänimi
|
||||||
config.db_ssl_mode=SSL
|
config.db_ssl_mode=SSL
|
||||||
config.db_path=Polku
|
config.db_path=Polku
|
||||||
|
|
||||||
|
@ -3357,6 +3396,8 @@ alt.repository = Tietovaraston tiedot
|
||||||
arch.version.replaces = Korvaa
|
arch.version.replaces = Korvaa
|
||||||
debian.repository = Tietovaraston tiedot
|
debian.repository = Tietovaraston tiedot
|
||||||
conda.registry = Määritä tämä rekisteri Conda-tietovarastoksi <code>.condarc</code>-tiedostossa:
|
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]
|
[secrets]
|
||||||
creation.failed = Salaisuuden lisääminen epäonnistui.
|
creation.failed = Salaisuuden lisääminen epäonnistui.
|
||||||
|
@ -3371,6 +3412,7 @@ deletion.description = Salaisuuden poistaminen on pysyvä toimenpide, eikä sit
|
||||||
deletion.success = Salaisuus on poistettu.
|
deletion.success = Salaisuus on poistettu.
|
||||||
description = Salaisuudet välitetään tietyille toimenpiteille, eikä niitä voi muuten lukea.
|
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.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]
|
[actions]
|
||||||
runners.name=Nimi
|
runners.name=Nimi
|
||||||
|
@ -3405,7 +3447,7 @@ workflow.dispatch.input_required = Arvo syötteelle "%s" vaadittu.
|
||||||
runners.status.active = Aktiivinen
|
runners.status.active = Aktiivinen
|
||||||
runs.no_workflows.documentation = Katso lisätietoja Forgejo Actions -ohjelmistosta <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaatiosta</a>.
|
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.
|
variables.description = Muuttujat asetetaan tietyille toiminnoille eikä niitä voida lukea muutoin.
|
||||||
runners.labels = Tunnisteet
|
runners.labels = Nimilaput
|
||||||
runners.delete_runner_failed = Testinajajan poisto epäonnistui
|
runners.delete_runner_failed = Testinajajan poisto epäonnistui
|
||||||
runners.delete_runner_header = Varmista testinajajan poisto
|
runners.delete_runner_header = Varmista testinajajan poisto
|
||||||
runners.task_list.status = Tila
|
runners.task_list.status = Tila
|
||||||
|
@ -3418,7 +3460,7 @@ runners.task_list.no_tasks = Tehtäviä ei ole vielä määritelty.
|
||||||
runners.last_online = Viimeisin käynnissäoloajankohta
|
runners.last_online = Viimeisin käynnissäoloajankohta
|
||||||
runners.runner_title = Testinajaja
|
runners.runner_title = Testinajaja
|
||||||
runners.task_list.done_at = Valmistunut ajankohtana
|
runners.task_list.done_at = Valmistunut ajankohtana
|
||||||
runs.no_matching_online_runner_helper = Testiajajaa tunnisteella %s ei löytynyt
|
runs.no_matching_online_runner_helper = Testiajajaa nimilapulla %s ei löytynyt
|
||||||
runs.no_results = Ei tuloksia.
|
runs.no_results = Ei tuloksia.
|
||||||
runners.delete_runner = Poista testinajaja
|
runners.delete_runner = Poista testinajaja
|
||||||
variables.deletion.description = Muuttujan poistaminen on lopullista, eikä sitä voi perua. Jatketaanko?
|
variables.deletion.description = Muuttujan poistaminen on lopullista, eikä sitä voi perua. Jatketaanko?
|
||||||
|
@ -3465,6 +3507,7 @@ runners.status.offline = Ei-verkkotilassa
|
||||||
runs.no_job_without_needs = Työnkulun tulee sisältää vähintään yksi työ ilman riippuvuuksia.
|
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.
|
runs.no_runs = Työnkululla ei ole vielä suorituksia.
|
||||||
variables.not_found = Muuttujaa ei löytynyt.
|
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ä.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3521,3 +3564,11 @@ releases.read = <b>Lue:</b> Katsele ja lataa julkaisuja.
|
||||||
pulls.read = <b>Lue:</b> Vetopyyntöjen lukeminen ja luominen.
|
pulls.read = <b>Lue:</b> Vetopyyntöjen lukeminen ja luominen.
|
||||||
ext_issues = Pääsy ulkoisen ongelmanseurannan linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
|
ext_issues = Pääsy ulkoisen ongelmanseurannan linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
|
||||||
ext_wiki = Pääsy ulkoisen wikin 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 :) :) :)
|
|
@ -38,9 +38,9 @@ logo = Logo
|
||||||
sign_in = Mag-sign in
|
sign_in = Mag-sign in
|
||||||
sign_in_with_provider = Mag-sign in gamit ang %s
|
sign_in_with_provider = Mag-sign in gamit ang %s
|
||||||
sign_in_or = o
|
sign_in_or = o
|
||||||
sign_out = Mag-Sign Out
|
sign_out = Mag-sign out
|
||||||
sign_up = Magrehistro
|
sign_up = Magrehistro
|
||||||
link_account = Mag-link ng Account
|
link_account = Mag-link ng account
|
||||||
template = Template
|
template = Template
|
||||||
tracked_time_summary = Buod ng mga nakasubaybay na oras base sa filter ng listahan ng isyu
|
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.
|
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
|
applications = Mga Aplikasyon
|
||||||
orgs = Ipamahala ang mga organisasyon
|
orgs = Ipamahala ang mga organisasyon
|
||||||
repos = Mga Repositoryo
|
repos = Mga Repositoryo
|
||||||
delete = Burahin ang Account
|
delete = Burahin ang account
|
||||||
twofa = Authentikasyong two-factor (TOTP)
|
twofa = Authentikasyong two-factor (TOTP)
|
||||||
account_link = Mga naka-link na account
|
account_link = Mga naka-link na account
|
||||||
uid = UID
|
uid = UID
|
||||||
|
@ -1674,10 +1674,10 @@ issues.new_label = Bagong label
|
||||||
issues.label_templates.title = Mag-load ng isang label preset
|
issues.label_templates.title = Mag-load ng isang label preset
|
||||||
issues.new.clear_milestone = I-clear ang milestone
|
issues.new.clear_milestone = I-clear ang milestone
|
||||||
issues.new.open_milestone = Mga bukas na milestone
|
issues.new.open_milestone = Mga bukas na milestone
|
||||||
issues.filter_milestones = I-filter ang Milestone
|
issues.filter_milestones = I-filter ang milestone
|
||||||
issues.filter_projects = I-filter ang Proyekto
|
issues.filter_projects = I-filter ang proyekto
|
||||||
issues.filter_labels = I-filter ang Label
|
issues.filter_labels = I-filter ang label
|
||||||
issues.filter_reviewers = I-filter ang Tagasuri
|
issues.filter_reviewers = I-filter ang tagasuri
|
||||||
issues.remove_labels = tinanggal ang mga label na %s %s
|
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_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`
|
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.add_labels = idinagdag ang mga label na %s %s
|
||||||
issues.remove_label = tinanggal ang %s na label %s
|
issues.remove_label = tinanggal ang %s na label %s
|
||||||
issues.desc = Ayusin ang mga ulat ng bug, gawain, at milestone.
|
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.labels = Mga label
|
||||||
issues.new.no_label = Walang mga label
|
issues.new.no_label = Walang mga label
|
||||||
issues.new.clear_labels = I-clear ang 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
|
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
|
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
|
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
|
wiki.create_first_page = Gawin ang unang pahina
|
||||||
pulls.switch_comparison_type = Ilipat ang uri ng pagkumpara
|
pulls.switch_comparison_type = Ilipat ang uri ng pagkumpara
|
||||||
settings.collaboration.read = Basahin
|
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_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_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.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.team_not_in_organization = Ang koponan ay hindi nasa katulad na organisasyon sa repositoryo
|
||||||
settings.teams = Mga Koponan
|
settings.teams = Mga Koponan
|
||||||
settings.add_team_success = May access na ang koponan sa repositoryo na ito.
|
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:
|
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:
|
vagrant.install = Para magdagdag ng Vagrant box, patakbuhin ang sumusunod na command:
|
||||||
settings.link = I-link ang package na ito sa repository
|
settings.link = I-link ang package na ito sa repository
|
||||||
settings.link.select = Pumili ng Repositoryo
|
settings.link.select = Pumili ng repositoryo
|
||||||
settings.link.button = I-update ang Link ng Repositoryo
|
settings.link.button = I-update ang link ng repositoryo
|
||||||
settings.link.error = Nabigong i-update ang link ng repositoryo.
|
settings.link.error = Nabigong i-update ang link ng repositoryo.
|
||||||
settings.delete = Burahin ang package
|
settings.delete = Burahin ang package
|
||||||
owner.settings.cargo.initialize = I-initialize ang index
|
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
|
runners.status.offline = Offline
|
||||||
workflow.dispatch.invalid_input_type = Hindi wastong input type "%s".
|
workflow.dispatch.invalid_input_type = Hindi wastong input type "%s".
|
||||||
runners.task_list.commit = Commit
|
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
|
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.input_required = Kumailangan ng value para sa input na "%s".
|
||||||
workflow.dispatch.warn_input_limit = Pinapakita lamang ang unang %d na mga input.
|
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.
|
deletion.failed = Nabigong tanggalin ang lihim.
|
||||||
creation.failed = Nabigong idagdag ang lihim.
|
creation.failed = Nabigong idagdag ang lihim.
|
||||||
deletion = Tanggalin 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.
|
description = Ang mga sikreto ay ipapasa sa ilang mga aksyon at hindi mababasa kung hindi.
|
||||||
none = Wala pang mga sikreto sa ngayon.
|
none = Wala pang mga sikreto sa ngayon.
|
||||||
creation.name_placeholder = case-insensitive, alphanumeric character o underscore lamang, hindi dapat magsimula sa GITEA_ o GITHUB_
|
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
|
filepreview.lines = Mga linya %[1]d hanggang %[2]d sa %[3]s
|
||||||
|
|
||||||
[projects]
|
[projects]
|
||||||
deleted.display_name = Binurang Proyekto
|
deleted.display_name = Binurang proyekto
|
||||||
type-2.display_name = Proyekto ng repositoryo
|
type-2.display_name = Proyekto ng repositoryo
|
||||||
type-1.display_name = Indibidwal na proyekto
|
type-1.display_name = Indibidwal na proyekto
|
||||||
type-3.display_name = Proyekto ng organisasyon
|
type-3.display_name = Proyekto ng organisasyon
|
||||||
|
|
|
@ -2044,7 +2044,7 @@ ext_wiki=Wiki externe
|
||||||
ext_wiki.desc=Lier un wiki externe.
|
ext_wiki.desc=Lier un wiki externe.
|
||||||
|
|
||||||
wiki=Wiki
|
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.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.desc=Écrire et partager de la documentation avec vos collaborateurs.
|
||||||
wiki.create_first_page=Créer la première page
|
wiki.create_first_page=Créer la première page
|
||||||
|
@ -2913,6 +2913,13 @@ 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_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.branch_behind_few = Cettte branche a %[1]d commits de retard sur %[2]s
|
||||||
sync_fork.button = Sync
|
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]
|
[graphs]
|
||||||
component_loading = Chargement %s…
|
component_loading = Chargement %s…
|
||||||
|
@ -2921,7 +2928,7 @@ component_loading_failed = Échec de chargement de %s
|
||||||
component_loading_info = Cela peut prendre du temps…
|
component_loading_info = Cela peut prendre du temps…
|
||||||
component_failed_to_load = Une erreur inattendue s'est produite.
|
component_failed_to_load = Une erreur inattendue s'est produite.
|
||||||
contributors.what = contributions
|
contributors.what = contributions
|
||||||
code_frequency.what = fŕequence de code
|
code_frequency.what = fréquence de code
|
||||||
recent_commits.what = commits récents
|
recent_commits.what = commits récents
|
||||||
|
|
||||||
|
|
||||||
|
@ -4004,7 +4011,7 @@ variables.not_found = La variable n'a pas été trouvée.
|
||||||
type-1.display_name=Projet personnel
|
type-1.display_name=Projet personnel
|
||||||
type-2.display_name=Projet du dépôt
|
type-2.display_name=Projet du dépôt
|
||||||
type-3.display_name=Projet de l'organisation
|
type-3.display_name=Projet de l'organisation
|
||||||
deleted.display_name = Projet Supprimé
|
deleted.display_name = Projet supprimé
|
||||||
|
|
||||||
[git.filemode]
|
[git.filemode]
|
||||||
changed_filemode=%[1]s → %[2]s
|
changed_filemode=%[1]s → %[2]s
|
||||||
|
|
|
@ -190,6 +190,7 @@ table_modal.placeholder.header = Cabeceira
|
||||||
link_modal.header = Engadir ligazón
|
link_modal.header = Engadir ligazón
|
||||||
link_modal.url = Url
|
link_modal.url = Url
|
||||||
link_modal.description = Descrición
|
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]
|
[search]
|
||||||
|
@ -225,6 +226,8 @@ app_desc = Um servizo Git autoxestionado e fácil de usar
|
||||||
install = Fácil de instalar
|
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>.
|
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
|
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]
|
[error]
|
||||||
occurred = Ocorreu un erro
|
occurred = Ocorreu un erro
|
||||||
|
@ -291,6 +294,7 @@ app_slogan = Slogan da instancia
|
||||||
app_slogan_helper = Escribe o slogan da túa instancia aqui. Ou deixao baleiro para desabilitala.
|
app_slogan_helper = Escribe o slogan da túa instancia aqui. Ou deixao baleiro para desabilitala.
|
||||||
domain = Dominio do servidor
|
domain = Dominio do servidor
|
||||||
ssh_port = Porto do servidor SSH
|
ssh_port = Porto do servidor SSH
|
||||||
|
require_db_desc = Forgejo precisa MySQL, PostgreSQL, SQLite3 ou TiDB (protocolo MySQL).
|
||||||
|
|
||||||
[repo]
|
[repo]
|
||||||
sync_fork.branch_behind_few = Esta rama ten %d achegas por detrás de %s
|
sync_fork.branch_behind_few = Esta rama ten %d achegas por detrás de %s
|
||||||
|
|
|
@ -8,7 +8,7 @@ sign_in=Accedi
|
||||||
sign_in_or=o
|
sign_in_or=o
|
||||||
sign_out=Esci
|
sign_out=Esci
|
||||||
sign_up=Registrati
|
sign_up=Registrati
|
||||||
link_account=Collega Profilo
|
link_account=Collega profilo
|
||||||
register=Registrati
|
register=Registrati
|
||||||
version=Versione
|
version=Versione
|
||||||
powered_by=Gestito da %s
|
powered_by=Gestito da %s
|
||||||
|
@ -99,7 +99,7 @@ preview=Anteprima
|
||||||
loading=Caricamento…
|
loading=Caricamento…
|
||||||
|
|
||||||
error=Errore
|
error=Errore
|
||||||
error404=La pagina che stai cercando di raggiungere <strong>non esiste</strong> oppure <strong>non sei autorizzato</strong> a visualizzarla.
|
error404=La pagina che stai cercando di raggiungere <strong>non esiste</strong>, <strong>è stata rimossa</strong> oppure <strong>non sei autorizzato</strong> a visualizzarla.
|
||||||
|
|
||||||
never=Mai
|
never=Mai
|
||||||
|
|
||||||
|
@ -3869,7 +3869,7 @@ changed_filemode = %[1]s → %[2]s
|
||||||
|
|
||||||
[search]
|
[search]
|
||||||
type_tooltip = Tipo ricerca
|
type_tooltip = Tipo ricerca
|
||||||
search = Cerca...
|
search = Cerca…
|
||||||
fuzzy = Approssimativa
|
fuzzy = Approssimativa
|
||||||
match = Precisa
|
match = Precisa
|
||||||
org_kind = Cerca organizzazioni...
|
org_kind = Cerca organizzazioni...
|
||||||
|
|
5
options/locale/locale_jbo.ini
Normal file
5
options/locale/locale_jbo.ini
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[common]
|
||||||
|
home = zdani
|
|
@ -312,7 +312,7 @@ default_allow_create_organization=조직 생성 허용을 기본값으로 설정
|
||||||
default_allow_create_organization.description=신규 사용자에게 기본적으로 조직 생성 권한을 부여합니다. 이 옵션이 꺼져있다면, 관리자가 신규 사용자에게 조직 생성 권한을 부여해야합니다.
|
default_allow_create_organization.description=신규 사용자에게 기본적으로 조직 생성 권한을 부여합니다. 이 옵션이 꺼져있다면, 관리자가 신규 사용자에게 조직 생성 권한을 부여해야합니다.
|
||||||
default_enable_timetracking=시간 기록 기능을 기본적으로 사용
|
default_enable_timetracking=시간 기록 기능을 기본적으로 사용
|
||||||
default_enable_timetracking.description=신규 저장소가 시간기록 기능을 기본적으로 사용할 수 있습니다.
|
default_enable_timetracking.description=신규 저장소가 시간기록 기능을 기본적으로 사용할 수 있습니다.
|
||||||
no_reply_address=가려진 이메일 도메인
|
no_reply_address=숨겨진 이메일 도메인
|
||||||
no_reply_address_helper=이메일을 가린 사용자에게 적용될 이메일 도메인입니다. 예를 들어, 사용자명 'joe'가 도메인'noreply.example.org'로 이메일을 가리면 Git에 'joe@noreply.example.org'로 로그인 하게 됩니다.
|
no_reply_address_helper=이메일을 가린 사용자에게 적용될 이메일 도메인입니다. 예를 들어, 사용자명 'joe'가 도메인'noreply.example.org'로 이메일을 가리면 Git에 'joe@noreply.example.org'로 로그인 하게 됩니다.
|
||||||
db_schema_helper = 데이터베이스 기본값 ("공개")를 사용하려면 빈 칸으로 두세요.
|
db_schema_helper = 데이터베이스 기본값 ("공개")를 사용하려면 빈 칸으로 두세요.
|
||||||
require_db_desc = Forgejo를 사용하려면 MySQL, PostgreSQL, SQLite3 또는 TiDB (MySQL 프로토콜) 이 설치되어 있어야 합니다.
|
require_db_desc = Forgejo를 사용하려면 MySQL, PostgreSQL, SQLite3 또는 TiDB (MySQL 프로토콜) 이 설치되어 있어야 합니다.
|
||||||
|
@ -330,6 +330,12 @@ app_slogan_helper = 인스턴스의 슬로건을 입력하세요. 비워두면
|
||||||
reinstall_confirm_check_1 = app.ini의 SECRET_KEY로 암호화 되어있는 데이터를 잃을 수 있습니다: 2FA/OTP를 통해 로그인 할 수 없으며 & 미러가 제대로 작동하지 않게됩니다. app.ini 파일에 정확한 SECRET_KEY가 있는것이 확실하다면 체크하세요.
|
reinstall_confirm_check_1 = app.ini의 SECRET_KEY로 암호화 되어있는 데이터를 잃을 수 있습니다: 2FA/OTP를 통해 로그인 할 수 없으며 & 미러가 제대로 작동하지 않게됩니다. app.ini 파일에 정확한 SECRET_KEY가 있는것이 확실하다면 체크하세요.
|
||||||
run_user_helper = Forgejo를 구동하는 운영체제의 사용자명입니다. 이 사용자는 저장소 루트 경로에 접근권한이 있어야 합니다.
|
run_user_helper = Forgejo를 구동하는 운영체제의 사용자명입니다. 이 사용자는 저장소 루트 경로에 접근권한이 있어야 합니다.
|
||||||
reinstall_confirm_check_2 = 저장소와 설정에 재동기화가 요구될 수 있습니다. 이 박스에 체크하면 저장소의 훅과 authorized_key 들을 수동으로 재동기화해야 한다는 것을 인지한다는 것을 의미합니다. 저장소와 미러의 설정이 올바른지 확인하세요.
|
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]
|
[home]
|
||||||
uname_holder=사용자명 또는 이메일 주소
|
uname_holder=사용자명 또는 이메일 주소
|
||||||
|
@ -347,6 +353,8 @@ search_repos=저장소 찾기..
|
||||||
show_private=비공개
|
show_private=비공개
|
||||||
|
|
||||||
issues.in_your_repos=당신의 저장소에
|
issues.in_your_repos=당신의 저장소에
|
||||||
|
feed_of = "%s"의 피드
|
||||||
|
filter = 다른 필터
|
||||||
|
|
||||||
[explore]
|
[explore]
|
||||||
repos=저장소
|
repos=저장소
|
||||||
|
|
|
@ -162,7 +162,7 @@ filter.not_archived = Nav arhivētas
|
||||||
filter.is_fork = Atzarojumi
|
filter.is_fork = Atzarojumi
|
||||||
filter.not_fork = Nav atzarojumi
|
filter.not_fork = Nav atzarojumi
|
||||||
filter.is_mirror = Spoguļglabātavas
|
filter.is_mirror = Spoguļglabātavas
|
||||||
filter.public = Atklātas
|
filter.public = Publiskas
|
||||||
filter.private = Privātas
|
filter.private = Privātas
|
||||||
filter.clear = Notīrīt atlasi
|
filter.clear = Notīrīt atlasi
|
||||||
confirm_delete_artifact = Vai tiešām izdzēst artefaktu '%s'?
|
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_only_unarchived=Attēlot tikai nearhivētos
|
||||||
|
|
||||||
show_private=Privāts
|
show_private=Privāts
|
||||||
show_both_private_public=Rāda gan atklātās, gan privātās
|
show_both_private_public=Rāda gan publiskās, gan privātās
|
||||||
show_only_private=Attēlot tikai privātos
|
show_only_private=Attēlot tikai privātos
|
||||||
show_only_public=Attēlo tikai atklātās
|
show_only_public=Tiek rādītas tikai publiskās
|
||||||
|
|
||||||
issues.in_your_repos=Manās glabātavā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…
|
change_avatar=Mainīt profila attēlu…
|
||||||
joined_on=Pievienojās %s
|
joined_on=Pievienojās %s
|
||||||
repositories=Glabātavas
|
repositories=Glabātavas
|
||||||
activity=Atklāti notikumi
|
activity=Publiskas darbības
|
||||||
followers_few=%d sekotāji
|
followers_few=%d sekotāji
|
||||||
starred=Izlasei pievienotās glabātavas
|
starred=Izlasei pievienotās glabātavas
|
||||||
watched=Vērotās glabātavas
|
watched=Vērotās glabātavas
|
||||||
|
@ -701,7 +701,7 @@ following_few=%d seko
|
||||||
follow=Sekot
|
follow=Sekot
|
||||||
unfollow=Pārtraukt sekot
|
unfollow=Pārtraukt sekot
|
||||||
user_bio=Apraksts par sevi
|
user_bio=Apraksts par sevi
|
||||||
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību visiem.
|
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību citiem.
|
||||||
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
|
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
|
||||||
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
|
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
|
||||||
show_on_map=Rādīt šo vietu kartē
|
show_on_map=Rādīt šo vietu kartē
|
||||||
|
@ -749,7 +749,7 @@ organization=Apvienības
|
||||||
uid=UID
|
uid=UID
|
||||||
webauthn=Divpakāpju pieteikšanās (drošības atslēgas)
|
webauthn=Divpakāpju pieteikšanās (drošības atslēgas)
|
||||||
|
|
||||||
public_profile=Visiem pieejamais profils
|
public_profile=Publiskais profils
|
||||||
biography_placeholder=Pastāsti citiem mazliet par sevi! (Tiek atbalstīts Markdown)
|
biography_placeholder=Pastāsti citiem mazliet par sevi! (Tiek atbalstīts Markdown)
|
||||||
location_placeholder=Kopīgot savu aptuveno atrašanās vietu ar citiem
|
location_placeholder=Kopīgot savu aptuveno atrašanās vietu ar citiem
|
||||||
profile_desc=Par Tevi
|
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?
|
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.
|
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
|
repo_and_org_access=Glabātavas un apvienības piekļuve
|
||||||
permissions_public_only=Tikai atklātās
|
permissions_public_only=Tikai publiskās
|
||||||
permissions_access_all=Visas (atklātās, privātās un ierobežotās)
|
permissions_access_all=Visas (publiskās, privātās un ierobežotās)
|
||||||
select_permissions=Atlasīt atļaujas
|
select_permissions=Atlasīt atļaujas
|
||||||
permission_no_access=Nav piekļuves
|
permission_no_access=Nav piekļuves
|
||||||
permission_read=Lasīt
|
permission_read=Lasīt
|
||||||
|
@ -1035,14 +1035,14 @@ email_notifications.submit=Iestatīt e-pasta iestatījumus
|
||||||
email_notifications.andyourown=Un manus paziņojumus
|
email_notifications.andyourown=Un manus paziņojumus
|
||||||
|
|
||||||
visibility=Lietotāja redzamība
|
visibility=Lietotāja redzamība
|
||||||
visibility.public=Atklāta
|
visibility.public=Publiska
|
||||||
visibility.public_tooltip=Redzams ikvienam
|
visibility.public_tooltip=Redzams ikvienam
|
||||||
visibility.limited=Ierobežota
|
visibility.limited=Ierobežota
|
||||||
visibility.limited_tooltip=Redzams tikai lietotājiem, kuri ir pieteikušies
|
visibility.limited_tooltip=Redzams tikai lietotājiem, kuri ir pieteikušies
|
||||||
visibility.private=Privāta
|
visibility.private=Privāta
|
||||||
visibility.private_tooltip=Redzams tikai apvienību, kurās pievienojies, dalībniekiem
|
visibility.private_tooltip=Redzams tikai apvienību, kurās pievienojies, dalībniekiem
|
||||||
change_password = Mainīt paroli
|
change_password = Mainīt paroli
|
||||||
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.
|
keep_activity_private.description = Tavas <a href="%s">publiskās darbības</a> būs redzamas tikai Tev un servera pārvaldītājiem.
|
||||||
update_hints = Atjaunināt norādes
|
update_hints = Atjaunināt norādes
|
||||||
update_hints_success = Norādes tika atjauninātas.
|
update_hints_success = Norādes tika atjauninātas.
|
||||||
user_block_success = Lietotājs tika sekmīgi liegts.
|
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.rule.no_limit = Neierobežots
|
||||||
quota.sizes.all = Viss
|
quota.sizes.all = Viss
|
||||||
quota.sizes.repos.all = Glabātavas
|
quota.sizes.repos.all = Glabātavas
|
||||||
quota.sizes.repos.public = Atklātās glabātavas
|
quota.sizes.repos.public = Publiskās glabātavas
|
||||||
quota.sizes.repos.private = Privātās glabātavas
|
quota.sizes.repos.private = Privātās glabātavas
|
||||||
regenerate_token = Izveidot no jauna
|
regenerate_token = Izveidot no jauna
|
||||||
access_token_regeneration = Izveidot piekļuves pilnvaru 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.
|
transfer.no_permission_to_reject=Nav atļaujas noraidīt šo nodošanu.
|
||||||
|
|
||||||
desc.private=Privāts
|
desc.private=Privāts
|
||||||
desc.public=Atklāts
|
desc.public=Publisks
|
||||||
desc.template=Sagatave
|
desc.template=Sagatave
|
||||||
desc.internal=Iekšējs
|
desc.internal=Iekšējs
|
||||||
desc.archived=Arhivēts
|
desc.archived=Arhivēts
|
||||||
|
@ -1464,7 +1464,7 @@ commit.cherry-pick-content=Atlasīt zaru, uz kuru izlasīt:
|
||||||
commitstatus.error=Kļūda
|
commitstatus.error=Kļūda
|
||||||
commitstatus.failure=Atteice
|
commitstatus.failure=Atteice
|
||||||
commitstatus.pending=Nav iesūtīts
|
commitstatus.pending=Nav iesūtīts
|
||||||
commitstatus.success=Pabeigts
|
commitstatus.success=Sekmīgs
|
||||||
|
|
||||||
ext_issues=Ārēji pieteikumi
|
ext_issues=Ārēji pieteikumi
|
||||||
ext_issues.desc=Saite uz ārējo problēmu sekotāju.
|
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_milestones=Atlasīt pēc atskaites punkta
|
||||||
issues.filter_projects=Atlasīt pēc projekta
|
issues.filter_projects=Atlasīt pēc projekta
|
||||||
issues.filter_labels=Atlasīt pēc iezīmes
|
issues.filter_labels=Atlasīt pēc iezīmes
|
||||||
issues.filter_reviewers=Atlasīt izskatītājus
|
issues.filter_reviewers=Atlasīt pēc izskatītājiem
|
||||||
issues.new=Jauns pieteikums
|
issues.new=Jauns pieteikums
|
||||||
issues.new.title_empty=Nosaukums nevar būt tukšs
|
issues.new.title_empty=Nosaukums nevar būt tukšs
|
||||||
issues.new.labels=Iezīmes
|
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.
|
ext_wiki.desc=Ārējā vikivietne norāda uz ārējo vikivietnes adresi.
|
||||||
|
|
||||||
wiki=Vikivietne
|
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.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.desc=Dokumentācijas rakstīšana un kopīgošana ar līdzdalībniekiem.
|
||||||
wiki.create_first_page=Izveidot pirmo lapu
|
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
|
size_format = %[1]s: %[2]s; %[3]s: %[4]s
|
||||||
mirror_public_key = Publiskā SSH atslēga
|
mirror_public_key = Publiskā SSH atslēga
|
||||||
mirror_use_ssh.text = Izmantot SSH autentificēšanos
|
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 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.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.not_available = SSH autentificēšanās nav pieejama.
|
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.
|
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.
|
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.permission=Tiesības
|
||||||
settings.repoadminchangeteam=Glabātavas pārvaldītājs var pievienot un noņemt komandu piekļuvi
|
settings.repoadminchangeteam=Glabātavas pārvaldītājs var pievienot un noņemt komandu piekļuvi
|
||||||
settings.visibility=Redzamība
|
settings.visibility=Redzamība
|
||||||
settings.visibility.public=Atklāta
|
settings.visibility.public=Publiska
|
||||||
settings.visibility.limited=Ierobežota (redzama tikai lietotājiem, kuri ir pieteikušies)
|
settings.visibility.limited=Ierobežota (redzama tikai lietotājiem, kuri ir pieteikušies)
|
||||||
settings.visibility.limited_shortname=Ierobežota
|
settings.visibility.limited_shortname=Ierobežota
|
||||||
settings.visibility.private=Privāta (redzama tikai apvienības dalībniekiem)
|
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.
|
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.app_slogan = Servera sauklis
|
||||||
config.allow_dots_in_usernames = Ļaut lietotājiem izmantot punktus savā lietotājvārdā. Neietekmē esošos kontus.
|
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 atklātajā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 publiskajām glabātavām.
|
||||||
dashboard.sync_tag.started = Uzsākta birku sinhronizēšana
|
dashboard.sync_tag.started = Uzsākta birku sinhronizēšana
|
||||||
users.organization_creation.description = Ļaut jaunu apvienību izveidošanu.
|
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.
|
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.status=Stāvoklis
|
||||||
runners.task_list.repository=Glabātava
|
runners.task_list.repository=Glabātava
|
||||||
runners.task_list.commit=Iesūtījums
|
runners.task_list.commit=Iesūtījums
|
||||||
runners.task_list.done_at=Beigu laiks
|
runners.task_list.done_at=Pabeigts
|
||||||
runners.edit_runner=Labot izpildītāju
|
runners.edit_runner=Labot izpildītāju
|
||||||
runners.update_runner=Atjaunināt izmaiņas
|
runners.update_runner=Atjaunināt izmaiņas
|
||||||
runners.update_runner_success=Izpildītājs sekmīgi atjaunināts
|
runners.update_runner_success=Izpildītājs sekmīgi atjaunināts
|
||||||
|
|
|
@ -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.reopen_issue = Weer opmaken
|
||||||
issues.closed_at = `hett deeses Gefall <a id="%[1]s" href="#%[1]s">%[2]s</a> dichtmaakt`
|
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.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 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_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_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_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_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`
|
issues.ref_from = `vun %[1]s`
|
||||||
|
@ -2614,6 +2614,13 @@ archive.nocomment = Kommenteren gaht hier nich, denn dat Repositorium is archive
|
||||||
sync_fork.button = Vernejen
|
sync_fork.button = Vernejen
|
||||||
sync_fork.branch_behind_one = Deeser Twieg is %[1]d Kommitteren achter %[2]s
|
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
|
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]
|
[repo.permissions]
|
||||||
code.read = <b>Lesen:</b> De Quelltext vun deesem Repositorium ankieken un klonen.
|
code.read = <b>Lesen:</b> De Quelltext vun deesem Repositorium ankieken un klonen.
|
||||||
|
|
|
@ -8,7 +8,7 @@ sign_in=Aanmelden
|
||||||
sign_in_or=of
|
sign_in_or=of
|
||||||
sign_out=Uitloggen
|
sign_out=Uitloggen
|
||||||
sign_up=Registreren
|
sign_up=Registreren
|
||||||
link_account=Account Koppelen
|
link_account=Account koppelen
|
||||||
register=Registreren
|
register=Registreren
|
||||||
version=Versie
|
version=Versie
|
||||||
powered_by=Mogelijk gemaakt door %s
|
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_inactive_user=Kan geen inactieve gebruiker toevoegen als medewerker.
|
||||||
settings.add_collaborator_duplicate=De collaborator is al toegevoegd aan deze repository.
|
settings.add_collaborator_duplicate=De collaborator is al toegevoegd aan deze repository.
|
||||||
settings.delete_collaborator=Verwijder
|
settings.delete_collaborator=Verwijder
|
||||||
settings.collaborator_deletion=Verwijder medewerker
|
settings.collaborator_deletion=Verwijder samenwerker
|
||||||
settings.collaborator_deletion_desc=Het verwijderen van een collaborator zal hun toegang tot deze repository intrekken. Doorgaan?
|
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.remove_collaborator_success=De medewerker is verwijderd.
|
||||||
settings.search_user_placeholder=Zoek gebruiker…
|
settings.search_user_placeholder=Zoek gebruiker…
|
||||||
|
@ -3914,7 +3914,7 @@ runners.task_list.no_tasks = Er is nog geen taak.
|
||||||
runners.labels = Labels
|
runners.labels = Labels
|
||||||
runners.last_online = Laatste online tijd
|
runners.last_online = Laatste online tijd
|
||||||
runners.task_list.status = Status
|
runners.task_list.status = Status
|
||||||
runners.task_list.done_at = Gedaan Op
|
runners.task_list.done_at = Gedaan op
|
||||||
runners.id = ID
|
runners.id = ID
|
||||||
runs.actor = Acteur
|
runs.actor = Acteur
|
||||||
actions = Actions
|
actions = Actions
|
||||||
|
|
|
@ -1503,11 +1503,11 @@ projects.card_type.images_and_text=Imagens e texto
|
||||||
projects.card_type.text_only=Somente texto
|
projects.card_type.text_only=Somente texto
|
||||||
|
|
||||||
issues.desc=Organize relatórios de bugs, tarefas e marcos.
|
issues.desc=Organize relatórios de bugs, tarefas e marcos.
|
||||||
issues.filter_assignees=Filtrar Atribuição
|
issues.filter_assignees=Filtrar atribuição
|
||||||
issues.filter_milestones=Filtrar Marco
|
issues.filter_milestones=Filtrar marco
|
||||||
issues.filter_projects=Filtrar Projeto
|
issues.filter_projects=Filtrar projeto
|
||||||
issues.filter_labels=Filtrar Rótulo
|
issues.filter_labels=Filtrar rótulo
|
||||||
issues.filter_reviewers=Filtrar Revisor
|
issues.filter_reviewers=Filtrar revisor
|
||||||
issues.new=Novo issue
|
issues.new=Novo issue
|
||||||
issues.new.title_empty=Título não pode ser em branco
|
issues.new.title_empty=Título não pode ser em branco
|
||||||
issues.new.labels=Etiquetas
|
issues.new.labels=Etiquetas
|
||||||
|
@ -2013,7 +2013,7 @@ ext_wiki=Wiki Externa
|
||||||
ext_wiki.desc=Link para uma wiki externa.
|
ext_wiki.desc=Link para uma wiki externa.
|
||||||
|
|
||||||
wiki=Wiki
|
wiki=Wiki
|
||||||
wiki.welcome=Bem-vindo a wiki.
|
wiki.welcome=Bem-vindo à wiki.
|
||||||
wiki.welcome_desc=A wiki permite que você escreva e compartilhe a documentação com os colaboradores.
|
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.desc=Escrever e compartilhar a documentação com os colaboradores.
|
||||||
wiki.create_first_page=Criar a primeira página
|
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:
|
vagrant.install=Para adicionar uma Vagrant box, execute o seguinte comando:
|
||||||
settings.link=Vincular este pacote a um repositório
|
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.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.select=Selecionar repositório
|
||||||
settings.link.button=Atualizar Link do Repositório
|
settings.link.button=Atualizar link do repositório
|
||||||
settings.link.success=Link do repositório foi atualizado com sucesso.
|
settings.link.success=Link do repositório foi atualizado com sucesso.
|
||||||
settings.link.error=Falha ao atualizar o link do repositório.
|
settings.link.error=Falha ao atualizar o link do repositório.
|
||||||
settings.delete=Excluir o pacote
|
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-1.display_name=Projeto individual
|
||||||
type-2.display_name=Projeto do repositório
|
type-2.display_name=Projeto do repositório
|
||||||
type-3.display_name=Projeto da organização
|
type-3.display_name=Projeto da organização
|
||||||
deleted.display_name = Projeto Apagado
|
deleted.display_name = Projeto apagado
|
||||||
|
|
||||||
[git.filemode]
|
[git.filemode]
|
||||||
symbolic_link=Ligação simbólica
|
symbolic_link=Ligação simbólica
|
||||||
|
|
|
@ -9,7 +9,7 @@ sign_in_with_provider=Iniciar sessão com %s
|
||||||
sign_in_or=ou
|
sign_in_or=ou
|
||||||
sign_out=Terminar sessão
|
sign_out=Terminar sessão
|
||||||
sign_up=Fazer inscrição
|
sign_up=Fazer inscrição
|
||||||
link_account=Vincular conta
|
link_account=Associar conta
|
||||||
register=Inscrição
|
register=Inscrição
|
||||||
version=Versão
|
version=Versão
|
||||||
powered_by=Implementado com %s
|
powered_by=Implementado com %s
|
||||||
|
@ -20,12 +20,12 @@ notifications=Notificações
|
||||||
active_stopwatch=Cronómetro em andamento
|
active_stopwatch=Cronómetro em andamento
|
||||||
tracked_time_summary=Resumo do tempo rastreado com base em filtros da lista de questões
|
tracked_time_summary=Resumo do tempo rastreado com base em filtros da lista de questões
|
||||||
create_new=Criar…
|
create_new=Criar…
|
||||||
user_profile_and_more=Perfil e configurações…
|
user_profile_and_more=Perfil e definições…
|
||||||
signed_in_as=Sessão iniciada como
|
signed_in_as=Sessão iniciada como
|
||||||
enable_javascript=Este sítio Web requer JavaScript.
|
enable_javascript=Este sítio Web requer JavaScript.
|
||||||
toc=Índice
|
toc=Índice
|
||||||
licenses=Licenças
|
licenses=Licenças
|
||||||
return_to_forgejo=Retornar ao Forgejo
|
return_to_forgejo=Voltar ao Forgejo
|
||||||
|
|
||||||
username=Nome de utilizador
|
username=Nome de utilizador
|
||||||
email=Endereço de email
|
email=Endereço de email
|
||||||
|
@ -59,10 +59,10 @@ new_migrate=Nova migração
|
||||||
new_mirror=Nova réplica
|
new_mirror=Nova réplica
|
||||||
new_fork=Nova derivação do repositório
|
new_fork=Nova derivação do repositório
|
||||||
new_org=Nova organização
|
new_org=Nova organização
|
||||||
new_project=Novo planeamento
|
new_project=Novo projeto
|
||||||
new_project_column=Nova coluna
|
new_project_column=Nova coluna
|
||||||
manage_org=Gerir organizações
|
manage_org=Gerir organizações
|
||||||
admin_panel=Administração do sítio
|
admin_panel=Administração do site
|
||||||
account_settings=Configurações da conta
|
account_settings=Configurações da conta
|
||||||
settings=Configurações
|
settings=Configurações
|
||||||
your_profile=Perfil
|
your_profile=Perfil
|
||||||
|
@ -155,7 +155,7 @@ invalid_data = Dados inválidos: %v
|
||||||
filter.clear = Retirar filtros
|
filter.clear = Retirar filtros
|
||||||
filter.is_archived = Arquivado
|
filter.is_archived = Arquivado
|
||||||
filter.not_template = Não modelos
|
filter.not_template = Não modelos
|
||||||
toggle_menu = Comutar menu
|
toggle_menu = Alternar menu
|
||||||
filter = Filtrar
|
filter = Filtrar
|
||||||
copy_generic = Copiar para a área de transferência
|
copy_generic = Copiar para a área de transferência
|
||||||
test = Teste
|
test = Teste
|
||||||
|
@ -233,7 +233,7 @@ platform_desc=Está confirmado que Forgejo corre em sistemas operativos livres,
|
||||||
lightweight=Leve
|
lightweight=Leve
|
||||||
lightweight_desc=Forgejo requer poucos recursos e pode correr num simples Raspberry Pi. Economize a energia da sua máquina!
|
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=Código aberto
|
||||||
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!
|
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!
|
||||||
|
|
||||||
[install]
|
[install]
|
||||||
install=Instalação
|
install=Instalação
|
||||||
|
@ -291,7 +291,7 @@ smtp_port=Porto do SMTP
|
||||||
smtp_from=Email do remetente
|
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>.
|
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_user=Nome de utilizador do SMTP
|
||||||
mailer_password=Senha do SMTP
|
mailer_password=Palavra-passe do SMTP
|
||||||
register_confirm=Exigir confirmação de email para se inscrever
|
register_confirm=Exigir confirmação de email para se inscrever
|
||||||
mail_notify=Habilitar notificações por email
|
mail_notify=Habilitar notificações por email
|
||||||
server_service_title=Configurações do servidor e de terceiros
|
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_title=Configurações da conta de administração
|
||||||
admin_name=Nome de utilizador do administrador
|
admin_name=Nome de utilizador do administrador
|
||||||
admin_password=Senha
|
admin_password=Senha
|
||||||
confirm_password=Confirme a senha
|
confirm_password=Confirme a palavra-passe
|
||||||
admin_email=Endereço de email
|
admin_email=Endereço de email
|
||||||
install_btn_confirm=Instalar Forgejo
|
install_btn_confirm=Instalar Forgejo
|
||||||
test_git_failed=Não foi possível testar o comando "git": %v
|
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.
|
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=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".
|
no_reply_address_helper=Nome de domínio para utilizadores com um endereço de email oculto. Por exemplo, o nome de utilizador "silva" será registado no Git como "silva@semresposta.exemplo.org" se o domínio de email oculto estiver definido como "semresposta.exemplo.org".
|
||||||
password_algorithm=Algoritmo de Hash da Senha
|
password_algorithm=Algoritmo de Hash da palavra-passe
|
||||||
invalid_password_algorithm=Algoritmo de hash da senha inválido
|
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.
|
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
|
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.
|
manual_activation_only=Contacte o administrador para completar a habilitação.
|
||||||
remember_me=Memorizar este dispositivo
|
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.
|
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 senha
|
forgot_password_title=Esqueci-me da palavra-passe
|
||||||
forgot_password=Esqueceu a sua senha?
|
forgot_password=Esqueceu a sua senha?
|
||||||
sign_up_now=Precisa de uma conta? Inscreva-se agora.
|
sign_up_now=Precisa de uma conta? Inscreva-se agora.
|
||||||
sign_up_successful=A conta foi criada com sucesso. Bem-vindo/a!
|
sign_up_successful=A conta foi criada com sucesso. Bem-vindo/a!
|
||||||
|
@ -744,7 +744,7 @@ social=Contas sociais
|
||||||
applications=Aplicações
|
applications=Aplicações
|
||||||
orgs=Organizações
|
orgs=Organizações
|
||||||
repos=Repositórios
|
repos=Repositórios
|
||||||
delete=Eliminar a conta
|
delete=Eliminar conta
|
||||||
twofa=Autenticação em dois passos (TOTP)
|
twofa=Autenticação em dois passos (TOTP)
|
||||||
account_link=Contas vinculadas
|
account_link=Contas vinculadas
|
||||||
organization=Organizações
|
organization=Organizações
|
||||||
|
@ -1060,7 +1060,7 @@ user_unblock_success = O utilizador foi desbloqueado com sucesso.
|
||||||
language.title = Idioma predefinido
|
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.
|
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.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">Saiba mais</a>.
|
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! <a href="%s">Ler mais</a>.
|
||||||
pronouns_custom_label = Pronomes personalizados
|
pronouns_custom_label = Pronomes personalizados
|
||||||
user_block_yourself = Não se pode bloquear a si próprio.
|
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.
|
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?
|
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]
|
[repo]
|
||||||
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>.
|
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>.
|
||||||
owner=Proprietá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.
|
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
|
repo_name=Nome do repositório
|
||||||
|
@ -1133,7 +1133,7 @@ issue_labels=Rótulos
|
||||||
issue_labels_helper=Escolha um conjunto de rótulos
|
issue_labels_helper=Escolha um conjunto de rótulos
|
||||||
license=Licença
|
license=Licença
|
||||||
license_helper=Escolha um ficheiro de 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 trabalho? 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 projeto? Veja: <a target="_blank" rel="noopener noreferrer" href="%s">Escolher uma licença</a>.
|
||||||
object_format=Formato dos elementos
|
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.
|
object_format_helper=Formato dos elementos do repositório. Não poderá ser alterado mais tarde. SHA1 é o mais compatível.
|
||||||
readme=README
|
readme=README
|
||||||
|
@ -1479,23 +1479,23 @@ projects=Planeamentos
|
||||||
projects.desc=Gerir questões e integrações nos quadros do planeamento.
|
projects.desc=Gerir questões e integrações nos quadros do planeamento.
|
||||||
projects.description=Descrição (opcional)
|
projects.description=Descrição (opcional)
|
||||||
projects.description_placeholder=Descrição
|
projects.description_placeholder=Descrição
|
||||||
projects.create=Criar planeamento
|
projects.create=Criar projeto
|
||||||
projects.title=Título
|
projects.title=Título
|
||||||
projects.new=Novo planeamento
|
projects.new=Novo projeto
|
||||||
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.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.create_success=O planeamento "%s" foi criado.
|
||||||
projects.deletion=Eliminar planeamento
|
projects.deletion=Eliminar projeto
|
||||||
projects.deletion_desc=Eliminar um planeamento remove-o de todas as questões relacionadas. Continuar?
|
projects.deletion_desc=Eliminar um planeamento remove-o de todas as questões relacionadas. Continuar?
|
||||||
projects.deletion_success=O planeamento foi eliminado.
|
projects.deletion_success=O planeamento foi eliminado.
|
||||||
projects.edit=Editar planeamentos
|
projects.edit=Editar projeto
|
||||||
projects.edit_subheader=Planeamentos organizam questões e acompanham o progresso.
|
projects.edit_subheader=Planeamentos organizam questões e acompanham o progresso.
|
||||||
projects.modify=Editar planeamento
|
projects.modify=Editar projeto
|
||||||
projects.edit_success=O planeamento "%s" foi modificado.
|
projects.edit_success=O planeamento "%s" foi modificado.
|
||||||
projects.type.none=Nenhum
|
projects.type.none=Nenhum
|
||||||
projects.type.basic_kanban=Kanban básico
|
projects.type.basic_kanban=Kanban básico
|
||||||
projects.type.bug_triage=Triagem de erros
|
projects.type.bug_triage=Triagem de erros
|
||||||
projects.template.desc=Modelo
|
projects.template.desc=Modelo
|
||||||
projects.template.desc_helper=Escolha um modelo de planeamento para começar
|
projects.template.desc_helper=Escolha um modelo de projeto para começar
|
||||||
projects.type.uncategorized=Sem categoria
|
projects.type.uncategorized=Sem categoria
|
||||||
projects.column.edit=Editar coluna
|
projects.column.edit=Editar coluna
|
||||||
projects.column.edit_title=Nome
|
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=Deixar de ser a predefinida
|
||||||
projects.column.unset_default_desc=Faz com que esta coluna deixe 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.delete=Eliminar coluna
|
||||||
projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna padrão. Continuar?
|
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.color=Colorido
|
projects.column.color=Colorido
|
||||||
projects.open=Abrir
|
projects.open=Abrir
|
||||||
projects.close=Fechar
|
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.desc=Organize relatórios de erros, tarefas e etapas.
|
||||||
issues.filter_assignees=Filtrar encarregado
|
issues.filter_assignees=Filtrar encarregado
|
||||||
issues.filter_milestones=Filtrar etapa
|
issues.filter_milestones=Filtrar etapa
|
||||||
issues.filter_projects=Filtrar planeamento
|
issues.filter_projects=Filtrar projeto
|
||||||
issues.filter_labels=Filtrar rótulo
|
issues.filter_labels=Filtrar rótulo
|
||||||
issues.filter_reviewers=Filtrar revisor
|
issues.filter_reviewers=Filtrar revisor
|
||||||
issues.new=Questão nova
|
issues.new=Questão nova
|
||||||
|
@ -1530,8 +1530,8 @@ issues.new.clear_labels=Retirar rótulos
|
||||||
issues.new.projects=Planeamentos
|
issues.new.projects=Planeamentos
|
||||||
issues.new.clear_projects=Limpar planeamentos
|
issues.new.clear_projects=Limpar planeamentos
|
||||||
issues.new.no_projects=Nenhum planeamento
|
issues.new.no_projects=Nenhum planeamento
|
||||||
issues.new.open_projects=Planeamentos abertos
|
issues.new.open_projects=Projetos abertos
|
||||||
issues.new.closed_projects=Planeamentos fechados
|
issues.new.closed_projects=Projetos fechados
|
||||||
issues.new.no_items=Sem itens
|
issues.new.no_items=Sem itens
|
||||||
issues.new.milestone=Etapa
|
issues.new.milestone=Etapa
|
||||||
issues.new.no_milestone=Sem etapa
|
issues.new.no_milestone=Sem etapa
|
||||||
|
@ -2049,7 +2049,7 @@ ext_wiki=Wiki externo
|
||||||
ext_wiki.desc=Ligação para um wiki externo.
|
ext_wiki.desc=Ligação para um wiki externo.
|
||||||
|
|
||||||
wiki=Wiki
|
wiki=Wiki
|
||||||
wiki.welcome=Bem-vindo(a) ao Wiki.
|
wiki.welcome=Bem-vindo(a) à wiki.
|
||||||
wiki.welcome_desc=O wiki permite escrever e partilhar documentação com os colaboradores.
|
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.desc=Escrever e partilhar documentação com os colaboradores.
|
||||||
wiki.create_first_page=Criar a primeira página
|
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.pulls.default_allow_edits_from_maintainers=Permitir, por norma, que os responsáveis editem
|
||||||
settings.releases_desc=Habilitar lançamentos no repositório
|
settings.releases_desc=Habilitar lançamentos no repositório
|
||||||
settings.packages_desc=Habilitar o registo de pacotes do repositório
|
settings.packages_desc=Habilitar o registo de pacotes do repositório
|
||||||
settings.projects_desc=Habilitar planeamentos no repositório
|
settings.projects_desc=Habilitar projetos no repositório
|
||||||
settings.actions_desc=Habilitar sequências CI/CD integradas com Forgejo Actions
|
settings.actions_desc=Habilitar sequências CI/CD integradas com Forgejo Actions
|
||||||
settings.admin_settings=Configurações do administrador
|
settings.admin_settings=Configurações do administrador
|
||||||
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
|
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_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.
|
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
|
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 = Planeamentos
|
project = Projetos
|
||||||
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
|
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.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.
|
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:
|
vagrant.install=Para adicionar uma máquina virtual Vagrant, execute o seguinte comando:
|
||||||
settings.link=Vincular este pacote a um repositório
|
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.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório.
|
||||||
settings.link.select=Escolha o repositório
|
settings.link.select=Escolher repositório
|
||||||
settings.link.button=Modificar vínculo ao 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.success=O vínculo ao repositório foi modificado com sucesso.
|
||||||
settings.link.error=Falhou a modificação do vínculo ao repositório.
|
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.
|
variables.not_found = Não foi possível encontrar a variável.
|
||||||
|
|
||||||
[projects]
|
[projects]
|
||||||
type-1.display_name=Planeamento individual
|
type-1.display_name=Projeto individual
|
||||||
type-2.display_name=Planeamento do repositório
|
type-2.display_name=Projeto do repositório
|
||||||
type-3.display_name=Planeamento da organização
|
type-3.display_name=Projeto da organização
|
||||||
deleted.display_name = Planeamento eliminado
|
deleted.display_name = Projeto eliminado
|
||||||
|
|
||||||
[git.filemode]
|
[git.filemode]
|
||||||
changed_filemode=%[1]s → %[2]s
|
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.
|
no_results = Não foram encontrados resultados correspondentes.
|
||||||
package_kind = Pesquisar pacotes…
|
package_kind = Pesquisar pacotes…
|
||||||
runner_kind = Pesquisar executores…
|
runner_kind = Pesquisar executores…
|
||||||
project_kind = Pesquisar planeamentos…
|
project_kind = Pesquisar projetos…
|
||||||
branch_kind = Pesquisar ramos…
|
branch_kind = Pesquisar ramos…
|
||||||
commit_kind = Pesquisar cometimentos…
|
commit_kind = Pesquisar cometimentos…
|
||||||
search = Procurar…
|
search = Procurar…
|
||||||
|
@ -4068,8 +4068,8 @@ test = ok :)
|
||||||
[repo.permissions]
|
[repo.permissions]
|
||||||
code.read = <b>Ler:</b> Aceder e clonar o código-fonte do repositório.
|
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.
|
releases.read = <b>Ler:</b> Ver e descarregar lançamentos.
|
||||||
projects.read = <b>Ler:</b> Aceder aos quadros de planeamento do repositório.
|
projects.read = <b>Ler:</b> Aceder aos quadros de projeto do repositório.
|
||||||
projects.write = <b>Escrever:</b> Criar planeamentos e colunas e editá-las.
|
projects.write = <b>Escrever:</b> Criar projetos e colunas e editá-las.
|
||||||
packages.read = <b>Ler:</b> Ver e descarregar pacotes atribuídos ao repositório.
|
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.
|
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.
|
actions.read = <b>Ler:</b> Ver sequências CI/CD integrados e os seus registos.
|
||||||
|
|
|
@ -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=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.
|
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.
|
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ştiriniz
|
openid_signin=OpenID Oturum Açmayı Etkinleştir
|
||||||
openid_signin.description=OpenID ile kullanıcı girişini etkinleştir.
|
openid_signin.description=OpenID ile kullanıcı girişini etkinleştir.
|
||||||
openid_signup=OpenID ile Kendi Kendine Kaydı Etkinleştir
|
openid_signup=OpenID ile Kendi Kendine Kaydı Etkinleştir
|
||||||
openid_signup.description=OpenID Tabanlı Kendi Kendi Kullanıcı Kaydını 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.size=Boyut
|
||||||
packages.published=Yayınlandı
|
packages.published=Yayınlandı
|
||||||
|
|
||||||
defaulthooks=Varsayılan Web İstemcileri
|
defaulthooks=Varsayılan web kancaları
|
||||||
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.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.add_webhook=Varsayılan Web İstemcisi Ekle
|
defaulthooks.add_webhook=Varsayılan Web İstemcisi Ekle
|
||||||
defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle
|
defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle
|
||||||
|
|
||||||
systemhooks=Sistem Web İstemcileri
|
systemhooks=Sistem web kancaları
|
||||||
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.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.add_webhook=Sistem Web İstemcisi Ekle
|
systemhooks.add_webhook=Sistem Web İstemcisi Ekle
|
||||||
systemhooks.update_webhook=Sistem Web İstemcisi Güncelle
|
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_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.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_signup=OpenID Kendinden Kaydı'nı Etkinleştir
|
||||||
config.enable_openid_signin=OpenID Oturum Açmayı Etkinleştiriniz
|
config.enable_openid_signin=OpenID Oturum Açmayı Etkinleştir
|
||||||
config.show_registration_button=Kaydolma Düğmesini Göster
|
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.require_sign_in_view=Sayfaları Görüntülemek için Giriş Yapmaya Zorla
|
||||||
config.mail_notify=E-Posta Bildirimlerini Etkinleştir
|
config.mail_notify=E-Posta Bildirimlerini Etkinleştir
|
||||||
|
|
|
@ -1780,7 +1780,7 @@ milestones.filter_sort.least_issues=Найменш задач
|
||||||
ext_wiki.desc=Посилання на зовнішню вікі.
|
ext_wiki.desc=Посилання на зовнішню вікі.
|
||||||
|
|
||||||
wiki=Вікі
|
wiki=Вікі
|
||||||
wiki.welcome=Ласкаво просимо до Вікі.
|
wiki.welcome=Ласкаво просимо до вікі.
|
||||||
wiki.welcome_desc=Wiki дозволяє писати та ділитися документацією з співавторами.
|
wiki.welcome_desc=Wiki дозволяє писати та ділитися документацією з співавторами.
|
||||||
wiki.desc=Пишіть та обмінюйтеся документацією із співавторами.
|
wiki.desc=Пишіть та обмінюйтеся документацією із співавторами.
|
||||||
wiki.create_first_page=Створити першу сторінку
|
wiki.create_first_page=Створити першу сторінку
|
||||||
|
@ -2663,6 +2663,11 @@ sync_fork.button = Синхронізувати
|
||||||
sync_fork.branch_behind_one = Ця гілка на %[1]d коміт позаду %[2]s
|
sync_fork.branch_behind_one = Ця гілка на %[1]d коміт позаду %[2]s
|
||||||
sync_fork.branch_behind_few = Ця гілка на %[1]d комітів позаду %[2]s
|
sync_fork.branch_behind_few = Ця гілка на %[1]d комітів позаду %[2]s
|
||||||
issues.role.first_time_contributor = Новий учасник
|
issues.role.first_time_contributor = Новий учасник
|
||||||
|
settings.event_action_failure = Помилка
|
||||||
|
settings.event_action_success = Успіх
|
||||||
|
settings.event_action_recover = Відновлено
|
||||||
|
commitstatus.success = Успіх
|
||||||
|
commitstatus.failure = Збій
|
||||||
|
|
||||||
[graphs]
|
[graphs]
|
||||||
contributors.what = внески
|
contributors.what = внески
|
||||||
|
|
|
@ -7,9 +7,9 @@ logo=徽标
|
||||||
sign_in=登录
|
sign_in=登录
|
||||||
sign_in_with_provider=使用 %s 登录
|
sign_in_with_provider=使用 %s 登录
|
||||||
sign_in_or=或
|
sign_in_or=或
|
||||||
sign_out=退出
|
sign_out=登出
|
||||||
sign_up=注册
|
sign_up=注册
|
||||||
link_account=链接账户
|
link_account=链接账号
|
||||||
register=注册
|
register=注册
|
||||||
version=当前版本
|
version=当前版本
|
||||||
powered_by=由 %s 提供支持
|
powered_by=由 %s 提供支持
|
||||||
|
@ -743,7 +743,7 @@ social=社交帐号
|
||||||
applications=应用
|
applications=应用
|
||||||
orgs=组织
|
orgs=组织
|
||||||
repos=仓库列表
|
repos=仓库列表
|
||||||
delete=删除帐户
|
delete=删除账号
|
||||||
twofa=两步验证(TOTP)
|
twofa=两步验证(TOTP)
|
||||||
account_link=已绑定的帐户
|
account_link=已绑定的帐户
|
||||||
organization=组织
|
organization=组织
|
||||||
|
@ -1515,7 +1515,7 @@ projects.card_type.images_and_text=图标和文字
|
||||||
projects.card_type.text_only=仅文本
|
projects.card_type.text_only=仅文本
|
||||||
|
|
||||||
issues.desc=组织 bug 报告、任务和里程碑。
|
issues.desc=组织 bug 报告、任务和里程碑。
|
||||||
issues.filter_assignees=筛选指派人
|
issues.filter_assignees=筛选指派成员
|
||||||
issues.filter_milestones=筛选里程碑
|
issues.filter_milestones=筛选里程碑
|
||||||
issues.filter_projects=筛选项目
|
issues.filter_projects=筛选项目
|
||||||
issues.filter_labels=筛选标签
|
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.comment_manually_pull_merged_at=手动合并提交 %[1]s 到 %[2]s %[3]s
|
||||||
issues.close_comment_issue=评论并关闭
|
issues.close_comment_issue=评论并关闭
|
||||||
issues.reopen_issue=重新开放
|
issues.reopen_issue=重新开放
|
||||||
issues.reopen_comment_issue=重新打开评论
|
issues.reopen_comment_issue=重新打开并评论
|
||||||
issues.create_comment=评论
|
issues.create_comment=评论
|
||||||
issues.closed_at=`于<a id="%[1]s" href="#%[1]s">%[2]s</a>关闭此议题`
|
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>`
|
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_owner=不能将所有者添加为协作者。
|
||||||
settings.add_collaborator_duplicate=合作者已经被添加到本仓库。
|
settings.add_collaborator_duplicate=合作者已经被添加到本仓库。
|
||||||
settings.delete_collaborator=删除
|
settings.delete_collaborator=删除
|
||||||
settings.collaborator_deletion=删除协作者
|
settings.collaborator_deletion=移除协作者
|
||||||
settings.collaborator_deletion_desc=删除协作者后他将无法再对此仓库的访问。继续?
|
settings.collaborator_deletion_desc=删除协作者后他将无法再对此仓库的访问。继续?
|
||||||
settings.remove_collaborator_success=已成功删除协作者。
|
settings.remove_collaborator_success=已成功删除协作者。
|
||||||
settings.search_user_placeholder=搜索用户...
|
settings.search_user_placeholder=搜索用户...
|
||||||
|
|
|
@ -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_commit = 路徑 %[1]s 不存在於提交 %[2]s 中
|
||||||
tree_path_not_found_branch = 路徑 %[1]s 不存在於分支 %[2]s 中
|
tree_path_not_found_branch = 路徑 %[1]s 不存在於分支 %[2]s 中
|
||||||
transfer.no_permission_to_accept = 您沒有權限接受這項轉讓。
|
transfer.no_permission_to_accept = 您沒有權限接受這項轉讓。
|
||||||
archive.title = 這個儲存庫被封存了。您可以檢視其中的檔案或是 Clone 它,但您無法推送提交,提出問題或合併請求。
|
archive.title = 這個儲存庫已被封存。您可以檢視其中的檔案或拓製儲存庫,但您無法提交推送和創建新議題、合併請求或評論。
|
||||||
archive.title_date = 這個儲存庫在 %s 被封存了。您可以檢視其中的檔案或 clone 它,但您無法推送提交,提出問題或合併請求。
|
archive.title_date = 這個儲存庫在 %s 被封存了。您可以檢視其中的檔案或拓製儲存庫,但您無法提交推送和創建新議題、合併請求或評論。
|
||||||
migrate.forgejo.description = 從 codeberg.org 或其他 Forgejo 站點遷移資料。
|
migrate.forgejo.description = 從 codeberg.org 或其他 Forgejo 站點遷移資料。
|
||||||
migrate.cancel_migrating_title = 取消遷移
|
migrate.cancel_migrating_title = 取消遷移
|
||||||
executable_file = 可執行檔
|
executable_file = 可執行檔
|
||||||
|
|
|
@ -98,5 +98,7 @@
|
||||||
"followers.incoming.list.none": "Tohoto uživatele nikdo nesleduje.",
|
"followers.incoming.list.none": "Tohoto uživatele nikdo nesleduje.",
|
||||||
"followers.outgoing.list.none": "%s nikoho nesleduje.",
|
"followers.outgoing.list.none": "%s nikoho nesleduje.",
|
||||||
"stars.list.none": "Tento repozitář si nikdo nepřidal do oblíbených.",
|
"stars.list.none": "Tento repozitář si nikdo nepřidal do oblíbených.",
|
||||||
"followers.outgoing.list.self.none": "Nikoho nesledujete."
|
"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>."
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,5 +84,13 @@
|
||||||
"moderation.report_remarks.placeholder": "Angiv venligst nogle detaljer vedrørende det misbrug, du anmelder.",
|
"moderation.report_remarks.placeholder": "Angiv venligst nogle detaljer vedrørende det misbrug, du anmelder.",
|
||||||
"moderation.submit_report": "Indsend rapport",
|
"moderation.submit_report": "Indsend rapport",
|
||||||
"moderation.reporting_failed": "Den nye misbrugsrapport kunne ikke indsendes: %v",
|
"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."
|
"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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,5 +90,7 @@
|
||||||
"followers.outgoing.list.self.none": "Du folgst niemanden.",
|
"followers.outgoing.list.self.none": "Du folgst niemanden.",
|
||||||
"followers.outgoing.list.none": "%s folgt niemanden.",
|
"followers.outgoing.list.none": "%s folgt niemanden.",
|
||||||
"stars.list.none": "Niemand hat dieses Repo favorisiert.",
|
"stars.list.none": "Niemand hat dieses Repo favorisiert.",
|
||||||
"followers.incoming.list.none": "Niemand folgt diesem Benutzer."
|
"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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,5 +92,6 @@
|
||||||
"discussion.locked": "This discussion has been locked. Commenting is limited to contributors.",
|
"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.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.",
|
"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."
|
"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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,5 +83,14 @@
|
||||||
"moderation.submit_report": "I-submit ang ulat",
|
"moderation.submit_report": "I-submit ang ulat",
|
||||||
"moderation.reporting_failed": "Hindi ma-submit ang bagong ulat sa pang aabuso: %v",
|
"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.",
|
"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."
|
"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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,5 +89,13 @@
|
||||||
"moderation.report_remarks": "Remarques",
|
"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.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.submit_report": "Soumettre le signalement",
|
||||||
"moderation.reporting_failed": "Impossible de soumettre le nouveau signalement : %v"
|
"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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,5 +98,7 @@
|
||||||
"followers.outgoing.list.self.none": "Tu nevienam neseko.",
|
"followers.outgoing.list.self.none": "Tu nevienam neseko.",
|
||||||
"followers.outgoing.list.none": "%s nevienam neseko.",
|
"followers.outgoing.list.none": "%s nevienam neseko.",
|
||||||
"stars.list.none": "Neviens šo glabātavu nav atzīmējis ar zvaigzni.",
|
"stars.list.none": "Neviens šo glabātavu nav atzīmējis ar zvaigzni.",
|
||||||
"followers.incoming.list.self.none": "Neviens neseko Tavam profilam."
|
"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!"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"repo.pulls.merged_title_desc": {
|
"repo.pulls.merged_title_desc": {
|
||||||
"one": "heeft %[1]d commit van <code>%[2]s</code> samengevoegd in <code>%[3]s</code> %[4]s",
|
"one": "heeft %[1]d commit 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"
|
"other": "heeft %[1]d commits van <code>%[2]s</code> samengevoegd in <code>%[3]s</code> %[4]s"
|
||||||
},
|
},
|
||||||
"repo.pulls.title_desc": {
|
"repo.pulls.title_desc": {
|
||||||
"one": "wil %[1]d commit van <code>%[2]s</code> samenvoegen in <code id=\"%[4]s\">%[3]s</code>",
|
"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 met <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>"
|
||||||
},
|
},
|
||||||
"search.milestone_kind": "Zoek mijlpalen…",
|
"search.milestone_kind": "Zoek mijlpalen…",
|
||||||
"home.welcome.no_activity": "Geen activiteit",
|
"home.welcome.no_activity": "Geen activiteit",
|
||||||
|
@ -13,27 +13,27 @@
|
||||||
"home.explore_repos": "Verken repositories",
|
"home.explore_repos": "Verken repositories",
|
||||||
"home.explore_users": "Verken gebruikers",
|
"home.explore_users": "Verken gebruikers",
|
||||||
"home.explore_orgs": "Verken organisaties",
|
"home.explore_orgs": "Verken organisaties",
|
||||||
"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.",
|
"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.",
|
||||||
"themes.names.forgejo-auto": "Forgejo (volg het systeemthema)",
|
"themes.names.forgejo-auto": "Forgejo (volg het systeemthema)",
|
||||||
"themes.names.forgejo-light": "Forgejo licht",
|
"themes.names.forgejo-light": "Forgejo licht",
|
||||||
"themes.names.forgejo-dark": "Forgejo donker",
|
"themes.names.forgejo-dark": "Forgejo donker",
|
||||||
"error.not_found.title": "Pagina niet gevonden",
|
"error.not_found.title": "Pagina niet gevonden",
|
||||||
"alert.asset_load_failed": "Het laden van asset-bestanden van {path} is mislukt. Controleer of de asset-bestanden toegankelijk zijn.",
|
"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 het opgegeven pad: %[1]s",
|
"install.invalid_lfs_path": "Kan de LFS-root niet aanmaken op de opgegeven locatie: %[1]s",
|
||||||
"alert.range_error": " moet een getal zijn tussen %[1]s en %[2]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.",
|
"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 repository %[2]s",
|
"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 repository %[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 repository %[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 repository %[2]s",
|
"mail.actions.not_successful_run": "Werkstroom %[1]s mislukt in repositorie %[2]s",
|
||||||
"mail.actions.run_info_cur_status": "De status van deze run: %[1]s (zojuist bijgewerkt van %[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_previous_status": "Status vorige run: %[1]s",
|
||||||
"mail.actions.run_info_ref": "Branch: %[1]s (%[2]s)",
|
"mail.actions.run_info_ref": "Branch: %[1]s (%[2]s)",
|
||||||
"mail.actions.run_info_trigger": "Getriggerd omdat: %[1]s door: %[2]s",
|
"mail.actions.run_info_trigger": "Getriggerd omdat: %[1]s door: %[2]s",
|
||||||
"discussion.locked": "Deze discussie is gesloten. Commentaar is beperkt tot bijdragers.",
|
"discussion.locked": "Deze discussie is afgesloten. Commentaar is alleen mogelijk voor bijdragers.",
|
||||||
"relativetime.now": "nu",
|
"relativetime.now": "nu",
|
||||||
"relativetime.future": "in de toekomst",
|
"relativetime.future": "in de toekomst",
|
||||||
"repo.form.cannot_create": "Alle spaces waarin u repositories kan maken hebben hun maximum aantal repositories bereikt.",
|
"repo.form.cannot_create": "Alle ruimtes waarin u repositories kan maken hebben hun maximum aantal repositories bereikt.",
|
||||||
"moderation.report_content": "Meldt content",
|
"moderation.report_content": "Meldt content",
|
||||||
"moderation.report_abuse_form.header": "Meld misbruik bij de beheerder",
|
"moderation.report_abuse_form.header": "Meld misbruik bij de beheerder",
|
||||||
"moderation.report_abuse_form.invalid": "Ongeldige argumenten",
|
"moderation.report_abuse_form.invalid": "Ongeldige argumenten",
|
||||||
|
@ -86,5 +86,11 @@
|
||||||
"relativetime.hours": {
|
"relativetime.hours": {
|
||||||
"one": "%d uur geleden",
|
"one": "%d uur geleden",
|
||||||
"other": "%d uren 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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,5 +98,7 @@
|
||||||
"followers.incoming.list.none": "Ninguém está seguindo este perfil.",
|
"followers.incoming.list.none": "Ninguém está seguindo este perfil.",
|
||||||
"followers.outgoing.list.none": "%s não está seguindo ninguém.",
|
"followers.outgoing.list.none": "%s não está seguindo ninguém.",
|
||||||
"stars.list.none": "Ninguém favoritou este repositório.",
|
"stars.list.none": "Ninguém favoritou este repositório.",
|
||||||
"followers.outgoing.list.self.none": "Você não está seguindo ninguém."
|
"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."
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,5 +98,7 @@
|
||||||
"moderation.reported_thank_you": "Спасибо за ваше сообщение. Администрация оповещена.",
|
"moderation.reported_thank_you": "Спасибо за ваше сообщение. Администрация оповещена.",
|
||||||
"moderation.report_abuse_form.details": "Через эту форму можно жаловаться на пользователей, распространяющих спам или ведущих себя неадекватно.",
|
"moderation.report_abuse_form.details": "Через эту форму можно жаловаться на пользователей, распространяющих спам или ведущих себя неадекватно.",
|
||||||
"moderation.report_abuse_form.invalid": "Невалидные аргументы",
|
"moderation.report_abuse_form.invalid": "Невалидные аргументы",
|
||||||
"moderation.report_abuse_form.header": "Жалоба администрации"
|
"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>, чтобы покинуть редактор."
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,5 +66,7 @@
|
||||||
"followers.outgoing.list.self.none": "你没有关注任何人。",
|
"followers.outgoing.list.self.none": "你没有关注任何人。",
|
||||||
"followers.outgoing.list.none": "%s 没有关注任何人。",
|
"followers.outgoing.list.none": "%s 没有关注任何人。",
|
||||||
"stars.list.none": "没有人点赞这个仓库。",
|
"stars.list.none": "没有人点赞这个仓库。",
|
||||||
"followers.incoming.list.self.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> 退出编辑器。"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,71 @@
|
||||||
{
|
{
|
||||||
"repo.pulls.merged_title_desc": "將 %[1]d 次提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code> %[4]s",
|
"repo.pulls.merged_title_desc": "將 %[1]d 次提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code> %[4]s",
|
||||||
"repo.pulls.title_desc": "請求將 %[1]d 次程式碼提交從 <code>%[2]s</code> 合併至 <code id=\"%[4]s\">%[3]s</code>",
|
"repo.pulls.title_desc": "請求將 %[1]d 次程式碼提交從 <code>%[2]s</code> 合併至 <code id=\"%[4]s\">%[3]s</code>",
|
||||||
"search.milestone_kind": "搜尋里程碑…"
|
"search.milestone_kind": "搜尋里程碑…",
|
||||||
|
"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": "您已檢舉此內容"
|
||||||
}
|
}
|
||||||
|
|
1724
package-lock.json
generated
1724
package-lock.json
generated
File diff suppressed because it is too large
Load diff
39
package.json
39
package.json
|
@ -36,7 +36,7 @@
|
||||||
"monaco-editor": "0.52.2",
|
"monaco-editor": "0.52.2",
|
||||||
"monaco-editor-webpack-plugin": "7.1.0",
|
"monaco-editor-webpack-plugin": "7.1.0",
|
||||||
"pdfobject": "2.3.0",
|
"pdfobject": "2.3.0",
|
||||||
"postcss": "8.5.2",
|
"postcss": "8.5.4",
|
||||||
"postcss-loader": "8.1.1",
|
"postcss-loader": "8.1.1",
|
||||||
"postcss-nesting": "13.0.1",
|
"postcss-nesting": "13.0.1",
|
||||||
"pretty-ms": "9.0.0",
|
"pretty-ms": "9.0.0",
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
"tributejs": "5.1.3",
|
"tributejs": "5.1.3",
|
||||||
"uint8-to-base64": "0.2.0",
|
"uint8-to-base64": "0.2.0",
|
||||||
"vanilla-colorful": "0.7.2",
|
"vanilla-colorful": "0.7.2",
|
||||||
"vue": "3.5.14",
|
"vue": "3.5.16",
|
||||||
"vue-chartjs": "5.3.1",
|
"vue-chartjs": "5.3.1",
|
||||||
"vue-loader": "17.4.2",
|
"vue-loader": "17.4.2",
|
||||||
"vue3-calendar-heatmap": "2.0.5",
|
"vue3-calendar-heatmap": "2.0.5",
|
||||||
|
@ -59,47 +59,46 @@
|
||||||
"wrap-ansi": "9.0.0"
|
"wrap-ansi": "9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@axe-core/playwright": "4.10.1",
|
"@axe-core/playwright": "4.10.2",
|
||||||
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
|
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
|
||||||
"@playwright/test": "1.52.0",
|
"@playwright/test": "1.52.0",
|
||||||
"@stoplight/spectral-cli": "6.15.0",
|
"@stoplight/spectral-cli": "6.15.0",
|
||||||
"@stylistic/eslint-plugin-js": "4.2.0",
|
"@stylistic/eslint-plugin-js": "4.4.1",
|
||||||
"@stylistic/stylelint-plugin": "3.1.2",
|
"@stylistic/stylelint-plugin": "3.1.2",
|
||||||
"@typescript-eslint/parser": "8.31.1",
|
"@vitejs/plugin-vue": "5.2.4",
|
||||||
"@vitejs/plugin-vue": "5.2.3",
|
"@vitest/coverage-v8": "3.2.3",
|
||||||
"@vitest/coverage-v8": "3.1.2",
|
"@vitest/eslint-plugin": "1.2.1",
|
||||||
"@vitest/eslint-plugin": "1.1.43",
|
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"eslint": "9.25.1",
|
"eslint": "9.28.0",
|
||||||
"eslint-import-resolver-typescript": "4.3.4",
|
"eslint-import-resolver-typescript": "4.4.3",
|
||||||
"eslint-plugin-array-func": "5.0.2",
|
"eslint-plugin-array-func": "5.0.2",
|
||||||
"eslint-plugin-import-x": "4.11.0",
|
"eslint-plugin-import-x": "4.15.1",
|
||||||
"eslint-plugin-no-jquery": "3.1.1",
|
"eslint-plugin-no-jquery": "3.1.1",
|
||||||
"eslint-plugin-no-use-extend-native": "0.7.2",
|
"eslint-plugin-no-use-extend-native": "0.7.2",
|
||||||
"eslint-plugin-playwright": "2.2.0",
|
"eslint-plugin-playwright": "2.2.0",
|
||||||
"eslint-plugin-regexp": "2.7.0",
|
"eslint-plugin-regexp": "2.9.0",
|
||||||
"eslint-plugin-sonarjs": "3.0.2",
|
"eslint-plugin-sonarjs": "3.0.2",
|
||||||
"eslint-plugin-unicorn": "59.0.0",
|
"eslint-plugin-unicorn": "59.0.1",
|
||||||
"eslint-plugin-toml": "0.12.0",
|
"eslint-plugin-toml": "0.12.0",
|
||||||
"eslint-plugin-vitest-globals": "1.5.0",
|
"eslint-plugin-vitest-globals": "1.5.0",
|
||||||
"eslint-plugin-vue": "10.1.0",
|
"eslint-plugin-vue": "10.2.0",
|
||||||
"eslint-plugin-vue-scoped-css": "2.9.0",
|
"eslint-plugin-vue-scoped-css": "2.10.0",
|
||||||
"eslint-plugin-wc": "2.2.1",
|
"eslint-plugin-wc": "2.2.1",
|
||||||
"globals": "16.1.0",
|
"globals": "16.1.0",
|
||||||
"happy-dom": "17.4.6",
|
"happy-dom": "17.6.3",
|
||||||
"license-checker-rseidelsohn": "4.4.2",
|
"license-checker-rseidelsohn": "4.4.2",
|
||||||
"markdownlint-cli": "0.44.0",
|
"markdownlint-cli": "0.45.0",
|
||||||
"postcss-html": "1.8.0",
|
"postcss-html": "1.8.0",
|
||||||
"sharp": "0.34.2",
|
"sharp": "0.34.2",
|
||||||
"stylelint": "16.19.1",
|
"stylelint": "16.20.0",
|
||||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||||
"stylelint-declaration-strict-value": "1.10.11",
|
"stylelint-declaration-strict-value": "1.10.11",
|
||||||
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||||
"svgo": "3.2.0",
|
"svgo": "3.2.0",
|
||||||
"typescript": "5.8.3",
|
"typescript": "5.8.3",
|
||||||
"typescript-eslint": "8.31.1",
|
"typescript-eslint": "8.33.1",
|
||||||
"vite-string-plugin": "1.3.4",
|
"vite-string-plugin": "1.3.4",
|
||||||
"vitest": "3.1.2"
|
"vitest": "3.2.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"defaults"
|
"defaults"
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue