diff --git a/cmd/web_acme.go b/cmd/web_acme.go
index 03b3b9f0da..be6314addb 100644
--- a/cmd/web_acme.go
+++ b/cmd/web_acme.go
@@ -15,6 +15,7 @@ import (
"forgejo.org/modules/graceful"
"forgejo.org/modules/log"
"forgejo.org/modules/process"
+ "forgejo.org/modules/proxy"
"forgejo.org/modules/setting"
"github.com/caddyserver/certmagic"
@@ -76,6 +77,12 @@ func runACME(listenAddr string, m http.Handler) error {
ListenHost: setting.HTTPAddr,
AltTLSALPNPort: altTLSALPNPort,
AltHTTPPort: altHTTPPort,
+ HTTPProxy: proxy.Proxy(),
+ }
+
+ // Preserve behavior to use Let's encrypt test CA when Let's encrypt is CA.
+ if certmagic.DefaultACME.CA == certmagic.LetsEncryptProductionCA {
+ certmagic.DefaultACME.TestCA = certmagic.LetsEncryptStagingCA
}
magic := certmagic.NewDefault()
diff --git a/models/actions/run.go b/models/actions/run.go
index 55def805ed..69592120e9 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -284,16 +284,10 @@ func GetLatestRun(ctx context.Context, repoID int64) (*ActionRun, error) {
return &run, nil
}
-// GetRunBefore returns the last run that completed a given timestamp (not inclusive).
-func GetRunBefore(ctx context.Context, repoID int64, timestamp timeutil.TimeStamp) (*ActionRun, error) {
- var run ActionRun
- has, err := db.GetEngine(ctx).Where("repo_id=? AND stopped IS NOT NULL AND stopped", repoID, timestamp).OrderBy("stopped DESC").Limit(1).Get(&run)
- if err != nil {
- return nil, err
- } else if !has {
- return nil, fmt.Errorf("run before: %w", util.ErrNotExist)
- }
- return &run, nil
+func GetRunBefore(ctx context.Context, _ *ActionRun) (*ActionRun, error) {
+ // TODO return the most recent run related to the run given in argument
+ // see https://codeberg.org/forgejo/user-research/issues/63 for context
+ return nil, nil
}
func GetLatestRunForBranchAndWorkflow(ctx context.Context, repoID int64, branch, workflowFile, event string) (*ActionRun, error) {
diff --git a/models/actions/run_test.go b/models/actions/run_test.go
index 11b03022ff..c9a552a2b2 100644
--- a/models/actions/run_test.go
+++ b/models/actions/run_test.go
@@ -5,92 +5,7 @@ package actions
import (
"testing"
- "time"
-
- "forgejo.org/models/db"
- "forgejo.org/models/unittest"
- "forgejo.org/modules/timeutil"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
)
func TestGetRunBefore(t *testing.T) {
- require.NoError(t, unittest.PrepareTestDatabase())
-
- // this repo is part of the test database requiring loading "repository.yml" in main_test.go
- var repoID int64 = 1
-
- workflowID := "test_workflow"
-
- // third completed run
- time1, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00")
- require.NoError(t, err)
- timeutil.MockSet(time1)
- run1 := ActionRun{
- ID: 1,
- Index: 1,
- RepoID: repoID,
- Stopped: timeutil.TimeStampNow(),
- WorkflowID: workflowID,
- }
-
- // fourth completed run
- time2, err := time.Parse(time.RFC3339, "2024-08-31T15:47:55+08:00")
- require.NoError(t, err)
- timeutil.MockSet(time2)
- run2 := ActionRun{
- ID: 2,
- Index: 2,
- RepoID: repoID,
- Stopped: timeutil.TimeStampNow(),
- WorkflowID: workflowID,
- }
-
- // second completed run
- time3, err := time.Parse(time.RFC3339, "2024-07-31T15:47:54+08:00")
- require.NoError(t, err)
- timeutil.MockSet(time3)
- run3 := ActionRun{
- ID: 3,
- Index: 3,
- RepoID: repoID,
- Stopped: timeutil.TimeStampNow(),
- WorkflowID: workflowID,
- }
-
- // first completed run
- time4, err := time.Parse(time.RFC3339, "2024-06-30T15:47:54+08:00")
- require.NoError(t, err)
- timeutil.MockSet(time4)
- run4 := ActionRun{
- ID: 4,
- Index: 4,
- RepoID: repoID,
- Stopped: timeutil.TimeStampNow(),
- WorkflowID: workflowID,
- }
- require.NoError(t, db.Insert(db.DefaultContext, &run1))
- runBefore, err := GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
- // there is no run before run1
- require.Error(t, err)
- require.Nil(t, runBefore)
-
- // now there is only run3 before run1
- require.NoError(t, db.Insert(db.DefaultContext, &run3))
- runBefore, err = GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
- require.NoError(t, err)
- assert.Equal(t, run3.ID, runBefore.ID)
-
- // there still is only run3 before run1
- require.NoError(t, db.Insert(db.DefaultContext, &run2))
- runBefore, err = GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
- require.NoError(t, err)
- assert.Equal(t, run3.ID, runBefore.ID)
-
- // run4 is further away from run1
- require.NoError(t, db.Insert(db.DefaultContext, &run4))
- runBefore, err = GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
- require.NoError(t, err)
- assert.Equal(t, run3.ID, runBefore.ID)
}
diff --git a/models/activities/action.go b/models/activities/action.go
index 8592f81414..f928ad6784 100644
--- a/models/activities/action.go
+++ b/models/activities/action.go
@@ -473,8 +473,11 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err
return nil, 0, err
}
+ sess := db.GetEngine(ctx).Where(cond).
+ Select("`action`.*"). // this line will avoid select other joined table's columns
+ Join("INNER", "repository", "`repository`.id = `action`.repo_id")
+
opts.SetDefaultValues()
- sess := db.GetEngine(ctx).Where(cond)
sess = db.SetSessionPagination(sess, &opts)
actions := make([]*Action, 0, opts.PageSize)
diff --git a/models/activities/action_test.go b/models/activities/action_test.go
index 47dbd8ac2d..161d05bbfa 100644
--- a/models/activities/action_test.go
+++ b/models/activities/action_test.go
@@ -227,6 +227,24 @@ func TestNotifyWatchers(t *testing.T) {
})
}
+func TestGetFeedsCorrupted(t *testing.T) {
+ require.NoError(t, unittest.PrepareTestDatabase())
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
+ unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
+ ID: 8,
+ RepoID: 1700,
+ })
+
+ actions, count, err := activities_model.GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{
+ RequestedUser: user,
+ Actor: user,
+ IncludePrivate: true,
+ })
+ require.NoError(t, err)
+ assert.Empty(t, actions)
+ assert.Equal(t, int64(0), count)
+}
+
func TestConsistencyUpdateAction(t *testing.T) {
if !setting.Database.Type.IsSQLite3() {
t.Skip("Test is only for SQLite database.")
diff --git a/models/db/context.go b/models/db/context.go
index 35526936af..3e035cd733 100644
--- a/models/db/context.go
+++ b/models/db/context.go
@@ -141,7 +141,7 @@ func TxContext(parentCtx context.Context) (*Context, Committer, error) {
return nil, nil, err
}
- return newContext(DefaultContext, sess, true), sess, nil
+ return newContext(parentCtx, sess, true), sess, nil
}
// WithTx represents executing database operations on a transaction, if the transaction exist,
diff --git a/models/db/context_test.go b/models/db/context_test.go
index 7ab327b7e9..d12d79ebe1 100644
--- a/models/db/context_test.go
+++ b/models/db/context_test.go
@@ -84,4 +84,16 @@ func TestTxContext(t *testing.T) {
return nil
}))
}
+
+ t.Run("Reuses parent context", func(t *testing.T) {
+ type unique struct{}
+
+ ctx := context.WithValue(db.DefaultContext, unique{}, "yes!")
+ assert.False(t, db.InTransaction(ctx))
+
+ require.NoError(t, db.WithTx(ctx, func(ctx context.Context) error {
+ assert.Equal(t, "yes!", ctx.Value(unique{}))
+ return nil
+ }))
+ })
}
diff --git a/models/fixtures/ModerationFeatures/abuse_report.yml b/models/fixtures/ModerationFeatures/abuse_report.yml
new file mode 100644
index 0000000000..f2e371ee35
--- /dev/null
+++ b/models/fixtures/ModerationFeatures/abuse_report.yml
@@ -0,0 +1,21 @@
+-
+ id: 1
+ status: 1
+ reporter_id: 2 # @user2
+ content_type: 4 # Comment
+ content_id: 18 # user2/repo2/issues/2#issuecomment-18
+ category: 2 # Spam
+ remarks: The comment I'm reporting is pure SPAM.
+ shadow_copy_id: null
+ created_unix: 1752697980 # 2025-07-16 20:33:00
+
+-
+ id: 2
+ status: 1 # Open
+ reporter_id: 2 # @user2
+ content_type: 1 # User (users or organizations)
+ content_id: 1002 # @alexsmith
+ category: 2 # Spam
+ remarks: This user just posted a spammy comment on my issue.
+ shadow_copy_id: null
+ created_unix: 1752698010 # 2025-07-16 20:33:30
diff --git a/models/fixtures/ModerationFeatures/comment.yml b/models/fixtures/ModerationFeatures/comment.yml
new file mode 100644
index 0000000000..a4d41ad997
--- /dev/null
+++ b/models/fixtures/ModerationFeatures/comment.yml
@@ -0,0 +1,7 @@
+- # This is a spam comment (abusive content), created for testing moderation functionalities.
+ id: 18
+ type: 0 # Standard comment
+ poster_id: 1002 # @alexsmith
+ issue_id: 7 # user2/repo2#2
+ content: If anyone needs help for promoting their business online using SEO, just contact me (check my profile page).
+ created_unix: 1752697860 # 2025-07-16 20:31:00
diff --git a/models/fixtures/ModerationFeatures/user.yml b/models/fixtures/ModerationFeatures/user.yml
new file mode 100644
index 0000000000..662c61a3e9
--- /dev/null
+++ b/models/fixtures/ModerationFeatures/user.yml
@@ -0,0 +1,22 @@
+- # This user is a spammer and will create abusive content (for testing moderation functionalities).
+ id: 1002
+ lower_name: alexsmith
+ name: alexsmith
+ full_name: Alex Smith
+ email: alexsmith@example.org
+ keep_email_private: false
+ passwd: passwdSalt:password
+ passwd_hash_algo: dummy
+ type: 0
+ location: '@master@seo.net'
+ website: http://promote-your-business.biz
+ pronouns: SEO
+ salt: passwdSalt
+ description: I can help you promote your business online using SEO.
+ created_unix: 1752697800 # 2025-07-16 20:30:00
+ is_active: true
+ is_admin: false
+ is_restricted: false
+ avatar: avatar-hash-1002
+ avatar_email: alexsmith@example.org
+ use_custom_avatar: false
diff --git a/models/fixtures/TestActivateUserEmail/email_address.yml b/models/fixtures/TestActivateUserEmail/email_address.yml
new file mode 100644
index 0000000000..cf41ff8241
--- /dev/null
+++ b/models/fixtures/TestActivateUserEmail/email_address.yml
@@ -0,0 +1,7 @@
+-
+ id: 1001
+ uid: 1001
+ email: AnotherTestUserWithUpperCaseEmail@otto.splvs.net
+ lower_email: anothertestuserwithuppercaseemail@otto.splvs.net
+ is_activated: false
+ is_primary: true
diff --git a/models/fixtures/TestActivateUserEmail/user.yml b/models/fixtures/TestActivateUserEmail/user.yml
new file mode 100644
index 0000000000..0a68e70a4a
--- /dev/null
+++ b/models/fixtures/TestActivateUserEmail/user.yml
@@ -0,0 +1,12 @@
+-
+ id: 1001
+ lower_name: user1001
+ name: user1001
+ full_name: User That loves Upper Cases
+ email: AnotherTestUserWithUpperCaseEmail@otto.splvs.net
+ passwd: ZogKvWdyEx:password
+ passwd_hash_algo: dummy
+ avatar: ''
+ avatar_email: anothertestuserwithuppercaseemail@otto.splvs.net
+ login_name: user1
+ created_unix: 1672578000
diff --git a/models/fixtures/TestAddTeamReviewRequest/issue.yml b/models/fixtures/TestAddTeamReviewRequest/issue.yml
new file mode 100644
index 0000000000..a1bcf2921f
--- /dev/null
+++ b/models/fixtures/TestAddTeamReviewRequest/issue.yml
@@ -0,0 +1,16 @@
+-
+ id: 23
+ repo_id: 2
+ index: 3
+ poster_id: 2
+ original_author_id: 0
+ name: protected branch pull
+ content: pull request to a protected branch
+ milestone_id: 0
+ priority: 0
+ is_pull: true
+ is_closed: false
+ num_comments: 0
+ created_unix: 1707270422
+ updated_unix: 1707270422
+ is_locked: false
\ No newline at end of file
diff --git a/models/fixtures/TestAddTeamReviewRequest/protected_branch.yml b/models/fixtures/TestAddTeamReviewRequest/protected_branch.yml
new file mode 100644
index 0000000000..93909bd991
--- /dev/null
+++ b/models/fixtures/TestAddTeamReviewRequest/protected_branch.yml
@@ -0,0 +1,28 @@
+- id: 1
+ repo_id: 2
+ branch_name: protected-main
+ can_push: false
+ enable_whitelist: true
+ whitelist_user_i_ds: [1]
+ whitelist_team_i_ds: []
+ enable_merge_whitelist: true
+ whitelist_deploy_keys: false
+ merge_whitelist_user_i_ds: [1]
+ merge_whitelist_team_i_ds: []
+ enable_status_check: false
+ status_check_contexts: []
+ enable_approvals_whitelist: true
+ approvals_whitelist_user_i_ds: []
+ approvals_whitelist_team_i_ds: [1]
+ required_approvals: 1
+ block_on_rejected_reviews: true
+ block_on_official_review_requests: true
+ block_on_outdated_branch: true
+ dismiss_stale_approvals: true
+ ignore_stale_approvals: false
+ require_signed_commits: false
+ protected_file_patterns: ""
+ unprotected_file_patterns: ""
+ apply_to_admins: true
+ created_unix: 1752513073
+ updated_unix: 1752513073
\ No newline at end of file
diff --git a/models/fixtures/TestAddTeamReviewRequest/pull_request.yml b/models/fixtures/TestAddTeamReviewRequest/pull_request.yml
new file mode 100644
index 0000000000..067bb01324
--- /dev/null
+++ b/models/fixtures/TestAddTeamReviewRequest/pull_request.yml
@@ -0,0 +1,12 @@
+-
+ id: 11
+ type: 0 # gitea pull request
+ status: 2 # mergeable
+ issue_id: 23
+ index: 3
+ head_repo_id: 2
+ base_repo_id: 2
+ head_branch: feature/protected-branch-pr
+ base_branch: protected-main
+ merge_base: 4a357436d925b5c974181ff12a994538ddc5a269
+ has_merged: false
\ No newline at end of file
diff --git a/models/fixtures/action.yml b/models/fixtures/action.yml
index a97e94fbf4..f1592d4569 100644
--- a/models/fixtures/action.yml
+++ b/models/fixtures/action.yml
@@ -59,6 +59,14 @@
created_unix: 1603011540 # grouped with id:7
- id: 8
+ user_id: 1
+ op_type: 12 # close issue
+ act_user_id: 1
+ repo_id: 1700 # dangling intentional
+ is_private: false
+ created_unix: 1603011541
+
+- id: 9
user_id: 34
op_type: 12 # close issue
act_user_id: 34
diff --git a/models/fixtures/comment.yml b/models/fixtures/comment.yml
index 34407d6f81..6908d85dda 100644
--- a/models/fixtures/comment.yml
+++ b/models/fixtures/comment.yml
@@ -186,10 +186,46 @@
type: 8 # milestone
poster_id: 1
issue_id: 1 # in repo_id 1
- milestone_id: 10 # not exsting milestone
+ milestone_id: 10 # not existing milestone
old_milestone_id: 0
created_unix: 946685080
+-
+ id: 2004
+ type: 8 # milestone
+ poster_id: 1
+ issue_id: 1 # in repo_id 1
+ milestone_id: 1
+ old_milestone_id: 10 # not existing (ghost) milestone
+ created_unix: 946685085
+
+-
+ id: 2005
+ type: 8 # milestone
+ poster_id: 1
+ issue_id: 1 # in repo_id 1
+ milestone_id: 10 # not existing (ghost) milestone
+ old_milestone_id: 1
+ created_unix: 946685090
+
+-
+ id: 2006
+ type: 8 # milestone
+ poster_id: 1
+ issue_id: 1 # in repo_id 1
+ milestone_id: 11 # not existing (ghost) milestone
+ old_milestone_id: 10 # not existing (ghost) milestone
+ created_unix: 946685095
+
+-
+ id: 2007
+ type: 8 # milestone
+ poster_id: 1
+ issue_id: 1 # in repo_id 1
+ milestone_id: 0
+ old_milestone_id: 11 # not existing (ghost) milestone
+ created_unix: 946685100
+
-
id: 2010
type: 30 # project
diff --git a/models/forgejo_migrations/migrate.go b/models/forgejo_migrations/migrate.go
index 737350b019..94469b7371 100644
--- a/models/forgejo_migrations/migrate.go
+++ b/models/forgejo_migrations/migrate.go
@@ -108,7 +108,9 @@ var migrations = []*Migration{
// v33 -> v34
NewMigration("Add `notify-email` column to `action_run` table", AddNotifyEmailToActionRun),
// v34 -> v35
- NewMigration("Add index to `stopped` column in `action_run` table", AddIndexToActionRunStopped),
+ NewMigration("Noop because of https://codeberg.org/forgejo/forgejo/issues/8373", NoopAddIndexToActionRunStopped),
+ // v35 -> v36
+ NewMigration("Fix wiki unit default permission", FixWikiUnitDefaultPermission),
}
// GetCurrentDBVersion returns the current Forgejo database version.
diff --git a/models/forgejo_migrations/v32.go b/models/forgejo_migrations/v32.go
index bed335ab6b..2460003597 100644
--- a/models/forgejo_migrations/v32.go
+++ b/models/forgejo_migrations/v32.go
@@ -12,6 +12,7 @@ import (
"strconv"
"strings"
+ "forgejo.org/models/db"
"forgejo.org/models/packages"
"forgejo.org/modules/json"
"forgejo.org/modules/log"
@@ -52,55 +53,50 @@ type mavenPackageResult struct {
// ChangeMavenArtifactConcatenation resolves old dash-concatenated Maven coordinates and regenerates metadata.
// Note: runs per-owner in a single transaction; failures roll back all owners.
func ChangeMavenArtifactConcatenation(x *xorm.Engine) error {
- sess := x.NewSession()
- defer sess.Close()
-
- if err := sess.Begin(); err != nil {
- return err
- }
-
- // get unique owner IDs of Maven packages
- var ownerIDs []*int64
- if err := sess.
- Table("package").
- Select("package.owner_id").
- Where("package.type = 'maven'").
- GroupBy("package.owner_id").
- OrderBy("package.owner_id DESC").
- Find(&ownerIDs); err != nil {
- return err
- }
-
- for _, id := range ownerIDs {
- if err := fixMavenArtifactPerOwner(sess, id); err != nil {
- log.Error("owner %d migration failed: %v", id, err)
- return err // rollback all
+ return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
+ // get unique owner IDs of Maven packages
+ var ownerIDs []*int64
+ if err := db.GetEngine(ctx).
+ Table("package").
+ Select("package.owner_id").
+ Where("package.type = 'maven'").
+ GroupBy("package.owner_id").
+ OrderBy("package.owner_id DESC").
+ Find(&ownerIDs); err != nil {
+ return err
}
- }
- return sess.Commit()
+ for _, id := range ownerIDs {
+ if err := fixMavenArtifactPerOwner(ctx, id); err != nil {
+ log.Error("owner %d migration failed: %v", id, err)
+ return err // rollback all
+ }
+ }
+
+ return nil
+ })
}
-func fixMavenArtifactPerOwner(sess *xorm.Session, ownerID *int64) error {
- results, err := getMavenPackageResultsToUpdate(sess, ownerID)
+func fixMavenArtifactPerOwner(ctx context.Context, ownerID *int64) error {
+ results, err := getMavenPackageResultsToUpdate(ctx, ownerID)
if err != nil {
return err
}
- if err = resolvePackageCollisions(results, sess); err != nil {
+ if err = resolvePackageCollisions(ctx, results); err != nil {
return err
}
- if err = processPackageVersions(results, sess); err != nil {
+ if err = processPackageVersions(ctx, results); err != nil {
return err
}
- return processPackageFiles(results, sess)
+ return processPackageFiles(ctx, results)
}
// processPackageFiles updates Maven package files and versions in the database
// Returns an error if any database or processing operation fails.
-func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) error {
+func processPackageFiles(ctx context.Context, results []*mavenPackageResult) error {
processedVersion := make(map[string][]*mavenPackageResult)
for _, r := range results {
@@ -113,7 +109,7 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
if r.PackageVersion.ID != r.PackageFile.VersionID {
pattern := strings.TrimSuffix(r.PackageFile.Name, ".pom") + "%"
// Per routers/api/packages/maven/maven.go:338, POM files already have the `IsLead`, so no update needed for this prop
- if _, err := sess.Exec("UPDATE package_file SET version_id = ? WHERE version_id = ? and name like ?", r.PackageVersion.ID, r.PackageFile.VersionID, pattern); err != nil {
+ if _, err := db.GetEngine(ctx).Exec("UPDATE package_file SET version_id = ? WHERE version_id = ? and name like ?", r.PackageVersion.ID, r.PackageFile.VersionID, pattern); err != nil {
return err
}
}
@@ -128,14 +124,14 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
rs := packageResults[0]
- pf, md, err := parseMetadata(sess, rs)
+ pf, md, err := parseMetadata(ctx, rs)
if err != nil {
return err
}
if pf != nil && md != nil && md.GroupID == rs.GroupID && md.ArtifactID == rs.ArtifactID {
if pf.VersionID != rs.PackageFile.VersionID {
- if _, err := sess.ID(pf.ID).Cols("version_id").Update(pf); err != nil {
+ if _, err := db.GetEngine(ctx).ID(pf.ID).Cols("version_id").Update(pf); err != nil {
return err
}
}
@@ -150,11 +146,9 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
// parseMetadata retrieves metadata for a Maven package file from the database and decodes it into a Metadata object.
// Returns the associated PackageFile, Metadata, and any error encountered during processing.
-func parseMetadata(sess *xorm.Session, snapshot *mavenPackageResult) (*packages.PackageFile, *Metadata, error) {
- ctx := context.Background()
-
+func parseMetadata(ctx context.Context, snapshot *mavenPackageResult) (*packages.PackageFile, *Metadata, error) {
var pf packages.PackageFile
- found, err := sess.Table(pf).
+ found, err := db.GetEngine(ctx).Table(pf).
Where("version_id = ?", snapshot.PackageFile.VersionID). // still the old id
And("lower_name = ?", "maven-metadata.xml").
Get(&pf)
@@ -183,7 +177,7 @@ func parseMetadata(sess *xorm.Session, snapshot *mavenPackageResult) (*packages.
// processPackageVersions processes Maven package versions by updating metadata or inserting new records as necessary.
// It avoids redundant updates by tracking already processed versions using a map. Returns an error on failure.
-func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) error {
+func processPackageVersions(ctx context.Context, results []*mavenPackageResult) error {
processedVersion := make(map[string]int64)
for _, r := range results {
@@ -196,14 +190,14 @@ func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) e
// for non collisions, just update the metadata
if r.PackageVersion.PackageID == r.Package.ID {
- if _, err := sess.ID(r.PackageVersion.ID).Cols("metadata_json").Update(r.PackageVersion); err != nil {
+ if _, err := db.GetEngine(ctx).ID(r.PackageVersion.ID).Cols("metadata_json").Update(r.PackageVersion); err != nil {
return err
}
} else {
log.Info("Create new maven package version for %s:%s", r.PackageName, r.PackageVersion.Version)
r.PackageVersion.ID = 0
r.PackageVersion.PackageID = r.Package.ID
- if _, err := sess.Insert(r.PackageVersion); err != nil {
+ if _, err := db.GetEngine(ctx).Insert(r.PackageVersion); err != nil {
return err
}
}
@@ -216,10 +210,9 @@ func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) e
// getMavenPackageResultsToUpdate retrieves Maven package results that need updates based on the owner ID.
// It processes POM metadata, fixes package inconsistencies, and filters corrupted package versions.
-func getMavenPackageResultsToUpdate(sess *xorm.Session, ownerID *int64) ([]*mavenPackageResult, error) {
- ctx := context.Background()
+func getMavenPackageResultsToUpdate(ctx context.Context, ownerID *int64) ([]*mavenPackageResult, error) {
var candidates []*mavenPackageResult
- if err := sess.
+ if err := db.GetEngine(ctx).
Table("package_file").
Select("package_file.*, package_version.*, package.*").
Join("INNER", "package_version", "package_version.id = package_file.version_id").
@@ -265,7 +258,7 @@ func getMavenPackageResultsToUpdate(sess *xorm.Session, ownerID *int64) ([]*mave
// resolvePackageCollisions handles name collisions by keeping the first existing record and inserting new Package records for subsequent collisions.
// Returns a map from PackageName to its resolved Package.ID.
-func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session) error {
+func resolvePackageCollisions(ctx context.Context, results []*mavenPackageResult) error {
// Group new names by lowerName
collisions := make(map[string][]string)
for _, r := range results {
@@ -292,7 +285,7 @@ func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session)
} else if list[0] == r.PackageName {
pkgIDByName[r.PackageName] = r.Package.ID
- if _, err = sess.ID(r.Package.ID).Cols("name", "lower_name").Update(r.Package); err != nil {
+ if _, err = db.GetEngine(ctx).ID(r.Package.ID).Cols("name", "lower_name").Update(r.Package); err != nil {
return err
}
// create a new entry
@@ -300,7 +293,7 @@ func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session)
log.Info("Create new maven package for %s", r.Package.Name)
r.Package.ID = 0
- if _, err = sess.Insert(r.Package); err != nil {
+ if _, err = db.GetEngine(ctx).Insert(r.Package); err != nil {
return err
}
diff --git a/models/forgejo_migrations/v35.go b/models/forgejo_migrations/v35.go
index 0fb3b43e2c..ca412d7951 100644
--- a/models/forgejo_migrations/v35.go
+++ b/models/forgejo_migrations/v35.go
@@ -4,16 +4,10 @@
package forgejo_migrations //nolint:revive
import (
- "forgejo.org/modules/timeutil"
-
"xorm.io/xorm"
)
-func AddIndexToActionRunStopped(x *xorm.Engine) error {
- type ActionRun struct {
- ID int64
- Stopped timeutil.TimeStamp `xorm:"index"`
- }
-
- return x.Sync(&ActionRun{})
+// see https://codeberg.org/forgejo/forgejo/issues/8373
+func NoopAddIndexToActionRunStopped(x *xorm.Engine) error {
+ return nil
}
diff --git a/models/forgejo_migrations/v36.go b/models/forgejo_migrations/v36.go
new file mode 100644
index 0000000000..019c177a08
--- /dev/null
+++ b/models/forgejo_migrations/v36.go
@@ -0,0 +1,55 @@
+// Copyright 2025 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package forgejo_migrations //nolint:revive
+
+import (
+ "xorm.io/xorm"
+)
+
+func FixWikiUnitDefaultPermission(x *xorm.Engine) error {
+ // Type is Unit's Type
+ type Type int
+
+ // Enumerate all the unit types
+ const (
+ TypeInvalid Type = iota // 0 invalid
+ TypeCode // 1 code
+ TypeIssues // 2 issues
+ TypePullRequests // 3 PRs
+ TypeReleases // 4 Releases
+ TypeWiki // 5 Wiki
+ TypeExternalWiki // 6 ExternalWiki
+ TypeExternalTracker // 7 ExternalTracker
+ TypeProjects // 8 Projects
+ TypePackages // 9 Packages
+ TypeActions // 10 Actions
+ )
+
+ // RepoUnitAccessMode specifies the users access mode to a repo unit
+ type UnitAccessMode int
+
+ const (
+ // UnitAccessModeUnset - no unit mode set
+ UnitAccessModeUnset UnitAccessMode = iota // 0
+ // UnitAccessModeNone no access
+ UnitAccessModeNone // 1
+ // UnitAccessModeRead read access
+ UnitAccessModeRead // 2
+ // UnitAccessModeWrite write access
+ UnitAccessModeWrite // 3
+ )
+ _ = UnitAccessModeNone
+ _ = UnitAccessModeWrite
+
+ type RepoUnit struct {
+ DefaultPermissions UnitAccessMode `xorm:"NOT NULL DEFAULT 0"`
+ }
+ _, err := x.Where("type = ?", TypeWiki).
+ Where("default_permissions = ?", UnitAccessModeRead).
+ Cols("default_permissions").
+ Update(RepoUnit{
+ DefaultPermissions: UnitAccessModeUnset,
+ })
+ return err
+}
diff --git a/models/issues/comment.go b/models/issues/comment.go
index a81221caf4..523a6ba9b9 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -1156,7 +1156,7 @@ func UpdateComment(ctx context.Context, c *Comment, contentVersion int, doer *us
defer committer.Close()
// If the comment was reported as abusive, a shadow copy should be created before first update.
- if err := IfNeededCreateShadowCopyForComment(ctx, c); err != nil {
+ if err := IfNeededCreateShadowCopyForComment(ctx, c, true); err != nil {
return err
}
@@ -1197,7 +1197,7 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
e := db.GetEngine(ctx)
// If the comment was reported as abusive, a shadow copy should be created before deletion.
- if err := IfNeededCreateShadowCopyForComment(ctx, comment); err != nil {
+ if err := IfNeededCreateShadowCopyForComment(ctx, comment, false); err != nil {
return err
}
diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go
index 7285e347b4..9b502d1c91 100644
--- a/models/issues/comment_list.go
+++ b/models/issues/comment_list.go
@@ -101,7 +101,7 @@ func (comments CommentList) loadMilestones(ctx context.Context) error {
return nil
}
- milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
+ milestones := make(map[int64]*Milestone, len(milestoneIDs))
left := len(milestoneIDs)
for left > 0 {
limit := db.DefaultMaxInSize
@@ -110,7 +110,7 @@ func (comments CommentList) loadMilestones(ctx context.Context) error {
}
err := db.GetEngine(ctx).
In("id", milestoneIDs[:limit]).
- Find(&milestoneMaps)
+ Find(&milestones)
if err != nil {
return err
}
@@ -118,8 +118,8 @@ func (comments CommentList) loadMilestones(ctx context.Context) error {
milestoneIDs = milestoneIDs[limit:]
}
- for _, issue := range comments {
- issue.Milestone = milestoneMaps[issue.MilestoneID]
+ for _, comment := range comments {
+ comment.Milestone = milestones[comment.MilestoneID]
}
return nil
}
@@ -140,7 +140,7 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error {
return nil
}
- milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
+ milestones := make(map[int64]*Milestone, len(milestoneIDs))
left := len(milestoneIDs)
for left > 0 {
limit := db.DefaultMaxInSize
@@ -149,7 +149,7 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error {
}
err := db.GetEngine(ctx).
In("id", milestoneIDs[:limit]).
- Find(&milestoneMaps)
+ Find(&milestones)
if err != nil {
return err
}
@@ -157,8 +157,8 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error {
milestoneIDs = milestoneIDs[limit:]
}
- for _, issue := range comments {
- issue.OldMilestone = milestoneMaps[issue.MilestoneID]
+ for _, comment := range comments {
+ comment.OldMilestone = milestones[comment.OldMilestoneID]
}
return nil
}
diff --git a/models/issues/moderation.go b/models/issues/moderation.go
index 635d295db0..921f770d4d 100644
--- a/models/issues/moderation.go
+++ b/models/issues/moderation.go
@@ -87,13 +87,19 @@ func IfNeededCreateShadowCopyForIssue(ctx context.Context, issue *Issue) error {
// IfNeededCreateShadowCopyForComment checks if for the given comment there are any reports of abusive content submitted
// and if found a shadow copy of relevant comment fields will be stored into DB and linked to the above report(s).
// This function should be called before a comment is deleted or updated.
-func IfNeededCreateShadowCopyForComment(ctx context.Context, comment *Comment) error {
+func IfNeededCreateShadowCopyForComment(ctx context.Context, comment *Comment, forUpdates bool) error {
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeComment, comment.ID)
if err != nil {
return err
}
if shadowCopyNeeded {
+ if forUpdates {
+ // get the unaltered comment fields (for updates the provided variable is already altered but not yet saved)
+ if comment, err = GetCommentByID(ctx, comment.ID); err != nil {
+ return err
+ }
+ }
commentData := newCommentData(comment)
content, err := json.Marshal(commentData)
if err != nil {
diff --git a/models/issues/review.go b/models/issues/review.go
index 584704d3e8..5370117a81 100644
--- a/models/issues/review.go
+++ b/models/issues/review.go
@@ -781,10 +781,6 @@ func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organizat
official, err := IsOfficialReviewerTeam(ctx, issue, reviewer)
if err != nil {
return nil, fmt.Errorf("isOfficialReviewerTeam(): %w", err)
- } else if !official {
- if official, err = IsOfficialReviewer(ctx, issue, doer); err != nil {
- return nil, fmt.Errorf("isOfficialReviewer(): %w", err)
- }
}
if review, err = CreateReview(ctx, CreateReviewOptions{
@@ -797,12 +793,6 @@ func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organizat
return nil, err
}
- if official {
- if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_team_id=?", false, issue.ID, reviewer.ID); err != nil {
- return nil, err
- }
- }
-
comment, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeReviewRequest,
Doer: doer,
diff --git a/models/issues/review_test.go b/models/issues/review_test.go
index 33d131c225..6e2f6ddfa8 100644
--- a/models/issues/review_test.go
+++ b/models/issues/review_test.go
@@ -8,6 +8,7 @@ import (
"forgejo.org/models/db"
issues_model "forgejo.org/models/issues"
+ organization_model "forgejo.org/models/organization"
repo_model "forgejo.org/models/repo"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
@@ -319,3 +320,80 @@ func TestAddReviewRequest(t *testing.T) {
require.Error(t, err)
assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err))
}
+
+func TestAddTeamReviewRequest(t *testing.T) {
+ defer unittest.OverrideFixtures("models/fixtures/TestAddTeamReviewRequest")()
+ require.NoError(t, unittest.PrepareTestDatabase())
+
+ setupForProtectedBranch := func() (*issues_model.Issue, *user_model.User) {
+ // From override models/fixtures/TestAddTeamReviewRequest/issue.yml; issue #23 is a PR into a protected branch
+ issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 23})
+ require.NoError(t, issue.LoadRepo(db.DefaultContext))
+ doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
+ return issue, doer
+ }
+
+ t.Run("Protected branch, not official team", func(t *testing.T) {
+ issue, doer := setupForProtectedBranch()
+ // Team 2 is not part of the whitelist for this protected branch
+ team := unittest.AssertExistsAndLoadBean(t, &organization_model.Team{ID: 2})
+
+ comment, err := issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer)
+ require.NoError(t, err)
+ require.NotNil(t, comment)
+
+ review, err := issues_model.GetTeamReviewerByIssueIDAndTeamID(db.DefaultContext, issue.ID, team.ID)
+ require.NoError(t, err)
+ require.NotNil(t, review)
+ assert.Equal(t, issues_model.ReviewTypeRequest, review.Type)
+ assert.Equal(t, team.ID, review.ReviewerTeamID)
+ // This review request should not be marked official because it is not a request for a team in the branch
+ // protection rule's whitelist...
+ assert.False(t, review.Official)
+ })
+
+ t.Run("Protected branch, official team", func(t *testing.T) {
+ issue, doer := setupForProtectedBranch()
+ // Team 1 is part of the whitelist for this protected branch
+ team := unittest.AssertExistsAndLoadBean(t, &organization_model.Team{ID: 1})
+
+ comment, err := issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer)
+ require.NoError(t, err)
+ require.NotNil(t, comment)
+
+ review, err := issues_model.GetTeamReviewerByIssueIDAndTeamID(db.DefaultContext, issue.ID, team.ID)
+ require.NoError(t, err)
+ require.NotNil(t, review)
+ assert.Equal(t, issues_model.ReviewTypeRequest, review.Type)
+ assert.Equal(t, team.ID, review.ReviewerTeamID)
+ // Expected to be considered official because team 1 is in the review whitelist for this protected branch
+ assert.True(t, review.Official)
+ })
+
+ t.Run("Unprotected branch, official team", func(t *testing.T) {
+ // Working on a PR into a branch that is not protected, issue #2
+ issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
+ require.NoError(t, issue.LoadRepo(db.DefaultContext))
+ doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
+ // team is a team that has write perms against the repo
+ team := unittest.AssertExistsAndLoadBean(t, &organization_model.Team{ID: 1})
+
+ comment, err := issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer)
+ require.NoError(t, err)
+ require.NotNil(t, comment)
+
+ review, err := issues_model.GetTeamReviewerByIssueIDAndTeamID(db.DefaultContext, issue.ID, team.ID)
+ require.NoError(t, err)
+ require.NotNil(t, review)
+ assert.Equal(t, issues_model.ReviewTypeRequest, review.Type)
+ assert.Equal(t, team.ID, review.ReviewerTeamID)
+ // Will not be marked as official because PR #2 there's no branch protection rule that enables whitelist
+ // approvals (verifying logic in `IsOfficialReviewerTeam` indirectly)
+ assert.False(t, review.Official)
+
+ // Adding the same team review request again should be a noop
+ comment, err = issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer)
+ require.NoError(t, err)
+ require.Nil(t, comment)
+ })
+}
diff --git a/models/moderation/abuse_report.go b/models/moderation/abuse_report.go
index dadd61a95e..3a6244ef4c 100644
--- a/models/moderation/abuse_report.go
+++ b/models/moderation/abuse_report.go
@@ -100,7 +100,7 @@ type AbuseReport struct {
// The abuse category selected by the reporter.
Category AbuseCategoryType `xorm:"INDEX NOT NULL"`
// Remarks provided by the reporter.
- Remarks string
+ Remarks string `xorm:"VARCHAR(500)"`
// The ID of the corresponding shadow-copied content when exists; otherwise null.
ShadowCopyID sql.NullInt64 `xorm:"DEFAULT NULL"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
diff --git a/models/moderation/shadow_copy.go b/models/moderation/shadow_copy.go
index cdd8f69c52..d363610a48 100644
--- a/models/moderation/shadow_copy.go
+++ b/models/moderation/shadow_copy.go
@@ -17,7 +17,7 @@ import (
type AbuseReportShadowCopy struct {
ID int64 `xorm:"pk autoincr"`
- RawValue string `xorm:"NOT NULL"`
+ RawValue string `xorm:"LONGTEXT NOT NULL"` // A JSON with relevant fields from user, repository, issue or comment table.
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
}
diff --git a/models/packages/package.go b/models/packages/package.go
index bdd1c74cad..c06dcf5eb3 100644
--- a/models/packages/package.go
+++ b/models/packages/package.go
@@ -125,7 +125,7 @@ func (pt Type) Name() string {
case TypeRpm:
return "RPM"
case TypeAlt:
- return "Alt"
+ return "ALT"
case TypeRubyGems:
return "RubyGems"
case TypeSwift:
diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go
index c11ad70627..e50f79e945 100644
--- a/models/repo/repo_unit.go
+++ b/models/repo/repo_unit.go
@@ -41,27 +41,30 @@ func (err ErrUnitTypeNotExist) Unwrap() error {
}
// RepoUnitAccessMode specifies the users access mode to a repo unit
+// Only UnitAccessModeWrite is used by the wiki, to mark it as instance-writable
type UnitAccessMode int
const (
// UnitAccessModeUnset - no unit mode set
UnitAccessModeUnset UnitAccessMode = iota // 0
+
// UnitAccessModeNone no access
- UnitAccessModeNone // 1
+ // UnitAccessModeNone UnitAccessMode = 1
// UnitAccessModeRead read access
- UnitAccessModeRead // 2
+ // UnitAccessModeRead UnitAccessMode = 2
+
// UnitAccessModeWrite write access
- UnitAccessModeWrite // 3
+ UnitAccessModeWrite UnitAccessMode = 3
)
func (mode UnitAccessMode) ToAccessMode(modeIfUnset perm.AccessMode) perm.AccessMode {
switch mode {
case UnitAccessModeUnset:
return modeIfUnset
- case UnitAccessModeNone:
- return perm.AccessModeNone
- case UnitAccessModeRead:
- return perm.AccessModeRead
+ // case UnitAccessModeNone:
+ // return perm.AccessModeNone
+ // case UnitAccessModeRead:
+ // return perm.AccessModeRead
case UnitAccessModeWrite:
return perm.AccessModeWrite
default:
diff --git a/models/repo/repo_unit_test.go b/models/repo/repo_unit_test.go
index a1964519bd..3d6d408fcb 100644
--- a/models/repo/repo_unit_test.go
+++ b/models/repo/repo_unit_test.go
@@ -34,8 +34,8 @@ func TestActionsConfig(t *testing.T) {
}
func TestRepoUnitAccessMode(t *testing.T) {
- assert.Equal(t, perm.AccessModeNone, UnitAccessModeNone.ToAccessMode(perm.AccessModeAdmin))
- assert.Equal(t, perm.AccessModeRead, UnitAccessModeRead.ToAccessMode(perm.AccessModeAdmin))
+ // assert.Equal(t, perm.AccessModeNone, UnitAccessModeNone.ToAccessMode(perm.AccessModeAdmin))
+ // assert.Equal(t, perm.AccessModeRead, UnitAccessModeRead.ToAccessMode(perm.AccessModeAdmin))
assert.Equal(t, perm.AccessModeWrite, UnitAccessModeWrite.ToAccessMode(perm.AccessModeAdmin))
assert.Equal(t, perm.AccessModeRead, UnitAccessModeUnset.ToAccessMode(perm.AccessModeRead))
}
diff --git a/models/user/email_address_test.go b/models/user/email_address_test.go
index 1801f57a23..85f5b16c65 100644
--- a/models/user/email_address_test.go
+++ b/models/user/email_address_test.go
@@ -181,3 +181,20 @@ func TestDeletePrimaryEmailAddressOfUser(t *testing.T) {
assert.True(t, user_model.IsErrEmailAddressNotExist(err))
assert.Nil(t, email)
}
+
+func TestActivateUserEmail(t *testing.T) {
+ defer unittest.OverrideFixtures("models/fixtures/TestActivateUserEmail")()
+ require.NoError(t, unittest.PrepareTestDatabase())
+
+ t.Run("Activate email", func(t *testing.T) {
+ require.NoError(t, user_model.ActivateUserEmail(t.Context(), 1001, "AnotherTestUserWithUpperCaseEmail@otto.splvs.net", true))
+
+ unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{UID: 1001}, "is_activated = true")
+ })
+
+ t.Run("Deactivate email", func(t *testing.T) {
+ require.NoError(t, user_model.ActivateUserEmail(t.Context(), 1001, "AnotherTestUserWithUpperCaseEmail@otto.splvs.net", false))
+
+ unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{UID: 1001}, "is_activated = false")
+ })
+}
diff --git a/models/user/moderation.go b/models/user/moderation.go
index afda497f02..f9c16a17b3 100644
--- a/models/user/moderation.go
+++ b/models/user/moderation.go
@@ -73,16 +73,20 @@ var userDataColumnNames = sync.OnceValue(func() []string {
// and if found a shadow copy of relevant user fields will be stored into DB and linked to the above report(s).
// This function should be called before a user is deleted or updated.
//
+// In case the User object was already altered before calling this method, just provide the userID and
+// nil for unalteredUser; when it is decided that a shadow copy should be created and unalteredUser is nil,
+// the user will be retrieved from DB based on the provided userID.
+//
// For deletions alteredCols argument must be omitted.
//
// In case of updates it will first checks whether any of the columns being updated (alteredCols argument)
// is relevant for moderation purposes (i.e. included in the UserData struct).
-func IfNeededCreateShadowCopyForUser(ctx context.Context, user *User, alteredCols ...string) error {
+func IfNeededCreateShadowCopyForUser(ctx context.Context, userID int64, unalteredUser *User, alteredCols ...string) error {
// TODO: this can be triggered quite often (e.g. by routers/web/repo/middlewares.go SetDiffViewStyle())
shouldCheckIfNeeded := len(alteredCols) == 0 // no columns being updated, therefore a deletion
if !shouldCheckIfNeeded {
- // for updates we need to go further only if certain column are being changed
+ // for updates we need to go further only if certain columns are being changed
for _, colName := range userDataColumnNames() {
if shouldCheckIfNeeded = slices.Contains(alteredCols, colName); shouldCheckIfNeeded {
break
@@ -94,18 +98,23 @@ func IfNeededCreateShadowCopyForUser(ctx context.Context, user *User, alteredCol
return nil
}
- shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeUser, user.ID)
+ shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeUser, userID)
if err != nil {
return err
}
if shadowCopyNeeded {
- userData := newUserData(user)
+ if unalteredUser == nil {
+ if unalteredUser, err = GetUserByID(ctx, userID); err != nil {
+ return err
+ }
+ }
+ userData := newUserData(unalteredUser)
content, err := json.Marshal(userData)
if err != nil {
return err
}
- return moderation.CreateShadowCopyForUser(ctx, user.ID, string(content))
+ return moderation.CreateShadowCopyForUser(ctx, userID, string(content))
}
return nil
diff --git a/models/user/user.go b/models/user/user.go
index eedd1db80e..6b54776adf 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -182,11 +182,11 @@ func (u *User) BeforeUpdate() {
u.MaxRepoCreation = -1
}
- // Organization does not need email
- u.Email = strings.ToLower(u.Email)
+ // Ensure AvatarEmail is set for non-organization users, because organization
+ // are not required to have a email set.
if !u.IsOrganization() {
if len(u.AvatarEmail) == 0 {
- u.AvatarEmail = u.Email
+ u.AvatarEmail = strings.ToLower(u.Email)
}
}
@@ -927,7 +927,9 @@ func UpdateUserCols(ctx context.Context, u *User, cols ...string) error {
// If the user was reported as abusive and any of the columns being updated is relevant
// for moderation purposes a shadow copy should be created before first update.
- if err := IfNeededCreateShadowCopyForUser(ctx, u, cols...); err != nil {
+ // Since u is already altered at this point we are sending nil instead as an argument
+ // so that the unaltered version will be retrieved from DB.
+ if err := IfNeededCreateShadowCopyForUser(ctx, u.ID, nil, cols...); err != nil {
return err
}
diff --git a/modules/assetfs/layered.go b/modules/assetfs/layered.go
index 48c6728f43..2041f28bb1 100644
--- a/modules/assetfs/layered.go
+++ b/modules/assetfs/layered.go
@@ -56,14 +56,7 @@ func Local(name, base string, sub ...string) *Layer {
panic(fmt.Sprintf("Unable to get absolute path for %q: %v", base, err))
}
root := util.FilePathJoinAbs(base, sub...)
- fsRoot, err := os.OpenRoot(root)
- if err != nil {
- if errors.Is(err, fs.ErrNotExist) {
- return nil
- }
- panic(fmt.Sprintf("Unable to open layer %q", err))
- }
- return &Layer{name: name, fs: fsRoot.FS(), localPath: root}
+ return &Layer{name: name, fs: os.DirFS(root), localPath: root}
}
// Bindata returns a new Layer with the given name, it serves files from the given bindata asset.
@@ -80,7 +73,7 @@ type LayeredFS struct {
// Layered returns a new LayeredFS with the given layers. The first layer is the top layer.
func Layered(layers ...*Layer) *LayeredFS {
- return &LayeredFS{layers: slices.DeleteFunc(layers, func(layer *Layer) bool { return layer == nil })}
+ return &LayeredFS{layers: layers}
}
// Open opens the named file. The caller is responsible for closing the file.
diff --git a/modules/assetfs/layered_test.go b/modules/assetfs/layered_test.go
index 87d1f92b00..76eeb61d83 100644
--- a/modules/assetfs/layered_test.go
+++ b/modules/assetfs/layered_test.go
@@ -1,4 +1,5 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
+// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package assetfs
@@ -108,3 +109,30 @@ func TestLayered(t *testing.T) {
assert.Equal(t, "l1", assets.GetFileLayerName("f1"))
assert.Equal(t, "l2", assets.GetFileLayerName("f2"))
}
+
+// Allow layers to read symlink outside the layer root.
+func TestLayeredSymlink(t *testing.T) {
+ dir := t.TempDir()
+ dirl1 := filepath.Join(dir, "l1")
+ require.NoError(t, os.MkdirAll(dirl1, 0o755))
+
+ // Open layer in dir/l1
+ layer := Local("l1", dirl1)
+
+ // Create a file in dir/outside
+ fileContents := []byte("I am outside the layer")
+ require.NoError(t, os.WriteFile(filepath.Join(dir, "outside"), fileContents, 0o600))
+ // Symlink dir/l1/outside to dir/outside
+ require.NoError(t, os.Symlink(filepath.Join(dir, "outside"), filepath.Join(dirl1, "outside")))
+
+ // Open dir/l1/outside.
+ f, err := layer.Open("outside")
+ require.NoError(t, err)
+ defer f.Close()
+
+ // Confirm it contains the output of dir/outside
+ contents, err := io.ReadAll(f)
+ require.NoError(t, err)
+
+ assert.Equal(t, fileContents, contents)
+}
diff --git a/modules/indexer/code/search.go b/modules/indexer/code/search.go
index adf51a76d7..499b9117c4 100644
--- a/modules/indexer/code/search.go
+++ b/modules/indexer/code/search.go
@@ -97,7 +97,7 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges
conv := hcd.ConvertToPlaceholders(string(hl))
convLines := strings.Split(conv, "\n")
- // each highlightRange is of the form [line number, start pos, end pos]
+ // each highlightRange is of the form [line number, start byte offset, end byte offset]
for _, highlightRange := range highlightRanges {
ln, start, end := highlightRange[0], highlightRange[1], highlightRange[2]
line := convLines[ln]
@@ -105,15 +105,18 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges
continue
}
+ sr := strings.NewReader(line)
sb := strings.Builder{}
count := -1
isOpen := false
- for _, r := range line {
+ for r, size, err := sr.ReadRune(); err == nil; r, size, err = sr.ReadRune() {
if token, ok := hcd.PlaceholderTokenMap[r];
// token was not found
- !ok ||
- // token was marked as used
- token == "" ||
+ !ok {
+ count += size
+ } else if
+ // token was marked as used
+ token == "" ||
// the token is not an valid html tag emitted by chroma
!(len(token) > 6 && (token[0:5] == "= end:
// if tag is not open, no need to close
if !isOpen {
break
}
sb.WriteRune(endTag)
isOpen = false
- case start:
+ case count >= start:
// if tag is open, do not open again
if isOpen {
break
@@ -161,7 +164,7 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges
highlightedLines := strings.Split(hcd.Recover(conv), "\n")
// The lineNums outputted by highlight.Code might not match the original lineNums, because "highlight" removes the last `\n`
lines := make([]ResultLine, min(len(highlightedLines), len(lineNums)))
- for i := 0; i < len(lines); i++ {
+ for i := range len(lines) {
lines[i].Num = lineNums[i]
lines[i].FormattedContent = template.HTML(highlightedLines[i])
}
diff --git a/modules/indexer/code/search_test.go b/modules/indexer/code/search_test.go
new file mode 100644
index 0000000000..e542b38c24
--- /dev/null
+++ b/modules/indexer/code/search_test.go
@@ -0,0 +1,122 @@
+// Copyright 2025 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package code
+
+import (
+ "html/template"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestHighlightSearchResultCode(t *testing.T) {
+ opts := []struct {
+ Title string
+ File string
+ Lines []int
+ Range [][3]int
+ Code string
+ Result []template.HTML
+ }{
+ {
+ Title: "One Match Text",
+ File: "test.txt",
+ Range: [][3]int{{1, 5, 9}},
+ Code: "First Line\nMark this only\nThe End",
+ Result: []template.HTML{
+ "First Line",
+ "Mark this only",
+ "The End",
+ },
+ },
+ {
+ Title: "Two Match Text",
+ File: "test.txt",
+ Range: [][3]int{
+ {1, 5, 9},
+ {2, 5, 9},
+ },
+ Code: "First Line\nMark this only\nMark this too\nThe End",
+ Result: []template.HTML{
+ "First Line",
+ "Mark this only",
+ "Mark this too",
+ "The End",
+ },
+ },
+ {
+ Title: "Unicode Before",
+ File: "test.txt",
+ Range: [][3]int{{1, 10, 14}},
+ Code: "First Line\nMark 👉 this only\nThe End",
+ Result: []template.HTML{
+ "First Line",
+ "Mark 👉 this only",
+ "The End",
+ },
+ },
+ {
+ Title: "Unicode Between",
+ File: "test.txt",
+ Range: [][3]int{{1, 5, 14}},
+ Code: "First Line\nMark this 😊 only\nThe End",
+ Result: []template.HTML{
+ "First Line",
+ "Mark this 😊 only",
+ "The End",
+ },
+ },
+ {
+ Title: "Unicode Before And Between",
+ File: "test.txt",
+ Range: [][3]int{{1, 10, 19}},
+ Code: "First Line\nMark 👉 this 😊 only\nThe End",
+ Result: []template.HTML{
+ "First Line",
+ "Mark 👉 this 😊 only",
+ "The End",
+ },
+ },
+ {
+ Title: "Golang",
+ File: "test.go",
+ Range: [][3]int{{1, 14, 23}},
+ Code: "func main() {\n\tfmt.Println(\"mark this\")\n}",
+ Result: []template.HTML{
+ "func main() {",
+ "\tfmt.Println("mark this")",
+ "}",
+ },
+ },
+ {
+ Title: "Golang Unicode",
+ File: "test.go",
+ Range: [][3]int{{1, 14, 28}},
+ Code: "func main() {\n\tfmt.Println(\"mark this 😊\")\n}",
+ Result: []template.HTML{
+ "func main() {",
+ "\tfmt.Println("mark this 😊")",
+ "}",
+ },
+ },
+ }
+ for _, o := range opts {
+ t.Run(o.Title, func(t *testing.T) {
+ lines := []int{}
+ for i := range strings.Count(strings.TrimSuffix(o.Code, "\n"), "\n") + 1 {
+ lines = append(lines, i+1)
+ }
+ res := HighlightSearchResultCode(o.File, lines, o.Range, o.Code)
+ assert.Len(t, res, len(o.Result))
+ assert.Len(t, res, len(lines))
+
+ for i, r := range res {
+ require.Equal(t, lines[i], r.Num)
+ require.Equal(t, o.Result[i], r.FormattedContent)
+ }
+ })
+ }
+}
diff --git a/modules/indexer/issues/bleve/bleve.go b/modules/indexer/issues/bleve/bleve.go
index 573d63a446..80af7bac45 100644
--- a/modules/indexer/issues/bleve/bleve.go
+++ b/modules/indexer/issues/bleve/bleve.go
@@ -156,11 +156,12 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (*internal.SearchResult, error) {
var queries []query.Query
- if options.Keyword != "" {
- tokens, err := options.Tokens()
- if err != nil {
- return nil, err
- }
+ tokens, err := options.Tokens()
+ if err != nil {
+ return nil, err
+ }
+
+ if len(tokens) > 0 {
q := bleve.NewBooleanQuery()
for _, token := range tokens {
innerQ := bleve.NewDisjunctionQuery(
diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go
index 9d2786e101..0c4e5fae02 100644
--- a/modules/indexer/issues/elasticsearch/elasticsearch.go
+++ b/modules/indexer/issues/elasticsearch/elasticsearch.go
@@ -149,12 +149,13 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (*internal.SearchResult, error) {
query := elastic.NewBoolQuery()
- if options.Keyword != "" {
+ tokens, err := options.Tokens()
+ if err != nil {
+ return nil, err
+ }
+
+ if len(tokens) > 0 {
q := elastic.NewBoolQuery()
- tokens, err := options.Tokens()
- if err != nil {
- return nil, err
- }
for _, token := range tokens {
innerQ := elastic.NewMultiMatchQuery(token.Term, "content", "comments").FieldWithBoost("title", 2.0).TieBreaker(0.5)
if token.Fuzzy {
diff --git a/modules/indexer/issues/internal/qstring.go b/modules/indexer/issues/internal/qstring.go
index 6b60b4c5f6..348f7a564b 100644
--- a/modules/indexer/issues/internal/qstring.go
+++ b/modules/indexer/issues/internal/qstring.go
@@ -45,12 +45,9 @@ func (t *Tokenizer) next() (tk Token, err error) {
// skip all leading white space
for {
- if r, _, err = t.in.ReadRune(); err == nil && r == ' ' {
- //nolint:staticcheck,wastedassign // SA4006 the variable is used after the loop
- r, _, err = t.in.ReadRune()
- continue
+ if r, _, err = t.in.ReadRune(); err != nil || r != ' ' {
+ break
}
- break
}
if err != nil {
return tk, err
@@ -107,11 +104,17 @@ nextEnd:
// Tokenize the keyword
func (o *SearchOptions) Tokens() (tokens []Token, err error) {
+ if o.Keyword == "" {
+ return nil, nil
+ }
+
in := strings.NewReader(o.Keyword)
it := Tokenizer{in: in}
for token, err := it.next(); err == nil; token, err = it.next() {
- tokens = append(tokens, token)
+ if token.Term != "" {
+ tokens = append(tokens, token)
+ }
}
if err != nil && err != io.EOF {
return nil, err
diff --git a/modules/indexer/issues/internal/qstring_test.go b/modules/indexer/issues/internal/qstring_test.go
index 835491707c..eb4bdb306f 100644
--- a/modules/indexer/issues/internal/qstring_test.go
+++ b/modules/indexer/issues/internal/qstring_test.go
@@ -41,6 +41,36 @@ var testOpts = []testIssueQueryStringOpt{
},
},
},
+ {
+ Keyword: "Hello World",
+ Results: []Token{
+ {
+ Term: "Hello",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ {
+ Term: "World",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ },
+ },
+ {
+ Keyword: " Hello World ",
+ Results: []Token{
+ {
+ Term: "Hello",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ {
+ Term: "World",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ },
+ },
{
Keyword: "+Hello +World",
Results: []Token{
@@ -156,6 +186,68 @@ var testOpts = []testIssueQueryStringOpt{
},
},
},
+ {
+ Keyword: "\\",
+ Results: nil,
+ },
+ {
+ Keyword: "\"",
+ Results: nil,
+ },
+ {
+ Keyword: "Hello \\",
+ Results: []Token{
+ {
+ Term: "Hello",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ },
+ },
+ {
+ Keyword: "\"\"",
+ Results: nil,
+ },
+ {
+ Keyword: "\" World \"",
+ Results: []Token{
+ {
+ Term: " World ",
+ Fuzzy: false,
+ Kind: BoolOptShould,
+ },
+ },
+ },
+ {
+ Keyword: "\"\" World \"\"",
+ Results: []Token{
+ {
+ Term: "World",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ },
+ },
+ {
+ Keyword: "Best \"Hello World\" Ever",
+ Results: []Token{
+ {
+ Term: "Best",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ {
+ Term: "Hello World",
+ Fuzzy: false,
+ Kind: BoolOptShould,
+ },
+ {
+ Term: "Ever",
+ Fuzzy: true,
+ Kind: BoolOptShould,
+ },
+ },
+ },
}
func TestIssueQueryString(t *testing.T) {
diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go
index ef75955a14..e7723ea69d 100644
--- a/modules/indexer/issues/internal/tests/tests.go
+++ b/modules/indexer/issues/internal/tests/tests.go
@@ -87,14 +87,44 @@ func TestIndexer(t *testing.T, indexer internal.Indexer) {
}
}
+func allResults(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
+ assert.Len(t, result.Hits, len(data))
+ assert.Equal(t, len(data), int(result.Total))
+}
+
var cases = []*testIndexerCase{
{
Name: "default",
SearchOptions: &internal.SearchOptions{},
- Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Len(t, result.Hits, len(data))
- assert.Equal(t, len(data), int(result.Total))
+ Expected: allResults,
+ },
+ {
+ Name: "empty keyword",
+ SearchOptions: &internal.SearchOptions{
+ Keyword: "",
},
+ Expected: allResults,
+ },
+ {
+ Name: "whitespace keyword",
+ SearchOptions: &internal.SearchOptions{
+ Keyword: " ",
+ },
+ Expected: allResults,
+ },
+ {
+ Name: "dangling slash in keyword",
+ SearchOptions: &internal.SearchOptions{
+ Keyword: "\\",
+ },
+ Expected: allResults,
+ },
+ {
+ Name: "dangling quote in keyword",
+ SearchOptions: &internal.SearchOptions{
+ Keyword: "\"",
+ },
+ Expected: allResults,
},
{
Name: "empty",
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index e229ee4c65..f7955115e0 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -104,7 +104,7 @@ func TestRender_Images(t *testing.T) {
test(
"",
- ``)
+ ``)
test(
"[["+title+"|"+url+"]]",
@@ -115,7 +115,7 @@ func TestRender_Images(t *testing.T) {
test(
"",
- ``)
+ ``)
test(
"[["+title+"|"+url+"]]",
@@ -412,8 +412,8 @@ func TestRenderSiblingImages_Issue12925(t *testing.T) {
testcase := `

`
- expected := `
+ expected := `
`
res, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase)
require.NoError(t, err)
@@ -845,10 +845,10 @@ mail@domain.com
remote link
local link
remote link
-
-
-
-
+
+
+
+
https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -872,10 +872,10 @@ space
88fc37a3c0...12fc37a3c0 (hash)
diff --git a/modules/util/string.go b/modules/util/string.go
index cf50f591c6..ca3d43ec6e 100644
--- a/modules/util/string.go
+++ b/modules/util/string.go
@@ -95,3 +95,25 @@ func UnsafeBytesToString(b []byte) string {
func UnsafeStringToBytes(s string) []byte {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
+
+// AsciiEqualFold is taken from Golang, but reimplemented here, since the original is not exposed to public
+// Taken from: https://cs.opensource.google/go/go/+/refs/tags/go1.24.4:src/net/http/internal/ascii/print.go
+func ASCIIEqualFold(s, t string) bool {
+ if len(s) != len(t) {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ if ASCIILower(s[i]) != ASCIILower(t[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// AsciiLower returns the ASCII lowercase version of b.
+func ASCIILower(b byte) byte {
+ if 'A' <= b && b <= 'Z' {
+ return b + ('a' - 'A')
+ }
+ return b
+}
diff --git a/modules/util/string_test.go b/modules/util/string_test.go
index 0a4a8bbcfb..1012ab32a4 100644
--- a/modules/util/string_test.go
+++ b/modules/util/string_test.go
@@ -45,3 +45,29 @@ func TestToSnakeCase(t *testing.T) {
assert.Equal(t, expected, ToSnakeCase(input))
}
}
+
+func TestASCIIEqualFold(t *testing.T) {
+ cases := map[string]struct {
+ First string
+ Second string
+ Expected bool
+ }{
+ "Empty String": {First: "", Second: "", Expected: true},
+ "Single Letter Ident": {First: "h", Second: "h", Expected: true},
+ "Single Letter Equal": {First: "h", Second: "H", Expected: true},
+ "Single Letter Unequal": {First: "h", Second: "g", Expected: false},
+ "Simple Match Ident": {First: "someString", Second: "someString", Expected: true},
+ "Simple Match Equal": {First: "someString", Second: "someSTRIng", Expected: true},
+ "Simple Match Unequal": {First: "someString", Second: "sameString", Expected: false},
+ "Different Length": {First: "abcdef", Second: "abcdefg", Expected: false},
+ "Unicode Kelvin": {First: "ghijklm", Second: "GHIJ\u212ALM", Expected: false},
+ }
+
+ for name := range cases {
+ c := cases[name]
+ t.Run(name, func(t *testing.T) {
+ Actual := ASCIIEqualFold(c.First, c.Second)
+ assert.Equal(t, c.Expected, Actual)
+ })
+ }
+}
diff --git a/options/locale/locale_ar.ini b/options/locale/locale_ar.ini
index f4ac1a0e3d..ca74a477ce 100644
--- a/options/locale/locale_ar.ini
+++ b/options/locale/locale_ar.ini
@@ -50,7 +50,7 @@ concept_user_organization = المنظمة
link_account = ربط الحساب
rerun_all = أعِد تشغيل جميع الوظائف
your_profile = الملف الشخصي
-sign_out = سجل الخروج
+sign_out = سجّل الخروج
settings = الإعدادات
locked = مقفول
error = خطأ
@@ -87,7 +87,7 @@ add_all = أضف الكل
new_fork = اشتقاق جديد لمستودع
new_project_column = عمود جديد
add = أضف
-active_stopwatch = تتبع وقت الإنجاز
+active_stopwatch = متتبِّع وقت النشاط
organization = منظمة
new_migrate = ترحيل جديد
save = احفظ
@@ -114,7 +114,7 @@ twofa_scratch = الرمز الاحتياطي للمصادقة بعاملين
home = الرئيسية
email = عنوان البريد الإلكتروني
issues = المسائل
-error404 = الصفحة التي تحاول الوصول لها إما لا توجد أو أنت لست مأذون لك بعرضها.
+error404 = الصفحة التي تحاول الوصول لها إما غير موجودو أو أنك غير مصرح لك بعرضها.
powered_by = مدعوم بواسطة %s
retry = أعد المحاولة
tracked_time_summary = ملخص للتتبع الزمني وفقًا لنتائج تصفية قائمة المسائل
@@ -127,8 +127,8 @@ toggle_menu = تبديل القائمة
more_items = عناصر اضافية
copy_generic = نسخ إلى الحافظة
invalid_data = بيانات غير صالحة: %v
-filter.clear = مسح المرشحات
-filter = مرشح
+filter.clear = مسح عوامل التصفية
+filter = عامل تصفية
filter.is_archived = مؤرشف
filter.is_template = قوالب
filter.not_mirror = ليست مرايا
@@ -137,7 +137,7 @@ filter.is_mirror = مرايا
filter.is_fork = الاشتقاقات
filter.not_fork = ليست اشتقاقات
filter.not_archived = ليس مؤرشف
-filter.public = علني
+filter.public = عام
filter.private = خاص
new_repo.title = مستودع جديد
new_migrate.title = انتقال جديد
@@ -145,6 +145,11 @@ new_org.title = منظمة جديدة
new_repo.link = مستودع جديد
new_migrate.link = انتقال جديد
+new_org.link = منظمة جديدة
+test = اختبار
+copy_path = نسخ المسار
+error413 = لقد استنفدت حصتك.
+
[install]
db_name = اسم قاعدة البيانات
user = اسم المستخدم
@@ -170,7 +175,7 @@ reinstall_confirm_check_2 = وقد يلزم إعادة تزامن المستود
run_user = شغّل عبر مستخدم
err_admin_name_is_invalid = اسم مستخدم المدير غير صالح
reinstall_confirm_check_3 = أنتِ تؤكد أنكِ متأكد تماماً من أن فورجيو يعمل مع مسار app.ini الصحيح وأنك متأكد من أنه يجب عليك إعادة تثبيته. أنت تُؤكّدُ بأنّك تُقرّ بالمخاطر السالفة الذكر.
-repo_path = المسار الجذري للمستودع
+repo_path = المسار الجذر للمستودع
err_empty_admin_email = عنوان بريد المدير لا يمكن أن يكون فارغ.
no_admin_and_disable_registration = لا يمكنك تعطيل التسجيل الذاتي للمستخدمين بدون إنشاء حساب إداري.
err_admin_name_pattern_not_allowed = اسم مستخدم المدير غير صالح، هذا الأسم يطابق نمطا محجوز
@@ -179,10 +184,10 @@ repo_path_helper = ستُحفظ كلّ مستودعات جِت البعيدة ف
general_title = الإعدادات العامة
lfs_path_helper = الملفات التي تم تعقبها بواسطة Git LFS ستُخزن في هذا الدليل. اتركه فارغًا لتعطيله.
err_empty_db_path = طريق قاعدة بيانات SQLite3 لا يمكن أن يكون فارغا.
-lfs_path = مسار جذر جِت LFS
-app_name_helper = يمكنك إدخال اسم شركتك هنا.
+lfs_path = مسار جذر Git LFS
+app_name_helper = أدخل اسم المثيل هنا. سيظهر هذا الاسم في كل الصفحات.
err_admin_name_is_reserved = اسم مستخدم المدير غير صالح، هذا الأسم محجوز
-app_name = عنوان الموقع
+app_name = عنوان المثيل
log_root_path = مسار السجل
log_root_path_helper = ستُكتب ملفات السجل في هذا الدليل.
smtp_addr = مضيف SMTP
@@ -190,7 +195,7 @@ smtp_port = منفذ SMTP
mailer_password = كلمة مرور SMTP
app_url_helper = العنوان الأساسي لاستنساخ عناوين URL HTTP(S) وإشعارات البريد الإلكتروني.
mailer_user = اسم مستخدم SMTP
-disable_gravatar.description = عطل جرافاتار والجهات الخارجية للصور الرمزية. ستُستخدم صورة رمزية مبدئية حتى يرفع المستخدم صورة.
+disable_gravatar.description = عطل Gravatar والجهات الخارجية للصور الرمزية. ستُستخدم صورة رمزية مبدئية حتى يرفع المستخدم صورة.
offline_mode.description = عطل خدمات توصيل المحتوى من الجهات الخارجية، واخدم كل المحتوى محلياً.
run_user_helper = اسم مستخدم نظام التشغيل الذي يشغل فورجيو. ملاحظة: هذا المستخدم يجب أن يكون له حق الوصول إلى المسار الجذري للمستودع.
domain = نطاق الخادم
@@ -199,28 +204,28 @@ smtp_from = أرسل البريد الإلكتروني كـ
federated_avatar_lookup = تفعيل الصور الرمزية الاتحادية
optional_title = إعدادات اختيارية
domain_helper = نطاق أو عنوان المضيف لخادمك.
-mail_notify = فعّل التنبيه عبر البريد الإلكتروني
-app_url = الرابط الأساس لفورجيو
+mail_notify = فعّل التنبيهات عبر البريد الإلكتروني
+app_url = الرابط الأساس
smtp_from_helper = عنوان البريد الإلكتروني الذي سيستخدمه فورجيو. أدخل عنوان بريد إلكتروني عادي أو استخدم صيغة"Name" /etc/apk/repositories
:
+alpine.registry.key = Изтеглете публичния RSA ключ на регистъра в папката /etc/apk/keys/
, за да проверите подписа на индекса:
+alpine.registry.info = Изберете $branch и $repository от списъка по-долу.
+alpine.install = За да инсталирате пакета, изпълнете следната команда:
+arch.version.properties = Свойства на версията
+arch.version.makedepends = Зависимости за изграждането
+arch.version.checkdepends = Зависимости за проверката
+chef.registry = Настройте този регистър във вашия файл ~/.chef/config.rb
:
+chef.install = За да инсталирате пакета, изпълнете следната команда:
+composer.registry = Настройте този регистър във вашия файл ~/.composer/config.json
:
+composer.install = За да инсталирате пакета с Composer, изпълнете следната команда:
+composer.dependencies = Зависимости
+conan.details.repository = Хранилище
+conan.registry = Настройте този регистър от командния ред:
+conan.install = За да инсталирате пакета с Conan, изпълнете следната команда:
+conda.registry = Настройте този регистър като Conda хранилище във вашия файл .condarc
:
+conda.install = За да инсталирате пакета с Conda, изпълнете следната команда:
+container.pull = Издърпайте образа от командния ред:
+container.multi_arch = ОС / Архитектура
+container.layers = Слоеве на образа
+cran.registry = Настройте този регистър във вашия файл Rprofile.site
:
+cran.install = За да инсталирате пакета, изпълнете следната команда:
+debian.registry = Настройте този регистър от командния ред:
+debian.registry.info = Изберете $distribution и $component от списъка по-долу.
+debian.install = За да инсталирате пакета, изпълнете следната команда:
+debian.repository = Информация за хранилището
+debian.repository.distributions = Дистрибуции
+debian.repository.components = Компоненти
+debian.repository.architectures = Архитектури
+helm.registry = Настройте този регистър от командния ред:
+helm.install = За да инсталирате пакета, изпълнете следната команда:
+maven.registry = Настройте този регистър във файла на вашия проект pom.xml
:
+maven.install = За да използвате пакета, включете следното в блока dependencies
във файла pom.xml
:
+maven.install2 = Изпълнете през командния ред:
+maven.download = За да изтеглите зависимостта, изпълнете през командния ред:
+nuget.registry = Настройте този регистър от командния ред:
+nuget.install = За да инсталирате пакета с NuGet, изпълнете следната команда:
+nuget.dependency.framework = Целева платформа
+npm.registry = Настройте този регистър във файла на вашия проект .npmrc
:
+npm.install = За да инсталирате пакета с npm, изпълнете следната команда:
+npm.install2 = или го добавете във файла package.json:
+npm.dependencies.optional = Опционални зависимости
+npm.details.tag = Маркер
+pub.install = За да инсталирате пакета с Dart, изпълнете следната команда:
+pypi.requires = Изисква Python
+pypi.install = За да инсталирате пакета с pip, изпълнете следната команда:
+rpm.registry = Настройте този регистър от командния ред:
+rpm.distros.redhat = на дистрибуции, базирани на RedHat
+rpm.distros.suse = на дистрибуции, базирани на SUSE
+rpm.install = За да инсталирате пакета, изпълнете следната команда:
+rpm.repository = Информация за хранилището
+rpm.repository.architectures = Архитектури
+rpm.repository.multiple_groups = Този пакет е наличен в няколко групи.
+alt.registry = Настройте този регистър от командния ред:
+alt.registry.install = За да инсталирате пакета, изпълнете следната команда:
+alt.install = Инсталиране на пакет
+alt.setup = Добавете хранилище към списъка със свързани хранилища (изберете необходимата архитектура вместо „_arch_“):
+alt.repository = Информация за хранилището
+alt.repository.architectures = Архитектури
+alt.repository.multiple_groups = Този пакет е наличен в няколко групи.
+swift.registry = Настройте този регистър от командния ред:
+swift.install = Добавете пакета във вашия файл Package.swift
:
+swift.install2 = и изпълнете следната команда:
+vagrant.install = За да добавите Vagrant box, изпълнете следната команда:
+settings.link = Свързване на този пакет с хранилище
+settings.link.description = Ако свържете пакет с хранилище, пакетът се изброява в списъка с пакети на хранилището.
+settings.link.select = Изберете хранилище
+settings.link.button = Обновяване на връзката на хранилището
+settings.link.success = Връзката на хранилището беше успешно обновена.
+settings.link.error = Неуспешно обновяване на връзката на хранилището.
+settings.delete.description = Изтриването на пакет е трайно и не може да бъде отменено.
+settings.delete.notice = На път сте да изтриете %s (%s). Тази операция е необратима, сигурни ли сте?
+owner.settings.cargo.title = Индекс на регистъра на Cargo
+owner.settings.cargo.initialize = Инициализиране на индекс
+owner.settings.cargo.initialize.description = Необходимо е специално Git хранилище за индекс, за да се използва регистърът на Cargo. Използването на тази опция ще (пре)създаде хранилището и ще го конфигурира автоматично.
+owner.settings.cargo.initialize.error = Неуспешно инициализиране на индекса на Cargo: %v
+owner.settings.cargo.initialize.success = Индексът на Cargo беше успешно създаден.
+owner.settings.cargo.rebuild = Преизграждане на индекс
+owner.settings.cargo.rebuild.description = Преизграждането може да бъде полезно, ако индексът не е синхронизиран със съхранените Cargo пакети.
+owner.settings.cargo.rebuild.error = Неуспешно преизграждане на индекса на Cargo: %v
+owner.settings.cargo.rebuild.success = Индексът на Cargo беше успешно преизграден.
+owner.settings.cargo.rebuild.no_index = Не може да се преизгради, няма инициализиран индекс.
+owner.settings.cleanuprules.title = Правила за почистване
+owner.settings.cleanuprules.add = Добавяне на правило за почистване
+owner.settings.cleanuprules.edit = Редактиране на правилото за почистване
+owner.settings.cleanuprules.none = Все още няма правила за почистване.
+owner.settings.cleanuprules.preview = Преглед на правило за почистване
+owner.settings.cleanuprules.preview.overview = %d пакета са насрочени за премахване.
+owner.settings.cleanuprules.preview.none = Правилото за почистване не съвпада с нито един пакет.
+owner.settings.cleanuprules.enabled = Включено
+owner.settings.cleanuprules.pattern_full_match = Прилагане на шаблона към пълното име на пакета
+owner.settings.cleanuprules.keep.title = Версиите, които съответстват на тези правила, се запазват, дори ако съответстват на правило за премахване по-долу.
+owner.settings.cleanuprules.keep.count = Запазване на най-новите
+owner.settings.cleanuprules.keep.count.1 = 1 версия на пакет
+owner.settings.cleanuprules.keep.count.n = %d версии на пакет
+owner.settings.cleanuprules.keep.pattern = Запазване на версии, съответстващи на
+owner.settings.cleanuprules.keep.pattern.container = Версията latest
винаги се запазва за Container пакети.
+owner.settings.cleanuprules.remove.title = Версиите, които съответстват на тези правила, се премахват, освен ако правило по-горе не казва да се запазят.
+owner.settings.cleanuprules.remove.days = Премахване на версии, по-стари от
+owner.settings.cleanuprules.remove.pattern = Премахване на версии, съответстващи на
+owner.settings.cleanuprules.success.update = Правилото за почистване е обновено.
+owner.settings.cleanuprules.success.delete = Правилото за почистване е изтрито.
+owner.settings.chef.title = Регистър на Chef
+owner.settings.chef.keypair = Генериране на двойка ключове
+owner.settings.chef.keypair.description = Заявките, изпратени до регистъра на Chef, трябва да бъдат криптографски подписани като средство за удостоверяване. При генериране на двойка ключове, само публичният ключ се съхранява във Forgejo. Частният ключ ви се предоставя, за да се използва с knife. Генерирането на нова двойка ключове ще презапише предишната.
+
[tool]
hours = %d часа
now = сега
@@ -749,7 +872,7 @@ settings.admin_settings = Администраторски настройки
issues.role.owner = Притежател
settings.transfer.title = Прехвърляне на притежанието
issues.author = Автор
-issues.closed_at = `затвори тази задача %[2]s`
+issues.closed_at = `затвори тази задача %s`
settings.collaborator_deletion_desc = Премахването на сътрудник ще отнеме достъпа му до това хранилище. Продължаване?
commits.message = Съобщение
issues.due_date_not_set = Няма зададен краен срок.
@@ -773,9 +896,9 @@ issues.filter_type.all_issues = Всички задачи
issues.filter_poster_no_select = Всички автори
issues.opened_by = отворена %[1]s от %[3]s
issues.action_open = Отваряне
-pulls.closed_at = `затвори тази заявка за сливане %[2]s`
-pulls.reopened_at = `отвори наново тази заявка за сливане %[2]s`
-issues.reopened_at = `отвори наново тази задача %[2]s`
+pulls.closed_at = `затвори тази заявка за сливане %s`
+pulls.reopened_at = `отвори наново тази заявка за сливане %s`
+issues.reopened_at = `отвори наново тази задача %s`
projects.column.edit = Редактиране на колоната
issues.close = Затваряне на задачата
issues.ref_reopened_from = `отвори наново тази задача %[4]s %[2]s`
@@ -940,9 +1063,9 @@ editor.no_changes_to_show = Няма промени за показване.
issues.choose.get_started = Първи стъпки
issues.change_milestone_at = `промени етапа от %s на %s %s`
issues.change_project_at = `промени проекта от %s на %s %s`
-issues.self_assign_at = `си само-възложи това %s`
+issues.self_assign_at = `си самовъзложи това %s`
issues.remove_assignee_at = `е премахнат като изпълнител от %s %s`
-issues.remove_self_assignment = `се само-премахна като изпълнител %s`
+issues.remove_self_assignment = `се самопремахна като изпълнител %s`
issues.add_assignee_at = `му бе възложено това от %s %s`
pulls.merged_by = от %[3]s бе слята %[1]s
pulls.merged_by_fake = от %[2]s бе слята %[1]s
@@ -1205,7 +1328,7 @@ issues.dependency.cancel = Отказ
issues.dependency.add_error_dep_exists = Зависимостта вече съществува.
issues.dependency.add_error_dep_not_exist = Зависимостта не съществува.
issues.remove_ref_at = `премахна препратката %s %s`
-issues.ref_pull_from = `спомена тази заявка за сливане %[4]s %[2]s`
+issues.ref_pull_from = `спомена тази заявка за сливане %[3]s %[1]s`
issues.dependency.pr_no_dependencies = Няма зададени зависимости.
issues.dependency.remove_info = Премахване на тази зависимост
issues.dependency.removed_dependency = `премахна зависимостта %s`
@@ -1230,11 +1353,11 @@ issues.dependency.title = Зависимости
issues.dependency.issue_no_dependencies = Няма зададени зависимости.
issues.dependency.pr_close_blocked = Трябва да затворите всички задачи, блокиращи тази заявка за сливане, преди да можете да я слеете.
issues.dependency.pr_close_blocks = Тази заявка за сливане блокира затварянето на следните задачи
-issues.ref_issue_from = `спомена тази задача %[4]s %[2]s`
-issues.commit_ref_at = `спомена тази задача в подаване %[2]s`
+issues.ref_issue_from = `спомена тази задача %[3]s %[1]s`
+issues.commit_ref_at = `спомена тази задача в подаване %s`
issues.add_ref_at = `добави препратка %s %s`
pulls.merged_info_text = Клонът %s вече може да бъде изтрит.
-pulls.commit_ref_at = `спомена тази заявка за сливане в подаване %[2]s`
+pulls.commit_ref_at = `спомена тази заявка за сливане в подаване %s`
issues.change_ref_at = `промени препратката от alt
+ click/enter
, за да изключите етикети`
+issues.filter_label_exclude = Използвайте Alt + Click, за да изключите етикети
migrate.migrating_failed = Мигрирането от %s е неуспешно.
migrate.migrating_issues = Мигриране на задачи
mirror_from = огледално на
@@ -1576,6 +1699,178 @@ issues.force_push_compare = Сравняване
pulls.status_checking = Някои проверки са в очакване
pulls.nothing_to_compare = Тези клонове са равни. Не е нужно да създавате заявка за сливане.
+rss.must_be_on_branch = Трябва да сте на клон, за да имате RSS емисия.
+admin.manage_flags = Управление на флаговете
+admin.enabled_flags = Флагове, включени за хранилището:
+admin.update_flags = Обновяване на флаговете
+admin.failed_to_replace_flags = Неуспешна замяна на флаговете на хранилището
+admin.flags_replaced = Флаговете на хранилището са заменени
+fork_to_different_account = Разклоняване в друг акаунт
+mirror_interval = Интервал на огледалото (валидни единици за време са „h“, „m“, „s“). 0 за изключване на периодичната синхронизация. (Минимален интервал: %s)
+mirror_interval_invalid = Интервалът на огледалото не е валиден.
+mirror_use_ssh.text = Използване на SSH удостоверяване
+mirror_use_ssh.helper = Forgejo ще създаде огледало на хранилището чрез Git през SSH и ще генерира двойка ключове за вас, когато изберете тази опция. Трябва да се уверите, че генерираният публичен ключ е упълномощен да изтласква към целевото хранилище. Не можете да използвате удостоверяване, базирано на парола, когато избирате това.
+mirror_use_ssh.not_available = SSH удостоверяването не е налично.
+mirror_denied_combination = Не може да се използва удостоверяване с публичен ключ и парола едновременно.
+mirror_sync_on_commit = Синхронизиране при изтласкване на подавания
+mirror_address_desc = Поставете всички необходими данни за удостоверяване в секцията „Упълномощаване“.
+mirror_address_url_invalid = Предоставеният URL е невалиден. Трябва да екранирате правилно всички компоненти на URL адреса.
+mirror_address_protocol_invalid = Предоставеният URL е невалиден. Само http(s):// или git:// адреси могат да се използват за огледални хранилища.
+mirror_lfs = Съхранение на големи файлове (LFS)
+mirror_password_help = Променете потребителското име, за да изтриете запазена парола.
+unit_disabled = Администраторът на сайта е изключил тази секция на хранилището.
+summary_card_alt = Карта с обобщение на хранилище %s
+template.items = Елементи на шаблона
+template.git_content = Git съдържание (стандартен клон)
+template.git_hooks = Git куки
+template.git_hooks_tooltip = В момента не можете да променяте или премахвате Git куки, след като са добавени. Изберете това само ако се доверявате на шаблонното хранилище.
+template.one_item = Трябва да изберете поне един елемент от шаблона
+template.invalid = Трябва да изберете шаблонно хранилище
+migrate.cancel_migrating_title = Отказ от миграцията
+migrate.cancel_migrating_confirm = Искате ли да откажете тази миграция?
+invisible_runes_description = `Този файл съдържа невидими Уникод знаци, които са неразличими за хората, но могат да бъдат обработени по различен начин от компютър. Ако смятате, че това е умишлено, можете спокойно да пренебрегнете това предупреждение. Използвайте бутона „Екраниране“, за да ги разкриете.`
+ambiguous_runes_header = `Този файл съдържа двусмислени Уникод знаци`
+ambiguous_runes_description = `Този файл съдържа Уникод знаци, които могат да бъдат объркани с други знаци. Ако смятате, че това е умишлено, можете спокойно да пренебрегнете това предупреждение. Използвайте бутона „Екраниране“, за да ги разкриете.`
+file_copy_permalink = Копиране на постоянна връзка
+view_git_blame = Преглед на git blame
+video_not_supported_in_browser = Вашият браузър не поддържа HTML5 тага „video“.
+audio_not_supported_in_browser = Вашият браузър не поддържа HTML5 тага „audio“.
+stored_lfs = Съхранено с Git LFS
+commit_graph.select = Изберете клонове
+editor.cannot_edit_lfs_files = LFS файлове не могат да се редактират в уеб интерфейса.
+editor.filename_help = Добавете директория, като въведете името ѝ, последвано от наклонена черта („/“). Премахнете директория, като натиснете backspace в началото на полето за въвеждане.
+editor.commit_signed_changes = Подаване на подписани промени
+editor.require_signed_commit = Клонът изисква подписано подаване
+editor.commit_email = Ел. поща на подаването
+commits.desc = Разглеждане на историята на промените в програмния код.
+commits.search.tooltip = Можете да добавите префикс към ключовите думи с „author:“, „committer:“, „after:“ или „before:“, напр. „revert author:Alice before:2019-01-13“.
+commits.signed_by = Подписано от
+commits.signed_by_untrusted_user = Подписано от недоверен потребител
+commits.signed_by_untrusted_user_unmatched = Подписано от недоверен потребител, който не съвпада с подаващия
+commits.ssh_key_fingerprint = Отпечатък на SSH ключ
+commits.view_single_diff = Преглед на промените в този файл, въведени в това подаване
+commit.revert = Връщане
+commit.revert-header = Връщане: %s
+commit.revert-content = Изберете клон, върху който да се върне:
+issues.desc = Организирайте доклади за грешки, задачи и етапи.
+issues.choose.ignore_invalid_templates = Невалидните шаблони са игнорирани
+issues.choose.invalid_config = Конфигурацията на задачите съдържа грешки:
+issues.filter_type.all_pull_requests = Всички заявки за сливане
+issues.role.member_helper = Този потребител е участник в организацията, притежаваща това хранилище.
+issues.lock.unknown_reason = Не може да се заключи задача с неизвестна причина.
+issues.lock_duplicate = Задача не може да бъде заключена два пъти.
+issues.unlock_error = Не може да се отключи задача, която не е заключена.
+issues.lock.notice_1 = - Други потребители не могат да добавят нови коментари към тази задача.
+issues.lock.notice_2 = - Вие и други сътрудници с достъп до това хранилище все още можете да оставяте коментари, които другите да виждат.
+issues.lock.notice_3 = - Винаги можете да отключите тази задача отново в бъдеще.
+issues.unlock.notice_1 = - Всеки ще може отново да коментира тази задача.
+issues.unlock.notice_2 = - Винаги можете да заключите тази задача отново в бъдеще.
+issues.lock.title = Заключване на обсъждането по тази задача.
+issues.unlock.title = Отключване на обсъждането по тази задача.
+issues.comment_on_locked = Не можете да коментирате заключена задача.
+issues.delete.text = Наистина ли искате да изтриете тази задача? (Това ще премахне трайно цялото съдържание. Помислете дали вместо това да не я затворите, ако възнамерявате да я запазите архивирана)
+issues.cancel_tracking_history = `отмени проследяването на времето %s`
+issues.add_time_sum_to_small = Не е въведено време.
+issues.due_date_form = гггг-мм-дд
+issues.due_date_invalid = Крайният срок е невалиден или извън обхвата. Моля, използвайте формата „гггг-мм-дд“.
+issues.dependency.no_permission_1 = Нямате разрешение да прочетете %d зависимост
+issues.dependency.no_permission_n = Нямате разрешение да прочетете %d зависимости
+issues.dependency.no_permission.can_remove = Нямате разрешение да прочетете тази зависимост, но можете да я премахнете
+issues.dependency.issue_batch_close_blocked = Не могат да бъдат затворени групово избраните задачи, защото задача #%d все още има отворени зависимости
+issues.dependency.blocked_by_short = Зависи от
+issues.dependency.setting = Включване на зависимости за задачи и заявки за сливане
+issues.dependency.add_error_same_issue = Не можете да направите задача зависима от самата нея.
+issues.dependency.add_error_dep_issue_not_exist = Зависимата задача не съществува.
+issues.dependency.add_error_cannot_create_circular = Не можете да създадете зависимост с две задачи, които се блокират взаимно.
+issues.dependency.add_error_dep_not_same_repo = И двете задачи трябва да са в едно и също хранилище.
+issues.review.self.rejection = Не можете да поискате промени в собствената си заявка за сливане.
+issues.review.dismissed = отхвърли рецензията на %s %s
+issues.review.content.empty = Трябва да оставите коментар, посочващ исканите промени.
+issues.review.add_review_requests = поиска рецензии от %[1]s %[2]s
+issues.review.remove_review_request = премахна заявката за рецензия за %[1]s %[2]s
+issues.review.remove_review_requests = премахна заявките за рецензия за %[1]s %[2]s
+issues.review.remove_review_request_self = отказа да рецензира %s
+issues.review.pending.tooltip = Този коментар в момента не е видим за други потребители. За да изпратите изчакващите си коментари, изберете „%s“ -> „%s/%s/%s“ в горната част на страницата.
+issues.review.outdated = Остарял
+issues.review.outdated_description = Съдържанието е променено, след като е направен този коментар
+issues.review.show_outdated = Показване на остарели
+issues.review.hide_outdated = Скриване на остарели
+issues.content_history.options = Опции
+issues.blocked_by_user = Не можете да създавате задачи в това хранилище, защото сте блокирани от притежателя на хранилището.
+comment.blocked_by_user = Коментирането не е възможно, защото сте блокирани от притежателя на хранилището или от автора.
+issues.reopen.blocked_by_user = Не можете да отворите наново тази задача, защото сте блокирани от притежателя на хранилището или от автора на тази задача.
+compare.compare_base = основа
+compare.compare_head = сравняване
+pulls.desc = Включване на заявки за сливане и рецензии на код.
+pulls.view = Преглед на заявката за сливане
+pulls.allow_edits_from_maintainers_desc = Потребители с право на запис в основния клон могат също да изтласкват към този клон
+pulls.allow_edits_from_maintainers_err = Обновяването е неуспешно
+pulls.has_changed_since_last_review = Променено след последната ви рецензия
+pulls.switch_comparison_type = Превключване на типа сравнение
+pulls.filter_branch = Филтриране на клон
+pulls.review_only_possible_for_full_diff = Рецензирането е възможно само при преглед на пълните разлики
+pulls.wrong_commit_id = ID на подаването трябва да бъде ID на подаване в целевия клон
+pulls.blocked_by_user = Не можете да създадете заявка за сливане в това хранилище, защото сте блокирани от притежателя на хранилището.
+pulls.no_merge_desc = Тази заявка за сливане не може да бъде слята, защото всички опции за сливане в хранилището са изключени.
+pulls.no_merge_helper = Включете опциите за сливане в настройките на хранилището или слейте заявката за сливане ръчно.
+pulls.no_merge_wip = Тази заявка за сливане не може да бъде слята, защото е отбелязана като в процес на работа.
+pulls.squash_merge_pull_request = Създаване на сплескано подаване
+pulls.merge_manually = Ръчно слята
+pulls.merge_commit_id = ID на подаването със сливане
+pulls.require_signed_wont_sign = Клонът изисква подписани подавания, но това сливане няма да бъде подписано
+pulls.merge_conflict = Сливането е неуспешно: Възникна конфликт по време на сливането. Подсказка: Опитайте различна стратегия
+pulls.merge_conflict_summary = Съобщение за грешка
+pulls.rebase_conflict_summary = Съобщение за грешка
+pulls.has_merged = Неуспешно: Заявката за сливане е слята, не можете да слеете отново или да промените целевия клон.
+pulls.push_rejected = Изтласкването е неуспешно: Изтласкването е отхвърлено. Прегледайте Git куките за това хранилище.
+pulls.push_rejected_no_message = Изтласкването е неуспешно: Изтласкването е отхвърлено, но няма отдалечено съобщение. Прегледайте Git куките за това хранилище
+pulls.update_not_allowed = Нямате разрешение да обновявате клона
+pulls.outdated_with_base_branch = Този клон е остарял спрямо основния клон
+pulls.cmd_instruction_merge_warning = Предупреждение: Настройката „Автоматично откриване на ръчно сливане“ не е включена за това хранилище, ще трябва да отбележите тази заявка за сливане като ръчно слята след това.
+pulls.editable_explanation = Тази заявка за сливане позволява редакции от поддържащите. Можете да допринесете директно към нея.
+pulls.auto_merge_button_when_succeed = (Когато проверките са успешни)
+pulls.auto_merge_when_succeed = Автоматично сливане, когато всички проверки са успешни
+pulls.auto_merge_newly_scheduled = Заявката за сливане е насрочена за сливане, когато всички проверки са успешни.
+pulls.auto_merge_has_pending_schedule = %[1]s насрочи тази заявка за сливане за автоматично сливане, когато всички проверки са успешни %[2]s.
+pulls.auto_merge_cancel_schedule = Отмяна на автоматичното сливане
+pulls.auto_merge_not_scheduled = Тази заявка за сливане не е насрочена за автоматично сливане.
+pulls.auto_merge_canceled_schedule = Автоматичното сливане е отменено за тази заявка за сливане.
+pulls.auto_merge_newly_scheduled_comment = `насрочи тази заявка за сливане за автоматично сливане, когато всички проверки са успешни %[1]s`
+pulls.auto_merge_canceled_schedule_comment = `отмени автоматичното сливане на тази заявка за сливане, когато всички проверки са успешни %[1]s`
+pulls.delete.title = Да се изтрие ли тази заявка за сливане?
+pulls.delete.text = Наистина ли искате да изтриете тази заявка за сливане? (Това ще премахне трайно цялото съдържание. Помислете дали вместо това да не я затворите, ако възнамерявате да я запазите архивирана)
+diff.data_not_available = Съдържанието на разликите не е налично
+diff.bin = ДВОИЧЕН
+diff.file_suppressed_line_too_long = Разликите във файла са потиснати, защото един или повече редове са твърде дълги
+diff.too_many_files = Някои файлове не бяха показани, защото твърде много файлове имат промени в тези разлики
+diff.show_more = Показване на още
+diff.generated = генериран
+diff.comment.add_line_comment = Добавяне на коментар към ред
+diff.comment.add_review_comment = Добавяне на коментар
+diff.review.self_reject = Авторите на заявки за сливане не могат да поискват промени в собствените си заявки
+diff.review.self_approve = Авторите на заявки за сливане не могат да одобряват собствените си заявки
+diff.image.side_by_side = Едно до друго
+diff.image.swipe = Плъзгане
+diff.image.overlay = Наслагване
+diff.has_escaped = Този ред има скрити Уникод знаци
+release.tag_name_protected = Името на маркера е защитено.
+release.add_tag_msg = Използване на заглавието и съдържанието на изданието като съобщение на маркера.
+release.hide_archive_links = Скриване на автоматично генерираните архиви
+release.hide_archive_links_helper = Скрийте автоматично генерираните архиви с програмен код за това издание. Например, ако качвате свои собствени.
+release.asset_external_url = Външен URL адрес
+release.summary_card_alt = Карта с обобщение на издание със заглавие „%s“ в хранилище %s
+branch.protected_deletion_failed = Клонът „%s“ е защитен. Не може да бъде изтрит.
+branch.default_deletion_failed = Клонът „%s“ е стандартният клон. Не може да бъде изтрит.
+branch.included_desc = Този клон е част от стандартния клон
+branch.included = Включен
+branch.warning_rename_default_branch = Преименувате стандартния клон.
+topic.count_prompt = Не можете да изберете повече от 25 теми
+find_file.no_matching = Не е намерен съвпадащ файл
+error.csv.too_large = Не може да се визуализира този файл, защото е твърде голям.
+error.csv.unexpected = Не може да се визуализира този файл, защото съдържа неочакван знак на ред %d и колона %d.
+error.csv.invalid_field_count = Не може да се визуализира този файл, защото има грешен брой полета на ред %d.
+error.broken_git_hook = Git куките на това хранилище изглеждат повредени. Моля, последвайте документацията, за да ги поправите, след което изтласкайте подавания, за да обновите статуса.
+
[modal]
confirm = Потвърждаване
no = Не
@@ -1663,18 +1958,18 @@ follow_blocked_user = Не можете да следвате тази орга
settings.delete_prompt = Организацията ще бъде премахната завинаги. Това НЕ МОЖЕ да бъде отменено!
settings.labels_desc = Добавете етикети, които могат да се използват за задачи за всички хранилища в тази организация.
teams.none_access = Без достъп
-teams.members.none = Няма членове в този екип.
+teams.members.none = Няма участници в този екип.
repo_updated = Обновено %s
teams.delete_team_success = Екипът е изтрит.
teams.search_repo_placeholder = Потърсете хранилище…
teams.delete_team_title = Изтриване на екипа
-teams.add_team_member = Добавяне на член на екипа
+teams.add_team_member = Добавяне на участник в екипа
teams.read_access_helper = Членовете могат да преглеждат и клонират хранилищата на екипа.
teams.invite.description = Моля, щракнете върху бутона по-долу, за да се присъедините към екипа.
teams.invite.title = Поканени сте да се присъедините към екип %s в организация %s.
team_permission_desc = Разрешение
members.public_helper = Да е скрит
-teams.members = Членове на екипа
+teams.members = Участници в екипа
teams.delete_team = Изтриване на екипа
members.owner = Притежател
members.member_role = Роля на участника:
@@ -1685,6 +1980,38 @@ settings.delete_org_desc = Тази организация ще бъде изт
open_dashboard = Отваряне на таблото
settings.change_orgname_prompt = Бележка: Промяната на името на организацията ще промени и URL адреса на вашата организация и ще освободи старото име.
+team_access_desc = Достъп до хранилище
+team_unit_desc = Разрешаване на достъп до секции на хранилището
+team_unit_disabled = (Изключено)
+form.name_reserved = Името на организацията „%s“ е резервирано.
+form.name_pattern_not_allowed = Шаблонът „%s“ не е разрешен в име на организация.
+form.create_org_not_allowed = Нямате разрешение да създавате организация.
+settings.update_setting_success = Настройките на организацията са обновени.
+settings.change_orgname_redirect_prompt = Старото име ще се пренасочва, докато не бъде взето.
+settings.change_orgname_redirect_prompt.with_cooldown.one = Старото име на организацията ще бъде достъпно за всички след период на изчакване от %[1]d ден. Все още можете да си върнете старото име по време на периода на изчакване.
+settings.change_orgname_redirect_prompt.with_cooldown.few = Старото име на организацията ще бъде достъпно за всички след период на изчакване от %[1]d дни. Все още можете да си върнете старото име по време на периода на изчакване.
+settings.update_avatar_success = Профилната снимка на организацията е обновена.
+settings.hooks_desc = Добавете уеб-куки, които ще се задействат за всички хранилища в тази организация.
+members.membership_visibility = Видимост на участничеството:
+members.public = Видим
+members.private = Скрит
+members.invite_desc = Добавяне на нов участник към %s:
+members.invite_now = Поканване сега
+teams.admin_access = Администраторски достъп
+teams.invite_team_member = Поканване в %s
+teams.invite_team_member.list = Чакащи покани
+teams.delete_team_desc = Изтриването на екип отнема достъпа до хранилището от неговите участници. Продължаване?
+teams.remove_all_repos_desc = Това ще премахне всички хранилища от екипа.
+teams.add_all_repos_title = Добавяне на всички хранилища
+teams.add_all_repos_desc = Това ще добави всички хранилища на организацията към екипа.
+teams.add_nonexistent_repo = Хранилището, което се опитвате да добавите, не съществува, моля, първо го създайте.
+teams.add_duplicate_users = Потребителят вече е участник в екипа.
+teams.repos.none = Няма хранилища, до които този екип да има достъп.
+teams.specific_repositories = Конкретни хранилища
+teams.specific_repositories_helper = Участниците ще имат достъп само до хранилища, изрично добавени към екипа. Избирането на това няма автоматично да премахне хранилища, вече добавени с Всички хранилища.
+teams.all_repositories_helper = Екипът има достъп до всички хранилища. Избирането на това ще добави всички съществуващи хранилища към екипа.
+teams.invite.by = Поканен от %s
+
[install]
admin_password = Парола
user = Потребителско име
@@ -1978,14 +2305,14 @@ Pronouns = Местоимения
Biography = Биография
Website = Уебсайт
Location = Местоположение
-cannot_add_org_to_team = Организация не може да бъде добавена като член на екип.
+cannot_add_org_to_team = Организация не може да бъде добавена като участник в екип.
auth_failed = Неуспешно удостоверяване: %v
team_no_units_error = Разрешете достъп до поне една секция на хранилището.
password_uppercase_one = Поне един голям знак
CommitSummary = Обобщение на подаването
username_error = ` може да съдържа само буквено-цифрови знаци („0-9“, „a-z“, „A-Z“), тире („-“), долна черта („_“) и точка („.“). Не може да започва или завършва с не-буквено-цифрови знаци, като също така са забранени и последователни не-буквено-цифрови знаци.`
username_error_no_dots = ` може да съдържа само буквено-цифрови знаци („0-9“, „a-z“, „A-Z“), тире („-“) и долна черта („_“). Не може да започва или завършва с не-буквено-цифрови знаци, като също така са забранени и последователни не-буквено-цифрови знаци.`
-duplicate_invite_to_team = Потребителят вече е поканен като член на екипа.
+duplicate_invite_to_team = Потребителят вече е поканен като участник в екипа.
must_use_public_key = Ключът, който предоставихте, е частен ключ. Моля, не качвайте частния си ключ никъде. Вместо това използвайте публичния си ключ.
org_still_own_packages = Тази организация все още притежава един или повече пакети, първо ги изтрийте.
admin_cannot_delete_self = Не можете да изтриете себе си, когато сте администратор. Моля, първо премахнете администраторските си привилегии.
@@ -2006,7 +2333,7 @@ enterred_invalid_repo_name = Името на хранилището, което
enterred_invalid_org_name = Името на организацията, което въведохте, е неправилно.
enterred_invalid_password = Паролата, която въведохте, е неправилна.
organization_leave_success = Успешно напуснахте организацията %s.
-still_has_org = Вашият акаунт е член на една или повече организации, първо ги напуснете.
+still_has_org = Вашият акаунт е участник в една или повече организации, първо ги напуснете.
org_still_own_repo = Тази организация все още притежава едно или повече хранилища, първо ги изтрийте или прехвърлете.
target_branch_not_exist = Целевият клон не съществува.
glob_pattern_error = ` glob шаблонът е невалиден: %s.`
@@ -2017,6 +2344,18 @@ AdminEmail = Администраторски адрес за ел. поща
email_domain_is_not_allowed = Домейнът на адреса за ел. поща на потребителя %s е в конфликт с EMAIL_DOMAIN_ALLOWLIST или EMAIL_DOMAIN_BLOCKLIST. Уверете се, че сте въвели правилно адреса за ел. поща.
email_been_used = Адресът за ел. поща вече се използва.
+NewBranchName = Име на новия клон
+git_ref_name_error = ` трябва да е правилно форматирано име на Git препратка.`
+regex_pattern_error = ` шаблонът на регулярния израз е невалиден: %s.`
+repository_files_already_exist = Вече съществуват файлове за това хранилище. Свържете се със системния администратор.
+repository_files_already_exist.delete = Вече съществуват файлове за това хранилище. Трябва да ги изтриете.
+enterred_invalid_owner_name = Името на новия притежател не е валидно.
+last_org_owner = Не можете да премахнете последния потребител от екипа на „притежателите“. Трябва да има поне един притежател за организация.
+invalid_ssh_key = Не може да се потвърди вашият SSH ключ: %s
+invalid_gpg_key = Не може да се потвърди вашият GPG ключ: %s
+unable_verify_ssh_key = Не може да се потвърди SSH ключът, проверете го отново за грешки.
+required_prefix = Въведеният текст трябва да започва с „%s“
+
[action]
close_issue = `затвори задача %[3]s#%[2]s`
rename_repo = преименува хранилище от %[1]s
на %[3]s
@@ -2045,6 +2384,12 @@ compare_branch = Сравняване
compare_commits_general = Сравняване на подавания
compare_commits = Сравнете %d подавания
+transfer_repo = прехвърли хранилище %s
към %s
+mirror_sync_push = синхронизира подавания към %[3]s на %[4]s от огледало
+mirror_sync_create = синхронизира нова препратка %[3]s към %[4]s от огледало
+mirror_sync_delete = синхронизира и изтри препратка %[2]s
на %[3]s от огледало
+review_dismissed = `отхвърли рецензия от %[4]s за %[3]s#%[2]s`
+
[auth]
tab_openid = OpenID
openid_connect_submit = Свързване
@@ -2178,6 +2523,15 @@ variables.not_found = Променливата не е открита.
variables.id_not_exist = Променлива с идентификатор %d не съществува.
runners.owner_type = Тип
+unit.desc = Управление на интегрирани CI/CD pipelines с Forgejo Actions.
+status.unknown = Неизвестно
+status.waiting = Изчаква се
+status.running = Изпълнява се
+status.success = Успешно
+status.failure = Неуспешно
+status.cancelled = Отменено
+status.skipped = Пропуснато
+
[heatmap]
less = По-малко
number_of_contributions_in_the_last_12_months = %s приноса през последните 12 месеца
@@ -2258,3 +2612,32 @@ eib = ЕиБ
[translation_meta]
test = окей
+
+[repo.permissions]
+code.read = Четене: Достъп и клониране на кода на хранилището.
+code.write = Писане: Изтласкване към хранилището, създаване на клонове и маркери.
+issues.read = Четене: Четене и създаване на задачи и коментари.
+issues.write = Писане: Затваряне на задачи и управление на метаданни като етикети, етапи, изпълнители, крайни срокове и зависимости.
+pulls.read = Четене: Четене и създаване на заявки за сливане.
+pulls.write = Писане: Затваряне на заявки за сливане и управление на метаданни като етикети, етапи, изпълнители, крайни срокове и зависимости.
+releases.read = Четене: Преглед и изтегляне на издания.
+wiki.read = Четене: Четене на интегрираното уики и неговата история.
+wiki.write = Писане: Създаване, обновяване и изтриване на страници в интегрираното уики.
+projects.read = Четене: Достъп до проектните табла на хранилището.
+projects.write = Писане: Създаване и редактиране на проекти и колони.
+
+[gpg]
+default_key = Подписано с ключ по подразбиране
+error.extract_sign = Неуспешно извличане на подпис
+error.generate_hash = Неуспешно генериране на хеш на подаването
+error.no_committer_account = Няма акаунт, свързан с адреса за ел. поща на подаващия
+error.no_gpg_keys_found = Не е намерен известен ключ за този подпис в базата данни
+error.not_signed_commit = Не е подписано подаване
+error.failed_retrieval_gpg_keys = Неуспешно извличане на ключ, свързан с акаунта на подаващия
+error.probable_bad_signature = ВНИМАНИЕ! Въпреки че има ключ с това ID в базата данни, той не потвърждава това подаване! Това подаване е ПОДОЗРИТЕЛНО.
+error.probable_bad_default_signature = ВНИМАНИЕ! Въпреки че ключът по подразбиране има това ID, той не потвърждава това подаване! Това подаване е ПОДОЗРИТЕЛНО.
+
+[units]
+unit = Елемент
+error.no_unit_allowed_repo = Нямате разрешение за достъп до никоя секция на това хранилище.
+error.unit_not_allowed = Нямате разрешение за достъп до тази секция на хранилището.
diff --git a/options/locale/locale_ca.ini b/options/locale/locale_ca.ini
index 9cb7d5e50c..ea2af3b645 100644
--- a/options/locale/locale_ca.ini
+++ b/options/locale/locale_ca.ini
@@ -153,26 +153,26 @@ fuzzy = Difusa
search = Cerca...
type_tooltip = Tipus de cerca
fuzzy_tooltip = Inclou resultats que s'assemblen al terme de la cerca
-repo_kind = Cerca repos...
-user_kind = Cerca usuaris...
+repo_kind = Cerca repos…
+user_kind = Cerca usuaris…
code_search_unavailable = La cerca de codi no està disponible actualment. Si us plau concteu amb l'administrador del lloc.
code_search_by_git_grep = Els resultats actuals de la cerca de codi són proporcionats per "git grep". Podríen haver-hi millors resultats si l'administrador del lloc habilita l'indexador de codi.
-package_kind = Cerca paquets...
-project_kind = Cerca projectes...
-branch_kind = Cerca branques...
-commit_kind = Cerca commits...
-runner_kind = Cerca executors...
+package_kind = Cerca paquets…
+project_kind = Cerca projectes…
+branch_kind = Cerca branques…
+commit_kind = Cerca commits…
+runner_kind = Cerca executors…
no_results = Cap resultat coincident trobat.
keyword_search_unavailable = La cerca per paraula clau no està disponible ara mateix. Si us plau contacteu amb l'administrador del lloc.
union = Paraules clau
union_tooltip = Inclou resultats que encaixen amb qualsevol paraula clau separada per espais
-org_kind = Cerca organitzacions...
-team_kind = Cerca teams...
-code_kind = Cerca codi...
-pull_kind = Cerca "pulls"...
+org_kind = Cerca organitzacions…
+team_kind = Cerca teams…
+code_kind = Cerca codi…
+pull_kind = Cerca "pulls"…
exact = Exacte
exact_tooltip = Inclou només resultats que són exactament el terme de cerca
-issue_kind = Cerca problemes...
+issue_kind = Cerca problemes…
regexp = RegExp
regexp_tooltip = Interpreta el terme de cerca com una expressió regular
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 9448dd8e7e..30fa95e6be 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -1063,7 +1063,7 @@ language.localization_project = Pomozte nám s překladem Forgejo do vašeho jaz
user_block_yourself = Nemůžete zablokovat sami sebe.
pronouns_custom_label = Vlastní zájmena
change_username_redirect_prompt.with_cooldown.few = Staré uživatelské jméno bude dostupné ostatním po %[1]d dnech. Do té doby budete moci své staré uživatelské jméno znovu získat.
-change_username_redirect_prompt.with_cooldown.one = Staré uživatelské jméno bude dostupné ostatním po %[1]d dni. Do té doby budete moci své staré uživatelské jméno znovu získat.
+change_username_redirect_prompt.with_cooldown.one = Staré uživatelské jméno bude dostupné ostatním po %[1]d dnu. Do té doby budete moci své staré uživatelské jméno znovu získat.
keep_pronouns_private = Zobrazovat zájmena pouze přihlášeným uživatelům
keep_pronouns_private.description = Toto nastavení skryje vaše zájmena před návštěvníky, kteří nejsou přihlášeni.
quota = Kvóta
@@ -1556,7 +1556,7 @@ issues.label_templates.info=Zatím nebyly vytvořeny žádné štítky. Vytvořt
issues.label_templates.helper=Vyberte přednastavené značky
issues.label_templates.use=Použít přednastavené štítky
issues.label_templates.fail_to_load_file=Nepodařilo se načíst soubor šablony popisku „%s“: %v
-issues.add_label=přidal/a %s štítek %s
+issues.add_label=přidal/a štítek %s %s
issues.add_labels=přidal/a %s štítky %s
issues.remove_label=odstranil/a %s štítek %s
issues.remove_labels=odstranil/a %s štítky %s
@@ -1579,7 +1579,7 @@ issues.remove_ref_at=`odstranil/a referenci %s %s`
issues.add_ref_at=`přidal/a referenci %s %s`
issues.delete_branch_at=`odstranil/a větev %s %s`
issues.filter_label=Štítek
-issues.filter_label_exclude=`Chcete-li vyloučit štítky, použijte alt
+ click/enter
`
+issues.filter_label_exclude=Chcete-li vyloučit štítky, použijte Alt + kliknutí
issues.filter_label_no_select=Všechny štítky
issues.filter_label_select_no_label=Bez štítku
issues.filter_milestone=Milník
@@ -1633,13 +1633,13 @@ issues.opened_by_fake=otevřeno %[1]s uživatelem %[2]s
issues.closed_by_fake=od %[2]s byl uzavřen %[1]s
issues.previous=Předchozí
issues.next=Další
-issues.open_title=Otevřeno
-issues.closed_title=Uzavřeno
+issues.open_title=Otevřené
+issues.closed_title=Uzavřené
issues.draft_title=Koncept
issues.num_comments_1=%d komentář
issues.num_comments=%d komentářů
issues.commented_at=`okomentoval/a %s`
-issues.delete_comment_confirm=Jste si jist, že chcete smazat tento komentář?
+issues.delete_comment_confirm=Opravdu chcete smazat tento komentář?
issues.context.copy_link=Kopírovat odkaz
issues.context.quote_reply=Citovat odpověď
issues.context.reference_issue=Odkázat v novém problému
@@ -1653,13 +1653,13 @@ issues.close_comment_issue=Zavřít s komentářem
issues.reopen_issue=Znovu otevřít
issues.reopen_comment_issue=Znovu otevřít s komentářem
issues.create_comment=Komentovat
-issues.closed_at=`uzavřel/a tento problém %[2]s`
-issues.reopened_at=`znovu otevřel/a tento problém %[2]s`
-issues.commit_ref_at=`odkázal/a na tento problém z revize %[2]s`
-issues.ref_issue_from=`odkázal/a na tento problém %[4]s %[2]s`
-issues.ref_pull_from=`odkázal/a na tuto žádost o sloučení %[4]s %[2]s`
-issues.ref_closing_from=`odkazoval/a na tento problém ze žádosti o sloučení %[4]s, která jej uzavře, %[2]s`
-issues.ref_reopening_from=`odkazoval/a na tento problém ze žádosti o sloučení %[4]s, která jej znovu otevře, %[2]s`
+issues.closed_at=`uzavřel/a tento problém %s`
+issues.reopened_at=`znovu otevřel/a tento problém %s`
+issues.commit_ref_at=`odkázal/a na tento problém z revize %s`
+issues.ref_issue_from=`odkázal/a na tento problém %[3]s %[1]s`
+issues.ref_pull_from=`odkázal/a na tuto žádost o sloučení %[3]s %[1]s`
+issues.ref_closing_from=`odkázal/a na tento problém ze žádosti o sloučení %[3]s, která jej uzavře, %[1]s`
+issues.ref_reopening_from=`odkázal/a na tento problém ze žádosti o sloučení %[3]s, která jej znovu otevře, %[1]s`
issues.ref_closed_from=`uzavřel/a tento problém %[4]s %[2]s`
issues.ref_reopened_from=`znovu otevřel/a tento problém %[4]s %[2]s`
issues.ref_from=`z %[1]s`
@@ -1763,7 +1763,7 @@ issues.error_modifying_due_date=Změna termínu dokončení selhala.
issues.error_removing_due_date=Odstranění termínu dokončení selhalo.
issues.push_commit_1=přidal/a %d revizi %s
issues.push_commits_n=přidal/a %d revize %s
-issues.force_push_codes=`vynucené nahrání %[1]s od %[2]s
do %[4]s
%[6]s`
+issues.force_push_codes=`vynutil/a nahrání %[1]s od %[2]s
do %[4]s
%[6]s`
issues.force_push_compare=Porovnat
issues.due_date_form=rrrr-mm-dd
issues.due_date_form_add=Přidat termín dokončení
@@ -1813,7 +1813,7 @@ issues.review.approve=schválil/a tyto změny %s
issues.review.comment=posoudil/a %s
issues.review.dismissed=zamítl/a posouzení uživatele %s %s
issues.review.dismissed_label=Zamítnuto
-issues.review.left_comment=zanechal komentář
+issues.review.left_comment=zanechal/a komentář
issues.review.content.empty=Je potřeba zanechat poznámku s uvedením požadované změny (požadovaných změn).
issues.review.reject=požádal/a o změny %s
issues.review.wait=byl/a požádán/a o posouzení %s
@@ -1966,8 +1966,8 @@ pulls.update_branch_success=Aktualizace větve byla úspěšná
pulls.update_not_allowed=Nemáte oprávnění aktualizovat větev
pulls.outdated_with_base_branch=Tato větev je zastaralá oproti základní větvi
pulls.close=Zavřít žádost o sloučení
-pulls.closed_at=`uzavřel/a tuto žádost o sloučení %[2]s`
-pulls.reopened_at=`znovu otevřel/a tuto žádost o sloučení %[2]s`
+pulls.closed_at=`uzavřel/a tuto žádost o sloučení %s`
+pulls.reopened_at=`znovu otevřel/a tuto žádost o sloučení %s`
pulls.cmd_instruction_hint=Zobrazit instrukce příkazové řádky
pulls.cmd_instruction_checkout_desc=Z vašeho repositáře projektu se podívejte na novou větev a vyzkoušejte změny.
pulls.cmd_instruction_merge_title=Sloučit
@@ -2758,7 +2758,7 @@ settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning = Tuto ak
settings.new_owner_blocked_doer = Nový majitel vás zablokoval.
settings.mirror_settings.pushed_repository = Odeslaný repozitář
settings.add_collaborator_blocked_our = Nepodařilo se přidat spolupracovníka, jelikož byl zablokován majitelem repozitáře.
-pulls.commit_ref_at = `se odkázal/a na tuto žádost o sloučení z revize %[2]s`
+pulls.commit_ref_at = `odkázal/a na tuto žádost o sloučení z revize %s`
settings.wiki_rename_branch_main = Normalizovat název větve wiki
settings.wiki_rename_branch_main_desc = Přejmenovat větev interně používanou pro wiki na „%s“. Tato změna je trvalá a nelze ji vrátit.
pulls.fast_forward_only_merge_pull_request = Pouze zrychlené
@@ -3058,7 +3058,7 @@ teams.invite.by=Pozvání od %s
teams.invite.description=Pro připojení k týmu klikněte na tlačítko níže.
follow_blocked_user = Tuto organizaci nemůžete sledovat, protože jste v ní zablokováni.
open_dashboard = Otevřít nástěnku
-settings.change_orgname_redirect_prompt.with_cooldown.one = Starý název organizace bude dostupný ostatním po %[1]d dni. Do té doby budete moci staré jméno znovu získat.
+settings.change_orgname_redirect_prompt.with_cooldown.one = Starý název organizace bude dostupný ostatním po %[1]d dnu. Do té doby budete moci staré jméno znovu získat.
settings.change_orgname_redirect_prompt.with_cooldown.few = Starý název organizace bude dostupný ostatním po %[1]d dnech. Do té doby budete moci starý název znovu získat.
[admin]
diff --git a/options/locale/locale_da.ini b/options/locale/locale_da.ini
index ea22f49e77..99b5789de3 100644
--- a/options/locale/locale_da.ini
+++ b/options/locale/locale_da.ini
@@ -1,6 +1,3 @@
-
-
-
[common]
home = Hjem
dashboard = Instrumentpanel
@@ -978,8 +975,8 @@ delete_with_all_comments = Din konto er yngre end %s. For at undgå spøgelsesko
delete_account_title = Slet brugerkonto
user_block_yourself = Du kan ikke blokere dig selv.
pronouns_custom_label = Brugerdefinerede stedord
-change_username_redirect_prompt.with_cooldown.one = Det gamle brugernavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dag, du kan stadig kræve det gamle brugernavn tilbage i nedkølingsperioden.
-change_username_redirect_prompt.with_cooldown.few = Det gamle brugernavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dage, du kan stadig kræve det gamle brugernavn tilbage i nedkølingsperioden.
+change_username_redirect_prompt.with_cooldown.one = Det gamle brugernavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dag, år. Du kan stadig kræve det gamle brugernavn tilbage i nedkølingsperioden.
+change_username_redirect_prompt.with_cooldown.few = Det gamle brugernavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dage, år. Du kan stadig kræve det gamle brugernavn tilbage i nedkølingsperioden.
keep_pronouns_private = Vis kun stedord til godkendte brugere
keep_pronouns_private.description = Dette vil skjule dine stedord for besøgende, der ikke er logget ind.
quota.applies_to_user = Følgende kvoteregler gælder for din konto
@@ -1520,15 +1517,15 @@ issues.add_labels = tilføjede %s etiketterne %s
issues.add_remove_labels = tilføjede %s og fjernede %s etiketter %s
issues.add_milestone_at = `føjede dette til %s milepælen %s`
issues.add_project_at = `føjede dette til %s- projektet %s`
-issues.ref_reopening_from = `henviste til dette problem fra en pull-anmodning %[4]s, der vil genåbne den, %[2]s`
+issues.ref_reopening_from = `henviste til dette problem fra en pull-anmodning %[3]s, der vil genåbne det, %[1]s`
issues.ref_closed_from = `lukkede dette problem %[4]s %[2 ]s`
issues.ref_reopened_from = `genåbnede dette problem %[4]s %[2 ]s`
issues.ref_from = `fra %[1]s`
issues.author = Forfatter
-issues.commit_ref_at = `henviste til dette problem fra en commit %[2]s`
-issues.ref_issue_from = `henviste til dette problem %[4]s %[2 ]s`
-issues.ref_pull_from = `henviste til denne pull-anmodning %[4]s %[ 2]s`
-issues.ref_closing_from = `henviste til dette problem fra en pull-anmodning %[4]s, der vil lukke det, %[2]s`
+issues.commit_ref_at = `henviste til dette problem fra en commit %s`
+issues.ref_issue_from = `henviste til dette problem %[3]s %[1]s`
+issues.ref_pull_from = `henviste til denne pull-anmodning %[3]s %[1]s`
+issues.ref_closing_from = `henviste til dette problem fra en pull-anmodning %[3]s, der vil lukke det, %[1]s`
issues.author.tooltip.issue = Denne bruger er forfatteren til dette problem.
issues.author.tooltip.pr = Denne bruger er forfatteren af denne pull-anmodning.
issues.role.owner = Ejer
@@ -1564,8 +1561,8 @@ issues.reaction.alt_add = Tilføj %[1]s reaktion til kommentar.
issues.context.menu = Kommentar menu
issues.reopen_comment_issue = Genåbner med kommentar
issues.create_comment = Kommentar
-issues.closed_at = `lukkede dette problem %[2]s`
-issues.reopened_at = `genåbnede dette problem %[2]s`
+issues.closed_at = `lukkede dette problem %s`
+issues.reopened_at = `genåbnede dette problem %s`
issues.remove_label = fjernede %s etiketten %s
issues.remove_labels = fjernede %s etiketterne %s
issues.change_project_at = `modificerede projektet fra %s til %s %s`
@@ -1582,7 +1579,7 @@ issues.change_ref_at = `ændret reference fra alt
+ klik/enter
for at ekskludere etiketter`
+issues.filter_label_exclude = Brug Alt + klik for at ekskludere etiketter
issues.filter_milestone = Milepæl
issues.filter_milestone_all = Alle milepæle
issues.filter_milestone_none = Ingen milepæle
@@ -1911,10 +1908,10 @@ pulls.editable_explanation = Denne pull-anmodning tillader redigeringer fra vedl
pulls.auto_merge_button_when_succeed = (Når kontroller lykkes)
pulls.status_checks_requested = Påkrævet
pulls.close = Luk pull anmodning
-pulls.commit_ref_at = `henviste til denne pull-anmodning fra en commit %[2]s`
+pulls.commit_ref_at = `henviste til denne pull-anmodning fra en commit %s`
pulls.cmd_instruction_hint = Se instruktionerne på kommandolinjen
-pulls.reopened_at = `genåbnede denne pull-anmodning %[2]s`
-pulls.closed_at = `lukkede denne pull-anmodning %[2]s`
+pulls.reopened_at = `genåbnede denne pull-anmodning %s`
+pulls.closed_at = `lukkede denne pull-anmodning %s`
pulls.cmd_instruction_checkout_desc = Fra dit projektdepot, tjek en ny gren og test ændringerne.
pulls.editable = Redigerbar
pulls.made_using_agit = AGit
@@ -2833,8 +2830,8 @@ team_permission_desc = Tilladelse
members.member = Medlem
settings.change_orgname_prompt = Bemærk: Ændring af organisationens navn vil også ændre din organisations URL og frigøre det gamle navn.
settings.change_orgname_redirect_prompt = Det gamle navn vil omdirigere, indtil det gøres krav på.
-settings.change_orgname_redirect_prompt.with_cooldown.one = Det gamle organisationsnavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dag, du kan stadig kræve det gamle navn tilbage i nedkølingsperioden.
-settings.change_orgname_redirect_prompt.with_cooldown.few = Det gamle organisationsnavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dage, du kan stadig kræve det gamle navn tilbage i .
+settings.change_orgname_redirect_prompt.with_cooldown.one = Det gamle organisationsnavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dag, år. Du kan stadig kræve det gamle navn tilbage i nedkølingsperioden.
+settings.change_orgname_redirect_prompt.with_cooldown.few = Det gamle organisationsnavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dage, år. Du kan stadig kræve det gamle navn tilbage i.
settings.update_avatar_success = Organisationens avatar er blevet opdateret.
members.public_helper = Gør skjult
members.private = Skjult
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index 829912b3cc..9f55f79fe9 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -251,12 +251,12 @@ db_schema_helper=Leer lassen, um den Datenbank-Standardwert („public“) zu ve
ssl_mode=SSL
path=Pfad
sqlite_helper=Dateipfad zur SQLite3-Datenbank.Alt
+ Klick/Enter
verwenden, um Labels auszuschließen`
+issues.filter_label_exclude=`Verwende Alt + Klick/Enter, um Labels auszuschließen`
issues.filter_label_no_select=Alle Labels
issues.filter_label_select_no_label=Kein Label
issues.filter_milestone=Meilenstein
@@ -1598,8 +1598,8 @@ issues.filter_type.all_issues=Alle Issues
issues.filter_type.assigned_to_you=Dir zugewiesen
issues.filter_type.created_by_you=Von dir erstellt
issues.filter_type.mentioning_you=Hat dich erwähnt
-issues.filter_type.review_requested=Review angefordert
-issues.filter_type.reviewed_by_you=Von dir gereviewt
+issues.filter_type.review_requested=Sichtung angefordert
+issues.filter_type.reviewed_by_you=Von dir gesichtet
issues.filter_sort=Sortieren
issues.filter_sort.latest=Neueste
issues.filter_sort.oldest=Älteste
@@ -1621,8 +1621,8 @@ issues.action_milestone=Meilenstein
issues.action_milestone_no_select=Kein Meilenstein
issues.action_assignee=Zuständig
issues.action_assignee_no_select=Niemand zuständig
-issues.action_check=Auswählen/Auswahl aufheben
-issues.action_check_all=Alles auswählen/Auswahl aufheben
+issues.action_check=Auswählen / Auswahl aufheben
+issues.action_check_all=Alles auswählen / Auswahl aufheben
issues.opened_by=%[1]s von %[3]s geöffnet
pulls.merged_by=von %[3]s wurde %[1]s zusammengeführt
pulls.merged_by_fake=von %[2]s %[1]s zusammengeführt
@@ -1651,13 +1651,13 @@ issues.close_comment_issue=Mit Kommentar schließen
issues.reopen_issue=Wieder öffnen
issues.reopen_comment_issue=Mit Kommentar wieder öffnen
issues.create_comment=Kommentieren
-issues.closed_at=`hat diesen Issue %[2]s geschlossen`
-issues.reopened_at=`hat dieses Issue %[2]s wieder geöffnet`
-issues.commit_ref_at=`hat dieses Issue %[2]s aus einem Commit referenziert`
-issues.ref_issue_from=`hat %[2]s auf dieses Issue verwiesen %[4]s`
-issues.ref_pull_from=`hat %[2]s auf diesen Pull-Request verwiesen %[4]s`
-issues.ref_closing_from=`hat %[2]s in einem Pull-Request %[4]s auf dieses Issue verwiesen, welcher es schließen wird`
-issues.ref_reopening_from=`hat %[2]s in einem Pull-Request %[4]s auf dieses Issue verwiesen, welcher es erneut öffnen wird`
+issues.closed_at=`hat dieses Issue %s geschlossen`
+issues.reopened_at=`hat dieses Issue %s wieder geöffnet`
+issues.commit_ref_at=`hat dieses Issue %s aus einem Commit referenziert`
+issues.ref_issue_from=`hat %[1]s auf dieses Issue verwiesen %[3]s`
+issues.ref_pull_from=`referenzierte diesen Pull-Request %[3]s %[1]s`
+issues.ref_closing_from=`referenzierte dieses Issue aus einem Pull-Request %[3]s der es schließen wird, %[1]s`
+issues.ref_reopening_from=`referenzierte dieses Issue aus einem Pull-Request %[3]s der es wieder öffnen wird, %[1]s`
issues.ref_closed_from=`hat dieses Issue %[4]s geschlossen %[2]s`
issues.ref_reopened_from=`hat dieses Issue %[4]s %[2]s wieder geöffnet`
issues.ref_from=`von %[1]s`
@@ -1673,12 +1673,12 @@ issues.role.first_time_contributor=Erstmaliger Mitwirkender
issues.role.first_time_contributor_helper=Dies ist der erste Beitrag dieses Benutzers zum Repository.
issues.role.contributor=Mitwirkender
issues.role.contributor_helper=Dieser Benutzer hat schon zuvor zu dem Repository beigetragen.
-issues.re_request_review=Review erneut anfordern
-issues.is_stale=Seit diesem Review gab es Änderungen an diesem PR
-issues.remove_request_review=Review-Anfrage entfernen
-issues.remove_request_review_block=Review-Anfrage kann nicht entfernt werden
-issues.dismiss_review=Review verwerfen
-issues.dismiss_review_warning=Bist du dir sicher, dass du dieses Review verwerfen willst?
+issues.re_request_review=Sichtung erneut anfordern
+issues.is_stale=Seit dieser Sichtung gab es Änderungen an diesem PR
+issues.remove_request_review=Sichtungsanfrage entfernen
+issues.remove_request_review_block=Sichtungsanfrage kann nicht entfernt werden
+issues.dismiss_review=Sichtung verwerfen
+issues.dismiss_review_warning=Bist du dir sicher, dass du diese Sichtung verwerfen willst?
issues.sign_in_require_desc=Anmelden, um an der Diskussion teilzunehmen.
issues.edit=Bearbeiten
issues.cancel=Abbrechen
@@ -1809,20 +1809,20 @@ issues.dependency.add_error_dep_not_same_repo=Beide Issues müssen sich im selbe
issues.review.self.approval=Du kannst nicht dein eigenen Pull-Request genehmigen.
issues.review.self.rejection=Du kannst keine Änderungen an deinem eigenen Pull-Request anfragen.
issues.review.approve=hat die Änderungen %s genehmigt
-issues.review.comment=hat %s gereviewt
+issues.review.comment=hat %s gesichtet
issues.review.dismissed=verwarf %ss Review %s
issues.review.dismissed_label=Verworfen
issues.review.left_comment=hat einen Kommentar hinterlassen
issues.review.content.empty=Du musst einen Kommentar hinterlassen, der die gewünschte(n) Änderung(en) beschreibt.
issues.review.reject=hat %s Änderungen angefragt
-issues.review.wait=wurde für ein Review %s angefragt
-issues.review.add_review_request=hat ein Review von %[1]s %[2]s angefragt
-issues.review.remove_review_request=hat die Aufforderung zum Review an %[1]s %[2]s entfernt
-issues.review.remove_review_request_self=hat das Review verweigert %s
+issues.review.wait=wurde für eine Sichtung von %s angefragt
+issues.review.add_review_request=hat eine Sichtung von %[1]s %[2]s angefragt
+issues.review.remove_review_request=hat die Sichtungsanfrage an %[1]s %[2]s entfernt
+issues.review.remove_review_request_self=hat die Sichtung %s verweigert
issues.review.pending=Ausstehend
issues.review.pending.tooltip=Dieser Kommentar ist derzeit nicht für andere Benutzer sichtbar. Um deine ausstehenden Kommentare einzureichen, wähle „%s“ -> „%s/%s/%s“ oben auf der Seite.
issues.review.review=Review
-issues.review.reviewers=Reviewer
+issues.review.reviewers=Sichter
issues.review.outdated=Veraltet
issues.review.outdated_description=Der Inhalt hat sich geändert, seit dieser Kommentar abgegeben wurde
issues.review.option.show_outdated_comments=Veraltete Kommentare anzeigen
@@ -1833,7 +1833,7 @@ issues.review.show_resolved=Erledigte anzeigen
issues.review.hide_resolved=Erledigte ausblenden
issues.review.resolve_conversation=Diskussion als „erledigt“ markieren
issues.review.un_resolve_conversation=Diskussion als „nicht erledigt“ markieren
-issues.review.resolved_by=markierte diese Unterhaltung als gelöst
+issues.review.resolved_by=markierte diese Unterhaltung als „erledigt“
issues.assignee.error=Aufgrund eines unerwarteten Fehlers konnten nicht alle Zuständigen hinzugefügt werden.
issues.reference_issue.body=Beschreibung
issues.content_history.deleted=gelöscht
@@ -1847,7 +1847,7 @@ issues.reference_link=Referenz: %s
compare.compare_base=Basis
compare.compare_head=vergleichen
-pulls.desc=Pull-Requests und Code-Reviews aktivieren.
+pulls.desc=Pull-Requests und Code-Sichtungen aktivieren.
pulls.new=Neuer Pull-Request
pulls.view=Pull-Request ansehen
pulls.compare_changes=Neuer Pull-Request
@@ -1856,7 +1856,7 @@ pulls.allow_edits_from_maintainers_desc=Nutzer mit Schreibzugriff auf den Basisb
pulls.allow_edits_from_maintainers_err=Aktualisieren fehlgeschlagen
pulls.compare_changes_desc=Wähle den Zielbranch, in das zusammengeführt werden soll, und den Quellbranch, von dem gepullt werden soll, aus.
pulls.has_viewed_file=Gesehen
-pulls.has_changed_since_last_review=Seit deinem letzten Review geändert
+pulls.has_changed_since_last_review=Seit deiner letzten Sichtung geändert
pulls.viewed_files_label=%[1]d / %[2]d Dateien betrachtet
pulls.expand_files=Alle Dateien ausklappen
pulls.collapse_files=Alle Dateien einklappen
@@ -1867,11 +1867,11 @@ pulls.switch_head_and_base=Head und Base vertauschen
pulls.filter_branch=Branch filtern
pulls.no_results=Keine Ergebnisse verfügbar.
pulls.show_all_commits=Alle Commits anzeigen
-pulls.show_changes_since_your_last_review=Zeige Änderungen seit deinem letzten Review
+pulls.show_changes_since_your_last_review=Zeige Änderungen seit deiner letzten Sichtung
pulls.showing_only_single_commit=Nur Änderungen aus Commit %[1]s werden angezeigt
pulls.showing_specified_commit_range=Zeige nur die Änderungen zwischen %[1]s..%[2]s
pulls.select_commit_hold_shift_for_range=Commit auswählen. Halte Shift + klicke, um eine Reihe auszuwählen
-pulls.review_only_possible_for_full_diff=Ein Review ist nur möglich, wenn das vollständige Diff angezeigt wird
+pulls.review_only_possible_for_full_diff=Eine Sichtung ist nur möglich, wenn der vollständige Diff angezeigt wird
pulls.filter_changes_by_commit=Nach Commit filtern
pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden.
pulls.nothing_to_compare_and_allow_empty_pr=Diese Branches sind gleich. Der Pull-Request wird leer sein.
@@ -1905,8 +1905,8 @@ pulls.required_status_check_failed=Einige erforderliche Prüfungen waren nicht e
pulls.required_status_check_missing=Einige erforderliche Prüfungen fehlen.
pulls.required_status_check_administrator=Als Administrator kannst du diesen Pull-Request weiterhin zusammenführen.
pulls.blocked_by_approvals=Dieser Pull-Request hat noch nicht genügend Genehmigungen. %d von %d Genehmigungen erteilt.
-pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Reviewer angefragt wurden.
-pulls.blocked_by_official_review_requests=Dieser Pull-Request ist blockiert, weil ihm die Genehmigung von einem oder mehreren offiziellen Reviewern fehlt.
+pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Sichter angefragt wurden.
+pulls.blocked_by_official_review_requests=Dieser Pull-Request ist blockiert, weil ihm die Genehmigung von einem oder mehreren offiziellen Sichtern fehlt.
pulls.blocked_by_outdated_branch=Dieser Pull-Request ist blockiert, da er veraltet ist.
pulls.blocked_by_changed_protected_files_1=Dieser Pull-Request ist blockiert, weil er eine geschützte Datei ändert:
pulls.blocked_by_changed_protected_files_n=Dieser Pull-Request ist blockiert, weil er geschützte Dateien ändert:
@@ -1919,14 +1919,14 @@ pulls.approve_count_1=%d Genehmigung
pulls.approve_count_n=%d Genehmigungen
pulls.reject_count_1=%d Änderungsanfrage
pulls.reject_count_n=%d Änderungsanfragen
-pulls.waiting_count_1=%d wartendes Review
-pulls.waiting_count_n=%d wartende Reviews
+pulls.waiting_count_1=%d wartende Sichtung
+pulls.waiting_count_n=%d wartende Sichtungen
pulls.wrong_commit_id=die Commit-ID muss eine Commit-ID auf dem Zielbranch sein
pulls.no_merge_desc=Dieser Pull-Request kann nicht zusammengeführt werden, da alle Repository-Merge-Optionen deaktiviert sind.
pulls.no_merge_helper=Aktiviere Mergeoptionen in den Repositoryeinstellungen oder führe den Pull-Request manuell zusammen.
pulls.no_merge_wip=Dieser Pull-Request kann nicht zusammengeführt werden, da er als „Work in Progress“ (in Bearbeitung) markiert ist.
-pulls.no_merge_not_ready=Dieser Pull-Request kann nicht zusammengeführt werden, überprüfe den Reviewstatus und die Statusprüfungen.
+pulls.no_merge_not_ready=Dieser Pull-Request kann nicht zusammengeführt werden, überprüfe den Sichtungsstatus und die Statusprüfungen.
pulls.no_merge_access=Du bist nicht berechtigt, diesen Pull-Request zusammenzuführen.
pulls.merge_pull_request=Merge-Commit erstellen
pulls.rebase_merge_pull_request=Rebasen und dann fast-forwarden
@@ -1962,8 +1962,8 @@ pulls.update_branch_success=Branch-Aktualisierung erfolgreich
pulls.update_not_allowed=Du hast keine Berechtigung, den Branch zu updaten
pulls.outdated_with_base_branch=Dieser Branch enthält nicht die neusten Commits des Basis-Branches
pulls.close=Pull-Request schließen
-pulls.closed_at=`hat diesen Pull-Request %[2]s geschlossen`
-pulls.reopened_at=`hat diesen Pull-Request %[2]s wieder geöffnet`
+pulls.closed_at=`hat diesen Pull-Request %s geschlossen`
+pulls.reopened_at=`hat diesen Pull-Request %s wieder geöffnet`
pulls.clear_merge_message=Merge-Nachricht löschen
pulls.clear_merge_message_hint=Das Löschen der Merge-Nachricht wird nur den Inhalt der Commit-Nachricht entfernen und generierte Git-Trailer wie „Co-Authored-By …“ erhalten.
@@ -2202,7 +2202,7 @@ settings.tracker_issue_style.numeric=Numerisch
settings.tracker_issue_style.alphanumeric=Alphanumerisch
settings.tracker_issue_style.regexp=Regulärer Ausdruck
settings.tracker_issue_style.regexp_pattern=Regulärer Ausdruck
-settings.tracker_issue_style.regexp_pattern_desc=Die erste gecapturte Gruppe wird statt {index}
verwendet.
+settings.tracker_issue_style.regexp_pattern_desc=Die erste gefundene Gruppe wird statt {index}
verwendet.
settings.tracker_url_format_desc=Du kannst die Platzhalter {user}
, {repo}
, {index}
für den Benutzernamen, den Namen des Repositorys und die Issue-Nummer verwenden.
settings.enable_timetracker=Zeiterfassung aktivieren
settings.allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen
@@ -2261,14 +2261,14 @@ settings.trust_model.collaborator=Mitarbeiter
settings.trust_model.collaborator.long=Mitarbeiter: Vertraue Signaturen von Mitarbeitern
settings.trust_model.collaborator.desc=Gültige Signaturen von Mitarbeitern dieses Projekts werden als „vertrauenswürdig“ markiert (egal, ob sie mit dem Committer übereinstimmen oder nicht). Andernfalls werden gültige Signaturen als „nicht vertrauenswürdig“ markiert, falls die Signatur zum Committer passt, ansonsten werden sie als „nicht übereinstimmend“ markiert.
settings.trust_model.committer=Committer
-settings.trust_model.committer.long=Committer: Vertraue Signaturen, die zu Committern passen (Dies stimmt mit GitHub überein und zwingt signierte Commits von Forgejo dazu, Forgejo als Committer zu haben)
+settings.trust_model.committer.long=Committer: Vertraue Signaturen, die zu Committern passen (dies stimmt mit GitHub überein und zwingt signierte Commits von Forgejo dazu, Forgejo als Committer zu haben)
settings.trust_model.committer.desc=Gültige Signaturen werden nur dann als „vertrauenswürdig“ gekennzeichnet, wenn sie mit ihrem Committer übereinstimmen. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Das führt dazu, dass Forgejo auf signierten Commits, bei denen der echte Committer als „Co-authored-by:“ oder „Co-committed-by:“ in der Beschreibung eingetragen wurde, als Committer gilt. Der Forgejo-Standard-Key muss zu einem Benutzer in der Datenbank passen.
settings.trust_model.collaboratorcommitter=Mitarbeiter+Committer
settings.trust_model.collaboratorcommitter.long=Mitarbeiter+Committer: Signaturen der Mitarbeiter vertrauen die mit dem Committer übereinstimmen
settings.trust_model.collaboratorcommitter.desc=Gültige Signaturen von Mitarbeitern dieses Projekts werden als „vertrauenswürdig“ markiert, wenn sie mit dem Committer übereinstimmen. Andernfalls werden gültige Signaturen als „nicht vertrauenswürdig“ markiert, wenn die Signatur mit dem Committer übereinstimmt. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Dies zwingt Forgejo, als Committer bei signierten Commits mit dem echten Committer als „Co-Authored-By:“ und „Co-Committed-By:“ im Commit zu markieren. Der Standard-Forgejo-Schlüssel muss mit einem Benutzer in der Datenbank übereinstimmen.
settings.wiki_delete=Wiki-Daten löschen
settings.wiki_delete_desc=Das Löschen von Wiki-Daten kann nicht rückgängig gemacht werden. Bitte sei vorsichtig.
-settings.wiki_delete_notices_1=– Dies löscht und deaktiviert das Wiki für %s.
+settings.wiki_delete_notices_1=– Dies wird das Repository-Wiki für %s dauerhaft löschen und deaktivieren.
settings.confirm_wiki_delete=Wiki-Daten löschen
settings.wiki_deletion_success=Repository-Wiki-Daten wurden gelöscht.
settings.delete=Dieses Repository löschen
@@ -2327,7 +2327,7 @@ settings.add_webhook_desc=Forgejo sendet eine POST
-Anfrage mit fest
settings.payload_url=Ziel-URL
settings.http_method=HTTP-Methode
settings.content_type=POST-Content-Type
-settings.secret=Secret
+settings.secret=Geheimnis
settings.slack_username=Benutzername
settings.slack_icon_url=Icon-URL
settings.slack_color=Farbe
@@ -2374,12 +2374,12 @@ settings.event_pull_request_milestone=Meilensteine
settings.event_pull_request_milestone_desc=Meilenstein hinzugefügt, entfernt oder bearbeitet.
settings.event_pull_request_comment=Kommentare
settings.event_pull_request_comment_desc=Pull-Request-Kommentar angelegt, geändert oder gelöscht.
-settings.event_pull_request_review=Reviews
-settings.event_pull_request_review_desc=Pull-Request genehmigt, abgelehnt oder Review-Kommentare hinterlassen.
+settings.event_pull_request_review=Sichtungen
+settings.event_pull_request_review_desc=Pull-Request genehmigt, abgelehnt oder Sichtungskommentare hinterlassen.
settings.event_pull_request_sync=Synchronisiert
settings.event_pull_request_sync_desc=Branch automatisch mit Zielbranch aktualisiert.
-settings.event_pull_request_review_request=Review-Anfragen
-settings.event_pull_request_review_request_desc=Überprüfung des Pull-Requests angefragt oder die Anfrage entfernt.
+settings.event_pull_request_review_request=Sichtungsanfragen
+settings.event_pull_request_review_request_desc=Pull-Request-Sichtung angefragt oder Sichtungsanfrage entfernt.
settings.event_pull_request_approvals=Genehmigungen zum Pull-Request
settings.event_pull_request_merge=Pull-Request-Merge
settings.event_package=Paket
@@ -2467,11 +2467,11 @@ settings.protect_status_check_matched=Übereinstimmung
settings.protect_invalid_status_check_pattern=Ungültiges Statusprüfungspattern: „%s“.
settings.protect_no_valid_status_check_patterns=Keine gültigen Statuscheck-Muster.
settings.protect_required_approvals=Erforderliche Genehmigungen
-settings.protect_required_approvals_desc=Erlaube das Zusammenführen des Pull-Requests nur mit genügend positiven Reviews.
+settings.protect_required_approvals_desc=Erlaube das Zusammenführen des Pull-Requests nur mit genügend positiven Sichtungen.
settings.protect_approvals_whitelist_enabled=Genehmigungen auf Benutzer oder Teams auf der Positivliste beschränken
-settings.protect_approvals_whitelist_enabled_desc=Nur Reviews von Benutzern oder Teams auf der Positivliste zählen zu den erforderlichen Genehmigungen. Existiert keine Positivliste, so zählen Reviews von jedem mit Schreibzugriff zu den erforderlichen Genehmigungen.
-settings.protect_approvals_whitelist_users=Nutzer, die reviewen dürfen
-settings.protect_approvals_whitelist_teams=Teams, die reviewen dürfen
+settings.protect_approvals_whitelist_enabled_desc=Nur Sichtungen von Benutzern oder Teams auf der Positivliste zählen zu den erforderlichen Genehmigungen. Existiert keine Positivliste, so zählen Sichtungen von jedem mit Schreibzugriff zu den erforderlichen Genehmigungen.
+settings.protect_approvals_whitelist_users=Nutzer, die sichten dürfen
+settings.protect_approvals_whitelist_teams=Teams, die sichten dürfen
settings.dismiss_stale_approvals=Entferne alte Genehmigungen
settings.dismiss_stale_approvals_desc=Wenn neue Commits gepusht werden, die den Inhalt des Pull-Requests ändern, werden alte Genehmigungen entfernt.
settings.require_signed_commits=Signierte Commits erforderlich
@@ -2489,10 +2489,10 @@ settings.remove_protected_branch_success=Branchschutzregel „%s“ wurde entfer
settings.remove_protected_branch_failed=Entfernen der Branchschutzregel „%s“ fehlgeschlagen.
settings.protected_branch_deletion=Branch-Schutz löschen
settings.protected_branch_deletion_desc=Wenn du den Branch-Schutz deaktivierst, können alle Nutzer mit Schreibrechten auf den Branch pushen. Fortfahren?
-settings.block_rejected_reviews=Zusammenführung bei abgelehnten Reviews blockieren
-settings.block_rejected_reviews_desc=Merge ist nicht möglich, wenn Änderungen durch offizielle Reviewer angefragt werden, auch wenn genügend Genehmigungen existieren.
-settings.block_on_official_review_requests=Merge bei offiziellen Review-Anfragen blockieren
-settings.block_on_official_review_requests_desc=Merge ist nicht möglich, wenn offizielle Review-Anfrangen vorliegen, selbst wenn genügend Genehmigungen existieren.
+settings.block_rejected_reviews=Zusammenführung bei abgelehnten Sichtungen blockieren
+settings.block_rejected_reviews_desc=Merge ist nicht möglich, wenn Änderungen durch offizielle Sichter angefragt werden, auch wenn genügend Genehmigungen existieren.
+settings.block_on_official_review_requests=Merge bei offiziellen Sichtungsanfragen blockieren
+settings.block_on_official_review_requests_desc=Merge ist nicht möglich, wenn offizielle Sichtungsanfrangen vorliegen, selbst wenn genügend Genehmigungen existieren.
settings.block_outdated_branch=Merge blockieren, wenn der Pull-Request veraltet ist
settings.block_outdated_branch_desc=Merge ist nicht möglich, wenn der Head-Branch hinter dem Basis-Branch ist.
settings.default_branch_desc=Wähle einen Standardbranch für Pull-Requests und Code-Commits:
@@ -2539,7 +2539,7 @@ settings.lfs_filelist=LFS-Dateien, die in diesem Repository gespeichert sind
settings.lfs_no_lfs_files=In diesem Repository sind keine LFS-Dateien gespeichert
settings.lfs_findcommits=Commits finden
settings.lfs_lfs_file_no_commits=Keine Commits für diese LFS-Datei gefunden
-settings.lfs_noattribute=Dieser Pfad hat nicht das sperrbare Attribut im Standard-Branch
+settings.lfs_noattribute=Dieser Pfad hat nicht das „lockable“-Attribut im Standard-Branch
settings.lfs_delete=LFS-Datei mit OID %s löschen
settings.lfs_delete_warning=Das Löschen einer LFS-Datei kann dazu führen, dass „Objekt existiert nicht“-Fehler beim Checkout auftreten. Bist du sicher?
settings.lfs_findpointerfiles=Pointer-Dateien finden
@@ -2580,8 +2580,8 @@ diff.show_unified_view=Gesamtansicht
diff.whitespace_button=Leerzeichen
diff.whitespace_show_everything=Alle Änderungen anzeigen
diff.whitespace_ignore_all_whitespace=Ignoriere Leerzeichen beim Zeilen vergleichen
-diff.whitespace_ignore_amount_changes=Ignoriere whitespace-Änderungen
-diff.whitespace_ignore_at_eol=Ignoriere EOL-whitespace-Änderungen
+diff.whitespace_ignore_amount_changes=Änderungen in der Anzahl der Leerzeichen und ähnlichen Zeichen ignorieren
+diff.whitespace_ignore_at_eol=Änderungen an den Leerzeichen und ähnlichen Zeichen am Zeilenende ignorieren
diff.stats_desc= %d geänderte Dateien mit %d neuen und %d gelöschten Zeilen
diff.stats_desc_file=%d Änderungen: %d Ergänzungen und %d Löschungen
diff.bin=BIN
@@ -2604,11 +2604,11 @@ diff.comment.placeholder=Kommentieren
diff.comment.markdown_info=Styling mit Markdown wird unterstützt.
diff.comment.add_single_comment=Einzelnen Kommentar hinzufügen
diff.comment.add_review_comment=Kommentar hinzufügen
-diff.comment.start_review=Review starten
+diff.comment.start_review=Sichtung starten
diff.comment.reply=Antworten
-diff.review=Review abschließen
-diff.review.header=Review einreichen
-diff.review.placeholder=Kommentar zum Review
+diff.review=Sichtung abschließen
+diff.review.header=Sichtung einreichen
+diff.review.placeholder=Kommentar zur Sichtung
diff.review.comment=Kommentieren
diff.review.approve=Genehmigen
diff.review.self_reject=Pull-Request-Autoren können keine Änderungen an ihren eigenen Pull-Request anfordern
@@ -2656,7 +2656,7 @@ release.edit_release=Release aktualisieren
release.delete_release=Release löschen
release.delete_tag=Tag löschen
release.deletion=Release löschen
-release.deletion_desc=Beim Entfernen wird ein Release nur von Forgejo gelöscht. Es betrifft weder den Git-Tag, noch den Inhalt des Repos oder seinen Änderungsverlauf. Fortfahren?
+release.deletion_desc=Beim Entfernen wird ein Release nur von Forgejo gelöscht. Es betrifft weder den Git-Tag noch den Inhalt des Repos oder seinen Änderungsverlauf. Fortfahren?
release.deletion_success=Das Release wurde gelöscht.
release.deletion_tag_desc=Löscht dieses Tag aus dem Projektarchiv. Repository-Inhalt und Verlauf bleiben unverändert. Fortfahren?
release.deletion_tag_success=Der Tag wurde gelöscht.
@@ -2666,7 +2666,7 @@ release.tag_name_protected=Der Tag-Name ist geschützt.
release.tag_already_exist=Dieser Tag-Name existiert bereits.
release.downloads=Downloads
release.download_count=Downloads: %s
-release.add_tag_msg=Titel und Beschreibung des Releases als Tag Nachricht verwenden.
+release.add_tag_msg=Titel und Beschreibung des Releases als Tag-Nachricht verwenden.
release.add_tag=Tag erstellen
release.releases_for=Releases für %s
release.tags_for=Tags für %s
@@ -2766,8 +2766,8 @@ wiki.cancel = Abbrechen
settings.wiki_globally_editable = Allen erlauben, das Wiki zu bearbeiten
settings.protect_branch_name_pattern_desc = Geschützte Branch-Namens-Patterns. Siehe die Dokumentation für Pattern-Syntax. Beispiele: main, release/**
settings.ignore_stale_approvals = Abgestandene Genehmigungen ignorieren
-settings.ignore_stale_approvals_desc = Genehmigungen, welche für ältere Commits gemacht wurden (abgestandene Reviews), nicht in die Gesamtzahl der Genehmigung des PRs mitzählen. Irrelevant, falls abgestandene Reviews bereits verworfen werden.
-pulls.commit_ref_at = `hat sich auf diesen Pull-Request von einem Commit %[2]s bezogen`
+settings.ignore_stale_approvals_desc = Genehmigungen, welche für ältere Commits gemacht wurden (abgestandene Sichtungen), nicht in die Gesamtzahl der Genehmigung des PRs mitzählen. Irrelevant, falls abgestandene Sichtungen bereits verworfen werden.
+pulls.commit_ref_at = `referenzierte diesen Pull-Request aus einem Commit %s`
pulls.fast_forward_only_merge_pull_request = Nur Fast-forward
pulls.cmd_instruction_checkout_desc = Checke einen neuen Branch aus deinem Projekt-Repository aus und teste die Änderungen.
pulls.cmd_instruction_merge_title = Zusammenführen
@@ -2782,7 +2782,7 @@ activity.navbar.contributors = Mitwirkende
contributors.contribution_type.deletions = Löschungen
contributors.contribution_type.additions = Einfügungen
contributors.contribution_type.filter_label = Art des Beitrags:
-vendored = Vendored
+vendored = Gevendort
activity.navbar.pulse = Puls
pulls.made_using_agit = AGit
settings.confirmation_string = Bestätigungsstring
@@ -2795,7 +2795,7 @@ pulls.merged_title_desc_one = hat %[1]d Commit von %[2]s
nach %[2]s
nach %[3]s
zusammenführen
open_with_editor = Öffnen mit %s
commits.search_branch = Dieser Branch
-pulls.ready_for_review = Bereit zum Review?
+pulls.ready_for_review = Bereit zur Sichtung?
settings.rename_branch_failed_protected = Branch %s kann nicht umbenannt werden, weil er ein geschützter Branch ist.
editor.commit_id_not_matching = Die Datei wurde geändert, während du sie bearbeitet hast. Committe in einen neuen Branch, dann führe einen Merge durch.
editor.push_out_of_date = Der Push scheint veraltet zu sein.
@@ -2824,7 +2824,7 @@ settings.sourcehut_builds.secrets_helper = Dem Job zugriff auf die Build-Geheimn
settings.web_hook_name_sourcehut_builds = SourceHut-Builds
settings.graphql_url = GraphQL-URL
settings.matrix.room_id_helper = Die Raum-ID kann über den Element-Webclient ermittelt werden: Raumeinstellungen > erweitert > interne Raum-ID. Beispielsweise %s.
-settings.sourcehut_builds.access_token_helper = Zugangstoken, der die JOBS:RW-Freigabe hat. Generiere auf meta.sr.ht einen builds.sr.ht-Token oder einen builds.sr.ht-Token mit Zugriff auf die Secrets.
+settings.sourcehut_builds.access_token_helper = Zugangstoken, der die JOBS:RW-Freigabe hat. Generiere auf meta.sr.ht einen builds.sr.ht-Token oder einen builds.sr.ht-Token mit Zugriff auf die Geheimnisse.
settings.matrix.access_token_helper = Es wird empfohlen, hierfür ein dediziertes Matrix-Konto anzulegen. Der Zugangstoken kann in einem Inkognito-Tab über den Element-Webclient geholt werden: Benutzermenü (oben links) > alle Einstellungen > Hilfe & Info > erweitert > Zugriffstoken (direkt unter der Heim-Server-URL). Schließe dann den Inkognito-Tab (Abmelden würde den Token ungültig machen).
release.hide_archive_links = Automatisch generierte Archive verstecken
release.hide_archive_links_helper = Verstecke automatisch generierte Quellcodearchive für diesen Release. Zum Beispiel, wenn du deine eigenen hochlädst.
@@ -2873,9 +2873,9 @@ mirror_use_ssh.not_available = SSH-Authentifizierung ist nicht verfügbar.
issues.new.assign_to_me = Mir selbst zuweisen
issues.all_title = Alle
settings.discord_icon_url.exceeds_max_length = Die Icon-URL darf eine Länge von 2048 Zeichen nicht überschreiten
-issues.review.add_review_requests = hat Reviews von %[1]s %[2]s angefragt
-issues.review.remove_review_requests = hat Aufforderungen zum Review an %[1]s %[2]s entfernt
-issues.review.add_remove_review_requests = hat Reviews von %[1]s angefragt und hat die Aufforderungen zum Review an %[2]s %[3]s entfernt
+issues.review.add_review_requests = hat Sichtungen von %[1]s %[2]s angefragt
+issues.review.remove_review_requests = hat die Sichtungsanfragen an %[1]s %[2]s entfernt
+issues.review.add_remove_review_requests = hat Sichtungen von %[1]s angefragt und die Sichtungsanfragen an %[2]s %[3]s entfernt
pulls.delete_after_merge.head_branch.is_default = Der Head-Branch, den du löschen willst, ist der Standardbranch und kann nicht gelöscht werden.
pulls.delete_after_merge.head_branch.is_protected = Der Head-Branch, den du löschen willst, ist ein geschützter Branch und kann nicht gelöscht werden.
pulls.delete_after_merge.head_branch.insufficient_branch = Du hast keine Erlaubnis, den Head-Branch zu löschen.
@@ -2883,9 +2883,9 @@ issues.filter_sort.relevance = Relevanz
diff.git-notes.add = Anmerkung hinzufügen
diff.git-notes.remove-header = Anmerkung entfernen
diff.git-notes.remove-body = Diese Anmerkung wird entfernt.
-issues.num_reviews_one = %d Review
+issues.num_reviews_one = %d Sichtung
issues.summary_card_alt = Zusammenfassung eines Issues mit dem Titel „%s“ im Repository %s
-issues.num_reviews_few = %d Reviews
+issues.num_reviews_few = %d Sichtungen
editor.add_tmpl.filename = Dateiname
settings.default_update_style_desc = Standard-Aktualisierungsart um Pull-Requests zu aktualisieren, die hinter dem Base-Branch sind.
new_advanced = Erweiterte Einstellungen
@@ -2902,7 +2902,7 @@ issues.reaction.alt_add = Füge %[1]s Reaktion zum Kommentar hinzu.
issues.reaction.alt_remove = Entferne %[1]s Reaktion von diesem Kommentar.
summary_card_alt = Zusammenfassungskarte des Repositorys %s
release.summary_card_alt = Übersichtskarte eines Releases mit dem Titel „%s“ im Repository %s
-archive.pull.noreview = Dieses Repository ist archiviert. Pull-Requests können nicht gereviewt werden.
+archive.pull.noreview = Dieses Repository ist archiviert. Pull-Requests können nicht gesichtet werden.
editor.commit_email = Commit-E-Mail
commits.view_single_diff = Änderungen an dieser Datei, die in diesem Commit eingeführt wurden, betrachten
pulls.editable = Bearbeitbar
@@ -2922,7 +2922,7 @@ settings.event_action_success_desc = Action-Run war erfolgreich.
settings.event_action_failure = Fehlschlag
settings.event_action_success = Erfolg
settings.event_header_action = Action-Run-Ereignisse
-settings.event_action_recover_desc = Action-Run war erfolgreich, nachdem der letzte Action-Run im selben Arbeitsablauf fehlgeschlagen ist.
+settings.event_action_recover_desc = Action-Run war erfolgreich, nachdem der letzte Action-Run im selben Workflow fehlgeschlagen ist.
settings.event_action_recover = Wiederherstellen
issues.filter_type.all_pull_requests = Alle Pull-Requests
@@ -3061,8 +3061,8 @@ teams.invite.by=Von %s eingeladen
teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten.
follow_blocked_user = Du kannst dieser Organisation nicht folgen, weil diese Organisation dich blockiert hat.
open_dashboard = Übersicht öffnen
-settings.change_orgname_redirect_prompt.with_cooldown.one = Der alte Organisationsname ist nach einer Abkühldauer von einem Tag wieder für alle verfügbar. Du kannst den alten Namen während dieser Abkühldauer erneut beanspruchen.
-settings.change_orgname_redirect_prompt.with_cooldown.few = Der alte Organisationsname ist nach einer Abkühldauer von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Namen während dieser Abkühldauer erneut beanspruchen.
+settings.change_orgname_redirect_prompt.with_cooldown.one = Der alte Organisationsname ist nach einer Schutzzeit von einem Tag wieder für alle verfügbar. Du kannst den alten Namen während dieser Schutzzeit erneut beanspruchen.
+settings.change_orgname_redirect_prompt.with_cooldown.few = Der alte Organisationsname ist nach einer Schutzzeit von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Namen während dieser Schutzzeit erneut beanspruchen.
[admin]
dashboard=Übersicht
@@ -3116,7 +3116,7 @@ dashboard.repo_health_check=Healthchecks für alle Repositorys ausführen
dashboard.check_repo_stats=Überprüfe alle Repository-Statistiken
dashboard.archive_cleanup=Alte Repository-Archive löschen
dashboard.deleted_branches_cleanup=Gelöschte Branches bereinigen
-dashboard.update_migration_poster_id=Migration Poster-IDs updaten
+dashboard.update_migration_poster_id=Migrations-Poster-IDs aktualisieren
dashboard.git_gc_repos=Garbage-Collection für alle Repositorys ausführen
dashboard.resync_all_sshkeys=Die Datei „.ssh/authorized_keys“ mit Forgejo-SSH-Schlüsseln aktualisieren.
dashboard.resync_all_sshprincipals=Aktualisiere die Datei „.ssh/authorized_principals“ mit Forgejo-SSH-Principals.
@@ -3159,7 +3159,7 @@ dashboard.delete_old_actions=Alle alten Aktivitäten aus der Datenbank löschen
dashboard.delete_old_actions.started=Löschen aller alten Aktivitäten aus der Datenbank gestartet.
dashboard.update_checker=Update-Checker
dashboard.delete_old_system_notices=Alle alten Systemmeldungen aus der Datenbank löschen
-dashboard.gc_lfs=Garbage-Collection für LFS Meta-Objekte ausführen
+dashboard.gc_lfs=Garbage-Collection für LFS-Meta-Objekte ausführen
dashboard.stop_zombie_tasks=Zombie-Actions-Aufgaben stoppen
dashboard.stop_endless_tasks=Endlose Actions-Aufgaben stoppen
dashboard.cancel_abandoned_jobs=Aufgegebene Actions-Jobs abbrechen
@@ -3335,7 +3335,7 @@ auths.pam_email_domain=PAM-E-Mail-Domain (optional)
auths.oauth2_provider=OAuth2-Anbieter
auths.oauth2_icon_url=Symbol-URL
auths.oauth2_clientID=Client-ID (Schlüssel)
-auths.oauth2_clientSecret=Client-Secret
+auths.oauth2_clientSecret=Client-Geheimnis
auths.openIdConnectAutoDiscoveryURL=OpenID-Connect-Auto-Discovery-URL
auths.oauth2_use_custom_url=Benutzerdefinierte URLs anstelle von Standard-URLs verwenden
auths.oauth2_tokenURL=Token-URL
@@ -3343,14 +3343,14 @@ auths.oauth2_authURL=Authorisierungs-URL
auths.oauth2_profileURL=Profil-URL
auths.oauth2_emailURL=E-Mail-URL
auths.skip_local_two_fa=Lokale 2FA überspringen
-auths.skip_local_two_fa_helper=Leer lassen bedeutet, dass lokale User die 2FA immer noch bestehen müssen, um sich anzumelden
+auths.skip_local_two_fa_helper=Das Leerlassen bedeutet, dass lokale User die 2FA immer noch bestehen müssen, um sich anzumelden
auths.oauth2_tenant=Inhaber
auths.oauth2_scopes=Zusätzliche Bereiche
auths.oauth2_required_claim_name=Benötigter Claim-Name
auths.oauth2_required_claim_name_helper=Setze diesen Namen, damit Nutzer aus dieser Quelle sich nur anmelden dürfen, wenn sie einen Claim mit diesem Namen besitzen
auths.oauth2_required_claim_value=Benötigter Claim-Wert
auths.oauth2_required_claim_value_helper=Setze diesen Wert, damit Nutzer aus dieser Quelle sich nur anmelden dürfen, wenn sie einen Claim mit diesem Namen und Wert besitzen
-auths.oauth2_group_claim_name=Claim-Name, der Gruppennamen für diese Quelle angibt. (Optional)
+auths.oauth2_group_claim_name=Claim-Name, der Gruppennamen für diese Quelle angibt (optional).
auths.oauth2_admin_group=Gruppen-Claim-Wert für Administratoren (optional – erfordert Claim-Namen oben).
auths.oauth2_restricted_group=Gruppen-Claim-Wert für eingeschränkte User. (Optional – erfordert Claim-Namen oben)
auths.oauth2_map_group_to_team=Gruppen aus OAuth-Claims den Organisationsteams zuordnen (optional – oben muss der Name des Claims angegeben werden).
@@ -3395,7 +3395,7 @@ auths.still_in_used=Diese Authentifizierungsquelle wird noch verwendet. Bearbeit
auths.deletion_success=Die Authentifizierungsquelle „%s“ wurde gelöscht.
auths.login_source_exist=Die Authentifizierungsquelle „%s“ existiert bereits.
auths.login_source_of_type_exist=Eine Authentifizierungart dieses Typs existiert bereits.
-auths.unable_to_initialize_openid=OpenID Connect Provider konnte nicht initialisiert werden: %s
+auths.unable_to_initialize_openid=Provider für OpenID Connect konnte nicht initialisiert werden: %s
auths.invalid_openIdConnectAutoDiscoveryURL=Ungültige Auto-Discovery-URL (dies muss eine gültige URL sein, die mit http:// oder https:// beginnt)
config.server_config=Serverkonfiguration
@@ -3526,7 +3526,7 @@ config.git_pull_timeout=Zeitlimit für Pull
config.git_gc_timeout=Zeitlimit für GC
config.log_config=Protokollierungs-Konfiguration
-config.logger_name_fmt=Logger: %s
+config.logger_name_fmt=Protokollierer: %s
config.disabled_logger=Deaktiviert
config.access_log_mode=Zugriffsprotokoll-Modus
config.access_log_template=Zugriffsprotokoll-Vorlage
@@ -3650,7 +3650,7 @@ mirror_sync_delete=hat die Referenz des Spiegels %[2]s
in %[3]s#%[2]s genehmigt`
reject_pull_request=`schlug Änderungen für %[3]s#%[2]s vor`
publish_release=`veröffentlichte Release %[4]s in %[3]s`
-review_dismissed=`verwarf das Review von %[4]s in %[3]s#%[2]s`
+review_dismissed=`verwarf die Sichtung von %[4]s in %[3]s#%[2]s`
review_dismissed_reason=Grund:
create_branch=legte den Branch %[3]s in %[4]s an
starred_repo=favorisierte %[2]s
@@ -3765,9 +3765,9 @@ conda.registry=Richte diese Registry als Conda-Repository in deiner .conda
conda.install=Um das Paket mit Conda zu installieren, führe den folgenden Befehl aus:
container.details.type=Abbildtyp
container.details.platform=Plattform
-container.pull=Downloade das Container-Image aus der Kommandozeile:
+container.pull=Lade das Container-Image von der Kommandozeile aus herunter:
container.digest=Prüfsumme
-container.multi_arch=Betriebsystem / Architektur
+container.multi_arch=Betriebsystem/Architektur
container.layers=Abbildebenen
container.labels=Labels
container.labels.key=Schlüssel
@@ -3781,7 +3781,7 @@ debian.repository=Repository-Informationen
debian.repository.distributions=Distributionen
debian.repository.components=Komponenten
debian.repository.architectures=Architekturen
-generic.download=Downloade das Paket aus der Kommandozeile:
+generic.download=Lade das Paket mit der Kommandozeile herunter:
go.install=Installiere das Paket über die Kommandozeile:
helm.registry=Diese Paketverwaltung über die Kommandozeile einrichten:
helm.install=Nutze folgenden Befehl, um das Paket zu installieren:
@@ -3813,10 +3813,10 @@ rubygems.install=Um das Paket mit gem zu installieren, führe den folgenden Befe
rubygems.install2=oder füg es zum Gemfile hinzu:
rubygems.dependencies.runtime=Laufzeitabhängigkeiten
rubygems.dependencies.development=Entwicklungsabhängigkeiten
-rubygems.required.ruby=Benötigt Ruby Version
-rubygems.required.rubygems=Benötigt RubyGem Version
+rubygems.required.ruby=Benötigt Ruby-Version
+rubygems.required.rubygems=Benötigt RubyGem-Version
swift.registry=Diese Registry über die Kommandozeile einrichten:
-swift.install=Füge das Paket deiner Package.swift
Datei hinzu:
+swift.install=Füge das Paket deiner Package.swift
-Datei hinzu:
swift.install2=und führe den folgenden Befehl aus:
vagrant.install=Um eine Vagrant-Box hinzuzufügen, führe den folgenden Befehl aus:
settings.link=Dieses Paket einem Repository zuweisen
@@ -3892,19 +3892,19 @@ alt.repository.architectures = Architekturen
alt.repository.multiple_groups = Dieses Paket ist in verschiedenen Gruppen verfügbar.
[secrets]
-secrets=Secrets
-description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden.
-none=Noch keine Secrets vorhanden.
-creation=Secret hinzufügen
+secrets=Geheimnisse
+description=Geheimnisse werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden.
+none=Noch keine Geheimnisse vorhanden.
+creation=Geheimnis hinzufügen
creation.name_placeholder=Groß-/Kleinschreibung wird ignoriert, nur alphanumerische Zeichen oder Unterstriche, darf nicht mit GITEA_ oder GITHUB_ beginnen
creation.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen.
-creation.success=Das Secret „%s“ wurde hinzugefügt.
-creation.failed=Secret konnte nicht hinzugefügt werden.
-deletion=Secret entfernen
-deletion.description=Das Entfernen eines Secrets kann nicht rückgängig gemacht werden. Fortfahren?
-deletion.success=Das Secret wurde entfernt.
-deletion.failed=Secret konnte nicht entfernt werden.
-management=Secrets verwalten
+creation.success=Das Geheimnis „%s“ wurde hinzugefügt.
+creation.failed=Geheimnis konnte nicht hinzugefügt werden.
+deletion=Geheimnis entfernen
+deletion.description=Das Entfernen eines Geheimnisses kann nicht rückgängig gemacht werden. Fortfahren?
+deletion.success=Das Geheimnis wurde entfernt.
+deletion.failed=Geheimnis konnte nicht entfernt werden.
+management=Geheimnisse verwalten
[actions]
actions=Actions
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 29085aebf1..41c55beb11 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -1626,13 +1626,13 @@ issues.close_comment_issue=Αποστολή σχολίου και κλείσιμ
issues.reopen_issue=Ανοίξτε ξανά
issues.reopen_comment_issue=Αποστολή σχολίου και επανάνοιγμα ζητήματος
issues.create_comment=Προσθήκη Σχολίου
-issues.closed_at=`αυτό το ζήτημα έκλεισε %[2]s`
-issues.reopened_at=`ξανά άνοιξε αυτό το ζήτημα %[2]s`
-issues.commit_ref_at=`αναφορά σε αυτό το ζήτημα από την παραπομπή %[2]s`
-issues.ref_issue_from=`αναφέρθηκε σε αυτό το ζήτημα %[4]s %[2]s`
-issues.ref_pull_from=`αναφέρθηκε σε αυτό το pull request %[4]s %[2]s`
-issues.ref_closing_from=`ανέφερε αυτό το ζήτημα σε ένα pull request %[4]s που στοχεύει να κλείσει το ζήτημα %[2]s`
-issues.ref_reopening_from=`αναφέρθηκε σε αυτό το ζήτημα σε ένα pull request %[4]s που θα ξαναανοίξει αυτό το ζήτημα %[2]s`
+issues.closed_at=`αυτό το ζήτημα έκλεισε %s`
+issues.reopened_at=`ξανά άνοιξε αυτό το ζήτημα %s`
+issues.commit_ref_at=`αναφορά σε αυτό το ζήτημα από την παραπομπή %s`
+issues.ref_issue_from=`αναφέρθηκε σε αυτό το ζήτημα %[3]s %[1]s`
+issues.ref_pull_from=`αναφέρθηκε σε αυτό το pull request %[3]s %[1]s`
+issues.ref_closing_from=`ανέφερε αυτό το ζήτημα σε ένα pull request %[3]s που στοχεύει να κλείσει το ζήτημα %[1]s`
+issues.ref_reopening_from=`αναφέρθηκε σε αυτό το ζήτημα σε ένα pull request %[3]s που θα ξαναανοίξει αυτό το ζήτημα %[1]s`
issues.ref_closed_from=`έκλεισε αυτό το ζήτημα %[4]s %[2]s`
issues.ref_reopened_from=`άνοιξε ξανά αυτό το ζήτημα %[4]s %[2]s`
issues.ref_from=`από %[1]s`
@@ -1939,8 +1939,8 @@ pulls.update_branch_success=Η ενημέρωση του κλάδου ήταν
pulls.update_not_allowed=Δεν επιτρέπεται να ενημερώσετε τον κλάδο
pulls.outdated_with_base_branch=Αυτός ο κλάδος δεν είναι ενημερωμένος με τον βασικό κλάδο
pulls.close=Κλείσιμο pull request
-pulls.closed_at=`έκλεισε αυτό το pull request %[2]s`
-pulls.reopened_at=`άνοιξε ξανά αυτό το pull request %[2]s`
+pulls.closed_at=`έκλεισε αυτό το pull request %s`
+pulls.reopened_at=`άνοιξε ξανά αυτό το pull request %s`
pulls.cmd_instruction_hint=Προβολή οδηγιών γραμμής εντολών
pulls.cmd_instruction_checkout_title=Έλεγχος
pulls.cmd_instruction_checkout_desc=Από το repository του έργου σας, ελέγξτε έναν νέο κλάδο και δοκιμάστε τις αλλαγές.
@@ -2720,7 +2720,7 @@ settings.new_owner_blocked_doer = Ο νέος κάτοχος του αποθετ
settings.enter_repo_name = Γράψτε το όνομα του κατόχου και του αποθετηρίου ακριβώς όπως το βλέπετε:
settings.confirmation_string = Κείμενο επιβεβαίωσης
settings.units.overview = Επισκόπηση
-pulls.commit_ref_at = `ανέφερε το pull request στο commit %[2]s`
+pulls.commit_ref_at = `ανέφερε το pull request στο commit %s`
contributors.contribution_type.filter_label = Είδος συνεισφοράς:
settings.wiki_rename_branch_main_notices_1 = Αυτή η ενέργεια ΔΕΝ αναιρείται.
activity.navbar.contributors = Συνεισφέροντες
@@ -3939,12 +3939,12 @@ submodule=Υπομονάδα
[search]
code_search_unavailable = Η αναζήτηση κώδικα δεν είναι επί του παρόντος διαθέσιμη. Παρακαλώ επικοινωνήστε με τον διαχειριστή σας.
keyword_search_unavailable = Η αναζήτηση με την χρήση λέξεων-κλειδιών δεν είναι επί του παρόντος διαθέσιμη. Παρακαλώ επικοινωνήστε με τον διαχειριστή σας.
-runner_kind = Αναζήτηση runner...
+runner_kind = Αναζήτηση runner…
code_search_by_git_grep = Για την αναζήτηση κώδικα, χρησιμοποιείται η εντολή «git grep». Ίσως να παρουσιαστούν καλύτερα αποτελέσματα, αν ο διαχειριστής σας ενεργοποιήσει ένα ευρετήριο για αποθετήρια («Repository Indexer»).
package_kind = Αναζήτηση πακέτων…
-project_kind = Αναζήτηση έργων...
+project_kind = Αναζήτηση έργων…
branch_kind = Αναζήτηση κλάδων…
-commit_kind = Αναζήτηση commit...
+commit_kind = Αναζήτηση commit…
no_results = Δεν βρέθηκαν κατάλληλα αποτελέσματα.
search = Αναζήτηση…
type_tooltip = Είδος αναζήτησης
@@ -3958,8 +3958,8 @@ org_kind = Αναζήτηση οργανισμών…
team_kind = Αναζήτηση ομαδών…
code_kind = Αναζήτηση κώδικα…
exact_tooltip = Να συμπεριληφθούν μόνο αποτελέσματα που ταιριάζουν με τον όρο αναζήτησης
-issue_kind = Αναζήτηση ζητημάτων...
-pull_kind = Αναζήτηση pull...
+issue_kind = Αναζήτηση ζητημάτων…
+pull_kind = Αναζήτηση pull…
exact = Ακριβής
milestone_kind = Αναζήτηση ορόσημων...
union = Ένωση
diff --git a/options/locale/locale_eo.ini b/options/locale/locale_eo.ini
index 6393765d63..5a06120e9e 100644
--- a/options/locale/locale_eo.ini
+++ b/options/locale/locale_eo.ini
@@ -630,7 +630,7 @@ account = Konto
ssh_gpg_keys = SSH / GPG-ŝlosiloj
twofa_disable = Malaktivigi duoblan aŭtentikigon
twofa_enroll = Ŝalti duoblan aŭtentikigon
-orgs = Mastrumi organizaĵojn
+orgs = Organizaĵoj
blocked_users = Blokitaj uzantoj
profile = Profilo
ui = Haŭto
@@ -686,7 +686,7 @@ verify_ssh_key_success = SSH-ŝlosilo «%s» jam konfirmiĝis.
edit_oauth2_application = Redakti OAuth2-programon
gpg_key_deletion = Forigi GPG-ŝlosilon
gpg_key_matched_identities = Akordaj identecoj:
-manage_themes = Elekti implicitan haŭton
+manage_themes = Defaŭlta temo
ssh_key_deletion = Forigi SSH-ŝlosilon
key_state_desc = Ĉi tiu ŝlosilo uziĝis dum la pasintaj 7 tagoj
valid_forever = Validos dumĉiame
@@ -700,7 +700,7 @@ primary = Ĉefa
ssh_disabled = SSH malaktivigita
update_avatar_success = Via profilbildo konserviĝis.
keep_email_private = Kaŝi retpoŝtadreson
-manage_openid = Mastrumi OpenID-adresojn
+manage_openid = OpenID-adresoj
delete_current_avatar = Forigi nunan profilbildon
email_preference_set_success = Retpoŝta prefero konserviĝis sukcese.
permissions_access_all = Ĉiu (publika, privata, kaj limigita)
@@ -884,9 +884,9 @@ commit_kind = Serĉi enmetojn…
no_results = Ne trovis kongruantajn rezultojn.
exact = Ĝusta
exact_tooltip = Inkluzivas nur rezultojn kongruantajn kun la ĝustaj serĉoterminoj
-issue_kind = Serĉi erarojn...
+issue_kind = Serĉi erarojn…
regexp_tooltip = Interpretas la serĉoterminoj kiel regulesprimo
fuzzy = Svaga
branch_kind = Serĉi disbranĉigojn…
-runner_kind = Serĉi rulantojn...
-pull_kind = Serĉi tirpetojn...
\ No newline at end of file
+runner_kind = Serĉi rulantojn…
+pull_kind = Serĉi tirpetojn…
\ No newline at end of file
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index f912409cc9..c783b1605b 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -740,7 +740,7 @@ avatar=Avatar
ssh_gpg_keys=Claves SSH / GPG
social=Redes sociales
applications=Aplicaciones
-orgs=Administrar organizaciones
+orgs=Organizaciones
repos=Repositorios
delete=Eliminar cuenta
twofa=Autenticación de dos factores (TOTP)
@@ -1075,8 +1075,8 @@ keep_pronouns_private = Mostrar pronombres solo a personas autenticadas
storage_overview = Resumen del almacenamiento
quota.sizes.assets.artifacts = Artefactos
quota.sizes.assets.attachments.releases = Archivos adjuntos del lanzamiento
-change_username_redirect_prompt.with_cooldown.few = El antiguo nombre de usuario estará disponible para todos después un periodo de tiempo de espera de %[1]d días, aún puedes reclamar el antiguo nombre de usuario durante el periodo de tiempo de espera.
-change_username_redirect_prompt.with_cooldown.one = El antiguo nombre de usuario estará disponible para todos después un periodo de tiempo de espera de %[1]d día, aún puedes reclamar el antiguo nombre de usuario durante el periodo de tiempo de espera.
+change_username_redirect_prompt.with_cooldown.few = El antiguo nombre de usuario estará disponible para todos después un periodo de tiempo de espera de %[1]d días. Aún puedes reclamar el antiguo nombre de usuario durante el periodo de tiempo de espera.
+change_username_redirect_prompt.with_cooldown.one = El antiguo nombre de usuario estará disponible para todos después un periodo de tiempo de espera de %[1]d día. Aún puedes reclamar el antiguo nombre de usuario durante el periodo de tiempo de espera.
quota.rule.exceeded = Excedido
quota.rule.no_limit = Ilimitado
quota.sizes.assets.all = Activos
@@ -1574,7 +1574,7 @@ issues.remove_ref_at=`eliminó la referencia %s %s`
issues.add_ref_at=`añadió la referencia %s %s`
issues.delete_branch_at=`eliminó la rama %s %s`
issues.filter_label=Etiqueta
-issues.filter_label_exclude=`Usa alt
+ clic/enter
para excluir etiquetas`
+issues.filter_label_exclude=Usa Alt + Click para excluir etiquetas
issues.filter_label_no_select=Todas las etiquetas
issues.filter_label_select_no_label=Sin etiqueta
issues.filter_milestone=Hito
@@ -1648,13 +1648,13 @@ issues.close_comment_issue=Cerrar con comentario
issues.reopen_issue=Reabrir
issues.reopen_comment_issue=Reabrir con comentario
issues.create_comment=Comentar
-issues.closed_at=`cerró esta incidencia %[2]s`
-issues.reopened_at=`reabrió esta incidencia %[2]s`
-issues.commit_ref_at=`referenció esta incidencia en un commit %[2]s`
-issues.ref_issue_from=`referenció esta incidencia %[4]s %[2]s`
-issues.ref_pull_from=`referenció este pull request %[4]s %[2]s`
-issues.ref_closing_from=`hizo referencia a esta incidencia desde un pull request %[4]s que lo cerrará , %[2]s`
-issues.ref_reopening_from=`hizo referencia a esta incidencia desde un pull request %[4]s que lo reabrirá, %[2]s`
+issues.closed_at=`cerró esta incidencia %s`
+issues.reopened_at=`reabrió esta incidencia %s`
+issues.commit_ref_at=`referenció esta incidencia en un commit %s`
+issues.ref_issue_from=`referenció esta incidencia %[3]s %[1]s`
+issues.ref_pull_from=`referenció este pull request %[3]s %[1]s`
+issues.ref_closing_from=`hizo referencia a esta incidencia desde un pull request %[3]s que lo cerrará , %[1]s`
+issues.ref_reopening_from=`hizo referencia a esta incidencia desde un pull request %[3]s que lo reabrirá, %[1]s`
issues.ref_closed_from=`cerró esta incidencia %[4]s %[2]s`
issues.ref_reopened_from=`reabrió esta incidencia %[4]s %[2]s`
issues.ref_from=`de %[1]s`
@@ -1959,8 +1959,8 @@ pulls.update_branch_success=La actualización de la rama ha finalizado correctam
pulls.update_not_allowed=No tiene permisos para actualizar esta rama
pulls.outdated_with_base_branch=Esta rama está desactualizada con la rama base
pulls.close=Cerrar pull request
-pulls.closed_at=`cerró este pull request %[2]s`
-pulls.reopened_at=`reabrió este pull request %[2]s`
+pulls.closed_at=`cerró este pull request %s`
+pulls.reopened_at=`reabrió este pull request %s`
pulls.clear_merge_message=Borrar mensaje de fusión
pulls.clear_merge_message_hint=Limpiar el mensaje de fusión solo eliminará el contenido del mensaje de commit y mantendrá frases generadas como "Co-Autorizado por …".
@@ -2789,7 +2789,7 @@ pulls.status_checks_hide_all = Ocultar todas las verificaciones
settings.federation_not_enabled = La federación no está habilitada en tu instancia.
wiki.search = Buscar en wiki
pulls.status_checks_show_all = Mostrar todas las verificaciones
-pulls.commit_ref_at = `hizo referencia a este pull request desde un commit %[2]s`
+pulls.commit_ref_at = `hizo referencia a este pull request desde un commit %s`
pulls.cmd_instruction_merge_title = Fusionar
contributors.contribution_type.deletions = Eliminaciones
contributors.contribution_type.filter_label = Tipo de contribución:
@@ -2888,6 +2888,9 @@ summary_card_alt = Tarjeta de resumen del repositorio %s
settings.pull_mirror_sync_quota_exceeded = Cuota excedida, no se empujan los cambios.
archive.nocomment = No es posible hacer comentarios porque el repositorio está archivado.
+sync_fork.branch_behind_one = Esta rama esta %[1]d cambios detrás de %[2]s
+sync_fork.branch_behind_few = Esta rama está %[1]d confirmaciones detrás de %[2]s
+
[graphs]
component_loading = Cargando %s…
component_loading_failed = No se pudo cargar %s
diff --git a/options/locale/locale_et.ini b/options/locale/locale_et.ini
index e54ceadbb5..441a7d8e07 100644
--- a/options/locale/locale_et.ini
+++ b/options/locale/locale_et.ini
@@ -108,7 +108,7 @@ never = Mitte kunagi
unknown = Teadmata
rss_feed = RSS infovoog
confirm_delete_artifact = Kas oled kindel et soovite artefakti "%s" kustutada?
-pin =
+pin =
artifacts = Artefaktid
archived = Arhiveeritud
concept_system_global = Ülemaailmne
@@ -145,25 +145,25 @@ fuzzy_tooltip = Lisage tulemused mis vastavad ka otsingu terminile
union = Märksõnad
exact = Täpne
exact_tooltip = Sisaldab ainult tulemusi mis vastavad täpsele otsingusõnale
-repo_kind = Otsi hoidlad...
-user_kind = Otsi kasutajaid...
-org_kind = Otsi organisatsioone...
-team_kind = Otsi meeskonnad...
-code_kind = Otsi koodi...
+repo_kind = Otsi hoidlad…
+user_kind = Otsi kasutajaid…
+org_kind = Otsi organisatsioone…
+team_kind = Otsi meeskonnad…
+code_kind = Otsi koodi…
code_search_by_git_grep = Praeguse koodi otsingu tulemused annab "git grep". Paremaid tulemusi võib saada, kui saidi administraator lubab koodi indekseerija.
-package_kind = Otsi pakette...
-project_kind = Otsi projekte...
-branch_kind = Otsi harusid...
-commit_kind = Otsi kommiteid...
-runner_kind = Otsi jooksjaid...
+package_kind = Otsi pakette…
+project_kind = Otsi projekte…
+branch_kind = Otsi harusid…
+commit_kind = Otsi kommiteid…
+runner_kind = Otsi jooksjaid…
no_results = Sobivaid tulemusi ei leitud.
-issue_kind = Otsi probleeme...
+issue_kind = Otsi probleeme…
milestone_kind = Otsi verstapostid...
type_tooltip = Otsingu tüüp
code_search_unavailable = Koodide otsing ei ole praegu saadaval. Palun võtke ühendust saidi administraatoriga.
union_tooltip = Sisaldab tulemused mis vastavad mis tahes tühikutega eraldatud võtmesõnadele
keyword_search_unavailable = Otsing märksõna järgi ei ole praegu saadaval. Palun võtke ühendust saidi administraatoriga.
-pull_kind = Otsi tõmbepäringuid...
+pull_kind = Otsi tõmbepäringuid…
[aria]
navbar = Navigatsiooniriba
diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini
index 804b48b2b2..23cb74f814 100644
--- a/options/locale/locale_fa-IR.ini
+++ b/options/locale/locale_fa-IR.ini
@@ -608,7 +608,7 @@ avatar=آواتار
ssh_gpg_keys=کلیدهای SSH / GPG
social=حساب های اجتماعی
applications=برنامهها
-orgs=مدیریت سازمانها
+orgs=سازمانها
repos=مخازن
delete=حذف حساب کاربری
twofa=احراز هویت دوگانه
@@ -653,8 +653,8 @@ password_change_disabled=کاربران غیر محلی نمیتوانند گذ
emails=نشانیهای ایمیل
manage_emails=مدیریت نشانیهای ایمیل
-manage_themes=تم پیش فرض را انتخاب کنید
-manage_openid=مدیریت نشانیهای OpenID
+manage_themes=تم پیش فرض
+manage_openid=آدرسهای OpenID
theme_desc=این پوشته پیش فرض شما در سراسر سایت می باشد.
primary=اصلی
activated=فعال شده
@@ -1250,13 +1250,13 @@ issues.close_comment_issue=ثبت دیدگاه و بستن
issues.reopen_issue=بازگشایی
issues.reopen_comment_issue=ثبت دیدگاه و بازگشایی
issues.create_comment=دیدگاه
-issues.closed_at=`%[2]s این موضوع را بست`
-issues.reopened_at=`%[2]s این موضوع را دوباره باز کرد`
-issues.commit_ref_at=`ارجاع این مسئله به کامیت %[2]s`
-issues.ref_issue_from=` ارجاعات این مسائله %[4] %[2]s`
-issues.ref_pull_from=` ارجاعات این تقاضای ادغام %[4] %[2]s`
-issues.ref_closing_from=` ارجاعات این تقاضای واکشی %[4] %[2]s`
-issues.ref_reopening_from=` تقاضای واکشی ارجاع شده %[4] که مسائله بازگشایی خواهد کرد %[2] `
+issues.closed_at=`%s این موضوع را بست`
+issues.reopened_at=`%s این موضوع را دوباره باز کرد`
+issues.commit_ref_at=`ارجاع این مسئله به کامیت %s`
+issues.ref_issue_from=` ارجاعات این مسائله %[3] %[1]s`
+issues.ref_pull_from=` ارجاعات این تقاضای ادغام %[4] %[1]s`
+issues.ref_closing_from=` ارجاعات این تقاضای واکشی %[4] %[1]s`
+issues.ref_reopening_from=` تقاضای واکشی ارجاع شده %[3]sکه مسائله بازگشایی خواهد کرد %[2] `
issues.ref_closed_from=` بسته شده این مسائله %[4] %[2]s`
issues.ref_reopened_from=` بازگشایی این مسائله %[4] %[2]s`
issues.ref_from=`از %[1]`
@@ -1493,8 +1493,8 @@ pulls.update_branch_rebase=بروزآوری شاخه با بازسازی مجد
pulls.update_branch_success=شاخه به موفقیت بروز شد
pulls.update_not_allowed=شما اجازه بروزرسانی شاخه را ندارید
pulls.outdated_with_base_branch=این شاخه با شاخه پایه منسوخ شده است
-pulls.closed_at=`این درخواست pull بسته شده %[2]s`
-pulls.reopened_at=`این درخواست pull را بازگشایی کرد %[2]s`
+pulls.closed_at=`این درخواست pull بسته شده %s`
+pulls.reopened_at=`این درخواست pull را بازگشایی کرد %s`
@@ -2766,23 +2766,23 @@ search = جستجو...
fuzzy = درهم
fuzzy_tooltip = پیامدهایی را درج کنید که دقیقا با عبارت جستجو همخوانی داشته باشند
regexp = عبارات باقاعده
-pull_kind = جستجو واکشیها...
+pull_kind = جستجو واکشیها…
no_results = نتیجه درخوری یافت نشد.
-runner_kind = جستجو دوندهها...
+runner_kind = جستجو دوندهها…
keyword_search_unavailable = جستجو کلیدواژه اکنون در درسترس نیست. لطفا با مدیر سایت در میان بگذارید.
-repo_kind = جستجو مخازن...
+repo_kind = جستجو مخازن…
regexp_tooltip = اصطلاح جستجو شده را با عبارات باقاعده تفسیر کن
-user_kind = جستجو کاربران...
-org_kind = جستجو سازمانها...
-team_kind = جستجو گروهها...
-package_kind = جستجو بستهها...
-project_kind = جستجو پروژهها...
+user_kind = جستجو کاربران…
+org_kind = جستجو سازمانها…
+team_kind = جستجو گروهها…
+package_kind = جستجو بستهها…
+project_kind = جستجو پروژهها…
code_search_unavailable = جستجوی کد اکنون در دسترس نیست. لطفا با مدیر سایت درمیان بگذارید.
-code_kind = جستجو کدها...
+code_kind = جستجو کدها…
union = بهم پیوستگی
union_tooltip = نتایجی را در بر بگیر که با هر یک از کلیدواژههای جدا شده از فضایخالی مطابقت دارد
-branch_kind = جستجو شاخهها...
-commit_kind = جستجو سپردهها...
-issue_kind = جستجو مشکلات...
+branch_kind = جستجو شاخهها…
+commit_kind = جستجو سپردهها…
+issue_kind = جستجو مشکلات…
exact = مو به مو
exact_tooltip = نتایجی را در بر بگیر که مو به مو با اصطلاح جستجو شده یکی باشد
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index cff940a05a..7eea87f959 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -669,6 +669,13 @@ username_claiming_cooldown = Käyttäjänimeä ei voi ottaa käyttöön, koska s
email_domain_is_not_allowed = Käyttäjän sähköpostiosoitteen %s verkkotunnus on ristiriidassa EMAIL_DOMAIN_ALLOWLIST:in tai EMAIL_DOMAIN_BLOCKLIST:in kanssa. Varmista, että olen asettanut sähköpostiosoitteen oikein.
+invalid_group_team_map_error = ` kuvaus ei ole kelvollinen: %s`
+visit_rate_limit = Etävierailujen pyyntörajoitukset.
+2fa_auth_required = Etävierailu vaati kaksivaiheisen todennuksen.
+unset_password = Kirjautuneen käyttäjän salasanaa ei ole asetettu.
+unsupported_login_type = Tällä kirjautumistavalla ei voi poistaa tunnusta.
+invalid_ssh_principal = Väärä toimija: %s
+
[user]
change_avatar=Vaihda profiilikuvasi…
repositories=Tietovarastot
@@ -1038,6 +1045,9 @@ 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.
+uid = UID
+hidden_comment_types.ref_tooltip = Kommentit missä tähän ongelmaan viitattiin toisesta ongelmasta/kommitista/…
+
[repo]
owner=Omistaja
owner_helper=Jotkin organisaatiot eivät välttämättä näy pudotusvalikossa, koska tietovarastojen enimmäismäärää on rajoitettu.
@@ -1293,9 +1303,9 @@ issues.close_comment_issue=Kommentoi ja sulje
issues.reopen_issue=Avaa uudelleen
issues.reopen_comment_issue=Kommentoi ja avaa uudelleen
issues.create_comment=Kommentoi
-issues.closed_at=`sulki tämän ongelman %[2]s`
-issues.reopened_at=`uudelleenavasi tämän ongelman %[2]s`
-issues.commit_ref_at=`viittasi tähän ongelmaan kommitissa %[2]s`
+issues.closed_at=`sulki tämän ongelman %s`
+issues.reopened_at=`uudelleenavasi tämän ongelman %s`
+issues.commit_ref_at=`viittasi tähän ongelmaan kommitissa %s`
issues.author=Tekijä
issues.role.owner=Omistaja
issues.role.member=Jäsen
@@ -2185,7 +2195,7 @@ settings.confirmation_string = Vahvistusteksti
settings.delete_notices_2 = - Tämä toiminto poistaa pysyvästi tietovaraston %s mukaan lukien koodin, ongelmat, kommentit, wikidatan ja avustaja-asetukset.
issues.filter_assginee_no_select = Kaikki käsittelijät
issues.new.assign_to_me = Osoita itselle
-pulls.closed_at = `sulki tämän vetopyynnön %[2]s`
+pulls.closed_at = `sulki tämän vetopyynnön %s`
tree_path_not_found_branch = Polkua %[1]s ei ole olemassa haarassa %[2]s
transfer.no_permission_to_reject = Sinulla ei ole oikeutta hylätä tätä siirtoa.
generate_repo = Luo tietovarasto
@@ -2199,8 +2209,8 @@ issues.new.no_reviewers = Ei katselmoijia
issues.add_label = lisäsi nimilapun %s %s
issues.due_date_added = lisäsi eräpäivän %s %s
issues.review.add_review_request = pyysi katselmointia käyttäjältä %[1]s %[2]s
-issues.ref_pull_from = `viittasi tähän vetopyyntöön %[4]s %[2]s`
-pulls.commit_ref_at = `viittasi tähän vetopyyntöön kommitista %[2]s`
+issues.ref_pull_from = `viittasi tähän vetopyyntöön %[3]s %[1]s`
+pulls.commit_ref_at = `viittasi tähän vetopyyntöön kommitista %s`
issues.review.comment = katselmoi %s
issues.add_labels = lisäsi nimilaput %s %s
issues.review.add_review_requests = pyysi katselmointeja käyttäjiltä %[1]s %[2]s
@@ -2255,14 +2265,14 @@ pulls.cmd_instruction_merge_warning = Varoitus: Asetusta ”Tunnista manu
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.
adopt_preexisting_success = Omaksuttu tiedostot ja luotu tietovarasto lähteestä %s
-issues.comment_manually_pull_merged_at = manuaalisesti yhdistetty kommitti %[1]s %[2]s tietovarastoon %[3]s
+issues.comment_manually_pull_merged_at = manuaalisesti yhdisti kommitin %[1]s %[2]s tietovarastoon %[3]s
pulls.cmd_instruction_merge_title = Yhdistä
pulls.has_merged = Epäonnistui: vetopyyntö on yhdistetty, joten et voi yhdistää uudelleen tai muuttaa kohdehaaraa.
pulls.cmd_instruction_checkout_title = Uloskuittaus
pulls.cmd_instruction_checkout_desc = Kuittaa ulos uusi haara projektitietovarastostasi ja testaa muutokset.
pulls.clear_merge_message_hint = Yhdistämisviestin tyhjentäminen poistaa vain kommittiviestin sisällön ja säilyttää luodut git-trailerit, kuten "Co-Authored-By…".
settings.protect_check_status_contexts_desc = Vaadi tilatarkistusten läpäisy ennen yhdistämistä. Kun käytössä, kommitit on ensin työnnettävä toiseen haaraan ja sitten yhdistettävä tai työnnettävä suoraan tätä sääntöä vastaavaan haaraan tilantarkistuksen jälkeen. Jos konteksteja ei löydy, viimeisen kommitin on oltava onnistunut kontekstista riippumatta.
-issues.comment_pull_merged_at = yhdistetty kommitti %[1]s %[2]s tietovarastoon %[3]s
+issues.comment_pull_merged_at = yhdisti kommitin %[1]s %[2]s haaraan %[3]s
settings.pulls.enable_autodetect_manual_merge = Ota Tunnista manuaalinen yhdistäminen automaattisesti -asetus käyttöön (Huomaa: joissakin erityistapauksissa voi esiintyä virhearviointeja)
pulls.no_merge_desc = Tätä vetopyyntöä ei voida yhdistää, koska kaikki tietovaraston yhdistämisvaihtoehdot ovat poistettu käytöstä.
pulls.no_merge_not_ready = Tämä vetopyyntö ei ole valmis yhdistettäväksi. Tarkista katselmoinnin tila ja tilantarkistukset.
@@ -2381,7 +2391,7 @@ wiki.page_name_desc = Kirjoita tämän wikisivun nimi. Joitain erikoisnimiä ova
pulls.blocked_by_changed_protected_files_1 = Tämä vetopyyntö sisältää suojatun tiedoston ja on siksi estetty:
pulls.status_checks_warning = Jotkin tarkistukset raportoivat varoituksia
pulls.status_checks_error = Jotkin tarkistukset raportoivat virheitä
-pulls.reopened_at = `avasi uudelleen tämän vetopyynnön %[2]s`
+pulls.reopened_at = `avasi uudelleen tämän vetopyynnön %s`
pulls.auto_merge_when_succeed = Yhdistä automaatisesti kun kaikki tarkistukset onnistuvat
signing.wont_sign.error = Tapahtui virhe tarkistaessa voiko kommitin allekirjoittaa.
signing.wont_sign.twofa = Sinulla tulee olla kaksivaiheinen todennus käytössä, jotta kommitit voi allekirjoittaa.
diff --git a/options/locale/locale_fil.ini b/options/locale/locale_fil.ini
index 7d1405f633..487768ea22 100644
--- a/options/locale/locale_fil.ini
+++ b/options/locale/locale_fil.ini
@@ -365,7 +365,7 @@ table_modal.label.columns = Mga Column
link_modal.header = Magdagdag ng link
link_modal.url = Url
link_modal.description = Deskripsyon
-link_modal.paste_reminder = Pahiwatig: Kapag may URL sa clipboard, maari mong direktang i-paste sa editor para gumawa ng link.
+link_modal.paste_reminder = Pahiwatig: Kapag may URL sa clipboard, maaari mong direktang i-paste sa editor para gumawa ng link.
[filter]
string.asc = A - Z
@@ -432,7 +432,7 @@ openid_connect_desc = Ang piniling OpenID URI ay hindi alam. Iugnay iyan sa bago
invalid_code = Ang iyong confirmation code ay hindi wasto o nag-expire na.
oauth_signin_title = Mag-sign in para pahintulutan ang naka-link na account
invalid_code_forgot_password = Ang iyong confirmation code ay hindi wasto o nag-expire na. Mag-click dito para magsimula ng bagong session.
-confirmation_mail_sent_prompt = Ang isang bagong email na pang-kumpirma ay ipinadala sa %s. Para kumpletuhin ang proseso ng pagrehistro, pakisuri ang iyong inbox at sundan ang ibinigay na link sa loob ng %s. Kung mali ang email, maari kang mag-log in, at humingi ng isa pang email pang-kumpirma na ipapadala sa ibang address.
+confirmation_mail_sent_prompt = Ang isang bagong email na pang-kumpirma ay ipinadala sa %s. Para kumpletuhin ang proseso ng pagrehistro, pakisuri ang iyong inbox at sundan ang ibinigay na link sa loob ng %s. Kung mali ang email, maaari kang mag-log in, at humingi ng isa pang email pang-kumpirma na ipapadala sa ibang address.
invalid_password = Ang iyong password ay hindi tugma sa password na ginamit para gawin ang account.
twofa_scratch_used = Ginamit mo na ang scratch code. Na-redirect ka sa two-factor settings page para tanggalin ang device enrollment o mag-generate ng bagong scratch code.
manual_activation_only = Makipag-ugnayan sa tagapangangasiwa ng site para kumpletuhin ang pagrehistro.
@@ -484,7 +484,7 @@ admin.new_user.text = Mangyaring mag-click dito para ipamahala
register_notify = Maligayang Pagdating sa %s
register_notify.title = %[1]s, maligayang pagdating sa %[2]s
register_notify.text_1 = ito ang iyong registration confirmation email para sa %s!
-register_notify.text_2 = Maari kang mag-sign in sa iyong account gamit ng iyong username: %s
+register_notify.text_2 = Maaari kang mag-sign in sa iyong account gamit ng iyong username: %s
reset_password = I-recover ang iyong account
reset_password.title = %s, nagkaroon kami ng hiling para i-recover ang iyong account
reset_password.text = Kung ikaw ito, paki-click ang sumusunod na link para i-recover ang iyong account sa loob ng %s:
@@ -535,7 +535,7 @@ totp_disabled.text_1 = Ngayon lang na-disable ang Time-based one-time password (
totp_disabled.no_2fa = Wala nang mga ibang paraan ng 2FA ang naka-configure, nangangahulugan na hindi na kailangang mag-log in sa iyong account gamit ang 2FA.
removed_security_key.subject = May tinanggal na security key
removed_security_key.text_1 = Tinanggal ngayon lang ang security key na "%[1]s" sa iyong account.
-account_security_caution.text_1 = Kung ikaw ito, maari mong ligtas na huwag pansinin ang mail na ito.
+account_security_caution.text_1 = Kung ikaw ito, maaari mong ligtas na huwag pansinin ang mail na ito.
account_security_caution.text_2 = Kung hindi ito ikaw, nakompromiso ang iyong account. Mangyaring makipag-ugnayan sa mga tagapangasiwa ng site na ito.
totp_enrolled.subject = Nag-activate ka ng TOTP bilang paraan ng 2FA
totp_enrolled.text_1.has_webauthn = Na-enable mo lang ang TOTP para sa iyong account. Nangangahulugan ito na para sa lahat ng mga hinaharap na pag-login sa iyong account, kailangan mong gumamit ng TOTP bilang paraan ng 2FA o gamitin ang iyong mga security key.
@@ -644,7 +644,7 @@ AccessToken = Token ng pag-access
Biography = Byograpya
Location = Lokasyon
visit_rate_limit = Natugunan ang limitasyon sa rate ng malayuang pagbisita.
-username_claiming_cooldown = Hindi ma-claim ang username na ito, dahil hindi pa tapos ang panahon ng cooldown. Maari itong i-claim sa %[1]s.
+username_claiming_cooldown = Hindi ma-claim ang username na ito, dahil hindi pa tapos ang panahon ng cooldown. Maaari itong i-claim sa %[1]s.
email_domain_is_not_allowed = Sumasalungat ang domain ng email address ng user %s sa EMAIL_DOMAIN_ALLOWLIST o EMAIL_DOMAIN_BLOCKLIST. Siguraduhing natakda mo ang email address nang tama.
[user]
@@ -685,7 +685,7 @@ followers.title.few = Mga tagasunod
following.title.one = Sinusundan
followers.title.one = Tagasunod
public_activity.visibility_hint.self_public = Nakikita ng lahat ang iyong aktibidad, maliban sa mga interaksyon sa pribadong espasyo. I-configure.
-public_activity.visibility_hint.admin_public = Nakikita ng lahat ang aktibidad na ito, ngunit bilang tagapangasiwa maari mo ring makita ang mga interaksyon sa mga pribadong espasyo.
+public_activity.visibility_hint.admin_public = Nakikita ng lahat ang aktibidad na ito, ngunit bilang tagapangasiwa maaari mo ring makita ang mga interaksyon sa mga pribadong espasyo.
public_activity.visibility_hint.self_private = Nakikita mo lang at mga tagapangasiwa ng instansya ang iyong aktibidad. I-configure.
public_activity.visibility_hint.admin_private = Nakikita mo ang aktibidad na ito dahil isa kang tagapangasiwa, ngunit gusto ng user na panatilihin itong pribado.
public_activity.visibility_hint.self_private_profile = Ikaw lang at ang mga tagapangasiwa ng instansya ang makakakita ng iyong aktibidad dahil pribado ang iyong profile. I-configure.
@@ -699,7 +699,7 @@ security = Seguridad
avatar = Avatar
ssh_gpg_keys = Mga SSH / GPG key
applications = Mga Aplikasyon
-orgs = Ipamahala ang mga organisasyon
+orgs = Mga organisasyon
repos = Mga Repositoryo
delete = Burahin ang account
twofa = Authentikasyong two-factor (TOTP)
@@ -707,7 +707,7 @@ account_link = Mga naka-link na account
uid = UID
webauthn = Authentikasyong two-factor (Mga security key)
blocked_users = Mga hinarang na user
-public_profile = Pampublikong Profile
+public_profile = Pampublikong profile
location_placeholder = Ibahagi ang iyong tinatayang lokasyon sa iba
password_username_disabled = Ang mga di-lokal na gumagamit ay hindi pinapayagan na baguhin ang kanilang username. Mangyaring makipag-ugnayan sa iyong tagapangasiwa ng site para sa higit pang mga detalye.
full_name = Buong pangalan
@@ -842,7 +842,7 @@ gpg_key_verify = I-verify
gpg_invalid_token_signature = Ang ibinigay na GPG key, signature, at token ay hindi tumutugma o luma.
gpg_token_required = Kailangan mong magbigay ng signature para sa token sa ibaba
gpg_token = Token
-gpg_token_help = Maari kang mag-generate ng signature gamit ng:
+gpg_token_help = Maaari kang mag-generate ng signature gamit ng:
gpg_token_signature = Naka-armor na GPG signature
key_signature_gpg_placeholder = Nagsisimula sa "-----BEGIN PGP SIGNATURE-----"
verify_gpg_key_success = Na-verify na ang GPG key na "%s".
@@ -851,7 +851,7 @@ ssh_key_verify = I-verify
ssh_invalid_token_signature = Ang ibinigay na SSH key, signature, o token ay hindi tumutugma o luma.
ssh_token_required = Kailangan mong magbigay ng signature para sa token sa ibaba
ssh_token = Token
-ssh_token_help = Maari kang mag-generate ng signature gamit ng:
+ssh_token_help = Maaari kang mag-generate ng signature gamit ng:
ssh_token_signature = Naka-armor na SSH signature
key_signature_ssh_placeholder = Nagsisimula sa "-----BEGIN SSH SIGNATURE-----"
verify_ssh_key_success = Na-verify na ang SSH key na "%s".
@@ -912,10 +912,10 @@ create_oauth2_application_success = Matagumpay kang gumawa ang bagong OAuth2 app
oauth2_confidential_client = Kumpidensyal na kliyente. Piliin para sa mga app na pinapatilihing kumpidensyal ang sikreto, tulad ng mga web app. Huwag piliin para sa mga web app kasama ang mga desktop at mobile app.
twofa_desc = Para protektahin ang iyong account laban sa pagnanakaw ng password, pwede mo gamitin ang iyong smartphone o ibang device para sa pagtanggap ng time-based one-time password ("TOTP").
twofa_scratch_token_regenerated = Ang iyong isang-beses na paggamit na recovery key ngayon ay %s. Ilagay ito sa ligtas na lugar, dahil hindi na ito ipapakita muli.
-regenerate_scratch_token_desc = Kapag nawala mo ang iyong recovery key o ginamit mo na oara mag-sign in, maari mong i-reset dito.
+regenerate_scratch_token_desc = Kapag nawala mo ang iyong recovery key o ginamit mo na oara mag-sign in, maaari mong i-reset dito.
twofa_disable_desc = Ang pag-disable ng authentikasyong two-factor ay gagawing hindi gaanong ligtas ang iyong account. Magpatuloy?
twofa_enrolled = Matagumpay na na-enroll ang iyong account. Ilagay ang iyong isang-beses na paggamit na recovery key (%s) sa isang ligtas na lugar, dahil hindi na ito ipapakita muli.
-webauthn_desc = Ang mga security key ay isang hardware device na naglalaman ng mga cryptographic key. Maari silang gamitin para sa authentikasyong two-factor. Ang mga security key ay dapat suportahan ang WebAuthn Authenticator na standard.
+webauthn_desc = Ang mga security key ay isang hardware device na naglalaman ng mga cryptographic key. Maaari silang gamitin para sa authentikasyong two-factor. Ang mga security key ay dapat suportahan ang WebAuthn Authenticator na standard.
remove_oauth2_application = Tanggalin ang OAuth2 Application
remove_oauth2_application_desc = Ang pagtanggal ng OAuth2 application ay babawiin ang access sa lahat ng mga naka-sign na access token. Magpatuloy?
remove_oauth2_application_success = Binura na ang application.
@@ -931,13 +931,13 @@ oauth2_regenerate_secret = I-regenerate ang sikreto
oauth2_regenerate_secret_hint = Nawala mo ang iyong sikreto?
oauth2_client_secret_hint = Ang sikreto ay hindi ipapakita muli pagkatapos umalis ka o i-refresh ang page na ito. Mangyaring siguraduhin na na-save mo iyan.
oauth2_application_edit = I-edit
-twofa_recovery_tip = Kapag mawala mo ang iyong device, maari kang gumamit ng isang isang-beses na paggamit na recovery key para makakuha muli ng access sa iyong account.
+twofa_recovery_tip = Kapag mawala mo ang iyong device, maaari kang gumamit ng isang isang-beses na paggamit na recovery key para makakuha muli ng access sa iyong account.
twofa_is_enrolled = Ang iyong account ay kasalukuyang naka-enroll sa autentikasyong two-factor.
twofa_not_enrolled = Kasalukuyang hindi naka-enroll ang iyong account sa authentikasyong two-factor.
twofa_disable = I-disable ang authentikasyong two-factor
twofa_scratch_token_regenerate = I-regenerate ang isang-beses na paggamit na recovery key
twofa_enroll = Mag-enroll sa authentikasyong two-factor
-twofa_disable_note = Maari mong i-disable ang authentikasyong two-factor kapag kinakailangan.
+twofa_disable_note = Maaari mong i-disable ang authentikasyong two-factor kapag kinakailangan.
twofa_disabled = Na-disable na ang authentikasyong two-factor.
scan_this_image = I-scan ang image na ito gamit ng iyong aplikasyong pang-authentikasyon:
or_enter_secret = O ilagay ang sikreto: %s
@@ -1005,8 +1005,8 @@ language.description = Mase-save ang wika sa iyong account at gagamitin bilang d
language.localization_project = Tulungan kaming isalin ang Forgejo sa iyong wika! Matuto pa.
pronouns_custom_label = Mga pasadyang pronoun
user_block_yourself = Hindi mo maaaring harangan ang sarili mo.
-change_username_redirect_prompt.with_cooldown.one = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
-change_username_redirect_prompt.with_cooldown.few = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
+change_username_redirect_prompt.with_cooldown.one = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
+change_username_redirect_prompt.with_cooldown.few = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
keep_pronouns_private = Ipakita lang ang mga panghalip sa mga naka-authenticate na user
keep_pronouns_private.description = Itatago nito ang iyong mga panghalip mula sa mga bisita na hindi naka-log in.
quota.applies_to_user = Nag-aapply ang mga sumusunod na panuntunan ng quota sa iyong account
@@ -1071,7 +1071,7 @@ readme_helper_desc = Ito ang lugar kung saan makakasulat ka ng kumpletong deskri
trust_model_helper_collaborator_committer = Katulong+Committer: I-trust ang mga signature batay sa mga katulong na tumutugma sa committer
mirror_interval = Interval ng mirror (ang mga wastong unit ng oras ay "h", "m", "s"). 0 para i-disable ang periodic sync. (Pinakamababang interval: %s)
transfer.reject_desc = Kanselahin ang pag-transfer mula sa "%s"
-mirror_lfs_endpoint_desc = Ang sync ay susubukang gamitin ang clone url upang matukoy ang LFS server. Maari ka rin tumukoy ng isang custom na endpoint kapag ang LFS data ng repositoryo ay nilalagay sa ibang lugar.
+mirror_lfs_endpoint_desc = Ang sync ay susubukang gamitin ang clone url upang matukoy ang LFS server. Maaari ka rin tumukoy ng isang custom na endpoint kapag ang LFS data ng repositoryo ay nilalagay sa ibang lugar.
adopt_search = Ilagay ang username para maghanap ng mga unadopted na repositoryo… (iwanang walang laman para hanapin lahat)
object_format = Format ng object
readme_helper = Pumili ng README file template
@@ -1164,8 +1164,8 @@ tree_path_not_found_commit = Hindi umiiral ang path na %[1]s sa commit %[2]s
tree_path_not_found_branch = Hindi umiiral ang daanang %[1]s sa branch %[2]s
migrate_items_pullrequests = Mga hiling sa paghila
archive.pull.nocomment = Naka-archive ang repositoryong ito. Hindi ka makakakomento sa mga pull request.
-archive.title = Naka-archive ang repositoryong ito. Maari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado ito, tulad ng pagtulak at paggawa ng mga isyu, pull request o mga komento.
-archive.title_date = Naka-archive ang repositoryo na ito noong %s. Maari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado nito, tulad ng pagtulak o paggawa ng mga bagong isyu, mga pull request, o komento.
+archive.title = Naka-archive ang repositoryong ito. Maaari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado ito, tulad ng pagtulak at paggawa ng mga isyu, pull request o mga komento.
+archive.title_date = Naka-archive ang repositoryo na ito noong %s. Maaari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado nito, tulad ng pagtulak o paggawa ng mga bagong isyu, mga pull request, o komento.
pulls = Mga hiling sa paghila
activity.merged_prs_count_n = Mga naisamang hiling sa paghila
wiki.last_updated = Huling binago %s
@@ -1183,7 +1183,7 @@ issues.action_open = Buksan
issues.closed_title = Sarado
issues.reopen_issue = Buksang muli
pulls.merged = Naisama na
-pulls.merged_info_text = Maari nang burahin ang branch %s.
+pulls.merged_info_text = Maaari nang burahin ang branch %s.
milestones.update_ago = Binago %s
activity.closed_issue_label = Sarado
activity.merged_prs_label = Naisama
@@ -1205,7 +1205,7 @@ migrate.clone_address_desc = Ang HTTP(S) o Git "clone" URL ng umiiral na reposit
need_auth = Awtorisasyon
migrate.github_token_desc = Maaari kang maglagay ng isa o higit pang mga token na hinihiwalay ng kuwit dito upang gawing mas-mabilis ang pagmigrate dahil sa rate limit ng GitHub API. BABALA: Ang pagabuso ng feature na ito ay maaaring maglabag sa patakaran ng tagapagbigay ng serbisyo at maaaring magdulot ng pag-block ng account.
template.invalid = Kailangang pumili ng kahit isang template na repositoryo
-migrate_options_lfs_endpoint.description = Susubukan ng migration na gamitin ang iyong Git remote upang matukoy ang LFS server. Maari mong magtiyak ng custom na endpoint kapag ang LFS data ng repositoryo ay nakalagay sa ibang lugar.
+migrate_options_lfs_endpoint.description = Susubukan ng migration na gamitin ang iyong Git remote upang matukoy ang LFS server. Maaari mong magtiyak ng custom na endpoint kapag ang LFS data ng repositoryo ay nakalagay sa ibang lugar.
blame.ignore_revs.failed = Nabigong hindi pansinin ang mga rebisyon sa .git-blame-ignore-revs.
tree_path_not_found_tag = Hindi umiiral ang path na %[1]s sa tag %[2]s
form.reach_limit_of_creation_n = Naabot na ng may-ari ang limitasyon na %d mga repositoryo.
@@ -1471,10 +1471,10 @@ activity.new_issue_label = Nabuksan
activity.merged_prs_count_1 = Naisamang hiling sa paghila
activity.opened_prs_count_1 = Inimungkahing hiling sa paghila
activity.opened_prs_label = Inimungkahi
-pulls.reopened_at = `nabuksang muli ang hiling sa paghatak na %[2]s`
+pulls.reopened_at = `binuksan muli ang hiling sa paghila %s`
issues.opened_by_fake = binuksan ang %[1]s ni/ng %[2]s
pulls.reopen_failed.base_branch = Hindi mabuksang muli ang hiling sa paghatak na ito dahil hindi na umiiral ang base branch.
-issues.reopened_at = `binuksang muli ang isyung ito %[2]s`
+issues.reopened_at = `binuksang muli ang isyung ito %s`
pulls.reopen_failed.head_branch = Hindi mabubuksan muli ang hiling sa paghila, dahil hindi na umiiral ang head branch.
settings.event_pull_request_desc = Binuksan, sinara, muling binuksan, o binago ang hiling sa paghatak.
activity.opened_prs_count_n = Mga inimungkahing hiling sa paghila
@@ -1500,7 +1500,7 @@ issues.content_history.created = ginawa
editor.patching = Pina-patch:
editor.fail_to_apply_patch = Hindi malapat ang patch na "%s"
settings.danger_zone = Mapanganib na lugar
-issues.closed_at = `isinara ang isyung ito %[2]s`
+issues.closed_at = `isinara ang isyung ito %s`
settings.collaboration.admin = Tagapangasiwa
settings.admin_settings = Mga setting ng tagapangasiwa
issues.start_tracking_history = `sinimulan ang trabaho %s`
@@ -1627,7 +1627,7 @@ projects.column.edit_title = Pangalan
projects.column.new_title = Pangalan
projects.card_type.desc = Mga preview ng card
commits.desc = I-browse ang history ng pagbabago ng source code.
-commits.search.tooltip = Maari kang mag-prefix ng mga keyword gamit ang "author:", "committer:", "after:", o "before:", hal. "revert author:Nijika before:2022-10-09".
+commits.search.tooltip = Maaari kang mag-prefix ng mga keyword gamit ang "author:", "committer:", "after:", o "before:", hal. "revert author:Nijika before:2022-10-09".
issues.force_push_codes = `puwersahang itinulak ang %[1]s mula %[2]s
sa %[4]s
%[6]s`
issues.push_commit_1 = idinagdag ang %d commit %s
issues.push_commits_n = idinagdag ang %d mga commit %s
@@ -1707,7 +1707,7 @@ issues.action_milestone = Milestone
issues.action_milestone_no_select = Walang milestone
issues.delete_branch_at = `binura ang branch na %s %s`
issues.filter_label = Label
-issues.filter_label_exclude = `Gamitin ang alt
+ click/enter
para hindi isama ang mga label`
+issues.filter_label_exclude = `Gamitin ang Alt + Click para hindi isama ang mga label`
issues.filter_label_no_select = Lahat ng mga label
issues.filter_milestone_closed = Mga nakasarang milestone
issues.filter_assignee = Mangangasiwa
@@ -1771,7 +1771,7 @@ issues.lock = I-lock ang usapan
issues.unlock = I-unlock ang usapan
issues.unlock_comment = na-unlock ang usapang ito %s
issues.unlock.notice_1 = - Makakakomento muli ang lahat ng mga tao sa isyung ito.
-issues.unlock.notice_2 = - Maari mong i-lock muli ang isyung ito sa hinaharap.
+issues.unlock.notice_2 = - Maaari mong i-lock muli ang isyung ito sa hinaharap.
issues.comment_on_locked = Hindi ka makakakomento sa naka-lock na isyu.
issues.closed_by_fake = ni/ng %[2]s ay isinara %[1]s
issues.comment_manually_pull_merged_at = manwal na isinama ang commit %[1]s sa %[2]s %[3]s
@@ -1787,10 +1787,10 @@ issues.label_archive_tooltip = Ang mga naka-archive na label ay hindi isasama bi
issues.is_stale = May mga pagbabago sa PR na ito mula sa pagsuri na ito
issues.role.first_time_contributor = Unang-beses na contributor
issues.lock.notice_1 = - Hindi makakadagdag ng mga bagong komento ang mga ibang user sa isyu na ito.
-issues.lock.notice_3 = - Maari mong i-unlock muli ang isyung ito sa hinaharap.
+issues.lock.notice_3 = - Maaari mong i-unlock muli ang isyung ito sa hinaharap.
issues.label_deletion_desc = Ang pagbura ng label ay tatanggalin ito sa lahat ng mga isyu. Magpatuloy?
-issues.commit_ref_at = `isinangguni ang isyu na ito mula sa commit %[2]s`
-issues.ref_issue_from = `isinangguni ang isyu na ito sa %[4]s %[2]s`
+issues.commit_ref_at = `isinangguni ang isyu na ito mula sa commit %s`
+issues.ref_issue_from = `isinangguni ang isyu na ito sa %[3]s %[1]s`
issues.num_participants_one = %d kasali
issues.attachment.download = `I-click para i-download ang "%s" `
issues.num_participants_few = %d mga kasali
@@ -1815,10 +1815,10 @@ issues.sign_in_require_desc = Mag-sign in upang sumali sa usapa
issues.num_comments = %d mga komento
issues.role.contributor_helper = Nakaraang nag-commit ang user na ito sa repositoryo na ito.
issues.comment_pull_merged_at = isinama ang commit %[1]s sa %[2]s %[3]s
-pulls.commit_ref_at = `isinangguni ang hiling sa paghila mula sa isang commit %[2]s`
+pulls.commit_ref_at = `isinangguni ang hiling sa paghila mula sa isang commit %s`
wiki.last_commit_info = Binago ni %s ang pahinang ito %s
issues.content_history.edited = binago
-issues.ref_pull_from = `isinangguni ang hiling sa paghila na ito %[4]s %[2]s`
+issues.ref_pull_from = `isinangguni ang hiling sa paghila na ito %[3]s %[1]s`
pulls.merged_title_desc_few = isinali ang %[1]d mga commit mula sa %[2]s
patungong %[3]s
%[4]s
settings.org_not_allowed_to_be_collaborator = Hindi maaaring idagdag ang mga organisasyon bilang tagatulong.
settings.add_collaborator_success = Naidagdag ang tagatulong.
@@ -1828,7 +1828,7 @@ pulls.create = Gumawa ng hiling sa paghila
issues.dependency.pr_close_blocked = Kailangan mong isara ang lahat ng mga isyu na humaharang sa hiling sa paghila na ito bago mo ito isama.
pulls.delete.title = Burahin ang hiling sa paghila na ito?
issues.dependency.pr_closing_blockedby = Hinarang ng mga sumusunod na isyu mula sa pagsara ng hiling sa paghila na ito
-pulls.closed_at = `isinara ang hiling sa paghila na %[2]s`
+pulls.closed_at = `isinara ang hiling sa paghila na ito %s`
pulls.close = Isara ang hiling sa paghila
pulls.cmd_instruction_hint = Tingnan ang mga panuto para sa command line
project = Mga proyekto
@@ -1836,8 +1836,8 @@ issues.content_history.deleted = binura
pulls.no_results = Walang mga nahanap na resulta.
pulls.closed = Sarado ang hiling sa paghila
pulls.is_closed = Naisara na ang hiling sa paghila.
-issues.ref_closing_from = `nagsangguni ang isyu mula sa hiling sa paghila %[4]s na magsasara sa isyu, %[2]s`
-issues.ref_reopening_from = `nagsangguni ang isyu na ito mula sa hiling sa paghila %[4]s na muling bubukas, %[2]s`
+issues.ref_closing_from = `nagsangguni ang isyu mula sa hiling sa paghila %[3]s na magsasara sa isyu, %[1]s`
+issues.ref_reopening_from = `nagsangguni ang isyu na ito mula sa hiling sa paghila %[3]s na muling bubukas nito, %[1]s`
issues.ref_closed_from = `isinara ang isyung ito %[4]s%[2]s`
issues.review.wait = hiniling sa pagsuri %s
issues.review.reject = hinihiling ang mga pagbago %s
@@ -2015,14 +2015,14 @@ wiki.cancel = Kanselahin
settings.collaboration.undefined = Hindi Natukoy
settings.federation_settings = Mga Setting ng Federation
settings = Mga Setting
-settings.desc = Ang mga setting ang lugar kung saan maari mong ipamahala ang mga setting para sa repositoryo
+settings.desc = Ang mga setting ang lugar kung saan maaari mong ipamahala ang mga setting para sa repositoryo
pulls.collapse_files = I-collapse ang lahat ng mga file
pulls.add_prefix = Magdagdag ng %s na prefix
pulls.still_in_progress = Ginagawa pa?
activity.title.prs_1 = %d hiling sa paghila
activity.active_issues_count_n = %d mga aktibong isyu
pulls.required_status_check_missing = Nawawala ang ilang mga kinakailangang pagsusuri.
-pulls.required_status_check_administrator = Bilang tagapangasiwa, maari mo pa ring isama ang hiling sa paghila na ito.
+pulls.required_status_check_administrator = Bilang tagapangasiwa, maaari mo pa ring isama ang hiling sa paghila na ito.
pulls.blocked_by_approvals = Wala pang sapat na pag-apruba ang hiling sa paghila na ito. %d ng %d na pag-apruba ang ibinigay.
settings.options = Repositoryo
wiki.back_to_wiki = Bumalik sa pahina ng wiki
@@ -2110,7 +2110,7 @@ settings.actions_desc = I-enable ang mga kasamang CI/CD pipeline gamit ang Forge
settings.admin_indexer_commit_sha = Huling na-index na commit
settings.admin_indexer_unindexed = Hindi naka-index
settings.transfer_notices_3 = - Kung pribado ang repositoryo at ilipat sa isang indibidwal na user, ang aksyon na ito ay sinisigurado na ang user ay may pahintulot na basahin (at palitan ang mga pahintulot kung kailangan).
-settings.convert_desc = Maari mong i-convert ang repositoryo na ito sa regular na repositoryo. Hindi ito mababawi.
+settings.convert_desc = Maaari mong i-convert ang repositoryo na ito sa regular na repositoryo. Hindi ito mababawi.
settings.transfer.button = Ilipat ang pagmamay-ari
settings.signing_settings = Mga setting sa pagpapatunay ng pag-sign
settings.admin_enable_close_issues_via_commit_in_any_branch = Isara ang isyu sa pamamagitan ng commit na ginawa sa hindi default na branch
@@ -2137,7 +2137,7 @@ settings.deploy_key_deletion = Tanggalin ang deploy key
settings.protect_enable_push = I-enable ang pagtulak
settings.discord_icon_url.exceeds_max_length = Kailangang bababa o equal sa 2048 characters ang URL ng icon
settings.protected_branch.save_rule = I-save ang rule
-settings.mirror_settings.docs.can_still_use = Bagama't na hindi ka makakabago ng mga umiiral na mirror o gumawa ng bago, maari mo pa rin gamitin ang iyong umiiral na mirror.
+settings.mirror_settings.docs.can_still_use = Bagama't na hindi ka makakabago ng mga umiiral na mirror o gumawa ng bago, maaari mo pa rin gamitin ang iyong umiiral na mirror.
settings.slack_color = Kulay
settings.discord_icon_url = URL ng icon
settings.convert_fork_confirm = I-convert ang repositoryo
@@ -2254,7 +2254,7 @@ settings.pulls.allow_rebase_update = I-enable ang pag-update ng hiling sa paghil
settings.admin_enable_health_check = I-enable ang pagsusuri ng kalusugan ng repositoryo (git fsck)
settings.new_owner_has_same_repo = Ang bagong may-ari ay may repositoryo na may katulad na pangalan. Mangyaring pumili ng ibang pangalan.
settings.convert = I-convert sa regular na repositoryo
-settings.convert_fork_desc = Maari mong i-convert ang fork na ito bilang regular na repositoryo. Hindi ito mababawi.
+settings.convert_fork_desc = Maaari mong i-convert ang fork na ito bilang regular na repositoryo. Hindi ito mababawi.
settings.convert_fork_notices_1 = Ang operasyon na ito ay ico-convert ang fork bilang regular na repositoryo at hindi mababawi.
settings.transfer_abort_invalid = Hindi mo makakansela ang isang hindi umiiral na paglipat ng repositoryo.
settings.transfer_quota_exceeded = Ang bagong may-ari (%s) ay lumalagpas sa quota. Hindi nailipat ang repositoryo.
@@ -2290,8 +2290,8 @@ settings.webhook.headers = Mga header
settings.webhook.payload = Nilalaman
settings.webhook.body = Katawan
settings.webhook.replay.description = I-replay ang webhook na ito.
-settings.webhook.delivery.success = May nadagdag na event sa delivery queue. Maari magtagal ng ilang segundo bago makita sa delivery history.
-settings.githooks_desc = Pinapagana ng Git ang mga Git hook. Maari mong baguhin ang mga hook file sa ibaba para mag-set up ng mga custom na operasyon.
+settings.webhook.delivery.success = May nadagdag na event sa delivery queue. Maaari magtagal ng ilang segundo bago makita sa delivery history.
+settings.githooks_desc = Pinapagana ng Git ang mga Git hook. Maaari mong baguhin ang mga hook file sa ibaba para mag-set up ng mga custom na operasyon.
settings.githook_name = Pangalan ng hook
settings.githook_content = Nilalaman ng hook
settings.update_githook = I-update ang hook
@@ -2362,7 +2362,7 @@ settings.mirror_settings.docs.pull_mirror_instructions = Para mag-set up ng pull
milestones.invalid_due_date_format = Kailangang "yyyy-mm-dd" na format ang takdang petsa.
signing.wont_sign.nokey = Walang key ang instansya na ito para i-sign ang commit na ito.
activity.title.releases_1 = %d paglabas
-settings.mirror_settings.docs.more_information_if_disabled = Maari kang matuto pa tungkol sa mga push at pull na mirror dito:
+settings.mirror_settings.docs.more_information_if_disabled = Maaari kang matuto pa tungkol sa mga push at pull na mirror dito:
settings.branches.switch_default_branch = Magpalit ng default branch
settings.convert_notices_1 = Ang operasyon na ito ay ico-covert ang mirror sa regular na repositoryo at hindi mababawi.
settings.convert_fork_succeed = Na-convert na ang fork sa regular na repositoryo.
@@ -2732,7 +2732,7 @@ settings.protect_protected_file_patterns = Mga pattern ng nakaprotektang file (h
settings.update_protect_branch_success = Binago na ang branch protection rule na "%s".
settings.remove_protected_branch_success = Tinanggal ang branch protection rule na "%s".
settings.tags.protection.pattern = Pattern ng tag
-settings.tags.protection.pattern.description = Maari kang gumamit ng iisang pangalan o glob pattern o regular expression para magtugma ng maraming tag. Magbasa pa sa guide ng mga nakaprotektang tag.
+settings.tags.protection.pattern.description = Maaari kang gumamit ng iisang pangalan o glob pattern o regular expression para magtugma ng maraming tag. Magbasa pa sa guide ng mga nakaprotektang tag.
settings.thread_id = ID ng thread
settings.matrix.room_id = ID ng room
diff.has_escaped = May mga nakatagong Unicode character ang linya na ito
@@ -2746,7 +2746,7 @@ diff.bin = BIN
settings.default_update_style_desc = Ang default na istilio na gagamitin sa pag-update ng mga hiling sa paghila na nalilipas sa base branch.
pulls.sign_in_require = Mag-sign in para gumawa ng bagong hiling sa paghila.
new_from_template = Gumamit ng template
-new_from_template_description = Maari kang pumili ng umiiral na repository template sa instansya na ito at i-apply ang mga setting nito.
+new_from_template_description = Maaari kang pumili ng umiiral na repository template sa instansya na ito at i-apply ang mga setting nito.
new_advanced = Mga advanced na setting
new_advanced_expand = I-click para i-expand
auto_init_description = Simulan ang kasaysayan ng Git gamit ang README at opsyonal na magdagdag ng mga lisensya at .gitignore na file.
@@ -2780,6 +2780,7 @@ settings.event_action_recover = I-recover
settings.event_action_success = Matagumpay
settings.event_action_success_desc = Matagumpay na natapos ang Action Run.
settings.event_action_recover_desc = Matagumpay na natapos ang Action Run pagkatapos na nabigo ang huling Action Run sa katulad na workflow.
+issues.filter_type.all_pull_requests = Lahat ng mga hiling sa paghila
[search]
commit_kind = Maghanap ng mga commit…
@@ -3205,7 +3206,7 @@ self_check.database_collation_mismatch = Inaasahan ang database na gamitin ang c
auths.oauth2_admin_group = Group claim value para sa mga tagapangasiwa. (Opsyonal - kinakailangan ang claim name sa itaas)
auths.tip.facebook = Magrehistro ng bagong application sa %s at idagdag ang produktong "Facebook Login"
users.restricted.description = Payagan lamang ang interaksyon sa mga repositoryo at organisasyon kung saan ang user ay dinagdag bilang tagatulong. Iniiwasan nito ang pag-access sa publikong repositoryo sa instansya na ito.
-users.local_import.description = Payagan ang pag-import ng mga repositoryo mula sa local file system ng user. Maari itong maging isyu sa seguridad.
+users.local_import.description = Payagan ang pag-import ng mga repositoryo mula sa local file system ng user. Maaari itong maging isyu sa seguridad.
emails.delete = Burahin ang Email
emails.deletion_success = Binura na ang email address.
auths.oauth2_required_claim_value = Kinakailangan na claim value
@@ -3450,8 +3451,8 @@ teams.owners_permission_desc = Ang mga owner ay may punong access sa lah
teams.add_nonexistent_repo = Hindi pa umiiral ang repositoryo na sinusubukan mong idagdag. Mangyaring gawin iyan muna.
teams.all_repositories = Lahat ng mga repositoryo
teams.all_repositories_helper = Ang koponan ay may access sa lahat ng mga repositoryo. Ang pagpili nito ay idadagdag ang lahat ng mga umiiral na repositoryo sa koponan.
-settings.change_orgname_redirect_prompt.with_cooldown.few = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang pangalan sa panahon ng cooldown.
-settings.change_orgname_redirect_prompt.with_cooldown.one = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang pangalan ng panahon ng cooldown.
+settings.change_orgname_redirect_prompt.with_cooldown.few = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang pangalan sa panahon ng cooldown.
+settings.change_orgname_redirect_prompt.with_cooldown.one = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang pangalan ng panahon ng cooldown.
[packages]
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 3fcfda18bd..db9872236b 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -1062,8 +1062,8 @@ language.localization_project = Aidez-nous à traduire Forgejo dans votre langue
language.description = Cette langue sera enregistrée dans votre compte et utilisée comme langue par défaut après votre connexion.
user_block_yourself = Vous ne pouvez pas vous bloquer vous même.
pronouns_custom_label = Pronoms personnalisés
-change_username_redirect_prompt.with_cooldown.one = L'ancien pseudonyme sera disponible pour n'importe qui après une période d'%[1]d jour, vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période.
-change_username_redirect_prompt.with_cooldown.few = L'ancien pseudonyme sera disponible pour n'importe qui après une période de %[1]d jours, vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période.
+change_username_redirect_prompt.with_cooldown.one = L'ancien pseudonyme sera disponible pour n'importe qui après une période d'%[1]d jour. Vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période.
+change_username_redirect_prompt.with_cooldown.few = L'ancien pseudonyme sera disponible pour n'importe qui après une période de %[1]d jours. Vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période.
quota.rule.exceeded = Dépassé
regenerate_token = Régénérer
access_token_regeneration = Régénérer le token d'accès
@@ -1579,7 +1579,7 @@ issues.remove_ref_at=`a supprimé la référence %s %s.`
issues.add_ref_at=`a ajouté la référence %s %s.`
issues.delete_branch_at=`a supprimé la branche %s %s.`
issues.filter_label=Label
-issues.filter_label_exclude=`Utilisez Alt
+ Clic/entrée
pour exclure les labels.`
+issues.filter_label_exclude=`Utilisez Alt + Click pour exclure les étiquettes.`
issues.filter_label_no_select=Toutes les labels
issues.filter_label_select_no_label=Aucun label
issues.filter_milestone=Jalon
@@ -1653,13 +1653,13 @@ issues.close_comment_issue=Fermer avec le commentaire
issues.reopen_issue=Rouvrir
issues.reopen_comment_issue=Réouvrir avec le commentaire
issues.create_comment=Commenter
-issues.closed_at=`a fermé ce ticket %[2]s.`
-issues.reopened_at=`a rouvert ce ticket %[2]s.`
-issues.commit_ref_at=`a référencé ce ticket depuis une révision %[2]s.`
-issues.ref_issue_from=`a fait référence à %[4]s ce ticket %[2]s.`
-issues.ref_pull_from=`a fait référence à cette demande d'ajout %[4]s %[2]s.`
-issues.ref_closing_from=`a fait référence à une demande d'ajout %[4]s qui clora ce ticket, %[2]s.`
-issues.ref_reopening_from=`a référencé une pull request %[4]s qui va ré-ouvrir ce ticket %[2]s`
+issues.closed_at=`a fermé ce ticket %s`
+issues.reopened_at=`a rouvert ce ticket %s`
+issues.commit_ref_at=`a référencé ce ticket depuis une révision %s`
+issues.ref_issue_from=`a fait référence à ce ticket %[3]s %[1]s`
+issues.ref_pull_from=`a fait référence à cette demande d'ajout %[3]s %[1]s`
+issues.ref_closing_from=`a fait référence à une demande d'ajout %[3]s qui clora ce ticket, %[1]s`
+issues.ref_reopening_from=`a référencé ce ticket dans une pull request %[3]s qui va ré-ouvrir ce ticket, %[1]s`
issues.ref_closed_from=`a fermé ce ticket %[4]s %[2]s`
issues.ref_reopened_from=`a rouvert ce ticket %[4]s %[2]s.`
issues.ref_from=`de %[1]s`
@@ -1967,8 +1967,8 @@ pulls.update_branch_success=La mise à jour de la branche a réussi
pulls.update_not_allowed=Vous n'êtes pas autorisé à mettre à jour la branche
pulls.outdated_with_base_branch=Cette branche est désynchronisée avec la branche de base
pulls.close=Fermer la demande d’ajout
-pulls.closed_at=`a fermé cette demande d'ajout %[2]s.`
-pulls.reopened_at=`a rouvert cette demande d'ajout %[2]s.`
+pulls.closed_at=`a fermé cette demande d'ajout %s`
+pulls.reopened_at=`a rouvert cette demande d'ajout %s`
pulls.cmd_instruction_hint=Voir les instructions en ligne de commande
pulls.cmd_instruction_checkout_title=Basculer
pulls.cmd_instruction_checkout_desc=Depuis votre dépôt, basculer sur une nouvelle branche et tester des modifications.
@@ -2762,7 +2762,7 @@ issues.blocked_by_user = Vous ne pouvez pas créer de tickets sur ce dépôt car
pulls.blocked_by_user = Vous ne pouvez pas créer une pull request sur ce dépôt car vous êtes bloqué par son propriétaire.
wiki.cancel = Annuler
settings.wiki_globally_editable = Permettre l'édition du wiki a tout le monde
-pulls.commit_ref_at = `a référencé cette pull request depuis le commit %[2]s`
+pulls.commit_ref_at = `a référencé cette pull request depuis un commit %s`
settings.new_owner_blocked_doer = Le nouveau propriétaire vous a bloqué.
settings.enter_repo_name = Confirmez en entrant le propriétaire et le nom du dépôt exactement comme affiché :
settings.wiki_rename_branch_main = Normalise le nom de la branche du Wiki
@@ -3058,8 +3058,8 @@ teams.invite.by=Invité par %s
teams.invite.description=Veuillez cliquer sur le bouton ci-dessous pour rejoindre l’équipe.
follow_blocked_user = Vous ne pouvez pas suivre cette organisation car elle vous a bloqué.
open_dashboard = Ouvrir le tableau de bord
-settings.change_orgname_redirect_prompt.with_cooldown.few = L'ancien nom d'organisation sera disponible pour n'importe qui après une période de %[1]d jours, vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période.
-settings.change_orgname_redirect_prompt.with_cooldown.one = L'ancien nom d'organisation sera disponible pour n'importe qui après une période d'%[1]d jour, vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période.
+settings.change_orgname_redirect_prompt.with_cooldown.few = L'ancien nom d'organisation sera disponible pour n'importe qui après une période de %[1]d jours. Vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période.
+settings.change_orgname_redirect_prompt.with_cooldown.one = L'ancien nom d'organisation sera disponible pour n'importe qui après une période d'%[1]d jour. Vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période.
[admin]
dashboard=Tableau de bord
@@ -4091,4 +4091,4 @@ issues.write = Écrire : Fermer des tickets et gérer les métadonnées t
pulls.read = Lire : Lire et créer des demandes de tirage.
[translation_meta]
-test = Ceci est une chaîne de test. Elle n'est pas affichée dans l'interface de Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce difficile 100 % de complétion. :-)
+test = Ceci est une chaîne de test. Elle n'est pas affichée dans Forgejo même mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce difficile 100 % de complétion. :-)
diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini
index d2d960b627..c8f4d2a72c 100644
--- a/options/locale/locale_ga-IE.ini
+++ b/options/locale/locale_ga-IE.ini
@@ -132,20 +132,20 @@ fuzzy = Doiléir
fuzzy_tooltip = Cuir san áireamh torthaí a mheaitseálann an téarma cuardaigh go dlúth freisin
exact = Beacht
exact_tooltip = Ní chuir san áireamh ach torthaí a mheaitseálann leis an téarma
-repo_kind = Cuardaigh stórtha...
-user_kind = Cuardaigh úsáideoirí...
-org_kind = Cuardaigh eagraíochtaí...
-team_kind = Cuardaigh foirne...
-code_kind = Cód cuardaigh...
+repo_kind = Cuardaigh stórtha…
+user_kind = Cuardaigh úsáideoirí…
+org_kind = Cuardaigh eagraíochtaí…
+team_kind = Cuardaigh foirne…
+code_kind = Cód cuardaigh…
code_search_unavailable = Níl cuardach cód ar fáil faoi láthair. Déan teagmháil le riarthóir an láithreáin.
-package_kind = Cuardaigh pacáistí...
-project_kind = Cuardaigh tionscadail...
-branch_kind = Cuardaigh brainsí...
-commit_kind = Cuardaigh tiomáintí...
-runner_kind = Cuardaigh reathaithe...
+package_kind = Cuardaigh pacáistí…
+project_kind = Cuardaigh tionscadail…
+branch_kind = Cuardaigh brainsí…
+commit_kind = Cuardaigh tiomáintí…
+runner_kind = Cuardaigh reathaithe…
no_results = Níl aon torthaí meaitseála le fáil.
-issue_kind = Saincheisteanna cuardaigh...
-pull_kind = Cuardaigh iarratais tarraingthe...
+issue_kind = Saincheisteanna cuardaigh…
+pull_kind = Cuardaigh iarratais tarraingthe…
keyword_search_unavailable = Níl cuardach de réir eochairfhocal ar fáil faoi láthair. Déan teagmháil le riarthóir an láithreáin.
[aria]
@@ -507,12 +507,12 @@ avatar = Abhatár
ssh_gpg_keys = Eochracha SSH/GPG
applications = Iarratais
repos = Stórais
-delete = Scrios Cuntas
+delete = Scrios cuntas
twofa = Fíordheimhniú Dhá Fachtóir (TOTP)
organization = Eagraíochtaí
uid = UID
webauthn = Fíordheimhniú Dhá-Fachtóir (Eochracha Slándála)
-public_profile = Próifíl Phoiblí
+public_profile = Próifíl phoiblí
location_placeholder = Comhroinn do shuíomh thart le daoine eile
full_name = Ainm Iomlán
website = Láithreán Gréasáin
@@ -1219,11 +1219,11 @@ issues.close_comment_issue = Dún le trácht
issues.reopen_issue = Athoscail
issues.reopen_comment_issue = Athoscail le trácht
issues.create_comment = Trácht
-issues.closed_at = `dhún an cheist seo %[2]s`
-issues.reopened_at = `athoscail an t-eagrán seo %[2]s`
-issues.commit_ref_at = `rinne tagairt don cheist seo ó ghealltanas %[2]s`
-issues.ref_issue_from = `rinne dagairt don cheist seo %[4]s %[2]s`
-issues.ref_pull_from = `rinne dagairt don iarratas tarraingthe seo %[4]s %[ 2]s`
+issues.closed_at = `dhún an cheist seo %s`
+issues.reopened_at = `athoscail an t-eagrán seo %s`
+issues.commit_ref_at = `rinne tagairt don cheist seo ó ghealltanas %s`
+issues.ref_issue_from = `rinne dagairt don cheist seo %[3]s %[1]s`
+issues.ref_pull_from = `rinne dagairt don iarratas tarraingthe seo %[3]s %[1]s`
issues.ref_closed_from = `dhún an cheist seo %[4]s %[2]s`
issues.ref_reopened_from = `d'athoscail an eagrán seo %[4]s %[2]s`
issues.ref_from = `ó %[1]s`
@@ -1456,8 +1456,8 @@ pulls.update_branch_success = Bhí nuashonrú brainse rathúil
pulls.update_not_allowed = Ní cheadaítear duit brainse a nuashonrú
pulls.outdated_with_base_branch = Tá an brainse seo as dáta leis an mbunbhrainse
pulls.close = Dún Iarratas Tarraing
-pulls.closed_at = `dhún an t-iarratas tarraingthe seo %[2]s`
-pulls.reopened_at = `athoscail an t-iarratas tarraingthe seo %[2]s`
+pulls.closed_at = `dhún an t-iarratas tarraingthe seo %s`
+pulls.reopened_at = `athoscail an t-iarratas tarraingthe seo %s`
pulls.cmd_instruction_checkout_title = Seiceáil
pulls.cmd_instruction_checkout_desc = Ó stór tionscadail, seiceáil brainse nua agus déan tástáil ar na hathruithe.
pulls.cmd_instruction_merge_title = Cumaisc
diff --git a/options/locale/locale_gl.ini b/options/locale/locale_gl.ini
index 3854b375af..c380e9b2ff 100644
--- a/options/locale/locale_gl.ini
+++ b/options/locale/locale_gl.ini
@@ -196,29 +196,29 @@ link_modal.paste_reminder = Consello: Coa URL no portapapeis, podes pegala direc
[search]
search = Buscar...
type_tooltip = Tipo de procura
-repo_kind = Buscar repositorios...
-user_kind = Buscar usuarios...
+repo_kind = Buscar repositorios…
+user_kind = Buscar usuarios…
regexp = RegExp
regexp_tooltip = Interpretar o termo da procura como expresión regular
-org_kind = Procurar organizacións...
-team_kind = Procurar equipos...
-code_kind = Procurar código...
+org_kind = Procurar organizacións…
+team_kind = Procurar equipos…
+code_kind = Procurar código…
code_search_unavailable = A procura de código non está dispoñible neste momento. Por favor contacte coa persoa responsable da administración da páxina.
-package_kind = Buscar paquetes...
+package_kind = Buscar paquetes…
fuzzy = Difusa
fuzzy_tooltip = Incluír resultados que tamén coincidan estreitamente co termo da procura
union = Palabras clave
union_tooltip = Incluír resultados correspondentes a calquera dal palabras clave separadas por espazos en branco
exact = Exacta
exact_tooltip = Incluír só resultados correspondentes ao termo exacto da procura
-issue_kind = Procurar incidencias...
-project_kind = Buscar proxectos...
-branch_kind = Buscar ramas...
+issue_kind = Procurar incidencias…
+project_kind = Buscar proxectos…
+branch_kind = Buscar ramas…
no_results = Non se atoparon resultados coincidentes.
keyword_search_unavailable = A busca por palabra clave non está dispoñible actualmente. Póñase en contacto co administrador do sitio.
-commit_kind = Buscar achegas...
-runner_kind = Buscar executores...
-pull_kind = Buscar pulls...
+commit_kind = Buscar achegas…
+runner_kind = Buscar executores…
+pull_kind = Buscar pulls…
[startpage]
platform = Multiplataforma
diff --git a/options/locale/locale_he.ini b/options/locale/locale_he.ini
index 19c4815277..26e3084809 100644
--- a/options/locale/locale_he.ini
+++ b/options/locale/locale_he.ini
@@ -1,6 +1,3 @@
-
-
-
[common]
webauthn_error_unable_to_process = שרת זה נכשל בעיבוד בקשתך.
help = עזרה
@@ -150,24 +147,24 @@ union = מילות מפתח
exact = מדויק
exact_tooltip = תוצאות יתאימו במדויק לתוכן תיבת החיפוש
regexp = רג'קס
-user_kind = חיפוש אנשים...
-code_kind = חיפוש קוד...
-team_kind = חיפוש צוותים...
+user_kind = חיפוש אנשים…
+code_kind = חיפוש קוד…
+team_kind = חיפוש צוותים…
no_results = לא נמצאו תוצאות.
union_tooltip = תוצאות יכללו לפחות מילת מפתח אחת; אפשר להפריד מילות מפתח עם רווחים
-org_kind = חיפוש ארגונים...
-package_kind = חיפוש חבילות...
-project_kind = חיפוש פרוייקטים...
-branch_kind = חיפוש ענפים...
-commit_kind = חיפוש קומיטים...
-issue_kind = חיפוש סוגיות...
+org_kind = חיפוש ארגונים…
+package_kind = חיפוש חבילות…
+project_kind = חיפוש פרוייקטים…
+branch_kind = חיפוש ענפים…
+commit_kind = חיפוש קומיטים…
+issue_kind = חיפוש סוגיות…
fuzzy_tooltip = תוצאות יתאימו לתוכן תיבת החיפוש בקירוב; מומלץ כנגד שגיאות כתיב
-repo_kind = חיפוש קרפיפים...
+repo_kind = חיפוש קרפיפים…
code_search_by_git_grep = תוצאות החיפוש יוצרו על ידי "git grep"; יכול להיות שיתקבלו תוצאות טובות יותר אם מנהלי המערכת יפעילו את המפתחן.
-runner_kind = חיפוש מריצים...
+runner_kind = חיפוש מריצים…
keyword_search_unavailable = חיפוש מילות מפתח לא זמין. נא לדווח למנהלי המערכת.
code_search_unavailable = חיפוש קוד לא זמין. נא לדווח למנהלי המערכת.
-pull_kind = חיפוש בקשות מיזוג...
+pull_kind = חיפוש בקשות מיזוג…
[heatmap]
number_of_contributions_in_the_last_12_months = % תרומות ב־12 החודשים האחרונים
@@ -385,6 +382,9 @@ account_activated = חשבונך הופעל
resent_limit_prompt = כבר ביקשת מייל אימות בשלושת הדקות האחרונות. נא לחכות ולנסות שוב.
has_unconfirmed_mail = שלום %s, חשבונך משויך לכתובת אימייל לא מאומתת (%s). אם לא קיבלת הודעת אימות באימייל, או שאתה צריך חדשה, נא ללחוץ על הכפתור למטה.
+confirmation_mail_sent_prompt = אימייל אימות חדש נשלח ל־%s. יש לבדוק את תיבת הדואר וללחוץ על הלינק תוך %s על מנת להשלים את רישום החשבון. אם כתובת המייל שגוייה, אפשר להיכנס לחשבון ולבקש דוא"ל אימות לכתובת אחרת.
+reset_password_mail_sent_prompt = אימייל אימות חדש נשלח ל־%s. יש לבדוק את תיבת הדואר וללחוץ על הלינק תוך %s על מנת להשלים את רישום החשבון.
+
[settings]
key_content = תוכן
principal_content = תוכן
@@ -469,7 +469,7 @@ uploaded_avatar_not_a_image = הקובץ שהועלה לא תמונה.
[repo]
new_advanced = הגדרות מתקדמות
-new_advanced_expand =
+new_advanced_expand =
owner = בעלים
repo_name = שם הקרפיף
repo_name_helper = שמות קרפיפים טובים הם זכירים, קצרים וייחודיים.
@@ -662,6 +662,10 @@ issues.label_archive = לארכיון
issues.label_archived_filter = הצגת תוויות מהארכיון
issues.label_archive_tooltip = תוויות בארכיון לא מוצעות בחיפוש על־בסיס תווית כברירת מחדל.
+issues.deleted_milestone = נמחק
+issues.deleted_project = נמחק
+issues.self_assign_at = `שייךה עצמית %s`
+
[translation_meta]
test = ואהבת לרעך כמוך
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index 411bad835a..c6eca84ac7 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -330,7 +330,7 @@ code_no_results=Nincs találat a keresési kifejezésedre.
code_last_indexed_at=Utoljára indexelve: %s
[auth]
-create_new_account=Regisztráció
+create_new_account=Fiók regisztrálása
register_helper_msg=Van már felhasználói fiókja? Jelentkezzen be!
social_register_helper_msg=Van már felhasználói fiókja? Csatlakoztassa most!
disable_register_prompt=Regisztráció le van tiltva. Kérjük, lépjen kapcsolatba az oldal adminisztrátorával.
@@ -532,8 +532,8 @@ password_change_disabled=A nem helyi felhasználók nem frissíthetik jelszavuka
emails=E-mail címek
manage_emails=E-mail címek kezelése
-manage_themes=Válassza ki az alapértelmezett témát
-manage_openid=OpenID címek kezelése
+manage_themes=Alapértelmezett téma
+manage_openid=OpenID címek
theme_desc=Ez lesz az alapértelmezett téma az oldalon.
primary=Elsődleges
activated=Aktivált
@@ -932,7 +932,7 @@ issues.close_comment_issue=Hozzászólás és lezárás
issues.reopen_issue=Újranyitás
issues.reopen_comment_issue=Hozzászólás és újranyitás
issues.create_comment=Hozzászólás
-issues.commit_ref_at=`hivatkozott erre a hibajegyre egy commit-ból %[2]s`
+issues.commit_ref_at=`hivatkozott erre a hibajegyre egy commit-ból %s`
issues.role.owner=Tulajdonos
issues.role.member=Tag
issues.re_request_review=Véleményezés újrakérése
@@ -1779,14 +1779,14 @@ directory = Könyvtár
[search]
search = Keresés...
type_tooltip = Keresés típusa
-code_kind = Kód keresése...
+code_kind = Kód keresése…
code_search_unavailable = A kódban való keresés jelenleg nem elérhető. Kérem vegye fel a kapcsolatot az oldal adminisztrátorával.
-package_kind = Csomagok keresése...
-project_kind = Projektek keresése...
-user_kind = Felhasználók keresése...
-repo_kind = Tárak keresése...
-org_kind = Szervezetek keresése...
-team_kind = Csapatok keresése...
+package_kind = Csomagok keresése…
+project_kind = Projektek keresése…
+user_kind = Felhasználók keresése…
+repo_kind = Tárak keresése…
+org_kind = Szervezetek keresése…
+team_kind = Csapatok keresése…
exact = Pontos
code_search_by_git_grep = A kódkeresés jelenleg a "git grep" parancsot használja. Lehet, hogy jobb találatok is lennének, ha a webhely adminisztrátora bekapcsolja a forráskód indexelését.
milestone_kind = Mérföldkövek keresése...
@@ -1794,8 +1794,8 @@ fuzzy_tooltip = A keresési kifejezéshez hasonló találatok mutatása
fuzzy = Hasonlók
union = Kulcsszavakra
union_tooltip = A szóközzel elválasztott kulcsszavak bármelyikét tartalmazó találatok mutatása
-branch_kind = Ágak keresése...
+branch_kind = Ágak keresése…
no_results = Nincsenek megfelelő találatok.
-issue_kind = Hibajegyek keresése...
+issue_kind = Hibajegyek keresése…
exact_tooltip = Csak a keresési kifejezést pontosan tartalmazó találatok mutatása
keyword_search_unavailable = A kulcsszó alapú keresés jelenleg nem elérhető. Kérlek értesítsd az oldal rendszergazdáját.
diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini
index 673d1464b1..56993bec0d 100644
--- a/options/locale/locale_id-ID.ini
+++ b/options/locale/locale_id-ID.ini
@@ -206,9 +206,9 @@ email_title = Pengaturan email
smtp_from = Kirim Email Sebagai
[home]
-uname_holder=Nama Pengguna atau Alamat Surel
+uname_holder=Nama pengguna atau alamat surel
password_holder=Kata Sandi
-switch_dashboard_context=Alihkan Dasbor Konteks
+switch_dashboard_context=Alihkan dasbor konteks
my_repos=Repositori
show_more_repos=Tampilkan repositori lainnya…
collaborative_repos=Repositori Kolaboratif
@@ -236,7 +236,7 @@ org_no_results=Tidak ada organisasi yang cocok ditemukan.
code_no_results=Tidak ada kode sumber yang cocok dengan istilah yang anda cari.
[auth]
-create_new_account=Daftar Akun
+create_new_account=Daftar akun
register_helper_msg=Sudah memiliki akun? Masuk sekarang!
social_register_helper_msg=Sudah memiliki akun? Hubungkan sekarang!
disable_register_prompt=Maaf, pendaftaran telah dinonaktifkan. Silakan hubungi administrator situs.
@@ -269,11 +269,11 @@ twofa_passcode_incorrect=Kata sandi Anda salah. Jika Anda salah tempatkan perang
twofa_scratch_token_incorrect=Kode coretan anda tidak tepat.
login_userpass=Masuk
tab_openid=OpenID
-oauth_signup_tab=Daftar Akun Baru
-oauth_signup_submit=Akun Lengkap
-oauth_signin_tab=Tautkan ke Akun yang Tersedia
-oauth_signin_title=Masuk untuk Izinkan Akun Tertaut
-oauth_signin_submit=Taut Akun
+oauth_signup_tab=Daftar akun baru
+oauth_signup_submit=Akun lengkap
+oauth_signin_tab=Tautkan ke akun yang tersedia
+oauth_signin_title=Masuk untuk izinkan akun tertaut
+oauth_signin_submit=Taut akun
openid_connect_submit=Sambungkan
openid_connect_title=Sambungkan ke akun yang sudah ada
openid_connect_desc=OpenID URI yang dipilih tak dikenal. Asosiasikan dengan akun baru disini.
@@ -398,14 +398,14 @@ avatar=Avatar
ssh_gpg_keys=Kunci SSH / GPG
social=Akun Sosial
applications=Aplikasi
-orgs=Kelola organisasi
+orgs=Organisasi
repos=Repositori
-delete=Hapus Akun
+delete=Hapus akun
twofa=Otentikasi Dua-Faktor
account_link=Akun Tertaut
organization=Organisasi
-public_profile=Profil Publik
+public_profile=Profil publik
password_username_disabled=Pengguna non-lokal tidak diizinkan untuk mengubah nama pengguna mereka. Silakan hubungi administrator sistem anda untuk lebih lanjut.
full_name=Nama Lengkap
website=Situs Web
@@ -438,8 +438,8 @@ password_change_disabled=Pengguna non-lokal tidak dapat mengganti kata sandi mer
emails=Alamat Surel
manage_emails=Kelola Alamat Surel
-manage_themes=Pilih tema default
-manage_openid=Kelola alamat OpenID
+manage_themes=Tema default
+manage_openid=Alamat OpenID
theme_desc=Ini akan menjadi tema asal Anda pada keseluruhan situs.
primary=Utama
activated=Diaktifkan
@@ -796,7 +796,7 @@ issues.close_comment_issue=Komentar dan Tutup
issues.reopen_issue=Buka kembali
issues.reopen_comment_issue=Komentar dan Buka Kembali
issues.create_comment=Komentar
-issues.commit_ref_at=`merujuk masalah dari komit %[2]s`
+issues.commit_ref_at=`merujuk masalah dari komit %s`
issues.role.owner=Pemilik
issues.role.member=Anggota
issues.sign_in_require_desc=Masuk untuk bergabung dengan percakapan ini.
@@ -1484,10 +1484,10 @@ search = Cari...
type_tooltip = Tipe pencarian
fuzzy_tooltip = Termasuk juga hasil yang mendekati kata pencarian
exact_tooltip = Hanya menampilkan hasil yang cocok dengan istilah pencarian
-repo_kind = Cari repo...
-user_kind = Telusuri pengguna...
-org_kind = Cari organisasi...
-team_kind = Cari tim...
-code_kind = Cari kode...
+repo_kind = Cari repo…
+user_kind = Telusuri pengguna…
+org_kind = Cari organisasi…
+team_kind = Cari tim…
+code_kind = Cari kode…
code_search_unavailable = Pencarian kode saat ini tidak tersedia. Silahkan hubungi administrator.
-branch_kind = Cari cabang...
+branch_kind = Cari cabang…
diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini
index 9b1d56fed9..f3333dbea2 100644
--- a/options/locale/locale_is-IS.ini
+++ b/options/locale/locale_is-IS.ini
@@ -223,7 +223,7 @@ default_keep_email_private.description=Fela sjálfgefið netföng nýrra notenda
no_reply_address_helper=Lén fyrir notendur með falið netfang. Til dæmis notandanafnið „joe“ verður skráð í Git sem „joe@noreply.example.org“ ef falið tölvupóstlén er stillt á „noreply.example.org“.
[home]
-uname_holder=Notandanafn eða Netfang
+uname_holder=Notandanafn eða netfang
password_holder=Lykilorð
my_repos=Hugbúnaðarsöfn
show_more_repos=Sýna fleiri hugbúnaðarsöfn…
@@ -255,7 +255,7 @@ org_no_results=Engar samsvarandi stofnanir fundust.
code_no_results=Enginn samsvarandi frumkóði fannst eftur þínum leitarorðum.
[auth]
-create_new_account=Skrá Notanda
+create_new_account=Skrá notanda
register_helper_msg=Ertu nú þegar með notanda? Skráðu þig inn núna!
social_register_helper_msg=Ertu nú þegar með reikning? Tengdu hann núna!
manual_activation_only=Hafðu samband við stjórnanda vefsvæðisins til að ljúka virkjun.
@@ -276,13 +276,13 @@ verify=Staðfesta
scratch_code=Skrapkóði
use_scratch_code=Nota skrapkóða
twofa_scratch_token_incorrect=Skrapkóði þinn er rangur.
-login_userpass=Skrá Inn
+login_userpass=Skrá inn
tab_openid=OpenID
-oauth_signup_tab=Skrá Nýjan Notanda
-oauth_signup_title=Klára Nýjum Notanda
-oauth_signup_submit=Klára Notanda
-oauth_signin_tab=Tengja Núverandi Reikning
-oauth_signin_submit=Tengja Notanda
+oauth_signup_tab=Skrá nýjan notanda
+oauth_signup_title=Klára nýjum notanda
+oauth_signup_submit=Klára notanda
+oauth_signin_tab=Tengja núverandi reikning
+oauth_signin_submit=Tengja notanda
openid_connect_submit=Tengjast
openid_register_title=Skrá nýjan notanda
disable_forgot_password_mail=Endurheimting reiknings er óvirk vegna þess að enginn tölvupóstur er uppsettur. Vinsamlegast hafðu samband við síðustjórann þinn.
@@ -434,15 +434,15 @@ avatar=Notandamynd
ssh_gpg_keys=SSH og GPG Lyklar
social=Félagsreikningar
applications=Forrit
-orgs=Stjórna Stofnunum
+orgs=Stofnanir
repos=Hugbúnaðarsöfn
-delete=Eyða Reikningi
+delete=Eyða reikningi
twofa=Tvíþætt Auðkenning
account_link=Tengdir Reikningar
organization=Stofnanir
webauthn=Öryggislyklar
-public_profile=Opinber Notandasíða
+public_profile=Opinber notandasíða
password_username_disabled=Notendum utan staðarins er ekki heimilt að breyta notendanafni sínu. Vinsamlegast hafðu samband við síðustjórann þinn til að fá frekari upplýsingar.
full_name=Fullt Nafn
website=Vefsíða
@@ -805,8 +805,8 @@ issues.close_comment_issue=Senda ummæli og Loka
issues.reopen_issue=Enduropna
issues.reopen_comment_issue=Senda ummæli og Enduropna
issues.create_comment=Senda Ummæli
-issues.closed_at=`lokaði þessu vandamáli %[2]s`
-issues.reopened_at=`enduropnaði þetta vandamál %[2]s`
+issues.closed_at=`lokaði þessu vandamáli %s`
+issues.reopened_at=`enduropnaði þetta vandamál %s`
issues.ref_reopened_from=`enduropnaði þetta vandamál %[4]s %[2]s`
issues.author=Höfundur
issues.role.owner=Eigandi
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index 48995e951f..50405ed756 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -54,7 +54,7 @@ mirror=Mirror
new_repo=Nuovo repository
new_migrate=Nuova migrazione
new_mirror=Nuovo mirror
-new_fork=Nuova derivazione
+new_fork=Nuova biforcazione
new_org=Nuova organizzazione
new_project=Nuovo progetto
manage_org=Gestisci le organizzazioni
@@ -143,12 +143,12 @@ confirm_delete_selected = Confermare l'eliminazione di tutti gli elementi selezi
sign_in_with_provider = Accedi con %s
new_project_column = Nuova colonna
toggle_menu = Mostra/Nascondi menu
-filter.not_fork = Non fork
+filter.not_fork = Non biforcazioni
filter = Filtro
filter.clear = Rimuovi filtri
filter.is_archived = Archiviato
filter.not_archived = Non archiviato
-filter.is_fork = Da fork
+filter.is_fork = Biforcazioni
filter.is_mirror = Mirror
filter.not_mirror = Non mirror
filter.is_template = Modelli
@@ -209,6 +209,7 @@ table_modal.label.columns = Colonne
link_modal.header = Aggiungi collegamento
link_modal.url = Url
link_modal.description = Descrizione
+link_modal.paste_reminder = Suggerimento: se hai già copiato un URL negli appunti, puoi incollarlo direttamente nell’editor per creare un collegamento.
[filter]
string.asc = A - Z
@@ -232,6 +233,7 @@ lightweight_desc=Forgejo ha requisiti minimi bassi e può funzionare su un econo
license=Open Source
license_desc=Ottieni Forgejo! Partecipa per contribuire a rendere questo progetto ancora più bello. Non aver paura di diventare collaborante!
install_desc = Semplicemente avvia l'eseguibile per la tua piattaforma, distribuiscilo con Docker, oppure scarica il pacchetto.
+platform_desc = È stato verificato che Forgejo è pienamente compatibile con sistemi operativi liberi, come Linux e FreeBSD, nonché con diverse architetture CPU. Scegli liberamente la piattaforma che preferisci!
[install]
install=Installazione
@@ -396,12 +398,12 @@ go_to = Vai a
search.type.tooltip = Tipo di ricerca
search.fuzzy.tooltip = Includi anche i risultati che corrispondono parzialmente ai termini di ricerca
code_search_results = Risultati di ricerca per "%s"
-relevant_repositories_tooltip = I repositori derivati o che non hanno argomento, icona, né descrizione sono nascosti.
+relevant_repositories_tooltip = I repositori che sono biforcazioni o che non hanno argomento, icona, né descrizione sono nascosti.
relevant_repositories = Sono visibili solo i repositori pertinenti, mostra risultati non filtrati.
search.match.tooltip = Includi solo risultati che combaciano perfettamente con i termini di ricerca
stars_few = %d stelle
-forks_one = %d fork
-forks_few = %d fork
+forks_one = %d biforcazioni
+forks_few = %d biforcazioni
stars_one = %d stella
[auth]
@@ -421,7 +423,7 @@ allow_password_change=Richiede all'utente di cambiare la password (scelta consig
reset_password_mail_sent_prompt=Un'e-mail di conferma è stata inviata a %s. Per completare il processo di recupero dell'account, controlla la tua posta in arrivo e clicca sul link entro i prossimi %s secondi.
active_your_account=Attiva il tuo account
account_activated=L'account è stato attivato
-prohibit_login=L'accesso è proibito
+prohibit_login=L'account è sospeso
resent_limit_prompt=Hai già richiesto un'e-mail d'attivazione recentemente. Si prega di attenere 3 minuti e poi riprovare.
has_unconfirmed_mail=Ciao %s, hai un indirizzo di posta elettronica non confermato (%s). Se non hai ricevuto una e-mail di conferma o vuoi riceverla nuovamente, fare clic sul pulsante qui sotto.
resend_mail=Clicca qui per inviare nuovamente l'e-mail di attivazione
@@ -485,6 +487,8 @@ sign_in_openid = Procedi con OpenID
hint_login = Hai già un'utenza? Accedi!
hint_register = Non hai un'utenza? Registrati ora.
sign_up_button = Registrati ora.
+unauthorized_credentials = Le credenziali non sono corrette o sono scadute. Controlla il comando o vedi %s per maggiori informazioni
+use_onetime_code = Usa un codice monouso
[mail]
view_it_on=Visualizza su %s
@@ -680,6 +684,8 @@ Location = Posizione
AccessToken = Token di accesso
FullName = Nome e cognome
To = Nome del ramo
+email_domain_is_not_allowed = Il dominio dell'indirizzo email dell'utente %s è in conflitto con EMAIL_DOMAIN_ALLOWLIST o EMAIL_DOMAIN_BLOCKLIST. Assicurati di aver inserito correttamente l'indirizzo email.
+username_claiming_cooldown = Il nome utente non può essere assegnato, poiché il periodo di attesa non è ancora terminato. Sarà disponibile il %[1]s.
[user]
@@ -723,6 +729,7 @@ followers.title.one = Seguace
followers.title.few = Seguaci
following.title.one = Seguito
following.title.few = Osservato
+public_activity.visibility_hint.self_private_profile = Poiché il tuo profilo è privato, la tua attività è visibile solo a te e agli amministratori dell'istanza. Configura.
[settings]
@@ -735,7 +742,7 @@ avatar=Avatar
ssh_gpg_keys=Chiavi SSH / GPG
social=Account Sociali
applications=Applicazioni
-orgs=Gestisci le organizzazioni
+orgs=Organizzazioni
repos=Repositori
delete=Elimina account
twofa=Verifica in due passaggi
@@ -796,8 +803,8 @@ password_change_disabled=Gli utenti non locali non possono cambiare la loro pass
emails=Indirizzi email
manage_emails=Gestisci indirizzi email
-manage_themes=Seleziona il tema predefinito
-manage_openid=Gestisci gli indirizzi OpenID
+manage_themes=Tema predefinito
+manage_openid=Indirizzi OpenID
theme_desc=Questo sarà il tuo tema di predefinito in tutto il sito.
primary=Primario
activated=Attivato
@@ -1045,7 +1052,7 @@ added_on = Aggiunto su %s
additional_repo_units_hint = Suggerisci l'attivazione di unità aggiuntive nel repositorio
update_hints = Aggiorna suggerimenti
update_hints_success = I suggerimenti sono stati aggiornati.
-additional_repo_units_hint_description = Mostra un pulsante "Aggiungi più sezioni..." per i repositori che non hanno tutte le sezioni disponibili aggiunte.
+additional_repo_units_hint_description = Visualizza un suggerimento “Abilita altro” per i repositori che non hanno tutte le unità disponibili abilitate.
hints = Suggerimenti
pronouns = Pronomi
pronouns_custom = Personalizzato
@@ -1053,6 +1060,34 @@ pronouns_unspecified = Non specificato
language.title = Lingua predefinita
language.description = Questa lingua verrà salvata nella tua utenza e verrà usata come predefinita ogni volta che farai l'accesso.
language.localization_project = Aiutaci a tradurre Forgejo nella tua lingua! Più informazioni.
+quota.sizes.assets.attachments.all = Allegati
+quota.rule.no_limit = Illimitato
+quota.sizes.assets.attachments.releases = Allegati del rilascio
+quota.rule.exceeded = Superato
+regenerate_token = Rigenera
+access_token_regeneration = Rigenera il token d'accesso
+access_token_regeneration_desc = Rigenerare un token comporterà la revoca dell'accesso al tuo account per tutte le applicazioni che lo utilizzano. Questa operazione è irreversibile. Vuoi procedere?
+regenerate_token_success = Il token è stato rigenerato. Le applicazioni che lo utilizzano non hanno più accesso alla tua utenza e devono essere aggiornate con il nuovo token.
+user_block_yourself = Non puoi bloccare te stesso.
+quota.applies_to_user = Le seguenti regole di quota si applicano al tuo account
+quota.applies_to_org = Le seguenti regole di quota si applicano a questa organizzazione
+quota.rule.exceeded.helper = La dimensione totale degli oggetti per questa regola ha superato la quota.
+quota.sizes.all = Tutti
+quota.sizes.repos.all = Repositori
+quota.sizes.repos.public = Repositori pubblici
+quota.sizes.repos.private = Repositori privati
+quota.sizes.git.all = Contenuto git
+quota.sizes.git.lfs = Git LFS
+quota.sizes.assets.all = Risorse
+quota.sizes.assets.attachments.issues = Allegati della segnalazione
+quota.sizes.assets.artifacts = Artefatti
+quota.sizes.assets.packages.all = Pacchetti
+quota.sizes.wiki = Wiki
+keep_pronouns_private = Mostra i pronomi solo agli utenti che hanno effettuato il login
+keep_pronouns_private.description = Questa impostazione nasconderà i tuoi pronomi agli utenti non ancora autenticati.
+storage_overview = Panoramica spazio di archiviazione
+quota = Quota
+change_username_redirect_prompt.with_cooldown.one = Il vecchio nome utente sarà disponibile per tutti dopo un periodo di protezione di %\[1]d giorni. Durante questo periodo di attesa potrai comunque tornare al vecchio nome utente.
[repo]
owner=Proprietario
@@ -1067,10 +1102,10 @@ template_description=I modelli di repositori consentono allɜ utenti di generare
visibility=Visibilità
visibility_description=Solo il proprietario o i membri dell'organizzazione se hanno diritti, saranno in grado di vederlo.
visibility_helper_forced=L'amministratorə del sito impone che i nuovi repositori siano privati.
-visibility_fork_helper=(Questa modifica influenzerà la visibilità di tutti i fork.)
+visibility_fork_helper=(Questa modifica influenzerà la visibilità di tutte le biforcazioni.)
clone_helper=Hai bisogno di aiuto per la clonazione? Visita Help.
fork_repo=Deriva repositorio
-fork_from=Deriva da
+fork_from=Biforcazione di
already_forked=Hai già fatto il fork di %s
fork_to_different_account=Fai Fork a un account diverso
fork_visibility_helper=La visibilità di un repositorio derivato non può essere modificata.
@@ -1514,13 +1549,13 @@ issues.close_comment_issue=Commenta e chiudi
issues.reopen_issue=Riapri
issues.reopen_comment_issue=Commenta e riapri
issues.create_comment=Commento
-issues.closed_at=`ha chiuso questa segnalazione %[2]s`
-issues.reopened_at=`ha riaperto questa segnalazione %[2]s`
-issues.commit_ref_at=`ha fatto riferimento a questa segnalazione dal commit %[2]s`
-issues.ref_issue_from=`ha fatto riferimento a questa segnalazione %[4]s %[2]s`
-issues.ref_pull_from=`ha fatto riferimento a questa richiesta di modifica %[4]s %[2]s`
-issues.ref_closing_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[4]s che la chiuderà, %[2]s`
-issues.ref_reopening_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[4]s che la riaprirà, %[2]s`
+issues.closed_at=`ha chiuso questa segnalazione %s`
+issues.reopened_at=`ha riaperto questa segnalazione %s`
+issues.commit_ref_at=`ha fatto riferimento a questa segnalazione dal commit %s`
+issues.ref_issue_from=`ha fatto riferimento a questa segnalazione %[3]s %[1]s`
+issues.ref_pull_from=`ha fatto riferimento a questa richiesta di modifica %[3]s %[1]s`
+issues.ref_closing_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[3]s che la chiuderà, %[1]s`
+issues.ref_reopening_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[3]s che la riaprirà, %[1]s`
issues.ref_closed_from=`chiuso questa segnalazione %[4]s %[2]s`
issues.ref_reopened_from=`ha riaperto questa segnalazione %[4]s %[2]s`
issues.ref_from=`da %[1]s`
@@ -1718,7 +1753,7 @@ pulls.cannot_merge_work_in_progress=Questa richiesta di modifica è contrassegna
pulls.still_in_progress=Ancora in corso?
pulls.add_prefix=Aggiungi prefisso %s
pulls.remove_prefix=Rimuovi il prefisso %s
-pulls.data_broken=Questa richiesta di modifica è rovinata a causa di informazioni mancanti riguardo la derivazione.
+pulls.data_broken=Questa richiesta di modifica non è valida a causa di informazioni mancanti sulla biforcazione.
pulls.files_conflicted=Questa richiesta di modifica va in conflitto con il ramo di destinazione.
pulls.is_checking=Verifica dei conflitti di fusione in corso. Riprova tra qualche istante.
pulls.is_ancestor=Questo ramo è già incluso nel ramo di destinazione. Non c'è nulla da fondere.
@@ -1776,8 +1811,8 @@ pulls.update_branch_rebase=Aggiorna il ramo per cambio base
pulls.update_branch_success=Ramo aggiornato con successo
pulls.update_not_allowed=Non ti è permesso aggiornare il ramo
pulls.outdated_with_base_branch=Questo ramo non è aggiornato con il ramo di base
-pulls.closed_at=`ha chiuso questa richiesta di modifica %[2]s`
-pulls.reopened_at=`ha riaperto questa richiesta di modifica %[2]s`
+pulls.closed_at=`ha chiuso questa richiesta di modifica %s`
+pulls.reopened_at=`ha riaperto questa richiesta di modifica %s`
pulls.auto_merge_button_when_succeed=(Quando i controlli sono superati)
pulls.auto_merge_when_succeed=Unione automatica quando tutti i controlli sono superati
@@ -2100,7 +2135,7 @@ settings.event_create_desc=Ramo o etichetta creati.
settings.event_delete=Elimina
settings.event_delete_desc=Ramo o etichetta eliminati.
settings.event_fork=Deriva
-settings.event_fork_desc=Repository derivato.
+settings.event_fork_desc=Creata una biforcazione del repositorio.
settings.event_wiki=Wiki
settings.event_release=Release
settings.event_release_desc=Release pubblicata, aggiornata o rimossa in una repository.
@@ -2137,7 +2172,7 @@ settings.event_pull_request_sync_desc=Pull request sincronizzata.
settings.event_package=Pacchetto
settings.event_package_desc=Pacchetto creato o eliminato in un repository.
settings.branch_filter=Filtro rami
-settings.branch_filter_desc=Whitelist dei rami per gli eventi di spinta, creazione dei rami e cancellazione dei rami, specificati come modello globo. Se vuoto o *
, gli eventi per tutti i rami sono segnalati. Vedi la documentazione %[2]s per la sintassi. Esempi: master
, {master,release*}
.
+settings.branch_filter_desc=Filtro, scritto come pattern glob, da applicare ai rami per gli eventi di tipo immissione, creazione di rami e rimozione di rami. Se vuoto o *
, vengono considerati tutti gli eventi di tutti i rami. Maggiori dettagli sulla sintassi presso %[2]s. Esempi: master
, {master,release*}
.
settings.active=Attivo
settings.active_helper=Le informazioni sugli eventi innescati saranno inviate a questo URL del webhook.
settings.add_hook_success=Il webhook è stato aggiunto.
@@ -2167,8 +2202,8 @@ settings.web_hook_name_packagist=Packagist
settings.packagist_username=Nome utente Packagist
settings.packagist_api_token=API token
settings.packagist_package_url=Url pacchetto pacchetti
-settings.deploy_keys=Dispiega chiavi
-settings.add_deploy_key=Aggiungi chiave di dispiego
+settings.deploy_keys=Chiavi di distribuzione
+settings.add_deploy_key=Aggiungi chiave di distribuzione
settings.deploy_key_desc=Le deploy key possiedono l'accesso solamente alla lettura di un repository.
settings.is_writable=Abilita accesso scrittura
settings.is_writable_info=Permetti a questa deploy key di pushare nella repository.
@@ -2177,7 +2212,7 @@ settings.title=Titolo
settings.deploy_key_content=Contenuto
settings.key_been_used=Una deploy key con contenuto identico è già in uso.
settings.key_name_used=Esiste già una deploy key con questo nome.
-settings.deploy_key_deletion=Rimuovi chiave di dispiego
+settings.deploy_key_deletion=Rimuovi chiave di distribuzione
settings.deploy_key_deletion_desc=Rimuovere una chiave di distribuzione ne revocherà l'accesso a questo repository. Continuare?
settings.deploy_key_deletion_success=La chiave di distribuzione è stata rimossa.
settings.branches=Rami
@@ -2620,7 +2655,7 @@ issues.filter_type.reviewed_by_you = Revisionati da te
projects.edit_success = Il progetto "%s" è stato aggiornato.
issues.keyword_search_unavailable = La ricerca per parola chiave non è attualmente disponibile. Contatta l'amministratore del sito.
issues.role.collaborator_helper = Quest*utente è statə invitatə a collaborare al progetto.
-pulls.commit_ref_at = `ha fatto riferimento a questa richiesta di modifica da un commit %[2]s`
+pulls.commit_ref_at = `ha fatto riferimento a questa richiesta di modifica da un commit %s`
settings.thread_id = ID della discussione
release.title = Titolo del rilascio
visibility_helper = Rendi il repositorio privato
@@ -2660,7 +2695,7 @@ wiki.page_title = Titolo della pagina
wiki.page_content = Contenuto della pagina
settings.mirror_settings.pushed_repository = Repositorio immesso
settings.mirror_settings.push_mirror.edit_sync_time = Modifica intervallo di sincronizzazione degli specchi
-settings.units.units = Unità della repository
+settings.units.units = Sezioni del repositorio
settings.units.add_more = Aggiungi ancora...
settings.wiki_globally_editable = Consenti a tutti di modificare la wiki
settings.pull_mirror_sync_in_progress = Prelevando cambiamenti dal progetto remoto %s.
@@ -2732,7 +2767,7 @@ pulls.merged_title_desc_one = ha fuso %[1]d commit da %[2]s
in Accedi per creare una richiesta di modifica.
+settings.mirror_settings.push_mirror.none_ssh = Nessuno
+sync_fork.branch_behind_one = Questo ramo è indietro di %[1]d commit rispetto a %[2]s
+sync_fork.branch_behind_few = Questo ramo è indietro di %[1]d commit rispetto a %[2]s
+no_eol.text = Nessun fine linea
+no_eol.tooltip = Questo file non contiene un carattere di fine linea finale.
+milestones.filter_sort.name = Nome
+settings.protect_new_rule = Crea una nuova regola di protezione dei rami
+editor.commit_email = E-mail di commit
+mirror_public_key = Chiave SSH pubblica
+mirror_denied_combination = Non è possibile utilizzare contemporaneamente l'autenticazione tramite chiave pubblica e password.
+release.type_attachment = Allegato
+release.invalid_external_url = URL esterno invalido: "%s"
+new_from_template = Utilizza un modello
+new_from_template_description = Puoi selezionare un modello di repositorio esistente su questa istanza e applicare le sue impostazioni.
+new_advanced = Impostazioni avanzate
+new_advanced_expand = Clicca per espandere
+summary_card_alt = Scheda riepilogativa del repository %s
+issues.filter_sort.relevance = Rilevanza
+issues.num_reviews_one = %d revisioni
+issues.num_reviews_few = %d revisioni
+issues.reaction.add = Aggiungi reazione
+issues.reaction.alt_many = %[1] e altri %[2]d hanno reagito %[3]s.
+issues.reaction.alt_remove = Rimuovi la reazione %[1]s dal commento.
+issues.reaction.alt_add = Aggiungi la reazione %[1]s al commento.
+issues.review.remove_review_requests = rimosso richieste di revisione per %\[1]s %\[2]s
+comment.blocked_by_user = Non è possibile commentare perché sei stato bloccato dal proprietario del repositorio o dall'autore.
+issues.summary_card_alt = Scheda riepilogativa di una segnalazione intitolata "%s" nel repositorio %s
+pulls.delete_after_merge.head_branch.is_default = Il ramo head che desideri eliminare è il ramo predefinito e non può essere eliminato.
+settings.event_action_success = Successo
+settings.event_action_success_desc = L'esecuzione dell'azione è andata a buon fine.
+diff.git-notes.remove-header = Rimuovi nota
+diff.git-notes.remove-body = Questa nota verrà rimossa.
+activity.commit = Attività di commit
[graphs]
contributors.what = contribuzioni
@@ -2839,7 +2947,7 @@ team_name_helper=I nomi dei team devono essere brevi e semplici da ricordare.
team_desc_helper=Descrivi lo scopo o il ruolo del team.
team_access_desc=Accesso al repository
team_permission_desc=Autorizzazione
-team_unit_desc=Consenti l'accesso a sezioni di progetto
+team_unit_desc=Consenti l'accesso alle sezioni del repositorio
team_unit_disabled=(Disabilitato)
form.create_org_not_allowed=Non disponi dell'autorizzazione per creare un organizzazione.
@@ -3493,6 +3601,12 @@ config.cache_test_slow = Successo nel controllo della cache, ma la risposta è l
config.app_slogan = Slogan dell'istanza
auths.default_domain_name = Nome di dominio predefinito utilizzato per l'indirizzo e-mail
users.restricted.description = Permetti di interagire solo con i repositori e le organizzazioni in cui l'utente è aggiuntə come collaborante. Ciò evita l'accesso ai repositori pubblici di quest'istanza.
+emails.deletion_success = L'indirizzo e-mail è stato eliminato.
+monitor.duration = Durata (s)
+emails.delete_desc = Confermare l’eliminazione di questo indirizzo email?
+emails.delete_primary_email_error = Non puoi eliminare la e-mail primaria.
+emails.delete = Elimina e-mail
+users.organization_creation.description = Abilita la creazione di nuove organizzazioni.
[action]
@@ -3737,6 +3851,31 @@ owner.settings.cargo.initialize.success = L'indice di Cargo è stato creato corr
owner.settings.cargo.rebuild.no_index = Impossibile ricostruire, nessun indice è inizializzato.
owner.settings.cargo.rebuild.description = La ricostruzione può essere utile se l'indice non è sincronizzato con i pacchetti Cargo conservati.
npm.dependencies.bundle = Dipendenze raggruppate
+arch.version.groups = Gruppo
+arch.version.conflicts = Va in conflitto con
+arch.version.depends = Dipende da
+arch.version.makedepends = Dipendenze di build
+arch.version.checkdepends = Dipendenze di controllo
+arch.version.replaces = Sostituisce
+arch.version.optdepends = Dipende opzionalmente da
+arch.version.backup = Backup
+search_in_external_registry = Cerca in %s
+arch.version.provides = Fornisce
+arch.pacman.conf = Aggiungi il server con la relativa distribuzione e architettura a /etc/pacman.conf
:
+alt.setup = Aggiungi il repositorio alla lista dei repositori in rete (seleziona l'architettura necessaria al posto di "_arch_"):
+container.images.title = Immagini
+arch.version.properties = Proprietà della versione
+alt.registry.install = Per installare il pacchetto, esegui il comando seguente:
+alt.install = Installa pacchetto
+alt.registry = Configura questo registro dalla riga di comando:
+arch.pacman.helper.gpg = Aggiungi il certificato a pacman:
+arch.pacman.repo.multi = %s ha la stessa versione in diverse distribuzioni.
+arch.pacman.repo.multi.item = Configurazione per %s
+arch.pacman.sync = Sincronizza il paccketto con pacman:
+arch.version.description = Descrizione
+alt.repository = Informazioni del repositorio
+alt.repository.architectures = Architetture
+alt.repository.multiple_groups = Questo pacchetto è disponibile per più gruppi.
[secrets]
secrets = Segreti
@@ -3834,7 +3973,7 @@ runs.empty_commit_message = (messaggio di commit vuoto)
runs.no_runs = Il flusso di lavoro non è stato ancora eseguito.
variables.creation.success = La variabile "%s" è stata aggiunta.
variables.description = Le variabili saranno passate a determinate azioni e non possono essere lette altrimenti.
-need_approval_desc = È necessaria l'approvazione per eseguire flussi di lavoro per richieste di modifica da derivazioni.
+need_approval_desc = È necessaria l'approvazione per eseguire flussi di lavoro per richieste di modifica da biforcazioni.
runs.no_workflows.documentation = Per ulteriori informazioni sulle Forgejo Actions vedi la documentazione.
runs.no_workflows.quick_start = Non sai come iniziare con le Forgejo Actions? Vedi la guida rapida.
runners.delete_runner_notice = Se un'attività è in esecuzione su questo esecutore sarà terminata ed etichettata fallito. Potrebbe rompere flussi di lavoro di costruzione.
@@ -3848,6 +3987,8 @@ workflow.dispatch.invalid_input_type = Tipo ingresso "%s" non valido.
workflow.dispatch.warn_input_limit = Visualizzati solo i primi %d ingressi.
runs.no_job = Il flusso di lavoro deve contenere almeno un incarico
workflow.dispatch.use_from = Usa flusso di lavoro da
+variables.not_found = Non è stato possibile trovare la variabile.
+runs.expire_log_message = I log sono stati eliminati in quanto troppo vecchi.
@@ -3856,6 +3997,7 @@ workflow.dispatch.use_from = Usa flusso di lavoro da
type-3.display_name = Progetto dell'organizzazione
type-1.display_name = Progetto individuale
type-2.display_name = Progetto
+deleted.display_name = Progetto eliminato
[git.filemode]
symbolic_link=Link Simbolico
@@ -3872,30 +4014,31 @@ type_tooltip = Tipo ricerca
search = Cerca…
fuzzy = Approssimativa
match = Precisa
-org_kind = Cerca organizzazioni...
-package_kind = Ricerca pacchetti...
+org_kind = Cerca organizzazioni…
+package_kind = Ricerca pacchetti…
code_search_unavailable = La ricerca del codice non è attualmente disponibile. Contatta l'amministratorə del sito.
-code_kind = Cerca nel codice...
-team_kind = Cerca team...
+code_kind = Cerca nel codice…
+team_kind = Cerca team…
code_search_by_git_grep = I risultati della ricerca del codice sono forniti da "git grep". Potrebbero esserci risultati migliori se l'amministratore del sito avesse abilitato l'indicizzatore del codice.
-project_kind = Ricerca progetti...
-commit_kind = Ricerca commit...
-branch_kind = Ricerca rami...
+project_kind = Ricerca progetti…
+commit_kind = Ricerca commit…
+branch_kind = Ricerca rami…
no_results = Non è stato trovato alcun risultato.
keyword_search_unavailable = La ricerca per parole chiave non è attualmente disponibile. Contatta l'amministratore del sito.
-runner_kind = Ricerca esecutori...
+runner_kind = Ricerca esecutori…
match_tooltip = Includi solo risultati che corrispondono precisamente al termine di ricerca
fuzzy_tooltip = Includi anche risultati che corrispondono approssimativamente al termine di ricerca
-user_kind = Cerca utenti...
-repo_kind = Cerca repo...
+user_kind = Cerca utenti…
+repo_kind = Cerca repo…
exact_tooltip = Includi solo i risultati che corrispondono esattamente al termine di ricerca
-issue_kind = Cerca segnalazioni...
-pull_kind = Cerca richieste...
+issue_kind = Cerca segnalazioni…
+pull_kind = Cerca richieste…
exact = Esatto
milestone_kind = Ricerca tappe...
regexp_tooltip = Interpreta i termini di ricerca come un'espressione regolare
regexp = Espressione Regolare
union_tooltip = Include i risultati che combaciano con una qualsiasi delle parole chiave separata da spazi
+union = Parole chiavi
[munits.data]
gib = GiB
@@ -3914,4 +4057,16 @@ filepreview.line = Linea %[1]d in %[2]s
[repo.permissions]
issues.write = Scrittura: Chiudere segnalazioni e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze.
-pulls.write = Scrittura: Chiudere richieste di modifica e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze.
\ No newline at end of file
+pulls.write = Scrittura: Chiudere richieste di modifica e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze.
+releases.write = Scrittura: Può pubblicare, modificare ed eliminare rilasci e le risorse ad essi allegate.
+code.write = Scrittura: Può aggiungere commit al repositorio, creare rami ed etichette.
+wiki.read = Lettura: Può leggere la wiki integrata e la sua cronologia.
+releases.read = Lettura: Può visualizzare e scaricare i rilasci.
+projects.read = Lettura: Può accedere alle board di progetto del repositorio.
+code.read = Lettura: Può accedere e clonare il codice del repositorio.
+wiki.write = Scrittura: Può creare, aggiornare ed eliminare pagine nella wiki integrata.
+issues.read = Lettura: Può leggere e creare segnalazioni e commenti.
+pulls.read = Lettura: Può leggere e creare richieste di modifica.
+
+[translation_meta]
+test = daje Roma
\ No newline at end of file
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index d4d7024f5d..f3a8922f88 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -250,7 +250,7 @@ err_empty_db_path=SQLite3のデータベースパスを空にすることはで
no_admin_and_disable_registration=管理者アカウントを作成せずに、セルフ登録を無効にすることはできません。
err_empty_admin_password=管理者パスワードは空にできません。
err_empty_admin_email=管理者のメールアドレスは空にできません。
-err_admin_name_is_reserved=管理者のユーザー名が不正です。予約済みのユーザー名です。
+err_admin_name_is_reserved=管理者のユーザー名が不正です。予約済みのユーザー名です
err_admin_name_pattern_not_allowed=管理者のユーザー名が不正です。 予約済みのパターンにマッチしています
err_admin_name_is_invalid=管理者のユーザー名が不正です
@@ -1048,6 +1048,8 @@ keep_activity_private.description = 公開アクティビティ
language.description = この言語はアカウントに保存され、ログイン後にデフォルトとして使用されます。
language.localization_project = Forgejo をあなたの言語に翻訳するのを手伝ってください。詳細はこちら。
+quota = クオータ
+
[repo]
new_repo_helper=リポジトリには、プロジェクトのすべてのファイルとリビジョン履歴が入ります。 すでにほかの場所でホストしていますか? リポジトリを移行 もどうぞ。
owner=オーナー
@@ -1610,13 +1612,13 @@ issues.close_comment_issue=コメントしてクローズ
issues.reopen_issue=再オープンする
issues.reopen_comment_issue=コメントして再オープン
issues.create_comment=コメントする
-issues.closed_at=`がイシューをクローズ %[2]s`
-issues.reopened_at=`がイシューを再オープン %[2]s`
-issues.commit_ref_at=`がコミットでこのイシューを参照 %[2]s`
-issues.ref_issue_from=`が%[4]s、このイシューを参照 %[2]s`
-issues.ref_pull_from=`が%[4]s、このプルリクエストを参照 %[2]s`
-issues.ref_closing_from=`が%[4]s、プルリクエストがこのイシューをクローズするよう参照 %[2]s`
-issues.ref_reopening_from=`が%[4]s、プルリクエストがこのイシューを再オープンするよう参照 %[2]s`
+issues.closed_at=`がイシューをクローズ %s`
+issues.reopened_at=`がイシューを再オープン %s`
+issues.commit_ref_at=`がコミットでこのイシューを参照 %s`
+issues.ref_issue_from=`が%[3]s、このイシューを参照 %[1]s`
+issues.ref_pull_from=`が%[3]s、このプルリクエストを参照 %[1]s`
+issues.ref_closing_from=`が%[3]s、プルリクエストがこのイシューをクローズするよう参照 %[1]s`
+issues.ref_reopening_from=`が%[3]s、プルリクエストがこのイシューを再オープンするよう参照 %[1]s`
issues.ref_closed_from=`が%[4]s、このイシューをクローズ %[2]s`
issues.ref_reopened_from=`が%[4]s、このイシューを再オープン %[2]s`
issues.ref_from=` %[1]s にて`
@@ -1923,8 +1925,8 @@ pulls.update_branch_success=ブランチの更新が成功しました
pulls.update_not_allowed=ブランチを更新する権限がありません
pulls.outdated_with_base_branch=このブランチはベースブランチに対して最新ではありません
pulls.close=プルリクエストをクローズ
-pulls.closed_at=`がプルリクエストをクローズ %[2]s`
-pulls.reopened_at=`がプルリクエストを再オープン %[2]s`
+pulls.closed_at=`がプルリクエストをクローズ %s`
+pulls.reopened_at=`がプルリクエストを再オープン %s`
pulls.cmd_instruction_hint=コマンドラインの手順を表示
pulls.cmd_instruction_checkout_title=チェックアウト
pulls.cmd_instruction_checkout_desc=プロジェクトリポジトリから新しいブランチをチェックアウトし、変更内容をテストします。
@@ -2721,7 +2723,7 @@ settings.wiki_rename_branch_main = wikiのブランチ名を正規化する
settings.wiki_rename_branch_main_desc = wikiによって内部的に使われているブランチ名を "%s" に変更します。これは恒久的で元に戻すことはできません。
contributors.contribution_type.additions = 追加
vendored = vendor済み
-pulls.commit_ref_at = `このプルリクエストを言及するコミット %[2]s`
+pulls.commit_ref_at = `このプルリクエストを言及するコミット %s`
pulls.fast_forward_only_merge_pull_request = Fast-forwardのみ
admin.manage_flags = フラグ管理
admin.update_flags = フラグを更新
@@ -3903,20 +3905,20 @@ submodule=サブモジュール
[search]
search = 検索...
type_tooltip = 検索タイプ
-org_kind = 組織の検索...
-code_kind = コードの検索...
+org_kind = 組織を検索…
+code_kind = コードを検索…
fuzzy = あいまい
-repo_kind = リポジトリの検索...
+repo_kind = リポジトリを検索…
code_search_unavailable = コード検索は現在利用できません。サイト管理者にお問い合わせください。
-branch_kind = ブランチの検索...
-commit_kind = コミットの検索...
-user_kind = ユーザーの検索...
-team_kind = チームの検索...
+branch_kind = ブランチを検索…
+commit_kind = コミットを検索…
+user_kind = ユーザーを検索…
+team_kind = チームを検索…
code_search_by_git_grep = 現在のコード検索結果は「git grep」によって提供されます。サイト管理者がコード インデクサーを有効にすると、より良い結果が得られる可能性があります。
-package_kind = パッケージの検索...
-project_kind = プロジェクトの検索...
+package_kind = パッケージを検索…
+project_kind = プロジェクトを検索…
keyword_search_unavailable = キーワードによる検索は現在ご利用いただけません。サイト管理者にお問い合わせください。
-runner_kind = ランナーの検索...
+runner_kind = ランナーを検索…
no_results = 一致する結果が見つかりませんでした。
fuzzy_tooltip = 入力された語句に近いものも結果に含める
match = 一致
@@ -3924,8 +3926,8 @@ match_tooltip = 検索語句に厳密に一致するもののみ結果に含め
milestone_kind = マイルストーンを検索...
union_tooltip = 空白で区切られたキーワードのいずれかに一致する結果を含める
exact_tooltip = 検索語句と完全に一致する結果のみを含める
-issue_kind = イシューを検索...
-pull_kind = プルを検索...
+issue_kind = イシューを検索…
+pull_kind = プルを検索…
exact = 完全一致
regexp_tooltip = 検索語句を正規表現として解釈する
regexp = 正規表現
diff --git a/options/locale/locale_jbo.ini b/options/locale/locale_jbo.ini
index 6124dc4d22..947bb298de 100644
--- a/options/locale/locale_jbo.ini
+++ b/options/locale/locale_jbo.ini
@@ -2,4 +2,12 @@
[common]
-home = zdani
\ No newline at end of file
+home = zdani
+dashboard = jitypalna
+explore = sisku
+help = se sidju
+logo = se'isni
+sign_in = co'a nerkla
+sign_in_with_provider = co'a nerka sepi'o la .%s.
+sign_out = co'a cliva
+sign_up = co'a gumri
\ No newline at end of file
diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini
index 433ec01828..5e2354f3a8 100644
--- a/options/locale/locale_ko-KR.ini
+++ b/options/locale/locale_ko-KR.ini
@@ -384,7 +384,7 @@ allow_password_change=사용자에게 비밀번호 변경을 요청 (권장됨)
reset_password_mail_sent_prompt=확인 메일이 %s로 전송되었습니다. 받은 편지함으로 도착한 메일을 %s 안에 확인해서 비밀번호 찾기 절차를 완료하십시오.
active_your_account=계정 활성화
account_activated=계정이 활성화 되었습니다
-prohibit_login =
+prohibit_login =
resent_limit_prompt=활성화를 위한 이메일을 이미 전송했습니다. 3분 내로 이메일을 받지 못한 경우 재시도해주세요.
has_unconfirmed_mail=안녕하세요 %s, 이메일 주소(%s)가 확인되지 않았습니다. 확인 메일을 받으시지 못하겼거나 새로운 확인 메일이 필요하다면, 아래 버튼을 클릭해 재발송하실 수 있습니다.
resend_mail=여기를 눌러 확인 메일 재전송
@@ -588,8 +588,8 @@ password_change_disabled=로컬 유저가 아닌 경우 Forgejo 웹 인터페이
emails=이메일 주소
manage_emails=이메일 주소 관리
-manage_themes=기본 테마 선택
-manage_openid=OpenID 주소 관리
+manage_themes=기본 테마
+manage_openid=OpenID 주소
theme_desc=이 테마가 사이트 전체 기본 테마가 됩니다.
primary=대표
activated=활성화됨
@@ -943,7 +943,7 @@ issues.close_comment_issue=클로즈 및 코멘트
issues.reopen_issue=다시 열기
issues.reopen_comment_issue=다시 오픈 및 코멘트
issues.create_comment=코멘트
-issues.commit_ref_at=` 커밋 %[2]s에서 이 이슈 언급`
+issues.commit_ref_at=` 커밋 %s에서 이 이슈 언급`
issues.role.owner=소유자
issues.role.member=멤버
issues.sign_in_require_desc=로그인하여 이 대화에 참여하세요.
@@ -1378,7 +1378,7 @@ issues.closed_by_fake = %[2]s님이 %[1]s에 닫음
issues.new.closed_projects = 닫힌 프로젝트
pulls.merged_by_fake = %[2]s님이 %[1]s 병합함
issues.closed_by = %[3]s님이 %[1]s에 닫음
-issues.closed_at = `%[2]s`에 이 이슈를 닫음
+issues.closed_at = `%s`에 이 이슈를 닫음
issues.filter_milestone_closed = 닫힌 마일스톤
issues.opened_by_fake = %[2]s님이 %[1]s에 열음
issues.filter_project_none = 프로젝트 없음
@@ -1900,9 +1900,9 @@ runs.commit=커밋
[search]
code_search_by_git_grep = 현재 코드 검색 결과는 "git grep"에 의해 제공됩니다.관리자가 코드 인덱서를 활성화하면 더 나은 결과가 제공될 수 있습니다.
-branch_kind = 브랜치 검색...
+branch_kind = 브랜치 검색…
keyword_search_unavailable = 지금은 키워드로 검색이 지원되지 않습니다. 사이트 관리자에게 문의하십시오.
-commit_kind = 커밋 검색...
+commit_kind = 커밋 검색…
no_results = 일치하는 결과를 찾을 수 없습니다.
search = 검색…
type_tooltip = 검색 타입
@@ -1910,11 +1910,11 @@ fuzzy_tooltip = 검색어와 밀접하게 일치하는 결과도 포함
repo_kind = 저장소 검색…
user_kind = 사용자 검색…
org_kind = 조직 검색…
-team_kind = 팀 검색...
-code_kind = 코드 검색...
+team_kind = 팀 검색…
+code_kind = 코드 검색…
code_search_unavailable = 코드 검색은 현재 허용되지 않았습니다. 사이트 관리자와 연락하세요.
-package_kind = 패키지 검색...
-project_kind = 프로젝트 검색...
+package_kind = 패키지 검색…
+project_kind = 프로젝트 검색…
exact_tooltip = 검색어와 정확하게 일치하는 결과만 포함
issue_kind = 이슈 검색…
pull_kind = 풀 검색…
diff --git a/options/locale/locale_lt.ini b/options/locale/locale_lt.ini
index 868e5bff6e..9d1c938379 100644
--- a/options/locale/locale_lt.ini
+++ b/options/locale/locale_lt.ini
@@ -149,24 +149,24 @@ fuzzy = Tikslintinas
union_tooltip = Įtraukti rezultatus, atitinkančius bet kurį iš matomą tarpą atskirtų raktažodžių
exact = Tiksliai
exact_tooltip = Įtraukti tik tuos rezultatus, kurie atitinka tikslią paieškos frazę
-user_kind = Ieškoti naudotojų...
-team_kind = Ieškoti komandų...
-code_kind = Ieškoti kodo...
+user_kind = Ieškoti naudotojų…
+team_kind = Ieškoti komandų…
+code_kind = Ieškoti kodo…
fuzzy_tooltip = Įtraukti rezultatus, kurie taip pat labai atitinka paieškos terminą
-repo_kind = Ieškoti saugyklų...
+repo_kind = Ieškoti saugyklų…
code_search_unavailable = Kodų paieška šiuo metu nepasiekiama. Kreipkis į svetainės administratorių.
-org_kind = Ieškoti organizacijų...
+org_kind = Ieškoti organizacijų…
union = Bendrinis
code_search_by_git_grep = Dabartiniai kodo paieškos rezultatai pateikiami atliekant „git grep“. Rezultatai gali būti geresni, jei svetainės administratorius įjungs kodo indeksuotoją.
-package_kind = Ieškoti paketų...
-project_kind = Ieškoti projektų...
-commit_kind = Ieškoti įsipareigojimų...
-runner_kind = Ieškoti vykdyklių...
+package_kind = Ieškoti paketų…
+project_kind = Ieškoti projektų…
+commit_kind = Ieškoti įsipareigojimų…
+runner_kind = Ieškoti vykdyklių…
no_results = Nerasta atitinkamų rezultatų.
-issue_kind = Ieškoti problemų...
-branch_kind = Ieškoti šakų...
+issue_kind = Ieškoti problemų…
+branch_kind = Ieškoti šakų…
milestone_kind = Ieškoti gairių...
-pull_kind = Ieškoti sujungimų...
+pull_kind = Ieškoti sujungimų…
keyword_search_unavailable = Ieškoti pagal raktažodį šiuo metu nepasiekiamas. Susisiekite su svetainės administratoriumi.
regexp = Reguliarusis reiškinys
regexp_tooltip = Interpretuoti paieškos terminą kaip reguliariąją reiškinį
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index 789871f3c3..4a98e1aa9d 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -1577,7 +1577,7 @@ issues.remove_ref_at=`noņēma atsauci no %s %s`
issues.add_ref_at=`pievienoja atsauci uz %s %s`
issues.delete_branch_at=`izdzēsa zaru %s %s`
issues.filter_label=Iezīme
-issues.filter_label_exclude=`Jāizmanto alt
+ klikšķis/Enter
, lai neiekļautu iezīmes`
+issues.filter_label_exclude=Jāizmanto Alt + klikšķis, lai neiekļautu iezīmes
issues.filter_label_no_select=Visas iezīmes
issues.filter_label_select_no_label=Bez iezīmes
issues.filter_milestone=Atskaites punkts
@@ -1651,13 +1651,13 @@ issues.close_comment_issue=Aizvērt ar piebildi
issues.reopen_issue=Atvērt atkārtoti
issues.reopen_comment_issue=Atkārtoti atvērt ar piebildi
issues.create_comment=Pievienot piebildi
-issues.closed_at=`aizvēra šo pieteikumu %[2]s`
-issues.reopened_at=`atkārtoti atvēra šo pieteikumu %[2]s`
-issues.commit_ref_at=`atsaucās uz šo pieteikumu iesūtījumā %[2]s`
-issues.ref_issue_from=`atsaucās uz šo pieteikumu %[4]s %[2]s`
-issues.ref_pull_from=`atsaucās uz šo izmaiņu pieprasījumu %[4]s %[2]s`
-issues.ref_closing_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[4]s, kas aizvērs to, %[2]s`
-issues.ref_reopening_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[4]s, kas atkārtoti atvērs to, %[2]s`
+issues.closed_at=`aizvēra šo pieteikumu %s`
+issues.reopened_at=`atkārtoti atvēra šo pieteikumu %s`
+issues.commit_ref_at=`atsaucās uz šo pieteikumu iesūtījumā %s`
+issues.ref_issue_from=`atsaucās uz šo pieteikumu %[3]s %[1]s`
+issues.ref_pull_from=`atsaucās uz šo izmaiņu pieprasījumu %[3]s %[1]s`
+issues.ref_closing_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[3]s, kas aizvērs to, %[1]s`
+issues.ref_reopening_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[3]s, kas atkārtoti atvērs to, %[1]s`
issues.ref_closed_from=`aizvēra pieteikumu %[4]s %[2]s`
issues.ref_reopened_from=`atkārtoti atvēra pieteikumu %[4]s %[2]s`
issues.ref_from=`no %[1]s`
@@ -1964,8 +1964,8 @@ pulls.update_branch_success=Zara atjaunināšana bija sekmīga
pulls.update_not_allowed=Nav ļauts atjaunināt zaru
pulls.outdated_with_base_branch=Šis zars ir novecojis salīdzinājumā ar pamata zaru
pulls.close=Aizvērt izmaiņu pieprasījumu
-pulls.closed_at=`aizvēra šo izmaiņu pieprasījumu %[2]s`
-pulls.reopened_at=`atkārtoti atvēra šo izmaiņu pieprasījumu %[2]s`
+pulls.closed_at=`aizvēra šo izmaiņu pieprasījumu %s`
+pulls.reopened_at=`atkārtoti atvēra šo izmaiņu pieprasījumu %s`
pulls.cmd_instruction_hint=Apskatīt komandrindas izmantošanas norādes
pulls.cmd_instruction_checkout_title=Paņemt
pulls.cmd_instruction_checkout_desc=Projekta glabātavā jāizveido jauns zars un jāpārbauda izmaiņas.
@@ -2826,7 +2826,7 @@ issues.author.tooltip.pr = Šis lietotājs ir šī izmaiņu pieprasījuma izveid
pulls.edit.already_changed = Neizdevās saglabāt izmaiņu pieprasījuma izmaiņas. Izskatās, ka saturu jau ir mainījis kāds cits lietotājs. Lūgums atsvaidzināt lapu un mēģināt labot vēlreiz, lai izvairītos no izmaiņu pārrakstīšanas
pulls.blocked_by_user = Tu nevari izveidot izmaiņu pieprasījumu šajā glabātavā, jo tās īpašnieks ir Tevi liedzis.
issues.all_title = Visi
-pulls.commit_ref_at = ` atsaucāš uz šo izmaiņu pieprasījumu iesūtījumā %[2]s`
+pulls.commit_ref_at = ` atsaucās uz šo izmaiņu pieprasījumu iesūtījumā %s`
issues.num_participants_one = %d dalībnieks
pulls.title_desc_one = vēlas iekļaut %[1]d iesūtījumu no %[2]s
%[3]s
issues.archived_label_description = (Arhivēts) %s
diff --git a/options/locale/locale_ml-IN.ini b/options/locale/locale_ml-IN.ini
index fcc9888d8e..c4c266ad86 100644
--- a/options/locale/locale_ml-IN.ini
+++ b/options/locale/locale_ml-IN.ini
@@ -356,7 +356,7 @@ avatar=അവതാര്
ssh_gpg_keys=SSH / GPG കീകള്
social=സോഷ്യൽ അക്കൗണ്ടുകൾ
applications=അപ്ലിക്കേഷനുകൾ
-orgs=സംഘടനകളെ നിയന്ത്രിക്കുക
+orgs=സംഘടനകൾ
repos=കലവറകള്
delete=അക്കൗണ്ട് ഇല്ലാതാക്കുക
twofa=ഇരട്ട ഘടക പ്രാമാണീകരണം
@@ -400,8 +400,8 @@ password_change_disabled=പ്രാദേശിക ഇതര ഉപയോക
emails=ഇ-മെയില് വിലാസങ്ങള്
manage_emails=ഇമെയിൽ വിലാസങ്ങൾ നിയന്ത്രിക്കുക
-manage_themes=സ്ഥിരസ്ഥിതി പ്രമേയം തിരഞ്ഞെടുക്കുക
-manage_openid=ഓപ്പൺഐഡി വിലാസങ്ങൾ നിയന്ത്രിക്കുക
+manage_themes=ഡിഫോൾട്ട് തീം
+manage_openid=OpenID വിലാസങ്ങൾ
email_desc=അറിയിപ്പുകൾക്കും മറ്റ് പ്രവർത്തനങ്ങൾക്കുമായി നിങ്ങളുടെ പ്രാഥമിക ഇമെയിൽ വിലാസം ഉപയോഗിക്കും.
theme_desc=സൈറ്റിലുടനീളം ഇത് നിങ്ങളുടെ സ്ഥിരസ്ഥിതി പ്രമേയം ആയിരിക്കും.
primary=പ്രാഥമികം
diff --git a/options/locale/locale_nb_NO.ini b/options/locale/locale_nb_NO.ini
index 2c8b5cfc64..7dda7499a5 100644
--- a/options/locale/locale_nb_NO.ini
+++ b/options/locale/locale_nb_NO.ini
@@ -60,7 +60,7 @@ rerun = Kjør på nytt
rerun_all = Kjør alle jobber på nytt
save = Lagre
cancel = Avbryt
-forks = Forks
+forks = Kopier
milestones = Milepæler
ok = OK
test = Test
@@ -134,14 +134,44 @@ webauthn_error_timeout = Et tidsavbrudd oppsto før nøkkelen din kunne leses. V
new_fork = Ny fork av repository
collaborative = Samarbeidende
+tracked_time_summary = Oppsummering av sporet tid basert på problemfiltre
+pull_requests = Pull requests
+issues = Saker
+copy_branch = Kopier branch navn
+error404 = Siden du forsøker å nå eksisterer ikke, er blitt fjernet eller du har ikke tilgang til å se den.
+error413 = Du har brukt opp kvoten din.
+unpin = Løsne
+filter.is_fork = Forks
+filter.not_fork = Ikke forks
+
[search]
-search = Søk...
+search = Søk…
type_tooltip = Søketype
fuzzy = Fuzzy
union = Union
regexp = RegExp
exact = Nøyaktig
+fuzzy_tooltip = Inkluder resultater som også stemmer godt overens med søketermen
+union_tooltip = Inkluder resultater som samsvarer med ett eller flere av nøkkelordene adskilt med mellomrom
+exact_tooltip = Inkluder kun resultater som samsvarer nøyaktig med søkeordet
+regexp_tooltip = Tolk søkeordet som et regulæruttrykk
+repo_kind = Søk i repositorer…
+user_kind = Søk i brukere…
+org_kind = Søk i organisasjoner…
+team_kind = Søk i teams…
+code_kind = Søk i kode…
+code_search_unavailable = Kodesøk er ikke tilgjengelig. Kontakt administratoren.
+package_kind = Søk i pakker…
+project_kind = Søk i prosjekter…
+branch_kind = Søk i brancher…
+commit_kind = Søk i commits…
+runner_kind = Søk i runners…
+no_results = Ingen treff funnet.
+issue_kind = Søk i saker…
+pull_kind = Søk i pulls…
+keyword_search_unavailable = Søk etter nøkkelord er for øyeblikket ikke tilgjengelig. Kontakt administratoren.
+
[auth]
verify = Bekreft
sign_up_button = Opprett konto nå.
@@ -152,4 +182,88 @@ oauth_signup_title = Fullfør ny konto
oauth_signup_submit = Fullfør konto
[home]
-uname_holder = Brukernavn eller e-postadresse
\ No newline at end of file
+uname_holder = Brukernavn eller e-postadresse
+
+[aria]
+navbar = Navigasjonslinje
+footer = Bunntekst
+footer.software = Om dette programmet
+footer.links = Linker
+
+[heatmap]
+number_of_contributions_in_the_last_12_months = %s bidrag de siste 12 månedene
+contributions_zero = Ingen bidrag
+contributions_format = {contributions} den {day} {month} {year}
+contributions_one = bidrag
+contributions_few = bidrag
+less = Mindre
+more = Mer
+
+[editor]
+buttons.heading.tooltip = Legg til overskrift
+buttons.bold.tooltip = Legg til uthevet tekst
+buttons.italic.tooltip = Legg til kursiv text
+buttons.quote.tooltip = Siter tekst
+buttons.code.tooltip = Legg til kode
+buttons.link.tooltip = Legg til link
+buttons.list.unordered.tooltip = Legg til punktliste
+buttons.list.ordered.tooltip = Legg til nummerert liste
+buttons.list.task.tooltip = Legg til liste over saker
+buttons.mention.tooltip = Nevn en bruker eller team
+buttons.ref.tooltip = Referanse til en sak eller pull request
+buttons.switch_to_legacy.tooltip = Bruk den gamle editoren istedenfor
+buttons.enable_monospace_font = Aktiver monospace font
+buttons.disable_monospace_font = Deaktiver monospace font
+buttons.indent.tooltip = Grupper elementene med et nivå
+buttons.unindent.tooltip = Pakk ut elementene med et nivå
+buttons.new_table.tooltip = Legg til tabell
+table_modal.header = Legg til tabell
+table_modal.placeholder.header = Overskrift
+table_modal.placeholder.content = Innhold
+table_modal.label.rows = Rader
+table_modal.label.columns = Kolonner
+link_modal.header = Legg til en link
+link_modal.url = Url
+link_modal.description = Beskrivelse
+link_modal.paste_reminder = Tips: Når du har en URL i utklippstavlen kan du lime den direkte inn i editoren for å lage en lenke.
+
+[filter]
+string.asc = A - Z
+string.desc = Z - A
+
+[error]
+occurred = En feil oppstod
+report_message = Hvis du mener dette er en feil i Forgejo kan du søke på Codeberg eller åpne en ny sak.
+not_found = Kunne ikke finne målet.
+network_error = Nettverks feil
+server_internal = Intern server feil
+
+[startpage]
+app_desc = En enkel Git-tjeneste du kan drifte selv
+install = Enkel å installere
+install_desc = Du kan enkelt kjøre programfilen for din platform, bruke Docker, eller hente den som en ferdig pakke.
+platform = Plattformuavhengig
+platform_desc = Forgejo fungerer på frie operativsystemer som Linux og FreeBSD, og støtter flere CPU-arkitekturer. Velg den plattformen du foretrekker!
+lightweight = Lettvekt
+lightweight_desc = Forgejo krever lite ressurser og kan kjøres på en rimelig Raspberry Pi. Spar strøm og miljøet!
+license = Åpen kildekode
+license_desc = Last ned Forgejo! Bli med ved å bidra for å gjøre prosjektet enda bedre. Ikke vær redd for å bli en bidragsyter!
+
+[install]
+install = Installasjon
+title = Førstegangsoppsett
+docker_helper = Dersom du bruker Forgejo med Docker, anbefales det å lese dokumentasjonen før du gjør endringer i konfigurasjonen.
+require_db_desc = Forgejo krever MySQL, PostgreSQL, SQLite3 eller TiDB (MySQL protokoll).
+db_title = Database innstillinger
+db_type = Database type
+host = Server
+user = Brukernavn
+password = Passord
+db_name = Database navn
+db_schema = Skjema
+db_schema_helper = La stå tomt for databasens standardverdi ("public").
+ssl_mode = SSL
+path = Sti
+sqlite_helper = Sti til SQLite3-databasen.
Bruk absolutt filsti dersom Forgejo kjøres som en tjeneste.
+reinstall_error = Du prøver å installere i en eksisterende Forgejo-database
+reinstall_confirm_message = Å installere på nytt med en eksisterende Forgejo-database kan føre til problemer. I de fleste tilfeller bør du bruke din eksisterende "app.ini" for å kjøre Forgejo. Hvis du vet hva du gjør, og vil fortsette, bekreft følgende:
\ No newline at end of file
diff --git a/options/locale/locale_nds.ini b/options/locale/locale_nds.ini
index 57985942ed..fe504b2a04 100644
--- a/options/locale/locale_nds.ini
+++ b/options/locale/locale_nds.ini
@@ -568,7 +568,7 @@ organization = Vereenigungen
uid = UID
webauthn = Twee-Faktooren-Anmellen (Sekerheids-Slötels)
blocked_users = Blockeert Brukers
-public_profile = Publikes Profil
+public_profile = Publikes profil
location_placeholder = Deel waar du umslags büst mit Annerns
pronouns = Pronomens
pronouns_custom = Eegene
@@ -1347,7 +1347,7 @@ issues.change_title_at = `hett %[3]s de Titel vun %[1]s
issues.change_ref_at = `hett %[3]s de Nömen vun %[1]s to %[2]s ännert`
issues.delete_branch_at = `hett %[2]s de Twieg %[1]s lösket`
issues.filter_label = Vermark
-issues.filter_label_exclude = `Bruuk Alt
+Klick/Enter
, um Vermarkens uttosluten`
+issues.filter_label_exclude = Bruuk Alt + Klick, um Vermarkens uttosluten
issues.filter_label_no_select = All Vermarkens
issues.filter_label_select_no_label = Keen Vermark
issues.filter_milestone = Marksteen
@@ -1434,12 +1434,12 @@ issues.comment_pull_merged_at = hett Kommitteren %[1]s in %[2]s %[3]s tosamenfö
issues.close_comment_issue = Mit Kommentaar dichtmaken
issues.reopen_comment_issue = Mit Kommentaar weer opmaken
issues.create_comment = Kommenteren
-issues.reopened_at = `hett deeses Gefall %[2]s weer opmaakt`
+issues.reopened_at = `hett deeses Gefall %s weer opmaakt`
issues.comment_manually_pull_merged_at = hett Kommitteren %[1]s in %[2]s %[3]s vun Hand tosamenföhrt
issues.reopen_issue = Weer opmaken
-issues.closed_at = `hett deeses Gefall %[2]s dichtmaakt`
-issues.commit_ref_at = `hett deeses Gefall %[2]s vun eenem Kommitteren benöömt`
-issues.ref_closing_from = `hett deeses Gefall %[2]s vun eenem Haalvörslag, wat ’t %[4]s dichtmaken word, benöömt`
+issues.closed_at = `hett deeses Gefall %s dichtmaakt`
+issues.commit_ref_at = `hett deeses Gefall %s vun eenem Kommitteren benöömt`
+issues.ref_closing_from = `hett deeses Gefall %[1]s vun eenem Haalvörslag, wat ’t %[3]s dichtmaken word, benöömt`
issues.ref_closed_from = `hett deeses Gefall %[4]s %[2]s dichtmaakt`
issues.ref_reopened_from = `hett deeses Gefall %[4]s %[2]s weer opmaakt`
issues.ref_from = `vun %[1]s`
@@ -1477,12 +1477,12 @@ issues.label.filter_sort.reverse_alphabetically = Umdreiht na de Alphabeet
issues.label.filter_sort.by_size = Lüttste Grött
issues.num_participants_one = %d Mitmaker
issues.num_participants_few = %d Mitmakers
-issues.ref_pull_from = `hett deesen Haalvörslag %[4]s %[2]s benöömt`
+issues.ref_pull_from = `hett deesen Haalvörslag %[3]s %[1]s benöömt`
issues.label_title = Naam
issues.label_archived_filter = Archiveert Vermarkens wiesen
issues.archived_label_description = (Archiveert) %s
-issues.ref_issue_from = `hett deeses Gefall %[4]s %[2]s benöömt`
-issues.ref_reopening_from = `hett deeses Gefall vun eenem Haalvörslag, wat ’t %[4]s weer opmaken word, %[2]s benöömt`
+issues.ref_issue_from = `hett deeses Gefall %[3]s %[1]s benöömt`
+issues.ref_reopening_from = `hett deeses Gefall vun eenem Haalvörslag, wat ’t %[3]s weer opmaken word, %[1]s benöömt`
issues.author.tooltip.issue = Deeser Bruker is de Autor vun deesem Gefall.
issues.role.member_helper = Deeser Bruker is een Liddmaat vun de Vereenigung, wat de Eegner vun deesem Repositorium is.
issues.role.collaborator_helper = Deeser Bruuker is inladen worden, in deesem Repositorium mittoarbeiden.
@@ -1552,7 +1552,7 @@ issues.dependency.pr_close_blocks = Deeser Haalvörslag blockeert dat Dichtmaken
issues.dependency.issue_batch_close_blocked = Kann de utköört Gefallens nich all tosamen dichtmaken, denn Gefall #%d hett noch open Ofhangens
issues.dependency.pr_close_blocked = Du muttst all Gefallens, wat deesen Haalvörslag blockeren, dichtmaken, ehr du dat hier tosamenföhren kannst.
issues.dependency.blocks_short = Blockeert
-issues.dependency.blocked_by_short = Hang of vun
+issues.dependency.blocked_by_short = Hangt of vun
issues.dependency.remove_header = Ofhangen wegdoon
issues.dependency.setting = Ofhangens för Gefallens un Haalvörslagen anknipsen
issues.dependency.add_error_same_issue = Du kannst een Gefall nich vun sik sülvst ofhangen laten.
@@ -1740,8 +1740,8 @@ pulls.status_checks_show_all = All Överprüfens wiesen
pulls.update_branch_rebase = Twieg mit Umbaseren vernejen
pulls.outdated_with_base_branch = De Twieg is tegen de Grund-Twieg verollt
pulls.close = Haalvörslag dichtmaken
-pulls.closed_at = `hett deesen Haalvörslag %[2]s dichtmaakt`
-pulls.reopened_at = `hett deesen Haalvörslag %[2]s weer opmaakt`
+pulls.closed_at = `hett deesen Haalvörslag %s dichtmaakt`
+pulls.reopened_at = `hett deesen Haalvörslag %s weer opmaakt`
pulls.cmd_instruction_hint = Wies Oorderreeg-Instruksjes
pulls.cmd_instruction_checkout_title = Utchecken
pulls.cmd_instruction_merge_title = Tosamenföhren
@@ -1771,7 +1771,7 @@ milestones.deletion = Marksteen lösken
pulls.has_merged = Fehlslagen: De Haalvörslag is tosamenföhrt worden, du kannst nich noch eenmaal tosamenföhren of de Enn-Twieg ännern.
pulls.unrelated_histories = Tosamenföhren fehlslagen: De Tosamenföhrens-Kopp un -Grund hebben keene gemeensame Histoorje. Wenk: Versöök eene anner Tosamenföhrens-Aard
pulls.update_not_allowed = Du düürst deesen Twieg nich vernejen
-pulls.commit_ref_at = `hett deesen Haalvörslag %[2]s vun eenem Kommitteren benöömt`
+pulls.commit_ref_at = `hett deesen Haalvörslag %s vun eenem Kommitteren benöömt`
pulls.auto_merge_newly_scheduled = De Haalvörslag weer sett, sik tosamentoföhren, wenn all Överprüfens kumpleet sünd.
milestones.clear = Leeg maken
pulls.push_rejected_no_message = Schuven fehlslagen: Dat Schuven is sünner feerne Naricht oflehnt worden. Bidde överprüüf de Git-Hakens för deeses Repositorium
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index 549718ce23..7f121395b9 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -559,7 +559,7 @@ team_invite.text_2 = Klik alstublieft op de volgende link om aan het team deel t
admin.new_user.text = Klik hier om deze gebruiker te beheren vanuit het beheerderspaneel.
password_change.subject = Uw wachtwoord is gewijzigd
password_change.text_1 = Het wachtwoord voor je account is zojuist gewijzigd.
-reset_password.text_1 =
+reset_password.text_1 =
totp_disabled.subject = TOTP is uitgeschakeld
primary_mail_change.subject = Uw primaire e-mail is gewijzigd
totp_disabled.no_2fa = Er zijn geen andere 2FA methodes meer geconfigureerd, wat betekent dat het niet langer nodig is om in te loggen op uw account met 2FA.
@@ -1495,7 +1495,7 @@ issues.remove_ref_at=`heeft referentie %s verwijderd %s`
issues.add_ref_at=`heeft referentie %s toegevoegd %s`
issues.delete_branch_at=`heeft %[2]s de branch %[1]s verwijderd.`
issues.filter_label=Label
-issues.filter_label_exclude=Gebruik alt
+ klik/voer
in om labels uit te sluiten
+issues.filter_label_exclude=Gebruik alt + klik om labels uit te sluiten
issues.filter_label_no_select=Alle labels
issues.filter_milestone=Mijlpaal
issues.filter_project=Project
@@ -1554,13 +1554,13 @@ issues.close_comment_issue=Sluit met commentaar
issues.reopen_issue=Heropen
issues.reopen_comment_issue=Heropen met commentaar
issues.create_comment=Reageer
-issues.closed_at=`heeft dit probleem gesloten %[2]s`
-issues.reopened_at=`heropende dit probleem %[2]s`
-issues.commit_ref_at=`verwees naar dit probleem vanuit commit %[2]s'`
-issues.ref_issue_from=`refereerde aan dit issue %[4]s %[2]s`
-issues.ref_pull_from=`refereerde aan deze pull request %[4]s %[2]s`
-issues.ref_closing_from=`verwees naar deze issue van een pull request %[4]s dat het zal sluiten, %[2]s`
-issues.ref_reopening_from=`verwees naar een pull request %[4]s dat dit issue heropent %[2]s `
+issues.closed_at=`heeft deze issue gesloten %s`
+issues.reopened_at=`heropende deze issue %s`
+issues.commit_ref_at=`verwees naar dit probleem vanuit commit %s`
+issues.ref_issue_from=`refereerde aan dit issue %[3]s %[1]s`
+issues.ref_pull_from=`refereerde aan deze pull request %[3]s %[1]s`
+issues.ref_closing_from=`verwees naar deze issue van een pull request %[3]s dat het zal sluiten, %[1]s`
+issues.ref_reopening_from=`verwees naar een pull request %[3]s dat dit issue heropent %[1]s `
issues.ref_closed_from=`sloot dit issue %[4]s %[2]s`
issues.ref_reopened_from=`heropende dit issue %[4]s %[2]s`
issues.ref_from=`van %[1]s`
@@ -1815,8 +1815,8 @@ pulls.update_branch_rebase=Update branch via herbaseren
pulls.update_branch_success=Branch update is geslaagd
pulls.update_not_allowed=Je hebt geen toestemming om branch bij te werken
pulls.outdated_with_base_branch=Deze branch is verouderd met de basis branch
-pulls.closed_at=`heeft deze pull request gesloten %[2]s`
-pulls.reopened_at=`heropende deze pull request %[2]s`
+pulls.closed_at=`heeft deze pull request gesloten %s`
+pulls.reopened_at=`heropende deze pull request %s`
pulls.auto_merge_button_when_succeed=(Bij geslaagde controles)
pulls.auto_merge_when_succeed=Automatisch samenvoegen wanneer alle controles gelukt zijn
@@ -2627,7 +2627,7 @@ projects.column.set_default_desc = Stel deze kolom in als standaard voor ongecat
issues.action_check = Aanvinken/uitvinken
issues.dependency.issue_batch_close_blocked = Het is niet mogelijk om de issues die u gekozen heeft in bulk te sluiten, omdat issue #%d nog open afhankelijkheden heeft
pulls.review_only_possible_for_full_diff = Beoordeling is alleen mogelijk bij het bekijken van de volledige diff
-pulls.commit_ref_at = `heeft naar deze pull request verwezen vanuit een commit %[2]s`
+pulls.commit_ref_at = `heeft naar deze pull request verwezen vanuit een commit %s`
pulls.cmd_instruction_hint = Bekijk opdrachtregelinstructies
pulls.cmd_instruction_checkout_desc = Vanuit uw project repository, schakel over naar een nieuwe branch en test de veranderingen.
pulls.showing_specified_commit_range = Alleen veranderingen weergeven tussen %[1]s..%[2]s
@@ -2915,6 +2915,15 @@ sync_fork.branch_behind_few = Deze branch is %[1]d commits achter %[2]s
+issues.filter_type.all_pull_requests = Alle pull requests
+settings.event_header_action = Actie run evenementen
+settings.event_action_failure = Mislukking
+settings.event_action_failure_desc = Action run is mislukt.
+settings.event_action_recover = Herstel
+settings.event_action_recover_desc = Action run is geslaagd nadat de laatste action run in dezelfde workflow is mislukt.
+settings.event_action_success = Succes
+settings.event_action_success_desc = Action run is geslaagd.
+
[graphs]
component_loading_info = Dit kan even duren…
component_failed_to_load = Er is een onverwachte fout opgetreden.
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index 86a333a886..a788badb47 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -1043,8 +1043,8 @@ language.title = Domyślny język
language.localization_project = Pomóż nam przetłumaczyć Forgejo na twój język! Dowiedz się więcej.
update_hints = Zaktualizuj wskazówki
update_hints_success = Wskazówki zostały zaktualizowane.
-change_username_redirect_prompt.with_cooldown.one = Stara nazwa użytkownika będzie dostępna dla każdego po okresie ochronnym wynoszącym %[1]d dzień, nadal możesz uzyskać z powrotem starą nazwę użytkownika podczas okresu ochronnego.
-change_username_redirect_prompt.with_cooldown.few = Stara nazwa użytkownika będzie dostępna dla każdego po okresie ochronnym wynoszącym %[1]d dni, nadal możesz uzyskać z powrotem starą nazwę użytkownika podczas okresu ochronnego.
+change_username_redirect_prompt.with_cooldown.one = Stara nazwa użytkownika będzie dostępna dla każdego po okresie ochronnym wynoszącym %[1]d dzień. Nadal możesz uzyskać z powrotem starą nazwę użytkownika podczas okresu ochronnego.
+change_username_redirect_prompt.with_cooldown.few = Stara nazwa użytkownika będzie dostępna dla każdego po okresie ochronnym wynoszącym %[1]d dni. Nadal możesz uzyskać z powrotem starą nazwę użytkownika podczas okresu ochronnego.
language.description = Ten język zostanie zapisany na twoim koncie i będzie używany jako domyślny po zalogowaniu.
hidden_comment_types_description = Rodzaje komentarzy zaznaczone tutaj nie będą wyświetlały się na stronach zgłoszeń. Zaznaczenie "Etykieta" na przykład usunie wszystkie komentarze " dodał/usunął ".
principal_desc = Te podmioty certyfikatu SSH będą powiązane z twoim kontem i pozwolą na pełen dostęp do twoich repozytoriów.
@@ -1460,13 +1460,13 @@ issues.close_comment_issue=Zamknij z komentarzem
issues.reopen_issue=Otwórz ponownie
issues.reopen_comment_issue=Otwórz ponownie z komentarzem
issues.create_comment=Skomentuj
-issues.closed_at=`zamknął(-ęła) to zgłoszenie %[2]s`
-issues.reopened_at=`otworzył(-a) ponownie to zgłoszenie %[2]s`
-issues.commit_ref_at=`wspomniał(-a) to zgłoszenie z commita %[2]s`
-issues.ref_issue_from=`odwołał(-a) się do tego zgłoszenia %[4]s %[2]s`
-issues.ref_pull_from=`odwołał(-a) się do tego Pull Requesta %[4]s %[2]s`
-issues.ref_closing_from=`odwołał(-a) się do pull requesta %[4]s, który zamknie to zgłoszenie %[2]s`
-issues.ref_reopening_from=`odwołał(-a) się z pull requesta %[4]s, który otworzy na nowo to zgłoszenie %[2]s`
+issues.closed_at=`zamknął(-ęła) to zgłoszenie %s`
+issues.reopened_at=`otworzył(-a) ponownie to zgłoszenie %s`
+issues.commit_ref_at=`wspomniał(-a) to zgłoszenie z commita %s`
+issues.ref_issue_from=`odwołał(-a) się do tego zgłoszenia %[3]s %[1]s`
+issues.ref_pull_from=`odwołał(-a) się do tego Pull Requesta %[3]s %[1]s`
+issues.ref_closing_from=`odwołał(-a) się do pull requesta %[3]s, który zamknie to zgłoszenie %[1]s`
+issues.ref_reopening_from=`odwołał(-a) się z pull requesta %[3]s, który otworzy na nowo to zgłoszenie %[1]s`
issues.ref_closed_from=`zamknął(-ęła) to zgłoszenie %[4]s %[2]s`
issues.ref_reopened_from=`ponownie otworzył(-a) to zgłoszenie %[4]s %[2]s`
issues.ref_from=`z %[1]s`
@@ -1679,8 +1679,8 @@ pulls.update_branch_rebase=Aktualizuj branch przez rebase
pulls.update_branch_success=Aktualizacja gałęzi powiodła się
pulls.update_not_allowed=Nie masz uprawnień do aktualizacji gałęzi
pulls.outdated_with_base_branch=Ta gałąź jest przestarzała w stosunku do gałęzi bazowej
-pulls.closed_at=`zamknął(-ęła) ten pull request %[2]s`
-pulls.reopened_at=`otworzył(-a) ponownie ten Pull Request %[2]s`
+pulls.closed_at=`zamknął(-ęła) ten pull request %s`
+pulls.reopened_at=`otworzył(-a) ponownie ten Pull Request %s`
@@ -2643,7 +2643,7 @@ pulls.closed = Pull request zamknięty
pulls.blocked_by_outdated_branch = Ten pull request jest zablokowany ponieważ jest przedawniony.
pulls.blocked_by_changed_protected_files_1 = Ten pull request jest zablokowany ponieważ wprowadza zmiany do chronionego pliku:
pulls.push_rejected_no_message = Wypchnięcie nie powiodło się: Wypchnięcie zostało odrzucone, ale nie otrzymano zdalnej wiadomości. Sprawdź hooki Git dla tego repozytorium.=
-pulls.commit_ref_at = `odniósł się do tego pull requesta z commita %[2]s`
+pulls.commit_ref_at = `odniósł się do tego pull requesta z commita %s`
pulls.cmd_instruction_checkout_desc = Ze swojego repozytorium projektu, utwórz nową gałąź i przetestuj zmiany.
pulls.clear_merge_message_hint = Wyczyszczenie wiadomości scalenia usunie tylko treść wiadomości commitu pozostawiając wygenerowane przez git dopiski takie jak "Co-Authored-By ...".
pulls.delete_after_merge.head_branch.insufficient_branch = Nie masz uprawnień by usunąć head gałęzi.
@@ -3951,29 +3951,29 @@ normal_file = Zwykły plik
search = Wyszukaj...
type_tooltip = Typ wyszukiwania
fuzzy = Przybliżone
-package_kind = Wyszukaj pakiety...
+package_kind = Wyszukaj pakiety…
fuzzy_tooltip = Uwzględnij wyniki, które są bliskie wyszukiwanemu hasłu
match = Dopasuj
match_tooltip = Uwzględniaj tylko wyniki pasujące do wyszukiwanego hasła
-repo_kind = Wyszukaj repozytoria...
-user_kind = Wyszukaj użytkownilków...
+repo_kind = Wyszukaj repozytoria…
+user_kind = Wyszukaj użytkownilków…
code_search_unavailable = Wyszukiwanie kodu jest obecnie niedostępne. Skontakuj sie z administratorem strony.
no_results = Nie znaleziono pasujących wyników.
-org_kind = Wyszukaj organizacje...
-team_kind = Wyszukaj zespoły...
-code_kind = Wyszukaj kod...
+org_kind = Wyszukaj organizacje…
+team_kind = Wyszukaj zespoły…
+code_kind = Wyszukaj kod…
code_search_by_git_grep = Obecne wyniki wyszukiwania kodu są dostarczane przez "git grep". Wyniki mogą być lepsze, jeśli administrator witryny włączy indeksator kodu.
-project_kind = Wyszukaj projekty...
-branch_kind = Wyszukaj gałęzie...
-commit_kind = Wyszukaj commity...
-runner_kind = Wyszukaj runnery...
+project_kind = Wyszukaj projekty…
+branch_kind = Wyszukaj gałęzie…
+commit_kind = Wyszukaj commity…
+runner_kind = Wyszukaj runnery…
keyword_search_unavailable = Wyszukiwanie według słów kluczowych jest obecnie niedostępne. Skontaktuj się z administratorem strony.
milestone_kind = Wyszukaj kamienie milowe...
union_tooltip = Uwzględnia wyniki pasujące do dowolnego słowa kluczowego rozdzielonego białymi znakami
exact = Dokładne
exact_tooltip = Uwzględniaj tylko wyniki pasujące do wyszukiwanego hasła
-issue_kind = Wyszukaj zgłoszenia...
-pull_kind = Wyszukaj pull requesty...
+issue_kind = Wyszukaj zgłoszenia…
+pull_kind = Wyszukaj pull requesty…
union = Unia
regexp = RegExp
regexp_tooltip = Interpretuj wyszukiwane hasło jako wyrażenie regularne
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 26bdd35420..cd5cc14833 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -1063,8 +1063,8 @@ language.localization_project = Ajude-nos a traduzir Forgejo para o seu idioma!
language.description = Essa língua será salva em sua conta e será usada como padrão após você iniciar a sessão.
user_block_yourself = Você não pode se bloquear.
pronouns_custom_label = Pronomes personalizados
-change_username_redirect_prompt.with_cooldown.one = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dia, você ainda pode recuperar o nome de usuário antigo durante este período de espera.
-change_username_redirect_prompt.with_cooldown.few = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dias, você ainda pode recuperar o nome de usuário antigo durante este período de espera.
+change_username_redirect_prompt.with_cooldown.one = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia. Você ainda pode recuperar o nome de usuário antigo durante este período de proteção.
+change_username_redirect_prompt.with_cooldown.few = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dias. Você ainda pode recuperar o nome de usuário antigo durante este período de proteção.
quota.applies_to_user = As seguintes regras de cota se aplicam à sua conta
quota.rule.exceeded.helper = O tamanho total de objetos para esta regra excedeu a cota.
keep_pronouns_private = Mostrar pronomes apenas para usuários autenticados
@@ -1278,7 +1278,7 @@ star_guest_user=Entre para adicionar este repositório aos favoritos.
unwatch=Deixar de observar
watch=Observar
unstar=Retirar dos favoritos
-star=Juntar aos favoritos
+star=Adicionar aos favoritos
fork=Fork
download_archive=Baixar repositório
more_operations=Mais operações
@@ -1568,7 +1568,7 @@ issues.remove_ref_at=`removeu a referência %s %s`
issues.add_ref_at=`adicionou a referência %s %s`
issues.delete_branch_at=`excluiu branch %s %s`
issues.filter_label=Etiqueta
-issues.filter_label_exclude=`Use alt
+ clique/enter
para excluir etiquetas`
+issues.filter_label_exclude=Use Alt + Clique para excluir etiquetas
issues.filter_label_no_select=Todas as etiquetas
issues.filter_label_select_no_label=Sem etiqueta
issues.filter_milestone=Marco
@@ -1642,13 +1642,13 @@ issues.close_comment_issue=Comentar e fechar
issues.reopen_issue=Reabrir
issues.reopen_comment_issue=Comentar e reabrir
issues.create_comment=Comentar
-issues.closed_at=`fechou esta issue %[2]s`
-issues.reopened_at=`reabriu esta issue %[2]s`
-issues.commit_ref_at=`citou esta issue em um commit %[2]s`
-issues.ref_issue_from=`referenciado esta issue %[4]s %[2]s`
-issues.ref_pull_from=`referenciado este pull request %[4]s %[2]s`
-issues.ref_closing_from=`referenciado esta issue de um pull request %[4]s que a fechará %[2]s`
-issues.ref_reopening_from=`referenciado esta issue de um pull request %[4]s que a reabrirá %[2]s`
+issues.closed_at=`fechou esta issue %s`
+issues.reopened_at=`reabriu esta issue %s`
+issues.commit_ref_at=`citou esta issue de um commit %s`
+issues.ref_issue_from=`citou esta issue %[3]s %[1]s`
+issues.ref_pull_from=`citou este pull request %[3]s %[1]s`
+issues.ref_closing_from=`citou esta issue de um pull request %[3]s que a fechará %[1]s`
+issues.ref_reopening_from=`citou esta issue de um pull request %[3]s que a reabrirá, %[1]s`
issues.ref_closed_from=`fechou esta issue %[4]s %[2]s`
issues.ref_reopened_from=`reabriu esta issue %[4]s %[2]s`
issues.ref_from=`de %[1]s`
@@ -1934,7 +1934,7 @@ pulls.status_checks_success=Todas as verificações foram bem sucedidas
pulls.status_checks_warning=Algumas verificações reportaram avisos
pulls.status_checks_failure=Algumas verificações falharam
pulls.status_checks_error=Algumas verificações reportaram erros
-pulls.status_checks_requested=Obrigatário
+pulls.status_checks_requested=Obrigatório
pulls.status_checks_details=Detalhes
pulls.update_branch=Atualizar branch por merge
pulls.update_branch_rebase=Atualizar branch por rebase
@@ -1942,8 +1942,8 @@ pulls.update_branch_success=Atualização do branch foi bem-sucedida
pulls.update_not_allowed=Você não tem permissão para atualizar o branch
pulls.outdated_with_base_branch=Este branch está desatualizado com o branch base
pulls.close=Fechar pull request
-pulls.closed_at=`fechou este pull request %[2]s`
-pulls.reopened_at=`reabriu este pull request %[2]s`
+pulls.closed_at=`fechou este pull request %s`
+pulls.reopened_at=`reabriu este pull request %s`
pulls.clear_merge_message=Limpar mensagem do merge
pulls.clear_merge_message_hint=Limpar a mensagem de merge só irá remover o conteúdo da mensagem de commit e manter trailers git gerados, como "Co-Authored-By …".
@@ -2719,7 +2719,7 @@ issues.label_archive_tooltip = Etiquetas arquivadas não serão exibidas nas sug
activity.navbar.pulse = Recente
settings.units.overview = Geral
settings.units.add_more = Habilitar mais
-pulls.commit_ref_at = `referenciou este pedido de mesclagem no commit %[2]s`
+pulls.commit_ref_at = `citou este pull request de um commit %s`
pulls.cmd_instruction_merge_title = Mesclar
settings.units.units = Unidades
vendored = Externo
@@ -2803,7 +2803,7 @@ mirror_use_ssh.helper = Forgejo irá espelhar o repositório via Git através de
mirror_denied_combination = Não é possível combinar o uso de chave pública e autenticação baseada em senha.
mirror_public_key = Chave SSH pública
mirror_use_ssh.text = Usar autenticação por SSH
-mirror_use_ssh.not_available = Autenticação por SSH não está disponível.
+mirror_use_ssh.not_available = A autenticação via SSH não está disponível.
settings.push_mirror_sync_in_progress = Fazendo push das mudanças para o remoto %s nesse momento.
settings.federation_apapiurl = URL de federação deste repositório. Copie e cole isso nas Configurações de Federação de outro repositório como uma URL de um Repositório Seguidor.
pulls.agit_explanation = Criado usando o fluxo de trabalho AGit. AGit permite que contribuidores proponham mudanças usando "git push" sem criar um fork ou novo branch.
@@ -2817,7 +2817,7 @@ settings.mirror_settings.pushed_repository = Repositório enviado
settings.mirror_settings.docs.disabled_pull_mirror.instructions = Configure seu projeto para automaticamente fazer push de commits, tags e branches para outro repositório. Espelhos de pull foram desativados pelo administrador do seu site.
settings.mirror_settings.docs.disabled_push_mirror.instructions = Configure seu projeto para automaticamente fazer pull de commits, tags e branches de outro repositório.
settings.mirror_settings.docs.doc_link_pull_section = a seção "Fazendo pull de um repositório remoto" da documentação.
-subscribe.pull.guest.tooltip = Entre para receber notificações deste pull request.
+subscribe.pull.guest.tooltip = Inicie a sessão para receber notificações deste pull request.
settings.pull_mirror_sync_quota_exceeded = Cota excedida, não será feito pull das mudanças.
settings.mirror_settings.docs.more_information_if_disabled = Saiba mais sobre espelhos de push e pull aqui:
settings.transfer_quota_exceeded = O novo dono (%s) excedeu a cota. O repositório não foi transferido.
@@ -2920,6 +2920,7 @@ settings.event_action_recover = Recuperar
settings.event_action_recover_desc = A execução da Action teve sucesso após a última execução no mesmo workflow ter falhado.
settings.event_action_success = Sucesso
settings.event_action_success_desc = A execução da Action foi bem sucedida.
+issues.filter_type.all_pull_requests = Todos os pull requests
[graphs]
component_loading = Carregando %s…
@@ -3056,8 +3057,8 @@ open_dashboard = Abrir painel
settings.change_orgname_prompt = Obs.: Alterar o nome de uma organização resultará na alteração do URL dela e disponibilizará o nome antigo para uso.
follow_blocked_user = Não foi possível seguir esta organização porque ela bloqueou-o(a).
form.name_pattern_not_allowed = O padrão "%s" não é permitido no nome de uma organização.
-settings.change_orgname_redirect_prompt.with_cooldown.one = O nome de organização antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia, você ainda pode recuperar o nome antigo durante este período de proteção.
-settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de organização antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dia, você ainda pode recuperar o nome antigo durante este período de espera.
+settings.change_orgname_redirect_prompt.with_cooldown.one = O nome de organização antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia. Você ainda pode recuperar o nome antigo durante este período de proteção.
+settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de organização antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia. Você ainda pode recuperar o nome antigo durante este período de proteção.
[admin]
dashboard=Painel
@@ -3899,7 +3900,7 @@ deletion=Excluir segredo
deletion.description=A exclusão de um segredo é permanente e não pode ser desfeita. Continuar?
deletion.success=O segredo foi excluído.
deletion.failed=Falha ao excluir segredo.
-management=Gerenciar segredos
+management=Gerenciamento de segredos
[actions]
actions=Ações
@@ -3908,12 +3909,12 @@ unit.desc=Gerenciar pipelines integradas de CI/CD com Forgejo Actions.
status.unknown=Desconhecido
status.waiting=Aguardando
-status.running=Rodando
+status.running=Executando
status.success=Sucesso
status.failure=Falha
-status.cancelled=Cancelado
-status.skipped=Ignorado
-status.blocked=Bloqueado
+status.cancelled=Cancelada
+status.skipped=Ignorada
+status.blocked=Bloqueada
runners=Runners
runners.runner_manage_panel=Gerenciar runners
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index 7f36d164b3..d82ae69fa4 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -1063,8 +1063,8 @@ language.description = Este idioma vai ser guardado na sua conta e ser usado com
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! Ler mais.
pronouns_custom_label = Pronomes personalizados
user_block_yourself = Não se pode bloquear a si próprio.
-change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
-change_username_redirect_prompt.with_cooldown.few = O nome de utilizador antigo ficará disponível para todos após um período de espera de %[1]d dias, 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. Pode ainda reivindicar o nome de utilizador antigo durante o período de espera.
+change_username_redirect_prompt.with_cooldown.few = O nome de utilizador antigo ficará disponível para todos após um período de espera de %[1]d dias. Pode ainda reivindicar o nome de utilizador antigo durante o período de espera.
quota.applies_to_user = As seguintes regras de quotas aplicam-se à sua conta
quota.sizes.assets.artifacts = Artefactos
quota.rule.exceeded.helper = O tamanho total dos objectos para esta regra excedeu a quota.
@@ -1583,7 +1583,7 @@ issues.remove_ref_at=`removeu a referência %s %s`
issues.add_ref_at=`adicionou a referência %s %s`
issues.delete_branch_at=`eliminou o ramo %s %s`
issues.filter_label=Rótulo
-issues.filter_label_exclude=`Use alt
+ clique/enter
para excluir rótulos`
+issues.filter_label_exclude=Use Alt + Clique para excluir rótulos
issues.filter_label_no_select=Todos os rótulos
issues.filter_label_select_no_label=Sem rótulo
issues.filter_milestone=Etapa
@@ -1657,13 +1657,13 @@ issues.close_comment_issue=Fechar com comentário
issues.reopen_issue=Reabrir
issues.reopen_comment_issue=Reabrir com comentário
issues.create_comment=Comentar
-issues.closed_at=`encerrou esta questão %[2]s`
-issues.reopened_at=`reabriu esta questão %[2]s`
-issues.commit_ref_at=`referenciou esta questão num cometimento %[2]s`
-issues.ref_issue_from=`referiu esta questão %[4]s %[2]s`
-issues.ref_pull_from=`referiu este pedido de integração %[4]s %[2]s`
-issues.ref_closing_from=`referiu esta questão a partir de um pedido de integração %[4]s que a fechará %[2]s`
-issues.ref_reopening_from=`referiu esta questão a partir de um pedido de integração %[4]s que a reabrirá %[2]s`
+issues.closed_at=`encerrou esta questão %s`
+issues.reopened_at=`reabriu esta questão %s`
+issues.commit_ref_at=`referenciou esta questão num cometimento %s`
+issues.ref_issue_from=`referiu esta questão %[3]s %[1]s`
+issues.ref_pull_from=`referiu este pedido de integração %[3]s %[1]s`
+issues.ref_closing_from=`referiu esta questão a partir de um pedido de integração %[3]s que a fechará %[1]s`
+issues.ref_reopening_from=`referiu esta questão a partir de um pedido de integração %[3]s que a reabrirá %[1]s`
issues.ref_closed_from=`encerrou esta questão %[4]s %[2]s`
issues.ref_reopened_from=`reabriu esta questão %[4]s %[2]s`
issues.ref_from=`de %[1]s`
@@ -1972,8 +1972,8 @@ pulls.update_branch_success=A sincronização do ramo foi bem sucedida
pulls.update_not_allowed=Não tem autorização para sincronizar o ramo
pulls.outdated_with_base_branch=Este ramo é obsoleto em relação ao ramo base
pulls.close=Encerrar pedido de integração
-pulls.closed_at=`fechou este pedido de integração %[2]s`
-pulls.reopened_at=`reabriu este pedido de integração %[2]s`
+pulls.closed_at=`fechou este pedido de integração %s`
+pulls.reopened_at=`reabriu este pedido de integração %s`
pulls.cmd_instruction_hint=Ver instruções para a linha de comandos
pulls.cmd_instruction_checkout_title=Conferir
pulls.cmd_instruction_checkout_desc=No seu repositório, irá criar um novo ramo para que possa testar as modificações.
@@ -2785,7 +2785,7 @@ settings.wiki_rename_branch_main_desc = Renomear o ramo usado internamente pelo
settings.add_collaborator_blocked_our = Não foi possível adicionar o/a colaborador/a porque o/a proprietário/a do repositório bloqueou-os.
settings.add_webhook.invalid_path = A localização não pode conter "." ou ".." ou ficar em branco. Não pode começar ou terminar com uma barra.
settings.graphql_url = URL do GraphQL
-pulls.commit_ref_at = `referiu este pedido de integração a partir de um cometimento %[2]s`
+pulls.commit_ref_at = `referiu este pedido de integração a partir de um cometimento %s`
settings.confirm_wiki_branch_rename = Renomear o ramo do wiki
settings.wiki_branch_rename_success = O nome do ramo do wiki do repositório foi normalizado com sucesso.
settings.wiki_branch_rename_failure = Falhou a normalização do nome do ramo do wiki do repositório.
@@ -2923,6 +2923,8 @@ settings.event_action_recover_desc = A execução de ação foi bem sucedida dep
settings.event_action_success = Sucesso
settings.event_action_success_desc = A Execução de ação foi bem sucedida.
+issues.filter_type.all_pull_requests = Todos os pedidos de integração
+
[graphs]
component_loading=A carregar %s…
component_loading_failed=Não foi possível carregar %s
@@ -3057,8 +3059,8 @@ teams.invite.by=Convidado(a) por %s
teams.invite.description=Clique no botão abaixo para se juntar à equipa.
follow_blocked_user = Não pode seguir esta organização porque esta organização bloqueou-o/a.
open_dashboard = Abrir painel de controlo
-settings.change_orgname_redirect_prompt.with_cooldown.one = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome antigo durante o período de espera.
-settings.change_orgname_redirect_prompt.with_cooldown.few = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dias, podendo ainda reivindicar o nome antigo durante o período de espera.
+settings.change_orgname_redirect_prompt.with_cooldown.one = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dia. Pode ainda reivindicar o nome antigo durante o período de espera.
+settings.change_orgname_redirect_prompt.with_cooldown.few = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dias. Pode ainda reivindicar o nome antigo durante o período de espera.
[admin]
dashboard=Painel de controlo
diff --git a/options/locale/locale_ro.ini b/options/locale/locale_ro.ini
index 305c34d013..c52788a05e 100644
--- a/options/locale/locale_ro.ini
+++ b/options/locale/locale_ro.ini
@@ -1,6 +1,3 @@
-
-
-
[common]
return_to_forgejo = Înapoi la Forgejo
explore = Explorează
@@ -223,12 +220,12 @@ invalid_db_setting = Setările pentru bază de date sunt invalide: %v
no_reply_address = Domeniu pentru adrese de email ascunse
[search]
-user_kind = Caută utilizatori...
-team_kind = Caută echipe...
-code_kind = Caută cod...
-project_kind = Caută proiecte...
-package_kind = Caută pachete...
-org_kind = Caută organizații...
+user_kind = Caută utilizatori…
+team_kind = Caută echipe…
+code_kind = Caută cod…
+project_kind = Caută proiecte…
+package_kind = Caută pachete…
+org_kind = Caută organizații…
code_search_unavailable = Căutarea de cod nu este disponibilă momentan. Te rog contactează administratorul site-ului.
keyword_search_unavailable = Căutarea după cuvânt cheie nu este disponibilă momentan. Te rog contactează administratorul site-ului.
no_results = Nu a fost găsit niciun rezultat corespunzător.
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index 9158329978..304b07b7ee 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -1063,7 +1063,7 @@ language.description = Выбранный язык будет сохранён
language.localization_project = Помогите с переводом Forgejo на свой язык! Подробнее.
user_block_yourself = Нельзя заблокировать себя.
pronouns_custom_label = Другие местоимения
-change_username_redirect_prompt.with_cooldown.one = Прежнее имя будет доступно для использования другим пользователям после истечения защиты в %[1]d день. Вы сможете вернуть его себе во время срока защиты.
+change_username_redirect_prompt.with_cooldown.one = Прежнее имя будет доступно для использования другим пользователям после истечения простоя в %[1]d день. Вы сможете вернуть его себе во время срока простоя.
change_username_redirect_prompt.with_cooldown.few = Прежнее имя будет доступно для использования другим пользователям после истечения защиты в %[1]d дней. Вы сможете вернуть его себе во время срока защиты.
keep_pronouns_private = Показывать местоимения только зарегистрированным пользователям
keep_pronouns_private.description = Местоимения будут скрыты от пользователей, не имеющих учётных записей на сервере.
@@ -1563,7 +1563,7 @@ issues.remove_ref_at=`убрана ссылка на %s %s`
issues.add_ref_at=`добавлена ссылка на %s %s`
issues.delete_branch_at=`удалена ветвь %s %s`
issues.filter_label=Метки
-issues.filter_label_exclude=`Исключайте метки с помощью alt
+ лкм/enter
`
+issues.filter_label_exclude=Исключайте метки с помощью Alt + ЛКМ
issues.filter_label_no_select=Любые метки
issues.filter_label_select_no_label=Без меток
issues.filter_milestone=Этап
@@ -1637,13 +1637,13 @@ issues.close_comment_issue=Закрыть комментарием
issues.reopen_issue=Открыть снова
issues.reopen_comment_issue=Открыть снова комментарием
issues.create_comment=Комментировать
-issues.closed_at=`задача была закрыта %[2]s`
-issues.reopened_at=`задача была открыта снова %[2]s`
-issues.commit_ref_at=`упоминание этой задачи в коммите %[2]s`
-issues.ref_issue_from=`упоминание этой задачи %[4]s %[2]s`
-issues.ref_pull_from=`упоминание этого запроса слияния %[4]s %[2]s`
-issues.ref_closing_from=`упоминание из запроса на слияние %[4]s, который закроет эту задачу %[2]s`
-issues.ref_reopening_from=`упоминание из запроса на слияние %[4]s, который повторно откроет эту задачу %[2]s`
+issues.closed_at=`задача была закрыта %s`
+issues.reopened_at=`задача была открыта снова %s`
+issues.commit_ref_at=`упоминание этой задачи в коммите %s`
+issues.ref_issue_from=`упоминание этой задачи %[3]s %[1]s`
+issues.ref_pull_from=`упомянул этот запрос на слияние %[3]s %[1]s`
+issues.ref_closing_from=`упомянул эту задачу в запросе на слияние %[3]s, который закроет её %[1]s`
+issues.ref_reopening_from=`упомянул эту задачу в запросе на слияние %[3]s, который переоткроет эту задачу %[1]s`
issues.ref_closed_from=`закрыл этот запрос %[4]s %[2]s`
issues.ref_reopened_from=`задача была открыта снова %[4]s %[2]s`
issues.ref_from=`из %[1]s`
@@ -1943,8 +1943,8 @@ pulls.update_branch_success=Ветвь успешно обновлена
pulls.update_not_allowed=Недостаточно прав для обновления ветви
pulls.outdated_with_base_branch=Эта ветвь отстает от базовой ветви
pulls.close=Закрыть запрос слияния
-pulls.closed_at=`закрыл этот запрос на слияние %[2]s`
-pulls.reopened_at=`переоткрыл этот запрос на слияние %[2]s`
+pulls.closed_at=`закрыл этот запрос на слияние %s`
+pulls.reopened_at=`переоткрыл этот запрос на слияние %s`
pulls.cmd_instruction_hint=Показать инструкции для командной строки
pulls.cmd_instruction_merge_title=Слейте изменения
pulls.cmd_instruction_merge_desc=Слейте изменения и отправьте их обратно.
@@ -2772,7 +2772,7 @@ settings.ignore_stale_approvals = Игнорировать устаревшие
contributors.contribution_type.additions = Добавления
contributors.contribution_type.deletions = Удаления
contributors.contribution_type.filter_label = Вид деятельности:
-pulls.commit_ref_at = `упоминание этого запроса слияния в коммите %[2]s`
+pulls.commit_ref_at = `сослался на этот запрос слияния в коммите %s`
settings.thread_id = ИД обсуждения
pulls.made_using_agit = AGit
activity.navbar.contributors = Соавторы
diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini
index d55b238b1c..e1e19fa78e 100644
--- a/options/locale/locale_si-LK.ini
+++ b/options/locale/locale_si-LK.ini
@@ -482,7 +482,7 @@ avatar=අවතාර්
ssh_gpg_keys=SSH/ජීපීජී යතුරු
social=සමාජ ගිණුම්
applications=යෙදුම්
-orgs=සංවිධාන කළමනාකරණය
+orgs=සංවිධාන
repos=කෝෂ්ඨ
delete=ගිණුම මකන්න
twofa=ද්වි-සාධක සත්යාපනය
@@ -527,8 +527,8 @@ password_change_disabled=දේශීය නොවන පරිශීලකය
emails=වි-තැපැල් ලිපින
manage_emails=වි-තැපැල් ලිපින කළමනාකරණය
-manage_themes=පෙරනිමි තේමාව තෝරන්න
-manage_openid=OpenID ලිපිනයන් කළමනාකරණය කරන්න
+manage_themes=පෙරනිමි තේමාව
+manage_openid=OpenID ලිපින
theme_desc=මෙම වෙබ් අඩවිය හරහා ඔබගේ පෙරනිමි තේමාව වනු ඇත.
primary=ප්රාථමික
activated=සක්රිය
@@ -1100,12 +1100,12 @@ issues.close_comment_issue=අදහස් දක්වා වසන්න
issues.reopen_issue=නැවත විවෘත කරන්න
issues.reopen_comment_issue=අදහස් දක්වා විවෘත කරන්න
issues.create_comment=අදහස
-issues.closed_at=`මෙම ගැටළුව වසා %[2]s`
-issues.reopened_at=`මෙම ගැටළුව නැවත විවෘත කරන ලදි %[2]s`
-issues.ref_issue_from=`මෙම නිකුතුව %[4]s හි %[2]s`
-issues.ref_pull_from=`මෙම අදින්න ඉල්ලීම%[4]s %[2]s`
-issues.ref_closing_from=`මෙම ගැටළුව වසා දමනු ඇත%[4]s මෙම ගැටළුව %[2]s`
-issues.ref_reopening_from=`මෙම ගැටළුව නැවත විවෘත කරනු ඇත%[4]s මෙම ගැටළුව %[2]s`
+issues.closed_at=`මෙම ගැටළුව වසා %s`
+issues.reopened_at=`මෙම ගැටළුව නැවත විවෘත කරන ලදි %s`
+issues.ref_issue_from=`මෙම නිකුතුව %[3]s හි %[1]s`
+issues.ref_pull_from=`මෙම අදින්න ඉල්ලීම%[3]s %[1]s`
+issues.ref_closing_from=`මෙම ගැටළුව වසා දමනු ඇත%[3]s මෙම ගැටළුව %[1]s`
+issues.ref_reopening_from=`මෙම ගැටළුව නැවත විවෘත කරනු ඇත%[3]s මෙම ගැටළුව %[1]s`
issues.ref_closed_from=`මෙම නිකුතුව%[4]s %[2]s`
issues.ref_reopened_from=`මෙම නිකුතුව%[4]s %[2]sනැවත විවෘත කරන ලදි`
issues.ref_from=`හිම%[1]s`
@@ -1342,8 +1342,8 @@ pulls.update_branch_rebase=රිබේස් මගින් ශාඛාව
pulls.update_branch_success=ශාඛා යාවත්කාලීන කිරීම සාර්ථක විය
pulls.update_not_allowed=ශාඛාව යාවත්කාලීන කිරීමට ඔබට අවසර නැත
pulls.outdated_with_base_branch=මෙම ශාඛාව මූලික ශාඛාව සමඟ දිවයයි
-pulls.closed_at=`මෙම අදින්න ඉල්ලීම වසා %[2]s`
-pulls.reopened_at=`මෙම අදින්න ඉල්ලීම නැවත විවෘත කරන ලදි %[2]s`
+pulls.closed_at=`මෙම අදින්න ඉල්ලීම වසා %s`
+pulls.reopened_at=`මෙම අදින්න ඉල්ලීම නැවත විවෘත කරන ලදි %s`
diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini
index 0c44df326a..aa2f863b14 100644
--- a/options/locale/locale_sk-SK.ini
+++ b/options/locale/locale_sk-SK.ini
@@ -597,7 +597,7 @@ avatar=Avatar
ssh_gpg_keys=SSH / GPG kľúče
social=Sociálne účty
applications=Aplikácie
-orgs=Spravovať organizácie
+orgs=Organizácie
repos=Repozitáre
delete=Zmazať účet
twofa=Dvojfaktorové overenie
@@ -656,8 +656,8 @@ password_change_disabled=Externe overovaní používatelia nemôžu aktualizova
emails=E-mailové adresy
manage_emails=Správa e-mailových adries
-manage_themes=Nastavenie predvolenej témy
-manage_openid=Správa OpenID adries
+manage_themes=Predvolená téma
+manage_openid=Adresy OpenID
theme_desc=Toto bude vaša predvolená téma vzhľadu naprieč stránkou.
primary=Primárny
activated=Aktivovaný
diff --git a/options/locale/locale_sl.ini b/options/locale/locale_sl.ini
index 608e05afa4..07ccaed259 100644
--- a/options/locale/locale_sl.ini
+++ b/options/locale/locale_sl.ini
@@ -133,7 +133,7 @@ reinstall_confirm_check_3 = Potrjujete, da ste popolnoma prepričani, da se ta p
require_db_desc = Forgejo zahteva MySQL, PostgreSQL, SQLite3 ali TiDB (protokol MySQL).
password_algorithm_helper = Nastavite algoritem za stiskanje gesla. Algoritmi imajo različne zahteve in moč. Algoritem argon2 je precej varen, vendar porabi veliko pomnilnika in je lahko neprimeren za majhne sisteme.
reinstall_confirm_message = Ponovna namestitev z obstoječo zbirko podatkov Forgejo lahko povzroči več težav. V večini primerov morate za zagon programa Forgejo uporabiti obstoječi "app.ini". Če veste, kaj počnete, potrdite naslednje:
-err_admin_name_is_reserved = Administrator Uporabniško ime je neveljavno, uporabniško ime je rezervirano
+err_admin_name_is_reserved = Administrator uporabniško ime je neveljavno, uporabniško ime je rezervirano
disable_gravatar.description = Onemogočite vire avatarjev Gravatar in avatarje tretjih oseb. Uporabi se privzeti avatar, razen če uporabnik lokalno naloži avatar.
install = Namestitev
title = Začetna nastavitev
@@ -367,7 +367,7 @@ delete = Brisanje računa
uploaded_avatar_is_too_big = Velikost naložene datoteke (%d KiB) presega največjo velikost (%d KiB).
webauthn = Dvofaktorsko preverjanje pristnosti (varnostni ključi)
change_username_redirect_prompt = Staro uporabniško ime bo preusmerjeno, dokler ga nekdo ne prevzame.
-orgs = Upravljanje organizacij
+orgs = Organizacije
public_profile = Javni profil
gpg_key_verified_long = Ključ je bil preverjen z žetonom in ga je mogoče uporabiti za preverjanje zavez, ki ustrezajo vsem aktiviranim e-poštnim naslovom tega uporabnika, poleg vseh ujemajočih se identitet za ta ključ.
@@ -495,14 +495,14 @@ tab_openid = Odprta identiteta
[home]
show_both_archived_unarchived = Prikazovanje arhiviranih in nearhiviranih
-switch_dashboard_context = Kontekst stikala Nadzorna plošča
+switch_dashboard_context = Kontekst stikala nadzorna plošča
search_repos = Poiščite skladišče…
filter_by_team_repositories = Filtriranje po skupinskih skladiščih
show_archived = Arhivirano
collaborative_repos = Sodelovalni repozitoriji
my_mirrors = Moja ogledala
show_only_public = Prikazovanje samo javnih
-uname_holder = Uporabniško ime ali E-poštovni naslov
+uname_holder = Uporabniško ime ali e-poštni naslov
password_holder = Geslo
my_repos = Repozitoriji
show_more_repos = Prikaži več skladišč…
diff --git a/options/locale/locale_sr-SP.ini b/options/locale/locale_sr-SP.ini
index 56c1a7e650..b14fdc1a35 100644
--- a/options/locale/locale_sr-SP.ini
+++ b/options/locale/locale_sr-SP.ini
@@ -326,7 +326,7 @@ issues.no_content=Још нема садржаја.
issues.close_issue=Затвори
issues.reopen_issue=Поново отвори
issues.create_comment=Коментирај
-issues.commit_ref_at=`поменуо овај задатак у комит %[2]s`
+issues.commit_ref_at=`поменуо овај задатак у комит %s`
issues.poster=Аутор
issues.collaborator=Коаутор
issues.owner=Власник
diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini
index 541acbf408..ec57f025cd 100644
--- a/options/locale/locale_sv-SE.ini
+++ b/options/locale/locale_sv-SE.ini
@@ -918,7 +918,7 @@ migrate.migrate_items_options=Åtkomsttoken krävs för att migrera ytterligare
migrated_from=Migrerad från %[2]s
migrated_from_fake=Migrerad från %[1]s
migrate.migrate=Migrera från %s
-migrate.migrating=Migrerar från %s ...
+migrate.migrating=Migrerar från %s …
migrate.migrating_failed=Migrering från %s misslyckades.
migrate.migrating_issues=Migrerar ärenden
@@ -1157,13 +1157,13 @@ issues.close_comment_issue=Stäng med kommentar
issues.reopen_issue=Återöppna
issues.reopen_comment_issue=Öppna igen med kommentar
issues.create_comment=Kommentera
-issues.closed_at=`stängde ärendet %[2]s`
-issues.reopened_at=`återöppnade detta ärende %[2]s`
-issues.commit_ref_at=`refererade till detta ärende från en incheckning %[2]s`
-issues.ref_issue_from=`refererade till detta ärende %[4]s %[2]s`
-issues.ref_pull_from=`refererade till denna pull-förfrågan %[4]s %[2]s`
-issues.ref_closing_from=`hänvisade till detta ärende från en pull-förfrågan %[4]s som kommer att stänga det %[2]s`
-issues.ref_reopening_from=`hänvisade till detta ärende från en pull-förfrågan %[4]s som kommer att öppna ärendet på nytt %[2]s`
+issues.closed_at=`stängde ärendet %s`
+issues.reopened_at=`återöppnade detta ärende %s`
+issues.commit_ref_at=`refererade till detta ärende från en incheckning %s`
+issues.ref_issue_from=`refererade till detta ärende %[3]s %[1]s`
+issues.ref_pull_from=`refererade till denna pull-förfrågan %[3]s %[1]s`
+issues.ref_closing_from=`hänvisade till detta ärende från en pull-förfrågan %[3]s som kommer att stänga det %[1]s`
+issues.ref_reopening_from=`hänvisade till detta ärende från en pull-förfrågan %[3]s som kommer att öppna ärendet på nytt %[1]s`
issues.ref_closed_from=`stängde detta ärende %[4]s %[2]s`
issues.ref_reopened_from=`öpnnade detta ärende igen %[4]s %[2]s`
issues.ref_from=`från %[1]s`
@@ -2324,17 +2324,17 @@ exact = Exakt
exact_tooltip = Inkludera bara resultat som exakt matchar söktermen
repo_kind = Sök repon…
user_kind = Sök användare…
-code_kind = Sök kod...
-package_kind = Sök paket...
-runner_kind = Sök exekutorer...
-branch_kind = Sök grenar...
-commit_kind = Sök commiter...
-project_kind = Sök projekt...
+code_kind = Sök kod…
+package_kind = Sök paket…
+runner_kind = Sök exekutorer…
+branch_kind = Sök grenar…
+commit_kind = Sök commiter…
+project_kind = Sök projekt…
search = Sök…
type_tooltip = Söktyp
-team_kind = Sök lag...
+team_kind = Sök team…
org_kind = Sök organisationer…
-issue_kind = Sök ärenden...
+issue_kind = Sök ärenden…
regexp_tooltip = Tolka söktermen som ett reguljärt uttryck
code_search_unavailable = Kodsökning är för närvarande inte tillgänglig. Vänligen kontakta webbplatsadministratören.
fuzzy_tooltip = Inkludera resultat som är närliggande till söktermen
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index 4f51ddcc7e..0bb49a2181 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -163,8 +163,8 @@ new_repo.link = Yeni depo
new_org.link = Yeni organizasyon
error413 = Kotanızı doldurdunuz.
toggle_menu = Menüyü aç-kapa
-new_migrate.title = Yeni geçiş
-new_migrate.link = Yeni geçiş
+new_migrate.title = Yeni göç
+new_migrate.link = Yeni göç
copy_path = Dizini kopyala
confirm_delete_artifact = "%s" adlı öğeyi silmek istediğinizden emin misiniz?
@@ -179,8 +179,10 @@ number_of_contributions_in_the_last_12_months=son 12 ayda %s katkı
contributions_zero=Katkı yapılmamış
less=Daha az
more=Daha Fazla
-contributions_one = katılım
-contributions_few = katılımlar
+contributions_one = katkı
+contributions_few = katkı
+
+contributions_format = {day} {month} {year} tarihinde {contributions} katkı
[editor]
buttons.heading.tooltip=Başlık ekle
@@ -204,6 +206,13 @@ table_modal.placeholder.content = İçerik
table_modal.label.rows = Satırlar
table_modal.label.columns = Sütunlar
+buttons.indent.tooltip = Bir seviye girinti artır
+buttons.unindent.tooltip = Bir seviye girinti azalt
+link_modal.header = Bağlantı ekle
+link_modal.url = Url
+link_modal.description = Açıklama
+link_modal.paste_reminder = İpucu: Panonuzdaki bir URL'yi doğrudan düzenleyiciye yapıştırarak bir bağlantı oluşturabilirsiniz.
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -227,6 +236,8 @@ lightweight_desc=Forgejo'nın minimal gereksinimleri çok düşüktür ve ucuz b
license=Açık Kaynak
license_desc=Gidin ve Forgejo'yı edinin! Bu projeyi daha da iyi yapmak için katkıda bulunarak bize katılın. Katkıda bulunmaktan çekinmeyin!
+platform_desc = Forgejo'nun Linux ve FreeBSD gibi özgür işletim sistemlerinde ve farklı CPU mimarilerinde çalıştığı doğrulandı. Sevdiğinizi seçin!
+
[install]
install=Kurulum
title=Başlangıç Yapılandırması
@@ -252,9 +263,9 @@ err_empty_db_path=SQLite3 veritabanı dosya yolu boş olamaz.
no_admin_and_disable_registration=Bir yönetici hesabı oluşturmadan kullanıcı kaydını kapatamazsınız.
err_empty_admin_password=Yönetici parolası boş olamaz.
err_empty_admin_email=Yönetici e-postası boş olamaz.
-err_admin_name_is_reserved=Yönetici Kullanıcı Adı geçersiz, bu kullanıcı adı rezerv edilen bir kelimedir
+err_admin_name_is_reserved=Yönetici kullanıcı adı geçersiz, bu kullanıcı adı rezerv edilen bir kelimedir
err_admin_name_pattern_not_allowed=Yönetici kullanıcı adı geçersiz, kullanıcı adı ayrılmış bir desenle eşleşiyor
-err_admin_name_is_invalid=Yönetici Kullanıcı Adı geçersiz
+err_admin_name_is_invalid=Yönetici kullanıcı adı geçersiz
general_title=Genel ayarlar
app_name=Site Başlığı
@@ -345,6 +356,8 @@ allow_dots_in_usernames = Kullanıcı isimlerinde noktaya izin ver. Var olan kul
smtp_from_invalid = `"E-posta Olarak Gönder" adresi geçersiz`
+config_location_hint = Bu yapılandırma seçenekleri şuraya kaydedilecek:
+
[home]
uname_holder=Kullanıcı adı veya e-posta adresi
password_holder=Parola
@@ -478,6 +491,8 @@ sign_in_openid = OpenID ile giriş yap
hint_login = Mevcut hesabın var mı? Hemen giriş yap!
use_onetime_code = Tek kullanımlık kod kullan
+change_unconfirmed_email = Kayıt sırasında yanlış e-posta adresi verdiyseniz, aşağıdan değiştirebilirsiniz; yeni adresinize bir onay mesajı gönderilecektir.
+
[mail]
view_it_on=%s üzerinde görüntüle
reply=veya doğrudan bu e-postayı yanıtlayın
@@ -722,16 +737,16 @@ avatar=Avatar
ssh_gpg_keys=SSH / GPG Anahtarları
social=Sosyal Medya Hesapları
applications=Uygulamalar
-orgs=Organizasyonları Yönet
+orgs=Kuruluşlar
repos=Depolar
-delete=Hesabı Sil
-twofa=İki Aşamalı Doğrulama
+delete=Hesabı sil
+twofa=İki aşamalı doğrulama
account_link=Bağlı Hesaplar
organization=Organizasyonlar
uid=UID
webauthn=Güvenlik Anahtarları
-public_profile=Herkese Açık Profil
+public_profile=Herkese açık profil
biography_placeholder=Bize kendiniz hakkında birşeyler söyleyin! (Markdown kullanabilirsiniz)
location_placeholder=Yaklaşık konumunuzu başkalarıyla paylaşın
profile_desc=Profilinizin başkalarına nasıl gösterildiğini yönetin. Ana e-posta adresiniz bildirimler, parola kurtarma ve web tabanlı Git işlemleri için kullanılacaktır.
@@ -796,8 +811,8 @@ password_change_disabled=Yerel olmayan kullanıcılar parolalarını Forgejo web
emails=E-Posta Adresleri
manage_emails=E-posta Adreslerini Yönet
-manage_themes=Varsayılan temayı seç
-manage_openid=OpenID Adreslerini Yönet
+manage_themes=Varsayılan tema
+manage_openid=OpenID adresleri
email_desc=Ana e-posta adresiniz bildirimler, parola kurtarma ve gizlenmemişse eğer web tabanlı Git işlemleri için kullanılacaktır.
theme_desc=Bu, sitedeki varsayılan temanız olacak.
primary=Birincil
@@ -1166,7 +1181,7 @@ form.name_reserved=Depo adı "%s" rezerve edilmiş.
form.name_pattern_not_allowed=Depo adında "%s" deseni kullanılamaz.
need_auth=Yetkilendirme
-migrate_options=Göç Seçenekleri
+migrate_options=Göç seçenekleri
migrate_service=Göç Hizmeti
migrate_options_mirror_helper=Bu depo bir yansı olacaktır
migrate_options_lfs=LFS dosyalarını taşı
@@ -1174,7 +1189,7 @@ migrate_options_lfs_endpoint.label=LFS Uç Noktası
migrate_options_lfs_endpoint.description=Taşıma, LFS sunucusunu belirlemek için Git uzak sunucusunu kullanmaya çalışacak. Eğer LFS veri deposu başka yerdeyse özel bir uç nokta da belirtebilirsiniz.
migrate_options_lfs_endpoint.description.local=Yerel bir sunucu yolu da destekleniyor.
migrate_options_lfs_endpoint.placeholder=Boş bırakılırsa, uç nokta klon URL'sinden türetilecektir
-migrate_items=Göç Öğeleri
+migrate_items=Göç öğeleri
migrate_items_wiki=Wiki
migrate_items_milestones=Kilometre Taşları
migrate_items_labels=Etiketler
@@ -1215,7 +1230,7 @@ migrate.migrating_labels=Etiketleri Taşıma
migrate.migrating_releases=Sürümleri Taşıma
migrate.migrating_issues=Konuları Taşıma
migrate.migrating_pulls=Değişiklik İsteklerini Taşıma
-migrate.cancel_migrating_title=Göçü İptal Et
+migrate.cancel_migrating_title=Göçü iptal et
migrate.cancel_migrating_confirm=Bu göçü iptal etmek istiyor musunuz?
mirror_from=şunun yansıması
@@ -1252,7 +1267,7 @@ find_tag=Etiketi bul
branches=Dal
tags=Etiket
issues=Konular
-pulls=Değişiklik İstekleri
+pulls=Değişiklik istekleri
project_board=Projeler
packages=Paketler
actions=İşlemler
@@ -1443,7 +1458,7 @@ projects.column.set_default=Varsayılanı Ayarla
projects.column.set_default_desc=Bu sütunu kategorize edilmemiş konular ve değişiklik istekleri için varsayılan olarak ayarlayın
projects.column.unset_default=Varsayılanları Geri Al
projects.column.unset_default_desc=Bu sütunu varsayılan olarak geri al
-projects.column.delete=Sutün Sil
+projects.column.delete=Sütunu sil
projects.column.deletion_desc=Bir proje sütununun silinmesi, ilgili tüm konuları 'Kategorize edilmemiş'e taşır. Devam edilsin mi?
projects.column.color=Renk
projects.open=Aç
@@ -1594,13 +1609,13 @@ issues.close_comment_issue=Yorum Yap ve Kapat
issues.reopen_issue=Yeniden aç
issues.reopen_comment_issue=Yorum Yap ve Yeniden Aç
issues.create_comment=Yorum yap
-issues.closed_at=`%[2]s konusunu kapattı`
-issues.reopened_at=`%[2]s konusunu yeniden açtı`
-issues.commit_ref_at=`%[2]s işlemesinde bu konuyu işaret etti`
-issues.ref_issue_from=`bu konuya referansta bulundu %[4]s %[2]s`
-issues.ref_pull_from=`bu değişiklik isteğine referansta bulundu %[4]s %[2]s`
-issues.ref_closing_from=`bir değişiklik isteğine referansta bulundu %[4]s bu konu kapatılacak %[2]s`
-issues.ref_reopening_from=`bir değişiklik isteğine referansta bulundu %[4]s bu konu yeniden açılacak %[2]s`
+issues.closed_at=`%s konusunu kapattı`
+issues.reopened_at=%s sorununu yeniden açtı
+issues.commit_ref_at=`%s işlemesinde bu konuyu işaret etti`
+issues.ref_issue_from=`bu konuya referansta bulundu %[3]s %[1]s`
+issues.ref_pull_from=`bu değişiklik isteğine referansta bulundu %[3]s %[1]s`
+issues.ref_closing_from=`bir değişiklik isteğine referansta bulundu %[3]s bu konu kapatılacak %[1]s`
+issues.ref_reopening_from=`bir değişiklik isteğine referansta bulundu %[3]s bu konu yeniden açılacak %[1]s`
issues.ref_closed_from=`bu konuyu kapat%[4]s %[2]s`
issues.ref_reopened_from=`konuyu yeniden aç%[4]s %[2]s`
issues.ref_from=`%[1]s'den`
@@ -1647,7 +1662,7 @@ issues.label.filter_sort.alphabetically=Alfabetik
issues.label.filter_sort.reverse_alphabetically=Ters alfabetik
issues.label.filter_sort.by_size=En küçük boyut
issues.label.filter_sort.reverse_by_size=En büyük boyut
-issues.num_participants_few=%d Katılımcı
+issues.num_participants_few=%d katılımcı
issues.attachment.open_tab=`Yeni bir sekmede "%s" görmek için tıkla`
issues.attachment.download=`"%s" indirmek için tıkla`
issues.subscribe=Abone Ol
@@ -1907,8 +1922,8 @@ pulls.update_branch_success=Dal güncellemesi başarıyla gerçekleştirildi
pulls.update_not_allowed=Dalı güncelleme izniniz yok
pulls.outdated_with_base_branch=Bu dal, temel dal ile güncel değil
pulls.close=Değişiklik İsteğini Kapat
-pulls.closed_at=`%[2]s değişiklik isteğini kapattı`
-pulls.reopened_at=`%[2]s değişiklik isteğini yeniden açtı`
+pulls.closed_at=`%s değişiklik isteğini kapattı`
+pulls.reopened_at=`%s değişiklik isteğini yeniden açtı`
pulls.cmd_instruction_hint=`Komut satırı talimatlarını görüntüleyin.`
pulls.cmd_instruction_checkout_title=Çekme
pulls.cmd_instruction_checkout_desc=Proje deponuzdan yeni bir dalı çekin ve değişiklikleri test edin.
@@ -1984,7 +1999,7 @@ ext_wiki=Harici Vikiye Erişim
ext_wiki.desc=Harici bir wiki'ye bağlantı.
wiki=Wiki
-wiki.welcome=Wiki'ye Hoşgeldiniz.
+wiki.welcome=Viki'ye Hoş geldiniz.
wiki.welcome_desc=Wiki, katkıcılarla belge yazmanıza ve paylaşmanıza olanak tanır.
wiki.desc=Katkıcılarla belgeler yazın ve paylaşın.
wiki.create_first_page=İlk sayfayı oluştur
@@ -2140,15 +2155,15 @@ settings.use_external_wiki=Harici Wiki Kullan
settings.external_wiki_url=Harici Wiki bağlantısı
settings.external_wiki_url_error=Harici wiki URL'si geçerli bir URL değil.
settings.external_wiki_url_desc=Ziyaretçiler, wiki sekmesine tıklandığında harici wiki URL'sine yönlendirilir.
-settings.issues_desc=Depo Konu İzleyicisini Etkinleştir
-settings.use_internal_issue_tracker=Yerleşik Konu İzleyici Kullan
-settings.use_external_issue_tracker=Harici Konu İzleyici Kullan
-settings.external_tracker_url=Harici Konu İzleyici URLsi
+settings.issues_desc=Depo sorun izleyicisini etkinleştir
+settings.use_internal_issue_tracker=Yerleşik sorun izleyici kullan
+settings.use_external_issue_tracker=Harici sorun izleyici kullan
+settings.external_tracker_url=Harici sorun izleyici URL'si
settings.external_tracker_url_error=Harici konu izleyici URL'si geçerli bir URL değil.
settings.external_tracker_url_desc=Ziyaretçiler, konular sekmesine tıkladığında harici konu izleyici URL'sine yönlendirilir.
-settings.tracker_url_format=Harici Konu İzleyici URL Biçimi
+settings.tracker_url_format=Harici sorun izleyici URL Biçimi
settings.tracker_url_format_error=Harici konu izleyici URL biçimi geçerli bir URL değil.
-settings.tracker_issue_style=Harici Konu İzleyici Numara Biçimi
+settings.tracker_issue_style=Harici sorun izleyici Numara Biçimi
settings.tracker_issue_style.numeric=Sayısal
settings.tracker_issue_style.alphanumeric=Alfanumerik
settings.tracker_issue_style.regexp=Düzenli ifade
@@ -2158,13 +2173,13 @@ settings.tracker_url_format_desc=Kullanıcı adı, depo adı ve yayın dizini i
settings.enable_timetracker=Zaman Takibini Etkinleştir
settings.allow_only_contributors_to_track_time=Sadece Katkıcılar İçin Zaman Takibine İzin Ver
settings.pulls_desc=Değişiklik İsteklerini Etkinleştir
-settings.pulls.ignore_whitespace=Çakışmalar için Boşlukları Gözardı Et
+settings.pulls.ignore_whitespace=Çakışmalar için boşlukları gözardı et
settings.pulls.enable_autodetect_manual_merge=Kendiliğinden algılamalı elle birleştirmeyi etkinleştir (Not: Bazı özel durumlarda yanlış kararlar olabilir)
settings.pulls.allow_rebase_update=Değişiklik isteği dalının yeniden yapılandırmayla güncellenmesine izin ver
settings.pulls.default_delete_branch_after_merge=Varsayılan olarak birleştirmeden sonra değişiklik isteği dalını sil
settings.pulls.default_allow_edits_from_maintainers=Bakımcıların düzenlemelerine izin ver
settings.releases_desc=Depo Sürümlerini Etkinleştir
-settings.packages_desc=Depo paket kütüğünü etkinleştir
+settings.packages_desc=Depo paket kayıt defterini etkinleştir
settings.projects_desc=Depo Projelerini Etkinleştir
settings.actions_desc=Depo İşlemlerini Etkinleştir
settings.admin_settings=Yönetici Ayarları
@@ -2188,7 +2203,7 @@ settings.convert_fork_desc=Bu çatalı normal bir depoya dönüştürebilirsiniz
settings.convert_fork_notices_1=Bu işlem çatalı normal bir depoya dönüştürür ve geri alınamaz.
settings.convert_fork_confirm=Depoyu Dönüştür
settings.convert_fork_succeed=Çatal normal bir depoya dönüştürüldü.
-settings.transfer.title=Sahipliği Aktar
+settings.transfer.title=Sahipliği aktar
settings.transfer.rejected=Depo aktarımı reddedildi.
settings.transfer.success=Depo aktarımı başarıyla tamamlandı.
settings.transfer_abort=Aktarımı iptal et
@@ -2448,7 +2463,7 @@ settings.block_on_official_review_requests_desc=Yeterli onay olsa bile, resmi in
settings.block_outdated_branch=Değişiklik isteği güncel değilse birleştirmeyi engelle
settings.block_outdated_branch_desc=Baş dal taban dalın arkasındayken birleştirme mümkün olmayacaktır.
settings.default_branch_desc=Değişiklik istekleri ve kod işlemeleri için varsayılan bir depo dalı seçin:
-settings.merge_style_desc=Biçimleri Birleştir
+settings.merge_style_desc=Birleştirme biçemleri
settings.default_merge_style_desc=Değişiklik istekleri için varsayılan birleştirme tarzı:
settings.choose_branch=Bir dal seç…
settings.no_protected_branch=Korumalı dal yok.
@@ -2701,7 +2716,7 @@ settings.new_owner_blocked_doer = Yeni sahip sizi engelledi.
open_with_editor = %s ile aç
object_format = Nesne Biçimi
-mirror_sync = eşitlendi
+mirror_sync = eşitlenme:
stars = Yıldızlar
desc.sha256 = SHA256
vendored = Sağlanmış
@@ -2722,6 +2737,26 @@ settings.ignore_stale_approvals = Eskimiş onayları yoksay
settings.ignore_stale_approvals_desc = Daha eski işlemelere (eski incelemelere) yapılmış olan onayları, Dİ'nin kaç onayı olduğunu belirlerken sayma. Eskimiş incelemeler atıldıysa bu ilgisizdir.
error.broken_git_hook = Bu deponun Git İstemcileri bozuk gibi gözüküyor. Onarmak için lütfen belgelere bakın, daha sonra durumu yenilemek için bazı işlemeler itin.
+mirror_public_key = Ortak SSH anahtarı
+mirror_use_ssh.text = SSH yetkilendirme kullan
+mirror_use_ssh.helper = Forgejo, bu seçeneği seçtiğinizde deponuzu SSH üzerinden Git üzerinden yansıtacak ve sizin için bir anahtar çifti oluşturacaktır. Oluşturulan ortak anahtarın hedef depoya gönderilmek üzere yetkilendirildiğinden emin olmalısınız. Bunu seçerken parola tabanlı yetkilendirme kullanamazsınız.
+mirror_use_ssh.not_available = SSH yetkilendirme kullanılamıyor.
+mirror_denied_combination = Ortak anahtar ve parola tabanlı kimlik doğrulama birlikte kullanılamaz.
+n_commit_few = %s gönderi
+n_branch_one = %s dal
+n_branch_few = %s dal
+n_tag_few = %s etiket
+commits.browse_further = Daha fazlasına göz at
+commits.renamed_from = %s adından yeniden adlandırıldı
+issues.filter_no_results = Sonuç yok
+issues.filter_no_results_placeholder = Arama filtrelerini değiştirmeyi deneyin.
+issues.num_participants_one = %d katılımcı
+settings.units.units = Birimler
+settings.units.add_more = Daha fazlasını etkinleştir
+settings.wiki_globally_editable = Vikiyi herkesin düzenlemesine izin ver
+settings.default_update_style_desc = Temel dalın ardındaki çekme isteklerini güncellemek için kullanılan varsayılan güncelleme stili.
+settings.wiki_rename_branch_main = Viki dal adını normalleştir
+
[graphs]
component_loading = %s yükleniyor...
component_loading_failed = %s yüklenemedi
@@ -2736,7 +2771,7 @@ org_name_holder=Organizasyon Adı
org_full_name_holder=Organizasyon Tam Adı
org_name_helper=Organizasyon adları kısa ve hatırlanabilir olmalıdır.
create_org=Organizasyon Oluştur
-repo_updated=Güncellendi %s
+repo_updated=%s güncellendi
members=Üyeler
teams=Takımlar
code=Kod
@@ -2792,7 +2827,7 @@ members.membership_visibility=Üyelik Görünürlüğü:
members.public=Görünür
members.public_helper=gizle
members.private=Gizlenmiş
-members.private_helper=görünür yap
+members.private_helper=Görünür yap
members.member_role=Üye Rolü:
members.owner=Sahibi
members.member=Üye
@@ -3311,7 +3346,7 @@ config.git_max_diff_lines=Maksimum Değişiklik Satırı (tek bir dosya için)
config.git_max_diff_line_characters=Maksimum Değişiklik Karakteri (tek bir satır için)
config.git_max_diff_files=Maksimum Değişiklik Dosyaları (gösterilecek)
config.git_gc_args=GC Argümanları
-config.git_migrate_timeout=Göç İşlemi Zaman Aşımı
+config.git_migrate_timeout=Göç işlemi zaman aşımı
config.git_mirror_timeout=Yansı Güncelleme Zaman Aşımı
config.git_clone_timeout=Klonlama İşlemi Zaman Aşımı
config.git_pull_timeout=Çekme İşlemi Zaman Aşımı
@@ -3363,7 +3398,7 @@ monitor.queue.settings.maxnumberworkers=En fazla çalışan Sayısı
monitor.queue.settings.maxnumberworkers.placeholder=Şu anda %[1]d
monitor.queue.settings.maxnumberworkers.error=En fazla çalışan sayısı bir sayı olmalıdır
monitor.queue.settings.submit=Ayarları Güncelle
-monitor.queue.settings.changed=Ayarlar Güncellendi
+monitor.queue.settings.changed=Ayarlar güncellendi
monitor.queue.settings.remove_all_items=Tümünü kaldır
monitor.queue.settings.remove_all_items_done=Kuyruktaki tüm öğeler kaldırıldı.
@@ -3771,23 +3806,23 @@ submodule=Alt modül
[search]
-project_kind = Projeleri ara...
+project_kind = Projeleri ara…
org_kind = Organizasyonları ara…
team_kind = Takımları ara…
search = Ara…
code_kind = Kod ara…
type_tooltip = Arama türü
-repo_kind = Depoları ara...
+repo_kind = Depoları ara…
user_kind = Kullanıcıları ara…
milestone_kind = Kilometre taşlarını ara...
-branch_kind = Dalları ara...
-package_kind = Paketleri ara...
-commit_kind = Katkıları ara...
-runner_kind = Çalıştırıcıları ara...
+branch_kind = Dalları ara…
+package_kind = Paketleri ara…
+commit_kind = Katkıları ara…
+runner_kind = Çalıştırıcıları ara…
no_results = Eşleşen sonuç bulunamadı.
code_search_unavailable = Kod araması şu anda kullanıma açık değildir. Lütfen site yöneticisi ile iletişime geçin.
-issue_kind = Sorunları ara...
-pull_kind = Birleştirme isteklerini ara...
+issue_kind = Sorunları ara…
+pull_kind = Birleştirme isteklerini ara…
code_search_by_git_grep = Anlık kod araması sonuçları "git grep" komutu tarafından sağlanmaktadır. Site yöneticisinin kod endekslemesini açması durumunda daha iyi sonuçlar verilmesi mümkün olabilir.
keyword_search_unavailable = Anahtar kelime ile arama şu anda kullanıma açık değildir. Lütfen site yöneticisi ile iletişime geçin.
fuzzy_tooltip = Arama terimine yakın olan eşleşmeleri dahil et
@@ -3795,3 +3830,15 @@ union_tooltip = Boşlukla ayrılmış anahtar kelime eşleşmelerini dahil et
exact_tooltip = Sadece arama terimiyle tam uyuşan sonuçları dahit et.
fuzzy = Bulanık
exact = Tam
+union = Anahtar sözcük
+regexp = Düzenliİfade
+regexp_tooltip = Arama terimini düzenli ifade olarak yorumla
+
+[munits.data]
+b = B
+kib = KiB
+mib = MiB
+gib = GiB
+tib = TiB
+pib = PiB
+eib = EiB
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index 2e536c3d1a..2e0928bb1f 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -29,7 +29,7 @@ password=Пароль
access_token=Токен доступу
re_type=Підтвердження пароля
captcha=CAPTCHA
-twofa=Двофакторна авторизація
+twofa=Двофакторна автентифікація
twofa_scratch=Двофакторний одноразовий пароль
passcode=Код доступу
@@ -112,7 +112,7 @@ webauthn_error_unknown = Сталася невідома помилка. Буд
webauthn_error_unable_to_process = Сервер не зміг обробити запит.
webauthn_error_duplicated = Запит із наданим ключем безпеки відхилено. Впевніться, що цього ключа ще не зареєстровано.
webauthn_error_empty = Ключ слід якось назвати.
-new_project_column = Нова колонка
+new_project_column = Новий стовпчик
retry = Повторити
rerun = Перезапустити
rerun_all = Перезапустити всі завдання
@@ -149,7 +149,7 @@ filter.not_archived = Не архівовано
filter.public = Загальнодоступні
filter.private = Приватні
more_items = Більше пунктів
-remove_label_str = Видалити об'єкт «%s»
+remove_label_str = Видалити елемент «%s»
new_repo.title = Новий репозиторій
new_migrate.title = Нова міграція
new_org.title = Нова організація
@@ -195,13 +195,13 @@ buttons.list.task.tooltip = Додати список завдань
buttons.heading.tooltip = Додати заголовок
buttons.switch_to_legacy.tooltip = Використовувати застарілий редактор замість поточного
buttons.disable_monospace_font = Вимкнути моноширинний шрифт
-buttons.indent.tooltip = Вкласти предмет на один рівень
-buttons.unindent.tooltip = Викласти об'єкт на один рівень
+buttons.indent.tooltip = Вкласти елемент на один рівень
+buttons.unindent.tooltip = Викласти елемент на один рівень
buttons.mention.tooltip = Згадати користувача чи команду
-buttons.ref.tooltip = Послатись на задачу чи на запит на злиття
+buttons.ref.tooltip = Послатися на задачу чи на запит на злиття
buttons.enable_monospace_font = Увімкнути моноширинний шрифт
buttons.new_table.tooltip = Додати таблицю
-table_modal.label.columns = Стовпці
+table_modal.label.columns = Стовпчики
table_modal.header = Додати таблицю
table_modal.placeholder.header = Заголовок
table_modal.placeholder.content = Вміст
@@ -343,13 +343,13 @@ enable_update_checker = Увімкнути перевірку оновлень
require_db_desc = Forgejo вимагає MySQL, PostgreSQL, SQLite3 чи TiDB (протокол MySQL).
allow_only_external_registration = Дозволити реєстрацію тільки через зовнішні сервіси
require_sign_in_view.description = Обмежити доступ до контенту лише користувачам, що увійшли. Гості зможуть лише відвідувати сторінки автентифікації.
-password_algorithm_helper = Встановити алгоритм хешування паролів. Алгоритми мають різні вимоги та силу. Алгоритм argon2 є досить безпечним, проте споживає багато памʼяті та є недоречним для малих систем.
+password_algorithm_helper = Установіть алгоритм хешування паролів. Алгоритми мають різні вимоги і стійкість. Алгоритм argon2 є досить безпечним, проте споживає багато памʼяті та є недоречним для малих систем.
app_slogan = Гасло екземпляра
app_slogan_helper = Уведіть гасло вашого екземпляра тут. Залиште порожнім, аби вимкнути.
run_user_helper = Імʼя користувача операційної системи, від якого запущено Forgejo. Зауважте, що цей користувач повинен мати доступ до кореневої теки репозиторію.
smtp_from_invalid = Адреса з «Відправляти email від імені» недійсна
-allow_dots_in_usernames = Дозволити користувачам використовувати крапки у своїх іменах. Не впливає на облікові записи, що вже існують.
-invalid_password_algorithm = Недійсний варіант алгоритму хешування паролів
+allow_dots_in_usernames = Дозволити використання крапки в іменах користувачів. Не впливає на облікові записи, що вже існують.
+invalid_password_algorithm = Недійсний алгоритм хешування паролів
enable_update_checker_helper_forgejo = Наявність нових версій Forgejo періодично перевірятиметься через перевірку запису TXT DNS на release.forgejo.org.
[home]
@@ -392,7 +392,7 @@ user_no_results=Відповідних користувачів не знайд
org_no_results=Відповідних організацій не знайдено.
code_no_results=Відповідний пошуковому запитанню код не знайдено.
code_last_indexed_at=Останні індексовані %s
-relevant_repositories = Відображаються лише релевантні репозиторії, переглянути результати без фільтру.
+relevant_repositories = Показано лише релевантні репозиторії, переглянути результати без фільтру.
relevant_repositories_tooltip = Приховано форки, а також репозиторії без теми, значка й опису.
go_to = Перейти до
stars_one = %d зірка
@@ -469,7 +469,7 @@ invalid_code_forgot_password = Ваш код підтвердження неді
reset_password_wrong_user = Ви ввійшли як %s, але посилання на відновлення було передбачене для %s
back_to_sign_in = Назад до входу
sign_in_openid = Продовжити з OpenID
-openid_signin_desc = Введіть ваше посилання OpenID. Наприклад: alice.openid.example.org чи https://openid.example.org/alice.
+openid_signin_desc = Уведіть свій OpenID URI. Наприклад: alice.openid.example.org чи https://openid.example.org/alice.
invalid_password = Ваш пароль не відповідає тому, що був заданий при створенні облікового запису.
hint_login = Вже маєте обліковий запис? Увійдіть зараз!
hint_register = Потрібен обліковий запис? Зареєструйтеся зараз.
@@ -694,7 +694,7 @@ disabled_public_activity=Цей користувач вимкнув публіч
joined_on = Реєстрація %s
email_visibility.private = Ваш email видно лише вам і адміністраторам
email_visibility.limited = Вашу е-пошту видно всім авторизованим
-settings = Користувацькі параметри
+settings = Користувацькі налаштування
block_user.detail_3 = Ви не зможете додати один одного в якості співавтора репозиторію.
show_on_map = Показати це місце на мапі
block_user.detail_2 = Цей користувач не зможе взаємодіяти з репозиторіями, власником яких є ви, а також із задачами та коментарями, які ви створили.
@@ -734,7 +734,7 @@ applications=Додатки
orgs=Організації
repos=Репозиторії
delete=Видалити обліковий запис
-twofa=Двофакторна авторизація (TOTP)
+twofa=Двофакторна автентифікація (TOTP)
account_link=Прив'язані облікові записи
organization=Організації
@@ -813,9 +813,9 @@ manage_ssh_keys=Керування ключами SSH
manage_ssh_principals=Управління SSH сертифікатами користувачів
manage_gpg_keys=Керування ключами GPG
add_key=Додати ключ
-ssh_desc=Ці відкриті ключі SSH повʼязані з вашим обліковим записом. Відповідні приватні ключі дозволяють отримати повний доступ до ваших репозиторіїв. Підтверджені ключі можна використати для підтвердження комітів Git, підписані з SSH.
+ssh_desc=Ці відкриті ключі SSH повʼязані з вашим обліковим записом. Відповідні приватні ключі дозволяють отримати повний доступ до ваших репозиторіїв. Підтверджені ключі можна використати для підтвердження комітів Git, підписаних із SSH.
principal_desc=Ці настройки SSH сертифікатів вказані у вашому обліковому записі та надають повний доступ до ваших репозиторіїв.
-gpg_desc=Ці публічні ключі GPG пов'язані з вашим обліковим записом. Тримайте свої приватні ключі в безпеці, оскільки вони дозволяють здійснювати перевірку комітів.
+gpg_desc=Ці публічні ключі GPG пов'язані з вашим обліковим записом і використовуються для підтвердження комітів. Тримайте свої приватні ключі в безпеці, оскільки вони дозволяють підписувати коміти вашим особистим підписом.
ssh_helper=Потрібна допомога? Дивіться гід на GitHub з генерації ключів SSH або виправлення типових неполадок SSH.
gpg_helper= Потрібна допомога? Перегляньте посібник GitHub про GPG .
add_new_key=Додати SSH ключ
@@ -893,7 +893,7 @@ manage_oauth2_applications=Керування програмами OAuth2
edit_oauth2_application=Редагувати програму OAuth2
oauth2_applications_desc=Програми OAuth2 дають можливість вашим стороннім програмам надійно аутентифікувати користувачів у цьому екземплярі Forgejo.
remove_oauth2_application=Видалити програму OAuth2
-remove_oauth2_application_desc=Видалення програми OAuth2 скасовує доступ до всіх підписаних маркерів доступу. Продовжити?
+remove_oauth2_application_desc=Видалення програми OAuth2 скасує доступ до всіх підписаних токенів доступу. Продовжити?
remove_oauth2_application_success=Програму видалено.
create_oauth2_application=Створити новий додаток OAuth2
create_oauth2_application_button=Створити програму
@@ -1077,6 +1077,9 @@ regenerate_token = Згенерувати знову
access_token_regeneration = Згенерувати новий токен доступу
quota.sizes.assets.all = Ресурси
+access_token_regeneration_desc = Регенерація токена скасує доступ програм, які використовують цей токен, до вашого облікового запису. Це незворотна дія. Продовжити?
+regenerate_token_success = Токен згенеровано наново. Програми, які його використовують, більше не мають доступу до вашого облікового запису; ви повинні відновити доступ за допомогою нового токена.
+
[repo]
owner=Власник
owner_helper=Деякі організації можуть не відображатися у випадаючому списку через максимальну кількість репозиторііїв.
@@ -1143,7 +1146,7 @@ forks=Форки
reactions_more=додати %d більше
unit_disabled=Адміністратор сайту вимкнув цей розділ репозиторію.
language_other=Інші
-adopt_search=Введіть ім'я користувач_ки для пошуку неприйнятих репозиторіїв… (залиште порожнім, щоб знайти всі)
+adopt_search=Уведіть ім'я користувач_ки для пошуку неприйнятих репозиторіїв… (залиште порожнім, щоб знайти всі)
adopt_preexisting_label=Прийняті файли
adopt_preexisting=Прийняти вже існуючі файли
adopt_preexisting_content=Створити репозиторій з %s
@@ -1168,7 +1171,7 @@ desc.archived=Архівний
template.items=Елементи шаблону
template.git_content=Вміст Git (типова гілка)
-template.git_hooks=Перехоплювачі Git
+template.git_hooks=Git-хуки
template.webhooks=Webhook'и
template.topics=Теми
template.avatar=Аватар
@@ -1276,7 +1279,7 @@ file_raw=Неформатований
file_history=Історія
file_view_source=Переглянути вихідний код
file_view_rendered=Переглянути відрендерено
-file_view_raw=Перегляд Raw
+file_view_raw=Переглянути неформатований
file_permalink=Постійне посилання
file_too_large=Цей файл завеликий щоб бути показаним.
@@ -1285,7 +1288,7 @@ video_not_supported_in_browser=Ваш браузер не підтримує т
audio_not_supported_in_browser=Ваш браузер не підтримує тег HTML5 «audio».
stored_lfs=Збережено з Git LFS
symbolic_link=Символічне посилання
-commit_graph=Графік комітів
+commit_graph=Граф комітів
commit_graph.select=Виберіть гілки
commit_graph.hide_pr_refs=Приховати запити на злиття
commit_graph.monochrome=Монохром
@@ -1402,9 +1405,9 @@ issues.new.open_projects=Відкриті проєкти
issues.new.closed_projects=Закриті проєкти
issues.new.no_items=Немає елементів
issues.new.milestone=Етап
-issues.new.no_milestone=Етап відсутній
+issues.new.no_milestone=Немає етапу
issues.new.clear_milestone=Очистити етап
-issues.new.open_milestone=Активні етапи
+issues.new.open_milestone=Відкриті етапи
issues.new.closed_milestone=Закриті етапи
issues.new.assignees=Виконавці
issues.new.clear_assignees=Прибрати виконавців
@@ -1447,7 +1450,7 @@ issues.remove_ref_at=`видалив посилання %s %s`
issues.add_ref_at=`додав посилання %s %s`
issues.delete_branch_at=`видалена гілка %s %s`
issues.filter_label=Мітка
-issues.filter_label_exclude=`Використовуйте Alt
+ клік/Enter
для виключення міток`
+issues.filter_label_exclude=Використовуйте Alt + клік для виключення міток
issues.filter_label_no_select=Всі мітки
issues.filter_milestone=Етап
issues.filter_project=Проєкт
@@ -1496,17 +1499,17 @@ issues.context.quote_reply=Цитувати відповідь
issues.context.reference_issue=Послатися в новій задачі
issues.context.edit=Редагувати
issues.context.delete=Видалити
-issues.close_comment_issue=Прокоментувати і закрити
+issues.close_comment_issue=Закрити з коментарем
issues.reopen_issue=Відкрити знову
-issues.reopen_comment_issue=Прокоментувати та відкрити знову
+issues.reopen_comment_issue=Відкрити знову з коментарем
issues.create_comment=Коментар
-issues.closed_at=`закрив цю задачу %[2]s`
-issues.reopened_at=`повторно відкрив цю задачу %[2]s`
-issues.commit_ref_at=`згадано цю задачу в коміті %[2]s`
-issues.ref_issue_from=`посилається на цю задачу %[4]s %[2]s`
-issues.ref_pull_from=`послався на цей запит злиття %[4]s %[2]s`
-issues.ref_closing_from=`згадав запит на злиття %[4]s, які закриють цю задачу %[2]s`
-issues.ref_reopening_from=`згадав запит на злиття %[4]s, які повторно відкриють цю задачу %[2]s`
+issues.closed_at=`закриває цю задачу %s`
+issues.reopened_at=`повторно відкриває цю задачу %s`
+issues.commit_ref_at=`посилається на цю задачу в коміті %s`
+issues.ref_issue_from=`посилається на цю задачу %[3]s %[1]s`
+issues.ref_pull_from=`посилається на цей запит на злиття %[3]s %[1]s`
+issues.ref_closing_from=`посилається в запиті на злиття %[3]s, який закриє цю задачу, %[1]s`
+issues.ref_reopening_from=`посилається в запиті на злиття %[3]s, який повторно відкриє цю задачу, %[1]s`
issues.ref_closed_from=`закрив цю задачу %[4]s %[2]s`
issues.ref_reopened_from=`повторно відкрито цю задачу %[4]s %[2]s`
issues.ref_from=`із %[1]s`
@@ -1707,7 +1710,7 @@ pulls.reject_count_1=%d запит на зміну
pulls.reject_count_n=%d запити на зміну
pulls.waiting_count_1=очікується %d рецензія
pulls.waiting_count_n=очікується %d рецензії(й)
-pulls.wrong_commit_id=ID коміта повинен бути ID коміта в цільовій гілці
+pulls.wrong_commit_id=ID коміту повинен бути ID коміту в цільовій гілці
pulls.no_merge_desc=Цей запити на злиття неможливо злити, оскільки всі параметри об'єднання репозиторія вимкнено.
pulls.no_merge_helper=Увімкніть параметри злиття в налаштуваннях репозиторія або злийте запити на злиття вручну.
@@ -1725,7 +1728,7 @@ pulls.require_signed_wont_sign=Гілка вимагає підписаних к
pulls.invalid_merge_option=Цей параметр злиття не можна використовувати для цього Pull Request'а.
pulls.merge_conflict=Не вдалося об'єднати: при об'єднанні виник конфлікт. Підказка: спробуйте іншу стратегію
pulls.merge_conflict_summary=Повідомлення про помилку
-pulls.rebase_conflict=Не вдалося об'єднати: виник конфлікт під час перебазування коміта: %[1]s. Підказка: спробуйте іншу стратегію
+pulls.rebase_conflict=Не вдалося об'єднати: виник конфлікт під час перебазування коміту: %[1]s. Підказка: спробуйте іншу стратегію
pulls.rebase_conflict_summary=Повідомлення про помилку
pulls.unrelated_histories=Не вдалося об'єднати: head та base злиття не мають спільної історії. Підказка: спробуйте іншу стратегію
pulls.merge_out_of_date=Не вдалося об'єднати: base було оновлено, поки відбувалося об'єднання. Підказка: спробуйте знову.
@@ -1743,8 +1746,8 @@ pulls.update_branch_rebase=Оновити гілку перебазування
pulls.update_branch_success=Оновлення гілки пройшло успішно
pulls.update_not_allowed=Ви не можете оновити гілку
pulls.outdated_with_base_branch=Ця гілка застаріла відносно базової гілки
-pulls.closed_at=`закрив цей запит на злиття %[2]s`
-pulls.reopened_at=`повторно відкрив цей запит на злиття %[2]s`
+pulls.closed_at=`закриває цей запит на злиття %s`
+pulls.reopened_at=`повторно відкриває цей запит на злиття %s`
@@ -1799,7 +1802,7 @@ wiki.delete_page_button=Видалити сторінку
wiki.page_already_exists=Вікі-сторінка з таким самим ім'ям вже існує.
wiki.pages=Сторінки
wiki.last_updated=Останні оновлення %s
-wiki.page_name_desc=Введіть назву вікі-сторінки. Деякі зі спеціальних імен: «Home», «_Sidebar» та «_Footer».
+wiki.page_name_desc=Уведіть назву вікі-сторінки. Деякі зі спеціальних імен: «Home», «_Sidebar» та «_Footer».
activity=Активність
activity.period.filter_label=Період:
@@ -1844,7 +1847,7 @@ activity.unresolved_conv_label=Відкрити
activity.title.releases_1=%d випуск
activity.title.releases_n=%d випусків
activity.title.releases_published_by=%s опубліковано %s
-activity.published_release_label=Опубліковано
+activity.published_release_label=Випуск
activity.no_git_activity=У цей період не було здійснено жодних дій.
activity.git_stats_exclude_merges=Не враховуючи злиття,
activity.git_stats_author_1=%d автор
@@ -1886,17 +1889,17 @@ settings.collaboration.read=Читати
settings.collaboration.owner=Власник
settings.collaboration.undefined=Не визначено
settings.hooks=Веб-хуки
-settings.githooks=Git хуки
-settings.basic_settings=Базові налаштування
+settings.githooks=Git-хуки
+settings.basic_settings=Основні налаштування
settings.mirror_settings=Налаштування дзеркала
settings.mirror_settings.mirrored_repository=Віддзеркалений репозиторій
settings.mirror_settings.direction=Напрямок
settings.mirror_settings.direction.pull=Pull
settings.mirror_settings.direction.push=Push
settings.mirror_settings.last_update=Останнє оновлення
-settings.mirror_settings.push_mirror.none=Не налаштовано дзеркало push
+settings.mirror_settings.push_mirror.none=Push-дзеркала не налаштовано
settings.mirror_settings.push_mirror.remote_url=URL віддаленого репозиторію Git
-settings.mirror_settings.push_mirror.add=Додати Push дзеркало
+settings.mirror_settings.push_mirror.add=Додати push-дзеркало
settings.sync_mirror=Синхронізувати зараз
settings.site=Веб-сайт
@@ -1927,9 +1930,9 @@ settings.pulls_desc=Увімкнути запити на злиття в реп
settings.pulls.ignore_whitespace=Ігнорувати пробіл у конфліктах
settings.pulls.enable_autodetect_manual_merge=Увімкнути автовизначення ручного злиття (Примітка: у деяких особливий випадках можуть виникнуть помилки)
settings.pulls.default_delete_branch_after_merge=Видаляти гілку запиту злиття, коли його прийнято
-settings.projects_desc=Увімкнути проєкти у репозиторії
+settings.projects_desc=Увімкнути проєкти в репозиторії
settings.admin_settings=Налаштування адміністратора
-settings.admin_enable_health_check=Включити перевірки працездатності репозиторію (git fsck)
+settings.admin_enable_health_check=Увімкнути перевірки стану репозиторію (git fsck)
settings.admin_enable_close_issues_via_commit_in_any_branch=Закрити задачу за допомогою коміта, зробленого не в головній гілці
settings.danger_zone=Небезпечна зона
settings.new_owner_has_same_repo=Новий власник вже має репозиторій з такою назвою. Будь ласка, виберіть інше ім'я.
@@ -2055,12 +2058,12 @@ settings.event_issue_assign=Призначення
settings.event_issue_assign_desc=Задачу призначено або скасовано.
settings.event_issue_label=Мітки
settings.event_issue_label_desc=Додавання або видалення міток задач.
-settings.event_issue_milestone=Задача з етапом
+settings.event_issue_milestone=Етапи
settings.event_issue_milestone_desc=Етап призначено, видалено або змінено.
settings.event_issue_comment=Коментарі
settings.event_issue_comment_desc=Коментар задачі створено, видалено чи відредаговано.
settings.event_header_pull_request=Події запиту на злиття
-settings.event_pull_request=Запити до злиття
+settings.event_pull_request=Зміна
settings.event_pull_request_desc=Запит до злиття відкрито, закрито, перевідкрито або відредаговано.
settings.event_pull_request_assign=Призначення
settings.event_pull_request_assign_desc=Запит про злиття призначено або скасовано.
@@ -2075,7 +2078,7 @@ settings.event_pull_request_review_desc=Запит на злиття схвал
settings.event_pull_request_sync=Синхронізовано
settings.event_pull_request_sync_desc=Гілку автоматично оновлено цільовою гілкою.
settings.branch_filter=Фільтр гілок
-settings.branch_filter_desc=Білий список гілок для push, створення гілок та видалення гілок, визначається як шаблон glob. Якщо він порожній або містить *
, то реєструються події для всіх гілок. Дивіться синтаксис у документації на %[2]s. Наприклад: master
, {master,release*}
.
+settings.branch_filter_desc=Білий список гілок для push, створення гілок та видалення гілок, визначається як шаблон glob. Якщо він порожній або містить *
, то реєструються події для всіх гілок. Дивіться синтаксис у документації %[2]s. Приклади: master
, {master,release*}
.
settings.active=Активний
settings.active_helper=Інформацію про викликані події буде надіслано за цією веб-хук URL-адресою.
settings.add_hook_success=Веб-хук було додано.
@@ -2154,7 +2157,7 @@ settings.edit_protected_branch=Редагувати
settings.protected_branch_required_approvals_min=Число необхідних схвалень не може бути від'ємним.
settings.tags=Теги
settings.tags.protection=Захист тегу
-settings.tags.protection.pattern=Шаблон тега
+settings.tags.protection.pattern=Шаблон тегів
settings.tags.protection.allowed=Дозволено
settings.tags.protection.allowed.users=Дозволені користувачі
settings.tags.protection.allowed.teams=Дозволені команди
@@ -2263,7 +2266,7 @@ release.detail=Деталі релізу
release.tags=Теги
release.new_release=Новий випуск
release.draft=Чернетка
-release.prerelease=Пре-реліз
+release.prerelease=Попередній випуск
release.stable=Стабільний
release.compare=Порівняти
release.edit=Редагувати
@@ -2275,15 +2278,15 @@ release.edit_subheader=Публікація релізів допоможе ва
release.tag_name=Назва тегу
release.target=Ціль
release.tag_helper=Виберіть існуючий тег або створіть новий.
-release.prerelease_desc=Позначити як пре-реліз
+release.prerelease_desc=Позначити як попередній випуск
release.prerelease_helper=Позначте цей випуск непридатним для ПРОД використання.
release.cancel=Відмінити
-release.publish=Опублікувати реліз
+release.publish=Опублікувати випуск
release.save_draft=Зберегти чернетку
-release.edit_release=Оновити реліз
-release.delete_release=Видалити реліз
+release.edit_release=Оновити випуск
+release.delete_release=Видалити випуск
release.delete_tag=Видалити тег
-release.deletion=Видалити реліз
+release.deletion=Видалити випуск
release.deletion_success=Реліз, було видалено.
release.deletion_tag_desc=Буде видалено цей тег із репозиторію. Вміст репозиторія та історія залишаться незмінними. Продовжити?
release.deletion_tag_success=Тег видалено.
@@ -2341,7 +2344,7 @@ issues.author = Автор
issues.author_helper = Цей користувач - автор.
issues.close = Закрити задачу
issues.role.owner_helper = Цей користувач є власником цього репозиторію.
-settings.mirror_settings.docs.more_information_if_disabled = Докладніше про push та pull дзеркала можна дізнатися тут:
+settings.mirror_settings.docs.more_information_if_disabled = Докладніше про push- та pull-дзеркала можна дізнатися тут:
issues.comment.blocked_by_user = Ви не можете коментувати цю задачу, оскільки вас заблокував власник репозиторію або автор цієї задачі.
editor.add_file = Додати файл
from_comment = (коментар)
@@ -2429,7 +2432,7 @@ pulls.is_ancestor = Цю гілку вже включено в цільову г
pulls.has_merged = Помилка: запит на злиття вже об'єднано, неможливо об'єднати знову чи змінити цільову гілку.
pulls.head_out_of_date = Не вдалося об'єднати: head було оновлено, поки відбувалося об'єднання. Підказка: спробуйте знову.
no_eol.tooltip = У цьому файлі відсутній символ закінчення рядка (EOL) у кінці.
-settings.trust_model.committer.desc = Допустимі підписи будуть позначатися як «довірені», тільки якщо вони відповідають автору коміта, в іншому випадку вони позначатимуться як «невідповідні». Це змусить Forgejo бути автором підписаних комітів, а фактичного автора зазначати в трейлерах «Co-authored-by» і «Co-committed-by» в описі коміта. Типовий ключ Forgejo повинен відповідати користувачу в базі даних.
+settings.trust_model.committer.desc = Допустимі підписи будуть позначатися як «довірені», тільки якщо вони відповідають авторові коміту, в іншому випадку вони позначатимуться як «невідповідні». Це змусить Forgejo бути автором підписаних комітів, а фактичного автора зазначати в трейлерах «Co-authored-by» і «Co-committed-by» в описі коміту. Типовий ключ Forgejo повинен відповідати користувачу в базі даних.
pulls.clear_merge_message_hint = Очищення повідомлення про об'єднання видалить лише вміст повідомлення коміту і збереже згенеровані git-трейлери, такі як «Co-Authored-By…».
branch.delete_branch_has_new_commits = Гілку «%s» не можна видалити, оскільки після об'єднання було додано нові коміти.
settings.graphql_url = Посилання GraphQL
@@ -2446,7 +2449,7 @@ settings.event_package = Пакунок
settings.event_package_desc = Пакунок у репозиторії створено або видалено.
settings.new_owner_blocked_doer = Новий власник заблокував вас.
settings.transfer_quota_exceeded = Новий власник (%s) перевищив квоту. Репозиторій не передано.
-release.title_empty = Заголовок не може бути порожнім.
+release.title_empty = Назва не може бути порожньою.
issues.role.member_helper = Цей користувач є членом організації, що володіє цим репозиторієм.
wiki.page_content = Вміст сторінки
wiki.page_title = Заголовок сторінки
@@ -2485,7 +2488,7 @@ signing.will_sign = Коміт буде підписано ключем «%s».
signing.wont_sign.error = Під час перевірки можливості підписати коміт сталася помилка.
commits.search_branch = У цій гілці
ext_wiki = Зовнішня вікі
-pulls.commit_ref_at = `посилається на цей запит на злиття в коміті %[2]s`
+pulls.commit_ref_at = `посилається на цей запит на злиття в коміті %s`
pulls.cmd_instruction_hint = Переглянути інструкції для командного рядка
issues.max_pinned = Неможливо закріпити більше задач
issues.unpin_comment = відкріпив %s
@@ -2512,7 +2515,7 @@ projects.column.set_default = Установити за замовчування
settings.federation_following_repos = URL-адреси відстежуваних репозиторіїв. Через «;», без пробілів.
settings.federation_not_enabled = Федерацію вимкнено у вашому екземплярі.
settings.federation_settings = Налаштування федерації
-signing.wont_sign.nokey = Цей екземпляр не має ключа для підписання цього коміта.
+signing.wont_sign.nokey = Цей екземпляр не має ключа для підписання цього коміту.
settings.federation_apapiurl = URL федерації цього репозиторію. Скопіюйте її та вставте в налаштування федерації іншого репозиторію як URL-адресу відстежуваного репозиторію.
fork_branch = Гілка, яку буде клоновано у форк
already_forked = Ви вже створили форк %s
@@ -2530,7 +2533,7 @@ settings.add_web_hook_desc = Інтегрувати Увійдіть, щоб створити новий запит на злиття.
@@ -2541,8 +2544,8 @@ auto_init_description = Почніть історію Git з README і за ба
new_from_template_description = Можете вибрати наявний шаблон репозиторію на цьому екземплярі і застосувати його налаштування.
form.string_too_long = Довжина введеного рядка більша за %d символів.
form.name_reserved = Назву репозиторію «%s» зарезервовано.
-form.name_pattern_not_allowed = Шаблон «%s» не допускається у назві репозиторію.
-settings.wiki_rename_branch_main_desc = Перейменувати внутрішню гілку, яка використовується у вікі, на «%s». Ця зміна є остаточною і її неможливо скасувати.
+form.name_pattern_not_allowed = Вираз «%s» не може бути частиною назви репозиторію.
+settings.wiki_rename_branch_main_desc = Перейменувати внутрішню гілку, яка використовується для вікі, на «%s». Ця зміна є остаточною і її неможливо скасувати.
wiki.reserved_page = Назву вікі-сторінки «%s» зарезервовано.
stars = Зірки
mirror_public_key = Відкритий SSH-ключ
@@ -2552,7 +2555,7 @@ activity.navbar.pulse = Пульс
open_with_editor = Відкрити в %s
commits.view_single_diff = Переглянути зміни до цього файлу, внесені у цьому коміті
pulls.editable = Редаговане
-pulls.editable_explanation = Цей запит на злиття дозволяє редагування від розробників. Ви можете зробити свій внесок безпосередньо до нього.
+pulls.editable_explanation = Цей запит на злиття дозволено редагувати супроводжувачам. Ви можете зробити свій внесок безпосередньо до нього.
admin.failed_to_replace_flags = Не вдалося замінити прапорці репозиторія
admin.enabled_flags = Для репозиторія ввімкнено прапорці:
admin.flags_replaced = Прапорці репозиторія замінено
@@ -2670,6 +2673,163 @@ commitstatus.success = Успіх
commitstatus.failure = Збій
issues.filter_type.all_pull_requests = Усі запити на злиття
+summary_card_alt = Підсумкова картка репозиторію %s
+migrate_options_lfs_endpoint.placeholder = Якщо залишити порожнім, то кінцеву точку буде визначено з URL-адреси клону
+migrate.invalid_local_path = Локальний шлях недійсний. Він не існує або не є каталогом.
+subscribe.issue.guest.tooltip = Увійдіть, щоб підписатися на цю задачу.
+subscribe.pull.guest.tooltip = Увійдіть, щоб підписатися на цей запит на злиття.
+cite_this_repo = Послатися на цей репозиторій
+broken_message = Неможливо прочитати дані Git, що лежать в основі цього репозиторію. Зверніться до адміністратора цього екземпляра або видаліть репозиторій.
+invisible_runes_header = `Цей файл містить невидимі символи Юнікоду`
+invisible_runes_description = `Цей файл містить невидимі символи Юнікоду, які людині неможливо розрізнити, але які по-різному обробляються комп'ютером. Якщо так зроблено навмисно, можете ігнорувати це попередження. Щоб показати ці символи, скористайтеся кнопкою «Escape».`
+ambiguous_runes_header = `Цей файл містить неоднозначні символи Юнікоду`
+ambiguous_runes_description = `Цей файл містить символи Юнікоду, які легко сплутати з іншими символами. Якщо так зроблено навмисно, можете ігнорувати це попередження. Щоб показати ці символи, скористайтеся кнопкою «Escape».`
+invisible_runes_line = `У цьому рядку є невидимі символи Юнікоду`
+ambiguous_runes_line = `У цьому рядку є неоднозначні символи Юнікоду`
+ambiguous_character = `%[1]c [U+%04[1]X] можна сплутати з %[2]c [U+%04[2]X]`
+escape_control_characters = Escape
+unescape_control_characters = Unescape
+no_eol.text = Без EOL
+editor.filename_is_invalid = Хибна назва файлу: «%s».
+editor.directory_is_a_file = Назва каталогу «%s» уже використовується в цьому репозиторії як назва файлу.
+editor.filename_is_a_directory = Назва файлу «%s» уже використовується в цьому репозиторії як назва каталогу.
+issues.choose.invalid_config = У конфігурації задачі є помилки:
+issues.summary_card_alt = Підсумкова картка задачі «%s» в репозиторії %s
+settings.sourcehut_builds.secrets_helper = Надати завданню доступ до секретів збірки (потрібен дозвіл SECRETS:RO)
+settings.remove_protected_branch_failed = Не вдалося видалити правило захисту гілок «%s».
+release.summary_card_alt = Підсумкова картка випуску «%s» в репозиторії %s
+
+view_git_blame = Переглянути git blame
+vendored = Сторонній
+editor.file_editing_no_longer_exists = Файл «%s», який ви редагуєте, більше не існує у цьому репозиторії.
+editor.file_deleting_no_longer_exists = Файл «%s», який ви видаляєте, більше не існує у цьому репозиторії.
+editor.file_already_exists = Файл із назвою «%s» вже є у цьому репозиторії.
+editor.push_rejected_no_message = Зміну відхилено сервером без повідомлення. Будь ласка, перевірте Git-хуки.
+editor.push_rejected = Зміну відхилено сервером. Будь ласка, перевірте Git-хуки.
+editor.unable_to_upload_files = Не вдалося завантажити файли в «%s» через помилку: %v
+editor.upload_files_to_dir = Завантажити файли в «%s»
+editor.cannot_commit_to_protected_branch = Неможливо здійснити коміт до захищеної гілки «%s».
+commits.renamed_from = Перейменовано з %s
+commits.ssh_key_fingerprint = Відбиток ключа SSH
+commits.view_path = Переглянути на цьому етапі історії
+issues.filter_sort.relevance = За відповідністю
+issues.action_check = Поставити/зняти позначку
+issues.action_check_all = Поставити/зняти позначку з усіх елементів
+issues.closed_by = від %[3]s закрито %[1]s
+issues.closed_by_fake = від %[2]s закрито %[1]s
+issues.label_archived_filter = Показати архівовані мітки
+pulls.allow_edits_from_maintainers_err = Не вдалося оновити
+pulls.has_viewed_file = Переглянуто
+pulls.viewed_files_label = %[1]d з %[2]d файлів переглянуто
+pulls.status_checks_hide_all = Приховати всі перевірки
+milestones.new_subheader = Етапи допомагають організувати задачі та відстежувати прогрес їх виконання.
+milestones.filter_sort.name = За назвою
+wiki.delete_page_notice_1 = Видалення вікі-сторінки «%s» неможливо скасувати. Продовжити?
+activity.published_prerelease_label = Пре-реліз
+settings.mirror_settings.docs.doc_link_pull_section = розділ документації «Отримання з віддаленого репозиторію».
+settings.mirror_settings.docs.pulling_remote_title = Отримання з віддаленого репозиторію
+settings.mirror_settings.push_mirror.edit_sync_time = Змінити інтервал синхронізації дзеркала
+settings.mirror_settings.push_mirror.none_ssh = Немає
+settings.pull_mirror_sync_in_progress = Триває отримання змін з віддаленого репозиторію %s.
+settings.pull_mirror_sync_quota_exceeded = Перевищено квоту, отримання змін неможливе.
+settings.push_mirror_sync_in_progress = Триває надсилання змін до віддаленого репозиторію %s.
+settings.pulls.allow_rebase_update = Увімкнути оновлення гілки запиту на злиття за допомогою перебазування
+settings.releases_desc = Увімкнути випуски в репозиторії
+settings.admin_code_indexer = Індексатор коду
+settings.admin_stats_indexer = Індексатор статистики коду
+settings.admin_indexer_commit_sha = Останній індексований коміт
+settings.admin_indexer_unindexed = Не індексовано
+settings.enter_repo_name = Уведіть ім'я власника і назву репозиторію, як показано:
+settings.wiki_rename_branch_main = Нормалізувати назву вікі-гілки
+settings.wiki_rename_branch_main_notices_1 = Цю операцію НЕМОЖЛИВО скасувати.
+settings.wiki_rename_branch_main_notices_2 = Внутрішню вікі-гілку репозиторію %s буде назавжди перейменовано. Існуючі перевірки потрібно буде оновити.
+settings.wiki_branch_rename_success = Назву вікі-гілки репозиторію успішно нормалізовано.
+settings.wiki_branch_rename_failure = Не вдалося нормалізувати назву вікі-гілки репозиторію.
+settings.add_webhook.invalid_path = Шлях не повинен містити частини «.» або «..» і не повинен бути порожнім. Він не може починатися або закінчуватися косою рискою.
+settings.discord_icon_url.exceeds_max_length = URL-адреса значка не може бути довшою, ніж 2048 символи
+settings.web_hook_name_telegram = Telegram
+settings.sourcehut_builds.manifest_path = Шлях до маніфесту збірки
+settings.sourcehut_builds.visibility = Видимість завдань
+settings.sourcehut_builds.access_token_helper = Токен доступу, який має дозвіл JOBS:RW. Згенеруйте токен builds.sr.ht або токен builds.sr.ht з доступом до секретів на meta.sr.ht.
+settings.protect_status_check_patterns_desc = Уведіть шаблони, щоб вказати, які перевірки стану повинні пройти гілки, перш ніж їх буде об'єднано у гілку, що відповідає цьому правилу. Кожен рядок визначає шаблон. Шаблони не можуть бути порожніми.
+settings.protect_invalid_status_check_pattern = Недійсний шаблон перевірки стану: «%s».
+settings.protect_no_valid_status_check_patterns = Немає дійсних шаблонів перевірки стану.
+settings.protect_patterns = Шаблони
+settings.protected_branch_duplicate_rule_name = Для цього набору гілок уже є правило
+settings.thread_id = Thread ID
+settings.matrix.access_token_helper = Рекомендується створити окремий обліковий запис Matrix. Токен доступу можна отримати у вебклієнті Element (у приватній/інкогніто вкладці): User menu (вгорі ліворуч) > All settings > Help & About > Advanced > Access Token (під URL-адресою Homeserver). Закрийте приватну вкладку (вихід із системи зробить токен недійсним).
+settings.matrix.room_id_helper = ID кімнати можна отримати у вебклієнті Element: Room Settings > Advanced > Internal room ID. Приклад: %s.
+settings.unarchive.header = Розархівувати цей репозиторій
+settings.unarchive.text = Розархівування репозиторію відновить можливість надсилати до нього коміти і виконувати push, а також створювати задачі і запити на злиття.
+settings.unarchive.success = Репозиторій успішно розархівовано.
+settings.unarchive.error = Сталася помилка при спробі розархівувати репозиторій. Докладнішу інформацію див. у журналі.
+diff.git-notes.remove-body = Цю примітку буде видалено.
+diff.has_escaped = У цьому рядку є приховані символи Юнікоду
+diff.show_file_tree = Показати дерево файлів
+diff.hide_file_tree = Приховати дерево файлів
+tag.ahead.target = до %s після цього тегу
+release.title = Назва випуску
+release.deletion_desc = Видалення випуску видаляє його лише з Forgejo. При цьому тег Git, вміст репозиторію чи його історію не буде змінено. Продовжити?
+release.hide_archive_links = Приховати автоматично генеровані архіви
+release.hide_archive_links_helper = Приховати для цього випуску архіви вихідного коду, що генеруються автоматично. Наприклад, якщо ви завантажуєте свої архіви.
+release.system_generated = Це вкладення згенеровано автоматично.
+branch.delete_desc = Видалення гілки є остаточним. Хоча видалена гілка може існувати ще деякий час до того, як її буде видалено, цю дію НЕМОЖЛИВО скасувати в більшості випадків. Продовжити?
+branch.branch_name_conflict = Назва гілки «%s» конфліктує з наявною гілкою «%s».
+branch.tag_collision = Неможливо створити гілку «%s», оскільки у репозиторії вже є тег із такою назвою.
+
+blame.ignore_revs = Зміни в .git-blame-ignore-revs ігноруються. Натисніть тут, щоб обійти це і переглянути авторство у звичайному вигляді.
+blame.ignore_revs.failed = Не вдалося проігнорувати зміни в .git-blame-ignore-revs.
+template.git_hooks_tooltip = Наразі ви не можете змінювати або видаляти додані Git-хуки. Вибирайте лише якщо ви довіряєте репозиторію шаблону.
+migrate.github_token_desc = Ви можете ввести тут один або кілька токенів через кому, щоб пришвидшити міграцію в обхід обмеження частоти звернень до API GitHub. ОБЕРЕЖНО: зловживання цією функцією може порушити політику постачальника послуг і призвести до блокування облікового запису.
+migrate.github.description = Перенесіть дані з github.com або сервера GitHub Enterprise.
+migrate.cancel_migrating_confirm = Бажаєте скасувати перенесення?
+editor.new_branch_name = Укажіть назву нової гілки для цього коміту
+projects.column.edit = Редагувати стовпчик
+projects.column.new_submit = Створити стовпчик
+projects.column.new = Новий стовпчик
+projects.column.set_default_desc = Призначити цей стовпчик за замовчуванням для задач і запитів на злиття без категорії
+projects.column.delete = Видалити стовпчик
+projects.column.deletion_desc = Видалення стовпчика проєкту призведе до переміщення всіх пов'язаних із ним задач до стовпчика за замовчуванням. Продовжити?
+issues.edit.already_changed = Не вдається зберегти зміни. Схоже, що хтось інший уже змінив вміст задачі. Оновіть сторінку і спробуйте відредагувати ще раз, щоб уникнути перезапису чужих змін
+issues.label_templates.fail_to_load_file = Не вдалося завантажити файл шаблону міток «%s»: %v
+issues.reaction.add = Додати реакцію
+issues.reaction.alt_many = %[1]s і ще %[2]d реагують %[3]s.
+issues.reaction.alt_remove = Прибрати реакцію %[1] з коментаря.
+issues.reaction.alt_add = Додати реакцію %[1]s до коментаря.
+issues.archived_label_description = (Архівна) %s
+issues.delete.text = Ви дійсно хочете видалити цю задачу? (Весь її вміст буде остаточно видалено. Можливо, варто її закрити і зберегти в архіві)
+pulls.edit.already_changed = Не вдається зберегти зміни. Схоже, що хтось інший уже змінив вміст запиту на злиття. Оновіть сторінку і спробуйте відредагувати ще раз, щоб уникнути перезапису чужих змін
+pulls.allow_edits_from_maintainers = Дозволити редагування від супроводжувачів
+pulls.showing_only_single_commit = Показано тільки зміни коміту %[1]s
+pulls.showing_specified_commit_range = Показано тільки зміни між %[1]s..%[2]s
+pulls.blocked_by_approvals = Цей запит на злиття ще не має достатньої кількості схвалень. Отримано %d з %d схвалень.
+pulls.blocked_by_rejection = Цей запит на злиття містить зміни, запропоновані офіційним рецензентом.
+pulls.blocked_by_official_review_requests = Цей запит на злиття заблоковано, оскільки йому бракує схвалення від одного або кількох офіційних рецензентів.
+pulls.blocked_by_outdated_branch = Цей запит на злиття заблоковано, оскільки він застарів.
+pulls.blocked_by_changed_protected_files_1 = Цей запит на злиття заблоковано, оскільки він змінює захищений файл:
+pulls.blocked_by_changed_protected_files_n = Цей запит на злиття заблоковано, оскільки він змінює захищені файли:
+pulls.auto_merge_newly_scheduled = Заплановано об'єднати запит на злиття після успішного завершення всіх перевірок.
+pulls.auto_merge_has_pending_schedule = %[1]s планує автоматично об'єднати цей запит на злиття після успішного завершення всіх перевірок %[2]s.
+pulls.auto_merge_newly_scheduled_comment = `планує автоматично об'єднати цей запит на злиття після успішного завершення всіх перевірок %[1]s`
+pulls.auto_merge_canceled_schedule_comment = `скасовує автоматичне об'єднання цього запиту на злиття після успішного завершення всіх перевірок %[1]s`
+pulls.delete.text = Ви дійсно хочете видалити цей запит на злиття? (Весь його вміст буде остаточно видалено. Можливо, варто його закрити і зберегти в архіві)
+comments.edit.already_changed = Не вдається зберегти зміни. Схоже, що хтось інший уже змінив вміст коментаря. Оновіть сторінку і спробуйте відредагувати ще раз, щоб уникнути перезапису чужих змін
+signing.wont_sign.pubkey = Коміт не буде підписано, оскільки у вас немає публічного ключа, пов'язаного з вашим обліковим записом.
+signing.wont_sign.twofa = Щоб підписувати коміти, у вас повинна бути ввімкнена двофакторна автентифікація.
+signing.wont_sign.parentsigned = Цей коміт не буде підписано, оскільки не підписано батьківський коміт.
+signing.wont_sign.basesigned = Злиття не буде підписано, оскільки не підписано базовий коміт.
+signing.wont_sign.headsigned = Злиття не буде підписано, оскільки не підписано головний коміт.
+signing.wont_sign.commitssigned = Злиття не буде підписано, оскільки всі пов'язані з ним коміти не підписані.
+signing.wont_sign.approved = Злиття не буде підписано, оскільки запит на злиття не схвалено.
+settings.mirror_settings.docs = Налаштуйте свій репозиторій на автоматичну синхронізацію комітів, тегів і гілок з іншим репозиторієм.
+settings.mirror_settings.docs.disabled_pull_mirror.instructions = Налаштуйте свій проєкт на автоматичне надсилання комітів, тегів і гілок до іншого репозиторію. Pull-дзеркала вимкнено адміністратором сайту.
+settings.mirror_settings.docs.disabled_push_mirror.instructions = Налаштуйте свій проєкт на автоматичне отримання комітів, тегів і гілок з іншого репозиторію.
+settings.mirror_settings.docs.disabled_push_mirror.info = Push-дзеркала вимкнено адміністратором сайту.
+settings.pulls.default_allow_edits_from_maintainers = За замовчуванням дозволити редагування від супроводжувачів
+settings.authorization_header = Заголовок авторизації
+settings.authorization_header_desc = За наявності буде включено як заголовок авторизації для запитів. Приклади: %s.
+settings.ignore_stale_approvals = Ігнорувати застарілі схвалення
+
[graphs]
contributors.what = внески
component_loading_info = Це може зайняти деякий час…
@@ -2799,6 +2959,9 @@ teams.write_access = Запис
teams.invite.by = Вас запрошує %s
teams.invite_team_member.list = Запрошення в очікуванні
+form.name_pattern_not_allowed = Вираз «%s» не може бути частиною назви організації.
+teams.add_nonexistent_repo = Репозиторій, який ви намагаєтеся додати, не існує. Спочатку створіть його.
+
[admin]
dashboard=Панель управління
users=Облікові записи користувачів
@@ -2847,7 +3010,7 @@ dashboard.update_migration_poster_id=Оновити мігровані ID авт
dashboard.git_gc_repos=Виконати очистку сміття для всіх репозиторіїв
dashboard.resync_all_sshkeys=Оновити файл «.ssh/authorized_keys» з SSH-ключами Forgejo.
dashboard.resync_all_sshprincipals=Оновити файл «.ssh/authorized_principals» з SSH даними користувача Forgejo.
-dashboard.resync_all_hooks=Пересинхронізувати перед-прийнятні, оновлюючі та пост-прийнятні хуки в усіх репозиторіях
+dashboard.resync_all_hooks=Пересинхронізувати хуки pre-receive, update та post-receive в усіх репозиторіях
dashboard.reinit_missing_repos=Переініціалізувати усі репозитрії git-файли яких втрачено
dashboard.sync_external_users=Синхронізувати дані зовнішніх користувачів
dashboard.cleanup_hook_task_table=Очистити hook_task таблицю
@@ -2906,11 +3069,11 @@ users.edit_account=Редагувати обліковий запис
users.max_repo_creation=Максимальна кількість репозиторіїв
users.max_repo_creation_desc=(Введіть -1, щоб використовувати глобальний ліміт за замовчуванням.)
users.is_activated=Обліковий запис користувача увімкнено
-users.prohibit_login=Вимкнути вхід
+users.prohibit_login=Заблокований обліковий запис
users.is_admin=Обліковий запис адміністратора
users.is_restricted=Обмежений
-users.allow_git_hook=Може створювати Git хуки
-users.allow_git_hook_tooltip=Git хуки виконуються від імені користувача OS сервісу Forgejo і мають однаковий рівень доступу до хоста. Як результат, користувачі з доступом до Git-хуків можуть отримати доступ і змінювати всі репозиторії Forgejo, а також базу даних, що використовуються в Forgejo. Отже, вони також здатні отримати права адміністратора Forgejo.
+users.allow_git_hook=Може створювати Git-хуки
+users.allow_git_hook_tooltip=Git-хуки виконуються від імені користувача ОС, від якого запущено Forgejo, і мають той самий рівень доступу до хоста. Таким чином, користувачі зі спеціальними правами Git-хуків можуть отримати доступ і змінювати всі репозиторії Forgejo, а також базу даних Forgejo. Вони також здатні отримати права адміністратора Forgejo.
users.allow_import_local=Може імпортувати локальні репозиторії
users.allow_create_organization=Може створювати організації
users.update_profile=Оновити обліковий запис
@@ -3051,7 +3214,7 @@ auths.sspi_default_language_helper=Типова мова для користув
auths.tips=Поради
auths.tips.oauth2.general=Автентифікація OAuth2
auths.tip.oauth2_provider=Постачальник OAuth2
-auths.tip.bitbucket=Створіть OAuth URI на сторінці %s
+auths.tip.bitbucket=Зареєструйте нового споживача OAuth на %s і додайте дозвіл «Обліковий запис» — «Читання»
auths.tip.nextcloud=`Зареєструйте нового споживача OAuth у вашому екземплярі за допомогою наступного меню "Налаштування -> Безпека -> клієнт OAuth 2.0"`
auths.tip.dropbox=Створіть новий додаток на %s
auths.tip.facebook=Зареєструйте новий додаток на %s і додайте модуль «Facebook Login»
@@ -3059,12 +3222,12 @@ auths.tip.github=Зареєструйте новий додаток OAuth на %
auths.tip.gitlab=Додайте новий додаток на https://gitlab.com/profile/applications
auths.tip.google_plus=Отримайте облікові дані клієнта OAuth2 в консолі Google API на сторінці %s
auths.tip.openid_connect=Використовуйте OpenID Connect Discovery URL (/.well-known/openid-configuration) для автоматичної настройки входу OAuth
-auths.tip.twitter=Перейдіть на %s, створіть програму і переконайтеся, що включена опція «Дозволити цю програму для входу в систему за допомогою Twitter»
+auths.tip.twitter=Перейдіть на %s, створіть програму і переконайтеся, що ввімкнено опцію «Дозволити використання цієї програми для входу через Twitter»
auths.tip.discord=Зареєструйте новий додаток на %s
auths.tip.yandex=Створіть новий додаток на %s. У розділі «Yandex.Passport API» виберіть такі дозволи: «Доступ до адреси електронної пошти», «Доступ до аватара» і «Доступ до імені користувача, імені та прізвища, статі»
auths.tip.mastodon=Введіть URL спеціального екземпляра для екземпляра mastodon, який ви хочете автентифікувати за допомогою (або використовувати за замовчуванням)
auths.edit=Редагувати джерело автентифікації
-auths.activated=Це джерело авторизації активоване
+auths.activated=Це джерело автентифікація активоване
auths.update_success=Параметри аутентифікації оновлені.
auths.update=Оновити джерело автентифікації
auths.delete=Видалити джерело автентифікації
@@ -3090,7 +3253,7 @@ config.repo_root_path=Шлях до кореня репозиторію
config.lfs_root_path=Кореневий шлях LFS
config.log_file_root_path=Шлях до лог файлу
config.script_type=Тип скрипта
-config.reverse_auth_user=Ім'я користувача для авторизації на reverse proxy
+config.reverse_auth_user=Користувач для авторизації на зворотному проксі
config.ssh_config=Конфігурація SSH
config.ssh_enabled=Увімкнено
@@ -3193,7 +3356,7 @@ config.git_gc_timeout=Тайм-аут операції збирача смітт
config.log_config=Конфігурація журналу
config.disabled_logger=Вимкнено
-config.access_log_mode=Режим доступу до журналу
+config.access_log_mode=Режим журналювання доступу
config.xorm_log_sql=Журнал SQL
@@ -3250,13 +3413,13 @@ packages.package_manage_panel = Керування пакунками
packages.published = Опубліковано
notices.operations = Дії
packages.cleanup = Очистити недійсні дані
-packages.cleanup.success = Успішно очищено недійсні дані
+packages.cleanup.success = Недійсні дані успішно очищено
users.still_own_packages = Цей користувач досі володіє одним чи більше пакунками, спочатку видаліть ці пакунки.
users.purge_help = Примусово видалити користувача і будь-які репозиторії, організації та пакунки, якими він володіє. Всі коментарі та задачі, створені цим користувачем, також будуть видалені.
dashboard.cleanup_packages = Очистити непридатні пакунки
monitor.last_execution_result = Результат
repos.lfs_size = Розмір LFS
-config.allow_dots_in_usernames = Дозволити використання крапки в іменах користувачів. Не впливає на існуючі облікові записи.
+config.allow_dots_in_usernames = Дозволити використання крапки в іменах користувачів. Не впливає на облікові записи, що вже існують.
config.mailer_enable_helo = Увімкнути HELO
users.organization_creation.description = Дозволити створення нових організацій.
users.cannot_delete_self = Ви не можете видалити себе
@@ -3305,8 +3468,29 @@ dashboard.cron.cancelled = Cron: %[1]s скасовано: %[3]s
defaulthooks.desc = Вебхуки автоматично сповіщають HTTP-сервер POST-запитами, коли в Forgejo відбуваються певні події. Вказані тут вебхуки є типовими і будуть скопійовані до всіх нових репозиторіїв. Докладніше — в посібнику з вебхуків.
assets = Ресурси коду
auths.invalid_openIdConnectAutoDiscoveryURL = Неправильна URL-адреса автоматичного виявлення (повинна бути дійсна URL-адреса, що починається з http:// або https://)
+settings = Налаштування адміністратора
+dashboard.cancel_abandoned_jobs = Скасувати покинуті завдання дій
+dashboard.start_schedule_tasks = Запустити заплановані завдання дій
+config.logger_name_fmt = Журнал: %s
+config.access_log_template = Шаблон журналу доступу
+config.set_setting_failed = Не вдалося встановити параметр %s
+monitor.download_diagnosis_report = Завантажити діагностичний звіт
+
+dashboard.update_checker = Перевірка оновлень
+auths.map_group_to_team_removal = Видаляти користувачів із синхронізованих команд, якщо користувачі не належать до відповідної групи LDAP
+auths.enable_ldap_groups = Увімкнути групи LDAP
+auths.oauth2_map_group_to_team_removal = Видаляти користувачів із синхронізованих команд, якщо користувачі не належать до відповідної групи.
+config.mailer_smtp_addr = Адреса SMTP
+
+auths.new_success = Метод автентифікації «%s» додано.
+auths.unable_to_initialize_openid = Не вдалося ініціалізувати постачальника OpenID Connect: %s
+config.cache_test = Перевірити кеш
+config.cache_test_failed = Не вдалося перевірити кеш: %v.
+config.cache_test_slow = Перевірку кешу завершено успішно, але відповідь повільна: %s.
+config.cache_test_succeeded = Перевірку кешу завершено успішно, відповідь отримано через %s.
+
[action]
create_repo=створив(ла) репозиторій %s
rename_repo=репозиторій перейменовано з %[1]s
на %[3]s
@@ -3409,7 +3593,7 @@ settings.delete.notice = Ви збираєтеся видалити %s (%s). Ц
details.author = Автор
title = Пакунки
arch.version.backup = Резервне копіювання
-arch.version.conflicts = Суперечки
+arch.version.conflicts = Конфлікти
arch.version.replaces = Заміни
arch.version.provides = Надає
arch.version.groups = Група
@@ -3526,6 +3710,16 @@ npm.registry = Налаштуйте цей реєстр у файлі .npm
chef.registry = Налаштуйте цей реєстр у файлі ~/.chef/config.rb
:
owner.settings.chef.keypair.description = Запити до реєстру Chef повинні бути криптографічно підписані як засіб автентифікації. При генерації пари ключів на Forgejo зберігається тільки публічний ключ. Приватний ключ надається вам для використання команд knife. Генерація нової пари ключів замінить попередню.
+nuget.dependency.framework = Цільовий фреймворк
+owner.settings.cleanuprules.preview.overview = Заплановано видалити %d пакунків.
+
+arch.pacman.repo.multi = %s має одну й ту саму версію в різних дистрибутивах.
+maven.install2 = Запустити з командного рядка:
+maven.download = Щоб завантажити залежність, запустіть із командного рядка:
+npm.dependencies.bundle = Пакетні залежності
+npm.dependencies.peer = Однорангові залежності
+owner.settings.cleanuprules.pattern_full_match = Застосувати шаблон до повної назви пакунка
+
[secrets]
deletion = Видалити секрет
creation.success = Секрет «%s» додано.
@@ -3578,7 +3772,7 @@ variables.management = Керування змінними
variables.id_not_exist = Змінної з ідентифікатором %d не існує.
variables.edit = Редагувати змінну
runs.expire_log_message = Журнали очищено, тому що вони були занадто старі.
-runs.empty_commit_message = (порожнє повідомлення коміта)
+runs.empty_commit_message = (порожнє повідомлення коміту)
runners.status.unspecified = Невідомо
runs.status_no_select = Усі стани
runs.status = Стан
@@ -3632,6 +3826,11 @@ runners.status.idle = Простоює
+runs.invalid_workflow_helper = Недійсний файл конфігурації робочого потоку. Будь ласка, перевірте файл конфігурації: %s
+runs.no_job_without_needs = Робочий потік повинен містити принаймні одне завдання без залежностей.
+runs.no_job = Робочий потік повинен містити принаймні одне завдання
+workflow.dispatch.use_from = Використати робочий потік із
+
[projects]
type-3.display_name = Проєкт організації
type-2.display_name = Проєкт репозиторію
@@ -3640,7 +3839,7 @@ deleted.display_name = Видалений проєкт
[git.filemode]
symbolic_link=Символічне посилання
-directory = Тека
+directory = Каталог
submodule = Підмодуль
normal_file = Звичайний файл
executable_file = Виконуваний файл
@@ -3697,6 +3896,8 @@ issues.read = Читати: дивитись і створювати за
wiki.read = Читати: переглядати вбудовану вікі та її історію.
actions.write = Писати: вручну запускати, перезапускати, скасовувати або схвалювати конвеєри CI/CD в очікуванні.
+projects.write = Писати: створювати проєкти і стовпчики та редагувати їх.
+
[munits.data]
pib = ПіБ
eib = ЕіБ
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index acdd4c0ced..fd6e625b5e 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -70,7 +70,7 @@ your_starred=点赞
your_settings=设置
all=所有
-sources=来源
+sources=原创
mirrors=镜像
collaborative=协作
forks=派生
@@ -171,7 +171,7 @@ copy_path = 复制路径
[aria]
navbar=导航栏
footer=页脚
-footer.software=关于软件
+footer.software=关于此软件
footer.links=链接
[heatmap]
@@ -1062,8 +1062,8 @@ language.description = 此语言将保存到您的账号中,并在您登录后
language.localization_project = 帮助我们将 Forgejo 翻译成您的语言!了解更多。
user_block_yourself = 您不能屏蔽自己。
pronouns_custom_label = 自定义代词
-change_username_redirect_prompt.with_cooldown.one = 旧的用户名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
-change_username_redirect_prompt.with_cooldown.few = 旧的用户名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
+change_username_redirect_prompt.with_cooldown.one = 旧用户名将在 %[1]d 天的保护期后对所有人可用。您仍可以在此期间重新认领旧用户名。
+change_username_redirect_prompt.with_cooldown.few = 旧用户名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧用户名。
keep_pronouns_private = 仅向已认证用户显示代词
keep_pronouns_private.description = 这将对未登录的访问者隐藏您的代词。
quota = 配额
@@ -1581,7 +1581,7 @@ issues.remove_ref_at=`删除了引用 %s %s`
issues.add_ref_at=`添加了引用 %s %s`
issues.delete_branch_at=`于 %[2]s 删除了分支 %[1]s`
issues.filter_label=标签筛选
-issues.filter_label_exclude=`使用 alt
+ 鼠标左键 / 回车
排除标签`
+issues.filter_label_exclude=使用 Alt + 单击 排除标签
issues.filter_label_no_select=所有标签
issues.filter_label_select_no_label=无标签
issues.filter_milestone=里程碑筛选
@@ -1655,13 +1655,13 @@ issues.close_comment_issue=评论并关闭
issues.reopen_issue=重新开放
issues.reopen_comment_issue=重新打开并评论
issues.create_comment=评论
-issues.closed_at=`于%[2]s关闭此议题`
-issues.reopened_at=`重新打开此问题 %[2]s`
-issues.commit_ref_at=`于%[2]s在代码提交中引用了该议题`
-issues.ref_issue_from=`引用了议题 %[4]s %[2]s`
-issues.ref_pull_from=`引用了合并请求 %[4]s %[2]s`
-issues.ref_closing_from=`于 %[2]s 从合并请求 %[4]s引用了此议题,将关闭此议题`
-issues.ref_reopening_from=`于 %[2]s 引用了合并请求 %[4]s 将重新讨论此议题 `
+issues.closed_at=`于 %s 关闭了此议题`
+issues.reopened_at=`于 %s 重新打开了此议题`
+issues.commit_ref_at=`于 %s 从提交中引用了此议题`
+issues.ref_issue_from=`引用了此议题 %[3]s %[1]s`
+issues.ref_pull_from=`引用了此合并请求 %[3]s %[1]s`
+issues.ref_closing_from=`于 %[1]s 从合并请求 %[3]s 引用了此议题,将关闭此议题`
+issues.ref_reopening_from=`于 %[1]s 从合并请求 %[3]s 引用了此议题,将重新打开此议题 `
issues.ref_closed_from=`关闭了这个议题 %[4]s %[2]s`
issues.ref_reopened_from=`重新打开这个议题 %[4]s %[2]s`
issues.ref_from=`来自 %[1]s`
@@ -1969,8 +1969,8 @@ pulls.update_branch_success=分支更新成功
pulls.update_not_allowed=您无权更新分支
pulls.outdated_with_base_branch=此分支相比基础分支已过期
pulls.close=关闭
-pulls.closed_at=`于%[2]s关闭此合并请求 `
-pulls.reopened_at=`重新打开此合并请求 %[2]s`
+pulls.closed_at=`于 %s 关闭了此合并请求 `
+pulls.reopened_at=`于 %s 重新打开了此合并请求`
pulls.cmd_instruction_hint=查看命令行说明
pulls.cmd_instruction_checkout_title=检出
pulls.cmd_instruction_checkout_desc=从你的仓库中检出一个新的分支并测试变更。
@@ -2770,7 +2770,7 @@ settings.wiki_rename_branch_main = 标准化百科分支名称
settings.wiki_rename_branch_main_notices_1 = 此操作无法撤消。
settings.wiki_branch_rename_success = 百科仓库的分支名称已成功规范化。
settings.confirm_wiki_branch_rename = 重命名百科分支
-pulls.commit_ref_at = `在提交 %[2]s 中引用了此合并请求`
+pulls.commit_ref_at = `于 %s 从提交中引用了此合并请求`
settings.wiki_rename_branch_main_notices_2 = 这将永久重命名 %s 的仓库百科的内部分支。现存的检出方式需要更新。
settings.wiki_branch_rename_failure = 无法标准化仓库百科的分支名称。
settings.add_collaborator_blocked_our = 因仓库所有者已将其拉黑,不能添加该用户为协作者。
@@ -2922,6 +2922,7 @@ settings.event_action_success = 成功
settings.event_action_success_desc = Action运行以成功结束。
settings.event_action_failure_desc = Action运行以失败结束。
settings.event_header_action = Action运行事件
+issues.filter_type.all_pull_requests = 所有合并请求
[graphs]
component_loading=正在加载 %s…
@@ -3057,8 +3058,8 @@ teams.invite.by=邀请人 %s
teams.invite.description=请点击下面的按钮加入团队。
follow_blocked_user = 你无法关注此组织,因为此组织已屏蔽你。
open_dashboard = 打开仪表盘
-settings.change_orgname_redirect_prompt.with_cooldown.one = 旧的组织名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧的名字。
-settings.change_orgname_redirect_prompt.with_cooldown.few = 旧的组织名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧名字。
+settings.change_orgname_redirect_prompt.with_cooldown.one = 旧组织名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧名称。
+settings.change_orgname_redirect_prompt.with_cooldown.few = 旧组织名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧名称。
[admin]
dashboard=管理面板
diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini
index e2cb0d8b2c..45534801de 100644
--- a/options/locale/locale_zh-HK.ini
+++ b/options/locale/locale_zh-HK.ini
@@ -574,7 +574,7 @@ issues.delete_comment_confirm=您確定要刪除該條評論嗎?
issues.context.edit=編輯
issues.reopen_issue=重新開啟
issues.create_comment=評論
-issues.commit_ref_at=`在代碼提交 %[2]s 中引用了該問題`
+issues.commit_ref_at=`在代碼提交 %s 中引用了該問題`
issues.role.owner=管理員
issues.role.member=普通成員
issues.sign_in_require_desc= 登入 才能加入這對話。
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index b21e4c8f79..ddc31730d7 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -1062,7 +1062,7 @@ language.localization_project = 幫助我們翻譯 Forgejo 至您的語言!公開活動只有你和站點管理員可見。
quota.rule.exceeded = 已超出
@@ -1604,13 +1604,13 @@ issues.close_comment_issue=留言並關閉
issues.reopen_issue=重新開放
issues.reopen_comment_issue=留言並重新開放
issues.create_comment=留言
-issues.closed_at=`關閉了這個問題 %[2]s`
-issues.reopened_at=`重新開放了這個問題 %[2]s`
-issues.commit_ref_at=`在提交中關聯了這個問題 %[2]s`
-issues.ref_issue_from=`關聯了這個問題 %[4]s %[2]s`
-issues.ref_pull_from=`關聯了這個合併請求 %[4]s %[2]s`
-issues.ref_closing_from=從將關閉此問題的拉取請求 %[4]s 中提及了此問題,%[2]s
-issues.ref_reopening_from=從將重新開啟此問題的拉取請求 %[4]s 中提及了此問題,%[2]s
+issues.closed_at=`關閉了這個問題 %s`
+issues.reopened_at=`重新開放了這個問題 %s`
+issues.commit_ref_at=`在提交中關聯了這個問題 %s`
+issues.ref_issue_from=`關聯了這個問題 %[3]s %[1]s`
+issues.ref_pull_from=`關聯了這個合併請求 %[3]s %[1]s`
+issues.ref_closing_from=從將關閉此問題的拉取請求 %[3]s 中提及了此問題,%[1]s
+issues.ref_reopening_from=從將重新開啟此問題的拉取請求 %[3]s 中提及了此問題,%[1]s
issues.ref_closed_from=`關閉了這個問題 %[4]s %[2]s`
issues.ref_reopened_from=`重新開放了這個問題 %[4]s %[2]s`
issues.ref_from=`自 %[1]s`
@@ -1879,8 +1879,8 @@ pulls.update_branch_success=分支更新成功
pulls.update_not_allowed=您無權更新分支
pulls.outdated_with_base_branch=相對於基底分支,此分支已過時
pulls.close=關閉合併請求
-pulls.closed_at=`關閉了這個合併請求 %[2]s`
-pulls.reopened_at=`重新開放了這個合併請求 %[2]s`
+pulls.closed_at=`關閉了這個合併請求 %s`
+pulls.reopened_at=`重新開放了這個合併請求 %s`
pulls.clear_merge_message=清除合併訊息
pulls.clear_merge_message_hint=清除合併訊息將僅移除提交訊息內容,留下產生的 git 結尾,如「Co-Authored-By …」。
@@ -2634,7 +2634,7 @@ commits.search_branch = 此分支
commits.browse_further = 進一步瀏覽
commits.renamed_from = 自 %s 重新命名
issues.filter_milestone_none = 沒有里程碑
-issues.num_comments_1 = %s 則留言
+issues.num_comments_1 = %d 則留言
issues.no_content = 沒有提供敘述。
settings.new_owner_blocked_doer = 新的所有者已封鎖您。
new_repo_helper = 一個儲存庫包含專案的所有檔案和它們的修訂歷史。在別處已經有儲存庫了嗎?遷移儲存庫。
@@ -2693,7 +2693,7 @@ signing.wont_sign.never = 永不簽署提交。
editor.push_out_of_date = 該推送似乎過期了。
issues.cancel_tracking_history = `已取消時間追蹤 %s`
issues.due_date_not_writer = 您需要有寫入這個儲存庫的權限才能更新其問題的到期日。
-pulls.commit_ref_at = `在提交 %[2]s 引用了這個合併請求`
+pulls.commit_ref_at = `在提交 %s 引用了這個合併請求`
pulls.cmd_instruction_checkout_desc = 從您的專案儲存庫中,建立並切換到一個新分支以測試這些變更。
pulls.cmd_instruction_merge_title = 合併
pulls.ready_for_review = 可以開始審閱了嗎?
diff --git a/options/locale_next/locale_ar.json b/options/locale_next/locale_ar.json
index 3d87c7ee95..1574d3eb7c 100644
--- a/options/locale_next/locale_ar.json
+++ b/options/locale_next/locale_ar.json
@@ -3,5 +3,72 @@
"home.welcome.no_activity": "لا يوجد نشاط",
"home.explore_repos": "اكتشف المستودعات",
"home.explore_users": "اكتشف المستخدمين",
- "home.explore_orgs": "اكتشف المنظمات"
+ "home.explore_orgs": "اكتشف المنظمات",
+ "moderation.abuse_category.malware": "برمجية خبيثة",
+ "moderation.abuse_category.illegal_content": "محتوى غير مشروع",
+ "stars.list.none": "لم يقم أحد بتمييز هذا المستودع بنجمة.",
+ "watch.list.none": "لا أحد يشاهد هذا المستودع.",
+ "followers.incoming.list.self.none": "لا أحد يتابع ملفك الشخصي.",
+ "followers.incoming.list.none": "لا أحد يتابع هذا المستخدم.",
+ "followers.outgoing.list.self.none": "أنت لا تتبع أي شخص.",
+ "followers.outgoing.list.none": "لا يتابع %s أي شخص.",
+ "relativetime.now": "الآن",
+ "relativetime.future": "في المستقبل",
+ "relativetime.1day": "الأمس",
+ "relativetime.2days": "منذ يومين",
+ "relativetime.1week": "أخر أسبوع",
+ "relativetime.2weeks": "منذ أسبوعين",
+ "relativetime.1month": "الشهر الفائت",
+ "relativetime.2months": "منذ شهرين",
+ "relativetime.1year": "السنة الفائتة",
+ "relativetime.2years": "منذ سنتين",
+ "repo.form.cannot_create": "بلغت جميع المساحات التي يمكنك إنشاء مستودعات بها حدها.",
+ "repo.issue_indexer.title": "مفهرس الإبلاغات",
+ "search.milestone_kind": "معالم البحث…",
+ "incorrect_root_url": "تم تكوين هذه النسخة من Forgejo لتعمل على العنوان \"%s\". أنت تقوم حاليًا بتصفّح Forgejo عبر رابط مختلف، مما قد يتسبب في تعطل بعض أجزاء التطبيق. يتم تحديد الرابط الرسمي (canonical URL) من قِبل مسؤولي Forgejo من خلال إعداد `ROOT_URL` في ملف `app.ini`.",
+ "themes.names.forgejo-auto": "فورجيو (اتبع سمة النظام)",
+ "themes.names.forgejo-light": "فورجيجو المضيء",
+ "themes.names.forgejo-dark": "فورجيجو الداكن",
+ "error.not_found.title": "الصفحة غير موجودة",
+ "alert.asset_load_failed": "تعذّر تحميل ملفات الأصول من {path}. تأكد من أن الملفات متاحة للوصول.",
+ "alert.range_error": " يجب أن يكون رقمًا بين %[1]s و %[2]s.",
+ "install.invalid_lfs_path": "غير قادر على إنشاء جذر LFS في المسار المحدد: %[1]s",
+ "profile.actions.tooltip": "إجراءات إضافية",
+ "profile.edit.link": "عدِّل ملف التعريف",
+ "feed.atom.link": "موجز Atom",
+ "keys.ssh.link": "مفاتيح SSH",
+ "keys.gpg.link": "مفاتيح GPG",
+ "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": "لقد قمت بالفعل بالإبلاغ عن هذا المحتوى",
+ "moderation.abuse_category": "الفئة",
+ "moderation.abuse_category.placeholder": "حدد الفئة",
+ "moderation.abuse_category.spam": "غير مرغوب به",
+ "moderation.abuse_category.other_violations": "انتهاكات أخرى لقواعد المنصة",
+ "moderation.report_remarks": "الملاحظات",
+ "moderation.report_remarks.placeholder": "يُرجى تقديم بعض التفاصيل المتعلقة بالإساءة التي أبلغت عنها.",
+ "moderation.submit_report": "إرسال التقرير",
+ "moderation.reporting_failed": "تعذر إرسال تقرير إساءة الاستخدام الجديد: %v",
+ "moderation.reported_thank_you": "شكراُ لك على تقريرك. وقد تم إبلاغ الإدارة به.",
+ "mail.actions.successful_run_after_failure_subject": "تم استعادة سير العمل %[1]s في المستودع %[2]s",
+ "mail.actions.not_successful_run_subject": "سير العمل %[1]s فشل في المستودت %[2]s",
+ "mail.actions.successful_run_after_failure": "تم استعادة سير العمل %[1]s في المستودع %[2]s",
+ "mail.actions.not_successful_run": "فشل سير العمل %[1]s في المستودع %[2]s",
+ "mail.actions.run_info_cur_status": "حالة هذا التشغيل: %[1]s (تم تحديثها من %[2]s للتو)",
+ "mail.actions.run_info_previous_status": "حالة التشغيل السابقة: %[1]s",
+ "mail.actions.run_info_sha": "إيداع: %[1]s",
+ "mail.actions.run_info_trigger": "تم تشغيله بسبب: %[1]s عبر: %[2]s",
+ "repo.diff.commit.next-short": "التالي",
+ "repo.diff.commit.previous-short": "السابق",
+ "discussion.locked": "تم إغلاق هذه المناقشة. يقتصر التعليق على المساهمين فقط.",
+ "editor.textarea.tab_hint": "السطر مُزاح بالفعل. اضغط Tab مرة أخرى أو Escape لمغادرة المحرر.",
+ "editor.textarea.shift_tab_hint": "لا توجد مسافة بادئة في هذا السطر. اضغط Shift + Tab مرة أخرى أو Escape لمغادرة المحرر.",
+ "admin.dashboard.cleanup_offline_runners": "تنظيف وحدات التشغيل غير المتصلة",
+ "settings.visibility.description": "رؤية ملفك الشخصي تؤثر في قدرة الآخرين على الوصول إلى مستودعاتك غير الخاصة. اعرف المزيد",
+ "avatar.constraints_hint": "لا يمكن أن يتجاوز حجم الصورة الشخصية المخصصة %[1]s، ولا أبعادها عن %[2]d×%[3]d بكسل",
+ "meta.last_line": "شكرًا لك على ترجمة Forgejo! هذا السطر لا يراه المستخدمون ولكنه يخدم أغراضًا أخرى في إدارة الترجمة. يمكنك وضع حقيقة ممتعة في الترجمة بدلاً من ترجمتها."
}
diff --git a/options/locale_next/locale_be.json b/options/locale_next/locale_be.json
index 0967ef424b..c8ff00bd87 100644
--- a/options/locale_next/locale_be.json
+++ b/options/locale_next/locale_be.json
@@ -1 +1,8 @@
-{}
+{
+ "moderation.abuse_category.malware": "Шкодная праграма",
+ "home.welcome.no_activity": "Няма падзей",
+ "home.welcome.activity_hint": "У вашай стужцы пакуль што нічога няма. Вашыя дзеяньні ды падзеі з рэпазыторыяў зьявяцца тут.",
+ "home.explore_repos": "Агляд рэпазыторыяў",
+ "home.explore_users": "Агляд карыстальнікаў",
+ "home.explore_orgs": "Агляд арганізацый"
+}
diff --git a/options/locale_next/locale_bn.json b/options/locale_next/locale_bn.json
index 0967ef424b..56a6e6dae4 100644
--- a/options/locale_next/locale_bn.json
+++ b/options/locale_next/locale_bn.json
@@ -1 +1,3 @@
-{}
+{
+ "moderation.abuse_category.malware": "ম্যালওয়্যার"
+}
diff --git a/options/locale_next/locale_ca.json b/options/locale_next/locale_ca.json
index 8eefc65a1a..606ab99173 100644
--- a/options/locale_next/locale_ca.json
+++ b/options/locale_next/locale_ca.json
@@ -1,3 +1,4 @@
{
- "search.milestone_kind": "Cerca fites..."
+ "search.milestone_kind": "Cerca fites...",
+ "moderation.abuse_category.malware": "Programari maliciós"
}
diff --git a/options/locale_next/locale_cs-CZ.json b/options/locale_next/locale_cs-CZ.json
index 97a8536d4f..7fb22a0d33 100644
--- a/options/locale_next/locale_cs-CZ.json
+++ b/options/locale_next/locale_cs-CZ.json
@@ -105,5 +105,11 @@
"settings.visibility.description": "Viditelnost profilu ovlivňuje možnost ostatních přistupovat k vašim veřejným repozitářům. Zjistit více",
"avatar.constraints_hint": "Velikost vlastního avataru nesmí překročit %[1]s nebo být větší než %[2]dx%[3]d pixelů",
"repo.diff.commit.next-short": "Další",
- "repo.diff.commit.previous-short": "Předchozí"
+ "repo.diff.commit.previous-short": "Předchozí",
+ "profile.actions.tooltip": "Další akce",
+ "profile.edit.link": "Upravit profil",
+ "feed.atom.link": "Zdroj Atom",
+ "keys.ssh.link": "Klíče SSH",
+ "keys.gpg.link": "Klíče GPG",
+ "mail.actions.run_info_sha": "Revize: %[1]s"
}
diff --git a/options/locale_next/locale_da.json b/options/locale_next/locale_da.json
index 8315e06bcc..c43a7e3d37 100644
--- a/options/locale_next/locale_da.json
+++ b/options/locale_next/locale_da.json
@@ -97,5 +97,10 @@
"settings.visibility.description": "Profilsynlighed påvirker andres adgang til dine ikke-private depoter. Læs mere",
"avatar.constraints_hint": "Brugerdefineret avatar må ikke overstige %[1]s i størrelse eller være større end %[2]dx%[3]d pixels",
"repo.diff.commit.next-short": "Næste",
- "repo.diff.commit.previous-short": "Forrige"
+ "repo.diff.commit.previous-short": "Forrige",
+ "profile.actions.tooltip": "Flere handlinger",
+ "profile.edit.link": "Redigere profil",
+ "feed.atom.link": "Atom feed",
+ "keys.ssh.link": "SSH Nøgler",
+ "keys.gpg.link": "GPG Nøgler"
}
diff --git a/options/locale_next/locale_de-DE.json b/options/locale_next/locale_de-DE.json
index 94ab12f180..c64e25b242 100644
--- a/options/locale_next/locale_de-DE.json
+++ b/options/locale_next/locale_de-DE.json
@@ -91,11 +91,17 @@
"followers.outgoing.list.none": "%s folgt niemanden.",
"stars.list.none": "Niemand hat dieses Repo favorisiert.",
"followers.incoming.list.none": "Niemand folgt diesem Benutzer.",
- "editor.textarea.tab_hint": "Zeile bereits eingerückt. Drücke nochmals Tab oder Escape um den Editor zu verlassen.",
- "editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals Shift + Tab oder Escape um den Editor zu verlassen.",
- "admin.dashboard.cleanup_offline_runners": "Aufräumen der offline Runner",
+ "editor.textarea.tab_hint": "Zeile bereits eingerückt. Drücke nochmals Tab oder Escape, um den Editor zu verlassen.",
+ "editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals Shift + Tab oder Escape, um den Editor zu verlassen.",
+ "admin.dashboard.cleanup_offline_runners": "Aufräumen der Offline-Runner",
"settings.visibility.description": "Die Profilsichtbarkeit beeinflusst die Möglichkeit anderer, auf deine nicht-privaten Repositorys zuzugreifen. Erfahre mehr",
- "avatar.constraints_hint": "Individuelles Profilbild darf %[1]s in der Größe nicht überschreiten, und nicht größer als %[2]dx%[3]d Pixel sein",
+ "avatar.constraints_hint": "Individuelles Profilbild darf %[1]s in der Größe nicht überschreiten, und nicht größer als %[2]d×%[3]d Pixel sein",
"repo.diff.commit.next-short": "Nächste",
- "repo.diff.commit.previous-short": "Vorherige"
+ "repo.diff.commit.previous-short": "Vorherige",
+ "profile.edit.link": "Profil bearbeiten",
+ "feed.atom.link": "Atom-Feed",
+ "keys.ssh.link": "SSH-Schlüssel",
+ "keys.gpg.link": "GPG-Schlüssel",
+ "profile.actions.tooltip": "Mehr Aktionen",
+ "mail.actions.run_info_sha": "Commit: %[1]s"
}
diff --git a/options/locale_next/locale_en-US.json b/options/locale_next/locale_en-US.json
index b1c98e4551..4f1c3904e2 100644
--- a/options/locale_next/locale_en-US.json
+++ b/options/locale_next/locale_en-US.json
@@ -92,7 +92,7 @@
"mail.actions.not_successful_run": "Workflow %[1]s failed in repository %[2]s",
"mail.actions.run_info_cur_status": "This Run's Status: %[1]s (just updated from %[2]s)",
"mail.actions.run_info_previous_status": "Previous Run's Status: %[1]s",
- "mail.actions.run_info_ref": "Branch: %[1]s (%[2]s)",
+ "mail.actions.run_info_sha": "Commit: %[1]s",
"mail.actions.run_info_trigger": "Triggered because: %[1]s by: %[2]s",
"repo.diff.commit.next-short": "Next",
"repo.diff.commit.previous-short": "Prev",
diff --git a/options/locale_next/locale_es-ES.json b/options/locale_next/locale_es-ES.json
index 37edef9211..82fbcfb4b6 100644
--- a/options/locale_next/locale_es-ES.json
+++ b/options/locale_next/locale_es-ES.json
@@ -30,5 +30,6 @@
"relativetime.future": "en el futuro",
"home.explore_repos": "Explorar repositorios",
"home.explore_users": "Explorar usuarios",
- "home.explore_orgs": "Explorar organizaciones"
+ "home.explore_orgs": "Explorar organizaciones",
+ "moderation.abuse_category.malware": "Malware"
}
diff --git a/options/locale_next/locale_fi-FI.json b/options/locale_next/locale_fi-FI.json
index cb26d76e66..14481acf6f 100644
--- a/options/locale_next/locale_fi-FI.json
+++ b/options/locale_next/locale_fi-FI.json
@@ -64,5 +64,6 @@
"mail.actions.run_info_cur_status": "Tämän juoksun tila: %[1]s (juuri päivitetty %[2]s:sta)",
"mail.actions.run_info_previous_status": "Edellisen ajon tila: %[1]s",
"mail.actions.run_info_ref": "Haara: %[1]s (%[2]s)",
- "mail.actions.run_info_trigger": "Laukaistui, koska: %[1]s, tekijänä: %[2]s"
+ "mail.actions.run_info_trigger": "Laukaistui, koska: %[1]s, tekijänä: %[2]s",
+ "moderation.abuse_category.malware": "Haittaohjelma"
}
diff --git a/options/locale_next/locale_fil.json b/options/locale_next/locale_fil.json
index 1f1e535dad..20b35b8edb 100644
--- a/options/locale_next/locale_fil.json
+++ b/options/locale_next/locale_fil.json
@@ -1,6 +1,6 @@
{
"repo.pulls.merged_title_desc": {
- "one": "isinali ang %[1]d commit mula%[2]s
patungong %[3]s
%[4]s",
+ "one": "isinali ang %[1]d commit mula %[2]s
patungong %[3]s
%[4]s",
"other": "isinali ang %[1]d mga commit mula sa %[2]s
patungong %[3]s
%[4]s"
},
"repo.pulls.title_desc": {
@@ -21,7 +21,7 @@
"alert.asset_load_failed": "Nabigong i-load ang mga asset file mula sa {path}. Siguraduhin na maa-access ang mga asset file.",
"install.invalid_lfs_path": "Nabigong gawin ang LFS root sa tinakdang path: %[1]s",
"alert.range_error": " dapat ay numero sa pagitan ng %[1]s at %[2]s.",
- "meta.last_line": "Sayori... I love you. — MC from Doki Doki Literature Club",
+ "meta.last_line": "Every day, I imagine a future where I can be with you. In my hand is a pen that will write a poem of me and you. The ink flows down into a dark puddle... Just move your hand, write the way into his heart. But in this world of infinite choices, what will it take just to find that special day? Have I found everybody a fun assignment to do today? When you're here, everything that we do is fun for them anyway... When I can't even read my own feelings, what good are words when a smile says it all? And if this world won't write me an ending, what will it take just for me to have it all? Does my pen only write bitter words for those who are dear to me? Is it love if I take you, or is it love if I set you free? The ink flows down into a dark puddle... How can I write love into reality? If I can't hear the sound of your heartbeat, what do you call love in your reality? And in your reality, if I don't know how to love you... I'll leave you be.",
"mail.actions.successful_run_after_failure": "Na-recover ang workflow na %[1]s sa repositoryong %[2]s",
"mail.actions.not_successful_run": "Nabigo ang workflow na %[1]s sa repositoryong %[2]s",
"mail.actions.run_info_previous_status": "Nakaraang Status ng Run: %[1]s",
@@ -94,5 +94,14 @@
"editor.textarea.tab_hint": "Naka-indent na ang linya. Pindutin ulit ang Tab o Escape para umalis sa editor.",
"editor.textarea.shift_tab_hint": "Walang indentation sa linyang ito. Pindutin ang Shift + Tab ulit o Escape para umalis sa editor.",
"admin.dashboard.cleanup_offline_runners": "Linisin ang mga offline na runner",
- "settings.visibility.description": "Maaapektuhan ng visibility ng profile ang kakayahan ng iba na i-access ang iyong mga hindi pribadong repositoryo. Matuto pa"
+ "settings.visibility.description": "Maaapektuhan ng visibility ng profile ang kakayahan ng iba na i-access ang iyong mga hindi pribadong repositoryo. Matuto pa",
+ "avatar.constraints_hint": "Hindi maaaring lumagpas sa laking %[1]s o mas malaki sa %[2]dx%[3]d pixel ang custom na avatar",
+ "repo.diff.commit.next-short": "Susunod",
+ "repo.diff.commit.previous-short": "Nakaraan",
+ "profile.edit.link": "I-edit ang profile",
+ "feed.atom.link": "Atom feed",
+ "keys.ssh.link": "Mga SSH key",
+ "keys.gpg.link": "Mga GPG key",
+ "profile.actions.tooltip": "Higit pang mga aksyon",
+ "mail.actions.run_info_sha": "Commit: %[1]s"
}
diff --git a/options/locale_next/locale_fr-FR.json b/options/locale_next/locale_fr-FR.json
index a9035f0848..da26d56107 100644
--- a/options/locale_next/locale_fr-FR.json
+++ b/options/locale_next/locale_fr-FR.json
@@ -6,7 +6,7 @@
},
"repo.pulls.title_desc": {
"one": "veut fusionner %[1]d commit depuis %[2]s
vers %[3]s
",
- "many": "souhaite fusionner %[1]d révision(s) depuis %[2]s
vers %[3]s
",
+ "many": "veut fusionner %[1]d commits depuis %[2]s
vers %[3]s
",
"other": ""
},
"search.milestone_kind": "Recherche dans les jalons…",
diff --git a/options/locale_next/locale_hu-HU.json b/options/locale_next/locale_hu-HU.json
index 9d52509102..1c02002e6e 100644
--- a/options/locale_next/locale_hu-HU.json
+++ b/options/locale_next/locale_hu-HU.json
@@ -1,5 +1,6 @@
{
"repo.pulls.merged_title_desc": "egyesítve %[1]d változás(ok) a %[2]s
-ból %[3]s
-ba %[4]s",
"repo.pulls.title_desc": "egyesíteni szeretné %[1]d változás(oka)t a(z) %[2]s
-ból %[3]s
-ba",
- "search.milestone_kind": "Mérföldkövek keresése..."
+ "search.milestone_kind": "Mérföldkövek keresése...",
+ "moderation.abuse_category.malware": "Malware"
}
diff --git a/options/locale_next/locale_id-ID.json b/options/locale_next/locale_id-ID.json
index f2dac8114f..0cf7ea4799 100644
--- a/options/locale_next/locale_id-ID.json
+++ b/options/locale_next/locale_id-ID.json
@@ -1,8 +1,9 @@
{
- "repo.pulls.merged_title_desc": {
- "other": "commit %[1]d telah digabungkan dari %[2]s
menjadi %[3]s
%[4]s"
- },
- "repo.pulls.title_desc": {
- "other": "ingin menggabungkan komit %[1]d dari %[2]s
menuju %[3]s
"
- }
+ "repo.pulls.merged_title_desc": {
+ "other": "commit %[1]d telah digabungkan dari %[2]s
menjadi %[3]s
%[4]s"
+ },
+ "repo.pulls.title_desc": {
+ "other": "ingin menggabungkan komit %[1]d dari %[2]s
menuju %[3]s
"
+ },
+ "moderation.abuse_category.malware": "Perangkat pembahaya"
}
diff --git a/options/locale_next/locale_it-IT.json b/options/locale_next/locale_it-IT.json
index 8bd6d811a0..8464d6244e 100644
--- a/options/locale_next/locale_it-IT.json
+++ b/options/locale_next/locale_it-IT.json
@@ -15,5 +15,83 @@
"home.welcome.no_activity": "Nessun'attività",
"home.explore_repos": "Esplora i repositori",
"home.explore_users": "Esplora l'utenza",
- "home.explore_orgs": "Esplora le organizzazioni"
+ "home.explore_orgs": "Esplora le organizzazioni",
+ "mail.actions.successful_run_after_failure_subject": "Il flusso di lavoro %[1] ha ripreso a funzionare nel repositorio %[2]s",
+ "mail.actions.not_successful_run_subject": "Il flusso di lavoro %[1]s è fallito nel repositorio %[2]s",
+ "relativetime.future": "nel futuro",
+ "relativetime.days": {
+ "one": "ieri",
+ "many": "%d giorni fa",
+ "other": "%d giorni fa"
+ },
+ "relativetime.1day": "ieri",
+ "repo.form.cannot_create": "Tutti gli spazi in cui puoi creare repositori hanno raggiunto il limite di repositori.",
+ "discussion.locked": "Questa discussione è stata bloccata. Solo i contributori possono commentare.",
+ "relativetime.hours": {
+ "one": "un'ora fa",
+ "many": "%d ore fa",
+ "other": "%d ore fa"
+ },
+ "relativetime.2years": "due anni fa",
+ "relativetime.now": "adesso",
+ "relativetime.weeks": {
+ "one": "una settimana fa",
+ "many": "%d settimane fa",
+ "other": "%d settimane fa"
+ },
+ "relativetime.months": {
+ "one": "un mese fa",
+ "many": "%d mesi fa",
+ "other": "%d mesi fa"
+ },
+ "relativetime.years": {
+ "one": "un anno fa",
+ "many": "%d anni fa",
+ "other": "%d anni fa"
+ },
+ "repo.issue_indexer.title": "Indicizzatore delle segnalazioni",
+ "admin.config.moderation_config": "Impostazioni di moderazione",
+ "moderation.report_abuse": "Segnala abuso",
+ "moderation.report_content": "Segnala contenuto",
+ "moderation.report_abuse_form.already_reported": "Hai già segnalato questo contenuto",
+ "moderation.abuse_category": "Categoria",
+ "moderation.abuse_category.placeholder": "Seleziona una categoria",
+ "moderation.abuse_category.spam": "Spam",
+ "moderation.abuse_category.malware": "Malware",
+ "moderation.abuse_category.illegal_content": "Contenuti illegali",
+ "moderation.abuse_category.other_violations": "Altre violazioni delle regole della piattaforma",
+ "moderation.report_remarks": "Note aggiuntive",
+ "moderation.report_remarks.placeholder": "Aggiungi dettagli riguardanti l'abuso che stai segnalando.",
+ "moderation.submit_report": "Invia segnalazione",
+ "error.not_found.title": "Pagina non trovata",
+ "themes.names.forgejo-auto": "Forgejo (segui le impostazioni di sistema)",
+ "stars.list.none": "Nessuno ha messo una stella a questo repo.",
+ "watch.list.none": "Nessuno sta osservando questo repo.",
+ "followers.incoming.list.self.none": "Nessuno sta seguendo il tuo profilo.",
+ "followers.incoming.list.none": "Nessuno sta seguendo questo utente.",
+ "followers.outgoing.list.self.none": "Non segui nessuno.",
+ "followers.outgoing.list.none": "%s non sta seguendo nessuno.",
+ "relativetime.2days": "due giorni fa",
+ "relativetime.2weeks": "due settimane fa",
+ "relativetime.1week": "la settimana scorsa",
+ "relativetime.1month": "il mese scorso",
+ "relativetime.2months": "due mesi fa",
+ "relativetime.1year": "l'anno scorso",
+ "moderation.report_abuse_form.header": "Segnala abuso all'amministratore",
+ "moderation.report_abuse_form.details": "Questo modulo dovrebbe essere utilizzato per segnalare utenti che creano profili, repositori, segnalazioni o commenti spam o che si comportano in modo non adeguato.",
+ "moderation.report_abuse_form.invalid": "Argomenti non validi",
+ "moderation.reporting_failed": "Impossibile inviare segnalazione: %v",
+ "moderation.reported_thank_you": "Grazie per la segnalazione. L'amministratore è stato avvertito.",
+ "mail.actions.run_info_ref": "Ramo: %[1]s (%[2]s)",
+ "alert.asset_load_failed": "Impossibile caricare i file di risorsa da {path}. Controlla che i file di risorsa siano accessibili.",
+ "install.invalid_lfs_path": "Non è possibile creare una root LFS nel percorso specificato: %[1]s",
+ "home.welcome.activity_hint": "Non c'è nulla nel tuo feed. Le tue azioni e le attività dei repositori che segui verranno mostrate qui.",
+ "relativetime.mins": {
+ "one": "un minuto fa",
+ "many": "%d minuti fa",
+ "other": "%d minuti fa"
+ },
+ "editor.textarea.tab_hint": "Linea già indentata. Premi di nuovo Tab o Esc per uscire dall'editor.",
+ "repo.diff.commit.previous-short": "Precedente",
+ "meta.last_line": "Ambaraba cicci cocco."
}
diff --git a/options/locale_next/locale_ja-JP.json b/options/locale_next/locale_ja-JP.json
index 40edf8cb90..c4b3a0a2e0 100644
--- a/options/locale_next/locale_ja-JP.json
+++ b/options/locale_next/locale_ja-JP.json
@@ -1,5 +1,6 @@
{
"repo.pulls.merged_title_desc": "が %[1]d 個のコミットを %[2]s
から %[3]s
へマージ %[4]s",
"repo.pulls.title_desc": "が %[2]s
から %[3]s
への %[1]d コミットのマージを希望しています",
- "search.milestone_kind": "マイルストーンを検索..."
+ "search.milestone_kind": "マイルストーンを検索...",
+ "moderation.abuse_category.malware": "悪意のコード"
}
diff --git a/options/locale_next/locale_ko-KR.json b/options/locale_next/locale_ko-KR.json
index 98c949d517..2e51144cb7 100644
--- a/options/locale_next/locale_ko-KR.json
+++ b/options/locale_next/locale_ko-KR.json
@@ -1,5 +1,6 @@
{
"repo.pulls.merged_title_desc": "님이 %[2]s
에서 %[3]s
로 %[1]d 커밋을 %[4]s 병합함",
"repo.pulls.title_desc": "%[2]s
에서 %[3]s
로 %[1]d개의 커밋들을 병합하려함",
- "home.welcome.no_activity": "활동 없음"
+ "home.welcome.no_activity": "활동 없음",
+ "moderation.abuse_category.malware": "악성 소프트웨어"
}
diff --git a/options/locale_next/locale_lv-LV.json b/options/locale_next/locale_lv-LV.json
index f71cfa227d..75835bc89c 100644
--- a/options/locale_next/locale_lv-LV.json
+++ b/options/locale_next/locale_lv-LV.json
@@ -105,5 +105,11 @@
"settings.visibility.description": "Profila redzamība ietekmē iespēju citiem piekļūt Tavām glabātavām, kas nav privātas. Uzzināt vairāk",
"avatar.constraints_hint": "Pielāgots profila attēls nevar pārsniegt %[1]s vai būt lielāks par %[2]dx%[3]d pikseļiem",
"repo.diff.commit.next-short": "Nāk.",
- "repo.diff.commit.previous-short": "Iepr."
+ "repo.diff.commit.previous-short": "Iepr.",
+ "profile.actions.tooltip": "Vairāk darbību",
+ "profile.edit.link": "Labot profilu",
+ "feed.atom.link": "Atom barotne",
+ "keys.ssh.link": "SSH atslēgas",
+ "keys.gpg.link": "GPG atslēgas",
+ "mail.actions.run_info_sha": "Iesūtījums: %[1]s"
}
diff --git a/options/locale_next/locale_nb_NO.json b/options/locale_next/locale_nb_NO.json
index 0967ef424b..8f2f9b5e1c 100644
--- a/options/locale_next/locale_nb_NO.json
+++ b/options/locale_next/locale_nb_NO.json
@@ -1 +1,73 @@
-{}
+{
+ "home.welcome.no_activity": "Ingen aktivitet",
+ "home.welcome.activity_hint": "Det er foreløpig ingenting i feeden din. Aktivitetene dine og handlingene dine fra repositorier du følger, vil vises her etter hvert.",
+ "home.explore_repos": "Utforsk repositorier",
+ "home.explore_users": "Utforsk brukere",
+ "home.explore_orgs": "Utforsk organisasjoner",
+ "stars.list.none": "Ingen har gitt stjerner til dette repoet.",
+ "watch.list.none": "Ingen følger dette repoet.",
+ "followers.incoming.list.self.none": "Ingen følger profilen din.",
+ "followers.incoming.list.none": "Ingen følger denne brukeren.",
+ "followers.outgoing.list.self.none": "Du følger ikke noen.",
+ "followers.outgoing.list.none": "%s følger ikke noen.",
+ "relativetime.now": "nå",
+ "relativetime.future": "i fremtiden",
+ "relativetime.1day": "i går",
+ "relativetime.2days": "to dager siden",
+ "relativetime.1week": "forrige uke",
+ "relativetime.2weeks": "to uker siden",
+ "relativetime.1month": "forrige måned",
+ "relativetime.2months": "to måneder siden",
+ "relativetime.1year": "i fjor",
+ "relativetime.2years": "to år siden",
+ "repo.form.cannot_create": "Det maksimale antallet repositories er nådd i alle områdene du har tilgang til.",
+ "repo.issue_indexer.title": "Saksindekserer",
+ "search.milestone_kind": "Søker i milepæler…",
+ "incorrect_root_url": "Denne Forgejo instansen er konfigurert til å bruke \"%s\". Du bruker Forgejo via en annen URL, noe som kan forårsake at deler av applikasjonen ikke fungerer. Den kanoniske URL-en styres av Forgejo-administratorer via innstillingen ROOT_URL i app.ini-filen.",
+ "themes.names.forgejo-auto": "Forgejo (følg systemtema)",
+ "themes.names.forgejo-light": "Forgejo lyst",
+ "themes.names.forgejo-dark": "Forgejo mørk",
+ "error.not_found.title": "Fant ikke siden",
+ "alert.asset_load_failed": "Kunne ikke laste inn ressursfiler fra {path}. Sørg for at ressursfilene er tilgjengelige.",
+ "alert.range_error": " må være et nummer mellom %[1]s og %[2]s.",
+ "install.invalid_lfs_path": "Kan ikke opprette LFS-root på: %[1]s",
+ "profile.actions.tooltip": "Flere handlinger",
+ "profile.edit.link": "Rediger profil",
+ "feed.atom.link": "Atom feed",
+ "keys.ssh.link": "SSH nøkler",
+ "keys.gpg.link": "GPG nøkler",
+ "admin.config.moderation_config": "Moderasjonskonfigurasjon",
+ "moderation.report_abuse": "Rapporter missbruk",
+ "moderation.report_content": "Rapporter innhold",
+ "moderation.report_abuse_form.header": "Rapporter missbruk til en administrator",
+ "moderation.report_abuse_form.details": "Denne formen skal brukes for å rapporterer brukere som oppretter spam profiler, repositorier, saker, kommentarer eller oppfører seg upassende.",
+ "moderation.report_abuse_form.invalid": "Ugyldige argumenter",
+ "moderation.report_abuse_form.already_reported": "Du har allerede rapportert dette innholdet",
+ "moderation.abuse_category": "Kategori",
+ "moderation.abuse_category.placeholder": "Velg en kategori",
+ "moderation.abuse_category.spam": "Spam",
+ "moderation.abuse_category.malware": "Skadelig programvare",
+ "moderation.abuse_category.illegal_content": "Ulovlig innhold",
+ "moderation.abuse_category.other_violations": "Andre regel overtredelser",
+ "moderation.report_remarks": "Kommentar",
+ "moderation.report_remarks.placeholder": "Skriv noen detaljer rundt missbruket du rapporterer.",
+ "moderation.submit_report": "Send rapport",
+ "moderation.reporting_failed": "Missbruk rapporten kunne ikke sendes inn: %v",
+ "moderation.reported_thank_you": "Takk for meldingen. Vi har varslet administratorene.",
+ "mail.actions.successful_run_after_failure_subject": "Arbeidsflyten %[1]s er gjenopprettet i repository %[2]s",
+ "mail.actions.not_successful_run_subject": "Arbeidsflyten %[1]s feilet i repository %[2]s",
+ "mail.actions.successful_run_after_failure": "Arbeidsflyten %[1]s er gjenopprettet i repository %[2]s",
+ "mail.actions.not_successful_run": "Arbeidsflyten %[1]s feilet i repository %[2]s",
+ "mail.actions.run_info_cur_status": "Status for denne kjøringen: %[1]s (oppdatert fra %[2]s)",
+ "mail.actions.run_info_previous_status": "Status for forrige kjøring: %[1]s",
+ "mail.actions.run_info_trigger": "Startet på grunn av: %[1]s by: %[2]s",
+ "repo.diff.commit.next-short": "Neste",
+ "repo.diff.commit.previous-short": "Forrige",
+ "discussion.locked": "Denne diskusjonen er låst. Kommentarer kan kun gjøres av bidragsytere.",
+ "editor.textarea.tab_hint": "Linjen er allerede innrykket. Trykk Tab igjen eller trykk Escape for å gå ut av editoren.",
+ "editor.textarea.shift_tab_hint": "Ingen innrykk på denne linjen. Trykk Shift + Tab igjen eller Escape for å gå ut av editoren.",
+ "admin.dashboard.cleanup_offline_runners": "Rydd opp offline runners",
+ "settings.visibility.description": "Profilens synlighet påvirker andres mulighet til å få tilgang til dine ikke-private repositorier. Les mer",
+ "avatar.constraints_hint": "Egendefinert avatar kan ikke overstige %[1]s i størrelse eller være større enn %[2]d × %[3]d piksler",
+ "meta.last_line": "Vi gir oss ikke. Kongen har sagt nei!"
+}
diff --git a/options/locale_next/locale_nds.json b/options/locale_next/locale_nds.json
index 9a3884a87f..c1769e55e6 100644
--- a/options/locale_next/locale_nds.json
+++ b/options/locale_next/locale_nds.json
@@ -97,5 +97,11 @@
"settings.visibility.description": "De Profil-Sichtbaarkeid maakt daar wat an, of un wo anner Lüü diene nich-privaaten Repositoriums ankieken könen. Mehr unnerhören",
"avatar.constraints_hint": "Dat eegene Kontobill düür nich groter as %[1]s wesen of groter as %[2]d×%[3]d Billtüttels wesen",
"repo.diff.commit.next-short": "Anner",
- "repo.diff.commit.previous-short": "Vörig"
+ "repo.diff.commit.previous-short": "Vörig",
+ "feed.atom.link": "Atom-Schuuv",
+ "keys.ssh.link": "SSH-Slötels",
+ "keys.gpg.link": "GPG-Slötels",
+ "profile.actions.tooltip": "Mehr Aktioonen",
+ "profile.edit.link": "Profil bewarken",
+ "mail.actions.run_info_sha": "Kommitteren: %[1]s"
}
diff --git a/options/locale_next/locale_nl-NL.json b/options/locale_next/locale_nl-NL.json
index 4f109825aa..5c9c8a9b07 100644
--- a/options/locale_next/locale_nl-NL.json
+++ b/options/locale_next/locale_nl-NL.json
@@ -92,5 +92,16 @@
"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."
+ "followers.outgoing.list.self.none": "U volgt niemand.",
+ "profile.actions.tooltip": "Meer acties",
+ "profile.edit.link": "Profiel bewerken",
+ "feed.atom.link": "Atom-feed",
+ "keys.ssh.link": "SSH sleutels",
+ "keys.gpg.link": "GPG sleutels",
+ "repo.diff.commit.next-short": "Volgende",
+ "repo.diff.commit.previous-short": "Vorige",
+ "admin.dashboard.cleanup_offline_runners": "Offline runners opruimen",
+ "settings.visibility.description": "Profielzichtbaarheid beïnvloedt de mogelijkheid van anderen om toegang te krijgen tot je niet-privé repositories. Lees meer",
+ "avatar.constraints_hint": "Eigen avatars mogen niet groter zijn dan %[1]s in grootte of groter zijn dan %[2]dx%[3]d pixels",
+ "mail.actions.run_info_sha": "Commit: %[1]s"
}
diff --git a/options/locale_next/locale_pt-BR.json b/options/locale_next/locale_pt-BR.json
index 92e140878e..0fc65a7dd6 100644
--- a/options/locale_next/locale_pt-BR.json
+++ b/options/locale_next/locale_pt-BR.json
@@ -83,7 +83,7 @@
"moderation.abuse_category": "Categoria",
"moderation.abuse_category.placeholder": "Selecione uma categoria",
"moderation.abuse_category.spam": "Spam",
- "moderation.abuse_category.malware": "Malware",
+ "moderation.abuse_category.malware": "Software malicioso",
"moderation.abuse_category.illegal_content": "Conteúdo ilegal",
"moderation.abuse_category.other_violations": "Outras violações de regras da plataforma",
"moderation.report_remarks": "Observações",
@@ -103,5 +103,13 @@
"editor.textarea.shift_tab_hint": "Sem indentação nesta linha. Pressione Shift + Tab novamente ou Esc para sair do editor.",
"admin.dashboard.cleanup_offline_runners": "Limpar runners desconectados",
"avatar.constraints_hint": "Imagem de perfil personalizada não pode exceder %[1]s em tamanho ou ser maior que %[2]dx%[3]d pixels",
- "settings.visibility.description": "A visibilidade do perfil afeta a habilidade de acessarem seus repositórios não-privados. Saiba mais"
+ "settings.visibility.description": "A visibilidade do perfil afeta a habilidade de acessarem seus repositórios não-privados. Saiba mais",
+ "repo.diff.commit.next-short": "Próximo",
+ "repo.diff.commit.previous-short": "Anterior",
+ "profile.actions.tooltip": "Mais Actions",
+ "profile.edit.link": "Editar perfil",
+ "feed.atom.link": "Feed Atom",
+ "keys.ssh.link": "Chaves SSH",
+ "keys.gpg.link": "Chaves GPG",
+ "mail.actions.run_info_sha": "Commit: %[1]s"
}
diff --git a/options/locale_next/locale_pt-PT.json b/options/locale_next/locale_pt-PT.json
index 78e6dc4493..5d68db624b 100644
--- a/options/locale_next/locale_pt-PT.json
+++ b/options/locale_next/locale_pt-PT.json
@@ -84,7 +84,7 @@
"moderation.abuse_category": "Categoria",
"moderation.abuse_category.placeholder": "Escolha uma categoria",
"moderation.abuse_category.spam": "Spam",
- "moderation.abuse_category.malware": "Malware",
+ "moderation.abuse_category.malware": "Software malicioso",
"moderation.abuse_category.illegal_content": "Conteúdo ilegal",
"moderation.abuse_category.other_violations": "Outras violações das regras da plataforma",
"moderation.report_remarks": "Observações",
@@ -103,5 +103,13 @@
"stars.list.none": "Ninguém juntou este repositório aos favoritos.",
"admin.dashboard.cleanup_offline_runners": "Limpeza de executores offline",
"settings.visibility.description": "A visibilidade do perfil afecta a capacidade de outros acederem aos seus repositórios não privados. Ler mais",
- "avatar.constraints_hint": "O avatar personalizado não pode exceder %[1]s de tamanho ou ser maior do que %[2]dx%[3]d pixéis"
+ "avatar.constraints_hint": "O avatar personalizado não pode exceder %[1]s de tamanho ou ser maior do que %[2]dx%[3]d pixéis",
+ "profile.actions.tooltip": "Mais Actions",
+ "profile.edit.link": "Editar perfil",
+ "feed.atom.link": "Feed Atom",
+ "keys.ssh.link": "Chaves SSH",
+ "keys.gpg.link": "Chaves GPG",
+ "repo.diff.commit.next-short": "Seg.",
+ "repo.diff.commit.previous-short": "Ant.",
+ "mail.actions.run_info_sha": "Cometimento: %[1]s"
}
diff --git a/options/locale_next/locale_ru-RU.json b/options/locale_next/locale_ru-RU.json
index 8992cc6abd..e49eb79ca2 100644
--- a/options/locale_next/locale_ru-RU.json
+++ b/options/locale_next/locale_ru-RU.json
@@ -23,7 +23,7 @@
"alert.asset_load_failed": "Не удалось получить ресурсы из {path}. Убедитесь, что файлы ресурсов доступны.",
"install.invalid_lfs_path": "Не удалось расположить корень LFS по указанному пути: %[1]s",
"alert.range_error": " - число должно быть в диапазоне от %[1]s-%[2]s.",
- "meta.last_line": "Unskip.",
+ "meta.last_line": "...ъъ",
"mail.actions.not_successful_run_subject": "Провал раб. потока %[1]s в репозитории %[2]s",
"mail.actions.successful_run_after_failure_subject": "Возобновление раб. потока %[1]s в репозитории %[2]s",
"mail.actions.run_info_ref": "Ветвь: %[1]s (%[2]s)",
@@ -104,6 +104,12 @@
"admin.dashboard.cleanup_offline_runners": "Удалить недоступных исполнителей",
"avatar.constraints_hint": "Изображение профиля не может быть более %[1]s и крупнее %[2]dx%[3]d пикселей",
"settings.visibility.description": "Видимость профиля влияет на доступ других до ваших не частных репозиториев. Подробнее",
- "repo.diff.commit.previous-short": "Предыдущий",
- "repo.diff.commit.next-short": "Далее"
+ "repo.diff.commit.previous-short": "Пред.",
+ "repo.diff.commit.next-short": "След.",
+ "profile.actions.tooltip": "Показать действия",
+ "feed.atom.link": "Atom-лента",
+ "keys.ssh.link": "Ключи SSH",
+ "keys.gpg.link": "Ключи GPG",
+ "profile.edit.link": "Изменить профиль",
+ "mail.actions.run_info_sha": "Коммит: %[1]s"
}
diff --git a/options/locale_next/locale_sr-SP.json b/options/locale_next/locale_sr-SP.json
index 0967ef424b..611f997b3e 100644
--- a/options/locale_next/locale_sr-SP.json
+++ b/options/locale_next/locale_sr-SP.json
@@ -1 +1,3 @@
-{}
+{
+ "moderation.abuse_category.malware": "Малвер"
+}
diff --git a/options/locale_next/locale_sv-SE.json b/options/locale_next/locale_sv-SE.json
index 9a8762212c..c8c50baa76 100644
--- a/options/locale_next/locale_sv-SE.json
+++ b/options/locale_next/locale_sv-SE.json
@@ -95,5 +95,12 @@
"moderation.abuse_category.spam": "Skräppost",
"moderation.abuse_category.malware": "Skadlig kod",
"settings.visibility.description": "Profilens synlighet påverkar andras möjlighet att komma åt dina icke-privata förråd. Läs mer",
- "avatar.constraints_hint": "Anpassade avatarer får inte vara större än %[1] eller %[2]dx%[3] bildpunkter"
+ "avatar.constraints_hint": "Anpassade avatarer får inte vara större än %[1] eller %[2]dx%[3] bildpunkter",
+ "profile.actions.tooltip": "Fler åtgärder",
+ "profile.edit.link": "Redigera profil",
+ "feed.atom.link": "Atom-flöde",
+ "keys.ssh.link": "SSH-nycklar",
+ "keys.gpg.link": "GPG-nycklar",
+ "repo.diff.commit.next-short": "Nästa",
+ "repo.diff.commit.previous-short": "Föreg"
}
diff --git a/options/locale_next/locale_tr-TR.json b/options/locale_next/locale_tr-TR.json
index b0e34e677f..fa71cb8e7d 100644
--- a/options/locale_next/locale_tr-TR.json
+++ b/options/locale_next/locale_tr-TR.json
@@ -1,5 +1,6 @@
{
"repo.pulls.merged_title_desc": "%[4]s %[2]s
içindeki %[1]d işlemeyi %[3]s
ile birleştirdi",
"repo.pulls.title_desc": "%[2]s
içindeki %[1]d işlemeyi %[3]s
ile birleştirmek istiyor",
- "search.milestone_kind": "Kilometre taşlarını ara..."
+ "search.milestone_kind": "Kilometre taşlarını ara...",
+ "moderation.abuse_category.malware": "Malware"
}
diff --git a/options/locale_next/locale_uk-UA.json b/options/locale_next/locale_uk-UA.json
index c3bcf5397c..81b69ec859 100644
--- a/options/locale_next/locale_uk-UA.json
+++ b/options/locale_next/locale_uk-UA.json
@@ -105,5 +105,11 @@
"settings.visibility.description": "Видимість профілю впливає на можливість інших користувачів отримати доступ до ваших неприватних репозиторіїв. Дізнатися більше",
"avatar.constraints_hint": "Розмір користувацького аватара не може перевищувати %[1]s або бути більшим за %[2]d×%[3]d пікселів",
"repo.diff.commit.next-short": "Наступний",
- "repo.diff.commit.previous-short": "Попередній"
+ "repo.diff.commit.previous-short": "Попередній",
+ "keys.ssh.link": "Ключі SSH",
+ "keys.gpg.link": "Ключі GPG",
+ "profile.edit.link": "Редагувати профіль",
+ "feed.atom.link": "Стрічка Atom",
+ "profile.actions.tooltip": "Більше дій",
+ "mail.actions.run_info_sha": "Коміт: %[1]s"
}
diff --git a/options/locale_next/locale_vi.json b/options/locale_next/locale_vi.json
index 0967ef424b..7ae64113b6 100644
--- a/options/locale_next/locale_vi.json
+++ b/options/locale_next/locale_vi.json
@@ -1 +1,3 @@
-{}
+{
+ "moderation.abuse_category.malware": "Phần mềm ác ý"
+}
diff --git a/options/locale_next/locale_zh-CN.json b/options/locale_next/locale_zh-CN.json
index e7c1bad81e..743cced8c1 100644
--- a/options/locale_next/locale_zh-CN.json
+++ b/options/locale_next/locale_zh-CN.json
@@ -71,5 +71,13 @@
"editor.textarea.shift_tab_hint": "此行无缩进。再次按 Shift + Tab 或按 Escape 退出编辑器。",
"admin.dashboard.cleanup_offline_runners": "清理离线运行器",
"settings.visibility.description": "个人资料可见性设置会影响他人对您的非私有仓库的访问。了解更多",
- "avatar.constraints_hint": "自定义头像大小不得超过 %[1]s,或大于 %[2]d×%[3]d 像素"
+ "avatar.constraints_hint": "自定义头像大小不得超过 %[1]s,且分辨率不得大于 %[2]d×%[3]d 像素",
+ "keys.ssh.link": "SSH 密钥",
+ "keys.gpg.link": "GPG 密钥",
+ "profile.actions.tooltip": "更多操作",
+ "repo.diff.commit.next-short": "下一个",
+ "repo.diff.commit.previous-short": "上一个",
+ "feed.atom.link": "Atom 订阅源",
+ "profile.edit.link": "编辑个人资料",
+ "mail.actions.run_info_sha": "提交:%[1]s"
}
diff --git a/options/locale_next/locale_zh-HK.json b/options/locale_next/locale_zh-HK.json
index 6baf89e022..7d624f24df 100644
--- a/options/locale_next/locale_zh-HK.json
+++ b/options/locale_next/locale_zh-HK.json
@@ -1,5 +1,6 @@
{
- "repo.pulls.merged_title_desc": {
- "other": "於 %[4]s 將 %[1]d 次代碼提交從 %[2]s
合併至 %[3]s
"
- }
+ "repo.pulls.merged_title_desc": {
+ "other": "於 %[4]s 將 %[1]d 次代碼提交從 %[2]s
合併至 %[3]s
"
+ },
+ "moderation.abuse_category.malware": "惡意程式"
}
diff --git a/options/locale_next/locale_zh-TW.json b/options/locale_next/locale_zh-TW.json
index 5e3e43f66e..3ae0b00d2b 100644
--- a/options/locale_next/locale_zh-TW.json
+++ b/options/locale_next/locale_zh-TW.json
@@ -68,5 +68,10 @@
"moderation.report_abuse_form.details": "這個表單是用來檢舉用戶建立垃圾帳號、儲存庫、問題、留言,或其他不當行為。",
"moderation.report_abuse_form.invalid": "無效參數",
"moderation.report_abuse_form.already_reported": "您已檢舉此內容",
- "meta.last_line": "Rubi-chan? Hai! Nani ga suki? Choko minto yori mo a・na・ta♡ Ayumu-chan? Hai! Nani ga suki? Sutoroberii fureibaa yori mo a・na・ta♡ Shiki-chan! Hai! Nani ga suki? Kukkii and kuriimu yori mo a・na・ta♡ Minna? Hai! Nani ga suki? Mochiron daisuki AiScReam."
+ "meta.last_line": "Rubi-chan? Hai! Nani ga suki? Choko minto yori mo a・na・ta♡ Ayumu-chan? Hai! Nani ga suki? Sutoroberii fureibaa yori mo a・na・ta♡ Shiki-chan! Hai! Nani ga suki? Kukkii and kuriimu yori mo a・na・ta♡ Minna? Hai! Nani ga suki? Mochiron daisuki AiScReam.",
+ "admin.dashboard.cleanup_offline_runners": "清理離線 runners",
+ "settings.visibility.description": "個人資料的可見度會影響他人存取您非私人儲存庫的能力。了解更多",
+ "avatar.constraints_hint": "自定義大頭貼的大小不得超過 %[1]s,且解析度不得大於 %[2]d×%[3]d 像素",
+ "repo.diff.commit.next-short": "下一個",
+ "repo.diff.commit.previous-short": "上一個"
}
diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go
index 79e61cf352..721f96b768 100644
--- a/routers/api/packages/api.go
+++ b/routers/api/packages/api.go
@@ -117,7 +117,7 @@ func verifyAuth(r *web.Route, authMethods []auth.Method) {
var err error
ctx.Doer, err = authGroup.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
if err != nil {
- log.Error("Failed to verify user: %v", err)
+ log.Info("Failed to verify user: %v", err)
ctx.Error(http.StatusUnauthorized, "authGroup.Verify")
return
}
@@ -631,7 +631,7 @@ func CommonRoutes() *web.Route {
baseURLPattern = regexp.MustCompile(`\A(.*?)\.repo\z`)
uploadPattern = regexp.MustCompile(`\A(.*?)/upload\z`)
baseRepoPattern = regexp.MustCompile(`(\S+)\.repo/(\S+)\/base/(\S+)`)
- rpmsRepoPattern = regexp.MustCompile(`(\S+)\.repo/(\S+)\.(\S+)\/([a-zA-Z0-9_-]+)-([\d.]+-[a-zA-Z0-9_-]+)\.(\S+)\.rpm`)
+ rpmsRepoPattern = regexp.MustCompile(`(\S+)\.repo/(\S+)\.(\S+)\/([a-zA-Z0-9_-]+)-([\d.]+-[a-zA-Z0-9_.-]+)\.(\S+)\.rpm`)
)
r.Methods("HEAD,GET,PUT,DELETE", "*", func(ctx *context.Context) {
diff --git a/routers/api/packages/container/container.go b/routers/api/packages/container/container.go
index 191a4aa455..9a7fd03aa8 100644
--- a/routers/api/packages/container/container.go
+++ b/routers/api/packages/container/container.go
@@ -399,12 +399,7 @@ func EndUploadBlob(ctx *context.Context) {
}
return
}
- doClose := true
- defer func() {
- if doClose {
- uploader.Close()
- }
- }()
+ defer uploader.Close()
if ctx.Req.Body != nil {
if err := uploader.Append(ctx, ctx.Req.Body); err != nil {
@@ -437,11 +432,10 @@ func EndUploadBlob(ctx *context.Context) {
return
}
- if err := uploader.Close(); err != nil {
- apiError(ctx, http.StatusInternalServerError, err)
- return
- }
- doClose = false
+ // There was a strange bug: the "Close" fails with error "close .../tmp/package-upload/....: file already closed"
+ // AFAIK there should be no other "Close" call to the uploader between NewBlobUploader and this line.
+ // At least it's safe to call Close twice, so ignore the error.
+ _ = uploader.Close()
if err := container_service.RemoveBlobUploadByID(ctx, uploader.ID); err != nil {
apiError(ctx, http.StatusInternalServerError, err)
diff --git a/routers/api/packages/helper/helper.go b/routers/api/packages/helper/helper.go
index f9b91d9a09..47d1f18623 100644
--- a/routers/api/packages/helper/helper.go
+++ b/routers/api/packages/helper/helper.go
@@ -25,7 +25,8 @@ func LogAndProcessError(ctx *context.Context, status int, obj any, cb func(strin
message = fmt.Sprintf("%s", obj)
}
if status == http.StatusInternalServerError {
- log.ErrorWithSkip(1, message)
+ // LogAndProcessError is always wrapped in a `apiError` call, so we need to skip two frames
+ log.ErrorWithSkip(2, message)
if setting.IsProd && (ctx.Doer == nil || !ctx.Doer.IsAdmin) {
message = ""
diff --git a/routers/api/shared/middleware.go b/routers/api/shared/middleware.go
index 7d537f1ef9..f56acbe1bf 100644
--- a/routers/api/shared/middleware.go
+++ b/routers/api/shared/middleware.go
@@ -30,6 +30,7 @@ func Middlewares() (stack []any) {
return append(stack,
context.APIContexter(),
+ checkDeprecatedAuthMethods,
// Get user from session if logged in.
apiAuth(buildAuthGroup()),
verifyAuthWithOptions(&common.VerifyOptions{
@@ -126,6 +127,13 @@ func verifyAuthWithOptions(options *common.VerifyOptions) func(ctx *context.APIC
}
}
+// check for and warn against deprecated authentication options
+func checkDeprecatedAuthMethods(ctx *context.APIContext) {
+ if ctx.FormString("token") != "" || ctx.FormString("access_token") != "" {
+ ctx.Resp.Header().Set("Warning", "token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization.")
+ }
+}
+
func securityHeaders() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index bf08bdd249..95c3ee4791 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -22,6 +22,8 @@
//
// Security:
// - BasicAuth :
+// - Token :
+// - AccessToken :
// - AuthorizationHeaderToken :
// - SudoParam :
// - SudoHeader :
@@ -30,6 +32,16 @@
// SecurityDefinitions:
// BasicAuth:
// type: basic
+// Token:
+// type: apiKey
+// name: token
+// in: query
+// description: This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.
+// AccessToken:
+// type: apiKey
+// name: access_token
+// in: query
+// description: This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.
// AuthorizationHeaderToken:
// type: apiKey
// name: Authorization
diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go
index 9c941ea07f..7fc59ea171 100644
--- a/routers/api/v1/repo/compare.go
+++ b/routers/api/v1/repo/compare.go
@@ -64,7 +64,7 @@ func CompareDiff(ctx *context.APIContext) {
}
}
- _, headGitRepo, ci, _, _ := parseCompareInfo(ctx, api.CreatePullRequestOption{
+ headRepository, headGitRepo, ci, _, _ := parseCompareInfo(ctx, api.CreatePullRequestOption{
Base: infos[0],
Head: infos[1],
})
@@ -80,7 +80,7 @@ func CompareDiff(ctx *context.APIContext) {
apiFiles := []*api.CommitAffectedFiles{}
userCache := make(map[string]*user_model.User)
for i := 0; i < len(ci.Commits); i++ {
- apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, ci.Commits[i], userCache,
+ apiCommit, err := convert.ToCommit(ctx, headRepository, headGitRepo, ci.Commits[i], userCache,
convert.ToCommitOptions{
Stat: true,
Verification: verification,
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index c9dda124de..9360ff1335 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -1125,7 +1125,6 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
}
}
- // Check if current user has fork of repository or in the same repository.
headRepo := repo_model.GetForkedRepo(ctx, headUser.ID, baseRepo.ID)
if headRepo == nil && !isSameRepo {
err := baseRepo.GetBaseRepo(ctx)
@@ -1134,13 +1133,11 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
return nil, nil, nil, "", ""
}
- // Check if baseRepo's base repository is the same as headUser's repository.
if baseRepo.BaseRepo == nil || baseRepo.BaseRepo.OwnerID != headUser.ID {
log.Trace("parseCompareInfo[%d]: does not have fork or in same repository", baseRepo.ID)
ctx.NotFound("GetBaseRepo")
return nil, nil, nil, "", ""
}
- // Assign headRepo so it can be used below.
headRepo = baseRepo.BaseRepo
}
@@ -1202,9 +1199,9 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
}
// Check if head branch is valid.
- headIsCommit := ctx.Repo.GitRepo.IsCommitExist(headBranch)
- headIsBranch := ctx.Repo.GitRepo.IsBranchExist(headBranch)
- headIsTag := ctx.Repo.GitRepo.IsTagExist(headBranch)
+ headIsCommit := headGitRepo.IsCommitExist(headBranch)
+ headIsBranch := headGitRepo.IsBranchExist(headBranch)
+ headIsTag := headGitRepo.IsTagExist(headBranch)
if !headIsCommit && !headIsBranch && !headIsTag {
// Check if headBranch is short sha commit hash
if headCommit, _ := headGitRepo.GetCommit(headBranch); headCommit != nil {
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 3d6a40e9ab..42385d54a6 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -861,7 +861,7 @@ func updateRepoUnits(ctx *context.APIContext, owner string, repo *repo_model.Rep
if *opts.GloballyEditableWiki {
wikiPermissions = repo_model.UnitAccessModeWrite
} else {
- wikiPermissions = repo_model.UnitAccessModeRead
+ wikiPermissions = repo_model.UnitAccessModeUnset
}
}
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index c83242754b..9b4e01597b 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -71,6 +71,9 @@ func SettingsPost(ctx *context.Context) {
ctx.Data["PageIsSettingsOptions"] = true
ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
ctx.Data["CooldownPeriod"] = setting.Service.UsernameCooldownPeriod
+ ctx.Data["MaxAvatarFileSize"] = setting.Avatar.MaxFileSize
+ ctx.Data["MaxAvatarWidth"] = setting.Avatar.MaxWidth
+ ctx.Data["MaxAvatarHeight"] = setting.Avatar.MaxHeight
if ctx.HasError() {
ctx.HTML(http.StatusOK, tplSettingsOptions)
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index de2e29ab9f..e3020c92d2 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -933,25 +933,29 @@ func ExcerptBlob(ctx *context.Context) {
ctx.Error(http.StatusInternalServerError, "getExcerptLines")
return
}
- if idxRight > lastRight {
+
+ // After the "up" or "down" expansion, check if there's any remaining content in the diff and add a line that will
+ // be rendered into a new expander at either the top, or bottom.
+ lineSection := &gitdiff.DiffLine{
+ Type: gitdiff.DiffLineSection,
+ SectionInfo: &gitdiff.DiffLineSectionInfo{
+ Path: filePath,
+ LastLeftIdx: lastLeft,
+ LastRightIdx: lastRight,
+ LeftIdx: idxLeft,
+ RightIdx: idxRight,
+ LeftHunkSize: leftHunkSize,
+ RightHunkSize: rightHunkSize,
+ },
+ }
+ if lineSection.GetExpandDirection() != gitdiff.DiffLineExpandNone {
lineText := " "
if rightHunkSize > 0 || leftHunkSize > 0 {
lineText = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize)
}
lineText = html.EscapeString(lineText)
- lineSection := &gitdiff.DiffLine{
- Type: gitdiff.DiffLineSection,
- Content: lineText,
- SectionInfo: &gitdiff.DiffLineSectionInfo{
- Path: filePath,
- LastLeftIdx: lastLeft,
- LastRightIdx: lastRight,
- LeftIdx: idxLeft,
- RightIdx: idxRight,
- LeftHunkSize: leftHunkSize,
- RightHunkSize: rightHunkSize,
- },
- }
+ lineSection.Content = lineText
+
switch direction {
case "up":
section.Lines = append([]*gitdiff.DiffLine{lineSection}, section.Lines...)
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index 5e228507c0..ef4589c8e6 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -3592,9 +3592,9 @@ func GetIssueAttachments(ctx *context.Context) {
if ctx.Written() {
return
}
- attachments := make([]*api.Attachment, len(issue.Attachments))
+ attachments := make([]*api.WebAttachment, len(issue.Attachments))
for i := 0; i < len(issue.Attachments); i++ {
- attachments[i] = convert.ToAttachment(ctx.Repo.Repository, issue.Attachments[i])
+ attachments[i] = convert.ToWebAttachment(ctx.Repo.Repository, issue.Attachments[i])
}
ctx.JSON(http.StatusOK, attachments)
}
@@ -3627,13 +3627,13 @@ func GetCommentAttachments(ctx *context.Context) {
return
}
- attachments := make([]*api.Attachment, 0)
if err := comment.LoadAttachments(ctx); err != nil {
ctx.ServerError("LoadAttachments", err)
return
}
+ attachments := make([]*api.WebAttachment, len(comment.Attachments))
for i := 0; i < len(comment.Attachments); i++ {
- attachments = append(attachments, convert.ToAttachment(ctx.Repo.Repository, comment.Attachments[i]))
+ attachments[i] = convert.ToWebAttachment(ctx.Repo.Repository, comment.Attachments[i])
}
ctx.JSON(http.StatusOK, attachments)
}
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index fd18646211..4e365f24ea 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -996,6 +996,13 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
ctx.Data["Verification"] = verification
ctx.Data["Author"] = user_model.ValidateCommitWithEmail(ctx, curCommit)
+ if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
+ return repo_model.IsOwnerMemberCollaborator(ctx, ctx.Repo.Repository, user.ID)
+ }, nil); err != nil {
+ ctx.ServerError("CalculateTrustStatus", err)
+ return
+ }
+
note := &git.Note{}
err = git.GetNote(ctx, ctx.Repo.GitRepo, specifiedEndCommit, note)
if err == nil {
diff --git a/routers/web/web.go b/routers/web/web.go
index 4b39f22f7d..6cca2a9f2e 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -117,7 +117,7 @@ func webAuth(authMethod auth_service.Method) func(*context.Context) {
return func(ctx *context.Context) {
ar, err := common.AuthShared(ctx.Base, ctx.Session, authMethod)
if err != nil {
- log.Error("Failed to verify user: %v", err)
+ log.Info("Failed to verify user: %v", err)
ctx.Error(http.StatusUnauthorized, ctx.Locale.TrString("auth.unauthorized_credentials", "https://codeberg.org/forgejo/forgejo/issues/2809"))
return
}
diff --git a/services/actions/notifier.go b/services/actions/notifier.go
index f1e9a6d7e9..a5bac730be 100644
--- a/services/actions/notifier.go
+++ b/services/actions/notifier.go
@@ -788,7 +788,7 @@ func (n *actionsNotifier) MigrateRepository(ctx context.Context, doer, u *user_m
// the ActionRun of the same workflow that finished before priorRun/updatedRun.
func sendActionRunNowDoneNotificationIfNeeded(ctx context.Context, priorRun, updatedRun *actions_model.ActionRun) error {
if !priorRun.Status.IsDone() && updatedRun.Status.IsDone() {
- lastRun, err := actions_model.GetRunBefore(ctx, updatedRun.RepoID, updatedRun.Stopped)
+ lastRun, err := actions_model.GetRunBefore(ctx, updatedRun)
if err != nil && !errors.Is(err, util.ErrNotExist) {
return err
}
diff --git a/services/agit/agit.go b/services/agit/agit.go
index 20e87642c3..8ef641629a 100644
--- a/services/agit/agit.go
+++ b/services/agit/agit.go
@@ -221,7 +221,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
}
// Validate pull request.
- pull_service.ValidatePullRequest(ctx, pr, oldCommitID, opts.NewCommitIDs[i], pusher)
+ pull_service.ValidatePullRequest(ctx, pr, opts.NewCommitIDs[i], oldCommitID, pusher)
// TODO: call `InvalidateCodeComments`
diff --git a/services/auth/oauth2.go b/services/auth/oauth2.go
index 093940aa18..fa13c20a7f 100644
--- a/services/auth/oauth2.go
+++ b/services/auth/oauth2.go
@@ -17,6 +17,7 @@ import (
"forgejo.org/modules/log"
"forgejo.org/modules/setting"
"forgejo.org/modules/timeutil"
+ "forgejo.org/modules/util"
"forgejo.org/modules/web/middleware"
"forgejo.org/services/actions"
"forgejo.org/services/auth/source/oauth2"
@@ -121,11 +122,23 @@ func (o *OAuth2) Name() string {
// representing whether the token exists or not
func parseToken(req *http.Request) (string, bool) {
_ = req.ParseForm()
+ if !setting.DisableQueryAuthToken {
+ // Check token.
+ if token := req.Form.Get("token"); token != "" {
+ return token, true
+ }
+ // Check access token.
+ if token := req.Form.Get("access_token"); token != "" {
+ return token, true
+ }
+ } else if req.Form.Get("token") != "" || req.Form.Get("access_token") != "" {
+ log.Warn("API token sent in query string but DISABLE_QUERY_AUTH_TOKEN=true")
+ }
// check header token
if auHead := req.Header.Get("Authorization"); auHead != "" {
auths := strings.Fields(auHead)
- if len(auths) == 2 && (auths[0] == "token" || strings.ToLower(auths[0]) == "bearer") {
+ if len(auths) == 2 && (util.ASCIIEqualFold(auths[0], "token") || util.ASCIIEqualFold(auths[0], "bearer")) {
return auths[1], true
}
}
diff --git a/services/auth/oauth2_test.go b/services/auth/oauth2_test.go
index d6455b33ad..3fce7df50b 100644
--- a/services/auth/oauth2_test.go
+++ b/services/auth/oauth2_test.go
@@ -4,6 +4,7 @@
package auth
import (
+ "net/http"
"testing"
"forgejo.org/models/unittest"
@@ -52,3 +53,30 @@ func TestCheckTaskIsRunning(t *testing.T) {
})
}
}
+
+func TestParseToken(t *testing.T) {
+ cases := map[string]struct {
+ Header string
+ ExpectedToken string
+ Expected bool
+ }{
+ "Token Uppercase": {Header: "Token 1234567890123456789012345687901325467890", ExpectedToken: "1234567890123456789012345687901325467890", Expected: true},
+ "Token Lowercase": {Header: "token 1234567890123456789012345687901325467890", ExpectedToken: "1234567890123456789012345687901325467890", Expected: true},
+ "Token Unicode": {Header: "to\u212Aen 1234567890123456789012345687901325467890", ExpectedToken: "", Expected: false},
+ "Bearer Uppercase": {Header: "Bearer 1234567890123456789012345687901325467890", ExpectedToken: "1234567890123456789012345687901325467890", Expected: true},
+ "Bearer Lowercase": {Header: "bearer 1234567890123456789012345687901325467890", ExpectedToken: "1234567890123456789012345687901325467890", Expected: true},
+ "Missing type": {Header: "1234567890123456789012345687901325467890", ExpectedToken: "", Expected: false},
+ "Three Parts": {Header: "abc 1234567890 test", ExpectedToken: "", Expected: false},
+ }
+
+ for name := range cases {
+ c := cases[name]
+ t.Run(name, func(t *testing.T) {
+ req, _ := http.NewRequest("GET", "/", nil)
+ req.Header.Add("Authorization", c.Header)
+ ActualToken, ActualSuccess := parseToken(req)
+ assert.Equal(t, c.ExpectedToken, ActualToken)
+ assert.Equal(t, c.Expected, ActualSuccess)
+ })
+ }
+}
diff --git a/services/convert/attachment.go b/services/convert/attachment.go
index 6617aac906..74ae7c509c 100644
--- a/services/convert/attachment.go
+++ b/services/convert/attachment.go
@@ -4,6 +4,9 @@
package convert
import (
+ "mime"
+ "path/filepath"
+
repo_model "forgejo.org/models/repo"
api "forgejo.org/modules/structs"
)
@@ -20,9 +23,13 @@ func APIAssetDownloadURL(repo *repo_model.Repository, attach *repo_model.Attachm
return attach.DownloadURL()
}
-// ToAttachment converts models.Attachment to api.Attachment for API usage
-func ToAttachment(repo *repo_model.Repository, a *repo_model.Attachment) *api.Attachment {
- return toAttachment(repo, a, WebAssetDownloadURL)
+// ToWebAttachment converts models.Attachment to api.WebAttachment for API usage
+func ToWebAttachment(repo *repo_model.Repository, a *repo_model.Attachment) *api.WebAttachment {
+ attachment := toAttachment(repo, a, WebAssetDownloadURL)
+ return &api.WebAttachment{
+ Attachment: attachment,
+ MimeType: mime.TypeByExtension(filepath.Ext(attachment.Name)),
+ }
}
// ToAPIAttachment converts models.Attachment to api.Attachment for API usage
diff --git a/services/convert/attachment_test.go b/services/convert/attachment_test.go
new file mode 100644
index 0000000000..d7bf0c1ee7
--- /dev/null
+++ b/services/convert/attachment_test.go
@@ -0,0 +1,56 @@
+// Copyright 2025 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package convert
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ repo_model "forgejo.org/models/repo"
+ "forgejo.org/models/unittest"
+ "forgejo.org/modules/setting"
+ api "forgejo.org/modules/structs"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestToWebAttachment(t *testing.T) {
+ require.NoError(t, unittest.PrepareTestDatabase())
+ headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ attachment := &repo_model.Attachment{
+ ID: 10,
+ UUID: "uuidxxx",
+ RepoID: 1,
+ IssueID: 1,
+ ReleaseID: 0,
+ UploaderID: 0,
+ CommentID: 0,
+ Name: "test.png",
+ DownloadCount: 90,
+ Size: 30,
+ NoAutoTime: false,
+ CreatedUnix: 9342,
+ CustomDownloadURL: "",
+ ExternalURL: "",
+ }
+
+ webAttachment := ToWebAttachment(headRepo, attachment)
+
+ assert.NotNil(t, webAttachment)
+ assert.Equal(t, &api.WebAttachment{
+ Attachment: &api.Attachment{
+ ID: 10,
+ Name: "test.png",
+ Created: time.Unix(9342, 0),
+ DownloadCount: 90,
+ Size: 30,
+ UUID: "uuidxxx",
+ DownloadURL: fmt.Sprintf("%sattachments/uuidxxx", setting.AppURL),
+ Type: "attachment",
+ },
+ MimeType: "image/png",
+ }, webAttachment)
+}
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 989f69d4f4..35f8cd3821 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -85,11 +85,20 @@ type DiffLine struct {
// DiffLineSectionInfo represents diff line section meta data
type DiffLineSectionInfo struct {
- Path string
- LastLeftIdx int
- LastRightIdx int
- LeftIdx int
- RightIdx int
+ Path string
+
+ // Last(Left/Right)Idx do not directly relate to this diff section, but indicate the last line number in the
+ // previous diff section. Set to 0 for the first diff section of a file, and 1 for the first line of code in the
+ // file.
+ LastLeftIdx int
+ LastRightIdx int
+
+ // (Left/Right)Idx are the first line number in this diff section
+ LeftIdx int
+ RightIdx int
+
+ // Number of lines contained within each diff section. In the UI, these fields are set to 0 in cases where a
+ // section is being used as a placeholder at the end of a diff to allow expansion into the remainder of the file.
LeftHunkSize int
RightHunkSize int
}
@@ -157,7 +166,7 @@ func (d *DiffLine) GetExpandDirection() DiffLineExpandDirection {
}
if d.SectionInfo.LastLeftIdx <= 0 && d.SectionInfo.LastRightIdx <= 0 {
return DiffLineExpandUp
- } else if d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx > BlobExcerptChunkSize && d.SectionInfo.RightHunkSize > 0 {
+ } else if d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx-1 > BlobExcerptChunkSize && d.SectionInfo.RightHunkSize > 0 {
return DiffLineExpandUpDown
} else if d.SectionInfo.LeftHunkSize <= 0 && d.SectionInfo.RightHunkSize <= 0 {
return DiffLineExpandDown
diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go
index 3d3c8432c4..9354abd656 100644
--- a/services/gitdiff/gitdiff_test.go
+++ b/services/gitdiff/gitdiff_test.go
@@ -715,6 +715,163 @@ func TestGetDiffFull(t *testing.T) {
})
}
+func TestDiffLine_GetExpandDirection(t *testing.T) {
+ tests := []struct {
+ name string
+ diffLine *DiffLine
+ expectedResult DiffLineExpandDirection
+ }{
+ {
+ name: "non-section line - no expansion",
+ diffLine: &DiffLine{
+ Type: DiffLineAdd,
+ SectionInfo: &DiffLineSectionInfo{},
+ },
+ expectedResult: DiffLineExpandNone,
+ },
+ {
+ name: "nil section info - no expansion",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: nil,
+ },
+ expectedResult: DiffLineExpandNone,
+ },
+ {
+ name: "no lines between",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // Previous section of the diff displayed up to line 530...
+ LastRightIdx: 530,
+ LastLeftIdx: 530,
+ // This section of the diff starts at line 531...
+ RightIdx: 531,
+ LeftIdx: 531,
+ },
+ },
+ // There are zero lines between 530 and 531, so we should have nothing to expand.
+ expectedResult: DiffLineExpandNone,
+ },
+ {
+ name: "first diff section is the start of the file",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // Last[...]Idx is set to zero when it's the first section in the file (and not 1, which would be
+ // the first section -is- the first line of the file).
+ LastRightIdx: 0,
+ LastLeftIdx: 0,
+ // The diff section is showing line 1, the top of th efile.
+ RightIdx: 1,
+ LeftIdx: 1,
+ },
+ },
+ // We're at the top of the file; no expansion.
+ expectedResult: DiffLineExpandNone,
+ },
+ {
+ name: "first diff section doesn't start at the top of the file",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // Last[...]Idx is set to zero when it's the first section in the file (and not 1, which would be
+ // the first section -is- the first line of the file).
+ LastRightIdx: 0,
+ LastLeftIdx: 0,
+ RightIdx: 531,
+ LeftIdx: 531,
+ },
+ },
+ // We're at the top of the diff but there's content above, so can only expand up.
+ expectedResult: DiffLineExpandUp,
+ },
+ {
+ name: "middle of the file with single expansion",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // Previous section ended at ~500...
+ LastRightIdx: 500,
+ LastLeftIdx: 500,
+ // Next section starts one line away...
+ RightIdx: 502,
+ LeftIdx: 502,
+ // The next block has content (> 0)
+ RightHunkSize: 50,
+ LeftHunkSize: 50,
+ },
+ },
+ // Can be expanded in a single direction, displaying the missing line (501).
+ expectedResult: DiffLineExpandSingle,
+ },
+ {
+ name: "middle of the file with multi line expansion",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // Previous section ended at ~500...
+ LastRightIdx: 500,
+ LastLeftIdx: 500,
+ // Lines 501-520 are hidden, exactly 20 lines, matching BlobExcerptChunkSize (20)...
+ RightIdx: 521,
+ LeftIdx: 521,
+ // The next block has content (> 0)
+ RightHunkSize: 50,
+ LeftHunkSize: 50,
+ },
+ },
+ // Can be expanded in a single direction, displaying all the hidden 20 lines.
+ expectedResult: DiffLineExpandSingle,
+ },
+ {
+ name: "middle of the file with multi direction expansion",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // Previous section ended at ~500...
+ LastRightIdx: 500,
+ LastLeftIdx: 500,
+ // Lines 501-521 are hidden, exactly 21 lines, exceeding BlobExcerptChunkSize (20)...
+ RightIdx: 522,
+ LeftIdx: 522,
+ // The next block has content (> 0)
+ RightHunkSize: 50,
+ LeftHunkSize: 50,
+ },
+ },
+ // Now can be expanded down to display from 501-520 (521 remains hidden), or up to display 502-521 (501
+ // remains hidden).
+ expectedResult: DiffLineExpandUpDown,
+ },
+ {
+ name: "end of the diff but still file content to display",
+ diffLine: &DiffLine{
+ Type: DiffLineSection,
+ SectionInfo: &DiffLineSectionInfo{
+ // We had a previous diff section, of any size/location...
+ LastRightIdx: 200,
+ LastLeftIdx: 200,
+ RightIdx: 531,
+ LeftIdx: 531,
+ // Hunk size size 0 is a placeholder value for the end or beginning of a file...
+ RightHunkSize: 0,
+ LeftHunkSize: 0,
+ },
+ },
+ // Combination of conditions says we're at the end of the last diff section, can only expand down.
+ expectedResult: DiffLineExpandDown,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := tt.diffLine.GetExpandDirection()
+ assert.Equal(t, tt.expectedResult, result)
+ })
+ }
+}
+
func TestNoCrashes(t *testing.T) {
type testcase struct {
gitdiff string
diff --git a/services/issue/comments_test.go b/services/issue/comments_test.go
index 8fa410c0f0..fcf06d9ec8 100644
--- a/services/issue/comments_test.go
+++ b/services/issue/comments_test.go
@@ -8,9 +8,11 @@ import (
"forgejo.org/models/db"
issues_model "forgejo.org/models/issues"
+ "forgejo.org/models/moderation"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
webhook_model "forgejo.org/models/webhook"
+ "forgejo.org/modules/json"
"forgejo.org/modules/setting"
"forgejo.org/modules/test"
issue_service "forgejo.org/services/issue"
@@ -148,3 +150,40 @@ func TestUpdateComment(t *testing.T) {
unittest.AssertNotExistsBean(t, &issues_model.ContentHistory{CommentID: comment.ID})
})
}
+
+func TestCreateShadowCopyOnCommentUpdate(t *testing.T) {
+ defer unittest.OverrideFixtures("models/fixtures/ModerationFeatures")()
+ require.NoError(t, unittest.PrepareTestDatabase())
+
+ userAlexSmithID := int64(1002)
+ spamCommentID := int64(18) // posted by @alexsmith
+ abuseReportID := int64(1) // submitted for above comment
+ newCommentContent := "If anyone needs help, just contact me."
+
+ // Retrieve the abusive user (@alexsmith), their SPAM comment and the abuse report already created for this comment.
+ poster := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userAlexSmithID})
+ comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: spamCommentID, PosterID: poster.ID})
+ report := unittest.AssertExistsAndLoadBean(t, &moderation.AbuseReport{
+ ID: abuseReportID,
+ ContentType: moderation.ReportedContentTypeComment,
+ ContentID: comment.ID,
+ })
+ // The report should not already have a shadow copy linked.
+ assert.False(t, report.ShadowCopyID.Valid)
+
+ // The abusive user is updating their comment.
+ oldContent := comment.Content
+ comment.Content = newCommentContent
+ require.NoError(t, issue_service.UpdateComment(t.Context(), comment, 0, poster, oldContent))
+
+ // Reload the report.
+ report = unittest.AssertExistsAndLoadBean(t, &moderation.AbuseReport{ID: report.ID})
+ // A shadow copy should have been created and linked to our report.
+ assert.True(t, report.ShadowCopyID.Valid)
+ // Retrieve the newly created shadow copy and unmarshal the stored JSON so that we can check the values.
+ shadowCopy := unittest.AssertExistsAndLoadBean(t, &moderation.AbuseReportShadowCopy{ID: report.ShadowCopyID.Int64})
+ shadowCopyCommentData := new(issues_model.CommentData)
+ require.NoError(t, json.Unmarshal([]byte(shadowCopy.RawValue), &shadowCopyCommentData))
+ // Check to see if the initial content of the comment was stored within the shadow copy.
+ assert.Equal(t, oldContent, shadowCopyCommentData.Content)
+}
diff --git a/services/mailer/mail_actions.go b/services/mailer/mail_actions.go
index 09763e164e..a99af823b3 100644
--- a/services/mailer/mail_actions.go
+++ b/services/mailer/mail_actions.go
@@ -16,8 +16,8 @@ const (
tplActionNowDone base.TplName = "actions/now_done"
)
-// requires !run.Status.IsSuccess() or !lastRun.Status.IsSuccess()
-func MailActionRun(run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) error {
+var MailActionRun = mailActionRun // make it mockable
+func mailActionRun(run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) error {
if setting.MailService == nil {
// No mail service configured
return nil
@@ -60,7 +60,6 @@ func sendMailActionRun(to *user_model.User, run *actions_model.ActionRun, priorS
if len(commitSHA) > 7 {
commitSHA = commitSHA[:7]
}
- branch := run.PrettyRef()
data := map[string]any{
"locale": locale,
@@ -73,7 +72,6 @@ func sendMailActionRun(to *user_model.User, run *actions_model.ActionRun, priorS
"LastRun": lastRun,
"PriorStatus": priorStatus,
"CommitSHA": commitSHA,
- "Branch": branch,
"IsSuccess": run.Status.IsSuccess(),
}
diff --git a/services/mailer/mail_actions_now_done_test.go b/services/mailer/mail_actions_now_done_test.go
index 6a01ea7631..e84441f460 100644
--- a/services/mailer/mail_actions_now_done_test.go
+++ b/services/mailer/mail_actions_now_done_test.go
@@ -54,7 +54,92 @@ func getActionsNowDoneTestOrg(t *testing.T, name, email string, owner *user_mode
}
func assertTranslatedLocaleMailActionsNowDone(t *testing.T, msgBody string) {
- AssertTranslatedLocale(t, msgBody, "mail.actions.successful_run_after_failure", "mail.actions.not_successful_run", "mail.actions.run_info_cur_status", "mail.actions.run_info_ref", "mail.actions.run_info_previous_status", "mail.actions.run_info_trigger", "mail.view_it_on")
+ AssertTranslatedLocale(t, msgBody, "mail.actions.successful_run_after_failure", "mail.actions.not_successful_run", "mail.actions.run_info_cur_status", "mail.actions.run_info_sha", "mail.actions.run_info_previous_status", "mail.actions.run_info_trigger", "mail.view_it_on")
+}
+
+func TestActionRunNowDoneStatusMatrix(t *testing.T) {
+ successStatuses := []actions_model.Status{
+ actions_model.StatusSuccess,
+ actions_model.StatusSkipped,
+ actions_model.StatusCancelled,
+ }
+ failureStatuses := []actions_model.Status{
+ actions_model.StatusFailure,
+ }
+
+ for _, testCase := range []struct {
+ name string
+ statuses []actions_model.Status
+ hasLastRun bool
+ lastStatuses []actions_model.Status
+ run bool
+ }{
+ {
+ name: "FailureNoLastRun",
+ statuses: failureStatuses,
+ run: true,
+ },
+ {
+ name: "SuccessNoLastRun",
+ statuses: successStatuses,
+ run: false,
+ },
+ {
+ name: "FailureLastRunSuccess",
+ statuses: failureStatuses,
+ hasLastRun: true,
+ lastStatuses: successStatuses,
+ run: true,
+ },
+ {
+ name: "FailureLastRunFailure",
+ statuses: failureStatuses,
+ hasLastRun: true,
+ lastStatuses: failureStatuses,
+ run: true,
+ },
+ {
+ name: "SuccessLastRunFailure",
+ statuses: successStatuses,
+ hasLastRun: true,
+ lastStatuses: failureStatuses,
+ run: true,
+ },
+ {
+ name: "SuccessLastRunSuccess",
+ statuses: successStatuses,
+ hasLastRun: true,
+ lastStatuses: successStatuses,
+ run: false,
+ },
+ } {
+ t.Run(testCase.name, func(t *testing.T) {
+ var called bool
+ defer test.MockVariableValue(&MailActionRun, func(run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) error {
+ called = true
+ return nil
+ })()
+ for _, status := range testCase.statuses {
+ for _, lastStatus := range testCase.lastStatuses {
+ called = false
+ n := NewNotifier()
+ var lastRun *actions_model.ActionRun
+ if testCase.hasLastRun {
+ lastRun = &actions_model.ActionRun{
+ Status: lastStatus,
+ }
+ }
+ n.ActionRunNowDone(t.Context(),
+ &actions_model.ActionRun{
+ Status: status,
+ },
+ actions_model.StatusUnknown,
+ lastRun)
+ assert.Equal(t, testCase.run, called, "status = %s, lastStatus = %s", status, lastStatus)
+ }
+ }
+ })
+ }
}
func TestActionRunNowDoneNotificationMail(t *testing.T) {
diff --git a/services/mailer/notify.go b/services/mailer/notify.go
index 7461a67181..640de31fcc 100644
--- a/services/mailer/notify.go
+++ b/services/mailer/notify.go
@@ -212,7 +212,7 @@ func (m *mailNotifier) NewUserSignUp(ctx context.Context, newUser *user_model.Us
func (m *mailNotifier) ActionRunNowDone(ctx context.Context, run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) {
// Only send a mail on a successful run when the workflow recovered (i.e., the run before failed).
- if run.Status.IsSuccess() && (lastRun == nil || lastRun.Status.IsSuccess()) {
+ if !run.Status.IsFailure() && (lastRun == nil || !lastRun.Status.IsFailure()) {
return
}
if err := MailActionRun(run, priorStatus, lastRun); err != nil {
diff --git a/services/packages/alt/repository.go b/services/packages/alt/repository.go
index 317862da9d..9693f4322e 100644
--- a/services/packages/alt/repository.go
+++ b/services/packages/alt/repository.go
@@ -714,21 +714,23 @@ func buildRelease(ctx context.Context, pv *packages_model.PackageVersion, pfs []
for architecture := range architectures.Seq() {
version := time.Now().Unix()
label := setting.AppName
- data := fmt.Sprintf(`Archive: Alt Linux Team
+ origin := setting.AppName
+ archive := setting.AppName
+
+ data := fmt.Sprintf(`Archive: %s
Component: classic
Version: %d
-Origin: Alt Linux Team
+Origin: %s
Label: %s
Architecture: %s
NotAutomatic: false
`,
- version, label, architecture)
+ archive, version, origin, label, architecture)
fileInfo, err := addReleaseAsFileToRepo(ctx, pv, "release.classic", data, group, architecture)
if err != nil {
return err
}
- origin := setting.AppName
codename := time.Now().Unix()
date := time.Now().UTC().Format(time.RFC1123)
@@ -744,7 +746,7 @@ NotAutomatic: false
data = fmt.Sprintf(`Origin: %s
Label: %s
-Suite: Sisyphus
+Suite: Unknown
Codename: %d
Date: %s
Architectures: %s
diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go
index fc70da10a4..4598d57b7a 100644
--- a/services/pull/merge_prepare.go
+++ b/services/pull/merge_prepare.go
@@ -249,6 +249,11 @@ func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle)
ctx.outbuf.Reset()
ctx.errbuf.Reset()
+ // If the pull request is zero commits behind, then no rebasing needs to be done.
+ if ctx.pr.CommitsBehind == 0 {
+ return nil
+ }
+
// Check git version for availability of git-replay. If it is available, we use
// it for performance and to preserve unknown commit headers like the
// "change-id" header used by Jujutsu and GitButler to track changes across
diff --git a/services/repository/files/file.go b/services/repository/files/file.go
index ef9a87dbcf..5b93258840 100644
--- a/services/repository/files/file.go
+++ b/services/repository/files/file.go
@@ -104,36 +104,35 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *user_m
// then we use bogus User objects for them to store their FullName and Email.
// If only one of the two are provided, we set both of them to it.
// If neither are provided, both are the doer.
- if committer != nil && committer.Email != "" {
- if doer != nil && strings.EqualFold(doer.Email, committer.Email) {
- committerUser = doer // the committer is the doer, so will use their user object
- if committer.Name != "" {
- committerUser.FullName = committer.Name
+ getUser := func(identity *IdentityOptions) *user_model.User {
+ if identity == nil || identity.Email == "" {
+ return nil
+ }
+
+ if doer != nil && strings.EqualFold(doer.Email, identity.Email) {
+ user := doer // the committer is the doer, so will use their user object
+ if identity.Name != "" {
+ user.FullName = identity.Name
}
// Use the provided email and not revert to placeholder mail.
- committerUser.KeepEmailPrivate = false
- } else {
- committerUser = &user_model.User{
- FullName: committer.Name,
- Email: committer.Email,
- }
- }
- }
- if author != nil && author.Email != "" {
- if doer != nil && strings.EqualFold(doer.Email, author.Email) {
- authorUser = doer // the author is the doer, so will use their user object
- if authorUser.Name != "" {
- authorUser.FullName = author.Name
- }
- // Use the provided email and not revert to placeholder mail.
- authorUser.KeepEmailPrivate = false
- } else {
- authorUser = &user_model.User{
- FullName: author.Name,
- Email: author.Email,
- }
+ user.KeepEmailPrivate = false
+ return user
+ }
+
+ var id int64
+ if doer != nil {
+ id = doer.ID
+ }
+ return &user_model.User{
+ ID: id, // Needed to ensure the doer is checked to pass rules for instance signing of CRUD actions.
+ FullName: identity.Name,
+ Email: identity.Email,
}
}
+
+ committerUser = getUser(committer)
+ authorUser = getUser(author)
+
if authorUser == nil {
if committerUser != nil {
authorUser = committerUser // No valid author was given so use the committer
diff --git a/services/user/delete.go b/services/user/delete.go
index 9caa24c373..bed7abde07 100644
--- a/services/user/delete.go
+++ b/services/user/delete.go
@@ -218,7 +218,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
// ***** END: ExternalLoginUser *****
// If the user was reported as abusive, a shadow copy should be created before deletion.
- if err = user_model.IfNeededCreateShadowCopyForUser(ctx, u); err != nil {
+ if err = user_model.IfNeededCreateShadowCopyForUser(ctx, u.ID, u); err != nil {
return err
}
diff --git a/services/user/email.go b/services/user/email.go
index 7a01fa77b3..36a1145aec 100644
--- a/services/user/email.go
+++ b/services/user/email.go
@@ -205,7 +205,7 @@ func MakeEmailAddressPrimary(ctx context.Context, u *user_model.User, newPrimary
oldPrimaryEmail := u.Email
// If the user was reported as abusive, a shadow copy should be created before first update (of certain columns).
- if err = user_model.IfNeededCreateShadowCopyForUser(ctx, u, "email"); err != nil {
+ if err = user_model.IfNeededCreateShadowCopyForUser(ctx, u.ID, u, "email"); err != nil {
return err
}
diff --git a/services/user/user_test.go b/services/user/user_test.go
index 4678d3bc9a..36f2776ad8 100644
--- a/services/user/user_test.go
+++ b/services/user/user_test.go
@@ -15,10 +15,13 @@ import (
asymkey_model "forgejo.org/models/asymkey"
"forgejo.org/models/auth"
"forgejo.org/models/db"
+ "forgejo.org/models/moderation"
"forgejo.org/models/organization"
repo_model "forgejo.org/models/repo"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
+ "forgejo.org/modules/json"
+ "forgejo.org/modules/optional"
"forgejo.org/modules/setting"
"forgejo.org/modules/test"
"forgejo.org/modules/timeutil"
@@ -277,3 +280,56 @@ func TestDeleteInactiveUsers(t *testing.T) {
unittest.AssertExistsIf(t, true, newUser)
unittest.AssertExistsIf(t, true, newEmail)
}
+
+func TestCreateShadowCopyOnUserUpdate(t *testing.T) {
+ defer unittest.OverrideFixtures("models/fixtures/ModerationFeatures")()
+ require.NoError(t, unittest.PrepareTestDatabase())
+
+ userAlexSmithID := int64(1002)
+ abuseReportID := int64(2) // submitted for @alexsmith
+ newDummyValue := "[REDACTED]" // used for updating profile text fields
+
+ // Retrieve the abusive user (@alexsmith) and the abuse report already created for this user.
+ abuser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userAlexSmithID})
+ report := unittest.AssertExistsAndLoadBean(t, &moderation.AbuseReport{
+ ID: abuseReportID,
+ ContentType: moderation.ReportedContentTypeUser,
+ ContentID: abuser.ID,
+ })
+ // The report should not already have a shadow copy linked.
+ assert.False(t, report.ShadowCopyID.Valid)
+
+ // Keep a copy of old field values before updating them.
+ oldUserData := user_model.UserData{
+ FullName: abuser.FullName,
+ Location: abuser.Location,
+ Website: abuser.Website,
+ Pronouns: abuser.Pronouns,
+ Description: abuser.Description,
+ }
+
+ // The abusive user is updating their profile.
+ opts := &UpdateOptions{
+ FullName: optional.Some(newDummyValue),
+ Location: optional.Some(newDummyValue),
+ Website: optional.Some(newDummyValue),
+ Pronouns: optional.Some(newDummyValue),
+ Description: optional.Some(newDummyValue),
+ }
+ require.NoError(t, UpdateUser(t.Context(), abuser, opts))
+
+ // Reload the report.
+ report = unittest.AssertExistsAndLoadBean(t, &moderation.AbuseReport{ID: report.ID})
+ // A shadow copy should have been created and linked to our report.
+ assert.True(t, report.ShadowCopyID.Valid)
+ // Retrieve the newly created shadow copy and unmarshal the stored JSON so that we can check the values.
+ shadowCopy := unittest.AssertExistsAndLoadBean(t, &moderation.AbuseReportShadowCopy{ID: report.ShadowCopyID.Int64})
+ shadowCopyUserData := new(user_model.UserData)
+ require.NoError(t, json.Unmarshal([]byte(shadowCopy.RawValue), &shadowCopyUserData))
+ // Check to see if the initial field values of the user were stored within the shadow copy.
+ assert.Equal(t, oldUserData.FullName, shadowCopyUserData.FullName)
+ assert.Equal(t, oldUserData.Location, shadowCopyUserData.Location)
+ assert.Equal(t, oldUserData.Website, shadowCopyUserData.Website)
+ assert.Equal(t, oldUserData.Pronouns, shadowCopyUserData.Pronouns)
+ assert.Equal(t, oldUserData.Description, shadowCopyUserData.Description)
+}
diff --git a/templates/mail/actions/now_done.tmpl b/templates/mail/actions/now_done.tmpl
index a890411055..adc990c545 100644
--- a/templates/mail/actions/now_done.tmpl
+++ b/templates/mail/actions/now_done.tmpl
@@ -21,7 +21,7 @@
{{.locale.Tr "mail.actions.run_info_cur_status" .Run.Status .PriorStatus}}
- {{.locale.Tr "mail.actions.run_info_ref" .Branch .CommitSHA}}
+ {{.locale.Tr "mail.actions.run_info_sha" .CommitSHA}}
{{if .LastRun}}
{{.locale.Tr "mail.actions.run_info_previous_status" .LastRun.Status}}
{{end}}
diff --git a/templates/package/content/alt.tmpl b/templates/package/content/alt.tmpl
index 9a5e9c7656..0a5c328e6d 100644
--- a/templates/package/content/alt.tmpl
+++ b/templates/package/content/alt.tmpl
@@ -24,7 +24,7 @@ apt-get install {{$.PackageDescriptor.Package.Name}}
-
+
diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl
index 8646562ca8..6d2f441793 100644
--- a/templates/repo/issue/card.tmpl
+++ b/templates/repo/issue/card.tmpl
@@ -4,7 +4,7 @@
{{if $attachments}}
{{end}}
diff --git a/templates/repo/issue/view_content/attachments.tmpl b/templates/repo/issue/view_content/attachments.tmpl
index 79085df3ab..8b5094771a 100644
--- a/templates/repo/issue/view_content/attachments.tmpl
+++ b/templates/repo/issue/view_content/attachments.tmpl
@@ -31,7 +31,7 @@
{{if FilenameIsImage .Name}}
{{if not (StringUtils.Contains (StringUtils.ToString $.RenderedContent) .UUID)}}
-
+
{{end}}
{{end}}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index 2e9ba3dcd7..d7701bc468 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -634,7 +634,7 @@
-
+
{{svg "octicon-x" 16}}
@@ -724,18 +724,18 @@
{{svg "octicon-dot-fill"}}
{{if .Issue.IsPull}}
- {{ctx.Locale.Tr "repo.pulls.reopened_at" "" ""}}
+ {{ctx.Locale.Tr "repo.pulls.reopened_at" ""}}
{{else}}
- {{ctx.Locale.Tr "repo.issues.reopened_at" "" ""}}
+ {{ctx.Locale.Tr "repo.issues.reopened_at" ""}}
{{end}}
{{else if and (not .Aggregator.PrevClosed) .Aggregator.IsClosed}}
{{svg "octicon-circle-slash"}}
{{if .Issue.IsPull}}
- {{ctx.Locale.Tr "repo.pulls.closed_at" "" ""}}
+ {{ctx.Locale.Tr "repo.pulls.closed_at" ""}}
{{else}}
- {{ctx.Locale.Tr "repo.issues.closed_at" "" ""}}
+ {{ctx.Locale.Tr "repo.issues.closed_at" ""}}
{{end}}
{{end}}
diff --git a/templates/repo/issue/view_content/context_menu.tmpl b/templates/repo/issue/view_content/context_menu.tmpl
index 6f43f768b3..8cd4a056f0 100644
--- a/templates/repo/issue/view_content/context_menu.tmpl
+++ b/templates/repo/issue/view_content/context_menu.tmpl
@@ -11,7 +11,7 @@
{{end}}
{{ctx.Locale.Tr "repo.issues.context.copy_link"}}
{{if and .ctxData.IsSigned (not .ctxData.Repository.IsArchived)}}
-
+
{{if not .ctxData.UnitIssuesGlobalDisabled}}
{{ctx.Locale.Tr "repo.issues.context.reference_issue"}}
{{end}}
diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl
index 788d7f015c..c5c7eb23fa 100644
--- a/templates/repo/release/new.tmpl
+++ b/templates/repo/release/new.tmpl
@@ -46,7 +46,7 @@
-
+
{{template "shared/combomarkdowneditor" (dict
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 3ef712c464..9b4d79f0df 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -22701,10 +22701,6 @@
},
"x-go-name": "Events"
},
- "is_system_webhook": {
- "type": "boolean",
- "x-go-name": "IsSystemWebhook"
- },
"type": {
"type": "string",
"enum": [
@@ -30062,6 +30058,12 @@
}
},
"securityDefinitions": {
+ "AccessToken": {
+ "description": "This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.",
+ "type": "apiKey",
+ "name": "access_token",
+ "in": "query"
+ },
"AuthorizationHeaderToken": {
"description": "API tokens must be prepended with \"token\" followed by a space.",
"type": "apiKey",
@@ -30088,12 +30090,24 @@
"type": "apiKey",
"name": "X-FORGEJO-OTP",
"in": "header"
+ },
+ "Token": {
+ "description": "This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.",
+ "type": "apiKey",
+ "name": "token",
+ "in": "query"
}
},
"security": [
{
"BasicAuth": []
},
+ {
+ "Token": []
+ },
+ {
+ "AccessToken": []
+ },
{
"AuthorizationHeaderToken": []
},
diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl
index d0ecb1fc36..cdf0429714 100644
--- a/templates/user/dashboard/feeds.tmpl
+++ b/templates/user/dashboard/feeds.tmpl
@@ -90,7 +90,7 @@
{{range $push.Commits}}
-
+
{{template "repo/shabox" (dict
"sha1" .Sha1
"commitLink" (printf "%s/commit/%s" $repoLink .Sha1)
diff --git a/tests/e2e/declare_repos_test.go b/tests/e2e/declare_repos_test.go
index 351f7821eb..39179b50e5 100644
--- a/tests/e2e/declare_repos_test.go
+++ b/tests/e2e/declare_repos_test.go
@@ -57,6 +57,22 @@ func DeclareGitRepos(t *testing.T) func() {
Filename: "a-file",
Versions: []string{"{a}{а}"},
}}),
+ newRepo(t, 2, "multiple-combo-boxes", []FileChanges{{
+ Filename: ".forgejo/issue_template/multi-combo-boxes.yaml",
+ Versions: []string{`
+name: "Multiple combo-boxes"
+description: "To show something"
+body:
+- type: textarea
+ id: textarea-one
+ attributes:
+ label: one
+- type: textarea
+ id: textarea-two
+ attributes:
+ label: two
+`},
+ }}),
// add your repo declarations here
}
diff --git a/tests/e2e/fixtures/comment.yml b/tests/e2e/fixtures/comment.yml
index f3f8a2d8e8..ae7c850036 100644
--- a/tests/e2e/fixtures/comment.yml
+++ b/tests/e2e/fixtures/comment.yml
@@ -3,7 +3,7 @@
type: 0 # comment
poster_id: 2
issue_id: 1 # in repo_id 1
- content: "## Lorem Ipsum\nI would like to say that **I am not appealed** that it took _so long_ for this `feature` to be [created](https://example.com) $e^{\\pi i} + 1 = 0$\n$$e^{\\pi i} + 1 = 0$$\n#1\n```js\nconsole.log('evil')\nalert('evil')\n```\n:+1: :100:"
+ content: "## Lorem Ipsum\nI would like to say that **I am not appealed** that it took _so long_ for this `feature` to be [created](https://example.com) $e^{\\pi i} + 1 = 0$\n$$e^{\\pi i} + 1 = 0$$\n#1\n```js\nconsole.log('evil')\nalert('evil')\n```\n:+1: :100:\n\n\n
"
created_unix: 946684811
updated_unix: 946684811
content_version: 1
@@ -13,7 +13,7 @@
type: 21 # code comment
poster_id: 2
issue_id: 19
- content: "## Lorem Ipsum\nI would like to say that **I am not appealed** that it took _so long_ for this `feature` to be [created](https://example.com) $e^{\\pi i} + 1 = 0$\n$$e^{\\pi i} + 1 = 0$$\n#1\n```js\nconsole.log('evil')\nalert('evil')\n```\n:+1: :100:"
+ content: "## Lorem Ipsum\nI would like to say that **I am not appealed** that it took _so long_ for this `feature` to be [created](https://example.com) $e^{\\pi i} + 1 = 0$\n$$e^{\\pi i} + 1 = 0$$\n#1\n```js\nconsole.log('evil')\nalert('evil')\n```\n:+1: :100:\n\n\n
"
review_id: 1001
line: 1
tree_path: "test1.txt"
diff --git a/tests/e2e/issue-comment-dropzone.test.e2e.ts b/tests/e2e/issue-comment-dropzone.test.e2e.ts
new file mode 100644
index 0000000000..33ea2c9403
--- /dev/null
+++ b/tests/e2e/issue-comment-dropzone.test.e2e.ts
@@ -0,0 +1,94 @@
+// Copyright 2025 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// @watch start
+// web_src/js/features/common-global.js
+// web_src/js/features/comp/Paste.js
+// web_src/js/features/repo-issue.js
+// web_src/js/features/repo-legacy.js
+// @watch end
+
+import {expect, type Locator, type Page, type TestInfo} from '@playwright/test';
+import {test, save_visual, dynamic_id} from './utils_e2e.ts';
+
+test.use({user: 'user2'});
+
+async function pasteImage(el: Locator) {
+ await el.evaluate(async (el) => {
+ const base64 = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAHklEQVQoU2MUk1P7z0AGYBzViDvURgMHT4oaQoEDAFuJEu2fuGfhAAAAAElFTkSuQmCC`;
+ // eslint-disable-next-line no-restricted-syntax
+ const response = await fetch(base64);
+ const blob = await response.blob();
+
+ el.focus();
+
+ let pasteEvent = new Event('paste', {bubbles: true, cancelable: true});
+ pasteEvent = Object.assign(pasteEvent, {
+ clipboardData: {
+ items: [
+ {
+ kind: 'file',
+ type: 'image/png',
+ getAsFile() {
+ return new File([blob], 'foo.png', {type: blob.type});
+ },
+ },
+ ],
+ },
+ });
+
+ el.dispatchEvent(pasteEvent);
+ });
+}
+
+async function assertCopy(page: Page, workerInfo: TestInfo, startWith: string) {
+ const project = workerInfo.project.name;
+ if (project === 'webkit' || project === 'Mobile Safari') return;
+
+ const dropzone = page.locator('.dropzone');
+ const preview = dropzone.locator('.dz-preview');
+ const copyLink = preview.locator('.octicon-copy').locator('..');
+ await copyLink.click();
+
+ const clipboardContent = await page.evaluate(() => navigator.clipboard.readText());
+ expect(clipboardContent).toContain(startWith);
+}
+
+test('Paste image in new comment', async ({page}, workerInfo) => {
+ await page.goto('/user2/repo1/issues/new');
+
+ await pasteImage(page.locator('.markdown-text-editor'));
+
+ const dropzone = page.locator('.dropzone');
+ await expect(dropzone.locator('.files')).toHaveCount(1);
+ const preview = dropzone.locator('.dz-preview');
+ await expect(preview).toHaveCount(1);
+ await expect(preview.locator('.dz-filename')).toHaveText('foo.png');
+ await expect(preview.locator('.octicon-copy')).toBeVisible();
+ await assertCopy(page, workerInfo, ';
+
+ await save_visual(page);
+});
+
+test('Re-add images to dropzone on edit', async ({page}, workerInfo) => {
+ await page.goto('/user2/repo1/issues/new');
+
+ const issueTitle = dynamic_id();
+ await page.locator('#issue_title').fill(issueTitle);
+ await pasteImage(page.locator('.markdown-text-editor'));
+ await page.getByRole('button', {name: 'Create issue'}).click();
+
+ await expect(page).toHaveURL(/\/user2\/repo1\/issues\/\d+$/);
+ await page.click('.comment-container .context-menu');
+ await page.click('.comment-container .menu > .edit-content');
+
+ const dropzone = page.locator('.dropzone');
+ await expect(dropzone.locator('.files').first()).toHaveCount(1);
+ const preview = dropzone.locator('.dz-preview');
+ await expect(preview).toHaveCount(1);
+ await expect(preview.locator('.dz-filename')).toHaveText('foo.png');
+ await expect(preview.locator('.octicon-copy')).toBeVisible();
+ await assertCopy(page, workerInfo, ';
+
+ await save_visual(page);
+});
diff --git a/tests/e2e/issue-comment.test.e2e.ts b/tests/e2e/issue-comment.test.e2e.ts
index d2dbafafd0..2017e4563e 100644
--- a/tests/e2e/issue-comment.test.e2e.ts
+++ b/tests/e2e/issue-comment.test.e2e.ts
@@ -123,7 +123,8 @@ test('Quote reply', async ({page}, workerInfo) => {
"> alert('evil')\n" +
'> ```\n' +
'> \n' +
- '> :+1: :100:\n\n');
+ '> :+1: :100: [](/user2/repo1/attachments/3f4f4016-877b-46b3-b79f-ad24519a9cf2)\n' +
+ '>
\n\n');
await editorTextarea.fill('');
@@ -197,7 +198,8 @@ test('Pull quote reply', async ({page}, workerInfo) => {
"> alert('evil')\n" +
'> ```\n' +
'> \n' +
- '> :+1: :100:\n\n');
+ '> :+1: :100: [](/user2/commitsonpr/attachments/3f4f4016-877b-46b3-b79f-ad24519a9cf2)\n' +
+ '>
\n\n');
await editorTextarea.fill('');
});
diff --git a/tests/e2e/issue-sidebar.test.e2e.ts b/tests/e2e/issue-sidebar.test.e2e.ts
index bc65b0842c..ca0ee5e278 100644
--- a/tests/e2e/issue-sidebar.test.e2e.ts
+++ b/tests/e2e/issue-sidebar.test.e2e.ts
@@ -50,7 +50,6 @@ test.describe('Pull: Toggle WIP', () => {
test('simple toggle', async ({page}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
- await page.goto('/user2/repo1/pulls/5');
// toggle to WIP
await toggle_wip_to({page}, true);
await check_wip({page}, true);
diff --git a/tests/e2e/issue-timetracking.test.e2e.ts b/tests/e2e/issue-timetracking.test.e2e.ts
new file mode 100644
index 0000000000..901cbe793f
--- /dev/null
+++ b/tests/e2e/issue-timetracking.test.e2e.ts
@@ -0,0 +1,48 @@
+// @watch start
+// web_src/js/features/comp/**
+// web_src/js/features/repo-**
+// templates/repo/issue/view_content/*
+// @watch end
+
+import {expect} from '@playwright/test';
+import {test, save_visual} from './utils_e2e.ts';
+
+test.use({user: 'user2'});
+
+test('Issue timetracking', async ({page}) => {
+ await page.goto('/user2/repo1/issues/new');
+
+ // Create temporary issue.
+ await page.getByPlaceholder('Title').fill('Just a title');
+ await page.getByPlaceholder('Leave a comment').fill('Hi, have you considered using a rotating fish as logo?');
+ await page.getByRole('button', {name: 'Create issue'}).click();
+ await expect(page).toHaveURL(/\/user2\/repo1\/issues\/\d+$/);
+
+ // Manually add time to the time tracker.
+ await page.getByRole('button', {name: 'Add time'}).click();
+ await page.getByPlaceholder('Hours').fill('5');
+ await page.getByPlaceholder('Minutes').fill('32');
+ await page.getByRole('button', {name: 'Add time', exact: true}).click();
+
+ // Verify this was added in the timeline.
+ await expect(page.locator('.ui.timeline')).toContainText('added spent time');
+ await expect(page.locator('.ui.timeline')).toContainText('5 hours 32 minutes');
+
+ // Verify it is shown in the issue sidebar
+ await expect(page.locator('.issue-content-right .comments')).toContainText('Total time spent: 5 hours 32 minutes');
+
+ await save_visual(page);
+
+ // Delete the added time.
+ await page.getByRole('button', {name: 'Delete this time log'}).click();
+ await page.getByRole('button', {name: 'Yes'}).click();
+
+ // Verify this was removed in the timeline.
+ await expect(page.locator('.ui.timeline')).toContainText('deleted spent time');
+ await expect(page.locator('.ui.timeline')).toContainText('- 5 hours 32 minutes');
+
+ // Delete the issue.
+ await page.getByRole('button', {name: 'Delete'}).click();
+ await page.getByRole('button', {name: 'Yes'}).click();
+ await expect(page).toHaveURL('/user2/repo1/issues');
+});
diff --git a/tests/e2e/login.test.e2e.ts b/tests/e2e/login.test.e2e.ts
index 1ffa0b2e5d..01cf4d7b8d 100644
--- a/tests/e2e/login.test.e2e.ts
+++ b/tests/e2e/login.test.e2e.ts
@@ -10,7 +10,8 @@
import {expect} from '@playwright/test';
import {test, save_visual, test_context} from './utils_e2e.ts';
-test('Mismatched ROOT_URL', async ({browser}) => {
+test('Mismatched ROOT_URL', async ({browser}, workerInfo) => {
+ test.skip(['Mobile Safari', 'webkit'].includes(workerInfo.project.name), 'init script gets randomly ignored');
const context = await test_context(browser);
const page = await context.newPage();
diff --git a/tests/e2e/markdown-editor.test.e2e.ts b/tests/e2e/markdown-editor.test.e2e.ts
index 2b5f0d80a0..7983907343 100644
--- a/tests/e2e/markdown-editor.test.e2e.ts
+++ b/tests/e2e/markdown-editor.test.e2e.ts
@@ -456,3 +456,62 @@ test('Combo Markdown: preview mode switch', async ({page}) => {
await expect(previewPanel).toBeHidden();
await save_visual(page);
});
+
+test('Multiple combo markdown: insert table', async ({page}) => {
+ const response = await page.goto('/user2/multiple-combo-boxes/issues/new?template=.forgejo%2fissue_template%2fmulti-combo-boxes.yaml');
+ expect(response?.status()).toBe(200);
+
+ // check that there are two textareas
+ const textareaOne = page.locator('textarea[name=form-field-textarea-one]');
+ const comboboxOne = page.locator('textarea#_combo_markdown_editor_0');
+ await expect(textareaOne).toBeVisible();
+ await expect(comboboxOne).toBeHidden();
+ const textareaTwo = page.locator('textarea[name=form-field-textarea-two]');
+ const comboboxTwo = page.locator('textarea#_combo_markdown_editor_1');
+ await expect(textareaTwo).toBeVisible();
+ await expect(comboboxTwo).toBeHidden();
+
+ // focus first one and add table to it
+ await textareaOne.click();
+ await expect(comboboxOne).toBeVisible();
+ await expect(comboboxTwo).toBeHidden();
+
+ const newTableButtonOne = page.locator('[for="_combo_markdown_editor_0"] button[data-md-action="new-table"]');
+ await newTableButtonOne.click();
+
+ const newTableModalOne = page.locator('div[data-markdown-table-modal-id="0"]');
+ await expect(newTableModalOne).toBeVisible();
+
+ await newTableModalOne.locator('input[name="table-rows"]').fill('3');
+ await newTableModalOne.locator('input[name="table-columns"]').fill('2');
+
+ await newTableModalOne.locator('button[data-selector-name="ok-button"]').click();
+
+ await expect(newTableModalOne).toBeHidden();
+
+ await expect(comboboxOne).toHaveValue('| Header | Header |\n|---------|---------|\n| Content | Content |\n| Content | Content |\n| Content | Content |\n');
+ await expect(comboboxTwo).toBeEmpty();
+ await save_visual(page);
+
+ // focus second one and add table to it
+ await textareaTwo.click();
+ await expect(comboboxOne).toBeHidden();
+ await expect(comboboxTwo).toBeVisible();
+
+ const newTableButtonTwo = page.locator('[for="_combo_markdown_editor_1"] button[data-md-action="new-table"]');
+ await newTableButtonTwo.click();
+
+ const newTableModalTwo = page.locator('div[data-markdown-table-modal-id="1"]');
+ await expect(newTableModalTwo).toBeVisible();
+
+ await newTableModalTwo.locator('input[name="table-rows"]').fill('2');
+ await newTableModalTwo.locator('input[name="table-columns"]').fill('3');
+
+ await newTableModalTwo.locator('button[data-selector-name="ok-button"]').click();
+
+ await expect(newTableModalTwo).toBeHidden();
+
+ await expect(comboboxOne).toHaveValue('| Header | Header |\n|---------|---------|\n| Content | Content |\n| Content | Content |\n| Content | Content |\n');
+ await expect(comboboxTwo).toHaveValue('| Header | Header | Header |\n|---------|---------|---------|\n| Content | Content | Content |\n| Content | Content | Content |\n');
+ await save_visual(page);
+});
diff --git a/tests/e2e/markup.test.e2e.ts b/tests/e2e/markup.test.e2e.ts
index 398a0a6300..b26e83661b 100644
--- a/tests/e2e/markup.test.e2e.ts
+++ b/tests/e2e/markup.test.e2e.ts
@@ -5,7 +5,8 @@
import {expect} from '@playwright/test';
import {save_visual, test} from './utils_e2e.ts';
-test('markup with #xyz-mode-only', async ({page}) => {
+test('markup with #xyz-mode-only', async ({page}, workerInfo) => {
+ test.skip(['webkit', 'Mobile Safari'].includes(workerInfo.project.name), 'Newest version contains a regression');
const response = await page.goto('/user2/repo1/issues/1');
expect(response?.status()).toBe(200);
diff --git a/tests/e2e/release.test.e2e.ts b/tests/e2e/release.test.e2e.ts
index 044e7b93ab..a4303a7320 100644
--- a/tests/e2e/release.test.e2e.ts
+++ b/tests/e2e/release.test.e2e.ts
@@ -14,78 +14,100 @@ import {validate_form} from './shared/forms.ts';
test.use({user: 'user2'});
-test.describe.configure({
- timeout: 30000,
-});
-
-test('External Release Attachments', async ({page, isMobile}) => {
- test.skip(isMobile);
-
- // Click "New Release"
- await page.goto('/user2/repo2/releases');
- await page.click('.button.small.primary');
-
- // Fill out form and create new release
- await expect(page).toHaveURL('/user2/repo2/releases/new');
- await validate_form({page}, 'fieldset');
- const textarea = page.locator('input[name=tag_name]');
- await textarea.pressSequentially('2.0');
- await expect(page.locator('input[name=title]')).toHaveValue('2.0');
- await page.click('#add-external-link');
- await page.click('#add-external-link');
- await page.fill('input[name=attachment-new-name-2]', 'Test');
- await page.fill('input[name=attachment-new-exturl-2]', 'https://forgejo.org/');
- await page.click('.remove-rel-attach');
- await save_visual(page);
- await page.click('.button.small.primary');
-
- // Validate release page and click edit
- await expect(page).toHaveURL('/user2/repo2/releases');
- await expect(page.locator('.download[open] li')).toHaveCount(3);
-
- await expect(page.locator('.download[open] li:nth-of-type(1)')).toContainText('Source code (ZIP)');
- await expect(page.locator('.download[open] li:nth-of-type(1) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.');
- await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.zip');
- await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('type', 'application/zip');
-
- await expect(page.locator('.download[open] li:nth-of-type(2)')).toContainText('Source code (TAR.GZ)');
- await expect(page.locator('.download[open] li:nth-of-type(2) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.');
- await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.tar.gz');
- await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('type', 'application/gzip');
-
- await expect(page.locator('.download[open] li:nth-of-type(3)')).toContainText('Test');
- await expect(page.locator('.download[open] li:nth-of-type(3) a')).toHaveAttribute('href', 'https://forgejo.org/');
- await save_visual(page);
- await page.locator('.octicon-pencil').first().click();
-
- // Validate edit page and edit the release
- await expect(page).toHaveURL('/user2/repo2/releases/edit/2.0');
- await validate_form({page}, 'fieldset');
- await expect(page.locator('.attachment_edit:visible')).toHaveCount(2);
- await expect(page.locator('.attachment_edit:visible').nth(0)).toHaveValue('Test');
- await expect(page.locator('.attachment_edit:visible').nth(1)).toHaveValue('https://forgejo.org/');
- await page.locator('.attachment_edit:visible').nth(0).fill('Test2');
- await page.locator('.attachment_edit:visible').nth(1).fill('https://gitea.io/');
- await page.click('#add-external-link');
- await expect(page.locator('.attachment_edit:visible')).toHaveCount(4);
- await page.locator('.attachment_edit:visible').nth(2).fill('Test3');
- await page.locator('.attachment_edit:visible').nth(3).fill('https://gitea.com/');
- await save_visual(page);
- await page.click('.button.small.primary');
-
- // Validate release page and click edit
- await expect(page).toHaveURL('/user2/repo2/releases');
- await expect(page.locator('.download[open] li')).toHaveCount(4);
- await expect(page.locator('.download[open] li:nth-of-type(3)')).toContainText('Test2');
- await expect(page.locator('.download[open] li:nth-of-type(3) a')).toHaveAttribute('href', 'https://gitea.io/');
- await expect(page.locator('.download[open] li:nth-of-type(4)')).toContainText('Test3');
- await expect(page.locator('.download[open] li:nth-of-type(4) a')).toHaveAttribute('href', 'https://gitea.com/');
- await save_visual(page);
- await page.locator('.octicon-pencil').first().click();
-
- // Delete release
- await expect(page).toHaveURL('/user2/repo2/releases/edit/2.0');
- await page.click('.delete-button');
- await page.click('.button.ok');
- await expect(page).toHaveURL('/user2/repo2/releases');
+test.describe('repo branch protection settings', () => {
+ test('External Release Attachments', async ({page, isMobile}, workerInfo) => {
+ test.skip(isMobile || workerInfo.project.name === 'webkit');
+
+ // Click "New Release"
+ await page.goto('/user2/repo2/releases');
+ await page.click('.button.small.primary');
+
+ // Fill out form and create new release
+ await expect(page).toHaveURL('/user2/repo2/releases/new');
+ await validate_form({page}, 'fieldset');
+ const textarea = page.locator('input[name=tag_name]');
+ await textarea.pressSequentially('2.0');
+ await expect(page.locator('input[name=title]')).toHaveValue('2.0');
+ await page.click('#add-external-link');
+ await page.click('#add-external-link');
+ await page.fill('input[name=attachment-new-name-2]', 'Test');
+ await page.fill('input[name=attachment-new-exturl-2]', 'https://forgejo.org/');
+ await page.click('.remove-rel-attach');
+ await save_visual(page);
+ await page.click('.button.small.primary');
+
+ // Validate release page and click edit
+ await expect(page).toHaveURL('/user2/repo2/releases');
+ await expect(page.locator('.download[open] li')).toHaveCount(3);
+
+ await expect(page.locator('.download[open] li:nth-of-type(1)')).toContainText('Source code (ZIP)');
+ await expect(page.locator('.download[open] li:nth-of-type(1) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.');
+ await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.zip');
+ await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('type', 'application/zip');
+
+ await expect(page.locator('.download[open] li:nth-of-type(2)')).toContainText('Source code (TAR.GZ)');
+ await expect(page.locator('.download[open] li:nth-of-type(2) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.');
+ await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.tar.gz');
+ await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('type', 'application/gzip');
+
+ await expect(page.locator('.download[open] li:nth-of-type(3)')).toContainText('Test');
+ await expect(page.locator('.download[open] li:nth-of-type(3) a')).toHaveAttribute('href', 'https://forgejo.org/');
+ await save_visual(page);
+ await page.locator('.octicon-pencil').first().click();
+
+ // Validate edit page and edit the release
+ await expect(page).toHaveURL('/user2/repo2/releases/edit/2.0');
+ await validate_form({page}, 'fieldset');
+ await expect(page.locator('.attachment_edit:visible')).toHaveCount(2);
+ await expect(page.locator('.attachment_edit:visible').nth(0)).toHaveValue('Test');
+ await expect(page.locator('.attachment_edit:visible').nth(1)).toHaveValue('https://forgejo.org/');
+ await page.locator('.attachment_edit:visible').nth(0).fill('Test2');
+ await page.locator('.attachment_edit:visible').nth(1).fill('https://gitea.io/');
+ await page.click('#add-external-link');
+ await expect(page.locator('.attachment_edit:visible')).toHaveCount(4);
+ await page.locator('.attachment_edit:visible').nth(2).fill('Test3');
+ await page.locator('.attachment_edit:visible').nth(3).fill('https://gitea.com/');
+ await save_visual(page);
+ await page.click('.button.small.primary');
+
+ // Validate release page and click edit
+ await expect(page).toHaveURL('/user2/repo2/releases');
+ await expect(page.locator('.download[open] li')).toHaveCount(4);
+ await expect(page.locator('.download[open] li:nth-of-type(3)')).toContainText('Test2');
+ await expect(page.locator('.download[open] li:nth-of-type(3) a')).toHaveAttribute('href', 'https://gitea.io/');
+ await expect(page.locator('.download[open] li:nth-of-type(4)')).toContainText('Test3');
+ await expect(page.locator('.download[open] li:nth-of-type(4) a')).toHaveAttribute('href', 'https://gitea.com/');
+ await save_visual(page);
+ await page.locator('.octicon-pencil').first().click();
+ });
+
+ test('Release name equals tag name if created from tag', async ({page}) => {
+ await page.goto('/user2/repo2/releases/new?tag=v1.1');
+
+ await expect(page.locator('input[name=title]')).toHaveValue('v1.1');
+ });
+
+ test('Release name equals release name if edit', async ({page, isMobile}) => {
+ test.skip(isMobile);
+
+ await page.goto('/user2/repo2/releases/new');
+
+ await page.locator('input[name=title]').pressSequentially('v2.0');
+ await page.locator('input[name=tag_name]').pressSequentially('2.0');
+ await page.click('.button.small.primary');
+
+ await page.goto('/user2/repo2/releases/edit/2.0');
+
+ await expect(page.locator('input[name=title]')).toHaveValue('v2.0');
+ });
+
+ test.afterEach(async ({page}) => {
+ // Delete release
+ const response = await page.goto('/user2/repo2/releases/edit/2.0');
+ test.skip(response.status() === 404, 'No release to delete');
+
+ await page.locator('.delete-button').dispatchEvent('click');
+ await page.locator('.button.ok').click();
+ await expect(page).toHaveURL('/user2/repo2/releases');
+ });
});
diff --git a/tests/e2e/webauthn.test.e2e.ts b/tests/e2e/webauthn.test.e2e.ts
index 0b5a6a6c2b..d4b81621d2 100644
--- a/tests/e2e/webauthn.test.e2e.ts
+++ b/tests/e2e/webauthn.test.e2e.ts
@@ -42,7 +42,6 @@ test('WebAuthn register & login flow', async ({browser, request}, workerInfo) =>
await page.locator('div[aria-label="Profile and settings…"]').click();
await page.getByText('Sign out').click();
}).toPass();
- await page.waitForURL(`${workerInfo.project.use.baseURL}/`);
// Login.
response = await page.goto('/user/login');
diff --git a/tests/integration/actions_run_now_done_notification_test.go b/tests/integration/actions_run_now_done_notification_test.go
index d5142096c5..480d67a73d 100644
--- a/tests/integration/actions_run_now_done_notification_test.go
+++ b/tests/integration/actions_run_now_done_notification_test.go
@@ -49,41 +49,22 @@ func (m *mockNotifier) ActionRunNowDone(ctx context.Context, run *actions_model.
assert.Equal(m.t, m.runID, run.ID)
assert.Equal(m.t, actions_model.StatusFailure, run.Status)
assert.Equal(m.t, actions_model.StatusRunning, priorStatus)
- assert.Equal(m.t, m.lastRunID, lastRun.ID)
- assert.Equal(m.t, actions_model.StatusSuccess, lastRun.Status)
assert.True(m.t, run.NotifyEmail)
case 2:
assert.Equal(m.t, m.runID, run.ID)
assert.Equal(m.t, actions_model.StatusCancelled, run.Status)
assert.Equal(m.t, actions_model.StatusRunning, priorStatus)
- assert.Equal(m.t, m.lastRunID, lastRun.ID)
- assert.Equal(m.t, actions_model.StatusFailure, lastRun.Status)
- assert.True(m.t, run.NotifyEmail)
- case 3:
- assert.Equal(m.t, m.runID, run.ID)
- assert.Equal(m.t, actions_model.StatusSuccess, run.Status)
- assert.Equal(m.t, actions_model.StatusRunning, priorStatus)
- assert.Equal(m.t, m.lastRunID, lastRun.ID)
- assert.Equal(m.t, actions_model.StatusCancelled, lastRun.Status)
- assert.True(m.t, run.NotifyEmail)
- case 4:
- assert.Equal(m.t, m.runID, run.ID)
- assert.Equal(m.t, actions_model.StatusSuccess, run.Status)
- assert.Equal(m.t, actions_model.StatusRunning, priorStatus)
- assert.Equal(m.t, m.lastRunID, lastRun.ID)
- assert.Equal(m.t, actions_model.StatusSuccess, lastRun.Status)
assert.True(m.t, run.NotifyEmail)
default:
assert.Fail(m.t, "too many notifications")
}
- m.lastRunID = m.runID
m.runID++
m.testIdx++
}
// ensure all tests have been run
func (m *mockNotifier) complete() {
- assert.Equal(m.t, 5, m.testIdx)
+ assert.Equal(m.t, 3, m.testIdx)
}
func TestActionNowDoneNotification(t *testing.T) {
@@ -159,24 +140,6 @@ func TestActionNowDoneNotification(t *testing.T) {
task = runner.fetchTask(t)
require.NoError(t, actions_service.StopTask(db.DefaultContext, task.Id, actions_model.StatusCancelled))
- // we can't differentiate different runs without a delay
- time.Sleep(time.Millisecond * 2000)
-
- // 3: successful run after failure
- _, _, err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2)
- require.NoError(t, err)
- task = runner.fetchTask(t)
- runner.succeedAtTask(t, task)
-
- // we can't differentiate different runs without a delay
- time.Sleep(time.Millisecond * 2000)
-
- // 4: successful run after success
- _, _, err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2)
- require.NoError(t, err)
- task = runner.fetchTask(t)
- runner.succeedAtTask(t, task)
-
notifier.complete()
})
}
diff --git a/tests/integration/api_block_test.go b/tests/integration/api_block_test.go
index 8b25ce9283..0e2cf7ee25 100644
--- a/tests/integration/api_block_test.go
+++ b/tests/integration/api_block_test.go
@@ -4,8 +4,10 @@
package integration
import (
+ "cmp"
"fmt"
"net/http"
+ "slices"
"testing"
auth_model "forgejo.org/models/auth"
@@ -46,6 +48,7 @@ func TestAPIUserBlock(t *testing.T) {
var blockedUsers []api.BlockedUser
DecodeJSON(t, resp, &blockedUsers)
assert.Len(t, blockedUsers, 2)
+ slices.SortFunc(blockedUsers, func(a, b api.BlockedUser) int { return cmp.Compare(a.BlockID, b.BlockID) })
assert.EqualValues(t, 1, blockedUsers[0].BlockID)
assert.EqualValues(t, 2, blockedUsers[1].BlockID)
})
diff --git a/tests/integration/api_branch_test.go b/tests/integration/api_branch_test.go
index 8e88501596..d8800217d3 100644
--- a/tests/integration/api_branch_test.go
+++ b/tests/integration/api_branch_test.go
@@ -116,7 +116,7 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
ctx := NewAPITestContext(t, "user2", "my-noo-repo-"+objectFormat.Name(), auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
giteaURL.Path = ctx.GitPath()
- t.Run("CreateRepo", doAPICreateRepository(ctx, false, objectFormat))
+ t.Run("CreateRepo", doAPICreateRepository(ctx, nil, objectFormat))
testCases := []struct {
OldBranch string
NewBranch string
diff --git a/tests/integration/api_helper_for_declarative_test.go b/tests/integration/api_helper_for_declarative_test.go
index c9b6f84f4f..ada6a2c311 100644
--- a/tests/integration/api_helper_for_declarative_test.go
+++ b/tests/integration/api_helper_for_declarative_test.go
@@ -48,20 +48,22 @@ func (ctx APITestContext) GitPath() string {
return fmt.Sprintf("%s/%s.git", ctx.Username, ctx.Reponame)
}
-func doAPICreateRepository(ctx APITestContext, empty bool, objectFormat git.ObjectFormat, callback ...func(*testing.T, api.Repository)) func(*testing.T) {
+func doAPICreateRepository(ctx APITestContext, opts *api.CreateRepoOption, objectFormat git.ObjectFormat, callback ...func(*testing.T, api.Repository)) func(*testing.T) {
return func(t *testing.T) {
- createRepoOption := &api.CreateRepoOption{
- AutoInit: !empty,
- Description: "Temporary repo",
- Name: ctx.Reponame,
- Private: true,
- Template: true,
- Gitignores: "",
- License: "WTFPL",
- Readme: "Default",
- ObjectFormatName: objectFormat.Name(),
+ if opts == nil {
+ opts = &api.CreateRepoOption{
+ AutoInit: true,
+ Description: "Temporary repo",
+ Name: ctx.Reponame,
+ Private: true,
+ Template: true,
+ Gitignores: "",
+ License: "WTFPL",
+ Readme: "Default",
+ }
}
- req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", createRepoOption).
+ opts.ObjectFormatName = objectFormat.Name()
+ req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", opts).
AddTokenAuth(ctx.Token)
if ctx.ExpectedCode != 0 {
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
@@ -237,8 +239,8 @@ func doAPICreatePullRequest(ctx APITestContext, owner, repo, baseBranch, headBra
}
}
-func doAPIGetPullRequest(ctx APITestContext, owner, repo string, index int64) func(*testing.T) (api.PullRequest, error) {
- return func(t *testing.T) (api.PullRequest, error) {
+func doAPIGetPullRequest(ctx APITestContext, owner, repo string, index int64) func(*testing.T) api.PullRequest {
+ return func(t *testing.T) api.PullRequest {
req := NewRequest(t, http.MethodGet, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner, repo, index)).
AddTokenAuth(ctx.Token)
@@ -248,10 +250,9 @@ func doAPIGetPullRequest(ctx APITestContext, owner, repo string, index int64) fu
}
resp := ctx.Session.MakeRequest(t, req, expected)
- decoder := json.NewDecoder(resp.Body)
pr := api.PullRequest{}
- err := decoder.Decode(&pr)
- return pr, err
+ DecodeJSON(t, resp, &pr)
+ return pr
}
}
@@ -347,20 +348,40 @@ func doAPICancelAutoMergePullRequest(ctx APITestContext, owner, repo string, ind
}
}
-func doAPIGetBranch(ctx APITestContext, branch string, callback ...func(*testing.T, api.Branch)) func(*testing.T) {
- return func(t *testing.T) {
+func doAPIGetBranch(ctx APITestContext, branch string) func(*testing.T) api.Branch {
+ return func(t *testing.T) api.Branch {
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/branches/%s", ctx.Username, ctx.Reponame, branch).
AddTokenAuth(ctx.Token)
+ expected := http.StatusOK
+ if ctx.ExpectedCode != 0 {
+ expected = ctx.ExpectedCode
+ }
+ resp := ctx.Session.MakeRequest(t, req, expected)
+
+ branch := api.Branch{}
+ DecodeJSON(t, resp, &branch)
+ return branch
+ }
+}
+
+func doAPICreateTag(ctx APITestContext, tag, target, message string, callback ...func(*testing.T, api.Tag)) func(*testing.T) {
+ return func(t *testing.T) {
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/tags", ctx.Username, ctx.Reponame), &api.CreateTagOption{
+ TagName: tag,
+ Message: message,
+ Target: target,
+ }).
+ AddTokenAuth(ctx.Token)
if ctx.ExpectedCode != 0 {
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
return
}
- resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
+ resp := ctx.Session.MakeRequest(t, req, http.StatusCreated)
- var branch api.Branch
- DecodeJSON(t, resp, &branch)
+ var tag api.Tag
+ DecodeJSON(t, resp, &tag)
if len(callback) > 0 {
- callback[0](t, branch)
+ callback[0](t, tag)
}
}
}
diff --git a/tests/integration/api_packages_alt_test.go b/tests/integration/api_packages_alt_test.go
index c7ee2c49a5..f43759364e 100644
--- a/tests/integration/api_packages_alt_test.go
+++ b/tests/integration/api_packages_alt_test.go
@@ -214,7 +214,7 @@ enabled=1`,
}
assert.Equal(t, "classic", result.Component)
- assert.Equal(t, "Alt Linux Team", result.Origin)
+ assert.Equal(t, "Forgejo", result.Origin)
assert.Equal(t, "Forgejo", result.Label)
assert.Equal(t, "x86_64", result.Architecture)
assert.False(t, result.NotAutomatic)
@@ -299,17 +299,17 @@ enabled=1`,
assert.Equal(t, "Forgejo", result.Origin)
assert.Equal(t, "Forgejo", result.Label)
- assert.Equal(t, "Sisyphus", result.Suite)
+ assert.Equal(t, "Unknown", result.Suite)
assert.Equal(t, "x86_64", result.Architectures)
assert.Len(t, result.MD5Sum, 3)
- assert.Equal(t, "bbf7ae6b2f540673ed1cfc0266b5f319", result.MD5Sum[0].Hash)
- assert.Equal(t, 1003, result.MD5Sum[0].Size)
+ assert.Equal(t, "3f25f44163e8e512efb248d3b96949c3", result.MD5Sum[0].Hash)
+ assert.Equal(t, 1147, result.MD5Sum[0].Size)
assert.Equal(t, "base/pkglist.classic", result.MD5Sum[0].File)
assert.Len(t, result.BLAKE2B, 3)
- assert.Equal(t, "b527bf038895ce29107ec3a6d2eebd7c365e8ce5ab767276eeddd7c549a159025225cb0ecfdbf7b71da13db7e865e77bcb0e2dae4d21335df01a4a17e0056a70", result.BLAKE2B[0].Hash)
- assert.Equal(t, 1003, result.BLAKE2B[0].Size)
+ assert.Equal(t, "21a63e12a41f70e0697d354ae31e22ad6f024ec5ead2ea498b9a1b7db0f98a4e441f46c96d6912fba19148ff013457561fbb9bf3fca2a21d04cf15a325be7de9", result.BLAKE2B[0].Hash)
+ assert.Equal(t, 1147, result.BLAKE2B[0].Size)
assert.Equal(t, "base/pkglist.classic", result.BLAKE2B[0].File)
})
@@ -567,9 +567,9 @@ enabled=1`,
assert.Equal(t, "https://gitea.io", result.URL)
assert.Equal(t, "x86_64", result.Arch)
assert.Equal(t, "gitea-test-1.0.2-1.src.rpm", result.SourceRpm)
- assert.Equal(t, []string{"", ""}, result.ProvideNames)
+ assert.Equal(t, []string{"gitea-test(x86-64)", "gitea-test(x86-64)"}, result.ProvideNames)
assert.Equal(t, []int{16777226, 16777226, 16777226, 16777226, 16777226, 16777226, 16777226}, result.RequireFlags)
- assert.Equal(t, []string{"", "", "", "", "", "", ""}, result.RequireNames)
+ assert.Equal(t, []string{"rpmlib(PayloadIsXz)", "rpmlib(PayloadIsXz)", "rpmlib(PayloadIsXz)", "rpmlib(PayloadIsXz)", "rpmlib(PayloadIsXz)", "rpmlib(PayloadIsXz)", "rpmlib(PayloadIsXz)"}, result.RequireNames)
assert.Equal(t, []string{"5.2-1", "5.2-1", "5.2-1", "5.2-1", "5.2-1", "5.2-1", "5.2-1"}, result.RequireVersions)
assert.Equal(t, []int{1678276800}, result.ChangeLogTimes)
assert.Equal(t, []string{"KN4CK3R "}, result.ChangeLogNames)
diff --git a/tests/integration/api_repo_compare_test.go b/tests/integration/api_repo_compare_test.go
index 35f0a21d82..e4e85fc742 100644
--- a/tests/integration/api_repo_compare_test.go
+++ b/tests/integration/api_repo_compare_test.go
@@ -4,56 +4,200 @@
package integration
import (
+ "encoding/base64"
+ "fmt"
"net/http"
+ "net/url"
"testing"
+ "time"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
+ "forgejo.org/modules/git"
api "forgejo.org/modules/structs"
- "forgejo.org/tests"
"github.com/stretchr/testify/assert"
)
-func TestAPICompareBranches(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
- user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- // Login as User2.
- session := loginUser(t, user.Name)
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
-
- repoName := "repo20"
-
- req := NewRequestf(t, "GET", "/api/v1/repos/user2/%s/compare/add-csv...remove-files-b", repoName).
- AddTokenAuth(token)
- resp := MakeRequest(t, req, http.StatusOK)
-
- var apiResp *api.Compare
- DecodeJSON(t, resp, &apiResp)
-
- assert.Equal(t, 2, apiResp.TotalCommits)
- assert.Len(t, apiResp.Commits, 2)
- assert.Len(t, apiResp.Files, 3)
-}
-
func TestAPICompareCommits(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
- user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- // Login as User2.
- session := loginUser(t, user.Name)
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
-
- req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/c8e31bc...8babce9").
- AddTokenAuth(token)
- resp := MakeRequest(t, req, http.StatusOK)
-
- var apiResp *api.Compare
- DecodeJSON(t, resp, &apiResp)
-
- assert.Equal(t, 2, apiResp.TotalCommits)
- assert.Len(t, apiResp.Commits, 2)
- assert.Len(t, apiResp.Files, 3)
+ forEachObjectFormat(t, testAPICompareCommits)
+}
+
+func testAPICompareCommits(t *testing.T, objectFormat git.ObjectFormat) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ newBranchAndFile := func(ctx APITestContext, user *user_model.User, branch, filename string) func(*testing.T) {
+ return func(t *testing.T) {
+ doAPICreateFile(ctx, filename, &api.CreateFileOptions{
+ FileOptions: api.FileOptions{
+ NewBranchName: branch,
+ Message: "create " + filename,
+ Author: api.Identity{
+ Name: user.Name,
+ Email: user.Email,
+ },
+ Committer: api.Identity{
+ Name: user.Name,
+ Email: user.Email,
+ },
+ Dates: api.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ },
+ ContentBase64: base64.StdEncoding.EncodeToString([]byte("content " + filename)),
+ })(t)
+ }
+ }
+
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ user2repo := "repoA"
+ user2Ctx := NewAPITestContext(t, user2.Name, user2repo, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ t.Run("CreateUser2Repository", doAPICreateRepository(user2Ctx, &api.CreateRepoOption{
+ AutoInit: true,
+ Description: "Temporary repo",
+ Name: user2Ctx.Reponame,
+ }, objectFormat))
+ user2branchName := "user2branch"
+ t.Run("CreateUser2RepositoryBranch", newBranchAndFile(user2Ctx, user2, user2branchName, "user2branchfilename.txt"))
+ user2branch := doAPIGetBranch(user2Ctx, user2branchName)(t)
+ user2master := doAPIGetBranch(user2Ctx, "master")(t)
+ user2tag1 := "tag1"
+ t.Run("CreateUser2RepositoryTag1", doAPICreateTag(user2Ctx, user2tag1, "master", "user2branchtag1"))
+ user2tag2 := "tag2"
+ t.Run("CreateUser2RepositoryTag1", doAPICreateTag(user2Ctx, user2tag2, user2branchName, "user2branchtag2"))
+
+ shortCommitLength := 7
+
+ for _, testCase := range []struct {
+ name string
+ a string
+ b string
+ }{
+ {
+ name: "Commits",
+ a: user2master.Commit.ID,
+ b: user2branch.Commit.ID,
+ },
+ {
+ name: "ShortCommits",
+ a: user2master.Commit.ID[:shortCommitLength],
+ b: user2branch.Commit.ID[:shortCommitLength],
+ },
+ {
+ name: "Branches",
+ a: "master",
+ b: user2branchName,
+ },
+ {
+ name: "Tags",
+ a: user2tag1,
+ b: user2tag2,
+ },
+ } {
+ t.Run("SameRepo"+testCase.name, func(t *testing.T) {
+ // a...b
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/compare/%s...%s", user2.Name, user2repo, testCase.a, testCase.b).
+ AddTokenAuth(user2Ctx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ var apiResp *api.Compare
+ DecodeJSON(t, resp, &apiResp)
+
+ assert.Equal(t, 1, apiResp.TotalCommits)
+ assert.Len(t, apiResp.Commits, 1)
+ assert.Len(t, apiResp.Files, 1)
+
+ // b...a
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/compare/%s...%s", user2.Name, user2repo, testCase.b, testCase.a).
+ AddTokenAuth(user2Ctx.Token)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ DecodeJSON(t, resp, &apiResp)
+
+ assert.Equal(t, 0, apiResp.TotalCommits)
+ assert.Empty(t, apiResp.Commits)
+ assert.Empty(t, apiResp.Files)
+ })
+ }
+
+ user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
+ user4Ctx := NewAPITestContext(t, user4.Name, user2repo, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ t.Run("User4ForksUser2Repository", doAPIForkRepository(user4Ctx, user2.Name))
+ user4branchName := "user4branch"
+ t.Run("CreateUser4RepositoryBranch", newBranchAndFile(user4Ctx, user4, user4branchName, "user4branchfilename.txt"))
+ user4branch := doAPIGetBranch(user4Ctx, user4branchName)(t)
+ user4tag4 := "tag4"
+ t.Run("CreateUser4RepositoryTag4", doAPICreateTag(user4Ctx, user4tag4, user4branchName, "user4branchtag4"))
+
+ t.Run("FromTheForkedRepo", func(t *testing.T) {
+ // user4/repoA is a fork of user2/repoA and when evaluating
+ //
+ // user4/repoA/compare/master...user2:user2branch
+ //
+ // user2/repoA is not explicitly specified, it is implicitly the repository
+ // from which user4/repoA was forked
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/compare/%s...%s:%s", user4.Name, user2repo, "master", user2.Name, user2branchName).
+ AddTokenAuth(user4Ctx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ var apiResp *api.Compare
+ DecodeJSON(t, resp, &apiResp)
+
+ assert.Equal(t, 1, apiResp.TotalCommits)
+ assert.Len(t, apiResp.Commits, 1)
+ assert.Len(t, apiResp.Files, 1)
+ })
+
+ for _, testCase := range []struct {
+ name string
+ a string
+ b string
+ }{
+ {
+ name: "Commits",
+ a: user2master.Commit.ID,
+ b: fmt.Sprintf("%s:%s", user4.Name, user4branch.Commit.ID),
+ },
+ {
+ name: "ShortCommits",
+ a: user2master.Commit.ID[:shortCommitLength],
+ b: fmt.Sprintf("%s:%s", user4.Name, user4branch.Commit.ID[:shortCommitLength]),
+ },
+ {
+ name: "Branches",
+ a: "master",
+ b: fmt.Sprintf("%s:%s", user4.Name, user4branchName),
+ },
+ {
+ name: "Tags",
+ a: user2tag1,
+ b: fmt.Sprintf("%s:%s", user4.Name, user4tag4),
+ },
+ {
+ name: "SameRepo",
+ a: "master",
+ b: fmt.Sprintf("%s:%s", user2.Name, user2branchName),
+ },
+ } {
+ t.Run("ForkedRepo"+testCase.name, func(t *testing.T) {
+ // user2/repoA is forked into user4/repoA and when evaluating
+ //
+ // user2/repoA/compare/a...user4:b
+ //
+ // user4/repoA is not explicitly specified, it is implicitly the repository
+ // owned by user4 which is a fork of repoA
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/compare/%s...%s", user2.Name, user2repo, testCase.a, testCase.b).
+ AddTokenAuth(user2Ctx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ var apiResp *api.Compare
+ DecodeJSON(t, resp, &apiResp)
+
+ assert.Equal(t, 1, apiResp.TotalCommits)
+ assert.Len(t, apiResp.Commits, 1)
+ assert.Len(t, apiResp.Files, 1)
+ })
+ }
+ })
}
diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go
index c112653e11..4916ef97ef 100644
--- a/tests/integration/api_repo_file_create_test.go
+++ b/tests/integration/api_repo_file_create_test.go
@@ -287,7 +287,14 @@ func TestAPICreateFile(t *testing.T) {
// Test creating a file in an empty repository
forEachObjectFormat(t, func(t *testing.T, objectFormat git.ObjectFormat) {
reponame := "empty-repo-" + objectFormat.Name()
- doAPICreateRepository(NewAPITestContext(t, "user2", reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser), true, objectFormat)(t)
+ ctx := NewAPITestContext(t, "user2", reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ opts := &api.CreateRepoOption{
+ Description: "Temporary repo",
+ Name: ctx.Reponame,
+ Private: true,
+ Template: true,
+ }
+ doAPICreateRepository(ctx, opts, objectFormat)(t)
createFileOptions = getCreateFileOptions()
fileID++
treePath = fmt.Sprintf("new/file%d.txt", fileID)
diff --git a/tests/integration/api_repo_file_get_test.go b/tests/integration/api_repo_file_get_test.go
index 7bd7393b01..408c630a1c 100644
--- a/tests/integration/api_repo_file_get_test.go
+++ b/tests/integration/api_repo_file_get_test.go
@@ -27,7 +27,7 @@ func TestAPIGetRawFileOrLFS(t *testing.T) {
// Test with LFS
onGiteaRun(t, func(t *testing.T, u *url.URL) {
httpContext := NewAPITestContext(t, "user2", "repo-lfs-test", auth_model.AccessTokenScopeWriteRepository)
- doAPICreateRepository(httpContext, false, git.Sha1ObjectFormat, func(t *testing.T, repository api.Repository) { // FIXME: use forEachObjectFormat
+ doAPICreateRepository(httpContext, nil, git.Sha1ObjectFormat, func(t *testing.T, repository api.Repository) { // FIXME: use forEachObjectFormat
u.Path = httpContext.GitPath()
dstPath := t.TempDir()
diff --git a/tests/integration/api_repo_lfs_test.go b/tests/integration/api_repo_lfs_test.go
index b8ba54f876..b0edf7b854 100644
--- a/tests/integration/api_repo_lfs_test.go
+++ b/tests/integration/api_repo_lfs_test.go
@@ -64,7 +64,7 @@ func TestAPILFSMediaType(t *testing.T) {
func createLFSTestRepository(t *testing.T, name string) *repo_model.Repository {
ctx := NewAPITestContext(t, "user2", "lfs-"+name+"-repo", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepo", doAPICreateRepository(ctx, false, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
+ t.Run("CreateRepo", doAPICreateRepository(ctx, nil, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "lfs-"+name+"-repo")
require.NoError(t, err)
diff --git a/tests/integration/api_repo_test.go b/tests/integration/api_repo_test.go
index fd62670eb3..e81f4307ee 100644
--- a/tests/integration/api_repo_test.go
+++ b/tests/integration/api_repo_test.go
@@ -415,7 +415,7 @@ func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
httpContext := baseAPITestContext
httpContext.Reponame = "repo-tmp-17"
- t.Run("CreateRepo", doAPICreateRepository(httpContext, false, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
+ t.Run("CreateRepo", doAPICreateRepository(httpContext, nil, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
user, err := user_model.GetUserByName(db.DefaultContext, httpContext.Username)
require.NoError(t, err)
@@ -498,7 +498,7 @@ func testAPIRepoCreateConflict(t *testing.T, u *url.URL) {
httpContext := baseAPITestContext
httpContext.Reponame = "repo-tmp-17"
- t.Run("CreateRepo", doAPICreateRepository(httpContext, false, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
+ t.Run("CreateRepo", doAPICreateRepository(httpContext, nil, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos",
&api.CreateRepoOption{
diff --git a/tests/integration/db_collation_test.go b/tests/integration/db_collation_test.go
index bf55bdd8ee..c41209f1fe 100644
--- a/tests/integration/db_collation_test.go
+++ b/tests/integration/db_collation_test.go
@@ -7,6 +7,7 @@ package integration
import (
"net/http"
"testing"
+ "time"
"forgejo.org/models/db"
"forgejo.org/modules/setting"
@@ -97,9 +98,13 @@ func TestDatabaseCollation(t *testing.T) {
defer test.MockVariableValue(&setting.Database.CharsetCollation, "utf8mb4_bin")()
require.NoError(t, db.ConvertDatabaseTable())
- r, err := db.CheckCollations(x)
- require.NoError(t, err)
- assert.Equal(t, "utf8mb4_bin", r.DatabaseCollation)
+ var r *db.CheckCollationsResult
+ assert.Eventually(t, func() bool {
+ r, err = db.CheckCollations(x)
+ require.NoError(t, err)
+
+ return r.DatabaseCollation == "utf8mb4_bin"
+ }, time.Second*30, time.Second)
assert.True(t, r.CollationEquals(r.ExpectedCollation, r.DatabaseCollation))
assert.Empty(t, r.InconsistentCollationColumns)
@@ -117,9 +122,13 @@ func TestDatabaseCollation(t *testing.T) {
defer test.MockVariableValue(&setting.Database.CharsetCollation, "utf8mb4_general_ci")()
require.NoError(t, db.ConvertDatabaseTable())
- r, err := db.CheckCollations(x)
- require.NoError(t, err)
- assert.Equal(t, "utf8mb4_general_ci", r.DatabaseCollation)
+ var r *db.CheckCollationsResult
+ assert.Eventually(t, func() bool {
+ r, err = db.CheckCollations(x)
+ require.NoError(t, err)
+
+ return r.DatabaseCollation == "utf8mb4_general_ci"
+ }, time.Second*30, time.Second)
assert.True(t, r.CollationEquals(r.ExpectedCollation, r.DatabaseCollation))
assert.Empty(t, r.InconsistentCollationColumns)
@@ -137,9 +146,15 @@ func TestDatabaseCollation(t *testing.T) {
defer test.MockVariableValue(&setting.Database.CharsetCollation, "")()
require.NoError(t, db.ConvertDatabaseTable())
+ var r *db.CheckCollationsResult
r, err := db.CheckCollations(x)
require.NoError(t, err)
- assert.True(t, r.IsCollationCaseSensitive(r.DatabaseCollation))
+ assert.Eventually(t, func() bool {
+ r, err = db.CheckCollations(x)
+ require.NoError(t, err)
+
+ return r.IsCollationCaseSensitive(r.DatabaseCollation)
+ }, time.Second*30, time.Second)
assert.True(t, r.CollationEquals(r.ExpectedCollation, r.DatabaseCollation))
assert.Empty(t, r.InconsistentCollationColumns)
})
diff --git a/tests/integration/git_test.go b/tests/integration/git_test.go
index e79f6fe802..9a66781024 100644
--- a/tests/integration/git_test.go
+++ b/tests/integration/git_test.go
@@ -69,7 +69,7 @@ func testGit(t *testing.T, u *url.URL) {
dstPath := t.TempDir()
- t.Run("CreateRepoInDifferentUser", doAPICreateRepository(forkedUserCtx, false, objectFormat))
+ t.Run("CreateRepoInDifferentUser", doAPICreateRepository(forkedUserCtx, nil, objectFormat))
t.Run("AddUserAsCollaborator", doAPIAddCollaborator(forkedUserCtx, httpContext.Username, perm.AccessModeRead))
t.Run("ForkFromDifferentUser", doAPIForkRepository(httpContext, forkedUserCtx.Username))
@@ -110,7 +110,7 @@ func testGit(t *testing.T, u *url.URL) {
sshContext.Reponame = "repo-tmp-18-" + objectFormat.Name()
keyname := "my-testing-key"
forkedUserCtx.Reponame = sshContext.Reponame
- t.Run("CreateRepoInDifferentUser", doAPICreateRepository(forkedUserCtx, false, objectFormat))
+ t.Run("CreateRepoInDifferentUser", doAPICreateRepository(forkedUserCtx, nil, objectFormat))
t.Run("AddUserAsCollaborator", doAPIAddCollaborator(forkedUserCtx, sshContext.Username, perm.AccessModeRead))
t.Run("ForkFromDifferentUser", doAPIForkRepository(sshContext, forkedUserCtx.Username))
@@ -529,8 +529,7 @@ func doMergeFork(ctx, baseCtx APITestContext, baseBranch, headBranch string) fun
t.Run("EnsureCanSeePull", doEnsureCanSeePull(headCtx, pr, false))
t.Run("CheckPR", func(t *testing.T) {
oldMergeBase := pr.MergeBase
- pr2, err := doAPIGetPullRequest(baseCtx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
- require.NoError(t, err)
+ pr2 := doAPIGetPullRequest(baseCtx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
assert.Equal(t, oldMergeBase, pr2.MergeBase)
})
t.Run("EnsurDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffHash, diffLength))
@@ -730,24 +729,21 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
// Check pr status
ctx.ExpectedCode = 0
- pr, err = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
- require.NoError(t, err)
+ pr = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
assert.False(t, pr.HasMerged)
// Call API to add Failure status for commit
t.Run("CreateStatus", addCommitStatus(api.CommitStatusFailure))
// Check pr status
- pr, err = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
- require.NoError(t, err)
+ pr = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
assert.False(t, pr.HasMerged)
// Call API to add Success status for commit
t.Run("CreateStatus", addCommitStatus(api.CommitStatusSuccess))
// test pr status
- pr, err = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
- require.NoError(t, err)
+ pr = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
assert.True(t, pr.HasMerged)
}
}
@@ -836,8 +832,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
assert.Equal(t, 1, pr1.CommitsAhead)
assert.Equal(t, 0, pr1.CommitsBehind)
- prMsg, err := doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr1.Index)(t)
- require.NoError(t, err)
+ prMsg := doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr1.Index)(t)
assert.Equal(t, "user2/"+headBranch, pr1.HeadBranch)
assert.False(t, prMsg.HasMerged)
@@ -858,8 +853,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
}
assert.Equal(t, 1, pr2.CommitsAhead)
assert.Equal(t, 0, pr2.CommitsBehind)
- prMsg, err = doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr2.Index)(t)
- require.NoError(t, err)
+ prMsg = doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr2.Index)(t)
assert.Equal(t, "user2/test/"+headBranch, pr2.HeadBranch)
assert.False(t, prMsg.HasMerged)
@@ -910,8 +904,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
require.NoError(t, err)
unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2)
- prMsg, err := doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr1.Index)(t)
- require.NoError(t, err)
+ prMsg := doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr1.Index)(t)
assert.False(t, prMsg.HasMerged)
assert.Equal(t, commit, prMsg.Head.Sha)
@@ -928,8 +921,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
require.NoError(t, err)
unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2)
- prMsg, err = doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr2.Index)(t)
- require.NoError(t, err)
+ prMsg = doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr2.Index)(t)
assert.False(t, prMsg.HasMerged)
assert.Equal(t, commit, prMsg.Head.Sha)
@@ -953,8 +945,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
err := pr3.LoadIssue(db.DefaultContext)
require.NoError(t, err)
- _, err2 := doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr3.Index)(t)
- require.NoError(t, err2)
+ doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr3.Index)(t)
assert.Equal(t, "Testing commit 2", pr3.Issue.Title)
assert.Contains(t, pr3.Issue.Content, "Longer description.")
@@ -975,8 +966,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
err := pr.LoadIssue(db.DefaultContext)
require.NoError(t, err)
- _, err = doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr.Index)(t)
- require.NoError(t, err)
+ doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr.Index)(t)
assert.Equal(t, "my-shiny-title", pr.Issue.Title)
assert.Contains(t, pr.Issue.Content, "Longer description.")
@@ -998,8 +988,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
err := pr.LoadIssue(db.DefaultContext)
require.NoError(t, err)
- _, err = doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr.Index)(t)
- require.NoError(t, err)
+ doAPIGetPullRequest(*ctx, ctx.Username, ctx.Reponame, pr.Index)(t)
assert.Equal(t, "Testing commit 2", pr.Issue.Title)
assert.Contains(t, pr.Issue.Content, "custom")
diff --git a/tests/integration/issue_comment_test.go b/tests/integration/issue_comment_test.go
index f77bfaa9bd..0c53c3028b 100644
--- a/tests/integration/issue_comment_test.go
+++ b/tests/integration/issue_comment_test.go
@@ -102,11 +102,35 @@ func TestIssueCommentChangeMilestone(t *testing.T) {
[]string{"user1 removed this from the milestone2 milestone"},
[]string{"/user1", "/user2/repo1/milestone/2"})
- // Deleted milestone
+ // Added milestone that in the meantime was deleted
testIssueCommentChangeEvent(t, htmlDoc, "2003",
"octicon-milestone", "User One", "/user1",
[]string{"user1 added this to the (deleted) milestone"},
[]string{"/user1"})
+
+ // Modified milestone - from a meantime deleted one to a valid one
+ testIssueCommentChangeEvent(t, htmlDoc, "2004",
+ "octicon-milestone", "User One", "/user1",
+ []string{"user1 modified the milestone from (deleted) to milestone1"},
+ []string{"/user1", "/user2/repo1/milestone/1"})
+
+ // Modified milestone - from a valid one to a meantime deleted one
+ testIssueCommentChangeEvent(t, htmlDoc, "2005",
+ "octicon-milestone", "User One", "/user1",
+ []string{"user1 modified the milestone from milestone1 to (deleted)"},
+ []string{"/user1", "/user2/repo1/milestone/1"})
+
+ // Modified milestone - from a meantime deleted one to a meantime deleted one
+ testIssueCommentChangeEvent(t, htmlDoc, "2006",
+ "octicon-milestone", "User One", "/user1",
+ []string{"user1 modified the milestone from (deleted) to (deleted)"},
+ []string{"/user1"})
+
+ // Removed milestone that in the meantime was deleted
+ testIssueCommentChangeEvent(t, htmlDoc, "2007",
+ "octicon-milestone", "User One", "/user1",
+ []string{"user1 removed this from the (deleted) milestone"},
+ []string{"/user1"})
}
func TestIssueCommentChangeProject(t *testing.T) {
diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go
index 120fe6534e..2b50be48a4 100644
--- a/tests/integration/issue_test.go
+++ b/tests/integration/issue_test.go
@@ -629,7 +629,12 @@ func TestIssueCommentAttachment(t *testing.T) {
assert.NotEqual(t, 0, id)
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/comments/%d/attachments", "user2", "repo1", id))
- session.MakeRequest(t, req, http.StatusOK)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ var attachments []*api.WebAttachment
+ DecodeJSON(t, resp, &attachments)
+ assert.Len(t, attachments, 1)
+ assert.Equal(t, attachments[0].UUID, uuid)
+ assert.Equal(t, "image/png", attachments[0].MimeType)
// Using the ID of a comment that does not belong to the repository must fail
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/comments/%d/attachments", "user5", "repo4", id))
diff --git a/tests/integration/org_settings_test.go b/tests/integration/org_settings_test.go
index fde57e2e26..3ea6f10bf6 100644
--- a/tests/integration/org_settings_test.go
+++ b/tests/integration/org_settings_test.go
@@ -57,7 +57,9 @@ func TestOrgSettingsChangeEmail(t *testing.T) {
settings := getOrgSettingsFormData(t, session, orgName)
settings["email"] = "invalid"
- session.MakeRequest(t, NewRequestWithValues(t, "POST", settingsURL, settings), http.StatusOK)
+ doc := NewHTMLParser(t, session.MakeRequest(t, NewRequestWithValues(t, "POST", settingsURL, settings), http.StatusOK).Body)
+ doc.AssertElement(t, ".status-page-500", false)
+ doc.AssertElement(t, ".flash-error", true)
org := getOrgSettings(t, token, orgName)
assert.Equal(t, "org3@example.com", org.Email)
@@ -69,7 +71,10 @@ func TestOrgSettingsChangeEmail(t *testing.T) {
settings := getOrgSettingsFormData(t, session, orgName)
settings["email"] = "example@example.com"
- session.MakeRequest(t, NewRequestWithValues(t, "POST", settingsURL, settings), http.StatusSeeOther)
+ doc := NewHTMLParser(t, session.MakeRequest(t, NewRequestWithValues(t, "POST", settingsURL, settings), http.StatusSeeOther).Body)
+ doc.AssertElement(t, "body", true)
+ doc.AssertElement(t, ".status-page-500", false)
+ doc.AssertElement(t, ".flash-error", false)
org := getOrgSettings(t, token, orgName)
assert.Equal(t, "example@example.com", org.Email)
@@ -81,7 +86,10 @@ func TestOrgSettingsChangeEmail(t *testing.T) {
settings := getOrgSettingsFormData(t, session, orgName)
settings["email"] = ""
- session.MakeRequest(t, NewRequestWithValues(t, "POST", settingsURL, settings), http.StatusSeeOther)
+ doc := NewHTMLParser(t, session.MakeRequest(t, NewRequestWithValues(t, "POST", settingsURL, settings), http.StatusSeeOther).Body)
+ doc.AssertElement(t, "body", true)
+ doc.AssertElement(t, ".status-page-500", false)
+ doc.AssertElement(t, ".flash-error", false)
org := getOrgSettings(t, token, orgName)
assert.Empty(t, org.Email)
diff --git a/tests/integration/pull_commit_test.go b/tests/integration/pull_commit_test.go
index 8ca78f8147..f82fc08df4 100644
--- a/tests/integration/pull_commit_test.go
+++ b/tests/integration/pull_commit_test.go
@@ -4,13 +4,26 @@
package integration
import (
+ "context"
+ "encoding/base64"
+ "fmt"
"net/http"
+ "net/url"
+ "os"
"testing"
+ auth_model "forgejo.org/models/auth"
+ "forgejo.org/models/unittest"
+ user_model "forgejo.org/models/user"
+ "forgejo.org/modules/git"
+ "forgejo.org/modules/setting"
+ api "forgejo.org/modules/structs"
+ "forgejo.org/modules/test"
pull_service "forgejo.org/services/pull"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestListPullCommits(t *testing.T) {
@@ -48,3 +61,83 @@ func TestPullCommitLinks(t *testing.T) {
commitLinkHref, _ := commitLink.Attr("href")
assert.Equal(t, "/user2/repo1/pulls/3/commits/5f22f7d0d95d614d25a5b68592adb345a4b5c7fd", commitLinkHref)
}
+
+func TestPullCommitSignature(t *testing.T) {
+ t.Cleanup(func() {
+ // Cannot use t.Context(), it is in the done state.
+ require.NoError(t, git.InitFull(context.Background())) //nolint:usetesting
+ })
+
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "UwU")()
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "fox@example.com")()
+ defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"always"})()
+ defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"always"})()
+
+ filePath := "signed.txt"
+ fromBranch := "master"
+ toBranch := "branch-signed"
+
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ // Use a new GNUPGPHOME to avoid messing with the existing GPG keyring.
+ tmpDir := t.TempDir()
+ require.NoError(t, os.Chmod(tmpDir, 0o700))
+ t.Setenv("GNUPGHOME", tmpDir)
+
+ rootKeyPair, err := importTestingKey()
+ require.NoError(t, err)
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningKey, rootKeyPair.PrimaryKey.KeyIdShortString())()
+ defer test.MockVariableValue(&setting.Repository.Signing.Format, "openpgp")()
+
+ // Ensure the git config is updated with the new signing format.
+ require.NoError(t, git.InitFull(t.Context()))
+
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ testCtx := NewAPITestContext(t, user.Name, "pull-request-commit-header-signed", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ u.Path = testCtx.GitPath()
+
+ t.Run("Create repository", doAPICreateRepository(testCtx, nil, git.Sha1ObjectFormat))
+
+ t.Run("Create commit", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ options := &api.CreateFileOptions{
+ FileOptions: api.FileOptions{
+ BranchName: fromBranch,
+ NewBranchName: toBranch,
+ Message: fmt.Sprintf("from:%s to:%s path:%s", fromBranch, toBranch, filePath),
+ Author: api.Identity{
+ Name: user.FullName,
+ Email: user.Email,
+ },
+ Committer: api.Identity{
+ Name: user.FullName,
+ Email: user.Email,
+ },
+ },
+ ContentBase64: base64.StdEncoding.EncodeToString(fmt.Appendf(nil, "This is new text for %s", filePath)),
+ }
+
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", testCtx.Username, testCtx.Reponame, filePath), &options).
+ AddTokenAuth(testCtx.Token)
+ resp := testCtx.Session.MakeRequest(t, req, http.StatusCreated)
+
+ var contents api.FileResponse
+ DecodeJSON(t, resp, &contents)
+
+ assert.True(t, contents.Verification.Verified)
+ })
+
+ t.Run("Create pull request", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ pr, err := doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, fromBranch, toBranch)(t)
+ require.NoError(t, err)
+
+ req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/pulls/%d/commits/%s", testCtx.Username, testCtx.Reponame, pr.Index, pr.Head.Sha))
+ resp := testCtx.Session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ htmlDoc.AssertElement(t, "#diff-commit-header .commit-header-row.message.isSigned.isVerified", true)
+ })
+ })
+}
diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go
index cca2381fd4..ab3d1604de 100644
--- a/tests/integration/pull_merge_test.go
+++ b/tests/integration/pull_merge_test.go
@@ -1135,3 +1135,32 @@ func TestPullDeleteBranchPerms(t *testing.T) {
user4Session.MakeRequest(t, req, http.StatusOK)
})
}
+
+// Test that rebasing only happens when its necessary.
+func TestRebaseWhenNecessary(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ session := loginUser(t, "user1")
+ testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+ testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+
+ resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
+ pullLink := test.RedirectURL(resp)
+
+ resp = session.MakeRequest(t, NewRequest(t, "GET", test.RedirectURL(resp)+"/commits"), http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ commitLinkBefore, ok := htmlDoc.Find("a.sha").Attr("href")
+ assert.True(t, ok)
+ commitBefore := commitLinkBefore[strings.LastIndexByte(commitLinkBefore, '/'):]
+
+ elem := strings.Split(pullLink, "/")
+ testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebase, false)
+
+ resp = session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1"), http.StatusOK)
+ htmlDoc = NewHTMLParser(t, resp.Body)
+ commitLinkAfter, ok := htmlDoc.Find(".latest-commit a.sha").Attr("href")
+ assert.True(t, ok)
+ commitAfter := commitLinkAfter[strings.LastIndexByte(commitLinkAfter, '/'):]
+
+ assert.Equal(t, commitBefore, commitAfter)
+ })
+}
diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go
index 603252f45f..4af0a1100e 100644
--- a/tests/integration/pull_review_test.go
+++ b/tests/integration/pull_review_test.go
@@ -5,19 +5,23 @@
package integration
import (
+ "bytes"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
+ "os"
"path"
"strconv"
"strings"
"testing"
+ "time"
"forgejo.org/models/db"
issues_model "forgejo.org/models/issues"
repo_model "forgejo.org/models/repo"
+ unit_model "forgejo.org/models/unit"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/git"
@@ -761,3 +765,158 @@ func updateFileInBranch(user *user_model.User, repo *repo_model.Repository, tree
_, err = files_service.ChangeRepoFiles(git.DefaultContext, repo, user, opts)
return err
}
+
+func TestPullRequestStaleReview(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+
+ // Create temporary repository.
+ repo, _, f := tests.CreateDeclarativeRepo(t, user2, "",
+ []unit_model.Type{unit_model.TypePullRequests}, nil,
+ []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: "FUNFACT",
+ ContentReader: strings.NewReader("Smithy was the runner up to be Forgejo's name"),
+ },
+ },
+ )
+ defer f()
+
+ // Clone it.
+ dstPath := t.TempDir()
+ r := fmt.Sprintf("%suser2/%s.git", u.String(), repo.Name)
+ cloneURL, _ := url.Parse(r)
+ cloneURL.User = url.UserPassword("user2", userPassword)
+ require.NoError(t, git.CloneWithArgs(t.Context(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{}))
+
+ // Create first commit.
+ require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## test content"), 0o600))
+ require.NoError(t, git.AddChanges(dstPath, true))
+ require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
+ Committer: &git.Signature{
+ Email: "user2@example.com",
+ Name: "user2",
+ When: time.Now(),
+ },
+ Author: &git.Signature{
+ Email: "user2@example.com",
+ Name: "user2",
+ When: time.Now(),
+ },
+ Message: "Add README.",
+ }))
+ stdout := &bytes.Buffer{}
+ require.NoError(t, git.NewCommand(t.Context(), "rev-parse", "HEAD").Run(&git.RunOpts{Dir: dstPath, Stdout: stdout}))
+ firstCommitID := strings.TrimSpace(stdout.String())
+
+ // Create agit PR.
+ require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
+
+ pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Index: 1, BaseRepoID: repo.ID})
+
+ req := NewRequest(t, "GET", "/"+repo.FullName()+"/pulls/1/files/reviews/new_comment")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+
+ t.Run("Mark review as stale", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ // Create a approved review against against this commit.
+ req = NewRequestWithValues(t, "POST", "/"+repo.FullName()+"/pulls/1/files/reviews/comments", map[string]string{
+ "_csrf": doc.GetCSRF(),
+ "origin": doc.GetInputValueByName("origin"),
+ "latest_commit_id": firstCommitID,
+ "side": "proposed",
+ "line": "1",
+ "path": "FUNFACT",
+ "diff_start_cid": doc.GetInputValueByName("diff_start_cid"),
+ "diff_end_cid": doc.GetInputValueByName("diff_end_cid"),
+ "diff_base_cid": doc.GetInputValueByName("diff_base_cid"),
+ "content": "nitpicking comment",
+ "pending_review": "",
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ req = NewRequestWithValues(t, "POST", "/"+repo.FullName()+"/pulls/1/files/reviews/submit", map[string]string{
+ "_csrf": doc.GetCSRF(),
+ "commit_id": firstCommitID,
+ "content": "looks good",
+ "type": "comment",
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ // Review is not stale.
+ review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
+ assert.False(t, review.Stale)
+
+ // Create second commit
+ require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## I prefer this heading"), 0o600))
+ require.NoError(t, git.AddChanges(dstPath, true))
+ require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
+ Committer: &git.Signature{
+ Email: "user2@example.com",
+ Name: "user2",
+ When: time.Now(),
+ },
+ Author: &git.Signature{
+ Email: "user2@example.com",
+ Name: "user2",
+ When: time.Now(),
+ },
+ Message: "Add README.",
+ }))
+
+ // Push to agit PR.
+ require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
+
+ // Review is stale.
+ review = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
+ assert.True(t, review.Stale)
+ })
+
+ t.Run("Create stale review", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ // Review based on the first commit, which is a stale review because the
+ // PR's head is at the seconnd commit.
+ req := NewRequestWithValues(t, "POST", "/"+repo.FullName()+"/pulls/1/files/reviews/submit", map[string]string{
+ "_csrf": doc.GetCSRF(),
+ "commit_id": firstCommitID,
+ "content": "looks good",
+ "type": "approve",
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ // There does not exist a review that is not stale, because all reviews
+ // are based on the first commit and the PR's head is at the second commit.
+ unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = false")
+ })
+
+ t.Run("Mark unstale", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ // Force push the PR to the first commit.
+ require.NoError(t, git.NewCommand(t.Context(), "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath}))
+ require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr", "-o", "force-push").Run(&git.RunOpts{Dir: dstPath}))
+
+ // There does not exist a review that is stale, because all reviews
+ // are based on the first commit and thus all reviews are no longer marked
+ // as stale.
+ unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
+ })
+
+ t.Run("Diff did not change", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ // Create a empty commit and push it to the PR.
+ require.NoError(t, git.NewCommand(t.Context(), "commit", "--allow-empty", "-m", "Empty commit").Run(&git.RunOpts{Dir: dstPath}))
+ require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
+
+ // There does not exist a review that is stale, because the diff did not
+ // change.
+ unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
+ })
+ })
+}
diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go
index b66726a3e6..7370b63dcd 100644
--- a/tests/integration/repo_test.go
+++ b/tests/integration/repo_test.go
@@ -5,15 +5,19 @@
package integration
import (
+ "context"
+ "encoding/base64"
"fmt"
"net/http"
"net/url"
+ "os"
"path"
"regexp"
"strings"
"testing"
"time"
+ auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
unit_model "forgejo.org/models/unit"
@@ -22,6 +26,7 @@ import (
"forgejo.org/modules/git"
"forgejo.org/modules/optional"
"forgejo.org/modules/setting"
+ api "forgejo.org/modules/structs"
"forgejo.org/modules/test"
"forgejo.org/modules/translation"
repo_service "forgejo.org/services/repository"
@@ -682,6 +687,79 @@ func TestViewCommit(t *testing.T) {
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()), "non-existing commit should render 404 page")
}
+func TestViewCommitSignature(t *testing.T) {
+ t.Cleanup(func() {
+ // Cannot use t.Context(), it is in the done state.
+ require.NoError(t, git.InitFull(context.Background())) //nolint:usetesting
+ })
+
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "UwU")()
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "fox@example.com")()
+ defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"always"})()
+ defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"always"})()
+
+ filePath := "signed.txt"
+ fromBranch := "master"
+ toBranch := "branch-signed"
+
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ // Use a new GNUPGPHOME to avoid messing with the existing GPG keyring.
+ tmpDir := t.TempDir()
+ require.NoError(t, os.Chmod(tmpDir, 0o700))
+ t.Setenv("GNUPGHOME", tmpDir)
+
+ rootKeyPair, err := importTestingKey()
+ require.NoError(t, err)
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningKey, rootKeyPair.PrimaryKey.KeyIdShortString())()
+ defer test.MockVariableValue(&setting.Repository.Signing.Format, "openpgp")()
+
+ // Ensure the git config is updated with the new signing format.
+ require.NoError(t, git.InitFull(t.Context()))
+
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ testCtx := NewAPITestContext(t, user.Name, "commit-header-signed", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ u.Path = testCtx.GitPath()
+
+ t.Run("Create repository", doAPICreateRepository(testCtx, nil, git.Sha1ObjectFormat))
+
+ t.Run("Create commit", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ options := &api.CreateFileOptions{
+ FileOptions: api.FileOptions{
+ BranchName: fromBranch,
+ NewBranchName: toBranch,
+ Message: fmt.Sprintf("from:%s to:%s path:%s", fromBranch, toBranch, filePath),
+ Author: api.Identity{
+ Name: user.FullName,
+ Email: user.Email,
+ },
+ Committer: api.Identity{
+ Name: user.FullName,
+ Email: user.Email,
+ },
+ },
+ ContentBase64: base64.StdEncoding.EncodeToString(fmt.Appendf(nil, "This is new text for %s", filePath)),
+ }
+
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", testCtx.Username, testCtx.Reponame, filePath), &options).
+ AddTokenAuth(testCtx.Token)
+ resp := testCtx.Session.MakeRequest(t, req, http.StatusCreated)
+
+ var contents api.FileResponse
+ DecodeJSON(t, resp, &contents)
+
+ assert.True(t, contents.Verification.Verified)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/commit/%s", testCtx.Username, testCtx.Reponame, contents.Commit.SHA))
+ resp = testCtx.Session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ htmlDoc.AssertElement(t, ".commit-header-row.message.isSigned.isVerified", true)
+ })
+ })
+}
+
func TestCommitView(t *testing.T) {
defer tests.PrepareTestEnv(t)()
diff --git a/tests/integration/signing_git_test.go b/tests/integration/signing_git_test.go
index 9d69306e0a..e4c0d6049b 100644
--- a/tests/integration/signing_git_test.go
+++ b/tests/integration/signing_git_test.go
@@ -109,13 +109,14 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
defer tests.PrintCurrentTest(t)()
testCtx := NewAPITestContext(t, username, "initial-unsigned"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
- t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CheckMasterBranchUnsigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
assert.NotNil(t, branch.Commit)
assert.NotNil(t, branch.Commit.Verification)
assert.False(t, branch.Commit.Verification.Verified)
assert.Empty(t, branch.Commit.Verification.Signature)
- }))
+ })
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
t, testCtx, user, "master", "never", "unsigned-never.txt", func(t *testing.T, response api.FileResponse) {
assert.False(t, response.Verification.Verified)
@@ -191,25 +192,27 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
defer tests.PrintCurrentTest(t)()
testCtx := NewAPITestContext(t, username, "initial-pubkey"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
- t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CheckMasterBranchSigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.True(t, branch.Commit.Verification.Verified)
assert.Equal(t, "fox@example.com", branch.Commit.Verification.Signer.Email)
- }))
+ })
})
t.Run("No publickey", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
testCtx := NewAPITestContext(t, "user4", "initial-no-pubkey"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
- t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CheckMasterBranchSigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.False(t, branch.Commit.Verification.Verified)
- }))
+ })
})
})
@@ -226,25 +229,27 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
testCtx := NewAPITestContext(t, username, "initial-2fa"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
unittest.AssertSuccessfulInsert(t, &auth_model.WebAuthnCredential{UserID: user.ID})
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
- t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CheckMasterBranchSigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.True(t, branch.Commit.Verification.Verified)
assert.Equal(t, "fox@example.com", branch.Commit.Verification.Signer.Email)
- }))
+ })
})
- t.Run("No publickey", func(t *testing.T) {
+ t.Run("No 2fa", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
testCtx := NewAPITestContext(t, "user4", "initial-no-2fa"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
- t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CheckMasterBranchSigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.False(t, branch.Commit.Verification.Verified)
- }))
+ })
})
})
@@ -253,13 +258,14 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
setting.Repository.Signing.InitialCommit = []string{"always"}
testCtx := NewAPITestContext(t, username, "initial-always"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
- t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CheckMasterBranchSigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.True(t, branch.Commit.Verification.Verified)
assert.Equal(t, "fox@example.com", branch.Commit.Verification.Signer.Email)
- }))
+ })
})
t.Run("AlwaysSign-Initial-CRUD-Never", func(t *testing.T) {
@@ -267,7 +273,7 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
setting.Repository.Signing.CRUDActions = []string{"never"}
testCtx := NewAPITestContext(t, username, "initial-always-never"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
t, testCtx, user, "master", "never", "unsigned-never.txt", func(t *testing.T, response api.FileResponse) {
assert.False(t, response.Verification.Verified)
@@ -279,7 +285,7 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
setting.Repository.Signing.CRUDActions = []string{"parentsigned"}
testCtx := NewAPITestContext(t, username, "initial-always-parent"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
assert.True(t, response.Verification.Verified)
@@ -287,12 +293,71 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
}))
})
+ t.Run("AlwaysSign-Initial-CRUD-Pubkey", func(t *testing.T) {
+ setting.Repository.Signing.CRUDActions = []string{"pubkey"}
+
+ t.Run("Has publickey", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ testCtx := NewAPITestContext(t, username, "initial-always-pubkey"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CreateCRUDFile-Pubkey", crudActionCreateFile(
+ t, testCtx, user, "master", "pubkey", "signed-pubkey.txt", func(t *testing.T, response api.FileResponse) {
+ assert.True(t, response.Verification.Verified)
+ assert.Equal(t, "fox@example.com", response.Verification.Signer.Email)
+ }))
+ })
+
+ t.Run("No publickey", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ testCtx := NewAPITestContext(t, "user4", "initial-always-no-pubkey"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CreateCRUDFile-Pubkey", crudActionCreateFile(
+ t, testCtx, user, "master", "pubkey", "unsigned-pubkey.txt", func(t *testing.T, response api.FileResponse) {
+ assert.False(t, response.Verification.Verified)
+ }))
+ })
+ })
+
+ t.Run("AlwaysSign-Initial-CRUD-Twofa", func(t *testing.T) {
+ setting.Repository.Signing.CRUDActions = []string{"twofa"}
+
+ t.Run("Has 2fa", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ t.Cleanup(func() {
+ unittest.AssertSuccessfulDelete(t, &auth_model.WebAuthnCredential{UserID: user.ID})
+ })
+
+ testCtx := NewAPITestContext(t, username, "initial-always-twofa"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ unittest.AssertSuccessfulInsert(t, &auth_model.WebAuthnCredential{UserID: user.ID})
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CreateCRUDFile-Twofa", crudActionCreateFile(
+ t, testCtx, user, "master", "twofa", "signed-twofa.txt", func(t *testing.T, response api.FileResponse) {
+ assert.True(t, response.Verification.Verified)
+ assert.Equal(t, "fox@example.com", response.Verification.Signer.Email)
+ }))
+ })
+
+ t.Run("No 2fa", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ testCtx := NewAPITestContext(t, "user4", "initial-always-no-twofa"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
+ t.Run("CreateCRUDFile-Pubkey", crudActionCreateFile(
+ t, testCtx, user, "master", "twofa", "unsigned-twofa.txt", func(t *testing.T, response api.FileResponse) {
+ assert.False(t, response.Verification.Verified)
+ }))
+ })
+ })
+
t.Run("AlwaysSign-Initial-CRUD-Always", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
setting.Repository.Signing.CRUDActions = []string{"always"}
testCtx := NewAPITestContext(t, username, "initial-always-always"+suffix, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- t.Run("CreateRepository", doAPICreateRepository(testCtx, false, objectFormat))
+ t.Run("CreateRepository", doAPICreateRepository(testCtx, nil, objectFormat))
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
assert.True(t, response.Verification.Verified)
@@ -310,12 +375,13 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
require.NoError(t, err)
t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index))
})
- t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CheckMasterBranchUnsigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.False(t, branch.Commit.Verification.Verified)
assert.Empty(t, branch.Commit.Verification.Signature)
- }))
+ })
})
t.Run("BaseSignedMerging", func(t *testing.T) {
@@ -328,12 +394,13 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
require.NoError(t, err)
t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index))
})
- t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CheckMasterBranchUnsigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.False(t, branch.Commit.Verification.Verified)
assert.Empty(t, branch.Commit.Verification.Signature)
- }))
+ })
})
t.Run("CommitsSignedMerging", func(t *testing.T) {
@@ -346,11 +413,12 @@ func testCRUD(t *testing.T, u *url.URL, signingFormat string, objectFormat git.O
require.NoError(t, err)
t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index))
})
- t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
+ t.Run("CheckMasterBranchUnsigned", func(t *testing.T) {
+ branch := doAPIGetBranch(testCtx, "master")(t)
require.NotNil(t, branch.Commit)
require.NotNil(t, branch.Commit.Verification)
assert.True(t, branch.Commit.Verification.Verified)
- }))
+ })
})
}
diff --git a/tests/integration/ssh_key_test.go b/tests/integration/ssh_key_test.go
index aece9c3fd9..a92694d2fa 100644
--- a/tests/integration/ssh_key_test.go
+++ b/tests/integration/ssh_key_test.go
@@ -55,7 +55,13 @@ func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
keyname := fmt.Sprintf("%s-push", ctx.Reponame)
u.Path = ctx.GitPath()
- t.Run("CreateEmptyRepository", doAPICreateRepository(ctx, true, objectFormat))
+ opts := &api.CreateRepoOption{
+ Description: "Temporary repo",
+ Name: ctx.Reponame,
+ Private: true,
+ Template: true,
+ }
+ t.Run("CreateEmptyRepository", doAPICreateRepository(ctx, opts, objectFormat))
t.Run("CheckIsEmpty", doCheckRepositoryEmptyStatus(ctx, true))
@@ -105,8 +111,8 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
failCtx := ctx
failCtx.ExpectedCode = http.StatusUnprocessableEntity
- t.Run("CreateRepository", doAPICreateRepository(ctx, false, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
- t.Run("CreateOtherRepository", doAPICreateRepository(otherCtx, false, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
+ t.Run("CreateRepository", doAPICreateRepository(ctx, nil, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
+ t.Run("CreateOtherRepository", doAPICreateRepository(otherCtx, nil, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
withKeyFile(t, keyname, func(keyFile string) {
var userKeyPublicKeyID int64
@@ -180,7 +186,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
t.Run("DeleteOtherRepository", doAPIDeleteRepository(otherCtxWithDeleteRepo))
- t.Run("RecreateRepository", doAPICreateRepository(ctxWithDeleteRepo, false, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
+ t.Run("RecreateRepository", doAPICreateRepository(ctxWithDeleteRepo, nil, git.Sha1ObjectFormat)) // FIXME: use forEachObjectFormat
t.Run("CreateUserKey", doAPICreateUserKey(ctx, keyname, keyFile, func(t *testing.T, publicKey api.PublicKey) {
userKeyPublicKeyID = publicKey.ID
diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl
index f44aff7594..3315d85a3f 100644
--- a/tests/mysql.ini.tmpl
+++ b/tests/mysql.ini.tmpl
@@ -92,6 +92,7 @@ DISABLE_GIT_HOOKS = false
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
+DISABLE_QUERY_AUTH_TOKEN = true
[lfs]
PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/data/lfs
diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl
index 829fdc5b75..1e9b981800 100644
--- a/tests/pgsql.ini.tmpl
+++ b/tests/pgsql.ini.tmpl
@@ -97,6 +97,7 @@ DISABLE_GIT_HOOKS = false
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
+DISABLE_QUERY_AUTH_TOKEN = true
[lfs]
MINIO_BASE_PATH = lfs/
diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl
index d36388405b..df6cea44ca 100644
--- a/tests/sqlite.ini.tmpl
+++ b/tests/sqlite.ini.tmpl
@@ -94,6 +94,7 @@ DISABLE_GIT_HOOKS = false
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8
+DISABLE_QUERY_AUTH_TOKEN = true
[oauth2]
JWT_SECRET = KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko
diff --git a/web_src/js/components/RepoContributors.vue b/web_src/js/components/RepoContributors.vue
index 07ad336cf7..5e03019ef1 100644
--- a/web_src/js/components/RepoContributors.vue
+++ b/web_src/js/components/RepoContributors.vue
@@ -391,7 +391,7 @@ export default {
#{{ index + 1 }}
-
+
{{ contributor.name }}
diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js
index 7d553f9692..2102e995d8 100644
--- a/web_src/js/features/common-global.js
+++ b/web_src/js/features/common-global.js
@@ -208,59 +208,128 @@ export function initGlobalDropzone() {
}
}
-export function initDropzone(el) {
- const $dropzone = $(el);
- const _promise = createDropzone(el, {
- url: $dropzone.data('upload-url'),
+export async function initDropzone(dropzoneEl, zone = undefined) {
+ if (!dropzoneEl) return;
+
+ let disableRemovedfileEvent = false; // when resetting the dropzone (removeAllFiles), disable the "removedfile" event
+ let fileUuidDict = {}; // to record: if a comment has been saved, then the uploaded files won't be deleted from server when clicking the Remove in the dropzone
+
+ const initFilePreview = (file, data, isReload = false) => {
+ file.uuid = data.uuid;
+ fileUuidDict[file.uuid] = {submitted: isReload};
+ const input = document.createElement('input');
+ input.id = data.uuid;
+ input.name = 'files';
+ input.type = 'hidden';
+ input.value = data.uuid;
+ dropzoneEl.querySelector('.files').append(input);
+
+ // Create a "Copy Link" element, to conveniently copy the image
+ // or file link as Markdown to the clipboard
+ const copyLinkElement = document.createElement('div');
+ copyLinkElement.className = 'tw-text-center';
+ // The a element has a hardcoded cursor: pointer because the default is overridden by .dropzone
+ copyLinkElement.innerHTML = `${svg('octicon-copy', 14, 'copy link')} Copy link`;
+ copyLinkElement.addEventListener('click', async (e) => {
+ e.preventDefault();
+ const name = file.name.slice(0, file.name.lastIndexOf('.'));
+ let fileMarkdown = `[${name}](/attachments/${file.uuid})`;
+ if (file.type.startsWith('image/')) {
+ fileMarkdown = `!${fileMarkdown}`;
+ } else if (file.type.startsWith('video/')) {
+ fileMarkdown = ``;
+ }
+ const success = await clippie(fileMarkdown);
+ showTemporaryTooltip(e.target, success ? i18n.copy_success : i18n.copy_error);
+ });
+ file.previewTemplate.append(copyLinkElement);
+ };
+ const updateDropzoneState = () => {
+ if (dropzoneEl.querySelector('.dz-preview')) {
+ dropzoneEl.classList.add('dz-started');
+ } else {
+ dropzoneEl.classList.remove('dz-started');
+ }
+ };
+
+ const dz = await createDropzone(dropzoneEl, {
+ url: dropzoneEl.getAttribute('data-upload-url'),
headers: {'X-Csrf-Token': csrfToken},
- maxFiles: $dropzone.data('max-file'),
- maxFilesize: $dropzone.data('max-size'),
- acceptedFiles: (['*/*', ''].includes($dropzone.data('accepts'))) ? null : $dropzone.data('accepts'),
+ maxFiles: dropzoneEl.getAttribute('data-max-file'),
+ maxFilesize: dropzoneEl.getAttribute('data-max-size'),
+ acceptedFiles: (['*/*', ''].includes(dropzoneEl.getAttribute('data-accepts')) ? null : dropzoneEl.getAttribute('data-accepts')),
addRemoveLinks: true,
- dictDefaultMessage: $dropzone.data('default-message'),
- dictInvalidFileType: $dropzone.data('invalid-input-type'),
- dictFileTooBig: $dropzone.data('file-too-big'),
- dictRemoveFile: $dropzone.data('remove-file'),
+ dictDefaultMessage: dropzoneEl.getAttribute('data-default-message'),
+ dictInvalidFileType: dropzoneEl.getAttribute('data-invalid-input-type'),
+ dictFileTooBig: dropzoneEl.getAttribute('data-file-too-big'),
+ dictRemoveFile: dropzoneEl.getAttribute('data-remove-file'),
timeout: 0,
thumbnailMethod: 'contain',
thumbnailWidth: 480,
thumbnailHeight: 480,
init() {
- this.on('success', (file, data) => {
- file.uuid = data.uuid;
- const $input = $(``).val(data.uuid);
- $dropzone.find('.files').append($input);
- // Create a "Copy Link" element, to conveniently copy the image
- // or file link as Markdown to the clipboard
- const copyLinkElement = document.createElement('div');
- copyLinkElement.className = 'tw-text-center';
- // The a element has a hardcoded cursor: pointer because the default is overridden by .dropzone
- copyLinkElement.innerHTML = `${svg('octicon-copy', 14, 'copy link')} Copy link`;
- copyLinkElement.addEventListener('click', async (e) => {
- e.preventDefault();
- let fileMarkdown = `[${file.name}](/attachments/${file.uuid})`;
- if (file.type.startsWith('image/')) {
- fileMarkdown = `!${fileMarkdown}`;
- } else if (file.type.startsWith('video/')) {
- fileMarkdown = ``;
+ this.on('success', initFilePreview);
+ this.on('removedfile', async (file) => {
+ document.getElementById(file.uuid)?.remove();
+ if (disableRemovedfileEvent) return;
+ if (dropzoneEl.getAttribute('data-remove-url') && !fileUuidDict[file.uuid].submitted) {
+ try {
+ await POST(dropzoneEl.getAttribute('data-remove-url'), {data: new URLSearchParams({file: file.uuid})});
+ } catch (error) {
+ console.error(error);
}
- const success = await clippie(fileMarkdown);
- showTemporaryTooltip(e.target, success ? i18n.copy_success : i18n.copy_error);
- });
- file.previewTemplate.append(copyLinkElement);
- });
- this.on('removedfile', (file) => {
- $(`#${file.uuid}`).remove();
- if ($dropzone.data('remove-url')) {
- POST($dropzone.data('remove-url'), {
- data: new URLSearchParams({file: file.uuid}),
- });
}
+ updateDropzoneState();
});
this.on('error', function (file, message) {
showErrorToast(message);
this.removeFile(file);
});
+ this.on('reload', async () => {
+ if (!zone || !dz.removeAllFiles) return;
+ try {
+ const response = await GET(zone.getAttribute('data-attachment-url'));
+ const data = await response.json();
+ // do not trigger the "removedfile" event, otherwise the attachments would be deleted from server
+ disableRemovedfileEvent = true;
+ dz.removeAllFiles(true);
+ dropzoneEl.querySelector('.files').innerHTML = '';
+ for (const element of dropzoneEl.querySelectorAll('.dz-preview')) element.remove();
+ fileUuidDict = {};
+ disableRemovedfileEvent = false;
+
+ for (const attachment of data) {
+ attachment.type = attachment.mime_type;
+ dz.emit('addedfile', attachment);
+ dz.emit('complete', attachment);
+ if (attachment.type.startsWith('image/')) {
+ const imgSrc = `${dropzoneEl.getAttribute('data-link-url')}/${attachment.uuid}`;
+ dz.emit('thumbnail', attachment, imgSrc);
+ }
+ initFilePreview(attachment, {uuid: attachment.uuid}, true);
+ fileUuidDict[attachment.uuid] = {submitted: true};
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ updateDropzoneState();
+ });
+ this.on('create-thumbnail', (attachment, file) => {
+ if (attachment.type && /image.*/.test(attachment.type)) {
+ // When a new issue is created, a thumbnail cannot be fetch, so we need to create it locally.
+ // The implementation is took from the dropzone library (`dropzone.js` > `_processThumbnailQueue()`)
+ dz.createThumbnail(
+ file,
+ dz.options.thumbnailWidth,
+ dz.options.thumbnailHeight,
+ dz.options.thumbnailMethod,
+ true,
+ (dataUrl) => {
+ dz.emit('thumbnail', attachment, dataUrl);
+ },
+ );
+ }
+ });
},
});
}
diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js
index 3c94274175..4edd13bfc2 100644
--- a/web_src/js/features/comp/ComboMarkdownEditor.js
+++ b/web_src/js/features/comp/ComboMarkdownEditor.js
@@ -11,8 +11,6 @@ import {initTextExpander} from './TextExpander.js';
import {showErrorToast, showHintToast} from '../../modules/toast.js';
import {POST} from '../../modules/fetch.js';
-let elementIdCounter = 0;
-
/**
* validate if the given textarea is non-empty.
* @param {HTMLElement} textarea - The textarea element to be validated.
@@ -39,10 +37,13 @@ export function validateTextareaNonEmpty(textarea) {
const listPrefixRegex = /^\s*((\d+)[.)]\s|[-*+]\s{1,4}\[[ x]\]\s?|[-*+]\s|(>\s?)+)?/;
class ComboMarkdownEditor {
+ static idSuffixCounter = 0;
+
constructor(container, options = {}) {
container._giteaComboMarkdownEditor = this;
this.options = options;
this.container = container;
+ this.elementIdSuffix = ComboMarkdownEditor.idSuffixCounter++;
}
async init() {
@@ -55,8 +56,6 @@ class ComboMarkdownEditor {
this.setupLinkInserter();
await this.switchToUserPreference();
-
- elementIdCounter++;
}
applyEditorHeights(el, heights) {
@@ -74,7 +73,7 @@ class ComboMarkdownEditor {
setupTextarea() {
this.textarea = this.container.querySelector('.markdown-text-editor');
this.textarea._giteaComboMarkdownEditor = this;
- this.textarea.id = `_combo_markdown_editor_${elementIdCounter}`;
+ this.textarea.id = `_combo_markdown_editor_${this.elementIdSuffix}`;
this.textarea.addEventListener('input', (e) => this.options?.onContentChanged?.(this, e));
this.applyEditorHeights(this.textarea, this.options.editorHeights);
@@ -96,8 +95,8 @@ class ComboMarkdownEditor {
this.textareaMarkdownToolbar.querySelector('button[data-md-action="unindent"]')?.addEventListener('click', () => {
this.indentSelection(true, false);
});
- this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-table"]')?.setAttribute('data-modal', `div[data-markdown-table-modal-id="${elementIdCounter}"]`);
- this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-link"]')?.setAttribute('data-modal', `div[data-markdown-link-modal-id="${elementIdCounter}"]`);
+ this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-table"]')?.setAttribute('data-modal', `div[data-markdown-table-modal-id="${this.elementIdSuffix}"]`);
+ this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-link"]')?.setAttribute('data-modal', `div[data-markdown-link-modal-id="${this.elementIdSuffix}"]`);
// Track whether any actual input or pointer action was made after focusing, and only intercept Tab presses after that.
this.tabEnabled = false;
@@ -195,7 +194,7 @@ class ComboMarkdownEditor {
setupDropzone() {
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
if (dropzoneParentContainer) {
- this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
+ this.dropzone = this.container.closest(dropzoneParentContainer)?.querySelector('.dropzone');
}
}
@@ -207,13 +206,13 @@ class ComboMarkdownEditor {
// So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic.
const tabEditor = Array.from(tabs).find((tab) => tab.getAttribute('data-tab-for') === 'markdown-writer');
const tabPreviewer = Array.from(tabs).find((tab) => tab.getAttribute('data-tab-for') === 'markdown-previewer');
- tabEditor.setAttribute('data-tab', `markdown-writer-${elementIdCounter}`);
- tabPreviewer.setAttribute('data-tab', `markdown-previewer-${elementIdCounter}`);
+ tabEditor.setAttribute('data-tab', `markdown-writer-${this.elementIdSuffix}`);
+ tabPreviewer.setAttribute('data-tab', `markdown-previewer-${this.elementIdSuffix}`);
const toolbar = $container[0].querySelector('markdown-toolbar');
const panelEditor = $container[0].querySelector('.ui.tab[data-tab-panel="markdown-writer"]');
const panelPreviewer = $container[0].querySelector('.ui.tab[data-tab-panel="markdown-previewer"]');
- panelEditor.setAttribute('data-tab', `markdown-writer-${elementIdCounter}`);
- panelPreviewer.setAttribute('data-tab', `markdown-previewer-${elementIdCounter}`);
+ panelEditor.setAttribute('data-tab', `markdown-writer-${this.elementIdSuffix}`);
+ panelPreviewer.setAttribute('data-tab', `markdown-previewer-${this.elementIdSuffix}`);
tabEditor.addEventListener('click', () => {
toolbar.classList.remove('markdown-toolbar-hidden');
@@ -276,10 +275,10 @@ class ComboMarkdownEditor {
setupTableInserter() {
const newTableModal = this.container.querySelector('div[data-modal-name="new-markdown-table"]');
- newTableModal.setAttribute('data-markdown-table-modal-id', elementIdCounter);
+ newTableModal.setAttribute('data-markdown-table-modal-id', this.elementIdSuffix);
const button = newTableModal.querySelector('button[data-selector-name="ok-button"]');
- button.setAttribute('data-element-id', elementIdCounter);
+ button.setAttribute('data-element-id', this.elementIdSuffix);
button.addEventListener('click', this.addNewTable);
}
@@ -311,8 +310,8 @@ class ComboMarkdownEditor {
setupLinkInserter() {
const newLinkModal = this.container.querySelector('div[data-modal-name="new-markdown-link"]');
- newLinkModal.setAttribute('data-markdown-link-modal-id', elementIdCounter);
- const textarea = document.getElementById(`_combo_markdown_editor_${elementIdCounter}`);
+ newLinkModal.setAttribute('data-markdown-link-modal-id', this.elementIdSuffix);
+ const textarea = document.getElementById(`_combo_markdown_editor_${this.elementIdSuffix}`);
$(newLinkModal).modal({
// Pre-fill the description field from the selection to create behavior similar
@@ -331,7 +330,7 @@ class ComboMarkdownEditor {
});
const button = newLinkModal.querySelector('button[data-selector-name="ok-button"]');
- button.setAttribute('data-element-id', elementIdCounter);
+ button.setAttribute('data-element-id', this.elementIdSuffix);
button.addEventListener('click', this.addNewLink);
}
diff --git a/web_src/js/features/comp/Paste.js b/web_src/js/features/comp/Paste.js
index 7e4ecbbeda..0fb6cf4615 100644
--- a/web_src/js/features/comp/Paste.js
+++ b/web_src/js/features/comp/Paste.js
@@ -82,9 +82,8 @@ class CodeMirrorEditor {
async function handleClipboardImages(editor, dropzone, images, e) {
const uploadUrl = dropzone.getAttribute('data-upload-url');
- const filesContainer = dropzone.querySelector('.files');
- if (!dropzone || !uploadUrl || !filesContainer || !images.length) return;
+ if (!dropzone || !uploadUrl || !images.length) return;
e.preventDefault();
e.stopPropagation();
@@ -92,7 +91,7 @@ async function handleClipboardImages(editor, dropzone, images, e) {
for (const img of images) {
const name = img.name.slice(0, img.name.lastIndexOf('.'));
- const placeholder = ``;
+ const placeholder = ``;
editor.insertPlaceholder(placeholder);
const {uuid} = await uploadFile(img, uploadUrl);
@@ -101,12 +100,11 @@ async function handleClipboardImages(editor, dropzone, images, e) {
const text = ``;
editor.replacePlaceholder(placeholder, text);
- const input = document.createElement('input');
- input.setAttribute('name', 'files');
- input.setAttribute('type', 'hidden');
- input.setAttribute('id', uuid);
- input.value = uuid;
- filesContainer.append(input);
+ const attachment = {uuid, name: img.name, browser_download_url: url, size: img.size, type: img.type};
+ dropzone.dropzone.emit('addedfile', attachment);
+ dropzone.dropzone.emit('create-thumbnail', attachment, img);
+ dropzone.dropzone.emit('complete', attachment);
+ dropzone.dropzone.emit('success', attachment, {uuid});
}
}
diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js
index 297329d816..d3f81c3a86 100644
--- a/web_src/js/features/repo-issue.js
+++ b/web_src/js/features/repo-issue.js
@@ -57,7 +57,7 @@ export function initRepoIssueTimeTracking() {
$(sel).modal({
duration: 200,
onApprove() {
- document.getElementById(`${sel} form`).requestSubmit();
+ document.querySelector(`${sel} form`).requestSubmit();
},
}).modal('show');
});
@@ -440,7 +440,7 @@ export async function handleReply($el) {
// When the page is loaded, the dropzone is initialized by initGlobalDropzone, but the editor is not initialized.
// When the form is submitted and partially reload, none of them is initialized.
const dropzone = $form.find('.dropzone')[0];
- if (!dropzone.dropzone) initDropzone(dropzone);
+ if (!dropzone.dropzone) await initDropzone(dropzone);
editor = await initComboMarkdownEditor($form.find('.combo-markdown-editor'));
}
editor.focus();
@@ -575,7 +575,7 @@ export function initRepoPullRequestReview() {
$td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed');
$td.find("input[name='path']").val(path);
- initDropzone($td.find('.dropzone')[0]);
+ await initDropzone($td.find('.dropzone')[0]);
const editor = await initComboMarkdownEditor($td.find('.combo-markdown-editor'));
editor.focus();
} catch (error) {
diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js
index 25ed181616..66ee945d02 100644
--- a/web_src/js/features/repo-legacy.js
+++ b/web_src/js/features/repo-legacy.js
@@ -16,7 +16,6 @@ import {
import {initCitationFileCopyContent} from './citation.js';
import {initCompLabelEdit} from './comp/LabelEdit.js';
import {initRepoDiffConversationNav} from './repo-diff.js';
-import {createDropzone} from './dropzone.js';
import {showErrorToast} from '../modules/toast.js';
import {initCommentContent, initMarkupContent} from '../markup/content.js';
import {initCompReactionSelector} from './comp/ReactionSelector.js';
@@ -26,12 +25,10 @@ import {initRepoPullRequestCommitStatus} from './repo-issue-pr-status.js';
import {hideElem, showElem} from '../utils/dom.js';
import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.js';
import {attachRefIssueContextPopup} from './contextpopup.js';
-import {POST, GET} from '../modules/fetch.js';
+import {POST} from '../modules/fetch.js';
import {MarkdownQuote} from '@github/quote-selection';
import {toAbsoluteUrl} from '../utils.js';
-import {initGlobalShowModal} from './common-global.js';
-
-const {csrfToken} = window.config;
+import {initDropzone, initGlobalShowModal} from './common-global.js';
export function initRepoCommentForm() {
const $commentForm = $('.comment.form');
@@ -312,115 +309,27 @@ async function onEditContent(event) {
let comboMarkdownEditor;
- /**
- * @param {HTMLElement} dropzone
- */
- const setupDropzone = async (dropzone) => {
- if (!dropzone) return null;
-
- let disableRemovedfileEvent = false; // when resetting the dropzone (removeAllFiles), disable the "removedfile" event
- let fileUuidDict = {}; // to record: if a comment has been saved, then the uploaded files won't be deleted from server when clicking the Remove in the dropzone
- const dz = await createDropzone(dropzone, {
- url: dropzone.getAttribute('data-upload-url'),
- headers: {'X-Csrf-Token': csrfToken},
- maxFiles: dropzone.getAttribute('data-max-file'),
- maxFilesize: dropzone.getAttribute('data-max-size'),
- acceptedFiles: ['*/*', ''].includes(dropzone.getAttribute('data-accepts')) ? null : dropzone.getAttribute('data-accepts'),
- addRemoveLinks: true,
- dictDefaultMessage: dropzone.getAttribute('data-default-message'),
- dictInvalidFileType: dropzone.getAttribute('data-invalid-input-type'),
- dictFileTooBig: dropzone.getAttribute('data-file-too-big'),
- dictRemoveFile: dropzone.getAttribute('data-remove-file'),
- timeout: 0,
- thumbnailMethod: 'contain',
- thumbnailWidth: 480,
- thumbnailHeight: 480,
- init() {
- this.on('success', (file, data) => {
- file.uuid = data.uuid;
- fileUuidDict[file.uuid] = {submitted: false};
- const input = document.createElement('input');
- input.id = data.uuid;
- input.name = 'files';
- input.type = 'hidden';
- input.value = data.uuid;
- dropzone.querySelector('.files').append(input);
- });
- this.on('removedfile', async (file) => {
- document.getElementById(file.uuid)?.remove();
- if (disableRemovedfileEvent) return;
- if (dropzone.getAttribute('data-remove-url') && !fileUuidDict[file.uuid].submitted) {
- try {
- await POST(dropzone.getAttribute('data-remove-url'), {data: new URLSearchParams({file: file.uuid})});
- } catch (error) {
- console.error(error);
- }
- }
- });
- this.on('submit', () => {
- for (const fileUuid of Object.keys(fileUuidDict)) {
- fileUuidDict[fileUuid].submitted = true;
- }
- });
- this.on('reload', async () => {
- try {
- const response = await GET(editContentZone.getAttribute('data-attachment-url'));
- const data = await response.json();
- // do not trigger the "removedfile" event, otherwise the attachments would be deleted from server
- disableRemovedfileEvent = true;
- dz.removeAllFiles(true);
- dropzone.querySelector('.files').innerHTML = '';
- for (const el of dropzone.querySelectorAll('.dz-preview')) el.remove();
- fileUuidDict = {};
- disableRemovedfileEvent = false;
-
- for (const attachment of data) {
- const imgSrc = `${dropzone.getAttribute('data-link-url')}/${attachment.uuid}`;
- dz.emit('addedfile', attachment);
- dz.emit('thumbnail', attachment, imgSrc);
- dz.emit('complete', attachment);
- fileUuidDict[attachment.uuid] = {submitted: true};
- dropzone.querySelector(`img[src='${imgSrc}']`).style.maxWidth = '100%';
- const input = document.createElement('input');
- input.id = attachment.uuid;
- input.name = 'files';
- input.type = 'hidden';
- input.value = attachment.uuid;
- dropzone.querySelector('.files').append(input);
- }
- if (!dropzone.querySelector('.dz-preview')) {
- dropzone.classList.remove('dz-started');
- }
- } catch (error) {
- console.error(error);
- }
- });
- },
- });
- dz.emit('reload');
- return dz;
- };
-
const cancelAndReset = (e) => {
e.preventDefault();
showElem(renderContent);
hideElem(editContentZone);
comboMarkdownEditor.value(rawContent.textContent);
- comboMarkdownEditor.attachedDropzoneInst?.emit('reload');
+ editContentZone.querySelector('.dropzone')?.dropzone?.emit('reload');
};
const saveAndRefresh = async (e) => {
e.preventDefault();
showElem(renderContent);
hideElem(editContentZone);
- const dropzoneInst = comboMarkdownEditor.attachedDropzoneInst;
+ const dropzone = editContentZone.querySelector('.dropzone')?.dropzone;
+ for (const element of dropzone?.element?.querySelectorAll('.dz-preview') ?? []) element.classList.remove('dz-success');
try {
const params = new URLSearchParams({
content: comboMarkdownEditor.value(),
context: editContentZone.getAttribute('data-context'),
content_version: editContentZone.getAttribute('data-content-version'),
});
- const files = dropzoneInst?.element?.querySelectorAll('.files [name=files]') ?? [];
+ const files = dropzone?.element?.querySelectorAll('.files [name=files]') ?? [];
for (const fileInput of files) {
params.append('files[]', fileInput.value);
}
@@ -451,8 +360,7 @@ async function onEditContent(event) {
} else {
content.querySelector('.dropzone-attachments').outerHTML = data.attachments;
}
- dropzoneInst?.emit('submit');
- dropzoneInst?.emit('reload');
+ dropzone?.emit('submit');
initMarkupContent();
initCommentContent();
} catch (error) {
@@ -463,8 +371,10 @@ async function onEditContent(event) {
comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
if (!comboMarkdownEditor) {
editContentZone.innerHTML = document.getElementById('issue-comment-editor-template').innerHTML;
+ const dropzone = editContentZone.querySelector('.dropzone');
+ if (!dropzone.dropzone) await initDropzone(dropzone, editContentZone);
comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
- comboMarkdownEditor.attachedDropzoneInst = await setupDropzone(editContentZone.querySelector('.dropzone'));
+ dropzone.dropzone.emit('reload');
editContentZone.addEventListener('ce-quick-submit', saveAndRefresh);
editContentZone.querySelector('button[data-button-name="cancel-edit"]').addEventListener('click', cancelAndReset);
editContentZone.querySelector('button[data-button-name="save-edit"]').addEventListener('click', saveAndRefresh);
@@ -621,6 +531,13 @@ const filters = {
}
return el;
},
+ IMG(el, context) {
+ const src = el.getAttribute('src');
+ if (src?.startsWith(context)) {
+ el.src = src.slice(context.length);
+ }
+ return el;
+ },
};
function hasContent(node) {
@@ -628,32 +545,34 @@ function hasContent(node) {
}
// This code matches that of what is done by @github/quote-selection
-function preprocessFragment(fragment) {
- const nodeIterator = document.createNodeIterator(fragment, NodeFilter.SHOW_ELEMENT, {
- acceptNode(node) {
- if (node.nodeName in filters && hasContent(node)) {
- return NodeFilter.FILTER_ACCEPT;
+function preprocessFragment(context) {
+ return function(fragment) {
+ const nodeIterator = document.createNodeIterator(fragment, NodeFilter.SHOW_ELEMENT, {
+ acceptNode(node) {
+ if (node.nodeName in filters && hasContent(node)) {
+ return NodeFilter.FILTER_ACCEPT;
+ }
+
+ return NodeFilter.FILTER_SKIP;
+ },
+ });
+ const results = [];
+ let node = nodeIterator.nextNode();
+
+ while (node) {
+ if (node instanceof HTMLElement) {
+ results.push(node);
}
-
- return NodeFilter.FILTER_SKIP;
- },
- });
- const results = [];
- let node = nodeIterator.nextNode();
-
- while (node) {
- if (node instanceof HTMLElement) {
- results.push(node);
+ node = nodeIterator.nextNode();
}
- node = nodeIterator.nextNode();
- }
// process deepest matches first
- results.reverse();
+ results.reverse();
- for (const el of results) {
- el.replaceWith(filters[el.nodeName](el));
- }
+ for (const el of results) {
+ el.replaceWith(filters[el.nodeName](el, context));
+ }
+ };
}
function initRepoIssueCommentEdit() {
@@ -663,7 +582,7 @@ function initRepoIssueCommentEdit() {
// Quote reply
$(document).on('click', '.quote-reply', async (event) => {
event.preventDefault();
- const quote = new MarkdownQuote('', preprocessFragment);
+ const quote = new MarkdownQuote('', preprocessFragment(event.target.getAttribute('data-context')));
let editorTextArea;
if (event.target.classList.contains('quote-reply-diff')) {
diff --git a/web_src/js/utils.test.js b/web_src/js/utils.test.js
index 535aae874a..365eb63e30 100644
--- a/web_src/js/utils.test.js
+++ b/web_src/js/utils.test.js
@@ -1,3 +1,4 @@
+import {expect, test} from 'vitest';
import {
basename, extname, isObject, stripTags, parseIssueHref,
parseUrl, translateMonth, translateDay, blobToDataURI,
@@ -182,5 +183,5 @@ async function testSleep(ms) {
await sleep(ms);
const endTime = Date.now(); // Record the end time
const actualSleepTime = endTime - startTime;
- expect(actualSleepTime >= ms).toBeTruthy();
+ expect(actualSleepTime).toBeGreaterThanOrEqual(ms);
}