mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-04-21 07:16:41 +02:00
Merge branch 'forgejo' into forgotten_password
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
This commit is contained in:
commit
95c4daaa4c
94 changed files with 1356 additions and 448 deletions
|
@ -22,11 +22,6 @@ code.gitea.io/gitea/models/actions
|
|||
ScheduleList.LoadTriggerUser
|
||||
ScheduleList.LoadRepos
|
||||
|
||||
code.gitea.io/gitea/models/asymkey
|
||||
ErrGPGKeyAccessDenied.Error
|
||||
ErrGPGKeyAccessDenied.Unwrap
|
||||
HasDeployKey
|
||||
|
||||
code.gitea.io/gitea/models/auth
|
||||
GetSourceByName
|
||||
WebAuthnCredentials
|
||||
|
@ -54,9 +49,7 @@ code.gitea.io/gitea/models/git
|
|||
|
||||
code.gitea.io/gitea/models/issues
|
||||
IsErrUnknownDependencyType
|
||||
ErrNewIssueInsert.Error
|
||||
IsErrIssueWasClosed
|
||||
ChangeMilestoneStatus
|
||||
|
||||
code.gitea.io/gitea/models/organization
|
||||
GetTeamNamesByID
|
||||
|
@ -81,16 +74,12 @@ code.gitea.io/gitea/models/repo
|
|||
WatchRepoMode
|
||||
|
||||
code.gitea.io/gitea/models/user
|
||||
ErrUserInactive.Error
|
||||
ErrUserInactive.Unwrap
|
||||
IsErrExternalLoginUserAlreadyExist
|
||||
IsErrExternalLoginUserNotExist
|
||||
NewFederatedUser
|
||||
IsErrUserSettingIsNotExist
|
||||
GetUserAllSettings
|
||||
DeleteUserSetting
|
||||
GetUserEmailsByNames
|
||||
GetUserNamesByIDs
|
||||
|
||||
code.gitea.io/gitea/modules/activitypub
|
||||
NewContext
|
||||
|
|
|
@ -3,7 +3,7 @@ runs:
|
|||
steps:
|
||||
- run: |
|
||||
su forgejo -c 'make deps-backend'
|
||||
- uses: actions/cache@v4
|
||||
- uses: https://data.forgejo.org/actions/cache@v4
|
||||
id: cache-backend
|
||||
with:
|
||||
path: ${{github.workspace}}/gitea
|
||||
|
|
|
@ -49,7 +49,7 @@ runs:
|
|||
|
||||
- name: "Restore Go dependencies from cache or mark for later caching"
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4
|
||||
uses: https://data.forgejo.org/actions/cache@v4
|
||||
with:
|
||||
key: setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}-${{ hashFiles('go.sum', 'go.mod') }}
|
||||
restore-keys: |
|
||||
|
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
if: vars.ROLE == 'forgejo-coding'
|
||||
runs-on: lxc-bookworm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
|
||||
- id: forgejo
|
||||
uses: https://data.forgejo.org/actions/setup-forgejo@v2.0.4
|
||||
|
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
# root is used for testing, allow it
|
||||
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
@ -37,11 +37,11 @@ jobs:
|
|||
container:
|
||||
image: data.forgejo.org/oci/node:20-bookworm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
show-progress: 'false'
|
||||
- uses: https://code.forgejo.org/actions/cascading-pr@v2.2.0
|
||||
- uses: https://data.forgejo.org/actions/cascading-pr@v2.2.0
|
||||
with:
|
||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||
origin-repo: ${{ github.repository }}
|
||||
|
|
|
@ -39,7 +39,7 @@ jobs:
|
|||
runs-on: lxc-bookworm
|
||||
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
|
||||
- name: copy & sign
|
||||
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.3.1
|
||||
|
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
apt-get update -qq
|
||||
apt-get -q install -qq -y zstd
|
||||
- name: "Cache frontend build for playwright testing"
|
||||
uses: actions/cache/save@v4
|
||||
uses: https://data.forgejo.org/actions/cache/save@v4
|
||||
with:
|
||||
path: ${{github.workspace}}/public/assets
|
||||
key: frontend-build-${{ github.sha }}
|
||||
|
@ -104,7 +104,7 @@ jobs:
|
|||
fetch-depth: 20
|
||||
- uses: ./.forgejo/workflows-composite/setup-env
|
||||
- name: "Restore frontend build"
|
||||
uses: actions/cache/restore@v4
|
||||
uses: https://data.forgejo.org/actions/cache/restore@v4
|
||||
id: cache-frontend
|
||||
with:
|
||||
path: ${{github.workspace}}/public/assets
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
|
@ -51,7 +51,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
|||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM code.forgejo.org/oci/alpine:3.21
|
||||
FROM data.forgejo.org/oci/alpine:3.21
|
||||
ARG RELEASE_VERSION
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
|
@ -49,7 +49,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
|||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM code.forgejo.org/oci/alpine:3.21
|
||||
FROM data.forgejo.org/oci/alpine:3.21
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
org.opencontainers.image.url="https://forgejo.org" \
|
||||
|
|
2
Makefile
2
Makefile
|
@ -37,7 +37,7 @@ endif
|
|||
XGO_VERSION := go-1.21.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.1.1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.0 # renovate: datasource=go
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2 # renovate: datasource=go
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
||||
|
|
|
@ -192,28 +192,6 @@ func (err ErrGPGKeyIDAlreadyUsed) Unwrap() error {
|
|||
return util.ErrAlreadyExist
|
||||
}
|
||||
|
||||
// ErrGPGKeyAccessDenied represents a "GPGKeyAccessDenied" kind of Error.
|
||||
type ErrGPGKeyAccessDenied struct {
|
||||
UserID int64
|
||||
KeyID int64
|
||||
}
|
||||
|
||||
// IsErrGPGKeyAccessDenied checks if an error is a ErrGPGKeyAccessDenied.
|
||||
func IsErrGPGKeyAccessDenied(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyAccessDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Error pretty-prints an error of type ErrGPGKeyAccessDenied.
|
||||
func (err ErrGPGKeyAccessDenied) Error() string {
|
||||
return fmt.Sprintf("user does not have access to the key [user_id: %d, key_id: %d]",
|
||||
err.UserID, err.KeyID)
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyAccessDenied) Unwrap() error {
|
||||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
|
||||
type ErrKeyAccessDenied struct {
|
||||
UserID int64
|
||||
|
|
|
@ -105,14 +105,6 @@ func addDeployKey(ctx context.Context, keyID, repoID int64, name, fingerprint st
|
|||
return key, db.Insert(ctx, key)
|
||||
}
|
||||
|
||||
// HasDeployKey returns true if public key is a deploy key of given repository.
|
||||
func HasDeployKey(ctx context.Context, keyID, repoID int64) bool {
|
||||
has, _ := db.GetEngine(ctx).
|
||||
Where("key_id = ? AND repo_id = ?", keyID, repoID).
|
||||
Get(new(DeployKey))
|
||||
return has
|
||||
}
|
||||
|
||||
// AddDeployKey add new deploy key to database and authorized_keys file.
|
||||
func AddDeployKey(ctx context.Context, repoID int64, name, content string, readOnly bool) (*DeployKey, error) {
|
||||
fingerprint, err := CalcFingerprint(content)
|
||||
|
|
|
@ -63,21 +63,6 @@ func (err ErrIssueIsClosed) Error() string {
|
|||
return fmt.Sprintf("issue is closed [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
|
||||
}
|
||||
|
||||
// ErrNewIssueInsert is used when the INSERT statement in newIssue fails
|
||||
type ErrNewIssueInsert struct {
|
||||
OriginalError error
|
||||
}
|
||||
|
||||
// IsErrNewIssueInsert checks if an error is a ErrNewIssueInsert.
|
||||
func IsErrNewIssueInsert(err error) bool {
|
||||
_, ok := err.(ErrNewIssueInsert)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrNewIssueInsert) Error() string {
|
||||
return err.OriginalError.Error()
|
||||
}
|
||||
|
||||
// ErrIssueWasClosed is used when close a closed issue
|
||||
type ErrIssueWasClosed struct {
|
||||
ID int64
|
||||
|
|
|
@ -433,7 +433,7 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *Issue, la
|
|||
LabelIDs: labelIDs,
|
||||
Attachments: uuids,
|
||||
}); err != nil {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("newIssue: %w", err)
|
||||
|
|
|
@ -251,21 +251,6 @@ func ChangeMilestoneStatusByRepoIDAndID(ctx context.Context, repoID, milestoneID
|
|||
return committer.Commit()
|
||||
}
|
||||
|
||||
// ChangeMilestoneStatus changes the milestone open/closed status.
|
||||
func ChangeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) (err error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err := changeMilestoneStatus(ctx, m, isClosed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
func changeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) error {
|
||||
m.IsClosed = isClosed
|
||||
if isClosed {
|
||||
|
|
|
@ -298,17 +298,16 @@ func TestNewMilestone(t *testing.T) {
|
|||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{})
|
||||
}
|
||||
|
||||
func TestChangeMilestoneStatus(t *testing.T) {
|
||||
func TestChangeMilestoneStatusByRepoIDAndID(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1})
|
||||
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatus(db.DefaultContext, milestone, true))
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{})
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatusByRepoIDAndID(db.DefaultContext, 1, 1, true))
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1, IsClosed: true})
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: 1}, &issues_model.Milestone{})
|
||||
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatus(db.DefaultContext, milestone, false))
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatusByRepoIDAndID(db.DefaultContext, 1, 1, false))
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}, "is_closed=0")
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{})
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: 1}, &issues_model.Milestone{})
|
||||
}
|
||||
|
||||
func TestDeleteMilestoneByRepoID(t *testing.T) {
|
||||
|
|
|
@ -575,7 +575,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *Iss
|
|||
Attachments: uuids,
|
||||
IsPull: true,
|
||||
}); err != nil {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("newIssue: %w", err)
|
||||
|
|
|
@ -71,27 +71,6 @@ func (err ErrUserProhibitLogin) Unwrap() error {
|
|||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrUserInactive represents a "ErrUserInactive" kind of error.
|
||||
type ErrUserInactive struct {
|
||||
UID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrUserInactive checks if an error is a ErrUserInactive
|
||||
func IsErrUserInactive(err error) bool {
|
||||
_, ok := err.(ErrUserInactive)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserInactive) Error() string {
|
||||
return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name)
|
||||
}
|
||||
|
||||
// Unwrap unwraps this error as a ErrPermission error
|
||||
func (err ErrUserInactive) Unwrap() error {
|
||||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrUserIsNotLocal represents a "ErrUserIsNotLocal" kind of error.
|
||||
type ErrUserIsNotLocal struct {
|
||||
UID int64
|
||||
|
|
|
@ -40,6 +40,7 @@ type SearchUserOptions struct {
|
|||
IsProhibitLogin optional.Option[bool]
|
||||
IncludeReserved bool
|
||||
|
||||
Load2FAStatus bool
|
||||
ExtraParamStrings map[string]string
|
||||
}
|
||||
|
||||
|
@ -126,17 +127,15 @@ func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) *xorm.Sess
|
|||
return e.Where(cond)
|
||||
}
|
||||
|
||||
// 2fa filter uses LEFT JOIN to check whether a user has a 2fa record
|
||||
// While using LEFT JOIN, sometimes the performance might not be good, but it won't be a problem now, such SQL is seldom executed.
|
||||
// There are some possible methods to refactor this SQL in future when we really need to optimize the performance (but not now):
|
||||
// (1) add a column in user table (2) add a setting value in user_setting table (3) use search engines (bleve/elasticsearch)
|
||||
// Check if the user has two factor enabled, which is TOTP or Webauthn.
|
||||
if opts.IsTwoFactorEnabled.Value() {
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL"))
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL OR webauthn_credential.user_id IS NOT NULL"))
|
||||
} else {
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NULL"))
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NULL AND webauthn_credential.user_id IS NULL"))
|
||||
}
|
||||
|
||||
return e.Join("LEFT OUTER", "two_factor", "two_factor.uid = `user`.id").
|
||||
Join("LEFT OUTER", "webauthn_credential", "webauthn_credential.user_id = `user`.id").
|
||||
Where(cond)
|
||||
}
|
||||
|
||||
|
|
|
@ -1043,22 +1043,6 @@ func GetUserByName(ctx context.Context, name string) (*User, error) {
|
|||
return u, nil
|
||||
}
|
||||
|
||||
// GetUserEmailsByNames returns a list of e-mails corresponds to names of users
|
||||
// that have their email notifications set to enabled or onmention.
|
||||
func GetUserEmailsByNames(ctx context.Context, names []string) []string {
|
||||
mails := make([]string, 0, len(names))
|
||||
for _, name := range names {
|
||||
u, err := GetUserByName(ctx, name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.IsMailable() && u.EmailNotificationsPreference != EmailNotificationsDisabled {
|
||||
mails = append(mails, u.Email)
|
||||
}
|
||||
}
|
||||
return mails
|
||||
}
|
||||
|
||||
// GetMaileableUsersByIDs gets users from ids, but only if they can receive mails
|
||||
func GetMaileableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([]*User, error) {
|
||||
if len(ids) == 0 {
|
||||
|
@ -1085,17 +1069,6 @@ func GetMaileableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([
|
|||
Find(&ous)
|
||||
}
|
||||
|
||||
// GetUserNamesByIDs returns usernames for all resolved users from a list of Ids.
|
||||
func GetUserNamesByIDs(ctx context.Context, ids []int64) ([]string, error) {
|
||||
unames := make([]string, 0, len(ids))
|
||||
err := db.GetEngine(ctx).In("id", ids).
|
||||
Table("user").
|
||||
Asc("name").
|
||||
Cols("name").
|
||||
Find(&unames)
|
||||
return unames, err
|
||||
}
|
||||
|
||||
// GetUserNameByID returns username for the id
|
||||
func GetUserNameByID(ctx context.Context, id int64) (string, error) {
|
||||
var name string
|
||||
|
|
|
@ -102,16 +102,6 @@ func TestGetUserByName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetUserEmailsByNames(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// ignore none active user email
|
||||
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
|
||||
assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
|
||||
|
||||
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "org7"}))
|
||||
}
|
||||
|
||||
func TestCanCreateOrganization(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
|
@ -222,7 +212,7 @@ func TestSearchUsers(t *testing.T) {
|
|||
[]int64{1041, 37})
|
||||
|
||||
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsTwoFactorEnabled: optional.Some(true)},
|
||||
[]int64{24})
|
||||
[]int64{24, 32})
|
||||
}
|
||||
|
||||
func TestEmailNotificationPreferences(t *testing.T) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
|
@ -83,6 +84,10 @@ func newFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
|
|||
} else if Type(filePath) != "" {
|
||||
urlFullSource = node.Data[m[0]:m[6]] + filePath + "?display=source#" + node.Data[m[8]:m[1]]
|
||||
}
|
||||
filePath, err := url.QueryUnescape(filePath)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
hash := node.Data[m[8]:m[9]]
|
||||
|
||||
preview.start = m[0]
|
||||
|
|
|
@ -759,9 +759,6 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
|
|||
title = path.Base(name)
|
||||
}
|
||||
alt := props["alt"]
|
||||
if alt == "" {
|
||||
alt = name
|
||||
}
|
||||
|
||||
// make the childNode an image - if we can, we also place the alt
|
||||
childNode.Type = html.ElementNode
|
||||
|
@ -772,9 +769,6 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
|
|||
{Key: "title", Val: title},
|
||||
{Key: "alt", Val: alt},
|
||||
}
|
||||
if alt == "" {
|
||||
childNode.Attr = childNode.Attr[:2]
|
||||
}
|
||||
} else {
|
||||
if !absoluteLink {
|
||||
if ctx.IsWiki {
|
||||
|
|
|
@ -416,7 +416,7 @@ func TestRender_ShortLinks(t *testing.T) {
|
|||
otherImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+Other.jpg")
|
||||
encodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+%23.jpg")
|
||||
notencodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "some", "path", "Link+#.jpg")
|
||||
favicon := "http://google.com/favicon.ico"
|
||||
favicon := "https://forgejo.org/favicon.ico"
|
||||
|
||||
test(
|
||||
"[[Link]]",
|
||||
|
@ -424,28 +424,28 @@ func TestRender_ShortLinks(t *testing.T) {
|
|||
`<p><a href="`+urlWiki+`" rel="nofollow">Link</a></p>`)
|
||||
test(
|
||||
"[[Link.jpg]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Link.jpg" alt="Link.jpg"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Link.jpg" alt="Link.jpg"/></a></p>`)
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Link.jpg" alt=""/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Link.jpg" alt=""/></a></p>`)
|
||||
test(
|
||||
"[["+favicon+"]]",
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt="`+favicon+`"/></a></p>`,
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt="`+favicon+`"/></a></p>`)
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt=""/></a></p>`,
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link]]",
|
||||
`<p><a href="`+url+`" rel="nofollow">Name</a></p>`,
|
||||
`<p><a href="`+urlWiki+`" rel="nofollow">Name</a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Name" alt="Name"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Name" alt="Name"/></a></p>`)
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Name" alt=""/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Name" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=AltName]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="AltName" alt="AltName"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="AltName" alt="AltName"/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg|title=Title]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="Title"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Title" alt="Title"/></a></p>`)
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt=""/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Title" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=AltName|title=Title]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
|
@ -472,16 +472,16 @@ func TestRender_ShortLinks(t *testing.T) {
|
|||
`<p><a href="`+urlWiki+`" rel="nofollow">Link</a> <a href="`+otherURLWiki+`" rel="nofollow">Other Link</a> <a href="`+encodedURLWiki+`" rel="nofollow">Link?</a></p>`)
|
||||
test(
|
||||
"[[Link #.jpg]]",
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`,
|
||||
`<p><a href="`+encodedImgurlWiki+`" rel="nofollow"><img src="`+encodedImgurlWiki+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`)
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt=""/></a></p>`,
|
||||
`<p><a href="`+encodedImgurlWiki+`" rel="nofollow"><img src="`+encodedImgurlWiki+`" title="Link #.jpg" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link #.jpg|alt=\"AltName\"|title='Title']]",
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
`<p><a href="`+encodedImgurlWiki+`" rel="nofollow"><img src="`+encodedImgurlWiki+`" title="Title" alt="AltName"/></a></p>`)
|
||||
test(
|
||||
"[[some/path/Link #.jpg]]",
|
||||
`<p><a href="`+notencodedImgurl+`" rel="nofollow"><img src="`+notencodedImgurl+`" title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p>`,
|
||||
`<p><a href="`+notencodedImgurlWiki+`" rel="nofollow"><img src="`+notencodedImgurlWiki+`" title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p>`)
|
||||
`<p><a href="`+notencodedImgurl+`" rel="nofollow"><img src="`+notencodedImgurl+`" title="Link #.jpg" alt=""/></a></p>`,
|
||||
`<p><a href="`+notencodedImgurlWiki+`" rel="nofollow"><img src="`+notencodedImgurlWiki+`" title="Link #.jpg" alt=""/></a></p>`)
|
||||
test(
|
||||
"<p><a href=\"https://example.org\">[[foobar]]</a></p>",
|
||||
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`,
|
||||
|
@ -1129,4 +1129,35 @@ func TestRender_FilePreview(t *testing.T) {
|
|||
localMetas,
|
||||
)
|
||||
})
|
||||
|
||||
commitFileURL = util.URLJoin(markup.TestRepoURL, "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d", "path", "to", "file%20%23.txt")
|
||||
|
||||
t.Run("file with strange characters in name", func(t *testing.T) {
|
||||
testRender(
|
||||
commitFileURL+"#L1",
|
||||
`<p></p>`+
|
||||
`<div class="file-preview-box">`+
|
||||
`<div class="header">`+
|
||||
`<div>`+
|
||||
`<a href="http://localhost:3000/gogits/gogs/src/commit/eeb243c3395e1921c5d90e73bd739827251fc99d/path/to/file%20%23.txt#L1" class="muted" rel="nofollow">path/to/file #.txt</a>`+
|
||||
`</div>`+
|
||||
`<span class="text small grey">`+
|
||||
`Line 1 in <a href="http://localhost:3000/gogits/gogs/src/commit/eeb243c3395e1921c5d90e73bd739827251fc99d" class="text black" rel="nofollow">eeb243c</a>`+
|
||||
`</span>`+
|
||||
`</div>`+
|
||||
`<div class="ui table">`+
|
||||
`<table class="file-preview">`+
|
||||
`<tbody>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="1"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner">A`+"\n"+`</code></td>`+
|
||||
`</tr>`+
|
||||
`</tbody>`+
|
||||
`</table>`+
|
||||
`</div>`+
|
||||
`</div>`+
|
||||
`<p></p>`,
|
||||
localMetas,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ func TestRender_Images(t *testing.T) {
|
|||
|
||||
test(
|
||||
"[["+title+"|"+url+"]]",
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt=""/></a></p>`)
|
||||
test(
|
||||
"[]("+href+")",
|
||||
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
@ -119,7 +119,7 @@ func TestRender_Images(t *testing.T) {
|
|||
|
||||
test(
|
||||
"[["+title+"|"+url+"]]",
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt=""/></a></p>`)
|
||||
test(
|
||||
"[]("+href+")",
|
||||
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
@ -149,13 +149,13 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
|
|||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><a href="` + baseURLImages + `/images/icon-install.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-install.png" title="icon-install.png" alt="images/icon-install.png"/></a></th>
|
||||
<th><a href="` + baseURLImages + `/images/icon-install.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-install.png" title="icon-install.png" alt=""/></a></th>
|
||||
<th><a href="` + baseURLContent + `/Installation" rel="nofollow">Installation</a></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="` + baseURLImages + `/images/icon-usage.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-usage.png" title="icon-usage.png" alt="images/icon-usage.png"/></a></td>
|
||||
<td><a href="` + baseURLImages + `/images/icon-usage.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-usage.png" title="icon-usage.png" alt=""/></a></td>
|
||||
<td><a href="` + baseURLContent + `/Usage" rel="nofollow">Usage</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -164,9 +164,9 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
|
|||
`<p><a href="http://www.excelsiorjet.com/" rel="nofollow">Excelsior JET</a> allows you to create native executables for Windows, Linux and Mac OS X.</p>
|
||||
<ol>
|
||||
<li><a href="https://github.com/libgdx/libgdx/wiki/Gradle-on-the-Commandline#packaging-for-the-desktop" rel="nofollow">Package your libGDX application</a><br/>
|
||||
<a href="` + baseURLImages + `/images/1.png" rel="nofollow"><img src="` + baseURLImages + `/images/1.png" title="1.png" alt="images/1.png"/></a></li>
|
||||
<a href="` + baseURLImages + `/images/1.png" rel="nofollow"><img src="` + baseURLImages + `/images/1.png" title="1.png" alt=""/></a></li>
|
||||
<li>Perform a test run by hitting the Run! button.<br/>
|
||||
<a href="` + baseURLImages + `/images/2.png" rel="nofollow"><img src="` + baseURLImages + `/images/2.png" title="2.png" alt="images/2.png"/></a></li>
|
||||
<a href="` + baseURLImages + `/images/2.png" rel="nofollow"><img src="` + baseURLImages + `/images/2.png" title="2.png" alt=""/></a></li>
|
||||
</ol>
|
||||
<h2 id="user-content-custom-id">More tests</h2>
|
||||
<p>(from <a href="https://www.markdownguide.org/extended-syntax/" rel="nofollow">https://www.markdownguide.org/extended-syntax/</a>)</p>
|
||||
|
@ -849,8 +849,8 @@ mail@domain.com
|
|||
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
|
||||
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -876,8 +876,8 @@ space</p>
|
|||
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/wiki/raw/image.jpg" rel="nofollow"><img src="/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/wiki/raw/image.jpg" rel="nofollow"><img src="/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -905,8 +905,8 @@ space</p>
|
|||
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="https://gitea.io/image.jpg" rel="nofollow"><img src="https://gitea.io/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="https://gitea.io/image.jpg" rel="nofollow"><img src="https://gitea.io/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -934,8 +934,8 @@ space</p>
|
|||
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="https://gitea.io/wiki/raw/image.jpg" rel="nofollow"><img src="https://gitea.io/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="https://gitea.io/wiki/raw/image.jpg" rel="nofollow"><img src="https://gitea.io/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -963,8 +963,8 @@ space</p>
|
|||
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/image.jpg" rel="nofollow"><img src="/relative/path/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/image.jpg" rel="nofollow"><img src="/relative/path/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -992,8 +992,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1022,8 +1022,8 @@ space</p>
|
|||
<a href="/user/repo/media/branch/main/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/path/file" alt="local image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1052,8 +1052,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1082,8 +1082,8 @@ space</p>
|
|||
<a href="/user/repo/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/path/file" alt="local image"/></a><br/>
|
||||
<a href="/user/repo/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/user/repo/image.jpg" rel="nofollow"><img src="/user/repo/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/user/repo/image.jpg" rel="nofollow"><img src="/user/repo/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1112,8 +1112,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1143,8 +1143,8 @@ space</p>
|
|||
<a href="/user/repo/media/branch/main/sub/folder/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/path/file" alt="local image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/sub/folder/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/sub/folder/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/sub/folder/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/sub/folder/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/sub/folder/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1174,8 +1174,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
x•ŽANÃ0EYû³GB;a U=D9€=þ&–ÚÙÓr} 7èêÞÓÓëåÒŒBœ^¬´¤˜yY8Ï:AІX}<7D>R×XkÎs"î;uìFº®9x” Œ ÊEdÐ’%Í~**Zß3\ºÙvíô9Й>nÿ8Žfxkû=<3D>[9K”%L>®ôêÙ{§<>7Ãs–;aÕvý4ÛhXOûH·Ô“þÕ†ûð`KÑ
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +1 @@
|
|||
c9913120ed2c1e27c1d7752ecdb7a504dc7cf6be
|
||||
eeb243c3395e1921c5d90e73bd739827251fc99d
|
||||
|
|
|
@ -34,7 +34,7 @@ func AvatarHTML(src string, size int, class, name string) template.HTML {
|
|||
name = "avatar"
|
||||
}
|
||||
|
||||
return template.HTML(`<img loading="lazy" class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||
return template.HTML(`<img loading="lazy" alt="" class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||
}
|
||||
|
||||
// Avatar renders user avatars. args: user, size (int), class (string)
|
||||
|
|
|
@ -194,8 +194,8 @@ func TestRenderMarkdownToHtml(t *testing.T) {
|
|||
<a href="https://example.com" rel="nofollow">remote link</a>
|
||||
<a href="/image.jpg" target="_blank" rel="nofollow noopener"><img src="/image.jpg" alt="local image"/></a>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt="local image"/></a>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt=""/></a>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow"><code>88fc37a3c0...12fc37a3c0 (hash)</code></a>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow"><code>88fc37a3c0</code></a>
|
||||
|
|
|
@ -158,6 +158,7 @@ commits = fallback value for commits
|
|||
|
||||
found := lang1.HasKey("no-such")
|
||||
assert.False(t, found)
|
||||
assert.EqualValues(t, "no-such", lang1.TrString("no-such"))
|
||||
require.NoError(t, ls.Close())
|
||||
}
|
||||
|
||||
|
|
|
@ -225,9 +225,9 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
|
|||
format = msg
|
||||
} else {
|
||||
// First fallback: old-style translation
|
||||
idx, ok := l.store.trKeyToIdxMap[trKey]
|
||||
idx, foundIndex := l.store.trKeyToIdxMap[trKey]
|
||||
found := false
|
||||
if ok {
|
||||
if foundIndex {
|
||||
if msg, ok := l.idxToMsgMap[idx]; ok {
|
||||
format = msg // use the found translation
|
||||
found = true
|
||||
|
@ -239,7 +239,7 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
|
|||
if defaultLang, ok := l.store.localeMap[l.store.defaultLang]; ok {
|
||||
if msg := defaultLang.LookupNewStyleMessage(trKey); msg != "" {
|
||||
format = msg
|
||||
} else {
|
||||
} else if foundIndex {
|
||||
// Third fallback: old-style default language
|
||||
if msg, ok := defaultLang.idxToMsgMap[idx]; ok {
|
||||
format = msg
|
||||
|
|
|
@ -680,6 +680,8 @@ Location = Umístění
|
|||
To = Název větve
|
||||
Biography = Životopis
|
||||
AccessToken = Přístupový token
|
||||
username_claiming_cooldown = Uživatelské jméno nelze získat, protože ještě neskončila doba jeho platnosti. Půjde jej získat %[1]s.
|
||||
email_domain_is_not_allowed = Doména uživatelské e-mailové adresy <b>%s</b> je v rozporu se seznamem EMAIL_DOMAIN_ALLOWLIST nebo EMAIL_DOMAIN_BLOCKLIST. Ujistěte se, že je vaše adresa správně nastavena.
|
||||
|
||||
[user]
|
||||
change_avatar=Změnit váš avatar…
|
||||
|
@ -804,7 +806,7 @@ old_password=Stávající heslo
|
|||
new_password=Nové heslo
|
||||
retype_new_password=Potvrzení nového hesla
|
||||
password_incorrect=Zadané heslo není správné.
|
||||
change_password_success=Vaše heslo bylo aktualizováno. Od teď se přihlašujte novým heslem.
|
||||
change_password_success=Vaše heslo bylo aktualizováno. Od nynějška používejte kpřihlášení nové heslo.
|
||||
password_change_disabled=Externě ověřovaní uživatelé nemohou aktualizovat své heslo prostřednictvím webového rozhraní Forgejo.
|
||||
|
||||
emails=E-mailové adresy
|
||||
|
@ -1056,6 +1058,8 @@ language.description = Tento jazyk bude uložen do vašeho účtu a po přihlá
|
|||
language.localization_project = Pomozte nám s překladem Forgejo do vašeho jazyka! <a href="%s">Více informací</a>.
|
||||
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.
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Repozitář obsahuje všechny soubory projektu, včetně historie revizí. Už jej hostujete jinde? <a href="%s">Migrovat repozitář</a>.
|
||||
|
@ -3001,6 +3005,8 @@ 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é 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.
|
||||
settings.change_orgname_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.
|
||||
|
||||
[admin]
|
||||
dashboard=Přehled
|
||||
|
|
|
@ -629,6 +629,8 @@ password_special_one = Mindst ét specialtegn (tegnsætning, parenteser, anførs
|
|||
unsupported_login_type = Login typen understøttes ikke for at slette kontoen.
|
||||
cannot_add_org_to_team = En organisation kan ikke tilføjes som et holdmedlem.
|
||||
must_use_public_key = Nøglen du har angivet er en privat nøgle. Lad være med at uploade din private nøgle nogen steder. Brug din offentlige nøgle i stedet.
|
||||
username_claiming_cooldown = Brugernavnet kan ikke gøres krav på, fordi dets nedkølingsperiode endnu ikke er forbi. Det kan gøres krav på %[1]s.
|
||||
email_domain_is_not_allowed = Domænet for brugerens e-mailadresse <b>%s</b> er i konflikt med EMAIL_DOMAIN_ALLOWLIST eller EMAIL_DOMAIN_BLOCKLIST. Sørg for, at du har indstillet e-mailadressen korrekt.
|
||||
|
||||
[user]
|
||||
change_avatar = Skift din avatar…
|
||||
|
@ -782,7 +784,7 @@ uploaded_avatar_is_too_big = Den uploadede filstørrelse (%d KiB) overstiger den
|
|||
email_deletion_desc = E-mailadressen og relaterede oplysninger vil blive fjernet fra din konto. Git commits af denne e-mailadresse forbliver uændret. Fortsætte?
|
||||
choose_new_avatar = Vælg ny avatar
|
||||
update_avatar = Opdater avatar
|
||||
change_password_success = Din adgangskode er blevet opdateret. Log ind med din nye adgangskode fra nu af.
|
||||
change_password_success = Din adgangskode er blevet opdateret. Fra nu af skal du bruge din nye adgangskode til at logge ind.
|
||||
add_email = Tilføj e-mailadresse
|
||||
add_openid = Tilføj OpenID URI
|
||||
add_email_confirmation_sent = En bekræftelses-e-mail er blevet sendt til "%s". For at bekræfte din e-mailadresse, tjek venligst din indbakke og følg det medfølgende link inden for de næste %s.
|
||||
|
@ -972,6 +974,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.
|
||||
|
||||
[repo]
|
||||
rss.must_be_on_branch = Du skal være på en gren for at have et RSS-feed.
|
||||
|
@ -1761,6 +1765,28 @@ pulls.compare_changes = Ny pull-anmodning
|
|||
issues.summary_card_alt = Oversigtskort over et problem med titlen "%s" i depotet %s
|
||||
pulls.edit.already_changed = Kunne ikke gemme ændringer af pull-anmodningen. Det ser ud til, at indholdet allerede er blevet ændret af en anden bruger. Opdater siden, og prøv at redigere igen for at undgå at overskrive deres ændringer
|
||||
pulls.sign_in_require = <a href="%s">Log ind</a> for at oprette en ny pull-anmodning.
|
||||
pulls.allow_edits_from_maintainers = Tillad redigeringer fra vedligeholdere
|
||||
pulls.allow_edits_from_maintainers_desc = Brugere med skriveadgang til basisgrenen kan også trykke til denne gren
|
||||
pulls.allow_edits_from_maintainers_err = Opdatering mislykkedes
|
||||
pulls.compare_base = flet ind i
|
||||
pulls.compare_compare = pull fra
|
||||
pulls.switch_comparison_type = Skift sammenligningstype
|
||||
pulls.switch_head_and_base = Skift hoved og base
|
||||
pulls.filter_branch = Filter gren
|
||||
pulls.compare_changes_desc = Vælg den gren, der skal flettes ind i, og den gren, der skal trækkes fra.
|
||||
pulls.has_viewed_file = Set
|
||||
pulls.has_changed_since_last_review = Ændret siden din sidste gennemgang
|
||||
pulls.no_results = Ingen resultater fundet.
|
||||
pulls.show_all_commits = Vis alle commits
|
||||
pulls.show_changes_since_your_last_review = Vis ændringer siden din sidste gennemgang
|
||||
pulls.showing_only_single_commit = Viser kun ændringer af commit %[1]s
|
||||
pulls.showing_specified_commit_range = Viser kun ændringer mellem %[1]s..%[2]s
|
||||
pulls.select_commit_hold_shift_for_range = Vælg commit. Hold Shift + klik for at vælge et område
|
||||
pulls.review_only_possible_for_full_diff = Gennemgang er kun mulig, når du ser den fulde diff
|
||||
pulls.filter_changes_by_commit = Filtrer efter commit
|
||||
pulls.expand_files = Udvid alle filer
|
||||
pulls.collapse_files = Skjul alle filer
|
||||
pulls.viewed_files_label = %[1]d / %[2]d filer set
|
||||
|
||||
[notification]
|
||||
watching = Overvåger
|
||||
|
|
|
@ -681,6 +681,8 @@ Website = Webseite
|
|||
Location = Ort
|
||||
To = Branchname
|
||||
AccessToken = Zugangstoken
|
||||
username_claiming_cooldown = Der Benutzername kann nicht beansprucht werden, weil seine Schutzzeit noch nicht vorbei ist. Er kann am %[1]s beansprucht werden.
|
||||
email_domain_is_not_allowed = Die Domain der E-Mail-Adresse des Benutzers <b>%s</b> steht in Konflikt mit EMAIL_DOMAIN_ALLOWLIST oder EMAIL_DOMAIN_BLOCKLIST. Bitte stelle sicher, dass du die E-Mail-Adresse richtig gesetzt hast.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -806,7 +808,7 @@ old_password=Aktuelles Passwort
|
|||
new_password=Neues Passwort
|
||||
retype_new_password=Neues Passwort bestätigen
|
||||
password_incorrect=Das aktuelle Passwort ist falsch.
|
||||
change_password_success=Dein Passwort wurde aktualisiert. Bitte verwende dieses beim nächsten Einloggen.
|
||||
change_password_success=Dein Passwort wurde aktualisiert. Verwende ab jetzt dein neues Passwort zum Einloggen.
|
||||
password_change_disabled=Benutzer, die nicht von Forgejo verwaltet werden, können ihr Passwort im Web-Interface nicht ändern.
|
||||
|
||||
emails=E-Mail-Adressen
|
||||
|
@ -1058,6 +1060,8 @@ language.localization_project = Hilf uns, Forgejo in deine Sprache zu übersetze
|
|||
language.description = Diese Sprache wird in deinem Konto gespeichert und standardmäßig nach dem Anmelden benutzt.
|
||||
user_block_yourself = Du kannst dich nicht selbst blockieren.
|
||||
pronouns_custom_label = Individuelle Pronomen
|
||||
change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
|
||||
[repo]
|
||||
owner=Besitzer
|
||||
|
@ -3004,6 +3008,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 Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
|
||||
[admin]
|
||||
dashboard=Übersicht
|
||||
|
@ -3109,7 +3115,7 @@ dashboard.sync_branch.started=Synchronisierung der Branches gestartet
|
|||
dashboard.rebuild_issue_indexer=Issue-Indexer neu bauen
|
||||
|
||||
users.user_manage_panel=Benutzerkonten verwalten
|
||||
users.new_account=Benutzerkonto erstellen
|
||||
users.new_account=Benutzeraccount erstellen
|
||||
users.name=Benutzername
|
||||
users.full_name=Vollständiger Name
|
||||
users.activated=Aktiviert
|
||||
|
@ -3579,7 +3585,7 @@ comment_pull=`hat den Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> kommentiert`
|
|||
merge_pull_request=`führte Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> zusammen`
|
||||
auto_merge_pull_request=`führte Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> automatisch zusammen`
|
||||
transfer_repo=hat Repository <code>%s</code> übertragen zu <a href="%s">%s</a>
|
||||
push_tag=Tag <a href="%[2]s">%[3]s</a> nach <a href="%[1]s">%[4]s</a> wurde gepusht
|
||||
push_tag=hat Tag <a href="%[2]s">%[3]s</a> auf <a href="%[1]s">%[4]s</a> gepusht
|
||||
delete_tag=hat Tag %[2]s in <a href="%[1]s">%[3]s</a> gelöscht
|
||||
delete_branch=hat Branch %[2]s in <a href="%[1]s">%[3]s</a> gelöscht
|
||||
compare_branch=Vergleichen
|
||||
|
|
|
@ -1193,6 +1193,7 @@ archive.title = This repository is archived. You can view files and clone it, bu
|
|||
archive.title_date = This repository has been archived on %s. You can view files and clone it, but cannot push or open issues or pull requests.
|
||||
archive.issue.nocomment = This repository is archived. You cannot comment on issues.
|
||||
archive.pull.nocomment = This repository is archived. You cannot comment on pull requests.
|
||||
archive.pull.noreview = This repository is archived. You cannot review pull requests.
|
||||
|
||||
form.reach_limit_of_creation_1 = The owner has already reached the limit of %d repository.
|
||||
form.reach_limit_of_creation_n = The owner has already reached the limit of %d repositories.
|
||||
|
@ -1431,6 +1432,7 @@ editor.user_no_push_to_branch = User cannot push to branch
|
|||
editor.require_signed_commit = Branch requires a signed commit
|
||||
editor.cherry_pick = Cherry-pick %s onto:
|
||||
editor.revert = Revert %s onto:
|
||||
editor.commit_email = Commit email
|
||||
|
||||
commits.desc = Browse source code change history.
|
||||
commits.commits = Commits
|
||||
|
|
|
@ -56,7 +56,7 @@ mirror=Réplica
|
|||
new_repo=Nuevo repositorio
|
||||
new_migrate=Nueva migración
|
||||
new_mirror=Nueva réplica
|
||||
new_fork=Nuevo fork de repositorio
|
||||
new_fork=Nueva bifurcación del repositorio
|
||||
new_org=Nueva organización
|
||||
new_project=Nuevo proyecto
|
||||
new_project_column=Nueva columna
|
||||
|
@ -75,7 +75,7 @@ collaborative=Colaborativo
|
|||
forks=Forks
|
||||
|
||||
activities=Actividades
|
||||
pull_requests=Pull requests
|
||||
pull_requests=Solicitudes de incorporación de cambios
|
||||
issues=Incidencias
|
||||
milestones=Hitos
|
||||
|
||||
|
@ -156,8 +156,8 @@ invalid_data = Datos inválidos: %v
|
|||
confirm_delete_artifact = ¿Estás seguro de que deseas eliminar el artefacto "%s"?
|
||||
more_items = Mas cosas
|
||||
copy_generic = Copiar al portapapeles
|
||||
filter.not_fork = No forks
|
||||
filter.is_fork = Forks
|
||||
filter.not_fork = No hay bifurcaciones
|
||||
filter.is_fork = Bifurcaciones
|
||||
test = Test
|
||||
error413 = Has agotado tu cuota.
|
||||
new_repo.title = Nuevo repositorio
|
||||
|
@ -397,8 +397,8 @@ code_search_results=Resultados de búsqueda para «%s»
|
|||
code_last_indexed_at=Indexado por última vez %s
|
||||
relevant_repositories_tooltip=Repositorios que son bifurcaciones o que no tienen ningún tema, ningún icono, y ninguna descripción están ocultos.
|
||||
relevant_repositories=Solo se muestran repositorios relevantes, <a href="%s">mostrar resultados sin filtrar</a>.
|
||||
forks_few = %d forks
|
||||
forks_one = %d fork
|
||||
forks_few = %d bifurcaciones
|
||||
forks_one = %d bifurcación
|
||||
stars_few = %d estrellas
|
||||
stars_one = %d estrella
|
||||
|
||||
|
@ -1070,10 +1070,10 @@ visibility=Visibilidad
|
|||
visibility_description=Sólo el propietario o los miembros de la organización -si tienen derechos- podrán verlo.
|
||||
visibility_helper=Hacer el repositorio privado
|
||||
visibility_helper_forced=El administrador de su sitio obliga a nuevos repositorios a ser privados.
|
||||
visibility_fork_helper=(Cambiar esto afectará a la visibilidad de todos los forks.)
|
||||
visibility_fork_helper=(Cambiar esto afectará a la visibilidad de todas las bifurcaciones.)
|
||||
clone_helper=¿Necesita ayuda para clonar? Visite <a target="_blank" rel="noopener noreferrer" href="%s">Ayuda</a>.
|
||||
fork_repo=Hacer fork del repositorio
|
||||
fork_from=Crear un fork desde
|
||||
fork_repo=Hacer una bifurcación del repositorio
|
||||
fork_from=Crear una bifurcación desde
|
||||
already_forked=Ya ha forkeado %s
|
||||
fork_to_different_account=Forkear a una cuenta diferente
|
||||
fork_visibility_helper=La visibilidad de un repositorio del cual se ha hecho fork no puede ser cambiada.
|
||||
|
@ -3852,7 +3852,7 @@ search = Buscar...
|
|||
type_tooltip = Tipo de búsqueda
|
||||
project_kind = Buscar proyectos...
|
||||
branch_kind = Buscar ramas...
|
||||
commit_kind = Buscar commits...
|
||||
commit_kind = Buscar confirmaciones...
|
||||
repo_kind = Buscar repositorios...
|
||||
user_kind = Buscar usuarios...
|
||||
org_kind = Buscar organizaciones...
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1756,7 +1756,7 @@ issues.close = Sulje ongelma
|
|||
issues.no_content = Ei kuvausta.
|
||||
pulls.reject_count_1 = %d muutospyyntö
|
||||
pulls.update_branch_success = Haarapäivitys onnistui
|
||||
milestones.completeness = <strong>%d%%</strong> valmiina
|
||||
milestones.completeness = <strong>%d% %</strong> valmiina
|
||||
contributors.contribution_type.additions = Lisäykset
|
||||
contributors.contribution_type.deletions = Poistot
|
||||
settings.webhook_deletion_success = Webkoukku on poistettu.
|
||||
|
@ -2088,6 +2088,9 @@ new_from_template_description = Voit valita olemassa olevan repon mallipohjan ja
|
|||
new_advanced = Lisäasetukset
|
||||
new_advanced_expand = Laajenna napsauttamalla
|
||||
template_description = Repojen mallipohjat mahdollistavat uusien repojen luomisen halutulla hakemistorakenteella, tiedostoilla ja valinnaisilla asetuksilla.
|
||||
settings.enter_repo_name = Kirjoita omistajan ja repon nimi täsmälleen kuten esitetty:
|
||||
settings.confirmation_string = Vahvistusteksti
|
||||
settings.delete_notices_2 = - Tämä toiminto poistaa pysyvästi repon <strong>%s</strong> mukaan lukien koodin, ongelmat, kommentit, wikidatan ja avustaja-asetukset.
|
||||
|
||||
|
||||
|
||||
|
@ -2578,6 +2581,12 @@ commit_repo = työnsi haaraan <a href="%[2]s">%[3]s</a> repossa <a href="%[1]s">
|
|||
create_issue = `avasi ongelman <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reopen_issue = `avasi uudelleen ongelman <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
create_pull_request = `loi vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reopen_pull_request = `avasi uudelleen vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
close_pull_request = `sulki vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
comment_issue = `kommentoi ongelmaa <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
close_issue = `sulki ongelman <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
merge_pull_request = `yhdisti vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
comment_pull = `kommentoi vetopyyntöä <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
|
||||
[tool]
|
||||
now=nyt
|
||||
|
@ -2624,6 +2633,7 @@ error.not_signed_commit=Kommitti ei ole allekirjoitettu
|
|||
error.extract_sign = Allekirjoituksen purkaminen epäonnistui
|
||||
default_key = Allekirjoitettu oletusavaimella
|
||||
error.failed_retrieval_gpg_keys = Ei saatu yhtäkään kommitin tekijän tiliin liitettyä avainta
|
||||
error.generate_hash = Tiivisteen luominen kommitista epäonnistui
|
||||
|
||||
[units]
|
||||
unit = Yksikkö
|
||||
|
@ -2765,6 +2775,11 @@ alpine.registry.info = Valitse $branch ja $repository alla olevasta listasta.
|
|||
container.images.title = Levykuvat
|
||||
owner.settings.cargo.initialize = Alusta indeksi
|
||||
owner.settings.cargo.initialize.description = Erityinen Git-repoindeksi vaaditaan Cargo-rekisterin käyttämiseksi. Tämän valinnan käyttäminen luo (tarvittaessa uudelleen) repon ja määrittää sen asetukset automaattisesti.
|
||||
settings.link.error = Repositorion linkin päivittäminen epäonnistui.
|
||||
alt.repository.multiple_groups = Tämä paketti on saatavilla useissa ryhmissä.
|
||||
alt.repository.architectures = Arkkitehtuurit
|
||||
alt.install = Asenna paketti
|
||||
alt.registry.install = Asenna paketti suorittamalla komento:
|
||||
|
||||
[secrets]
|
||||
creation.failed = Salaisuuden lisääminen epäonnistui.
|
||||
|
|
|
@ -640,6 +640,8 @@ 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.
|
||||
email_domain_is_not_allowed = Sumasalungat ang domain ng email address ng user <b>%s</b> sa EMAIL_DOMAIN_ALLOWLIST o EMAIL_DOMAIN_BLOCKLIST. Siguraduhing natakda mo ang email address nang tama.
|
||||
|
||||
[user]
|
||||
joined_on = Sumali noong %s
|
||||
|
@ -784,7 +786,7 @@ old_password = Kasalukuyang password
|
|||
new_password = Bagong password
|
||||
retype_new_password = Kumpirmahin ang bagong password
|
||||
password_incorrect = Mali ang kasalukuyang password.
|
||||
change_password_success = Na-update na ang iyong password. Mag-sign in gamit ng bagong password simula ngayon.
|
||||
change_password_success = Na-update na ang iyong password. Simula ngayon, gamitin ang iyong bagong password para mag-sign in.
|
||||
password_change_disabled = Hindi mababago ng mga di-lokal na gumagamit ang kanilang password sa pamamagitan ng Forgejo web interface.
|
||||
emails = Mga email address
|
||||
manage_emails = Ipamahala ang mga email address
|
||||
|
@ -999,6 +1001,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! <a href="%s">Matuto pa</a>.
|
||||
pronouns_custom_label = Mga pasadyang pronoun
|
||||
user_block_yourself = Hindi mo maaring 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.
|
||||
|
||||
[repo]
|
||||
template_description = Ang mga template na repositoryo ay pinapayagan ang mga gumagamit na mag-generate ng mga bagong repositoryo na may magkatulad na istraktura ng direktoryo, mga file, at opsyonal na mga setting.
|
||||
|
@ -2911,7 +2915,7 @@ dashboard.delete_old_system_notices = Burahin ang lahat ng mga lumang paunawa ng
|
|||
dashboard.gc_lfs = I-garbage collect ang mga LFS meta object
|
||||
dashboard.stop_zombie_tasks = Itigil ang mga zombie action task
|
||||
users.user_manage_panel = Ipamahala ang mga user account
|
||||
users.new_account = Gumawa ng User Account
|
||||
users.new_account = Gumawa ng user account
|
||||
users.auth_login_name = Pangalan ng sign-in authentication
|
||||
users.password_helper = Iwanang walang laman ang password upang panatilihing hindi nabago.
|
||||
users.max_repo_creation = Pinakamataas na numero ng mga repositoryo
|
||||
|
@ -3394,6 +3398,8 @@ teams.owners_permission_desc = Ang mga owner ay may punong access sa <strong>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 <strong>idadagdag ang lahat ng mga umiiral</strong> na repositoryo sa koponan.
|
||||
settings.change_orgname_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.
|
||||
settings.change_orgname_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.
|
||||
|
||||
|
||||
[packages]
|
||||
|
@ -3571,7 +3577,7 @@ alt.registry = I-setup ang registry na ito mula sa command line:
|
|||
alt.registry.install = Para i-install ang package na ito, patakbuhin ang sumusunod na command:
|
||||
alt.install = I-install ang package
|
||||
alt.setup = Idagdag ang repositoryo sa listahan ng mga nakakonektang repositoryo (piliin ang kinakailangang architechture sa halip ng '_arch_'):
|
||||
alt.repository = Info ng Repositoryo
|
||||
alt.repository = Info ng repositoryo
|
||||
alt.repository.architectures = Mga architechture
|
||||
alt.repository.multiple_groups = Available ang package na ito sa iba't ibang grupo.
|
||||
|
||||
|
@ -3693,7 +3699,7 @@ approve_pull_request = `inaprubahan ang <a href="%[1]s">%[3]s#%[2]s</a>`
|
|||
review_dismissed_reason = Dahilan:
|
||||
compare_branch = Ikumpara
|
||||
reject_pull_request = `nagmungkahi ng mga pagbabago para sa <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
rename_repo = pinalitan ang pangalan ng repositoryo mula <code>%[1]s</code> sa <a href="%[2]s">%[3]#</a>
|
||||
rename_repo = pinalitan ang pangalan ng repositoryo mula <code>%[1]s</code> sa <a href="%[2]s">%[3]s</a>
|
||||
close_issue = `sinara ang isyu na <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed = `na-dismiss ang pagsusuri mula <b>%[4]s</b> para sa <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
close_pull_request = `sinara ang hiling sa paghila na <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
|
|
|
@ -680,6 +680,7 @@ Biography = Biographie
|
|||
Website = Site web
|
||||
Location = Emplacement
|
||||
To = Nom de la branche
|
||||
email_domain_is_not_allowed = Le domaine <b>%s</b> du courriel utilisateur entre en conflit avec EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Veuillez vous assurer le courriel est renseigné.
|
||||
|
||||
[user]
|
||||
change_avatar=Changer votre avatar…
|
||||
|
|
|
@ -75,7 +75,7 @@ mirrors=Spoguļglabātavas
|
|||
collaborative=Līdzdarbošanās
|
||||
forks=Atzarojumi
|
||||
|
||||
activities=Aktivitāte
|
||||
activities=Darbības
|
||||
pull_requests=Izmaiņu pieprasījumi
|
||||
issues=Pieteikumi
|
||||
milestones=Atskaites punkti
|
||||
|
@ -678,6 +678,8 @@ Biography = Dzīves un darbības apraksts
|
|||
Website = Tīmekļvietne
|
||||
AccessToken = Piekļuves pilnvara
|
||||
To = Zara nosaukums
|
||||
username_claiming_cooldown = Šo lietotājvārdu vēl nevar izmantot, jo tā noilgums vēl nav beidzies. To varēs izmantot %[1]s.
|
||||
email_domain_is_not_allowed = Lietotāja e-pasta adreses <b>%s</b> domēna vārds ir pretrunāt ar EMAIL_DOMAIN_ALLOWLIST vai EMAIL_DOMAIN_BLOCKLIST. Jāpārliecinās, ka e-pasta adrese ir norādīta pareizi.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -695,7 +697,7 @@ following_few=%d seko
|
|||
follow=Sekot
|
||||
unfollow=Nesekot
|
||||
user_bio=Biogrāfija
|
||||
disabled_public_activity=Šis lietotājs ir atslēdzies iespēju aplūkot tā aktivitāti.
|
||||
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību visiem.
|
||||
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
|
||||
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
|
||||
show_on_map=Rādīt šo vietu kartē
|
||||
|
@ -803,7 +805,7 @@ old_password=Pašreizējā parole
|
|||
new_password=Jaunā parole
|
||||
retype_new_password=Apstiprināt jauno paroli
|
||||
password_incorrect=Ievadīta nepareiza pašreizējā parole.
|
||||
change_password_success=Parole tika sekmīgi nomainīta. Turpmāk jāpiesakās ar savu jauno paroli.
|
||||
change_password_success=Parole tika atjaunināta. Turpmāk jāizmanto sava jaunā parole, lai pieteiktos.
|
||||
password_change_disabled=Ārējie lietotāji nevar mainīt savu paroli Forgejo tīmekļa saskarnē.
|
||||
|
||||
emails=E-pasta adreses
|
||||
|
@ -904,7 +906,7 @@ added_on=Pievienots %s
|
|||
valid_until_date=Derīgs līdz %s
|
||||
valid_forever=Derīgs mūžīgi
|
||||
last_used=Pēdējo reizi izmantota
|
||||
no_activity=Nav nesenas aktivitātes
|
||||
no_activity=Nav nesenu darbību
|
||||
can_read_info=Lasīt
|
||||
can_write_info=Rakstīt
|
||||
key_state_desc=Šī atslēga ir izmantota pēdējo 7 dienu laikā
|
||||
|
@ -1055,6 +1057,8 @@ additional_repo_units_hint_description = Attēlot norādi "Iespējot vēl" glab
|
|||
language.description = Šī valoda tiks saglabāta kontā un pēc pieteikšanās tiks izmantota kā noklusējuma.
|
||||
user_block_yourself = Nevar liegt sevi.
|
||||
pronouns_custom_label = Pielāgoti vietniekvārdi
|
||||
change_username_redirect_prompt.with_cooldown.one = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d diena. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
change_username_redirect_prompt.with_cooldown.few = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d dienas. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Glabātava satur visas projekta datnes, tajā skaitā izmaiņu vēsturi. Jau tiek izmantota kaut kur citur? <a href="%s">Pārcelt glabātavu</a>.
|
||||
|
@ -1652,7 +1656,7 @@ issues.save=Saglabāt
|
|||
issues.label_title=Nosaukums
|
||||
issues.label_description=Apraksts
|
||||
issues.label_color=Krāsa
|
||||
issues.label_exclusive=Ekskluzīvs
|
||||
issues.label_exclusive=Sevišķa
|
||||
issues.label_archive=Arhivēt iezīmi
|
||||
issues.label_archived_filter=Rādīt arhivētās iezīmes
|
||||
issues.label_archive_tooltip=Arhivētās iezīmes pēc noklusējuma netiek iekļautas ieteikumos, kad meklē pēc iezīmes.
|
||||
|
@ -2033,7 +2037,7 @@ wiki.last_updated=Pēdējo reizi labota %s
|
|||
wiki.page_name_desc=Jāievada šīs vikivietnes lapas nosaukums. Daži īpašie nosaukumi ir: "Home", "_Sidebar" un "_Footer".
|
||||
wiki.original_git_entry_tooltip=Rādīt sākotnējo Git datni, nevis izmantot draudzīgo saiti.
|
||||
|
||||
activity=Aktivitāte
|
||||
activity=Notikumi
|
||||
activity.period.filter_label=Laika periods:
|
||||
activity.period.daily=1 diena
|
||||
activity.period.halfweekly=3 dienas
|
||||
|
@ -2999,6 +3003,8 @@ teams.invite.by=Uzaicināja %s
|
|||
teams.invite.description=Lūgums nospiest zemāk esošo pogu, lai pievienotos komandai.
|
||||
open_dashboard = Atvērt pārskata paneli
|
||||
follow_blocked_user = Tu nevari sekot šai apvienībai, jo tā ir liegusi Tevi.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d diena. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d dienas. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
|
||||
[admin]
|
||||
dashboard=Pārskata panelis
|
||||
|
@ -3761,7 +3767,7 @@ settings.link.select=Atlasīt glabātavu
|
|||
settings.link.button=Atjaunināt glabātavas saiti
|
||||
settings.link.success=Glabātavas saite tika sekmīgi atjaunināta.
|
||||
settings.link.error=Neizdevās atjaunināt glabātavas saiti.
|
||||
settings.delete=Dzēst pakotni
|
||||
settings.delete=Izdzēst pakotni
|
||||
settings.delete.description=Pakotne tiks neatgriezeniski izdzēsta.
|
||||
settings.delete.notice=Tiks izdzēsta pakotne %s (%s). Šī darbība ir neatgriezeniska. Tiešām turpināt?
|
||||
settings.delete.success=Pakotne tika izdzēsta.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[common]
|
||||
enable_javascript = Denne nettsiden behøver JavaScript.
|
||||
enable_javascript = Denne nettsiden krever JavaScript.
|
||||
toc = Innholdsfortegnelse
|
||||
licenses = Lisenser
|
||||
return_to_forgejo = Tilbake til Forgejo
|
||||
|
@ -126,6 +126,13 @@ webauthn_sign_in = Trykk på knappen på sikkerhetsnøkkelen din. Dersom nøkkel
|
|||
copy_path = Kopier sti
|
||||
webauthn_error_unable_to_process = Tjeneren kunne ikke behandle forespørselen din.
|
||||
webauthn_error_empty = Du må gi nøkkelen et navn.
|
||||
toggle_menu = Åpne/lukke meny
|
||||
twofa_scratch = To-faktor skrapekode
|
||||
webauthn_press_button = Vennligst trykk på knappen på sikkerhetsnøkkelen…
|
||||
webauthn_error_duplicated = Sikkerhetsnøkkelen er ikke tillatt for denne forespørselen. Vennligst sørg for at nøkkelen ikke allerede er registrert.
|
||||
webauthn_error_timeout = Et tidsavbrudd oppsto før nøkkelen din kunne leses. Vennligst last inn siden på nytt og prøv igjen.
|
||||
new_fork = Ny fork av repository
|
||||
collaborative = Samarbeidende
|
||||
|
||||
[search]
|
||||
search = Søk...
|
||||
|
|
|
@ -681,6 +681,8 @@ To = Branch naam
|
|||
Website = Website
|
||||
AccessToken = Toegangstoken
|
||||
Pronouns = Voornaamwoorden
|
||||
username_claiming_cooldown = De gebruikersnaam kan niet opgeëist worden, omdat de afkoelperiode nog niet voorbij is. Hij kan worden opgeëist op %[1]s.
|
||||
email_domain_is_not_allowed = Het domein van het e-mailadres van de gebruiker <b>%s</b> is in strijd met EMAIL_DOMAIN_ALLOWLIST of EMAIL_DOMAIN_BLOCKLIST. Controleer of u het e-mailadres correct hebt ingesteld.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -1058,6 +1060,8 @@ language.description = Deze taal wordt opgeslagen in uw account en wordt als sta
|
|||
language.localization_project = Help ons Forgejo in uw taal te vertalen! <a href="%s">Leer meer</a>.
|
||||
user_block_yourself = U kunt niet zichzelf blokkeren.
|
||||
pronouns_custom_label = Aangepaste voornaamwoorden
|
||||
change_username_redirect_prompt.with_cooldown.few = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dagen. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
change_username_redirect_prompt.with_cooldown.one = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dag. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
|
||||
[repo]
|
||||
owner=Eigenaar
|
||||
|
@ -2863,6 +2867,7 @@ summary_card_alt = Overzichtskaart van repository %s
|
|||
release.summary_card_alt = Samenvattende kaart van een release met de titel "%s" in repository %s
|
||||
issues.reaction.alt_remove = Verwijder %[1]s reactie van bericht.
|
||||
issues.reaction.alt_many = %[1]s en %[2]d meer gereageerd %[3]s.
|
||||
editor.commit_email = Commit e-mail
|
||||
|
||||
|
||||
|
||||
|
@ -3001,6 +3006,8 @@ settings.visibility.limited = Beperkt (alleen zichtbaar voor ingelogde gebruiker
|
|||
teams.add_nonexistent_repo = De repository die u probeert toe te voegen bestaat niet, maak deze eerst aan alstublieft.
|
||||
teams.all_repositories_write_permission_desc = Dit team verleent <strong>Schrijf</strong> permissies tot <strong>alle repositories</strong>: leden kunnen lezen en pushen naar repositories.
|
||||
open_dashboard = Open dashboard
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dag. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dagen. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
|
||||
[admin]
|
||||
dashboard=Overzicht
|
||||
|
@ -3083,7 +3090,7 @@ dashboard.gc_times=GC verwerkingen
|
|||
dashboard.delete_old_system_notices=Verwijder alle oude systeemmededelingen uit de database
|
||||
|
||||
users.user_manage_panel=Gebruikersaccounts beheren
|
||||
users.new_account=Nieuw account aanmaken
|
||||
users.new_account=Gebruikersaccount aanmaken
|
||||
users.name=Gebruikersnaam
|
||||
users.full_name=Volledige naam
|
||||
users.activated=Geactiveerd
|
||||
|
|
|
@ -680,6 +680,8 @@ required_prefix = A entrada deve começar com "%s"
|
|||
FullName = Nome completo
|
||||
Description = Descrição
|
||||
unset_password = O usuário de login não definiu a senha.
|
||||
username_claiming_cooldown = Este nome de usuário não pode ser registrado porque o período de espera ainda não acabou. Ele poderá ser registrado em %[1]s.
|
||||
email_domain_is_not_allowed = O domínio do endereço de email da conta <b>%s</b> está em conflito com EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Certifique-se de que você colocou o endereço de email correto.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -805,7 +807,7 @@ old_password=Senha atual
|
|||
new_password=Nova senha
|
||||
retype_new_password=Confirme a nova senha
|
||||
password_incorrect=A senha atual está incorreta.
|
||||
change_password_success=Sua senha foi atualizada. Acesse usando sua nova senha de agora em diante.
|
||||
change_password_success=Sua senha foi atualizada. A partir de agora, use sua nova senha para acessar sua conta.
|
||||
password_change_disabled=Contas não-locais não podem alterar sua senha através da interface web do Forgejo.
|
||||
|
||||
emails=Endereços de e-mail
|
||||
|
@ -1057,6 +1059,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.
|
||||
|
||||
[repo]
|
||||
owner=Proprietário
|
||||
|
@ -2619,7 +2623,7 @@ tag.create_tag_from=`Criar nova tag a partir de "%s"`
|
|||
|
||||
tag.create_success=Tag "%s" criada.
|
||||
|
||||
topic.manage_topics=Gerenciar Tópicos
|
||||
topic.manage_topics=Gerenciar tópicos
|
||||
topic.done=Feito
|
||||
topic.count_prompt=Você não pode selecionar mais de 25 tópicos
|
||||
|
||||
|
@ -3000,6 +3004,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 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.
|
||||
settings.change_orgname_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.
|
||||
|
||||
[admin]
|
||||
dashboard=Painel
|
||||
|
@ -3820,6 +3826,13 @@ owner.settings.cargo.initialize.description = É necessário um repositório Git
|
|||
owner.settings.chef.keypair.description = É necessário um par de chaves para autenticar no registro Chef. Se você já gerou um par de chaves, gere um novo par e descarte o antigo.
|
||||
container.images.title = Imagens
|
||||
search_in_external_registry = Buscar em %s
|
||||
alt.registry.install = Para instalar o pacote, execute o seguinte comando:
|
||||
alt.registry = Configurar este registro da linha de comando:
|
||||
alt.install = Instalar pacote
|
||||
alt.repository = Informação do repositório
|
||||
alt.repository.architectures = Arquiteturas
|
||||
alt.repository.multiple_groups = Este pacote está disponível em múltiplos grupos.
|
||||
alt.setup = Adicionar um repositório à lista de repositórios conectados (escolha a arquitetura necessária em vez de '_arch_'):
|
||||
|
||||
[secrets]
|
||||
secrets=Segredos
|
||||
|
|
|
@ -681,6 +681,8 @@ AccessToken = Código de acesso
|
|||
FullName = Nome completo
|
||||
Description = Descrição
|
||||
Pronouns = Pronomes
|
||||
username_claiming_cooldown = O nome de utilizador não pode ser reivindicado, porque o período de espera do mesmo ainda não terminou. Pode ser reivindicado em %[1]s.
|
||||
email_domain_is_not_allowed = O domínio do endereço de email <b>%s</b> do utilizador entra em conflito com EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Certifique-se de que definiu corretamente o endereço de email.
|
||||
|
||||
[user]
|
||||
change_avatar=Mude o seu avatar…
|
||||
|
@ -805,7 +807,7 @@ old_password=Senha corrente
|
|||
new_password=Nova senha
|
||||
retype_new_password=Confirme a nova senha
|
||||
password_incorrect=A senha corrente está errada.
|
||||
change_password_success=A sua senha foi substituída. Inicie a sessão com a nova senha a partir de agora.
|
||||
change_password_success=A sua senha foi atualizada. A partir de agora, utilize a sua nova senha para iniciar sessão.
|
||||
password_change_disabled=Os utilizadores não-locais não podem alterar a sua senha através da interface web do Forgejo.
|
||||
|
||||
emails=Endereços de email
|
||||
|
@ -1057,6 +1059,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! <a href="%s">Saiba mais</a>.
|
||||
pronouns_custom_label = Pronomes personalizados
|
||||
user_block_yourself = Não se pode bloquear a si próprio.
|
||||
change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
|
||||
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.
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Um repositório contém todos os ficheiros do trabalho, incluindo o histórico das revisões. Já tem um hospedado noutro sítio? <a href="%s">Migre o repositório</a>.
|
||||
|
@ -3001,6 +3005,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 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.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de utilizador antigo estará 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.
|
||||
|
||||
[admin]
|
||||
dashboard=Painel de controlo
|
||||
|
@ -3821,6 +3827,13 @@ arch.version.backup = Cópia de segurança
|
|||
arch.version.replaces = Substitui
|
||||
container.images.title = Imagens
|
||||
search_in_external_registry = Procurar em %s
|
||||
alt.registry = Configure este registo a partir da linha de comandos:
|
||||
alt.registry.install = Para instalar o pacote, execute o seguinte comando:
|
||||
alt.install = Instalar pacote
|
||||
alt.repository = Informação do repositório
|
||||
alt.repository.architectures = Arquiteturas
|
||||
alt.repository.multiple_groups = Este pacote está disponível em vários grupos.
|
||||
alt.setup = Adicionar um repositório à lista de repositórios ligados (escolha a arquitetura necessária em vez de '_arch_'):
|
||||
|
||||
[secrets]
|
||||
secrets=Segredos
|
||||
|
|
|
@ -680,6 +680,8 @@ Biography = О себе
|
|||
Website = Веб-сайт
|
||||
Location = Местоположение
|
||||
To = Название ветви
|
||||
email_domain_is_not_allowed = Домен адреса эл. почты <b>%s</b> не разрешён к использованию. Убедитесь, что он введён правильно или попробуйте другой адрес.
|
||||
username_claiming_cooldown = Это имя пока не может быть занято, т.к. срок его защиты ещё не вышел. Его получится занять после %[1]s.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -761,7 +763,7 @@ update_language_success=Язык обновлён.
|
|||
update_profile_success=Ваш профиль успешно обновлён.
|
||||
change_username=Ваше имя пользователя было изменено.
|
||||
change_username_prompt=Обратите внимание: изменение имени пользователя также меняет URL вашей учётной записи.
|
||||
change_username_redirect_prompt=Старое имя пользователя будет перенаправлять на новое до тех пор, пока его не займут.
|
||||
change_username_redirect_prompt=Старое имя будет перенаправлять на новое до тех пор, пока оно не будет занято.
|
||||
continue=Далее
|
||||
cancel=Отмена
|
||||
language=Язык
|
||||
|
@ -1057,6 +1059,8 @@ language.description = Выбранный язык будет сохранён
|
|||
language.localization_project = Помогите с переводом Forgejo на свой язык! <a href="%s">Подробнее</a>.
|
||||
user_block_yourself = Нельзя заблокировать себя.
|
||||
pronouns_custom_label = Другие местоимения
|
||||
change_username_redirect_prompt.with_cooldown.one = Прежнее имя будет доступно для использования другим пользователям после истечения защиты в %[1]d день. Вы сможете вернуть его себе во время срока защиты.
|
||||
change_username_redirect_prompt.with_cooldown.few = Прежнее имя будет доступно для использования другим пользователям после истечения защиты в %[1]d дней. Вы сможете вернуть его себе во время срока защиты.
|
||||
|
||||
[repo]
|
||||
owner=Владелец
|
||||
|
@ -2650,7 +2654,7 @@ tag.create_tag_from=Создать новый тег из «%s»
|
|||
|
||||
tag.create_success=Тег «%s» создан.
|
||||
|
||||
topic.manage_topics=Редактировать тематические метки
|
||||
topic.manage_topics=Изменить темы
|
||||
topic.done=Сохранить
|
||||
topic.count_prompt=Нельзя выбрать более 25 тем
|
||||
topic.format_prompt=Темы должны начинаться с буквы или цифры и могут содержать дефисы («-») и точки («.»). Длина темы не должна превышать 35 символов. Все буквы должны быть строчными.
|
||||
|
@ -3003,6 +3007,8 @@ teams.invite.description=Нажмите на кнопку ниже, чтобы
|
|||
follow_blocked_user = Вы не можете подписаться на эту организацию, т.к. вы в ней заблокированы.
|
||||
teams.general_access = Настраиваемый доступ
|
||||
open_dashboard = Открыть панель
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Прежнее название будет доступно для использования другим пользователям после истечения защиты в %[1]d дней. Вы сможете вернуть его во время срока защиты.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Прежнее название будет доступно для использования другим пользователям после истечения защиты в %[1]d день. Вы сможете вернуть его во время срока защиты.
|
||||
|
||||
[admin]
|
||||
dashboard=Панель управления
|
||||
|
@ -3708,7 +3714,7 @@ composer.install=Чтобы установить пакет с помощью Co
|
|||
composer.dependencies=Зависимости
|
||||
composer.dependencies.development=Зависимости для разработки
|
||||
conan.details.repository=Репозиторий
|
||||
conan.registry=Настроить реестр из командной строки:
|
||||
conan.registry=Добавьте реестр командой:
|
||||
conan.install=Чтобы установить пакет с помощью Conan, выполните следующую команду:
|
||||
conda.registry=Пропишите этот реестр в качестве репозитория Conda в своём файле <code>.condarc</code>:
|
||||
conda.install=Чтобы установить пакет с помощью Conda, выполните следующую команду:
|
||||
|
@ -3723,7 +3729,7 @@ container.labels.key=Ключ
|
|||
container.labels.value=Значение
|
||||
cran.registry=Настройте этот реестр в файле <code>Rprofile.site</code>:
|
||||
cran.install=Чтобы установить пакет, выполните следующую команду:
|
||||
debian.registry=Настроить реестр из командной строки:
|
||||
debian.registry=Добавьте реестр командой:
|
||||
debian.registry.info=Выберите $distribution и $component из списка ниже.
|
||||
debian.install=Чтобы установить пакет, выполните следующую команду:
|
||||
debian.repository=О репозитории
|
||||
|
@ -3732,13 +3738,13 @@ debian.repository.components=Компоненты
|
|||
debian.repository.architectures=Архитектуры
|
||||
generic.download=Скачать пакет из командной строки:
|
||||
go.install=Установите пакет из командной строки:
|
||||
helm.registry=Настроить реестр из командной строки:
|
||||
helm.registry=Добавьте реестр командой:
|
||||
helm.install=Чтобы установить пакет, выполните следующую команду:
|
||||
maven.registry=Настройте реестр в файле <code>pom.xml</code> вашего проекта:
|
||||
maven.install=Чтобы использовать пакет, включите в блок <code>dependencies</code> в файле <code>pom.xml</code> следующее:
|
||||
maven.install2=Выполнить через командную строку:
|
||||
maven.download=Чтобы скачать зависимость, запустите в командной строке:
|
||||
nuget.registry=Настроить реестр из командной строки:
|
||||
nuget.registry=Добавьте реестр командой:
|
||||
nuget.install=Чтобы установить пакет с помощью NuGet, выполните следующую команду:
|
||||
nuget.dependency.framework=Целевой фреймворк
|
||||
npm.registry=Настройте реестр в файле <code>.npmrc</code> вашего проекта:
|
||||
|
@ -3752,7 +3758,7 @@ npm.details.tag=Тег
|
|||
pub.install=Чтобы установить пакет с помощью Dart, выполните следующую команду:
|
||||
pypi.requires=Требуется Python
|
||||
pypi.install=Чтобы установить пакет с помощью pip, выполните следующую команду:
|
||||
rpm.registry=Настроить реестр из командной строки:
|
||||
rpm.registry=Добавьте реестр командой:
|
||||
rpm.distros.redhat=на дистрибутивах семейства RedHat
|
||||
rpm.distros.suse=на дистрибутивах семейства SUSE
|
||||
rpm.install=Чтобы установить пакет, выполните следующую команду:
|
||||
|
@ -3764,7 +3770,7 @@ rubygems.dependencies.runtime=Зависимости времени выполн
|
|||
rubygems.dependencies.development=Зависимости для разработки
|
||||
rubygems.required.ruby=Требуется версия Ruby
|
||||
rubygems.required.rubygems=Требуется версия RubyGem
|
||||
swift.registry=Настроить реестр из командной строки:
|
||||
swift.registry=Добавьте реестр командой:
|
||||
swift.install=Добавьте пакет в свой файл <code>Package.swift</code>:
|
||||
swift.install2=и запустите следующую команду:
|
||||
vagrant.install=Чтобы добавить бокс Vagrant, выполните следующую команду:
|
||||
|
@ -3834,6 +3840,9 @@ container.images.title = Образы
|
|||
search_in_external_registry = Найти в %s
|
||||
alt.repository = О репозитории
|
||||
alt.repository.architectures = Архитектуры
|
||||
alt.registry = Добавьте реестр командой:
|
||||
alt.repository.multiple_groups = Этот пакет доступен в нескольких группах.
|
||||
alt.setup = Добавьте репозиторий в свой список репозиториев (выберите подходящую архитектуру вместо «_arch_»):
|
||||
|
||||
[secrets]
|
||||
secrets=Секреты
|
||||
|
|
|
@ -666,6 +666,8 @@ invalid_group_team_map_error = ` призначення недійсне: %s`
|
|||
unsupported_login_type = Цей тип входу не підтримує видалення облікового запису.
|
||||
admin_cannot_delete_self = Ви не можете видалити себе, якщо ви є адміністратором. Спочатку зніміть із себе права адміністратора.
|
||||
unset_password = Для користувача не встановлено пароль.
|
||||
username_claiming_cooldown = Це ім'я користувача не можна присвоїти, оскільки його період захисту ще не закінчився. Ім'я можна буде присвоїти %[1]s.
|
||||
email_domain_is_not_allowed = Домен адреси електронної пошти <b>%s</b> конфліктує з EMAIL_DOMAIN_ALLOWLIST або EMAIL_DOMAIN_BLOCKLIST. Перевірте, чи ви правильно вказали адресу електронної пошти.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -761,7 +763,7 @@ update_password=Оновити пароль
|
|||
old_password=Поточний пароль
|
||||
new_password=Новий пароль
|
||||
password_incorrect=Поточний пароль неправильний.
|
||||
change_password_success=Ваш пароль був оновлений. Тепер увійдіть в систему, використовуючи новий пароль.
|
||||
change_password_success=Ваш пароль оновлено. Відтепер входьте в систему, використовуючи новий пароль.
|
||||
password_change_disabled=Нелокальні акаунти не можуть змінити пароль через Forgejo.
|
||||
|
||||
emails=Адреса електронної пошти
|
||||
|
@ -1006,6 +1008,9 @@ key_signature_ssh_placeholder = Починається з «-----BEGIN SSH SIGNA
|
|||
user_block_yourself = Ви не можете заблокувати себе.
|
||||
pronouns_custom_label = Інші займенники
|
||||
repo_and_org_access = Доступ до репозиторію та організації
|
||||
change_username_redirect_prompt.with_cooldown.few = Старе ім'я користувача буде доступне всім після періоду захисту, який триватиме %[1]d днів. Протягом періоду захисту ви ще можете повернути собі старе ім'я.
|
||||
change_username_redirect_prompt.with_cooldown.one = Старе ім'я користувача буде доступне всім після періоду захисту, який триватиме %[1]d день. Протягом періоду захисту ви ще можете повернути собі старе ім'я.
|
||||
change_username_redirect_prompt = Старе ім'я користувача буде перенаправленням, поки хтось не присвоїть ім'я собі.
|
||||
|
||||
[repo]
|
||||
owner=Власник
|
||||
|
@ -2595,6 +2600,8 @@ follow_blocked_user = Ви не можете стежити за цією орг
|
|||
teams.invite.description = Щоб приєднатися до команди, натисніть кнопку нижче.
|
||||
teams.invite.title = Вас запрошено приєднатися до команди <strong>%s</strong> в організації <strong>%s</strong>.
|
||||
form.name_reserved = Назву організації «%s» зарезервовано.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Стара назва буде доступна всім після періоду захисту, який триватиме %[1]d день. Протягом періоду захисту ви ще можете повернути стару назву.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Стара назва буде доступна всім після періоду захисту, який триватиме %[1]d днів. Протягом періоду захисту ви ще можете повернути стару назву.
|
||||
|
||||
[admin]
|
||||
dashboard=Панель управління
|
||||
|
|
|
@ -680,6 +680,8 @@ AccessToken = 访问令牌
|
|||
Description = 描述
|
||||
Pronouns = 代称
|
||||
Biography = 简历
|
||||
username_claiming_cooldown = 用户名不能被认领,因为其仍处于冷却期间。其可以在%[1]s后被认领。
|
||||
email_domain_is_not_allowed = 用户电子邮箱的域名<b>%s</b>与EMAIL_DOMAIN_ALLOWLIST或EMAIL_DOMAIN_BLOCKLIST冲突。请确保您正确设置了电子邮件地址。
|
||||
|
||||
[user]
|
||||
change_avatar=修改头像…
|
||||
|
@ -804,7 +806,7 @@ old_password=当前密码
|
|||
new_password=新的密码
|
||||
retype_new_password=确认新密码
|
||||
password_incorrect=当前密码不正确。
|
||||
change_password_success=您的密码已更新。从现在开始使用您的新密码登录。
|
||||
change_password_success=您的密码已更新。从现在开始请使用您的新密码登录。
|
||||
password_change_disabled=非本地帐户不能通过 Forgejo 的 web 界面更改密码。
|
||||
|
||||
emails=邮箱地址
|
||||
|
@ -1056,6 +1058,8 @@ language.description = 此语言将保存到您的账号中,并在您登录后
|
|||
language.localization_project = 帮助我们将 Forgejo 翻译成您的语言!<a href="%s">了解更多</a>。
|
||||
user_block_yourself = 您不能屏蔽自己。
|
||||
pronouns_custom_label = 自定义代词
|
||||
change_username_redirect_prompt.with_cooldown.one = 旧的用户名将在%[1]d天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
change_username_redirect_prompt.with_cooldown.few = 旧的用户名将在%[1]d天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
|
||||
[repo]
|
||||
new_repo_helper=代码仓库包含了所有的项目文件,包括版本历史记录。已经在其他地方托管了?<a href="%s">迁移仓库</a>。
|
||||
|
@ -2866,6 +2870,7 @@ issues.context.menu = 评论菜单
|
|||
issues.reaction.alt_add = 对评论添加 %[1]s 回应。
|
||||
release.summary_card_alt = 仓库 %[2]s 中标题为 %[1]s 的版本发布的摘要卡片
|
||||
summary_card_alt = 仓库 %s 的摘要卡片
|
||||
editor.commit_email = 提交电子邮件
|
||||
|
||||
[graphs]
|
||||
component_loading=正在加载 %s…
|
||||
|
@ -3001,6 +3006,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天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
|
||||
[admin]
|
||||
dashboard=管理面板
|
||||
|
|
854
package-lock.json
generated
854
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -61,7 +61,7 @@
|
|||
"devDependencies": {
|
||||
"@axe-core/playwright": "4.10.1",
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "4.4.1",
|
||||
"@playwright/test": "1.49.1",
|
||||
"@playwright/test": "1.50.1",
|
||||
"@stoplight/spectral-cli": "6.14.2",
|
||||
"@stylistic/eslint-plugin-js": "2.12.1",
|
||||
"@stylistic/stylelint-plugin": "3.1.1",
|
||||
|
@ -85,9 +85,9 @@
|
|||
"eslint-plugin-vue-scoped-css": "2.9.0",
|
||||
"eslint-plugin-wc": "2.2.0",
|
||||
"globals": "15.14.0",
|
||||
"happy-dom": "16.3.0",
|
||||
"happy-dom": "16.8.1",
|
||||
"license-checker-rseidelsohn": "4.4.2",
|
||||
"markdownlint-cli": "0.43.0",
|
||||
"markdownlint-cli": "0.44.0",
|
||||
"postcss-html": "1.8.0",
|
||||
"stylelint": "16.12.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"description": "Group nodejs packages",
|
||||
"matchPackageNames": [
|
||||
"code.forgejo.org/oci/node",
|
||||
"data.forgejo.org/oci/node",
|
||||
"docker.io/library/node",
|
||||
"docker.io/node",
|
||||
"node"
|
||||
|
|
|
@ -112,7 +112,7 @@ Here are some links to the most important topics. You can find the full list of
|
|||
<h2 id="user-content-quick-links">Quick Links</h2>
|
||||
<p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>
|
||||
<p><a href="` + FullURL + `wiki/Configuration" rel="nofollow">Configuration</a>
|
||||
<a href="` + FullURL + `wiki/raw/images/icon-bug.png" rel="nofollow"><img src="` + FullURL + `wiki/raw/images/icon-bug.png" title="icon-bug.png" alt="images/icon-bug.png"/></a></p>
|
||||
<a href="` + FullURL + `wiki/raw/images/icon-bug.png" rel="nofollow"><img src="` + FullURL + `wiki/raw/images/icon-bug.png" title="icon-bug.png" alt=""/></a></p>
|
||||
`,
|
||||
}
|
||||
|
||||
|
|
|
@ -303,11 +303,7 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.ParamsInt64(":id")); err != nil {
|
||||
if asymkey_model.IsErrGPGKeyAccessDenied(err) {
|
||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err)
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -317,8 +313,6 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
|||
// HandleAddGPGKeyError handle add GPGKey error
|
||||
func HandleAddGPGKeyError(ctx *context.APIContext, err error, token string) {
|
||||
switch {
|
||||
case asymkey_model.IsErrGPGKeyAccessDenied(err):
|
||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyAccessDenied", "You do not have access to this GPG key")
|
||||
case asymkey_model.IsErrGPGKeyIDAlreadyUsed(err):
|
||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyIDAlreadyUsed", "A key with the same id already exists")
|
||||
case asymkey_model.IsErrGPGKeyParsing(err):
|
||||
|
|
|
@ -83,6 +83,7 @@ func Users(ctx *context.Context) {
|
|||
IsTwoFactorEnabled: util.OptionalBoolParse(statusFilterMap["is_2fa_enabled"]),
|
||||
IsProhibitLogin: util.OptionalBoolParse(statusFilterMap["is_prohibit_login"]),
|
||||
IncludeReserved: true, // administrator needs to list all accounts include reserved, bot, remote ones
|
||||
Load2FAStatus: true,
|
||||
ExtraParamStrings: extraParamStrings,
|
||||
}, tplUsers)
|
||||
}
|
||||
|
|
|
@ -228,15 +228,6 @@ func SignInPost(ctx *context.Context) {
|
|||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
} else if user_model.IsErrUserInactive(err) {
|
||||
if setting.Service.RegisterEmailConfirm {
|
||||
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
|
||||
ctx.HTML(http.StatusOK, TplActivate)
|
||||
} else {
|
||||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
}
|
||||
|
|
|
@ -99,16 +99,6 @@ func handleSignInError(ctx *context.Context, userName string, ptrForm any, tmpl
|
|||
log.Info("Failed authentication attempt for %s from %s: %v", userName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
} else if user_model.IsErrUserInactive(err) {
|
||||
ctx.Data["user_exists"] = true
|
||||
if setting.Service.RegisterEmailConfirm {
|
||||
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
|
||||
ctx.HTML(http.StatusOK, TplActivate)
|
||||
} else {
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", userName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError(invoker, err)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,11 @@ func Organizations(ctx *context.Context) {
|
|||
)
|
||||
sortOrder := ctx.FormString("sort")
|
||||
if sortOrder == "" {
|
||||
sortOrder = "newest"
|
||||
if supportedSortOrders.Contains(setting.UI.ExploreDefaultSort) {
|
||||
sortOrder = setting.UI.ExploreDefaultSort
|
||||
} else {
|
||||
sortOrder = "newest"
|
||||
}
|
||||
ctx.SetFormString("sort", sortOrder)
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,9 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions,
|
|||
ctx.Data["Keyword"] = opts.Keyword
|
||||
ctx.Data["Total"] = count
|
||||
ctx.Data["Users"] = users
|
||||
ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus(ctx)
|
||||
if opts.Load2FAStatus {
|
||||
ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus(ctx)
|
||||
}
|
||||
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
|
||||
|
@ -149,7 +151,11 @@ func Users(ctx *context.Context) {
|
|||
)
|
||||
sortOrder := ctx.FormString("sort")
|
||||
if sortOrder == "" {
|
||||
sortOrder = "newest"
|
||||
if supportedSortOrders.Contains(setting.UI.ExploreDefaultSort) {
|
||||
sortOrder = setting.UI.ExploreDefaultSort
|
||||
} else {
|
||||
sortOrder = "newest"
|
||||
}
|
||||
ctx.SetFormString("sort", sortOrder)
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ func RefBlame(ctx *context.Context) {
|
|||
HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err)
|
||||
return
|
||||
}
|
||||
if entry.IsDir() {
|
||||
ctx.NotFound("Cannot blame directory", nil)
|
||||
return
|
||||
}
|
||||
|
||||
blob := entry.Blob()
|
||||
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
|
|
|
@ -937,6 +937,9 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
|||
// of repository reference
|
||||
func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context) context.CancelFunc {
|
||||
return func(ctx *Context) (cancel context.CancelFunc) {
|
||||
if ctx.Repo.Repository.IsBeingCreated() {
|
||||
return nil // no git repo, so do nothing
|
||||
}
|
||||
// Empty repository does not have reference information.
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
// assume the user is viewing the (non-existent) default branch
|
||||
|
|
|
@ -363,5 +363,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<img class="tw-hidden" src="{{AssetUrlPrefix}}/img/forgejo-loading.svg" width="256" height="256">
|
||||
<img class="tw-hidden" src="{{AssetUrlPrefix}}/img/forgejo-loading.svg" alt="{{ctx.Locale.Tr "loading"}}" width="256" height="256">
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{{if .blobBase}}
|
||||
<span class="side">
|
||||
<p class="side-header">{{ctx.Locale.Tr "repo.diff.file_before"}}</p>
|
||||
<span class="before-container"><img class="image-before"></span>
|
||||
<span class="before-container"><img class="image-before" alt=""></span>
|
||||
<p>
|
||||
<span class="bounds-info-before">
|
||||
{{ctx.Locale.Tr "repo.diff.file_image_width"}}: <span class="text bounds-info-width"></span>
|
||||
|
@ -37,7 +37,7 @@
|
|||
{{if .blobHead}}
|
||||
<span class="side">
|
||||
<p class="side-header">{{ctx.Locale.Tr "repo.diff.file_after"}}</p>
|
||||
<span class="after-container"><img class="image-after"></span>
|
||||
<span class="after-container"><img class="image-after" alt=""></span>
|
||||
<p>
|
||||
<span class="bounds-info-after">
|
||||
{{ctx.Locale.Tr "repo.diff.file_image_width"}}: <span class="text bounds-info-width"></span>
|
||||
|
@ -55,9 +55,9 @@
|
|||
<div class="ui bottom attached tab image-diff-container" data-tab="diff-swipe-{{.file.Index}}">
|
||||
<div class="diff-swipe">
|
||||
<div class="swipe-frame">
|
||||
<span class="before-container"><img class="image-before"></span>
|
||||
<span class="before-container"><img class="image-before" alt="{{ctx.Locale.Tr "repo.diff.file_before"}}"></span>
|
||||
<span class="swipe-container">
|
||||
<span class="after-container"><img class="image-after"></span>
|
||||
<span class="after-container"><img class="image-after" alt="{{ctx.Locale.Tr "repo.diff.file_after"}}"></span>
|
||||
</span>
|
||||
<span class="swipe-bar">
|
||||
<span class="handle top-handle"></span>
|
||||
|
@ -70,8 +70,8 @@
|
|||
<div class="diff-overlay">
|
||||
<input type="range" min="0" max="100" value="50">
|
||||
<div class="overlay-frame">
|
||||
<span class="before-container"><img class="image-before"></span>
|
||||
<span class="after-container"><img class="image-after"></span>
|
||||
<span class="before-container"><img class="image-before" alt="{{ctx.Locale.Tr "repo.diff.file_before"}}"></span>
|
||||
<span class="after-container"><img class="image-after" alt="{{ctx.Locale.Tr "repo.diff.file_after"}}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
<div id="review-box">
|
||||
<button class="ui tiny primary button tw-pr-1 tw-flex js-btn-review {{if not $.IsShowingAllCommits}}disabled{{end}}" {{if not $.IsShowingAllCommits}}data-tooltip-content="{{ctx.Locale.Tr "repo.pulls.review_only_possible_for_full_diff"}}"{{end}}>
|
||||
{{ctx.Locale.Tr "repo.diff.review"}}
|
||||
<span class="ui small label review-comments-counter" data-pending-comment-number="{{.PendingCodeCommentNumber}}">{{.PendingCodeCommentNumber}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</button>
|
||||
<div
|
||||
{{if not $.IsShowingAllCommits}}
|
||||
data-tooltip-content="{{ctx.Locale.Tr "repo.pulls.review_only_possible_for_full_diff"}}"
|
||||
{{else if .Repository.IsArchived}}
|
||||
data-tooltip-content="{{ctx.Locale.Tr "repo.archive.pull.noreview"}}"
|
||||
{{end}}>
|
||||
<button class="ui tiny primary button tw-pr-1 tw-flex js-btn-review {{if or (not $.IsShowingAllCommits) .Repository.IsArchived}}disabled{{end}}">
|
||||
{{ctx.Locale.Tr "repo.diff.review"}}
|
||||
<span class="ui small label review-comments-counter" data-pending-comment-number="{{.PendingCodeCommentNumber}}">{{.PendingCodeCommentNumber}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</button>
|
||||
</div>
|
||||
{{if $.IsShowingAllCommits}}
|
||||
<div class="review-box-panel tippy-target">
|
||||
<div class="ui segment">
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
{{end}}
|
||||
</div>
|
||||
<div class="field {{if .Err_CommitMailID}}error{{end}}">
|
||||
<label for="commit_mail_id">Commit email</label>
|
||||
<label for="commit_mail_id">{{ctx.Locale.Tr "repo.editor.commit_email"}}</label>
|
||||
<select class="ui selection dropdown" name="commit_mail_id">
|
||||
{{range .CommitMails}}
|
||||
<option{{if eq $.DefaultCommitMail .Email}} selected="selected"{{end}} value="{{.ID}}">{{.Email}}</option>
|
||||
|
|
|
@ -602,7 +602,7 @@
|
|||
<div class="timeline-item-group">
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<a class="timeline-avatar"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>
|
||||
<img src="{{.Poster.AvatarLink $.Context}}" width="40" height="40">
|
||||
<img src="{{.Poster.AvatarLink $.Context}}" alt="" width="40" height="40">
|
||||
</a>
|
||||
<span class="badge grey">{{svg "octicon-x" 16}}</span>
|
||||
<span class="text grey muted-links">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="ui stackable middle very relaxed page grid">
|
||||
<div id="repo_migrating" class="sixteen wide center aligned centered column" data-migrating-task-id="{{.MigrateTask.ID}}">
|
||||
<div>
|
||||
<img src="{{AssetUrlPrefix}}/img/forgejo-loading.svg" width="256" height="256">
|
||||
<img src="{{AssetUrlPrefix}}/img/forgejo-loading.svg" alt="{{ctx.Locale.Tr "loading"}}" width="256" height="256">
|
||||
</div>
|
||||
</div>
|
||||
<div id="repo_migrating_failed_image" class="sixteen wide center aligned centered column tw-hidden">
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
{{else if not .IsTextFile}}
|
||||
<div class="view-raw">
|
||||
{{if .IsImageFile}}
|
||||
<img src="{{$.RawFileLink}}">
|
||||
<img src="{{$.RawFileLink}}" alt="">
|
||||
{{else if .IsVideoFile}}
|
||||
<video controls src="{{$.RawFileLink}}">
|
||||
<strong>{{ctx.Locale.Tr "repo.video_not_supported_in_browser"}}</strong>
|
||||
|
|
|
@ -20,7 +20,12 @@
|
|||
{{end}}
|
||||
</div>
|
||||
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}}
|
||||
<div class="ui segment sub-menu language-stats-details tw-hidden">
|
||||
<a class="ui segment show-panel toggle" id="language-stats-bar" data-panel="#language-stats-legend">
|
||||
{{range .LanguageStats}}
|
||||
<div class="bar" style="width: {{.Percentage}}%; background-color: {{.Color}}" data-tooltip-placement="top" data-tooltip-content={{.Language}} data-tooltip-follow-cursor="horizontal"></div>
|
||||
{{end}}
|
||||
</a>
|
||||
<div class="ui segment sub-menu tw-hidden" id="language-stats-legend">
|
||||
{{range .LanguageStats}}
|
||||
<div class="item">
|
||||
<i class="color-icon" style="background-color: {{.Color}}"></i>
|
||||
|
@ -35,11 +40,6 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<a class="ui segment language-stats show-panel toggle" data-panel=".repository-summary > .sub-menu">
|
||||
{{range .LanguageStats}}
|
||||
<div class="bar" style="width: {{.Percentage}}%; background-color: {{.Color}}" data-tooltip-placement="top" data-tooltip-content={{.Language}} data-tooltip-follow-cursor="horizontal"></div>
|
||||
{{end}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
@ -3,27 +3,27 @@
|
|||
{{$size = .Size}}
|
||||
{{end}}
|
||||
{{if eq .HookType "forgejo"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/forgejo.svg">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/forgejo.svg" alt="">
|
||||
{{else if eq .HookType "gitea"}}
|
||||
{{svg "gitea-gitea" $size "img"}}
|
||||
{{else if eq .HookType "gogs"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/gogs.ico">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/gogs.ico" alt="">
|
||||
{{else if eq .HookType "slack"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/slack.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/slack.png" alt="">
|
||||
{{else if eq .HookType "discord"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/discord.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/discord.png" alt="">
|
||||
{{else if eq .HookType "dingtalk"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/dingtalk.ico">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/dingtalk.ico" alt="">
|
||||
{{else if eq .HookType "telegram"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/telegram.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/telegram.png" alt="">
|
||||
{{else if eq .HookType "msteams"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/msteams.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/msteams.png" alt="">
|
||||
{{else if eq .HookType "feishu"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/feishu.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/feishu.png" alt="">
|
||||
{{else if eq .HookType "matrix"}}
|
||||
{{svg "gitea-matrix" $size "img"}}
|
||||
{{else if eq .HookType "wechatwork"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/wechatwork.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/wechatwork.png" alt="">
|
||||
{{else if eq .HookType "packagist"}}
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/packagist.png">
|
||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/packagist.png" alt="">
|
||||
{{end}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{if .EnableCaptcha}}{{if eq .CaptchaType "image"}}
|
||||
<div class="inline field tw-text-center">
|
||||
<input type="hidden" name="img-captcha-id" value="{{.Captcha}}">
|
||||
<img style="transform: scaleX(-1)" onclick="this.src=`{{AppSubUrl}}/captcha/{{.Captcha}}.png?reload=${Date.now()}`" class="captcha-img" src="{{AppSubUrl}}/captcha/{{.Captcha}}.png">
|
||||
<img style="transform: scaleX(-1)" onclick="this.src=`{{AppSubUrl}}/captcha/{{.Captcha}}.png?reload=${Date.now()}`" class="captcha-img" src="{{AppSubUrl}}/captcha/{{.Captcha}}.png" alt="{{ctx.Locale.Tr "captcha"}}">
|
||||
</div>
|
||||
<div class="required field {{if .Err_Captcha}}error{{end}}">
|
||||
<label for="captcha">{{ctx.Locale.Tr "captcha"}}</label>
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
{{range $push.Commits}}
|
||||
{{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}}
|
||||
<div class="flex-text-block">
|
||||
<img class="ui avatar" src="{{$push.AvatarLink $.Context .AuthorEmail}}" title="{{.AuthorName}}" width="16" height="16">
|
||||
<img class="ui avatar" src="{{$push.AvatarLink $.Context .AuthorEmail}}" alt="" title="{{.AuthorName}}" width="16" height="16">
|
||||
<a class="ui sha label" href="{{$commitLink}}">{{ShortSha .Sha1}}</a>
|
||||
<span class="text truncate">
|
||||
{{RenderCommitMessage $.Context .Message ($repo.ComposeMetas ctx)}}
|
||||
|
@ -103,11 +103,11 @@
|
|||
<a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{ctx.Locale.Tr "action.compare_commits" $push.Len}} »</a>
|
||||
{{end}}
|
||||
{{else if .GetOpType.InActions "create_issue"}}
|
||||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span>
|
||||
<span class="text truncate issue title">{{RenderIssueTitle ctx (index .GetIssueInfos 1) (.Repo.ComposeMetas ctx)}}</span>
|
||||
{{else if .GetOpType.InActions "create_pull_request"}}
|
||||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span>
|
||||
<span class="text truncate issue title">{{RenderIssueTitle ctx (index .GetIssueInfos 1) (.Repo.ComposeMetas ctx)}}</span>
|
||||
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}}
|
||||
<a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</a>
|
||||
<a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{RenderIssueTitle ctx (.GetIssueTitle ctx) (.Repo.ComposeMetas ctx)}}</a>
|
||||
{{$comment := index .GetIssueInfos 1}}
|
||||
{{if $comment}}
|
||||
<div class="markup tw-text-14">{{RenderMarkdownToHtml ctx $comment}}</div>
|
||||
|
@ -115,7 +115,7 @@
|
|||
{{else if .GetOpType.InActions "merge_pull_request"}}
|
||||
<div class="flex-item-body text black">{{index .GetIssueInfos 1}}</div>
|
||||
{{else if .GetOpType.InActions "close_issue" "reopen_issue" "close_pull_request" "reopen_pull_request"}}
|
||||
<span class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</span>
|
||||
<span class="text truncate issue title">{{RenderIssueTitle ctx (.GetIssueTitle ctx) (.Repo.ComposeMetas ctx)}}</span>
|
||||
{{else if .GetOpType.InActions "pull_review_dismissed"}}
|
||||
<div class="flex-item-body text black">{{ctx.Locale.Tr "action.review_dismissed_reason"}}</div>
|
||||
<div class="flex-item-body text black">{{index .GetIssueInfos 2 | RenderEmoji $.Context}}</div>
|
||||
|
|
19
tests/e2e/repo-home.e2e.ts
Normal file
19
tests/e2e/repo-home.e2e.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
// @watch start
|
||||
// web_src/js/features/common-global.js
|
||||
// web_src/css/repo.css
|
||||
// @watch end
|
||||
|
||||
import {expect} from '@playwright/test';
|
||||
import {save_visual, test} from './utils_e2e.ts';
|
||||
|
||||
test('Language stats bar', async ({page}) => {
|
||||
const response = await page.goto('/user2/repo1');
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
await expect(page.locator('#language-stats-legend')).toBeVisible();
|
||||
await save_visual(page);
|
||||
|
||||
await page.click('#language-stats-bar');
|
||||
await expect(page.locator('#language-stats-legend')).toBeHidden();
|
||||
await save_visual(page);
|
||||
});
|
|
@ -26,13 +26,36 @@ import (
|
|||
func TestAdminViewUsers(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
req := NewRequest(t, "GET", "/admin/users")
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
t.Run("Admin user", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session = loginUser(t, "user2")
|
||||
req = NewRequest(t, "GET", "/admin/users")
|
||||
session.MakeRequest(t, req, http.StatusForbidden)
|
||||
session := loginUser(t, "user1")
|
||||
req := NewRequest(t, "GET", "/admin/users")
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
req = NewRequest(t, "GET", "/admin/users?status_filter[is_2fa_enabled]=1")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// 6th column is the 2FA column.
|
||||
// One user that has TOTP and another user that has WebAuthn.
|
||||
assert.EqualValues(t, 2, htmlDoc.Find(".admin-setting-content table tbody tr td:nth-child(6) .octicon-check").Length())
|
||||
})
|
||||
|
||||
t.Run("Normal user", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequest(t, "GET", "/admin/users")
|
||||
session.MakeRequest(t, req, http.StatusForbidden)
|
||||
})
|
||||
|
||||
t.Run("Anonymous user", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/admin/users")
|
||||
MakeRequest(t, req, http.StatusSeeOther)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdminViewUser(t *testing.T) {
|
||||
|
|
49
tests/integration/explore_org_test.go
Normal file
49
tests/integration/explore_org_test.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestExploreOrg(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// Set the default sort order
|
||||
defer test.MockVariableValue(&setting.UI.ExploreDefaultSort, "alphabetically")()
|
||||
|
||||
cases := []struct{ sortOrder, expected string }{
|
||||
{"", "?sort=" + setting.UI.ExploreDefaultSort + "&q="},
|
||||
{"newest", "?sort=newest&q="},
|
||||
{"oldest", "?sort=oldest&q="},
|
||||
{"alphabetically", "?sort=alphabetically&q="},
|
||||
{"reversealphabetically", "?sort=reversealphabetically&q="},
|
||||
}
|
||||
for _, c := range cases {
|
||||
req := NewRequest(t, "GET", "/explore/organizations?sort="+c.sortOrder)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
h := NewHTMLParser(t, resp.Body)
|
||||
href, _ := h.Find(`.ui.dropdown .menu a.active.item[href^="?sort="]`).Attr("href")
|
||||
assert.Equal(t, c.expected, href)
|
||||
}
|
||||
|
||||
// these sort orders shouldn't be supported, to avoid leaking user activity
|
||||
cases404 := []string{
|
||||
"/explore/organizations?sort=mostMembers",
|
||||
"/explore/organizations?sort=leastGroups",
|
||||
"/explore/organizations?sort=leastupdate",
|
||||
"/explore/organizations?sort=reverseleastupdate",
|
||||
}
|
||||
for _, c := range cases404 {
|
||||
req := NewRequest(t, "GET", c).SetHeader("Accept", "text/html")
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ import (
|
|||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -15,8 +17,11 @@ import (
|
|||
func TestExploreUser(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// Set the default sort order
|
||||
defer test.MockVariableValue(&setting.UI.ExploreDefaultSort, "reversealphabetically")()
|
||||
|
||||
cases := []struct{ sortOrder, expected string }{
|
||||
{"", "?sort=newest&q="},
|
||||
{"", "?sort=" + setting.UI.ExploreDefaultSort + "&q="},
|
||||
{"newest", "?sort=newest&q="},
|
||||
{"oldest", "?sort=oldest&q="},
|
||||
{"alphabetically", "?sort=alphabetically&q="},
|
||||
|
|
|
@ -133,7 +133,7 @@ func testPullRequestListIcon(t *testing.T, doc *HTMLDoc, name, expectedColor, ex
|
|||
}
|
||||
|
||||
func createOpenPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
|
||||
pull := createPullRequest(t, user, repo, "open")
|
||||
pull := createPullRequest(t, user, repo, "branch-open", "open")
|
||||
|
||||
assert.False(t, pull.Issue.IsClosed)
|
||||
assert.False(t, pull.HasMerged)
|
||||
|
@ -143,7 +143,7 @@ func createOpenPullRequest(ctx context.Context, t *testing.T, user *user_model.U
|
|||
}
|
||||
|
||||
func createOpenWipPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
|
||||
pull := createPullRequest(t, user, repo, "open-wip")
|
||||
pull := createPullRequest(t, user, repo, "branch-open-wip", "open-wip")
|
||||
|
||||
err := issue_service.ChangeTitle(ctx, pull.Issue, user, "WIP: "+pull.Issue.Title)
|
||||
require.NoError(t, err)
|
||||
|
@ -156,7 +156,7 @@ func createOpenWipPullRequest(ctx context.Context, t *testing.T, user *user_mode
|
|||
}
|
||||
|
||||
func createClosedPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
|
||||
pull := createPullRequest(t, user, repo, "closed")
|
||||
pull := createPullRequest(t, user, repo, "branch-closed", "closed")
|
||||
|
||||
err := issue_service.ChangeStatus(ctx, pull.Issue, user, "", true)
|
||||
require.NoError(t, err)
|
||||
|
@ -169,7 +169,7 @@ func createClosedPullRequest(ctx context.Context, t *testing.T, user *user_model
|
|||
}
|
||||
|
||||
func createClosedWipPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
|
||||
pull := createPullRequest(t, user, repo, "closed-wip")
|
||||
pull := createPullRequest(t, user, repo, "branch-closed-wip", "closed-wip")
|
||||
|
||||
err := issue_service.ChangeTitle(ctx, pull.Issue, user, "WIP: "+pull.Issue.Title)
|
||||
require.NoError(t, err)
|
||||
|
@ -185,7 +185,7 @@ func createClosedWipPullRequest(ctx context.Context, t *testing.T, user *user_mo
|
|||
}
|
||||
|
||||
func createMergedPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
|
||||
pull := createPullRequest(t, user, repo, "merged")
|
||||
pull := createPullRequest(t, user, repo, "branch-merged", "merged")
|
||||
|
||||
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
|
||||
defer gitRepo.Close()
|
||||
|
@ -202,10 +202,7 @@ func createMergedPullRequest(ctx context.Context, t *testing.T, user *user_model
|
|||
return pull
|
||||
}
|
||||
|
||||
func createPullRequest(t *testing.T, user *user_model.User, repo *repo_model.Repository, name string) *issues_model.PullRequest {
|
||||
branch := "branch-" + name
|
||||
title := "Testing " + name
|
||||
|
||||
func createPullRequest(t *testing.T, user *user_model.User, repo *repo_model.Repository, branch, title string) *issues_model.PullRequest {
|
||||
_, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user, &files_service.ChangeRepoFilesOptions{
|
||||
Files: []*files_service.ChangeRepoFile{
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
@ -362,6 +363,8 @@ func TestPullView_CodeOwner(t *testing.T) {
|
|||
defer f()
|
||||
|
||||
t.Run("First Pull Request", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// create a new branch to prepare for pull request
|
||||
_, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
|
||||
NewBranch: "codeowner-basebranch",
|
||||
|
@ -409,6 +412,8 @@ func TestPullView_CodeOwner(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
t.Run("Second Pull Request", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// create a new branch to prepare for pull request
|
||||
_, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
|
||||
NewBranch: "codeowner-basebranch2",
|
||||
|
@ -431,6 +436,8 @@ func TestPullView_CodeOwner(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Forked Repo Pull Request", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
forkedRepo, err := repo_service.ForkRepositoryAndUpdates(db.DefaultContext, user2, user5, repo_service.ForkRepoOptions{
|
||||
BaseRepo: repo,
|
||||
|
@ -483,6 +490,8 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
|
|||
defer baseGitRepo.Close()
|
||||
|
||||
t.Run("Submit approve/reject review on merged PR", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Create a merged PR (made by user1) in the upstream repo1.
|
||||
testEditFile(t, user1Session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "master", "This is a pull title")
|
||||
|
@ -513,12 +522,14 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Submit approve/reject review on closed PR", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Created a closed PR (made by user1) in the upstream repo1.
|
||||
testEditFileToNewBranch(t, user1Session, "user1", "repo1", "master", "a-test-branch", "README.md", "Hello, World (Edited...again)\n")
|
||||
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "a-test-branch", "This is a pull title")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testIssueClose(t, user1Session, elem[1], elem[2], elem[4])
|
||||
testIssueClose(t, user1Session, elem[1], elem[2], elem[4], true)
|
||||
|
||||
// Get the commit SHA
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
|
||||
|
@ -544,6 +555,41 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestPullReviewInArchivedRepo(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
// Open a PR
|
||||
testEditFileToNewBranch(t, session, "user2", "repo1", "master", "for-pr", "README.md", "Hi!\n")
|
||||
resp := testPullCreate(t, session, "user2", "repo1", true, "master", "for-pr", "PR title")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
|
||||
t.Run("Review box normally", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// The "Finish review button" must be available
|
||||
resp = session.MakeRequest(t, NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4], "files")), http.StatusOK)
|
||||
button := NewHTMLParser(t, resp.Body).Find("#review-box button")
|
||||
assert.False(t, button.HasClass("disabled"))
|
||||
})
|
||||
|
||||
t.Run("Review box in archived repo", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Archive the repo
|
||||
resp = session.MakeRequest(t, NewRequestWithValues(t, "POST", path.Join(elem[1], elem[2], "settings"), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, path.Join(elem[1], elem[2], "settings")),
|
||||
"action": "archive",
|
||||
}), http.StatusSeeOther)
|
||||
|
||||
// The "Finish review button" must be disabled
|
||||
resp = session.MakeRequest(t, NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4], "files")), http.StatusOK)
|
||||
button := NewHTMLParser(t, resp.Body).Find("#review-box button")
|
||||
assert.True(t, button.HasClass("disabled"))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func testNofiticationCount(t *testing.T, session *TestSession, csrf string, expectedSubmitStatus int) *httptest.ResponseRecorder {
|
||||
options := map[string]string{
|
||||
"_csrf": csrf,
|
||||
|
@ -579,8 +625,12 @@ func testSubmitReview(t *testing.T, session *TestSession, csrf, owner, repo, pul
|
|||
return session.MakeRequest(t, req, expectedSubmitStatus)
|
||||
}
|
||||
|
||||
func testIssueClose(t *testing.T, session *TestSession, owner, repo, issueNumber string) *httptest.ResponseRecorder {
|
||||
req := NewRequest(t, "GET", path.Join(owner, repo, "pulls", issueNumber))
|
||||
func testIssueClose(t *testing.T, session *TestSession, owner, repo, issueNumber string, isPull bool) *httptest.ResponseRecorder {
|
||||
issueType := "issues"
|
||||
if isPull {
|
||||
issueType = "pulls"
|
||||
}
|
||||
req := NewRequest(t, "GET", path.Join(owner, repo, issueType, issueNumber))
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
|
|
@ -1462,3 +1462,15 @@ func TestRepoSubmoduleView(t *testing.T) {
|
|||
htmlDoc.AssertElement(t, fmt.Sprintf(`tr[data-entryname="repo1"] a[href="%s"]`, u.JoinPath("/user2/repo1").String()), true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBlameDirectory(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// Ensure directory exists.
|
||||
req := NewRequest(t, "GET", "/user2/repo59/src/branch/master/deep")
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Blame is not allowed
|
||||
req = NewRequest(t, "GET", "/user2/repo59/blame/branch/master/deep")
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
|
|
@ -5,12 +5,21 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -28,3 +37,45 @@ func TestUserDashboardActionLinks(t *testing.T) {
|
|||
assert.EqualValues(t, locale.TrString("new_migrate.link"), strings.TrimSpace(links.Find("a[href='/repo/migrate']").Text()))
|
||||
assert.EqualValues(t, locale.TrString("new_org.link"), strings.TrimSpace(links.Find("a[href='/org/create']").Text()))
|
||||
}
|
||||
|
||||
func TestDashboardTitleRendering(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
sess := loginUser(t, user4.Name)
|
||||
|
||||
repo, _, f := tests.CreateDeclarativeRepo(t, user4, "",
|
||||
[]unit_model.Type{unit_model.TypePullRequests, unit_model.TypeIssues}, nil,
|
||||
[]*files_service.ChangeRepoFile{
|
||||
{
|
||||
Operation: "create",
|
||||
TreePath: "test.txt",
|
||||
ContentReader: strings.NewReader("Just some text here"),
|
||||
},
|
||||
},
|
||||
)
|
||||
defer f()
|
||||
|
||||
issue := createIssue(t, user4, repo, "`:exclamation:` not rendered", "Hi there!")
|
||||
pr := createPullRequest(t, user4, repo, "testing", "`:exclamation:` not rendered")
|
||||
|
||||
_, err := issue_service.CreateIssueComment(db.DefaultContext, user4, repo, issue, "hi", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = issue_service.CreateIssueComment(db.DefaultContext, user4, repo, pr.Issue, "hi", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
testIssueClose(t, sess, repo.OwnerName, repo.Name, strconv.Itoa(int(issue.Index)), false)
|
||||
testIssueClose(t, sess, repo.OwnerName, repo.Name, strconv.Itoa(int(pr.Issue.Index)), true)
|
||||
|
||||
response := sess.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, response.Body)
|
||||
|
||||
count := 0
|
||||
htmlDoc.doc.Find("#activity-feed .flex-item-main .title").Each(func(i int, s *goquery.Selection) {
|
||||
count++
|
||||
assert.EqualValues(t, ":exclamation: not rendered", s.Text())
|
||||
})
|
||||
|
||||
assert.EqualValues(t, 6, count)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2022,13 +2022,14 @@ details.repo-search-result summary::marker {
|
|||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
|
||||
.repository .repository-summary .segment.language-stats {
|
||||
.repository .repository-summary #language-stats-bar {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
padding: 0;
|
||||
height: 10px;
|
||||
white-space: nowrap;
|
||||
border-radius: 0 0 3px 3px !important;
|
||||
border-top-left-radius: 0 !important;
|
||||
border-top-right-radius: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import {createApp, nextTick} from 'vue';
|
||||
import {createApp} from 'vue';
|
||||
import $ from 'jquery';
|
||||
import {SvgIcon} from '../svg.js';
|
||||
import {GET} from '../modules/fetch.js';
|
||||
|
@ -103,9 +103,6 @@ const sfc = {
|
|||
const el = document.getElementById('dashboard-repo-list');
|
||||
this.changeReposFilter(this.reposFilter);
|
||||
$(el).find('.dropdown').dropdown();
|
||||
nextTick(() => {
|
||||
this.$refs.search.focus();
|
||||
});
|
||||
|
||||
this.textArchivedFilterTitles = {
|
||||
'archived': this.textShowOnlyArchived,
|
||||
|
|
Loading…
Add table
Reference in a new issue