Compare commits

..

8 Commits

Author SHA1 Message Date
yp05327
0945bf63d3
Fix missed .hide class (#23208)
https://github.com/go-gitea/gitea/pull/22950 removed `hide` class, and
use `gt-hidden`
But there are some missed `hide`....

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2023-03-02 12:22:04 +08:00
GiteaBot
785a3e6e92 [skip ci] Updated translations via Crowdin 2023-03-02 00:23:09 +00:00
Lauris BH
58b4143803
Add loading yaml label template files (#22976)
Extract from #11669 and enhancement to #22585 to support exclusive
scoped labels in label templates

* Move label template functionality to label module
* Fix handling of color codes
* Add Advanced label template
2023-03-02 01:44:23 +02:00
Sybren
de6c718b46
Allow <video> in MarkDown (#22892)
As you can imagine, for the Blender development process it is rather
nice to be able to include videos in issues, pull requests, etc.

This PR allows the `<video>` HTML tag to be used in MarkDown, with the
`src`, `autoplay`, and `controls` attributes.

## Help Needed

To have this fully functional, personally I feel the following things
are still missing, and would appreciate some help from the Gitea team.

### Styling

Some CSS is needed, but I couldn't figure out which of the LESS files
would work. I tried `web_src/less/markup/content.less` and
`web_src/less/_base.less`, but after running `make` the changes weren't
seen in the frontend.

This I would consider a minimal set of CSS rules to be applied:

```css
video {
  max-width: 100%;
  max-height: 100vh;
}
```

### Default Attributes

It would be fantastic if Gitea could add some default attributes to the
`<video>` tag. Basically `controls` should always be there, as there is
no point in disallowing scrolling through videos, looping them, etc.

### Integration with the attachments system

Another thing that could be added, but probably should be done in a
separate PR, is the integration with the attachments system. Dragging in
a video should attach it, then generate the appropriate MarkDown/HTML.
2023-03-01 16:30:51 -05:00
Brecht Van Lommel
545495dcb0
Pull Requests: add button to compare force pushed commits (#22857)
To quickly see what changed without having to re-read the whole diff.
2023-03-01 14:19:47 -05:00
Brecht Van Lommel
0268ee5c37
Do not create commit graph for temporary repos (#23219)
When fetching remotes for conflict checking, skip unnecessary and
potentially slow writing of commit graphs.

In a test with the Blender repository, this reduces conflict checking
time for one pull request from about 2s to 0.1s.
2023-03-01 14:19:04 -05:00
wxiaoguang
403f3e9208
Use the correct selector to hide the checkmark of selected labels on clear (#23224)
Regression of #10107
(https://github.com/go-gitea/gitea/pull/10107/files#diff-a15e36f2f9c13339f7fdd38bc2887db2ff2945cb8434464318ab9105fcc846bdR460)

Fix #22222


Before: the "clear" action couldn't remove these check marks.


![image](https://user-images.githubusercontent.com/2114189/222212998-c9f33459-b71d-4e80-8588-2935f3b7050c.png)


After: the "clear" action can remove these  check marks.


![image](https://user-images.githubusercontent.com/2114189/222213048-2be98ed0-cac0-4e27-b72c-1dd0ac2637d5.png)
2023-03-01 14:18:35 -05:00
Brecht Van Lommel
df48af2229
Order pull request conflict checking by recently updated, for each push (#23220)
When a change is pushed to the default branch and many pull requests are
open for that branch, conflict checking can take some time.

Previously it would go from oldest to newest pull request. Now
prioritize pull requests that are likely being actively worked on or
prepared for merging.

This only changes the order within one push to one repository, but the
change is trivial and can already be quite helpful for smaller Gitea
instances where a few repositories have most pull requests. A global
order would require deeper changes to queues.
2023-03-01 14:14:02 -05:00
28 changed files with 842 additions and 289 deletions

View File

@ -7,12 +7,12 @@ package issues
import ( import (
"context" "context"
"fmt" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -78,9 +78,6 @@ func (err ErrLabelNotExist) Unwrap() error {
return util.ErrNotExist return util.ErrNotExist
} }
// LabelColorPattern is a regexp witch can validate LabelColor
var LabelColorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$")
// Label represents a label of repository for issues. // Label represents a label of repository for issues.
type Label struct { type Label struct {
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
@ -109,12 +106,12 @@ func init() {
} }
// CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues. // CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues.
func (label *Label) CalOpenIssues() { func (l *Label) CalOpenIssues() {
label.NumOpenIssues = label.NumIssues - label.NumClosedIssues l.NumOpenIssues = l.NumIssues - l.NumClosedIssues
} }
// CalOpenOrgIssues calculates the open issues of a label for a specific repo // CalOpenOrgIssues calculates the open issues of a label for a specific repo
func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) { func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{ counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{
RepoID: repoID, RepoID: repoID,
LabelIDs: []int64{labelID}, LabelIDs: []int64{labelID},
@ -122,22 +119,22 @@ func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64)
}) })
for _, count := range counts { for _, count := range counts {
label.NumOpenRepoIssues += count l.NumOpenRepoIssues += count
} }
} }
// LoadSelectedLabelsAfterClick calculates the set of selected labels when a label is clicked // LoadSelectedLabelsAfterClick calculates the set of selected labels when a label is clicked
func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) { func (l *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) {
var labelQuerySlice []string var labelQuerySlice []string
labelSelected := false labelSelected := false
labelID := strconv.FormatInt(label.ID, 10) labelID := strconv.FormatInt(l.ID, 10)
labelScope := label.ExclusiveScope() labelScope := l.ExclusiveScope()
for i, s := range currentSelectedLabels { for i, s := range currentSelectedLabels {
if s == label.ID { if s == l.ID {
labelSelected = true labelSelected = true
} else if -s == label.ID { } else if -s == l.ID {
labelSelected = true labelSelected = true
label.IsExcluded = true l.IsExcluded = true
} else if s != 0 { } else if s != 0 {
// Exclude other labels in the same scope from selection // Exclude other labels in the same scope from selection
if s < 0 || labelScope == "" || labelScope != currentSelectedExclusiveScopes[i] { if s < 0 || labelScope == "" || labelScope != currentSelectedExclusiveScopes[i] {
@ -148,23 +145,23 @@ func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64,
if !labelSelected { if !labelSelected {
labelQuerySlice = append(labelQuerySlice, labelID) labelQuerySlice = append(labelQuerySlice, labelID)
} }
label.IsSelected = labelSelected l.IsSelected = labelSelected
label.QueryString = strings.Join(labelQuerySlice, ",") l.QueryString = strings.Join(labelQuerySlice, ",")
} }
// BelongsToOrg returns true if label is an organization label // BelongsToOrg returns true if label is an organization label
func (label *Label) BelongsToOrg() bool { func (l *Label) BelongsToOrg() bool {
return label.OrgID > 0 return l.OrgID > 0
} }
// BelongsToRepo returns true if label is a repository label // BelongsToRepo returns true if label is a repository label
func (label *Label) BelongsToRepo() bool { func (l *Label) BelongsToRepo() bool {
return label.RepoID > 0 return l.RepoID > 0
} }
// Get color as RGB values in 0..255 range // Get color as RGB values in 0..255 range
func (label *Label) ColorRGB() (float64, float64, float64, error) { func (l *Label) ColorRGB() (float64, float64, float64, error) {
color, err := strconv.ParseUint(label.Color[1:], 16, 64) color, err := strconv.ParseUint(l.Color[1:], 16, 64)
if err != nil { if err != nil {
return 0, 0, 0, err return 0, 0, 0, err
} }
@ -176,9 +173,9 @@ func (label *Label) ColorRGB() (float64, float64, float64, error) {
} }
// Determine if label text should be light or dark to be readable on background color // Determine if label text should be light or dark to be readable on background color
func (label *Label) UseLightTextColor() bool { func (l *Label) UseLightTextColor() bool {
if strings.HasPrefix(label.Color, "#") { if strings.HasPrefix(l.Color, "#") {
if r, g, b, err := label.ColorRGB(); err == nil { if r, g, b, err := l.ColorRGB(); err == nil {
// Perceived brightness from: https://www.w3.org/TR/AERT/#color-contrast // Perceived brightness from: https://www.w3.org/TR/AERT/#color-contrast
// In the future WCAG 3 APCA may be a better solution // In the future WCAG 3 APCA may be a better solution
brightness := (0.299*r + 0.587*g + 0.114*b) / 255 brightness := (0.299*r + 0.587*g + 0.114*b) / 255
@ -190,40 +187,26 @@ func (label *Label) UseLightTextColor() bool {
} }
// Return scope substring of label name, or empty string if none exists // Return scope substring of label name, or empty string if none exists
func (label *Label) ExclusiveScope() string { func (l *Label) ExclusiveScope() string {
if !label.Exclusive { if !l.Exclusive {
return "" return ""
} }
lastIndex := strings.LastIndex(label.Name, "/") lastIndex := strings.LastIndex(l.Name, "/")
if lastIndex == -1 || lastIndex == 0 || lastIndex == len(label.Name)-1 { if lastIndex == -1 || lastIndex == 0 || lastIndex == len(l.Name)-1 {
return "" return ""
} }
return label.Name[:lastIndex] return l.Name[:lastIndex]
} }
// NewLabel creates a new label // NewLabel creates a new label
func NewLabel(ctx context.Context, label *Label) error { func NewLabel(ctx context.Context, l *Label) error {
if !LabelColorPattern.MatchString(label.Color) { color, err := label.NormalizeColor(l.Color)
return fmt.Errorf("bad color code: %s", label.Color) if err != nil {
return err
} }
l.Color = color
// normalize case return db.Insert(ctx, l)
label.Color = strings.ToLower(label.Color)
// add leading hash
if label.Color[0] != '#' {
label.Color = "#" + label.Color
}
// convert 3-character shorthand into 6-character version
if len(label.Color) == 4 {
r := label.Color[1]
g := label.Color[2]
b := label.Color[3]
label.Color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
}
return db.Insert(ctx, label)
} }
// NewLabels creates new labels // NewLabels creates new labels
@ -234,11 +217,14 @@ func NewLabels(labels ...*Label) error {
} }
defer committer.Close() defer committer.Close()
for _, label := range labels { for _, l := range labels {
if !LabelColorPattern.MatchString(label.Color) { color, err := label.NormalizeColor(l.Color)
return fmt.Errorf("bad color code: %s", label.Color) if err != nil {
return err
} }
if err := db.Insert(ctx, label); err != nil { l.Color = color
if err := db.Insert(ctx, l); err != nil {
return err return err
} }
} }
@ -247,15 +233,18 @@ func NewLabels(labels ...*Label) error {
// UpdateLabel updates label information. // UpdateLabel updates label information.
func UpdateLabel(l *Label) error { func UpdateLabel(l *Label) error {
if !LabelColorPattern.MatchString(l.Color) { color, err := label.NormalizeColor(l.Color)
return fmt.Errorf("bad color code: %s", l.Color) if err != nil {
return err
} }
l.Color = color
return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive") return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive")
} }
// DeleteLabel delete a label // DeleteLabel delete a label
func DeleteLabel(id, labelID int64) error { func DeleteLabel(id, labelID int64) error {
label, err := GetLabelByID(db.DefaultContext, labelID) l, err := GetLabelByID(db.DefaultContext, labelID)
if err != nil { if err != nil {
if IsErrLabelNotExist(err) { if IsErrLabelNotExist(err) {
return nil return nil
@ -271,10 +260,10 @@ func DeleteLabel(id, labelID int64) error {
sess := db.GetEngine(ctx) sess := db.GetEngine(ctx)
if label.BelongsToOrg() && label.OrgID != id { if l.BelongsToOrg() && l.OrgID != id {
return nil return nil
} }
if label.BelongsToRepo() && label.RepoID != id { if l.BelongsToRepo() && l.RepoID != id {
return nil return nil
} }
@ -682,14 +671,14 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
if err = issue.LoadRepo(ctx); err != nil { if err = issue.LoadRepo(ctx); err != nil {
return err return err
} }
for _, label := range labels { for _, l := range labels {
// Don't add already present labels and invalid labels // Don't add already present labels and invalid labels
if HasIssueLabel(ctx, issue.ID, label.ID) || if HasIssueLabel(ctx, issue.ID, l.ID) ||
(label.RepoID != issue.RepoID && label.OrgID != issue.Repo.OwnerID) { (l.RepoID != issue.RepoID && l.OrgID != issue.Repo.OwnerID) {
continue continue
} }
if err = newIssueLabel(ctx, issue, label, doer); err != nil { if err = newIssueLabel(ctx, issue, l, doer); err != nil {
return fmt.Errorf("newIssueLabel: %w", err) return fmt.Errorf("newIssueLabel: %w", err)
} }
} }

View File

@ -15,8 +15,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
// TODO TestGetLabelTemplateFile
func TestLabel_CalOpenIssues(t *testing.T) { func TestLabel_CalOpenIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})

View File

@ -111,6 +111,7 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
return prs, db.GetEngine(db.DefaultContext). return prs, db.GetEngine(db.DefaultContext).
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?", Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
repoID, branch, false, false). repoID, branch, false, false).
OrderBy("issue.updated_unix DESC").
Join("INNER", "issue", "issue.id=pull_request.issue_id"). Join("INNER", "issue", "issue.id=pull_request.issue_id").
Find(&prs) Find(&prs)
} }

46
modules/label/label.go Normal file
View File

@ -0,0 +1,46 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package label
import (
"fmt"
"regexp"
"strings"
)
// colorPattern is a regexp which can validate label color
var colorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$")
// Label represents label information loaded from template
type Label struct {
Name string `yaml:"name"`
Color string `yaml:"color"`
Description string `yaml:"description,omitempty"`
Exclusive bool `yaml:"exclusive,omitempty"`
}
// NormalizeColor normalizes a color string to a 6-character hex code
func NormalizeColor(color string) (string, error) {
// normalize case
color = strings.TrimSpace(strings.ToLower(color))
// add leading hash
if len(color) == 6 || len(color) == 3 {
color = "#" + color
}
if !colorPattern.MatchString(color) {
return "", fmt.Errorf("bad color code: %s", color)
}
// convert 3-character shorthand into 6-character version
if len(color) == 4 {
r := color[1]
g := color[2]
b := color[3]
color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
}
return color, nil
}

126
modules/label/parser.go Normal file
View File

@ -0,0 +1,126 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package label
import (
"errors"
"fmt"
"strings"
"code.gitea.io/gitea/modules/options"
"gopkg.in/yaml.v3"
)
type labelFile struct {
Labels []*Label `yaml:"labels"`
}
// ErrTemplateLoad represents a "ErrTemplateLoad" kind of error.
type ErrTemplateLoad struct {
TemplateFile string
OriginalError error
}
// IsErrTemplateLoad checks if an error is a ErrTemplateLoad.
func IsErrTemplateLoad(err error) bool {
_, ok := err.(ErrTemplateLoad)
return ok
}
func (err ErrTemplateLoad) Error() string {
return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
}
// GetTemplateFile loads the label template file by given name,
// then parses and returns a list of name-color pairs and optionally description.
func GetTemplateFile(name string) ([]*Label, error) {
data, err := options.GetRepoInitFile("label", name+".yaml")
if err == nil && len(data) > 0 {
return parseYamlFormat(name+".yaml", data)
}
data, err = options.GetRepoInitFile("label", name+".yml")
if err == nil && len(data) > 0 {
return parseYamlFormat(name+".yml", data)
}
data, err = options.GetRepoInitFile("label", name)
if err != nil {
return nil, ErrTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %w", err)}
}
return parseLegacyFormat(name, data)
}
func parseYamlFormat(name string, data []byte) ([]*Label, error) {
lf := &labelFile{}
if err := yaml.Unmarshal(data, lf); err != nil {
return nil, err
}
// Validate label data and fix colors
for _, l := range lf.Labels {
l.Color = strings.TrimSpace(l.Color)
if len(l.Name) == 0 || len(l.Color) == 0 {
return nil, ErrTemplateLoad{name, errors.New("label name and color are required fields")}
}
color, err := NormalizeColor(l.Color)
if err != nil {
return nil, ErrTemplateLoad{name, fmt.Errorf("bad HTML color code '%s' in label: %s", l.Color, l.Name)}
}
l.Color = color
}
return lf.Labels, nil
}
func parseLegacyFormat(name string, data []byte) ([]*Label, error) {
lines := strings.Split(string(data), "\n")
list := make([]*Label, 0, len(lines))
for i := 0; i < len(lines); i++ {
line := strings.TrimSpace(lines[i])
if len(line) == 0 {
continue
}
parts, description, _ := strings.Cut(line, ";")
color, name, ok := strings.Cut(parts, " ")
if !ok {
return nil, ErrTemplateLoad{name, fmt.Errorf("line is malformed: %s", line)}
}
color, err := NormalizeColor(color)
if err != nil {
return nil, ErrTemplateLoad{name, fmt.Errorf("bad HTML color code '%s' in line: %s", color, line)}
}
list = append(list, &Label{
Name: strings.TrimSpace(name),
Color: color,
Description: strings.TrimSpace(description),
})
}
return list, nil
}
// LoadFormatted loads the labels' list of a template file as a string separated by comma
func LoadFormatted(name string) (string, error) {
var buf strings.Builder
list, err := GetTemplateFile(name)
if err != nil {
return "", err
}
for i := 0; i < len(list); i++ {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(list[i].Name)
}
return buf.String(), nil
}

View File

@ -0,0 +1,72 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package label
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestYamlParser(t *testing.T) {
data := []byte(`labels:
- name: priority/low
exclusive: true
color: "#0000ee"
description: "Low priority"
- name: priority/medium
exclusive: true
color: "0e0"
description: "Medium priority"
- name: priority/high
exclusive: true
color: "#ee0000"
description: "High priority"
- name: type/bug
color: "#f00"
description: "Bug"`)
labels, err := parseYamlFormat("test", data)
require.NoError(t, err)
require.Len(t, labels, 4)
assert.Equal(t, "priority/low", labels[0].Name)
assert.True(t, labels[0].Exclusive)
assert.Equal(t, "#0000ee", labels[0].Color)
assert.Equal(t, "Low priority", labels[0].Description)
assert.Equal(t, "priority/medium", labels[1].Name)
assert.True(t, labels[1].Exclusive)
assert.Equal(t, "#00ee00", labels[1].Color)
assert.Equal(t, "Medium priority", labels[1].Description)
assert.Equal(t, "priority/high", labels[2].Name)
assert.True(t, labels[2].Exclusive)
assert.Equal(t, "#ee0000", labels[2].Color)
assert.Equal(t, "High priority", labels[2].Description)
assert.Equal(t, "type/bug", labels[3].Name)
assert.False(t, labels[3].Exclusive)
assert.Equal(t, "#ff0000", labels[3].Color)
assert.Equal(t, "Bug", labels[3].Description)
}
func TestLegacyParser(t *testing.T) {
data := []byte(`#ee0701 bug ; Something is not working
#cccccc duplicate ; This issue or pull request already exists
#84b6eb enhancement`)
labels, err := parseLegacyFormat("test", data)
require.NoError(t, err)
require.Len(t, labels, 3)
assert.Equal(t, "bug", labels[0].Name)
assert.False(t, labels[0].Exclusive)
assert.Equal(t, "#ee0701", labels[0].Color)
assert.Equal(t, "Something is not working", labels[0].Description)
assert.Equal(t, "duplicate", labels[1].Name)
assert.False(t, labels[1].Exclusive)
assert.Equal(t, "#cccccc", labels[1].Color)
assert.Equal(t, "This issue or pull request already exists", labels[1].Description)
assert.Equal(t, "enhancement", labels[2].Name)
assert.False(t, labels[2].Exclusive)
assert.Equal(t, "#84b6eb", labels[2].Color)
assert.Empty(t, labels[2].Description)
}

View File

@ -132,6 +132,8 @@ func createDefaultPolicy() *bluemonday.Policy {
policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...) policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...)
policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
policy.AllowAttrs("itemscope", "itemtype").OnElements("div") policy.AllowAttrs("itemscope", "itemtype").OnElements("div")
// FIXME: Need to handle longdesc in img but there is no easy way to do it // FIXME: Need to handle longdesc in img but there is no easy way to do it

44
modules/options/repo.go Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package options
import (
"fmt"
"os"
"path"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
// GetRepoInitFile returns repository init files
func GetRepoInitFile(tp, name string) ([]byte, error) {
cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
relPath := path.Join("options", tp, cleanedName)
// Use custom file when available.
customPath := path.Join(setting.CustomPath, relPath)
isFile, err := util.IsFile(customPath)
if err != nil {
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
}
if isFile {
return os.ReadFile(customPath)
}
switch tp {
case "readme":
return Readme(cleanedName)
case "gitignore":
return Gitignore(cleanedName)
case "license":
return License(cleanedName)
case "label":
return Labels(cleanedName)
default:
return []byte{}, fmt.Errorf("Invalid init file type")
}
}

View File

@ -23,6 +23,7 @@ import (
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
@ -189,7 +190,7 @@ func CreateRepository(doer, u *user_model.User, opts CreateRepoOptions) (*repo_m
// Check if label template exist // Check if label template exist
if len(opts.IssueLabels) > 0 { if len(opts.IssueLabels) > 0 {
if _, err := GetLabelTemplateFile(opts.IssueLabels); err != nil { if _, err := label.GetTemplateFile(opts.IssueLabels); err != nil {
return nil, err return nil, err
} }
} }

View File

@ -18,6 +18,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/options" "code.gitea.io/gitea/modules/options"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -40,114 +41,6 @@ var (
LabelTemplates map[string]string LabelTemplates map[string]string
) )
// ErrIssueLabelTemplateLoad represents a "ErrIssueLabelTemplateLoad" kind of error.
type ErrIssueLabelTemplateLoad struct {
TemplateFile string
OriginalError error
}
// IsErrIssueLabelTemplateLoad checks if an error is a ErrIssueLabelTemplateLoad.
func IsErrIssueLabelTemplateLoad(err error) bool {
_, ok := err.(ErrIssueLabelTemplateLoad)
return ok
}
func (err ErrIssueLabelTemplateLoad) Error() string {
return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
}
// GetRepoInitFile returns repository init files
func GetRepoInitFile(tp, name string) ([]byte, error) {
cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
relPath := path.Join("options", tp, cleanedName)
// Use custom file when available.
customPath := path.Join(setting.CustomPath, relPath)
isFile, err := util.IsFile(customPath)
if err != nil {
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
}
if isFile {
return os.ReadFile(customPath)
}
switch tp {
case "readme":
return options.Readme(cleanedName)
case "gitignore":
return options.Gitignore(cleanedName)
case "license":
return options.License(cleanedName)
case "label":
return options.Labels(cleanedName)
default:
return []byte{}, fmt.Errorf("Invalid init file type")
}
}
// GetLabelTemplateFile loads the label template file by given name,
// then parses and returns a list of name-color pairs and optionally description.
func GetLabelTemplateFile(name string) ([][3]string, error) {
data, err := GetRepoInitFile("label", name)
if err != nil {
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %w", err)}
}
lines := strings.Split(string(data), "\n")
list := make([][3]string, 0, len(lines))
for i := 0; i < len(lines); i++ {
line := strings.TrimSpace(lines[i])
if len(line) == 0 {
continue
}
parts := strings.SplitN(line, ";", 2)
fields := strings.SplitN(parts[0], " ", 2)
if len(fields) != 2 {
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("line is malformed: %s", line)}
}
color := strings.Trim(fields[0], " ")
if len(color) == 6 {
color = "#" + color
}
if !issues_model.LabelColorPattern.MatchString(color) {
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("bad HTML color code in line: %s", line)}
}
var description string
if len(parts) > 1 {
description = strings.TrimSpace(parts[1])
}
fields[1] = strings.TrimSpace(fields[1])
list = append(list, [3]string{fields[1], color, description})
}
return list, nil
}
func loadLabels(labelTemplate string) ([]string, error) {
list, err := GetLabelTemplateFile(labelTemplate)
if err != nil {
return nil, err
}
labels := make([]string, len(list))
for i := 0; i < len(list); i++ {
labels[i] = list[i][0]
}
return labels, nil
}
// LoadLabelsFormatted loads the labels' list of a template file as a string separated by comma
func LoadLabelsFormatted(labelTemplate string) (string, error) {
labels, err := loadLabels(labelTemplate)
return strings.Join(labels, ", "), err
}
// LoadRepoConfig loads the repository config // LoadRepoConfig loads the repository config
func LoadRepoConfig() { func LoadRepoConfig() {
// Load .gitignore and license files and readme templates. // Load .gitignore and license files and readme templates.
@ -158,6 +51,14 @@ func LoadRepoConfig() {
if err != nil { if err != nil {
log.Fatal("Failed to get %s files: %v", t, err) log.Fatal("Failed to get %s files: %v", t, err)
} }
if t == "label" {
for i, f := range files {
ext := strings.ToLower(filepath.Ext(f))
if ext == ".yaml" || ext == ".yml" {
files[i] = f[:len(f)-len(ext)]
}
}
}
customPath := path.Join(setting.CustomPath, "options", t) customPath := path.Join(setting.CustomPath, "options", t)
isDir, err := util.IsDir(customPath) isDir, err := util.IsDir(customPath)
if err != nil { if err != nil {
@ -190,7 +91,7 @@ func LoadRepoConfig() {
// Load label templates // Load label templates
LabelTemplates = make(map[string]string) LabelTemplates = make(map[string]string)
for _, templateFile := range LabelTemplatesFiles { for _, templateFile := range LabelTemplatesFiles {
labels, err := LoadLabelsFormatted(templateFile) labels, err := label.LoadFormatted(templateFile)
if err != nil { if err != nil {
log.Error("Failed to load labels: %v", err) log.Error("Failed to load labels: %v", err)
} }
@ -235,7 +136,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
} }
// README // README
data, err := GetRepoInitFile("readme", opts.Readme) data, err := options.GetRepoInitFile("readme", opts.Readme)
if err != nil { if err != nil {
return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.Readme, err) return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.Readme, err)
} }
@ -263,7 +164,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
var buf bytes.Buffer var buf bytes.Buffer
names := strings.Split(opts.Gitignores, ",") names := strings.Split(opts.Gitignores, ",")
for _, name := range names { for _, name := range names {
data, err = GetRepoInitFile("gitignore", name) data, err = options.GetRepoInitFile("gitignore", name)
if err != nil { if err != nil {
return fmt.Errorf("GetRepoInitFile[%s]: %w", name, err) return fmt.Errorf("GetRepoInitFile[%s]: %w", name, err)
} }
@ -281,7 +182,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
// LICENSE // LICENSE
if len(opts.License) > 0 { if len(opts.License) > 0 {
data, err = GetRepoInitFile("license", opts.License) data, err = options.GetRepoInitFile("license", opts.License)
if err != nil { if err != nil {
return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.License, err) return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.License, err)
} }
@ -443,7 +344,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re
// InitializeLabels adds a label set to a repository using a template // InitializeLabels adds a label set to a repository using a template
func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg bool) error { func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg bool) error {
list, err := GetLabelTemplateFile(labelTemplate) list, err := label.GetTemplateFile(labelTemplate)
if err != nil { if err != nil {
return err return err
} }
@ -451,9 +352,10 @@ func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg
labels := make([]*issues_model.Label, len(list)) labels := make([]*issues_model.Label, len(list))
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
labels[i] = &issues_model.Label{ labels[i] = &issues_model.Label{
Name: list[i][0], Name: list[i].Name,
Description: list[i][2], Exclusive: list[i].Exclusive,
Color: list[i][1], Description: list[i].Description,
Color: list[i].Color,
} }
if isOrg { if isOrg {
labels[i].OrgID = id labels[i].OrgID = id

View File

@ -0,0 +1,70 @@
labels:
- name: "Kind/Bug"
color: ee0701
description: Something is not working
- name: "Kind/Feature"
color: 0288d1
description: New functionality
- name: "Kind/Enhancement"
color: 84b6eb
description: Improve existing functionality
- name: "Kind/Security"
color: 9c27b0
description: This is security issue
- name: "Kind/Testing"
color: 795548
description: Issue or pull request related to testing
- name: "Kind/Breaking"
color: c62828
description: Breaking change that won't be backward compatible
- name: "Kind/Documentation"
color: 37474f
description: Documentation changes
- name: "Reviewed/Duplicate"
exclusive: true
color: 616161
description: This issue or pull request already exists
- name: "Reviewed/Invalid"
exclusive: true
color: 546e7a
description: Invalid issue
- name: "Reviewed/Confirmed"
exclusive: true
color: 795548
description: Issue has been confirmed
- name: "Reviewed/Won't Fix"
exclusive: true
color: eeeeee
description: This issue won't be fixed
- name: "Status/Need More Info"
exclusive: true
color: 424242
description: Feedback is required to reproduce issue or to continue work
- name: "Status/Blocked"
exclusive: true
color: 880e4f
description: Something is blocking this issue or pull request
- name: "Status/Abandoned"
exclusive: true
color: "222222"
description: Somebody has started to work on this but abandoned work
- name: "Priority/Critical"
exclusive: true
color: b71c1c
description: The priority is critical
priority: critical
- name: "Priority/High"
exclusive: true
color: d32f2f
description: The priority is high
priority: high
- name: "Priority/Medium"
exclusive: true
color: e64a19
description: The priority is medium
priority: medium
- name: "Priority/Low"
exclusive: true
color: 4caf50
description: The priority is low
priority: low

View File

@ -1470,6 +1470,7 @@ issues.error_removing_due_date = "Failed to remove the due date."
issues.push_commit_1 = "added %d commit %s" issues.push_commit_1 = "added %d commit %s"
issues.push_commits_n = "added %d commits %s" issues.push_commits_n = "added %d commits %s"
issues.force_push_codes = `force-pushed %[1]s from <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> to <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s` issues.force_push_codes = `force-pushed %[1]s from <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> to <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
issues.force_push_compare = Compare
issues.due_date_form = "yyyy-mm-dd" issues.due_date_form = "yyyy-mm-dd"
issues.due_date_form_add = "Add due date" issues.due_date_form_add = "Add due date"
issues.due_date_form_edit = "Edit" issues.due_date_form_edit = "Edit"

View File

@ -57,6 +57,7 @@ new_mirror=新しいミラー
new_fork=新しいフォーク new_fork=新しいフォーク
new_org=新しい組織 new_org=新しい組織
new_project=新しいプロジェクト new_project=新しいプロジェクト
new_project_column=新しい列
manage_org=組織を管理 manage_org=組織を管理
admin_panel=サイト管理 admin_panel=サイト管理
account_settings=アカウント設定 account_settings=アカウント設定
@ -90,6 +91,7 @@ disabled=無効
copy=コピー copy=コピー
copy_url=URLをコピー copy_url=URLをコピー
copy_content=内容をコピー
copy_branch=ブランチ名をコピー copy_branch=ブランチ名をコピー
copy_success=コピーされました! copy_success=コピーされました!
copy_error=コピーに失敗しました copy_error=コピーに失敗しました
@ -247,6 +249,8 @@ no_reply_address=メールを隠すときのドメイン
no_reply_address_helper=メールアドレスを隠しているユーザーに使用するドメイン名。 例えば 'noreply.example.org' と設定した場合、ユーザー名 'joe' はGitに 'joe@noreply.example.org' としてログインすることになります。 no_reply_address_helper=メールアドレスを隠しているユーザーに使用するドメイン名。 例えば 'noreply.example.org' と設定した場合、ユーザー名 'joe' はGitに 'joe@noreply.example.org' としてログインすることになります。
password_algorithm=パスワードハッシュアルゴリズム password_algorithm=パスワードハッシュアルゴリズム
password_algorithm_helper=パスワードハッシュアルゴリズムを設定します。 アルゴリズムにより動作要件と強度が異なります。 `argon2`は良い特性を備えていますが、多くのメモリを使用するため小さなシステムには適さない場合があります。 password_algorithm_helper=パスワードハッシュアルゴリズムを設定します。 アルゴリズムにより動作要件と強度が異なります。 `argon2`は良い特性を備えていますが、多くのメモリを使用するため小さなシステムには適さない場合があります。
enable_update_checker=アップデートチェッカーを有効にする
enable_update_checker_helper=gitea.ioに接続して定期的に新しいバージョンのリリースを確認します。
[home] [home]
uname_holder=ユーザー名またはメールアドレス uname_holder=ユーザー名またはメールアドレス
@ -324,6 +328,7 @@ email_not_associate=このメールアドレスは、どのアカウントにも
send_reset_mail=アカウント回復メールを送信 send_reset_mail=アカウント回復メールを送信
reset_password=アカウントの回復 reset_password=アカウントの回復
invalid_code=確認コードが無効か期限切れです。 invalid_code=確認コードが無効か期限切れです。
invalid_password=アカウントの作成に使用されたパスワードと一致しません。
reset_password_helper=アカウント回復 reset_password_helper=アカウント回復
reset_password_wrong_user=アカウント回復のリンクは %[2]s のものですが、あなたは %[1]s でサインイン中です reset_password_wrong_user=アカウント回復のリンクは %[2]s のものですが、あなたは %[1]s でサインイン中です
password_too_short=%d文字未満のパスワードは設定できません。 password_too_short=%d文字未満のパスワードは設定できません。
@ -367,6 +372,7 @@ password_pwned_err=HaveIBeenPwnedへのリクエストを完了できません
[mail] [mail]
view_it_on=%s で見る view_it_on=%s で見る
reply=またはこのメールに直接返信してください
link_not_working_do_paste=開かないですか? コピーしてブラウザーに貼り付けてみてください。 link_not_working_do_paste=開かないですか? コピーしてブラウザーに貼り付けてみてください。
hi_user_x=こんにちは、<b>%s</b> さん。 hi_user_x=こんにちは、<b>%s</b> さん。
@ -510,6 +516,7 @@ duplicate_invite_to_team=指定したユーザーはすでにチームメンバ
invalid_ssh_key=SSHキーが確認できません: %s invalid_ssh_key=SSHキーが確認できません: %s
invalid_gpg_key=GPGキーが確認できません: %s invalid_gpg_key=GPGキーが確認できません: %s
invalid_ssh_principal=無効なプリンシパル: %s invalid_ssh_principal=無効なプリンシパル: %s
must_use_public_key=あなたが提供したキーは秘密鍵です。秘密鍵をどこにもアップロードしないでください。代わりに公開鍵を使用してください。
unable_verify_ssh_key=SSHキーが確認できません。間違いが無いか、よく確認してください。 unable_verify_ssh_key=SSHキーが確認できません。間違いが無いか、よく確認してください。
auth_failed=認証に失敗しました: %v auth_failed=認証に失敗しました: %v
@ -746,6 +753,8 @@ access_token_deletion_cancel_action=キャンセル
access_token_deletion_confirm_action=削除 access_token_deletion_confirm_action=削除
access_token_deletion_desc=トークンを削除すると、それを使用しているアプリケーションは、アカウントへのアクセスができなくなります。これは元に戻せません。続行しますか? access_token_deletion_desc=トークンを削除すると、それを使用しているアプリケーションは、アカウントへのアクセスができなくなります。これは元に戻せません。続行しますか?
delete_token_success=トークンを削除しました。 削除したトークンを使用しているアプリケーションは、今後あなたのアカウントにアクセスできません。 delete_token_success=トークンを削除しました。 削除したトークンを使用しているアプリケーションは、今後あなたのアカウントにアクセスできません。
select_scopes=スコープを選択
scopes_list=スコープ:
manage_oauth2_applications=OAuth2アプリケーションの管理 manage_oauth2_applications=OAuth2アプリケーションの管理
edit_oauth2_application=OAuth2アプリケーションの編集 edit_oauth2_application=OAuth2アプリケーションの編集
@ -1018,10 +1027,12 @@ unstar=スター取消
star=スター star=スター
fork=フォーク fork=フォーク
download_archive=リポジトリをダウンロード download_archive=リポジトリをダウンロード
more_operations=その他の操作
no_desc=説明なし no_desc=説明なし
quick_guide=クイック ガイド quick_guide=クイック ガイド
clone_this_repo=このリポジトリのクローンを作成 clone_this_repo=このリポジトリのクローンを作成
cite_this_repo=このリポジトリを引用
create_new_repo_command=コマンドラインから新しいリポジトリを作成 create_new_repo_command=コマンドラインから新しいリポジトリを作成
push_exist_repo=コマンドラインから既存のリポジトリをプッシュ push_exist_repo=コマンドラインから既存のリポジトリをプッシュ
empty_message=このリポジトリの中には何もありません。 empty_message=このリポジトリの中には何もありません。
@ -1120,6 +1131,7 @@ editor.commit_directly_to_this_branch=ブランチ<strong class="branch-name">%s
editor.create_new_branch=<strong>新しいブランチ</strong>にコミットしてプルリクエストを作成する。 editor.create_new_branch=<strong>新しいブランチ</strong>にコミットしてプルリクエストを作成する。
editor.create_new_branch_np=<strong>新しいブランチ</strong>にコミットする。 editor.create_new_branch_np=<strong>新しいブランチ</strong>にコミットする。
editor.propose_file_change=ファイル修正を提案 editor.propose_file_change=ファイル修正を提案
editor.new_branch_name=このコミットの新しいブランチに名前を付けます
editor.new_branch_name_desc=新しいブランチ名… editor.new_branch_name_desc=新しいブランチ名…
editor.cancel=キャンセル editor.cancel=キャンセル
editor.filename_cannot_be_empty=ファイル名は空にできません。 editor.filename_cannot_be_empty=ファイル名は空にできません。
@ -1171,6 +1183,7 @@ commits.signed_by_untrusted_user_unmatched=コミッターと一致しない信
commits.gpg_key_id=GPGキーID commits.gpg_key_id=GPGキーID
commits.ssh_key_fingerprint=SSH鍵のフィンガープリント commits.ssh_key_fingerprint=SSH鍵のフィンガープリント
commit.operations=操作
commit.revert=リバート commit.revert=リバート
commit.revert-header=リバート: %s commit.revert-header=リバート: %s
commit.revert-content=リバートするブランチを選択: commit.revert-content=リバートするブランチを選択:
@ -1195,19 +1208,30 @@ projects.deletion_desc=プロジェクトを削除し、関連するすべての
projects.deletion_success=プロジェクトを削除しました。 projects.deletion_success=プロジェクトを削除しました。
projects.edit=プロジェクトの編集 projects.edit=プロジェクトの編集
projects.edit_subheader=プロジェクトはイシューをまとめ、進捗を管理します。 projects.edit_subheader=プロジェクトはイシューをまとめ、進捗を管理します。
projects.modify=プロジェクトを更新 projects.modify=プロジェクトを編集
projects.edit_success=プロジェクト '%s' を更新しました。 projects.edit_success=プロジェクト '%s' を更新しました。
projects.type.none=なし projects.type.none=なし
projects.type.basic_kanban=基本的なカンバン projects.type.basic_kanban=基本的なカンバン
projects.type.bug_triage=バグ トリアージ projects.type.bug_triage=バグ トリアージ
projects.template.desc=プロジェクト テンプレート projects.template.desc=テンプレート
projects.template.desc_helper=開始するプロジェクトテンプレートを選択 projects.template.desc_helper=開始するプロジェクトテンプレートを選択
projects.type.uncategorized=未分類 projects.type.uncategorized=未分類
projects.column.edit=列を編集
projects.column.edit_title=名称 projects.column.edit_title=名称
projects.column.new_title=名称 projects.column.new_title=名称
projects.column.new_submit=列を作成
projects.column.new=新しい列
projects.column.set_default=デフォルトに設定
projects.column.set_default_desc=この列を未分類のイシューやプルリクエストが入るデフォルトの列にします
projects.column.delete=列を削除
projects.column.deletion_desc=プロジェクト列を削除すると、関連するすべてのイシューが '未分類' に移動します。 続行しますか?
projects.column.color=カラー projects.column.color=カラー
projects.open=オープン projects.open=オープン
projects.close=クローズ projects.close=クローズ
projects.column.assigned_to=担当
projects.card_type.desc=カードプレビュー
projects.card_type.images_and_text=画像とテキスト
projects.card_type.text_only=テキストのみ
issues.desc=バグ報告、タスク、マイルストーンの作成。 issues.desc=バグ報告、タスク、マイルストーンの作成。
issues.filter_assignees=候補者の絞り込み issues.filter_assignees=候補者の絞り込み
@ -1284,6 +1308,7 @@ issues.filter_label_no_select=すべてのラベル
issues.filter_milestone=マイルストーン issues.filter_milestone=マイルストーン
issues.filter_milestone_no_select=すべてのマイルストーン issues.filter_milestone_no_select=すべてのマイルストーン
issues.filter_project=プロジェクト issues.filter_project=プロジェクト
issues.filter_project_all=すべてのプロジェクト
issues.filter_project_none=プロジェクトなし issues.filter_project_none=プロジェクトなし
issues.filter_assignee=担当者 issues.filter_assignee=担当者
issues.filter_assginee_no_select=すべての担当者 issues.filter_assginee_no_select=すべての担当者
@ -1295,6 +1320,7 @@ issues.filter_type.assigned_to_you=自分が担当
issues.filter_type.created_by_you=自分が作成 issues.filter_type.created_by_you=自分が作成
issues.filter_type.mentioning_you=自分が関係 issues.filter_type.mentioning_you=自分が関係
issues.filter_type.review_requested=レビュー依頼あり issues.filter_type.review_requested=レビュー依頼あり
issues.filter_type.reviewed_by_you=自分がレビュー
issues.filter_sort=並べ替え issues.filter_sort=並べ替え
issues.filter_sort.latest=新しい順 issues.filter_sort.latest=新しい順
issues.filter_sort.oldest=古い順 issues.filter_sort.oldest=古い順
@ -1316,6 +1342,8 @@ issues.action_milestone=マイルストーン
issues.action_milestone_no_select=マイルストーンなし issues.action_milestone_no_select=マイルストーンなし
issues.action_assignee=担当者 issues.action_assignee=担当者
issues.action_assignee_no_select=担当者なし issues.action_assignee_no_select=担当者なし
issues.action_check=チェックを設定/解除します
issues.action_check_all=すべての項目のチェックを設定/解除します
issues.opened_by=<a href="%[2]s">%[3]s</a>が%[1]sに作成 issues.opened_by=<a href="%[2]s">%[3]s</a>が%[1]sに作成
pulls.merged_by=<a href="%[2]s">%[3]s</a>が作成、%[1]sにマージ pulls.merged_by=<a href="%[2]s">%[3]s</a>が作成、%[1]sにマージ
pulls.merged_by_fake=%[2]sが作成、%[1]sにマージ pulls.merged_by_fake=%[2]sが作成、%[1]sにマージ
@ -1622,6 +1650,7 @@ pulls.reopened_at=`がプルリクエストを再オープン <a id="%[1]s" href
pulls.merge_instruction_hint=`<a class="show-instruction">コマンドラインの手順</a>も確認できます。` pulls.merge_instruction_hint=`<a class="show-instruction">コマンドラインの手順</a>も確認できます。`
pulls.merge_instruction_step1_desc=あなたのプロジェクトリポジトリで新しいブランチをチェックアウトし、変更内容をテストします。 pulls.merge_instruction_step1_desc=あなたのプロジェクトリポジトリで新しいブランチをチェックアウトし、変更内容をテストします。
pulls.merge_instruction_step2_desc=変更内容をマージして、Giteaに反映します。 pulls.merge_instruction_step2_desc=変更内容をマージして、Giteaに反映します。
pulls.clear_merge_message=マージメッセージをクリア
pulls.auto_merge_button_when_succeed=(チェックがすべて成功した場合) pulls.auto_merge_button_when_succeed=(チェックがすべて成功した場合)
pulls.auto_merge_when_succeed=すべてのチェックが成功したら自動マージ pulls.auto_merge_when_succeed=すべてのチェックが成功したら自動マージ
@ -1813,6 +1842,7 @@ settings.mirror_sync_in_progress=ミラー同期を実行しています。 し
settings.site=Webサイト settings.site=Webサイト
settings.update_settings=設定を更新 settings.update_settings=設定を更新
settings.branches.update_default_branch=デフォルトブランチを更新 settings.branches.update_default_branch=デフォルトブランチを更新
settings.branches.add_new_rule=新しいルールを追加
settings.advanced_settings=拡張設定 settings.advanced_settings=拡張設定
settings.wiki_desc=Wikiを有効にする settings.wiki_desc=Wikiを有効にする
settings.use_internal_wiki=ビルトインのWikiを使用する settings.use_internal_wiki=ビルトインのWikiを使用する
@ -1842,8 +1872,11 @@ settings.pulls.ignore_whitespace=空白文字のコンフリクトを無視す
settings.pulls.enable_autodetect_manual_merge=手動マージの自動検出を有効にする (注意: 特殊なケースでは判定ミスが発生する場合があります) settings.pulls.enable_autodetect_manual_merge=手動マージの自動検出を有効にする (注意: 特殊なケースでは判定ミスが発生する場合があります)
settings.pulls.allow_rebase_update=リベースでプルリクエストのブランチの更新を可能にする settings.pulls.allow_rebase_update=リベースでプルリクエストのブランチの更新を可能にする
settings.pulls.default_delete_branch_after_merge=デフォルトでプルリクエストのブランチをマージ後に削除する settings.pulls.default_delete_branch_after_merge=デフォルトでプルリクエストのブランチをマージ後に削除する
settings.pulls.default_allow_edits_from_maintainers=デフォルトでメンテナからの編集を許可する
settings.releases_desc=リリースを有効にする
settings.packages_desc=リポジトリパッケージレジストリを有効にする settings.packages_desc=リポジトリパッケージレジストリを有効にする
settings.projects_desc=リポジトリプロジェクトを有効にする settings.projects_desc=リポジトリプロジェクトを有効にする
settings.actions_desc=Actionsを有効にする
settings.admin_settings=管理者用設定 settings.admin_settings=管理者用設定
settings.admin_enable_health_check=リポジトリのヘルスチェックを有効にする (git fsck) settings.admin_enable_health_check=リポジトリのヘルスチェックを有効にする (git fsck)
settings.admin_code_indexer=コードインデクサ settings.admin_code_indexer=コードインデクサ
@ -2053,6 +2086,8 @@ settings.deploy_key_deletion_desc=デプロイキーを削除し、リポジト
settings.deploy_key_deletion_success=デプロイキーを削除しました。 settings.deploy_key_deletion_success=デプロイキーを削除しました。
settings.branches=ブランチ settings.branches=ブランチ
settings.protected_branch=ブランチの保護 settings.protected_branch=ブランチの保護
settings.protected_branch.save_rule=ルールを保存
settings.protected_branch.delete_rule=ルールを削除
settings.protected_branch_can_push=プッシュを許可する settings.protected_branch_can_push=プッシュを許可する
settings.protected_branch_can_push_yes=プッシュできます settings.protected_branch_can_push_yes=プッシュできます
settings.protected_branch_can_push_no=プッシュできません settings.protected_branch_can_push_no=プッシュできません
@ -2087,15 +2122,17 @@ settings.dismiss_stale_approvals=古くなった承認を取り消す
settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える新たなコミットがブランチにプッシュされた場合、以前の承認を取り消します。 settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える新たなコミットがブランチにプッシュされた場合、以前の承認を取り消します。
settings.require_signed_commits=コミット署名必須 settings.require_signed_commits=コミット署名必須
settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。 settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。
settings.protect_branch_name_pattern=保護ブランチ名のパターン
settings.protect_protected_file_patterns=保護されるファイルのパターン (セミコロン'\;'で区切る): settings.protect_protected_file_patterns=保護されるファイルのパターン (セミコロン'\;'で区切る):
settings.protect_protected_file_patterns_desc=保護されたファイルは、このブランチにファイルを追加・編集・削除する権限を持つユーザーであっても、直接変更することができなくなります。 セミコロン('\;')で区切って複数のパターンを指定できます。 パターンの文法については <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code> settings.protect_protected_file_patterns_desc=保護されたファイルは、このブランチにファイルを追加・編集・削除する権限を持つユーザーであっても、直接変更することができなくなります。 セミコロン('\;')で区切って複数のパターンを指定できます。 パターンの文法については <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
settings.protect_unprotected_file_patterns=保護しないファイルのパターン (セミコロン'\;'で区切る): settings.protect_unprotected_file_patterns=保護しないファイルのパターン (セミコロン'\;'で区切る):
settings.protect_unprotected_file_patterns_desc=保護しないファイルは、ユーザーに書き込み権限があればプッシュ制限をバイパスして直接変更できます。 セミコロン('\;')で区切って複数のパターンを指定できます。 パターンの文法については <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code> settings.protect_unprotected_file_patterns_desc=保護しないファイルは、ユーザーに書き込み権限があればプッシュ制限をバイパスして直接変更できます。 セミコロン('\;')で区切って複数のパターンを指定できます。 パターンの文法については <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
settings.add_protected_branch=保護を有効にする settings.add_protected_branch=保護を有効にする
settings.delete_protected_branch=保護を無効にする settings.delete_protected_branch=保護を無効にする
settings.update_protect_branch_success=ブランチ '%s' の保護を更新しました。 settings.update_protect_branch_success=ルール '%s' に対するブランチ保護を更新しました。
settings.remove_protected_branch_success=ブランチ '%s' の保護を無効にしました。 settings.remove_protected_branch_success=ルール '%s' に対するブランチ保護を削除しました。
settings.protected_branch_deletion=ブランチ保護の無効化 settings.remove_protected_branch_failed=ブランチ保護ルール '%s' を削除できませんでした。
settings.protected_branch_deletion=ブランチ保護の削除
settings.protected_branch_deletion_desc=ブランチ保護を無効にすると、書き込み権限を持つユーザーにブランチへのプッシュを許可することになります。 続行しますか? settings.protected_branch_deletion_desc=ブランチ保護を無効にすると、書き込み権限を持つユーザーにブランチへのプッシュを許可することになります。 続行しますか?
settings.block_rejected_reviews=不承認レビューでマージをブロック settings.block_rejected_reviews=不承認レビューでマージをブロック
settings.block_rejected_reviews_desc=公式レビューアが変更を要請しているときは、承認数を満たしていてもマージできないようにします。 settings.block_rejected_reviews_desc=公式レビューアが変更を要請しているときは、承認数を満たしていてもマージできないようにします。
@ -2104,10 +2141,13 @@ settings.block_on_official_review_requests_desc=公式レビュー依頼があ
settings.block_outdated_branch=遅れているプルリクエストのマージをブロック settings.block_outdated_branch=遅れているプルリクエストのマージをブロック
settings.block_outdated_branch_desc=baseブランチがheadブランチより進んでいる場合、マージできないようにします。 settings.block_outdated_branch_desc=baseブランチがheadブランチより進んでいる場合、マージできないようにします。
settings.default_branch_desc=プルリクエストやコミット表示のデフォルトのブランチを選択: settings.default_branch_desc=プルリクエストやコミット表示のデフォルトのブランチを選択:
settings.default_merge_style_desc=プルリクエストのデフォルトのマージ方法: settings.merge_style_desc=マージ スタイル
settings.default_merge_style_desc=デフォルトのマージスタイル
settings.choose_branch=ブランチを選択… settings.choose_branch=ブランチを選択…
settings.no_protected_branch=保護しているブランチはありません。 settings.no_protected_branch=保護しているブランチはありません。
settings.edit_protected_branch=編集 settings.edit_protected_branch=編集
settings.protected_branch_required_rule_name=ルール名は必須です
settings.protected_branch_duplicate_rule_name=ルール名が重複しています
settings.protected_branch_required_approvals_min=必要な承認数は負の数にできません。 settings.protected_branch_required_approvals_min=必要な承認数は負の数にできません。
settings.tags=タグ settings.tags=タグ
settings.tags.protection=タグの保護 settings.tags.protection=タグの保護
@ -2530,6 +2570,10 @@ dashboard.delete_old_actions=データベースから古い操作履歴をすべ
dashboard.delete_old_actions.started=データベースからの古い操作履歴の削除を開始しました。 dashboard.delete_old_actions.started=データベースからの古い操作履歴の削除を開始しました。
dashboard.update_checker=更新チェック dashboard.update_checker=更新チェック
dashboard.delete_old_system_notices=データベースから古いシステム通知をすべて削除 dashboard.delete_old_system_notices=データベースから古いシステム通知をすべて削除
dashboard.gc_lfs=LFSメタオブジェクトのガベージコレクション
dashboard.stop_zombie_tasks=ゾンビタスクを停止
dashboard.stop_endless_tasks=終わらないタスクを停止
dashboard.cancel_abandoned_jobs=放置されたままのジョブをキャンセル
users.user_manage_panel=ユーザーアカウント管理 users.user_manage_panel=ユーザーアカウント管理
users.new_account=ユーザーアカウントを作成 users.new_account=ユーザーアカウントを作成
@ -2973,6 +3017,7 @@ monitor.queue.pool.cancel_desc=キューをワーカーグループ無しのま
notices.system_notice_list=システム通知 notices.system_notice_list=システム通知
notices.view_detail_header=通知の詳細を表示 notices.view_detail_header=通知の詳細を表示
notices.operations=操作
notices.select_all=すべて選択 notices.select_all=すべて選択
notices.deselect_all=すべて選択解除 notices.deselect_all=すべて選択解除
notices.inverse_selection=選択を反転 notices.inverse_selection=選択を反転
@ -3097,6 +3142,8 @@ keywords=キーワード
details=詳細 details=詳細
details.author=著作者 details.author=著作者
details.project_site=プロジェクトサイト details.project_site=プロジェクトサイト
details.repository_site=リポジトリサイト
details.documentation_site=ドキュメンテーションサイト
details.license=ライセンス details.license=ライセンス
assets=アセット assets=アセット
versions=バージョン versions=バージョン
@ -3104,6 +3151,8 @@ versions.on=on
versions.view_all=すべて表示 versions.view_all=すべて表示
dependency.id=ID dependency.id=ID
dependency.version=バージョン dependency.version=バージョン
cargo.details.repository_site=リポジトリサイト
cargo.details.documentation_site=ドキュメンテーションサイト
chef.install=パッケージをインストールするには、次のコマンドを実行します: chef.install=パッケージをインストールするには、次のコマンドを実行します:
composer.registry=あなたの <code>~/.composer/config.json</code> ファイルに、このレジストリをセットアップします: composer.registry=あなたの <code>~/.composer/config.json</code> ファイルに、このレジストリをセットアップします:
composer.install=Composer を使用してパッケージをインストールするには、次のコマンドを実行します: composer.install=Composer を使用してパッケージをインストールするには、次のコマンドを実行します:
@ -3114,6 +3163,11 @@ conan.details.repository=リポジトリ
conan.registry=このレジストリをコマンドラインからセットアップします: conan.registry=このレジストリをコマンドラインからセットアップします:
conan.install=Conan を使用してパッケージをインストールするには、次のコマンドを実行します: conan.install=Conan を使用してパッケージをインストールするには、次のコマンドを実行します:
conan.documentation=Conan レジストリの詳細については、 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">ドキュメント</a> を参照してください。 conan.documentation=Conan レジストリの詳細については、 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">ドキュメント</a> を参照してください。
conda.registry=あなたの <code>.condarc</code> ファイルに、このレジストリを Conda リポジトリとしてセットアップします:
conda.install=Conda を使用してパッケージをインストールするには、次のコマンドを実行します:
conda.documentation=Condaレジストリの詳細については、 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">ドキュメント</a> を参照してください。
conda.details.repository_site=リポジトリサイト
conda.details.documentation_site=ドキュメンテーションサイト
container.details.type=イメージタイプ container.details.type=イメージタイプ
container.details.platform=プラットフォーム container.details.platform=プラットフォーム
container.pull=コマンドラインでイメージを取得します: container.pull=コマンドラインでイメージを取得します:
@ -3172,26 +3226,91 @@ settings.delete.description=パッケージの削除は恒久的で元に戻す
settings.delete.notice=%s (%s) を削除しようとしています。この操作は元に戻せません。よろしいですか? settings.delete.notice=%s (%s) を削除しようとしています。この操作は元に戻せません。よろしいですか?
settings.delete.success=パッケージを削除しました。 settings.delete.success=パッケージを削除しました。
settings.delete.error=パッケージの削除に失敗しました。 settings.delete.error=パッケージの削除に失敗しました。
owner.settings.cleanuprules.title=クリーンアップルールの管理
owner.settings.cleanuprules.add=クリーンアップルールを追加
owner.settings.cleanuprules.edit=クリーンアップルールを編集
owner.settings.cleanuprules.none=クリーンアップルールはありません。詳細はドキュメントをご覧ください。
owner.settings.cleanuprules.preview=クリーンアップルールをプレビュー
owner.settings.cleanuprules.preview.overview=%d パッケージが削除される予定です。
owner.settings.cleanuprules.preview.none=クリーンアップルールと一致するパッケージがありません。
owner.settings.cleanuprules.enabled=有効 owner.settings.cleanuprules.enabled=有効
owner.settings.cleanuprules.success.update=クリーンアップルールが更新されました。
owner.settings.cleanuprules.success.delete=クリーンアップルールが削除されました。
owner.settings.chef.title=Chefレジストリ
owner.settings.chef.keypair=キーペアを生成
owner.settings.chef.keypair.description=Chefレジストリの認証に使用するキーペアを生成します。 それ以降は、以前のキーは使用できなくなります。
[secrets] [secrets]
secrets=シークレット
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
none=まだシークレットはありません。
value= value=
name=名称 name=名称
creation=シークレットを追加
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
creation.success=シークレット '%s' を追加しました。
creation.failed=シークレットの追加に失敗しました。
deletion=シークレットの削除
deletion.description=シークレットの削除は恒久的で元に戻すことはできません。 続行しますか?
deletion.success=シークレットを削除しました。
deletion.failed=シークレットの削除に失敗しました。
[actions] [actions]
actions=Actions
unit.desc=Actionsの管理
status.unknown=不明
status.waiting=待機中
status.running=実行中
status.success=成功
status.failure=失敗
status.cancelled=キャンセルされた
status.skipped=スキップ
status.blocked=ブロックされた
runners=ランナー
runners.runner_manage_panel=ランナーの管理
runners.new=新しいランナーを作成
runners.new_notice=ランナーの開始方法
runners.status=ステータス
runners.id=ID runners.id=ID
runners.name=名称 runners.name=名称
runners.owner_type=タイプ runners.owner_type=タイプ
runners.description=説明 runners.description=説明
runners.labels=ラベル runners.labels=ラベル
runners.last_online=最終オンライン時刻
runners.agent_labels=エージェントのラベル
runners.custom_labels=カスタムラベル
runners.custom_labels_helper=カスタムラベルは管理者により手動で追加されたラベルです。 ラベルはカンマで区切り、各ラベルの前後の空白は無視されます。
runners.runner_title=ランナー
runners.task_list=このランナーの最近のタスク
runners.task_list.run=実行 runners.task_list.run=実行
runners.task_list.status=ステータス
runners.task_list.repository=リポジトリ runners.task_list.repository=リポジトリ
runners.task_list.commit=コミット runners.task_list.commit=コミット
runners.status.active=有効 runners.task_list.done_at=終了時刻
runners.edit_runner=ランナーの編集
runners.update_runner=変更を保存
runners.update_runner_success=ランナーを更新しました
runners.update_runner_failed=ランナーの更新に失敗しました
runners.delete_runner=このランナーを削除
runners.delete_runner_success=ランナーを削除しました
runners.delete_runner_failed=ランナーの削除に失敗しました
runners.delete_runner_header=ランナー削除の確認
runners.delete_runner_notice=このランナーでタスクが実行されている場合、タスクは停止され失敗扱いとなります。 それによりビルドワークフローが途中で終了することになるかもしれません。
runners.none=利用可能なランナーはありません
runners.status.unspecified=不明
runners.status.idle=アイドル
runners.status.active=稼働中
runners.status.offline=オフライン
runs.all_workflows=すべてのワークフロー
runs.open_tab=%d オープン
runs.closed_tab=%d クローズ
runs.commit=コミット runs.commit=コミット
runs.pushed_by=Pushed by
need_approval_desc=フォークプルリクエストのワークフローを実行するには承認が必要です。

View File

@ -112,7 +112,9 @@ never=Nunca
rss_feed=Feed RSS rss_feed=Feed RSS
[aria] [aria]
navbar=Barra de navegação
footer=Rodapé footer=Rodapé
footer.software=Sobre o Software
footer.links=Links footer.links=Links
[filter] [filter]
@ -325,6 +327,7 @@ email_not_associate=O endereço de e-mail não está associado à nenhuma conta.
send_reset_mail=Enviar e-mail de recuperação de conta send_reset_mail=Enviar e-mail de recuperação de conta
reset_password=Recuperação de conta reset_password=Recuperação de conta
invalid_code=Seu código de confirmação é inválido ou expirou. invalid_code=Seu código de confirmação é inválido ou expirou.
invalid_password=Sua senha não coincide com a senha que foi usada para criar a conta.
reset_password_helper=Recuperar conta reset_password_helper=Recuperar conta
reset_password_wrong_user=Você está conectado como %s, mas o link de recuperação de conta é para %s reset_password_wrong_user=Você está conectado como %s, mas o link de recuperação de conta é para %s
password_too_short=A senha deve ter %d ou mais caracteres. password_too_short=A senha deve ter %d ou mais caracteres.
@ -472,6 +475,8 @@ url_error=`'%s' não é uma URL válida.`
include_error=` deve conter '%s'.` include_error=` deve conter '%s'.`
glob_pattern_error=` padrão glob é inválido: %s.` glob_pattern_error=` padrão glob é inválido: %s.`
regex_pattern_error=` o regex é inválido: %s.` regex_pattern_error=` o regex é inválido: %s.`
username_error=` só pode conter caracteres alfanuméricos ('0-9','a-z','A-Z'), traço ('-'), sublinhado ('_') e ponto ('.'). Não pode começar ou terminar com caracteres não alfanuméricos, e caracteres não-alfanuméricos consecutivos também são proibidos.`
invalid_group_team_map_error=` mapeamento é inválido: %s`
unknown_error=Erro desconhecido: unknown_error=Erro desconhecido:
captcha_incorrect=O código CAPTCHA está incorreto. captcha_incorrect=O código CAPTCHA está incorreto.
password_not_match=As senhas não coincidem. password_not_match=As senhas não coincidem.
@ -507,6 +512,8 @@ user_not_exist=O usuário não existe.
team_not_exist=A equipe não existe. team_not_exist=A equipe não existe.
last_org_owner=Você não pode remover o último usuário do time 'proprietários'. Deve haver pelo menos um proprietário em uma organização. last_org_owner=Você não pode remover o último usuário do time 'proprietários'. Deve haver pelo menos um proprietário em uma organização.
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipe. cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipe.
duplicate_invite_to_team=O usuário já foi convidado para se juntar da equipe.
organization_leave_success=Você saiu da organização %s com sucesso.
invalid_ssh_key=Não é possível verificar sua chave SSH: %s invalid_ssh_key=Não é possível verificar sua chave SSH: %s
invalid_gpg_key=Não é possível verificar sua chave GPG: %s invalid_gpg_key=Não é possível verificar sua chave GPG: %s
@ -748,6 +755,7 @@ access_token_deletion_cancel_action=Cancelar
access_token_deletion_confirm_action=Excluir access_token_deletion_confirm_action=Excluir
access_token_deletion_desc=A exclusão de um token revoga o acesso à sua conta para aplicativos que o usam. Continuar? access_token_deletion_desc=A exclusão de um token revoga o acesso à sua conta para aplicativos que o usam. Continuar?
delete_token_success=O token foi excluído. Os aplicativos que o utilizam já não têm acesso à sua conta. delete_token_success=O token foi excluído. Os aplicativos que o utilizam já não têm acesso à sua conta.
select_scopes=Selecione os escopos
scopes_list=Escopos: scopes_list=Escopos:
manage_oauth2_applications=Gerenciar aplicativos OAuth2 manage_oauth2_applications=Gerenciar aplicativos OAuth2
@ -1020,10 +1028,12 @@ unstar=Retirar dos favoritos
star=Juntar aos favoritos star=Juntar aos favoritos
fork=Fork fork=Fork
download_archive=Baixar repositório download_archive=Baixar repositório
more_operations=Mais Operações
no_desc=Nenhuma descrição no_desc=Nenhuma descrição
quick_guide=Guia Rápido quick_guide=Guia Rápido
clone_this_repo=Clonar este repositório clone_this_repo=Clonar este repositório
cite_this_repo=Citar este repositório
create_new_repo_command=Criando um novo repositório por linha de comando create_new_repo_command=Criando um novo repositório por linha de comando
push_exist_repo=Realizando push para um repositório existente por linha de comando push_exist_repo=Realizando push para um repositório existente por linha de comando
empty_message=Este repositório está vazio. empty_message=Este repositório está vazio.
@ -1122,6 +1132,7 @@ editor.commit_directly_to_this_branch=Commit diretamente no branch <strong class
editor.create_new_branch=Crie um <strong>novo branch</strong> para este commit e crie um pull request. editor.create_new_branch=Crie um <strong>novo branch</strong> para este commit e crie um pull request.
editor.create_new_branch_np=Crie um <strong>novo branch</strong> para este commit. editor.create_new_branch_np=Crie um <strong>novo branch</strong> para este commit.
editor.propose_file_change=Propor alteração de arquivo editor.propose_file_change=Propor alteração de arquivo
editor.new_branch_name=Nome do novo branch para este commit
editor.new_branch_name_desc=Novo nome do branch... editor.new_branch_name_desc=Novo nome do branch...
editor.cancel=Cancelar editor.cancel=Cancelar
editor.filename_cannot_be_empty=Nome do arquivo não pode ser em branco. editor.filename_cannot_be_empty=Nome do arquivo não pode ser em branco.
@ -1206,13 +1217,21 @@ projects.type.bug_triage=Triagem de Bugs
projects.template.desc=Modelo de projeto projects.template.desc=Modelo de projeto
projects.template.desc_helper=Selecione um modelo de projeto para começar projects.template.desc_helper=Selecione um modelo de projeto para começar
projects.type.uncategorized=Sem categoria projects.type.uncategorized=Sem categoria
projects.column.edit=Editar coluna
projects.column.edit_title=Nome projects.column.edit_title=Nome
projects.column.new_title=Nome projects.column.new_title=Nome
projects.column.new_submit=Criar coluna
projects.column.new=Nova Coluna projects.column.new=Nova Coluna
projects.column.set_default=Definir padrão
projects.column.set_default_desc=Definir esta coluna como padrão para pull e issues sem categoria
projects.column.delete=Excluir coluna projects.column.delete=Excluir coluna
projects.column.deletion_desc=Excluir uma coluna do projeto move todas as issues relacionadas para 'Sem categoria'. Continuar?
projects.column.color=Colorido projects.column.color=Colorido
projects.open=Abrir projects.open=Abrir
projects.close=Fechar projects.close=Fechar
projects.column.assigned_to=Atribuído a
projects.card_type.images_and_text=Imagens e Texto
projects.card_type.text_only=Somente texto
issues.desc=Organize relatórios de bugs, tarefas e marcos. issues.desc=Organize relatórios de bugs, tarefas e marcos.
issues.filter_assignees=Filtrar Atribuição issues.filter_assignees=Filtrar Atribuição
@ -1289,6 +1308,7 @@ issues.filter_label_no_select=Todas as etiquetas
issues.filter_milestone=Marco issues.filter_milestone=Marco
issues.filter_milestone_no_select=Todos os marcos issues.filter_milestone_no_select=Todos os marcos
issues.filter_project=Projeto issues.filter_project=Projeto
issues.filter_project_all=Todos os projetos
issues.filter_project_none=Sem projeto issues.filter_project_none=Sem projeto
issues.filter_assignee=Atribuído issues.filter_assignee=Atribuído
issues.filter_assginee_no_select=Todos os responsáveis issues.filter_assginee_no_select=Todos os responsáveis
@ -1300,6 +1320,7 @@ issues.filter_type.assigned_to_you=Atribuídos a você
issues.filter_type.created_by_you=Criado por você issues.filter_type.created_by_you=Criado por você
issues.filter_type.mentioning_you=Mencionando você issues.filter_type.mentioning_you=Mencionando você
issues.filter_type.review_requested=Revisão solicitada issues.filter_type.review_requested=Revisão solicitada
issues.filter_type.reviewed_by_you=Revisado por você
issues.filter_sort=Ordenação issues.filter_sort=Ordenação
issues.filter_sort.latest=Mais recentes issues.filter_sort.latest=Mais recentes
issues.filter_sort.oldest=Mais antigos issues.filter_sort.oldest=Mais antigos
@ -1374,6 +1395,7 @@ issues.save=Salvar
issues.label_title=Nome da etiqueta issues.label_title=Nome da etiqueta
issues.label_description=Descrição da etiqueta issues.label_description=Descrição da etiqueta
issues.label_color=Cor da etiqueta issues.label_color=Cor da etiqueta
issues.label_exclusive=Exclusivo
issues.label_count=%d etiquetas issues.label_count=%d etiquetas
issues.label_open_issues=%d issues abertas issues.label_open_issues=%d issues abertas
issues.label_edit=Editar issues.label_edit=Editar
@ -1627,6 +1649,7 @@ pulls.reopened_at=`reabriu este pull request <a id="%[1]s" href="#%[1]s">%[2]s</
pulls.merge_instruction_hint=`Você também pode ver as <a class="show-instruction">instruções para a linha de comandos</a>.` pulls.merge_instruction_hint=`Você também pode ver as <a class="show-instruction">instruções para a linha de comandos</a>.`
pulls.merge_instruction_step1_desc=No repositório do seu projeto, crie um novo branch e teste as alterações. pulls.merge_instruction_step1_desc=No repositório do seu projeto, crie um novo branch e teste as alterações.
pulls.merge_instruction_step2_desc=Faça merge das alterações e atualize no Gitea. pulls.merge_instruction_step2_desc=Faça merge das alterações e atualize no Gitea.
pulls.clear_merge_message=Limpar mensagem do merge
pulls.auto_merge_button_when_succeed=(Quando a verificação for bem-sucedida) pulls.auto_merge_button_when_succeed=(Quando a verificação for bem-sucedida)
pulls.auto_merge_when_succeed=Mesclar automaticamente quando todas as verificações forem bem sucedidas pulls.auto_merge_when_succeed=Mesclar automaticamente quando todas as verificações forem bem sucedidas
@ -1817,6 +1840,7 @@ settings.mirror_sync_in_progress=Sincronização do espelhamento está em andame
settings.site=Site settings.site=Site
settings.update_settings=Atualizar configurações settings.update_settings=Atualizar configurações
settings.branches.update_default_branch=Atualizar Branch Padrão settings.branches.update_default_branch=Atualizar Branch Padrão
settings.branches.add_new_rule=Adicionar Nova Regra
settings.advanced_settings=Configurações avançadas settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Habilitar a wiki do repositório settings.wiki_desc=Habilitar a wiki do repositório
settings.use_internal_wiki=Usar a wiki nativa settings.use_internal_wiki=Usar a wiki nativa
@ -1846,8 +1870,11 @@ settings.pulls.ignore_whitespace=Ignorar espaço em branco em conflitos
settings.pulls.enable_autodetect_manual_merge=Habilitar a detecção automática de merge manual (Nota: Em alguns casos especiais, podem ocorrer julgamentos errados) settings.pulls.enable_autodetect_manual_merge=Habilitar a detecção automática de merge manual (Nota: Em alguns casos especiais, podem ocorrer julgamentos errados)
settings.pulls.allow_rebase_update=Ativar atualização do branch do pull request por rebase settings.pulls.allow_rebase_update=Ativar atualização do branch do pull request por rebase
settings.pulls.default_delete_branch_after_merge=Excluir o branch de pull request após o merge por padrão settings.pulls.default_delete_branch_after_merge=Excluir o branch de pull request após o merge por padrão
settings.pulls.default_allow_edits_from_maintainers=Permitir edições de mantenedores por padrão
settings.releases_desc=Habilitar versões do Repositório
settings.packages_desc=Habilitar Registro de Pacotes de Repositório settings.packages_desc=Habilitar Registro de Pacotes de Repositório
settings.projects_desc=Habilitar Projetos do Repositório settings.projects_desc=Habilitar Projetos do Repositório
settings.actions_desc=Habilitar ações do repositório
settings.admin_settings=Configurações do administrador settings.admin_settings=Configurações do administrador
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
settings.admin_code_indexer=Indexador de código settings.admin_code_indexer=Indexador de código
@ -2056,6 +2083,8 @@ settings.deploy_key_deletion_desc=A exclusão de uma chave de deploy irá revoga
settings.deploy_key_deletion_success=A chave de deploy foi removida. settings.deploy_key_deletion_success=A chave de deploy foi removida.
settings.branches=Branches settings.branches=Branches
settings.protected_branch=Proteção de Branch settings.protected_branch=Proteção de Branch
settings.protected_branch.save_rule=Salvar Regra
settings.protected_branch.delete_rule=Excluir Regra
settings.protected_branch_can_push=Permitir push? settings.protected_branch_can_push=Permitir push?
settings.protected_branch_can_push_yes=Você pode fazer push settings.protected_branch_can_push_yes=Você pode fazer push
settings.protected_branch_can_push_no=Você não pode fazer push settings.protected_branch_can_push_no=Você não pode fazer push
@ -2107,6 +2136,7 @@ settings.block_on_official_review_requests_desc=O merge não será possível qua
settings.block_outdated_branch=Bloquear o merge se o pull request estiver desatualizado settings.block_outdated_branch=Bloquear o merge se o pull request estiver desatualizado
settings.block_outdated_branch_desc=O merge não será possível quando o branch de topo estiver atrás do branch base. settings.block_outdated_branch_desc=O merge não será possível quando o branch de topo estiver atrás do branch base.
settings.default_branch_desc=Selecione um branch padrão para pull requests e commits de código: settings.default_branch_desc=Selecione um branch padrão para pull requests e commits de código:
settings.merge_style_desc=Estilos de Merge
settings.default_merge_style_desc=Estilo de merge padrão para pull requests: settings.default_merge_style_desc=Estilo de merge padrão para pull requests:
settings.choose_branch=Escolha um branch... settings.choose_branch=Escolha um branch...
settings.no_protected_branch=Não há branches protegidos. settings.no_protected_branch=Não há branches protegidos.
@ -2673,6 +2703,7 @@ auths.admin_filter=Filtro de administrador
auths.restricted_filter=Filtro de restrição auths.restricted_filter=Filtro de restrição
auths.restricted_filter_helper=Deixe em branco para não definir nenhum usuário como restrito. Use um asterisco ('*') para definir todos os usuários que não correspondem ao Filtro de administrador como restritos. auths.restricted_filter_helper=Deixe em branco para não definir nenhum usuário como restrito. Use um asterisco ('*') para definir todos os usuários que não correspondem ao Filtro de administrador como restritos.
auths.verify_group_membership=Verificar associação ao grupo no LDAP (deixe o filtro vazio para ignorar) auths.verify_group_membership=Verificar associação ao grupo no LDAP (deixe o filtro vazio para ignorar)
auths.group_search_base=Grupo de Pesquisa DN Base
auths.group_attribute_list_users=Atributo do Grupo que Contém a Lista de Usuários auths.group_attribute_list_users=Atributo do Grupo que Contém a Lista de Usuários
auths.user_attribute_in_group=Atributo do Usuário Listado em Grupo auths.user_attribute_in_group=Atributo do Usuário Listado em Grupo
auths.map_group_to_team=Mapear grupos LDAP para Organizações (deixe o campo vazio para pular) auths.map_group_to_team=Mapear grupos LDAP para Organizações (deixe o campo vazio para pular)
@ -3099,6 +3130,8 @@ keywords=Palavras-chave
details=Detalhes details=Detalhes
details.author=Autor details.author=Autor
details.project_site=Site do Projeto details.project_site=Site do Projeto
details.repository_site=Site do Repositório
details.documentation_site=Site da Documentação
details.license=Licença details.license=Licença
assets=Recursos assets=Recursos
versions=Versões versions=Versões
@ -3106,6 +3139,11 @@ versions.on=em
versions.view_all=Ver todas versions.view_all=Ver todas
dependency.id=ID dependency.id=ID
dependency.version=Versão dependency.version=Versão
cargo.registry=Configurar este registro no arquivo de configuração de Cargo (por exemplo <code>~/.cargo/config.toml</code>):
cargo.install=Para instalar o pacote usando Cargo, execute o seguinte comando:
cargo.details.repository_site=Site do Repositório
cargo.details.documentation_site=Site da Documentação
chef.registry=Configure este registro em seu arquivo <code>~/.chef/config.rb</code>:
chef.install=Para instalar o pacote, execute o seguinte comando: chef.install=Para instalar o pacote, execute o seguinte comando:
composer.registry=Configure este registro em seu arquivo <code>~/.composer/config.json</code>: composer.registry=Configure este registro em seu arquivo <code>~/.composer/config.json</code>:
composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando: composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando:
@ -3116,6 +3154,11 @@ conan.details.repository=Repositório
conan.registry=Configure este registro pela linha de comando: conan.registry=Configure este registro pela linha de comando:
conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando: conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando:
conan.documentation=Para obter mais informações sobre o registro Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">a documentação</a>. conan.documentation=Para obter mais informações sobre o registro Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">a documentação</a>.
conda.registry=Configure este registro como um repositório Conda no arquivo <code>.condarc</code>:
conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando:
conda.documentation=Para obter mais informações sobre o registro Conda, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">a documentação</a>.
conda.details.repository_site=Site do Repositório
conda.details.documentation_site=Site da Documentação
container.details.type=Tipo de Imagem container.details.type=Tipo de Imagem
container.details.platform=Plataforma container.details.platform=Plataforma
container.pull=Puxe a imagem pela linha de comando: container.pull=Puxe a imagem pela linha de comando:
@ -3174,26 +3217,78 @@ settings.delete.description=A exclusão de um pacote é permanente e não pode s
settings.delete.notice=Você está prestes a excluir %s (%s). Esta operação é irreversível, tem certeza? settings.delete.notice=Você está prestes a excluir %s (%s). Esta operação é irreversível, tem certeza?
settings.delete.success=O pacote foi excluído. settings.delete.success=O pacote foi excluído.
settings.delete.error=Falha ao excluir o pacote. settings.delete.error=Falha ao excluir o pacote.
owner.settings.cleanuprules.title=Gerenciar Regras de Limpeza
owner.settings.cleanuprules.add=Adicionar Regra de Limpeza
owner.settings.cleanuprules.edit=Editar Regra de Limpeza
owner.settings.cleanuprules.none=Não há regras de limpeza disponíveis. Leia a documentação para saber mais.
owner.settings.cleanuprules.preview=Pré-visualizar Regra de Limpeza
owner.settings.cleanuprules.preview.overview=%d pacotes agendados para serem removidos.
owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote.
owner.settings.cleanuprules.enabled=Habilitado owner.settings.cleanuprules.enabled=Habilitado
owner.settings.cleanuprules.keep.title=Versões que correspondem a estas regras são mantidas, mesmo se corresponderem a uma regra de remoção abaixo.
owner.settings.cleanuprules.keep.count=Manter o mais recente
owner.settings.cleanuprules.keep.count.1=1 versão por pacote
owner.settings.cleanuprules.keep.count.n=%d versões por pacote
owner.settings.cleanuprules.keep.pattern=Manter versões correspondentes
owner.settings.cleanuprules.keep.pattern.container=A versão <code>latest</code> é sempre mantida para pacotes de Container.
owner.settings.cleanuprules.remove.title=Versões que correspondem a essas regras são removidas, a menos que uma regra acima diga para mantê-las.
owner.settings.cleanuprules.remove.days=Remover versões mais antigas que
owner.settings.cleanuprules.remove.pattern=Remover versões correspondentes
owner.settings.cleanuprules.success.update=Regra de limpeza foi atualizada.
owner.settings.cleanuprules.success.delete=Regra de limpeza foi excluída.
owner.settings.chef.title=Registro Chef
owner.settings.chef.keypair=Gerar par de chaves
[secrets] [secrets]
secrets=Segredos
description=Os segredos serão passados a certas ações e não poderão ser lidos de outra forma.
none=Não há segredos ainda.
value=Valor value=Valor
name=Nome name=Nome
creation=Adicionar Segredo
creation.success=O segredo '%s' foi adicionado.
creation.failed=Falha ao adicionar segredo.
deletion=Excluir segredo
deletion.description=A exclusão de um segredo é permanente e não pode ser desfeita. Continuar?
deletion.success=O segredo foi excluído.
deletion.failed=Falha ao excluir segredo.
[actions] [actions]
actions=Ações
unit.desc=Gerenciar ações
status.unknown=Desconhecido
status.waiting=Em espera
status.running=Rodando
status.success=Sucesso
status.failure=Falha
status.cancelled=Cancelado
status.skipped=Ignorado
status.blocked=Bloqueado
runners.status=Status
runners.id=ID runners.id=ID
runners.name=Nome runners.name=Nome
runners.owner_type=Tipo runners.owner_type=Tipo
runners.description=Descrição runners.description=Descrição
runners.labels=Rótulos runners.labels=Rótulos
runners.last_online=Última Vez Online
runners.custom_labels=Etiquetas Personalizadas
runners.custom_labels_helper=Etiquetas personalizadas são etiquetas que são adicionadas manualmente por um administrador. Separe as etiquetas com vírgula. Espaço em branco no começo ou no final de cada etiqueta é ignorado.
runners.task_list.run=Executar runners.task_list.run=Executar
runners.task_list.status=Status
runners.task_list.repository=Repositório runners.task_list.repository=Repositório
runners.task_list.commit=Commit runners.task_list.commit=Commit
runners.update_runner=Atualizar as Alterações
runners.status.unspecified=Desconhecido
runners.status.idle=Inativo
runners.status.active=Ativo runners.status.active=Ativo
runners.status.offline=Offiline
runs.open_tab=%d Aberto
runs.closed_tab=%d Fechado
runs.commit=Commit runs.commit=Commit
runs.pushed_by=Push realizado por

View File

@ -95,6 +95,7 @@ copy_content=Copiar conteúdo
copy_branch=Copiar nome do ramo copy_branch=Copiar nome do ramo
copy_success=Copiado! copy_success=Copiado!
copy_error=Falha ao copiar copy_error=Falha ao copiar
copy_type_unsupported=Este tipo de ficheiro não pode ser copiado
write=Escrever write=Escrever
preview=Pré-visualizar preview=Pré-visualizar
@ -327,6 +328,7 @@ email_not_associate=O endereço de email não está associado a qualquer conta.
send_reset_mail=Enviar email de recuperação da conta send_reset_mail=Enviar email de recuperação da conta
reset_password=Recuperação de conta reset_password=Recuperação de conta
invalid_code=O seu código de confirmação é inválido ou expirou. invalid_code=O seu código de confirmação é inválido ou expirou.
invalid_password=A sua senha não corresponde à senha que foi usada para criar a conta.
reset_password_helper=Recuperar conta reset_password_helper=Recuperar conta
reset_password_wrong_user=Tem conta iniciada como %s, mas a ligação de recuperação de conta é para %s reset_password_wrong_user=Tem conta iniciada como %s, mas a ligação de recuperação de conta é para %s
password_too_short=O tamanho da senha não pode ser inferior a %d caracteres. password_too_short=O tamanho da senha não pode ser inferior a %d caracteres.
@ -2091,6 +2093,8 @@ settings.deploy_key_deletion_desc=Remover uma chave de instalação irá revogar
settings.deploy_key_deletion_success=A chave de instalação foi removida. settings.deploy_key_deletion_success=A chave de instalação foi removida.
settings.branches=Ramos settings.branches=Ramos
settings.protected_branch=Salvaguarda do ramo settings.protected_branch=Salvaguarda do ramo
settings.protected_branch.save_rule=Guardar regra
settings.protected_branch.delete_rule=Eliminar regra
settings.protected_branch_can_push=Permitir envios? settings.protected_branch_can_push=Permitir envios?
settings.protected_branch_can_push_yes=Pode enviar settings.protected_branch_can_push_yes=Pode enviar
settings.protected_branch_can_push_no=Não pode enviar settings.protected_branch_can_push_no=Não pode enviar
@ -2125,6 +2129,7 @@ settings.dismiss_stale_approvals=Descartar aprovações obsoletas
settings.dismiss_stale_approvals_desc=Quando novos cometimentos que mudam o conteúdo do pedido de integração forem enviados para o ramo, as aprovações antigas serão descartadas. settings.dismiss_stale_approvals_desc=Quando novos cometimentos que mudam o conteúdo do pedido de integração forem enviados para o ramo, as aprovações antigas serão descartadas.
settings.require_signed_commits=Exigir cometimentos assinados settings.require_signed_commits=Exigir cometimentos assinados
settings.require_signed_commits_desc=Rejeitar envios para este ramo que não estejam assinados ou que não sejam validáveis. settings.require_signed_commits_desc=Rejeitar envios para este ramo que não estejam assinados ou que não sejam validáveis.
settings.protect_branch_name_pattern=Padrão do nome do ramo protegido
settings.protect_protected_file_patterns=Padrões de ficheiros protegidos (separados com ponto e vírgula '\;'): settings.protect_protected_file_patterns=Padrões de ficheiros protegidos (separados com ponto e vírgula '\;'):
settings.protect_protected_file_patterns_desc=Ficheiros protegidos que não podem ser modificados, mesmo que o utilizador tenha direitos para adicionar, editar ou eliminar ficheiros neste ramo. Múltiplos padrões podem ser separados com ponto e vírgula ('\;'). Veja a documentação em <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>. settings.protect_protected_file_patterns_desc=Ficheiros protegidos que não podem ser modificados, mesmo que o utilizador tenha direitos para adicionar, editar ou eliminar ficheiros neste ramo. Múltiplos padrões podem ser separados com ponto e vírgula ('\;'). Veja a documentação em <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=Padrões de ficheiros desprotegidos (separados com ponto e vírgula '\;'): settings.protect_unprotected_file_patterns=Padrões de ficheiros desprotegidos (separados com ponto e vírgula '\;'):
@ -2133,6 +2138,7 @@ settings.add_protected_branch=Habilitar salvaguarda
settings.delete_protected_branch=Desabilitar salvaguarda settings.delete_protected_branch=Desabilitar salvaguarda
settings.update_protect_branch_success=A salvaguarda do ramo '%s' foi modificada. settings.update_protect_branch_success=A salvaguarda do ramo '%s' foi modificada.
settings.remove_protected_branch_success=A salvaguarda do ramo '%s' foi desabilitada. settings.remove_protected_branch_success=A salvaguarda do ramo '%s' foi desabilitada.
settings.remove_protected_branch_failed=A remoção da regra '%s' de salvaguarda do ramo falhou.
settings.protected_branch_deletion=Desabilitar salvaguarda do ramo settings.protected_branch_deletion=Desabilitar salvaguarda do ramo
settings.protected_branch_deletion_desc=Desabilitar a salvaguarda do ramo irá permitir que os utilizadores que tenham permissão de escrita enviem para o ramo. Quer continuar? settings.protected_branch_deletion_desc=Desabilitar a salvaguarda do ramo irá permitir que os utilizadores que tenham permissão de escrita enviem para o ramo. Quer continuar?
settings.block_rejected_reviews=Bloquear a integração quando há revisões rejeitadas settings.block_rejected_reviews=Bloquear a integração quando há revisões rejeitadas
@ -2142,10 +2148,13 @@ settings.block_on_official_review_requests_desc=A integração não será possí
settings.block_outdated_branch=Bloquear integração se o pedido de integração for obsoleto settings.block_outdated_branch=Bloquear integração se o pedido de integração for obsoleto
settings.block_outdated_branch_desc=A integração não será possível quando o ramo de topo estiver abaixo do ramo base. settings.block_outdated_branch_desc=A integração não será possível quando o ramo de topo estiver abaixo do ramo base.
settings.default_branch_desc=Escolha um ramo do repositório como sendo o predefinido para pedidos de integração e cometimentos: settings.default_branch_desc=Escolha um ramo do repositório como sendo o predefinido para pedidos de integração e cometimentos:
settings.merge_style_desc=Estilos de integração
settings.default_merge_style_desc=Tipo de integração predefinido para pedidos de integração: settings.default_merge_style_desc=Tipo de integração predefinido para pedidos de integração:
settings.choose_branch=Escolha um ramo… settings.choose_branch=Escolha um ramo…
settings.no_protected_branch=Não existem ramos protegidos. settings.no_protected_branch=Não existem ramos protegidos.
settings.edit_protected_branch=Editar settings.edit_protected_branch=Editar
settings.protected_branch_required_rule_name=Nome de regra obrigatório
settings.protected_branch_duplicate_rule_name=Nome de regra duplicado
settings.protected_branch_required_approvals_min=O número mínimo exigido de aprovações não pode ser negativo. settings.protected_branch_required_approvals_min=O número mínimo exigido de aprovações não pode ser negativo.
settings.tags=Etiquetas settings.tags=Etiquetas
settings.tags.protection=Proteger etiquetas settings.tags.protection=Proteger etiquetas
@ -2301,6 +2310,8 @@ release.downloads=Descargas
release.download_count=Descargas: %s release.download_count=Descargas: %s
release.add_tag_msg=Usar o título e o conteúdo do lançamento como mensagem da etiqueta. release.add_tag_msg=Usar o título e o conteúdo do lançamento como mensagem da etiqueta.
release.add_tag=Criar apenas a etiqueta release.add_tag=Criar apenas a etiqueta
release.releases_for=Lançamentos para %s
release.tags_for=Etiquetas para %s
branch.name=Nome do ramo branch.name=Nome do ramo
branch.search=Procurar ramos branch.search=Procurar ramos
@ -2568,6 +2579,10 @@ dashboard.delete_old_actions=Eliminar todas as operações antigas da base de da
dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todas as operações antigas da base de dados. dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todas as operações antigas da base de dados.
dashboard.update_checker=Verificador de novas versões dashboard.update_checker=Verificador de novas versões
dashboard.delete_old_system_notices=Eliminar todas as notificações do sistema antigas da base de dados dashboard.delete_old_system_notices=Eliminar todas as notificações do sistema antigas da base de dados
dashboard.gc_lfs=Recolher lixo dos meta-elementos LFS
dashboard.stop_zombie_tasks=Parar tarefas zombies
dashboard.stop_endless_tasks=Parar tarefas intermináveis
dashboard.cancel_abandoned_jobs=Cancelar trabalhos abandonados
users.user_manage_panel=Gestão das contas de utilizadores users.user_manage_panel=Gestão das contas de utilizadores
users.new_account=Criar conta de utilizador users.new_account=Criar conta de utilizador
@ -2656,6 +2671,7 @@ repos.size=Tamanho
packages.package_manage_panel=Gestão de pacotes packages.package_manage_panel=Gestão de pacotes
packages.total_size=Tamanho total: %s packages.total_size=Tamanho total: %s
packages.unreferenced_size=Tamanho não referenciado: %s
packages.owner=Proprietário packages.owner=Proprietário
packages.creator=Criador packages.creator=Criador
packages.name=Nome packages.name=Nome
@ -2749,6 +2765,8 @@ auths.oauth2_required_claim_value_helper=Defina este valor para restringir o in
auths.oauth2_group_claim_name=Reivindicar nome que fornece nomes de grupo para esta fonte. (Opcional) auths.oauth2_group_claim_name=Reivindicar nome que fornece nomes de grupo para esta fonte. (Opcional)
auths.oauth2_admin_group=Valor da Reivindicação de Grupo para utilizadores administradores. (Opcional - exige a reivindicação de nome acima) auths.oauth2_admin_group=Valor da Reivindicação de Grupo para utilizadores administradores. (Opcional - exige a reivindicação de nome acima)
auths.oauth2_restricted_group=Valor da Reivindicação de Grupo para utilizadores restritos. (Opcional - exige a reivindicação de nome acima) auths.oauth2_restricted_group=Valor da Reivindicação de Grupo para utilizadores restritos. (Opcional - exige a reivindicação de nome acima)
auths.oauth2_map_group_to_team=Mapear grupos reclamados em equipas da organização (opcional — requer nome de reclamação acima).
auths.oauth2_map_group_to_team_removal=Remover utilizadores das equipas sincronizadas se esses utilizadores não pertencerem ao grupo correspondente.
auths.enable_auto_register=Habilitar o registo automático auths.enable_auto_register=Habilitar o registo automático
auths.sspi_auto_create_users=Criar utilizadores automaticamente auths.sspi_auto_create_users=Criar utilizadores automaticamente
auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie, automaticamente, novas contas para utilizadores que iniciam a sessão pela primeira vez auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie, automaticamente, novas contas para utilizadores que iniciam a sessão pela primeira vez
@ -3136,6 +3154,8 @@ keywords=Palavras-chave
details=Detalhes details=Detalhes
details.author=Autor(a) details.author=Autor(a)
details.project_site=Página web do projecto details.project_site=Página web do projecto
details.repository_site=Página web do repositório
details.documentation_site=Página web da documentação
details.license=Licença details.license=Licença
assets=Recursos assets=Recursos
versions=Versões versions=Versões
@ -3143,7 +3163,14 @@ versions.on=ligado
versions.view_all=Ver todas versions.view_all=Ver todas
dependency.id=ID dependency.id=ID
dependency.version=Versão dependency.version=Versão
cargo.registry=Configurar este registo no ficheiro de configuração do Cargo (por exemplo: <code>~/.cargo/config.toml</code>):
cargo.install=Para instalar o pacote usando o Cargo, execute o seguinte comando:
cargo.documentation=Para obter mais informações sobre o registo do Cargo, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">a documentação</a>.
cargo.details.repository_site=Página web do repositório
cargo.details.documentation_site=Página web da documentação
chef.registry=Configure este registo no seu ficheiro <code>~/.chef/config.rb</code>:
chef.install=Para instalar o pacote, execute o seguinte comando: chef.install=Para instalar o pacote, execute o seguinte comando:
chef.documentation=Para obter mais informações sobre o registo do Chef, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">a documentação</a>.
composer.registry=Configure este registo no seu ficheiro <code>~/.composer/config.json</code>: composer.registry=Configure este registo no seu ficheiro <code>~/.composer/config.json</code>:
composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando: composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando:
composer.documentation=Para obter mais informações sobre o registo do Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">a documentação</a>. composer.documentation=Para obter mais informações sobre o registo do Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">a documentação</a>.
@ -3153,6 +3180,11 @@ conan.details.repository=Repositório
conan.registry=Configurar este registo usando a linha de comandos: conan.registry=Configurar este registo usando a linha de comandos:
conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando: conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando:
conan.documentation=Para obter mais informações sobre o registo do Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">a documentação</a>. conan.documentation=Para obter mais informações sobre o registo do Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">a documentação</a>.
conda.registry=Configure este registo como um repositório Conda no seu ficheiro <code>.condarc</code>:
conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando:
conda.documentation=Para obter mais informações sobre o registo do Conda, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">a documentação</a>.
conda.details.repository_site=Página web do repositório
conda.details.documentation_site=Página web da documentação
container.details.type=Tipo de imagem container.details.type=Tipo de imagem
container.details.platform=Plataforma container.details.platform=Plataforma
container.pull=Puxar a imagem usando a linha de comandos: container.pull=Puxar a imagem usando a linha de comandos:
@ -3211,7 +3243,25 @@ settings.delete.description=Eliminar o pacote é permanente e não pode ser desf
settings.delete.notice=Está prestes a eliminar %s (%s). Esta operação é irreversível. Tem a certeza? settings.delete.notice=Está prestes a eliminar %s (%s). Esta operação é irreversível. Tem a certeza?
settings.delete.success=O pacote foi eliminado. settings.delete.success=O pacote foi eliminado.
settings.delete.error=Falhou a eliminação do pacote. settings.delete.error=Falhou a eliminação do pacote.
owner.settings.cargo.title=Índice do registo do Cargo
owner.settings.cargo.initialize=Inicializar índice
owner.settings.cargo.initialize.description=Para usar o registo Cargo, é necessário um repositório git de índice especial. Aqui pode (re)criá-lo com a configuração necessária.
owner.settings.cargo.initialize.error=Falhou ao inicializar o índice do Cargo: %v
owner.settings.cargo.initialize.success=O índice do Cargo foi criado com sucesso.
owner.settings.cargo.rebuild=Reconstruir índice
owner.settings.cargo.rebuild.description=Se o índice não estiver sincronizado com os pacotes Cargo armazenados, pode reconstruí-lo aqui.
owner.settings.cargo.rebuild.error=Falhou ao reconstruir o índice do Cargo: %v
owner.settings.cargo.rebuild.success=O índice do Cargo foi reconstruído com sucesso.
owner.settings.cleanuprules.title=Gerir regras de limpeza
owner.settings.cleanuprules.add=Adicionar regra de limpeza
owner.settings.cleanuprules.edit=Editar regra de limpeza
owner.settings.cleanuprules.none=Não há regras de limpeza disponíveis. Leia a documentação para obter mais informação.
owner.settings.cleanuprules.preview=Previsão da regra de limpeza
owner.settings.cleanuprules.preview.overview=%d pacotes estão agendados para serem removidos.
owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote.
owner.settings.cleanuprules.enabled=Habilitado owner.settings.cleanuprules.enabled=Habilitado
owner.settings.cleanuprules.pattern_full_match=Aplicar o padrão ao nome completo do pacote
owner.settings.cleanuprules.keep.title=As versões que correspondem a estas regras serão mantidas, mesmo que correspondam à regra de remoção abaixo.
owner.settings.cleanuprules.keep.count=Manter a mais recente owner.settings.cleanuprules.keep.count=Manter a mais recente
owner.settings.cleanuprules.keep.count.1=1 versão por pacote owner.settings.cleanuprules.keep.count.1=1 versão por pacote
owner.settings.cleanuprules.keep.count.n=%d versões por pacote owner.settings.cleanuprules.keep.count.n=%d versões por pacote
@ -3221,24 +3271,73 @@ owner.settings.cleanuprules.remove.title=Versões que correspondam a estas regra
owner.settings.cleanuprules.remove.days=Remover versões mais antigas do que owner.settings.cleanuprules.remove.days=Remover versões mais antigas do que
owner.settings.cleanuprules.remove.pattern=Remover as versões correspondentes owner.settings.cleanuprules.remove.pattern=Remover as versões correspondentes
owner.settings.cleanuprules.success.update=A regra de limpeza foi modificada. owner.settings.cleanuprules.success.update=A regra de limpeza foi modificada.
owner.settings.cleanuprules.success.delete=A regra de limpeza foi eliminada.
owner.settings.chef.title=Registo do Chef
owner.settings.chef.keypair=Gerar par de chaves
owner.settings.chef.keypair.description=Gerar um par de chaves para se autenticar no registo do Chef. A chave anterior deixará de poder ser utilizada.
[secrets] [secrets]
secrets=Segredos
description=Os segredos serão transmitidos a certas operações e não poderão ser lidos de outra forma.
none=Ainda não há segredos.
value=Valor value=Valor
name=Nome name=Nome
creation=Adicionar segredo
creation.name_placeholder=apenas caracteres sem distinção de maiúsculas, alfanuméricos ou sublinhados, não podem começar com GITEA_ nem com GITHUB_
creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos.
creation.success=O segredo '%s' foi adicionado.
creation.failed=Falhou ao adicionar o segredo.
deletion=Remover segredo
deletion.description=Remover um segredo é permanente e não pode ser revertido. Continuar?
deletion.success=O segredo foi removido.
deletion.failed=Falhou ao remover o segredo.
[actions] [actions]
actions=Operações
unit.desc=Gerir operações
status.unknown=Desconhecido
status.waiting=Aguardando
status.running=Em execução
status.success=Sucesso
status.failure=Falha
status.cancelled=Cancelada
status.skipped=Ignorada
status.blocked=Bloqueada
runners=Executores
runners.runner_manage_panel=Gestão de executores
runners.new=Criar um novo executor
runners.new_notice=Como iniciar um executor
runners.status=Estado
runners.id=ID runners.id=ID
runners.name=Nome runners.name=Nome
runners.owner_type=Tipo runners.owner_type=Tipo
runners.description=Descrição runners.description=Descrição
runners.labels=Rótulos runners.labels=Rótulos
runners.last_online=Última vez ligado
runners.agent_labels=Rótulos do agente
runners.custom_labels=Rótulos personalizados
runners.custom_labels_helper=Rótulos personalizados são rótulos que são adicionados manualmente por um administrador. São separados por vírgulas e espaços em branco antes e após cada rótulo são ignorados.
runners.runner_title=Executor
runners.task_list=Tarefas recentes deste executor
runners.task_list.run=Executar runners.task_list.run=Executar
runners.task_list.status=Estado
runners.task_list.repository=Repositório runners.task_list.repository=Repositório
runners.task_list.commit=Cometimento runners.task_list.commit=Cometimento
runners.task_list.done_at=Feito em
runners.edit_runner=Editar executor
runners.update_runner=Guardar alterações
runners.update_runner_success=O executor foi modificado com sucesso
runners.update_runner_failed=Falhou ao modificar o executor
runners.delete_runner=Eliminar o executor runners.delete_runner=Eliminar o executor
runners.delete_runner_success=O executor foi eliminado com sucesso
runners.delete_runner_failed=Falhou ao eliminar o executor
runners.delete_runner_header=Confirme que quer eliminar este executor
runners.delete_runner_notice=Se uma tarefa estiver a correr sob este executor, será terminada e marcada como tendo falhado. Pode quebrar o fluxo de trabalho de construção.
runners.none=Não há executores disponíveis
runners.status.unspecified=Desconhecido
runners.status.idle=Parada runners.status.idle=Parada
runners.status.active=Em funcionamento runners.status.active=Em funcionamento
runners.status.offline=Desconectada runners.status.offline=Desconectada

View File

@ -258,40 +258,7 @@ view_home=访问 %s
search_repos=查找仓库… search_repos=查找仓库…
filter=其他过滤器 filter=其他过滤器
filter_by_team_repositories=按团队仓库筛选 filter_by_team_repositories=按团队仓库筛选
feed_of="%s\" 的源 feed_of=%s" 的源
show_archived=已存档
show_both_archived_unarchived=显示已存档和未存档的
show_only_archived=只显示已归档的
show_only_unarchived=只显示未存档的
show_private=私有
show_both_private_public=显示公开的和私有的
show_only_private=只显示私有的
show_only_public=只显示公开的
issues.in_your_repos=属于该用户仓库的
[explore]
repos=仓库
users=用户
organizations=组织
search=搜索
code=代码
search.type.tooltip=搜索类型
search.fuzzy=模糊
search.fuzzy.tooltip=包含近似匹配搜索词的结果
search.match=匹配
search.match.tooltip=仅包含精确匹配搜索词的结果
code_search_unavailable=当前代码搜索不可用。请与网站管理员联系。
repo_no_results=未找到匹配的仓库。
user_no_results=未找到匹配的用户。
org_no_results=未找到匹配的组织。
code_no_results=未找到与搜索字词匹配的源代码。
code_search_results=“%s” 的搜索结果是
code_last_indexed_at=最后索引于 %s
relevant_repositories_tooltip=派生的仓库,以及缺少主题、图标和描述的仓库将被隐藏。
relevant_repositories=只显示相关的仓库, <a href="
show_private=私有库 show_private=私有库

View File

@ -4,13 +4,13 @@
package org package org
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
@ -84,13 +84,12 @@ func CreateLabel(ctx *context.APIContext) {
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateLabelOption) form := web.GetForm(ctx).(*api.CreateLabelOption)
form.Color = strings.Trim(form.Color, " ") form.Color = strings.Trim(form.Color, " ")
if len(form.Color) == 6 { color, err := label.NormalizeColor(form.Color)
form.Color = "#" + form.Color if err != nil {
} ctx.Error(http.StatusUnprocessableEntity, "Color", err)
if !issues_model.LabelColorPattern.MatchString(form.Color) {
ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", form.Color))
return return
} }
form.Color = color
label := &issues_model.Label{ label := &issues_model.Label{
Name: form.Name, Name: form.Name,
@ -183,7 +182,7 @@ func EditLabel(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.EditLabelOption) form := web.GetForm(ctx).(*api.EditLabelOption)
label, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, ctx.ParamsInt64(":id")) l, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, ctx.ParamsInt64(":id"))
if err != nil { if err != nil {
if issues_model.IsErrOrgLabelNotExist(err) { if issues_model.IsErrOrgLabelNotExist(err) {
ctx.NotFound() ctx.NotFound()
@ -194,30 +193,28 @@ func EditLabel(ctx *context.APIContext) {
} }
if form.Name != nil { if form.Name != nil {
label.Name = *form.Name l.Name = *form.Name
} }
if form.Exclusive != nil { if form.Exclusive != nil {
label.Exclusive = *form.Exclusive l.Exclusive = *form.Exclusive
} }
if form.Color != nil { if form.Color != nil {
label.Color = strings.Trim(*form.Color, " ") color, err := label.NormalizeColor(*form.Color)
if len(label.Color) == 6 { if err != nil {
label.Color = "#" + label.Color ctx.Error(http.StatusUnprocessableEntity, "Color", err)
}
if !issues_model.LabelColorPattern.MatchString(label.Color) {
ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", label.Color))
return return
} }
l.Color = color
} }
if form.Description != nil { if form.Description != nil {
label.Description = *form.Description l.Description = *form.Description
} }
if err := issues_model.UpdateLabel(label); err != nil { if err := issues_model.UpdateLabel(l); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateLabel", err) ctx.Error(http.StatusInternalServerError, "UpdateLabel", err)
return return
} }
ctx.JSON(http.StatusOK, convert.ToLabel(label, nil, ctx.Org.Organization.AsUser())) ctx.JSON(http.StatusOK, convert.ToLabel(l, nil, ctx.Org.Organization.AsUser()))
} }
// DeleteLabel delete a label for an organization // DeleteLabel delete a label for an organization

View File

@ -5,13 +5,12 @@
package repo package repo
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
@ -93,14 +92,14 @@ func GetLabel(ctx *context.APIContext) {
// "$ref": "#/responses/Label" // "$ref": "#/responses/Label"
var ( var (
label *issues_model.Label l *issues_model.Label
err error err error
) )
strID := ctx.Params(":id") strID := ctx.Params(":id")
if intID, err2 := strconv.ParseInt(strID, 10, 64); err2 != nil { if intID, err2 := strconv.ParseInt(strID, 10, 64); err2 != nil {
label, err = issues_model.GetLabelInRepoByName(ctx, ctx.Repo.Repository.ID, strID) l, err = issues_model.GetLabelInRepoByName(ctx, ctx.Repo.Repository.ID, strID)
} else { } else {
label, err = issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, intID) l, err = issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, intID)
} }
if err != nil { if err != nil {
if issues_model.IsErrRepoLabelNotExist(err) { if issues_model.IsErrRepoLabelNotExist(err) {
@ -111,7 +110,7 @@ func GetLabel(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusOK, convert.ToLabel(label, ctx.Repo.Repository, nil)) ctx.JSON(http.StatusOK, convert.ToLabel(l, ctx.Repo.Repository, nil))
} }
// CreateLabel create a label for a repository // CreateLabel create a label for a repository
@ -145,28 +144,27 @@ func CreateLabel(ctx *context.APIContext) {
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateLabelOption) form := web.GetForm(ctx).(*api.CreateLabelOption)
form.Color = strings.Trim(form.Color, " ")
if len(form.Color) == 6 { color, err := label.NormalizeColor(form.Color)
form.Color = "#" + form.Color if err != nil {
} ctx.Error(http.StatusUnprocessableEntity, "StringToColor", err)
if !issues_model.LabelColorPattern.MatchString(form.Color) {
ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", form.Color))
return return
} }
form.Color = color
label := &issues_model.Label{ l := &issues_model.Label{
Name: form.Name, Name: form.Name,
Exclusive: form.Exclusive, Exclusive: form.Exclusive,
Color: form.Color, Color: form.Color,
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
Description: form.Description, Description: form.Description,
} }
if err := issues_model.NewLabel(ctx, label); err != nil { if err := issues_model.NewLabel(ctx, l); err != nil {
ctx.Error(http.StatusInternalServerError, "NewLabel", err) ctx.Error(http.StatusInternalServerError, "NewLabel", err)
return return
} }
ctx.JSON(http.StatusCreated, convert.ToLabel(label, ctx.Repo.Repository, nil)) ctx.JSON(http.StatusCreated, convert.ToLabel(l, ctx.Repo.Repository, nil))
} }
// EditLabel modify a label for a repository // EditLabel modify a label for a repository
@ -206,7 +204,7 @@ func EditLabel(ctx *context.APIContext) {
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.EditLabelOption) form := web.GetForm(ctx).(*api.EditLabelOption)
label, err := issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) l, err := issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
if err != nil { if err != nil {
if issues_model.IsErrRepoLabelNotExist(err) { if issues_model.IsErrRepoLabelNotExist(err) {
ctx.NotFound() ctx.NotFound()
@ -217,30 +215,28 @@ func EditLabel(ctx *context.APIContext) {
} }
if form.Name != nil { if form.Name != nil {
label.Name = *form.Name l.Name = *form.Name
} }
if form.Exclusive != nil { if form.Exclusive != nil {
label.Exclusive = *form.Exclusive l.Exclusive = *form.Exclusive
} }
if form.Color != nil { if form.Color != nil {
label.Color = strings.Trim(*form.Color, " ") color, err := label.NormalizeColor(*form.Color)
if len(label.Color) == 6 { if err != nil {
label.Color = "#" + label.Color ctx.Error(http.StatusUnprocessableEntity, "StringToColor", err)
}
if !issues_model.LabelColorPattern.MatchString(label.Color) {
ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", label.Color))
return return
} }
l.Color = color
} }
if form.Description != nil { if form.Description != nil {
label.Description = *form.Description l.Description = *form.Description
} }
if err := issues_model.UpdateLabel(label); err != nil { if err := issues_model.UpdateLabel(l); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateLabel", err) ctx.Error(http.StatusInternalServerError, "UpdateLabel", err)
return return
} }
ctx.JSON(http.StatusOK, convert.ToLabel(label, ctx.Repo.Repository, nil)) ctx.JSON(http.StatusOK, convert.ToLabel(l, ctx.Repo.Repository, nil))
} }
// DeleteLabel delete a label for a repository // DeleteLabel delete a label for a repository

View File

@ -19,6 +19,7 @@ import (
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -248,7 +249,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.") ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.")
} else if db.IsErrNameReserved(err) || } else if db.IsErrNameReserved(err) ||
db.IsErrNamePatternNotAllowed(err) || db.IsErrNamePatternNotAllowed(err) ||
repo_module.IsErrIssueLabelTemplateLoad(err) { label.IsErrTemplateLoad(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err) ctx.Error(http.StatusUnprocessableEntity, "", err)
} else { } else {
ctx.Error(http.StatusInternalServerError, "CreateRepository", err) ctx.Error(http.StatusInternalServerError, "CreateRepository", err)

View File

@ -9,6 +9,7 @@ import (
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/forms"
@ -103,8 +104,8 @@ func InitializeLabels(ctx *context.Context) {
} }
if err := repo_module.InitializeLabels(ctx, ctx.Org.Organization.ID, form.TemplateName, true); err != nil { if err := repo_module.InitializeLabels(ctx, ctx.Org.Organization.ID, form.TemplateName, true); err != nil {
if repo_module.IsErrIssueLabelTemplateLoad(err) { if label.IsErrTemplateLoad(err) {
originalErr := err.(repo_module.ErrIssueLabelTemplateLoad).OriginalError originalErr := err.(label.ErrTemplateLoad).OriginalError
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr)) ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") ctx.Redirect(ctx.Org.OrgLink + "/settings/labels")
return return

View File

@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
@ -41,8 +42,8 @@ func InitializeLabels(ctx *context.Context) {
} }
if err := repo_module.InitializeLabels(ctx, ctx.Repo.Repository.ID, form.TemplateName, false); err != nil { if err := repo_module.InitializeLabels(ctx, ctx.Repo.Repository.ID, form.TemplateName, false); err != nil {
if repo_module.IsErrIssueLabelTemplateLoad(err) { if label.IsErrTemplateLoad(err) {
originalErr := err.(repo_module.ErrIssueLabelTemplateLoad).OriginalError originalErr := err.(label.ErrTemplateLoad).OriginalError
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr)) ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
ctx.Redirect(ctx.Repo.RepoLink + "/labels") ctx.Redirect(ctx.Repo.RepoLink + "/labels")
return return

View File

@ -21,6 +21,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
base "code.gitea.io/gitea/modules/migration" base "code.gitea.io/gitea/modules/migration"
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
@ -217,18 +218,20 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err
// CreateLabels creates labels // CreateLabels creates labels
func (g *GiteaLocalUploader) CreateLabels(labels ...*base.Label) error { func (g *GiteaLocalUploader) CreateLabels(labels ...*base.Label) error {
lbs := make([]*issues_model.Label, 0, len(labels)) lbs := make([]*issues_model.Label, 0, len(labels))
for _, label := range labels { for _, l := range labels {
// We must validate color here: if color, err := label.NormalizeColor(l.Color); err != nil {
if !issues_model.LabelColorPattern.MatchString("#" + label.Color) { log.Warn("Invalid label color: #%s for label: %s in migration to %s/%s", l.Color, l.Name, g.repoOwner, g.repoName)
log.Warn("Invalid label color: #%s for label: %s in migration to %s/%s", label.Color, label.Name, g.repoOwner, g.repoName) l.Color = "#ffffff"
label.Color = "ffffff" } else {
l.Color = color
} }
lbs = append(lbs, &issues_model.Label{ lbs = append(lbs, &issues_model.Label{
RepoID: g.repo.ID, RepoID: g.repo.ID,
Name: label.Name, Name: l.Name,
Description: label.Description, Exclusive: l.Exclusive,
Color: "#" + label.Color, Description: l.Description,
Color: l.Color,
}) })
} }

View File

@ -67,6 +67,12 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
remoteRepoName := "head_repo" remoteRepoName := "head_repo"
baseBranch := "base" baseBranch := "base"
fetchArgs := git.TrustedCmdArgs{"--no-tags"}
if git.CheckGitVersionAtLeast("2.25.0") == nil {
// Writing the commit graph can be slow and is not needed here
fetchArgs = append(fetchArgs, "--no-write-commit-graph")
}
// Add head repo remote. // Add head repo remote.
addCacheRepo := func(staging, cache string) error { addCacheRepo := func(staging, cache string) error {
p := filepath.Join(staging, ".git", "objects", "info", "alternates") p := filepath.Join(staging, ".git", "objects", "info", "alternates")
@ -108,7 +114,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
outbuf.Reset() outbuf.Reset()
errbuf.Reset() errbuf.Reset()
if err := git.NewCommand(ctx, "fetch", "origin", "--no-tags").AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch). if err := git.NewCommand(ctx, "fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).
Run(&git.RunOpts{ Run(&git.RunOpts{
Dir: tmpBasePath, Dir: tmpBasePath,
Stdout: &outbuf, Stdout: &outbuf,
@ -171,7 +177,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
} else { } else {
headBranch = pr.GetGitRefName() headBranch = pr.GetGitRefName()
} }
if err := git.NewCommand(ctx, "fetch", "--no-tags").AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch). if err := git.NewCommand(ctx, "fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch).
Run(&git.RunOpts{ Run(&git.RunOpts{
Dir: tmpBasePath, Dir: tmpBasePath,
Stdout: &outbuf, Stdout: &outbuf,

View File

@ -50,7 +50,7 @@
</div> </div>
</div> </div>
<div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .login_type "0-0"}}hide{{end}}"> <div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .login_type "0-0"}}gt-hidden{{end}}">
<label for="login_name">{{.locale.Tr "admin.users.auth_login_name"}}</label> <label for="login_name">{{.locale.Tr "admin.users.auth_login_name"}}</label>
<input id="login_name" name="login_name" value="{{.login_name}}"> <input id="login_name" name="login_name" value="{{.login_name}}">
</div> </div>
@ -62,12 +62,12 @@
<label for="email">{{.locale.Tr "email"}}</label> <label for="email">{{.locale.Tr "email"}}</label>
<input id="email" name="email" type="email" value="{{.email}}" required> <input id="email" name="email" type="email" value="{{.email}}" required>
</div> </div>
<div class="required local field {{if .Err_Password}}error{{end}} {{if not (eq .login_type "0-0")}}hide{{end}}"> <div class="required local field {{if .Err_Password}}error{{end}} {{if not (eq .login_type "0-0")}}gt-hidden{{end}}">
<label for="password">{{.locale.Tr "password"}}</label> <label for="password">{{.locale.Tr "password"}}</label>
<input id="password" name="password" type="password" autocomplete="new-password" value="{{.password}}" {{if eq .login_type "0-0"}}required{{end}}> <input id="password" name="password" type="password" autocomplete="new-password" value="{{.password}}" {{if eq .login_type "0-0"}}required{{end}}>
</div> </div>
<div class="inline field local{{if ne .login_type "0-0"}} hide{{end}}"> <div class="inline field local {{if ne .login_type "0-0"}}gt-hidden{{end}}">
<div class="ui checkbox"> <div class="ui checkbox">
<label><strong>{{.locale.Tr "auth.allow_password_change"}}</strong></label> <label><strong>{{.locale.Tr "auth.allow_password_change"}}</strong></label>
<input name="must_change_password" type="checkbox" checked> <input name="must_change_password" type="checkbox" checked>

View File

@ -58,7 +58,7 @@
</label> </label>
</div> </div>
</div> </div>
<div class="quick-pull-branch-name {{if not (eq .commit_choice "commit-to-new-branch")}}hide{{end}}"> <div class="quick-pull-branch-name {{if not (eq .commit_choice "commit-to-new-branch")}}gt-hidden{{end}}">
<div class="new-branch-name-input field {{if .Err_NewBranchName}}error{{end}}"> <div class="new-branch-name-input field {{if .Err_NewBranchName}}error{{end}}">
{{svg "octicon-git-branch"}} {{svg "octicon-git-branch"}}
<input type="text" name="new_branch_name" value="{{.new_branch_name}}" class="input-contrast gt-mr-2 js-quick-pull-new-branch-name" placeholder="{{.locale.Tr "repo.editor.new_branch_name_desc"}}" {{if eq .commit_choice "commit-to-new-branch"}}required{{end}} title="{{.locale.Tr "repo.editor.new_branch_name"}}"> <input type="text" name="new_branch_name" value="{{.new_branch_name}}" class="input-contrast gt-mr-2 js-quick-pull-new-branch-name" placeholder="{{.locale.Tr "repo.editor.new_branch_name_desc"}}" {{if eq .commit_choice "commit-to-new-branch"}}required{{end}} title="{{.locale.Tr "repo.editor.new_branch_name"}}">

View File

@ -707,6 +707,11 @@
{{$.locale.TrN (len .Commits) "repo.issues.push_commit_1" "repo.issues.push_commits_n" (len .Commits) $createdStr | Safe}} {{$.locale.TrN (len .Commits) "repo.issues.push_commit_1" "repo.issues.push_commits_n" (len .Commits) $createdStr | Safe}}
{{end}} {{end}}
</span> </span>
{{if and .IsForcePush $.Issue.PullRequest.BaseRepo.Name}}
<span class="ui float right comparebox">
<a href="{{$.Issue.PullRequest.BaseRepo.Link}}/compare/{{PathEscape .OldCommit}}..{{PathEscape .NewCommit}}" rel="nofollow" class="ui compare label">{{$.locale.Tr "repo.issues.force_push_compare"}}</a>
</span>
{{end}}
</div> </div>
{{if not .IsForcePush}} {{if not .IsForcePush}}
{{template "repo/commits_list_small" dict "comment" . "root" $}} {{template "repo/commits_list_small" dict "comment" . "root" $}}

View File

@ -232,7 +232,7 @@ export function initRepoCommentForm() {
$(this).parent().find('.item').each(function () { $(this).parent().find('.item').each(function () {
$(this).removeClass('checked'); $(this).removeClass('checked');
$(this).find('.octicon').addClass('invisible'); $(this).find('.octicon-check').addClass('invisible');
}); });
if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') { if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {

View File

@ -952,6 +952,17 @@
margin-top: 4px; margin-top: 4px;
} }
.comparebox {
line-height: 32px;
vertical-align: middle;
.compare.label {
font-size: 1rem;
margin: 0;
border: 1px solid var(--color-light-border);
}
}
.comment-form-reply .footer { .comment-form-reply .footer {
padding-bottom: 1em; padding-bottom: 1em;
} }