diff --git a/docs/scripts/trans-copy b/docs/scripts/trans-copy index 17f197946..773219288 100755 --- a/docs/scripts/trans-copy +++ b/docs/scripts/trans-copy @@ -28,6 +28,8 @@ for SOURCE in $(find ${ROOT}/content -type f -iname *.en-us.md); do if [[ ! -f ${DEST} ]]; then echo "Creating fallback for ${DEST#${ROOT}/content/}" cp ${SOURCE} ${DEST} + sed -i.bak "s/en\-us/${LOCALE}/g" ${DEST} + rm ${DEST}.bak fi done done diff --git a/models/fixtures/hook_task.yml b/models/fixtures/hook_task.yml index 151fe250f..bb662345c 100644 --- a/models/fixtures/hook_task.yml +++ b/models/fixtures/hook_task.yml @@ -3,3 +3,4 @@ repo_id: 1 hook_id: 1 uuid: uuid1 + is_delivered: true diff --git a/models/issue.go b/models/issue.go index a620b5f6b..94c9124aa 100644 --- a/models/issue.go +++ b/models/issue.go @@ -51,9 +51,10 @@ type Issue struct { UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` ClosedUnix util.TimeStamp `xorm:"INDEX"` - Attachments []*Attachment `xorm:"-"` - Comments []*Comment `xorm:"-"` - Reactions ReactionList `xorm:"-"` + Attachments []*Attachment `xorm:"-"` + Comments []*Comment `xorm:"-"` + Reactions ReactionList `xorm:"-"` + TotalTrackedTime int64 `xorm:"-"` } var ( @@ -69,6 +70,15 @@ func init() { issueTasksDonePat = regexp.MustCompile(issueTasksDoneRegexpStr) } +func (issue *Issue) loadTotalTimes(e Engine) (err error) { + opts := FindTrackedTimesOptions{IssueID: issue.ID} + issue.TotalTrackedTime, err = opts.ToSession(e).SumInt(&TrackedTime{}, "time") + if err != nil { + return err + } + return nil +} + func (issue *Issue) loadRepo(e Engine) (err error) { if issue.Repo == nil { issue.Repo, err = getRepositoryByID(e, issue.RepoID) @@ -79,6 +89,15 @@ func (issue *Issue) loadRepo(e Engine) (err error) { return nil } +// IsTimetrackerEnabled returns true if the repo enables timetracking +func (issue *Issue) IsTimetrackerEnabled() bool { + if err := issue.loadRepo(x); err != nil { + log.Error(4, fmt.Sprintf("loadRepo: %v", err)) + return false + } + return issue.Repo.IsTimetrackerEnabled() +} + // GetPullRequest returns the issue pull request func (issue *Issue) GetPullRequest() (pr *PullRequest, err error) { if !issue.IsPull { @@ -225,6 +244,11 @@ func (issue *Issue) loadAttributes(e Engine) (err error) { if err = issue.loadComments(e); err != nil { return err } + if issue.IsTimetrackerEnabled() { + if err = issue.loadTotalTimes(e); err != nil { + return err + } + } return issue.loadReactions(e) } diff --git a/models/issue_comment.go b/models/issue_comment.go index c88bfe2ce..8c811d5d6 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -441,7 +441,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err } // update the issue's updated_unix column - if err = updateIssueCols(e, opts.Issue); err != nil { + if err = updateIssueCols(e, opts.Issue, "updated_unix"); err != nil { return nil, err } diff --git a/models/issue_list.go b/models/issue_list.go index 4910915cd..01a1a15f4 100644 --- a/models/issue_list.go +++ b/models/issue_list.go @@ -290,6 +290,50 @@ func (issues IssueList) loadComments(e Engine) (err error) { return nil } +func (issues IssueList) loadTotalTrackedTimes(e Engine) (err error) { + type totalTimesByIssue struct { + IssueID int64 + Time int64 + } + if len(issues) == 0 { + return nil + } + var trackedTimes = make(map[int64]int64, len(issues)) + + var ids = make([]int64, 0, len(issues)) + for _, issue := range issues { + if issue.Repo.IsTimetrackerEnabled() { + ids = append(ids, issue.ID) + } + } + + // select issue_id, sum(time) from tracked_time where issue_id in () group by issue_id + rows, err := e.Table("tracked_time"). + Select("issue_id, sum(time) as time"). + In("issue_id", ids). + GroupBy("issue_id"). + Rows(new(totalTimesByIssue)) + if err != nil { + return err + } + + defer rows.Close() + + for rows.Next() { + var totalTime totalTimesByIssue + err = rows.Scan(&totalTime) + if err != nil { + return err + } + trackedTimes[totalTime.IssueID] = totalTime.Time + } + + for _, issue := range issues { + issue.TotalTrackedTime = trackedTimes[issue.ID] + } + return nil +} + // loadAttributes loads all attributes, expect for attachments and comments func (issues IssueList) loadAttributes(e Engine) (err error) { if _, err = issues.loadRepositories(e); err != nil { @@ -316,6 +360,10 @@ func (issues IssueList) loadAttributes(e Engine) (err error) { return } + if err = issues.loadTotalTrackedTimes(e); err != nil { + return + } + return nil } diff --git a/models/issue_list_test.go b/models/issue_list_test.go index 958e07466..9197e0615 100644 --- a/models/issue_list_test.go +++ b/models/issue_list_test.go @@ -7,6 +7,8 @@ package models import ( "testing" + "code.gitea.io/gitea/modules/setting" + "github.com/stretchr/testify/assert" ) @@ -29,7 +31,7 @@ func TestIssueList_LoadRepositories(t *testing.T) { func TestIssueList_LoadAttributes(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) - + setting.Service.EnableTimetracking = true issueList := IssueList{ AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue), AssertExistsAndLoadBean(t, &Issue{ID: 2}).(*Issue), @@ -61,5 +63,10 @@ func TestIssueList_LoadAttributes(t *testing.T) { for _, comment := range issue.Comments { assert.EqualValues(t, issue.ID, comment.IssueID) } + if issue.ID == int64(1) { + assert.Equal(t, int64(400), issue.TotalTrackedTime) + } else if issue.ID == int64(2) { + assert.Equal(t, int64(3662), issue.TotalTrackedTime) + } } } diff --git a/models/issue_milestone.go b/models/issue_milestone.go index a5e0bd60d..949932fb2 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -29,6 +29,8 @@ type Milestone struct { DeadlineString string `xorm:"-"` DeadlineUnix util.TimeStamp ClosedDateUnix util.TimeStamp + + TotalTrackedTime int64 `xorm:"-"` } // BeforeUpdate is invoked from XORM before updating this object. @@ -118,14 +120,69 @@ func GetMilestoneByRepoID(repoID, id int64) (*Milestone, error) { return getMilestoneByRepoID(x, repoID, id) } +// MilestoneList is a list of milestones offering additional functionality +type MilestoneList []*Milestone + +func (milestones MilestoneList) loadTotalTrackedTimes(e Engine) error { + type totalTimesByMilestone struct { + MilestoneID int64 + Time int64 + } + if len(milestones) == 0 { + return nil + } + var trackedTimes = make(map[int64]int64, len(milestones)) + + // Get total tracked time by milestone_id + rows, err := e.Table("issue"). + Join("INNER", "milestone", "issue.milestone_id = milestone.id"). + Join("LEFT", "tracked_time", "tracked_time.issue_id = issue.id"). + Select("milestone_id, sum(time) as time"). + In("milestone_id", milestones.getMilestoneIDs()). + GroupBy("milestone_id"). + Rows(new(totalTimesByMilestone)) + if err != nil { + return err + } + + defer rows.Close() + + for rows.Next() { + var totalTime totalTimesByMilestone + err = rows.Scan(&totalTime) + if err != nil { + return err + } + trackedTimes[totalTime.MilestoneID] = totalTime.Time + } + + for _, milestone := range milestones { + milestone.TotalTrackedTime = trackedTimes[milestone.ID] + } + return nil +} + +// LoadTotalTrackedTimes loads for every milestone in the list the TotalTrackedTime by a batch request +func (milestones MilestoneList) LoadTotalTrackedTimes() error { + return milestones.loadTotalTrackedTimes(x) +} + +func (milestones MilestoneList) getMilestoneIDs() []int64 { + var ids = make([]int64, 0, len(milestones)) + for _, ms := range milestones { + ids = append(ids, ms.ID) + } + return ids +} + // GetMilestonesByRepoID returns all milestones of a repository. -func GetMilestonesByRepoID(repoID int64) ([]*Milestone, error) { +func GetMilestonesByRepoID(repoID int64) (MilestoneList, error) { miles := make([]*Milestone, 0, 10) return miles, x.Where("repo_id = ?", repoID).Find(&miles) } // GetMilestones returns a list of milestones of given repository and status. -func GetMilestones(repoID int64, page int, isClosed bool, sortType string) ([]*Milestone, error) { +func GetMilestones(repoID int64, page int, isClosed bool, sortType string) (MilestoneList, error) { miles := make([]*Milestone, 0, setting.UI.IssuePagingNum) sess := x.Where("repo_id = ? AND is_closed = ?", repoID, isClosed) if page > 0 { @@ -146,7 +203,6 @@ func GetMilestones(repoID int64, page int, isClosed bool, sortType string) ([]*M default: sess.Asc("deadline_unix") } - return miles, sess.Find(&miles) } diff --git a/models/issue_milestone_test.go b/models/issue_milestone_test.go index c57f92439..c9b53f4f4 100644 --- a/models/issue_milestone_test.go +++ b/models/issue_milestone_test.go @@ -253,3 +253,14 @@ func TestDeleteMilestoneByRepoID(t *testing.T) { assert.NoError(t, DeleteMilestoneByRepoID(NonexistentID, NonexistentID)) } + +func TestMilestoneList_LoadTotalTrackedTimes(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + miles := MilestoneList{ + AssertExistsAndLoadBean(t, &Milestone{ID: 1}).(*Milestone), + } + + assert.NoError(t, miles.LoadTotalTrackedTimes()) + + assert.Equal(t, miles[0].TotalTrackedTime, int64(3662)) +} diff --git a/models/issue_stopwatch.go b/models/issue_stopwatch.go index 92b1bb9a5..178b76c5d 100644 --- a/models/issue_stopwatch.go +++ b/models/issue_stopwatch.go @@ -69,7 +69,7 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error { Doer: user, Issue: issue, Repo: issue.Repo, - Content: secToTime(timediff), + Content: SecToTime(timediff), Type: CommentTypeStopTracking, }); err != nil { return err @@ -124,7 +124,8 @@ func CancelStopwatch(user *User, issue *Issue) error { return nil } -func secToTime(duration int64) string { +// SecToTime converts an amount of seconds to a human-readable string (example: 66s -> 1min 6s) +func SecToTime(duration int64) string { seconds := duration % 60 minutes := (duration / (60)) % 60 hours := duration / (60 * 60) diff --git a/models/issue_test.go b/models/issue_test.go index 851fe684f..d98debb17 100644 --- a/models/issue_test.go +++ b/models/issue_test.go @@ -279,3 +279,11 @@ func TestGetUserIssueStats(t *testing.T) { assert.Equal(t, test.ExpectedIssueStats, *stats) } } + +func TestIssue_loadTotalTimes(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + ms, err := GetIssueByID(2) + assert.NoError(t, err) + assert.NoError(t, ms.loadTotalTimes(x)) + assert.Equal(t, int64(3662), ms.TotalTrackedTime) +} diff --git a/models/issue_tracked_time.go b/models/issue_tracked_time.go index c314f8f44..6592f06d7 100644 --- a/models/issue_tracked_time.go +++ b/models/issue_tracked_time.go @@ -11,6 +11,7 @@ import ( api "code.gitea.io/sdk/gitea" "github.com/go-xorm/builder" + "github.com/go-xorm/xorm" ) // TrackedTime represents a time that was spent for a specific issue. @@ -44,6 +45,7 @@ type FindTrackedTimesOptions struct { IssueID int64 UserID int64 RepositoryID int64 + MilestoneID int64 } // ToCond will convert each condition into a xorm-Cond @@ -58,16 +60,23 @@ func (opts *FindTrackedTimesOptions) ToCond() builder.Cond { if opts.RepositoryID != 0 { cond = cond.And(builder.Eq{"issue.repo_id": opts.RepositoryID}) } + if opts.MilestoneID != 0 { + cond = cond.And(builder.Eq{"issue.milestone_id": opts.MilestoneID}) + } return cond } +// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required +func (opts *FindTrackedTimesOptions) ToSession(e Engine) *xorm.Session { + if opts.RepositoryID > 0 || opts.MilestoneID > 0 { + return e.Join("INNER", "issue", "issue.id = tracked_time.issue_id").Where(opts.ToCond()) + } + return x.Where(opts.ToCond()) +} + // GetTrackedTimes returns all tracked times that fit to the given options. func GetTrackedTimes(options FindTrackedTimesOptions) (trackedTimes []*TrackedTime, err error) { - if options.RepositoryID > 0 { - err = x.Join("INNER", "issue", "issue.id = tracked_time.issue_id").Where(options.ToCond()).Find(&trackedTimes) - return - } - err = x.Where(options.ToCond()).Find(&trackedTimes) + err = options.ToSession(x).Find(&trackedTimes) return } @@ -85,7 +94,7 @@ func AddTime(user *User, issue *Issue, time int64) (*TrackedTime, error) { Issue: issue, Repo: issue.Repo, Doer: user, - Content: secToTime(time), + Content: SecToTime(time), Type: CommentTypeAddTimeManual, }); err != nil { return nil, err @@ -115,7 +124,7 @@ func TotalTimes(options FindTrackedTimesOptions) (map[*User]string, error) { } return nil, err } - totalTimes[user] = secToTime(total) + totalTimes[user] = SecToTime(total) } return totalTimes, nil } diff --git a/models/oauth2.go b/models/oauth2.go index a1917540d..0640471a4 100644 --- a/models/oauth2.go +++ b/models/oauth2.go @@ -97,14 +97,17 @@ func GetActiveOAuth2Providers() ([]string, map[string]OAuth2Provider, error) { } // InitOAuth2 initialize the OAuth2 lib and register all active OAuth2 providers in the library -func InitOAuth2() { - oauth2.Init() +func InitOAuth2() error { + if err := oauth2.Init(x); err != nil { + return err + } loginSources, _ := GetActiveOAuth2ProviderLoginSources() for _, source := range loginSources { oAuth2Config := source.OAuth2() oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping) } + return nil } // wrapOpenIDConnectInitializeError is used to wrap the error but this cannot be done in modules/auth/oauth2 diff --git a/modules/auth/oauth2/oauth2.go b/modules/auth/oauth2/oauth2.go index 4584c48db..89286a1bd 100644 --- a/modules/auth/oauth2/oauth2.go +++ b/modules/auth/oauth2/oauth2.go @@ -7,13 +7,12 @@ package oauth2 import ( "math" "net/http" - "os" - "path/filepath" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - "github.com/gorilla/sessions" + "github.com/go-xorm/xorm" + "github.com/lafriks/xormstore" "github.com/markbates/goth" "github.com/markbates/goth/gothic" "github.com/markbates/goth/providers/bitbucket" @@ -41,13 +40,14 @@ type CustomURLMapping struct { } // Init initialize the setup of the OAuth2 library -func Init() { - sessionDir := filepath.Join(setting.AppDataPath, "sessions", "oauth2") - if err := os.MkdirAll(sessionDir, 0700); err != nil { - log.Fatal(4, "Fail to create dir %s: %v", sessionDir, err) - } +func Init(x *xorm.Engine) error { + store, err := xormstore.NewOptions(x, xormstore.Options{ + TableName: "oauth2_session", + }, []byte(sessionUsersStoreKey)) - store := sessions.NewFilesystemStore(sessionDir, []byte(sessionUsersStoreKey)) + if err != nil { + return err + } // according to the Goth lib: // set the maxLength of the cookies stored on the disk to a larger number to prevent issues with: // securecookie: the value is too long @@ -65,6 +65,7 @@ func Init() { return req.Header.Get(providerHeaderKey), nil } + return nil } // Auth OAuth2 auth service diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 98900c753..8dfa6dec8 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -179,8 +179,9 @@ func NewFuncMap() []template.FuncMap { } return dict, nil }, - "Printf": fmt.Sprintf, - "Escape": Escape, + "Printf": fmt.Sprintf, + "Escape": Escape, + "Sec2Time": models.SecToTime, }} } diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go index bd5ea3fd3..b2b96fff9 100644 --- a/modules/test/context_tests.go +++ b/modules/test/context_tests.go @@ -13,10 +13,11 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "net/http/httptest" + "github.com/go-macaron/session" "github.com/stretchr/testify/assert" "gopkg.in/macaron.v1" - "net/http/httptest" ) // MockContext mock context for unit tests @@ -48,6 +49,16 @@ func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) { ctx.Repo.RepoLink = ctx.Repo.Repository.Link() } +// LoadRepoCommit loads a repo's commit into a test context. +func LoadRepoCommit(t *testing.T, ctx *context.Context) { + gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath()) + assert.NoError(t, err) + branch, err := gitRepo.GetHEADBranch() + assert.NoError(t, err) + ctx.Repo.Commit, err = gitRepo.GetBranchCommit(branch.Name) + assert.NoError(t, err) +} + // LoadUser load a user into a test context. func LoadUser(t *testing.T, ctx *context.Context, userID int64) { ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: userID}).(*models.User) diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 9d5487d78..f71469c17 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -28,7 +28,7 @@ password=Passwort re_type=Passwort erneut eingeben captcha=CAPTCHA twofa=Zwei-Faktor-Authentifizierung -twofa_scratch=Zwei-Faktor-Scratch-Code +twofa_scratch=Zwei-Faktor-Einmalpasswort passcode=PIN repository=Repository @@ -81,10 +81,12 @@ err_empty_admin_password=Das Administrator-Passwort darf nicht leer sein. general_title=Allgemeine Einstellungen app_name=Seitentitel +app_name_helper=Gebe hier den Namen deines Unternehmens ein. repo_path=Repository-Verzeichnis repo_path_helper=Remote-Git-Repositories werden in diesem Verzeichnis gespeichert. lfs_path=Git LFS-Wurzelpfad lfs_path_helper=In diesem Verzeichnis werden die Dateien von Git LFS abgespeichert. Leer lassen um LFS zu deaktivieren. +run_user=Ausführen als run_user_helper=Gebe den Betriebssystem-Benutzernamen ein, unter welchem Gitea laufen soll. Beachte, dass dieser Nutzer Zugriff auf den Repository-Ordner haben muss. domain=SSH Server-Domain domain_helper=Domain oder Host-Adresse für die SSH-URL. @@ -144,6 +146,7 @@ default_allow_create_organization=Erstellen von Organisationen standarmäßig er default_allow_create_organization_popup=Neuen Nutzern das Erstellen von Organisationen standardmäßig erlauben. default_enable_timetracking=Zeiterfassung standardmäßig aktivieren default_enable_timetracking_popup=Zeiterfassung standardmäßig für neue Repositories aktivieren. +no_reply_address_helper=Domain-Namen für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername "Joe" in Git als "joe@noreply.example.org" protokolliert, wenn die versteckte E-Mail-Domäne "noreply.example.org" festgelegt ist. [home] uname_holder=E-Mail-Adresse oder Benutzername @@ -185,23 +188,29 @@ confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an %s reset_password_mail_sent_prompt=Eine E-Mail wurde an %s gesendet. Bitte überprüfe dein Postfach innerhalb der nächsten %s, um das Passwort zurückzusetzen. active_your_account=Aktiviere dein Konto prohibit_login=Anmelden verboten +resent_limit_prompt=Du hast bereits eine Aktivierungs-E-Mail angefordert. Bitte warte 3 Minuten und probiere es dann nochmal. has_unconfirmed_mail=Hallo %s, du hast eine unbestätigte E-Mail-Adresse (%s). Wenn du keine Bestätigungs-E-Mail erhalten hast oder eine neue senden möchtest, klicke bitte auf den folgenden Button. resend_mail=Aktivierungs-E-Mail erneut verschicken email_not_associate=Diese E-Mail-Adresse ist mit keinem Konto verknüpft. send_reset_mail=E-Mail zum Passwort-zurücksetzen erneut verschicken reset_password=Passwort zurücksetzen +invalid_code=Dein Bestätigungs-Code ist ungültig oder abgelaufen. reset_password_helper=Passwort zurückzusetzen password_too_short=Das Passwort muss mindenstens %d Zeichen lang sein. +non_local_account=Benutzer, die nicht von Gitea verwaltet werden können ihre Passwörter nicht über das Web Interface ändern. verify=Verifizieren scratch_code=Einmalpasswort use_scratch_code=Einmalpasswort verwenden twofa_scratch_used=Du hast dein Einmalpasswort verwendet. Du wurdest zu den Einstellung der Zwei-Faktor-Authentifizierung umgeleitet, dort kannst du dein Gerät abmelden oder ein neues Einmalpasswort erzeugen. +twofa_passcode_incorrect=Ungültige PIN. Wenn du dein Gerät verloren hast, verwende dein Einmalpasswort. twofa_scratch_token_incorrect=Das Einmalpasswort ist falsch. login_userpass=Anmelden login_openid=OpenID openid_connect_submit=Verbinden openid_connect_title=Mit bestehendem Konto verbinden openid_register_title=Neues Konto einrichten +openid_signin_desc=Gib deine OpenID-URI ein. Zum Beispiel: https://anne.me, bob.openid.org.cn oder gnusocial.net/carry. +disable_forgot_password_mail=Das Zurücksetzen von Passwörtern wurde deaktiviert. Bitte wende dich an den Administrator. [mail] activate_account=Bitte aktiviere dein Konto @@ -236,6 +245,9 @@ TreeName=Dateipfad Content=Inhalt require_error=` darf nicht leer sein.` +alpha_dash_error=` sollte nur Buchstaben, Zahlen, Bindestriche ('-') und Unterstriche ('_') enthalten` +alpha_dash_dot_error=` sollte nur Buchstaben, Zahlen, Bindestriche ('-'), Unterstriche ('_') und Punkte ('.') enthalten` +git_ref_name_error=` muss ein wohlgeformter Git-Referenzname sein.` size_error=` muss die Größe %s haben.` min_size_error=` muss mindestens %s Zeichen enthalten.` max_size_error=` darf höchstens %s Zeichen enthalten.` @@ -250,8 +262,11 @@ username_been_taken=Der Benutzername ist bereits vergeben. repo_name_been_taken=Der Repository-Name wird schon verwendet. org_name_been_taken=Der Organisationsname ist bereits vergeben. team_name_been_taken=Der Teamname ist bereits vergeben. +team_no_units_error=Das Team muss auf mindestens einen Bereich Zugriff haben. email_been_used=Die E-Mail-Adresse wird bereits verwendet. +openid_been_used=Die OpenID-Adresse "%s" wird bereits verwendet. username_password_incorrect=Benutzername oder Passwort ist falsch. +enterred_invalid_repo_name=Der eingegebenen Repository-Name ist falsch. user_not_exist=Dieser Benutzer ist nicht vorhanden. auth_failed=Authentifizierung fehlgeschlagen: %v @@ -290,11 +305,13 @@ organization=Organisationen uid=Uid public_profile=Öffentliches Profil +password_username_disabled=Benutzer, die nicht von Gitea verwaltet werden können ihren Benutzernamen nicht ändern. Bitte kontaktiere deinen Administrator für mehr Details. full_name=Vollständiger Name website=Webseite location=Standort update_profile=Profil aktualisieren update_profile_success=Dein Profil wurde aktualisiert. +change_username=Dein Benutzername wurde geändert. continue=Weiter cancel=Abbrechen @@ -309,6 +326,7 @@ change_password=Passwort aktualisieren old_password=Aktuelles Passwort new_password=Neues Passwort retype_new_password=Neues Passwort erneut eingeben +password_change_disabled=Benutzer, die nicht von Gitea verwaltet werden, können ihr Passwort im Web Interface nicht ändern. emails=E-Mail-Adressen email_desc=Deine primäre E-Mail-Adresse wird für Benachrichtigungen und andere Funktionen verwendet. @@ -372,6 +390,7 @@ delete_account_title=Benutzerkonto löschen [repo] owner=Besitzer repo_name=Repository-Name +repo_name_helper=Ein guter Repository-Name besteht normalerweise aus kurzen, unvergesslichen und einzigartigen Schlagwörtern. visibility=Sichtbarkeit fork_repo=Repository forken fork_from=Fork von diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 0aa85894d..b193924a4 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -737,6 +737,7 @@ issues.add_time_sum_to_small = No time was entered. issues.cancel_tracking = Cancel issues.cancel_tracking_history = `cancelled time tracking %s` issues.time_spent_total = Total time spent +issues.time_spent_from_all_authors = `Total Time Spent: %s` issues.dependency.title = Dependencies issues.dependency.issue_no_dependencies = This issue currently doesn't have any dependencies. issues.dependency.pr_no_dependencies = This pull request currently doesn't have any dependencies. diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 802a77186..04542c0a1 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -1,12 +1,16 @@ +app_desc=Um serviço de hospedagem Git amigável home=Página inicial dashboard=Painel explore=Explorar help=Ajuda -sign_in=Entrar +sign_in=Acessar +sign_in_with=Acessar com sign_out=Sair +sign_up=Cadastrar link_account=Conectar Conta -register=Registrar +link_account_signin_or_signup=Acesse para conectar sua conta existente à sua nova conta, ou cadastre-se para uma nova conta. +register=Cadastrar website=Site version=Versão page=Página @@ -14,10 +18,17 @@ template=Template language=Idioma notifications=Notificações create_new=Criar… -signed_in_as=Logado como +user_profile_and_more=Perfil e Configurações... +signed_in_as=Acessado como +enable_javascript=Este site funciona melhor com JavaScript. -username=Usuário +username=Nome de usuário +email=Endereço de e-mail password=Senha +re_type=Digite a senha novamente +captcha=CAPTCHA +twofa=Autenticação de dois fatores +twofa_scratch=Código de backup da autenticação de dois fatores passcode=Senha repository=Repositório @@ -29,8 +40,12 @@ new_mirror=Novo mirror new_fork=Novo Fork de Repositório new_org=Nova organização manage_org=Gerenciar organizações +admin_panel=Administração do site account_settings=Configurações da conta settings=Configurações +your_profile=Perfil +your_starred=Favorito +your_settings=Configurações all=Todos sources=Fontes @@ -46,28 +61,97 @@ cancel=Cancelar [install] install=Instalação +title=Configuração inicial +docker_helper=Se você está rodando o Gitea dentro do Docker, por favor leia a documentação cuidadosamente antes de alterar qualquer coisa nesta página. +requite_db_desc=Gitea requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB. db_title=Configurações de banco de dados db_type=Tipo de banco de dados host=Servidor +user=Nome de usuário password=Senha db_name=Nome do banco de dados +db_helper=Nota para usuários do MySQL: por favor, use o mecanismo de armazenamento InnoDB e o conjunto de caracteres 'utf8_general_ci'. +ssl_mode=SSL path=Caminho +sqlite_helper=Caminho do arquivo do banco de dados SQLite3 ou TiDB.
Digite um caminho absoluto se você executar o Gitea como um serviço. +err_empty_db_path=O Caminho do banco de dados SQLite3 ou TiDB não pode ser em branco. +err_invalid_tidb_name=O nome do banco de dados do TiDB não pode conter os caracteres '.' e '-'. +no_admin_and_disable_registration=Você não pode desabilitar o auto-cadastro do usuário sem criar uma conta de administrador. +err_empty_admin_password=A senha do administrador não pode ser em branco. +general_title=Configurações gerais +app_name=Título do site +app_name_helper=Digite o nome da sua empresa aqui. repo_path=Caminho raíz do repositório +repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diretório. +lfs_path=Caminho raiz do Git LFS +lfs_path_helper=Os arquivos armazenados com o Git LFS serão armazenados neste diretório. Deixe em branco para desabilitar. +run_user=Executar como nome de usuário +run_user_helper=Digite o nome de usuário do sistema operacional que o Gitea 'executa como'. Observe que esse usuário deve ter acesso ao caminho da raiz do repositório. +domain=Domínio do servidor SSH +domain_helper=Domínio ou endereço do servidor para URLs clone do SSH. +ssh_port=Porta do servidor SSH +ssh_port_helper=Número da porta que seu servidor SSH está usando. Deixe em branco para desabilitar. +http_port=Porta HTTP de uso do Gitea +http_port_helper=Número da porta que o servidor web do Gitea irá usar. +app_url=URL base do Gitea +app_url_helper=Endereço base para URLs clone HTTP(S) e notificações por e-mail. log_root_path=Caminho do log +log_root_path_helper=Arquivos de log serão gravados neste diretório. optional_title=Configurações opcionais +email_title=Configurações de e-mail smtp_host=Host SMTP +smtp_from=Enviar e-mail como +smtp_from_helper=Endereço de e-mail que o Gitea irá usar. Digite um endereço de e-mail simples ou use o formato "Nome" . +mailer_user=Nome de usuário do SMTP +mailer_password=Senha do SMTP +register_confirm=Exigir confirmação de e-mail para se cadastrar +mail_notify=Habilitar notificações de e-mail +server_service_title=Configurações de servidor e serviços de terceiros +offline_mode=Habilitar autenticação local +offline_mode_popup=Desabilitar redes de entrega de conteúdo de terceiros e entregar todos os recursos localmente. +disable_gravatar=Desabilitar o gravatar +disable_gravatar_popup=Desabilitar o gravatar e avatar de fontes de terceiros. Um avatar padrão será usado a menos que um usuário localmente carrega um avatar. +federated_avatar_lookup=Habilitar avatares federativos federated_avatar_lookup_popup=Habilitar a busca federativa de avatares a usar o serviço federativo de código aberto baseado no libravatar. -openid_signin=Habilitar login via OpenID -enable_captcha_popup=Obrigar validação por CAPTCHA para auto-registro de usuários. +disable_registration=Desabilitar auto-cadastro +disable_registration_popup=Desabilitar auto-cadastro de usuário. Somente os administradores serão capazes de criar novas contas de usuário. +openid_signin=Habilitar acesso via OpenID +openid_signin_popup=Habilitar o acesso de usuários via OpenID. +openid_signup=Habilitar o auto-cadastro via OpenID +openid_signup_popup=Habilitar o auto-cadastro com base no OpenID. +enable_captcha=Habilitar o CAPTCHA +enable_captcha_popup=Obrigar validação por CAPTCHA para auto-cadastro de usuários. +require_sign_in_view=Exigir acesso do usuário para a visualização de páginas +require_sign_in_view_popup=Limitar o acesso de página aos usuários que acessaram. Os visitantes só verão a página de 'acesso' e páginas de cadastro. +admin_setting_desc=Criar uma conta de administrador é opcional. O primeiro usuário cadastrado automaticamente se tornará um administrador. +admin_title=Configurações da conta de administrador +admin_name=Nome do usuário administrador admin_password=Senha confirm_password=Confirmar senha +admin_email=Endereço de e-mail install_btn_confirm=Instalar Gitea test_git_failed=Falha ao testar o comando 'git': %v +sqlite3_not_available=Esta versão do Gitea não suporta SQLite3. Por favor faça o download da versão binária oficial em %s (não utilize a versão 'gobuild'). +invalid_db_setting=Configuração de banco de dados está inválida: %v +invalid_repo_path=A raiz do repositório está inválida: %v +run_user_not_match=O nome de usuário 'Executar como' não é o nome de usuário atual: %s -> %s save_config_failed=Falha ao salvar a configuração: %v +invalid_admin_setting=Configuração da conta de administrador está inválida: %v +install_success=Bem-vindo! Obrigado por escolher Gitea. Divertir-se. E, tome cuidado! +invalid_log_root_path=Pasta raíz do log está inválida: %v +default_keep_email_private=Ocultar endereços de e-mail por padrão +default_keep_email_private_popup=Ocultar endereços de e-mail de novas contas de usuário por padrão. +default_allow_create_organization=Permitir a criação de organizações por padrão +default_allow_create_organization_popup=Permitir que novas contas de usuários criem organizações por padrão. +default_enable_timetracking=Habilitar o contador de tempo por padrão +default_enable_timetracking_popup=Habilitar o contador de tempo para novos repositórios por padrão. +no_reply_address=Domínio de e-mail oculto +no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'. [home] +uname_holder=Nome de usuário ou endereço de e-mail password_holder=Senha switch_dashboard_context=Trocar contexto do painel de controle my_repos=Meus repositórios @@ -86,48 +170,71 @@ users=Usuários organizations=Organizações search=Pesquisar code=Código +repo_no_results=Nenhum repositório correspondente foi encontrado. +user_no_results=Nenhum usuário correspondente foi encontrado. +org_no_results=Nenhuma organização correspondente foi encontrada. +code_no_results=Nenhum código-fonte correspondente ao seu termo de pesquisa foi encontrado. +code_search_results=Resultados da pesquisa por: '%s' [auth] -register_helper_msg=Já tem uma conta? Entre agora! +create_new_account=Cadastrar conta +register_helper_msg=Já tem uma conta? Acesse agora! +social_register_helper_msg=Já tem uma conta? Vincule agora! +disable_register_prompt=Cadastro está desabilitado. Entre em contato com o administrador do site. +disable_register_mail=E-mail de confirmação de cadastro está desabilitado. remember_me=Lembrar de mim forgot_password_title=Esqueci minha senha forgot_password=Esqueceu sua senha? -confirmation_mail_sent_prompt=Um novo e-mail de confirmação foi enviado para %s. Por favor, verifique sua caixa de e-mail nas próximas %s horas para finalizar o processo de registro. +sign_up_now=Precisa de uma conta? Cadastre-se agora. +confirmation_mail_sent_prompt=Um novo e-mail de confirmação foi enviado para %s. Por favor, verifique sua caixa de e-mail nas próximas %s horas para finalizar o processo de cadastro. reset_password_mail_sent_prompt=Um email de confirmação foi enviado para %s. Por favor, verifique sua caixa de e-mail nas próximas %s horas para finalizar o processo de troca de senha. active_your_account=Ativar sua conta +prohibit_login=Acesso proibido +prohibit_login_desc=Sua conta foi proibida de acessar, por favor entre em conato com o administrador do site. +resent_limit_prompt=Você já solicitou recentemente um e-mail de ativação. Por favor, aguarde 3 minutos e tente novamente. has_unconfirmed_mail=Oi %s, você possui um endereço de e-mail não confirmado (%s). Se você não recebeu um e-mail de confirmação ou precisa reenviar um novo, clique no botão abaixo. resend_mail=Clique aqui para reenviar seu e-mail de ativação email_not_associate=O endereço de e-mail não está associado à nenhuma conta. send_reset_mail=Clique aqui para re-enviar seu e-mail de redefinição de senha reset_password=Redefinir sua senha +invalid_code=Seu código de confirmação é inválido ou expirou. reset_password_helper=Clique aqui para redefinir sua senha password_too_short=O comprimento da senha não pode ser menor que %d. +non_local_account=Usuários não-locais não podem atualizar sua senha através da interface web do Gitea. verify=Verificar scratch_code=Código de backup use_scratch_code=Use um código de backup twofa_scratch_used=Você usou seu código de backup. Você foi redirecionado para a página de configurações de dois fatores para que você possa remover a inscrição de seu dispositivo ou gerar um novo código de backup. +twofa_passcode_incorrect=Seu código de acesso está incorreto. Se você perdeu seu dispositivo, use seu código de backup para acessar. twofa_scratch_token_incorrect=Seu código de backup está incorreto. +login_userpass=Acessar login_openid=OpenID openid_connect_submit=Conectar openid_connect_title=Conectar à uma conta existente +openid_connect_desc=O URI do OpenID escolhido é desconhecido. Associe-o com uma nova conta aqui. openid_register_title=Criar uma nova conta +openid_register_desc=O URI do OpenID escolhido é desconhecido. Associe-o com uma nova conta aqui. +openid_signin_desc=Digite a URI do seu OpenID. Por exemplo: https://anne.me, bob.openid.org.cn ou gnusocial.net/carry. +disable_forgot_password_mail=Redefinição de senha está desabilitada. Entre em contato com o administrador do site. [mail] activate_account=Por favor, ative sua conta activate_email=Verifique seu endereço de e-mail reset_password=Resetar sua senha -register_success=Registro bem-sucedido +register_success=Cadastro bem-sucedido register_notify=Bem-vindo ao Gitea [modal] yes=Sim no=Não +modify=Atualizar [form] UserName=Nome de usuário RepoName=Nome do repositório Email=Endereço de e-mail Password=Senha +Retype=Digite a senha novamente SSHTitle=Nome da chave SSH HttpsUrl=URL HTTPS PayloadUrl=URL de carga @@ -142,7 +249,10 @@ CommitChoice=Escolha de commit TreeName=Caminho do arquivo Content=Conteúdo -require_error=` não pode estar vazio.` +require_error=` não pode estar em branco.` +alpha_dash_error=` deve conter somente alfanumérico, caracteres de traço ('-') e sublinhado ('_').` +alpha_dash_dot_error=` deve conter somente alfanumérico, caracteres de traço ('-'), sublinhado ('_') e ponto ('. ') .` +git_ref_name_error=` deve ser um nome de referência Git válido.` size_error=`deve ser do tamanho %s.` min_size_error=` deve conter pelo menos %s caracteres.` max_size_error=` deve conter no máximo %s caracteres.` @@ -150,24 +260,48 @@ email_error=` não é um endereço de e-mail válido.` url_error=`não é uma URL válida.` include_error=` deve conter '%s'.` unknown_error=Erro desconhecido: +captcha_incorrect=O código CAPTCHA está incorreto. +password_not_match=As senhas não coincidem. +username_been_taken=O nome de usuário já está sendo usado. +repo_name_been_taken=O nome de repositório já está sendo usado. +org_name_been_taken=O nome da organização já está sendo usado. +team_name_been_taken=O nome do time já está sendo usado. +team_no_units_error=Permitir acesso a pelo menos uma seção de repositório. +email_been_used=Este endereço de e-mail já está sendo usado. +openid_been_used=O endereço OpenID '%s' já está sendo usado. +username_password_incorrect=Nome de usuário ou senha incorretos. +enterred_invalid_repo_name=O nome do repositório que você digitou está incorreto. +enterred_invalid_owner_name=O nome do novo proprietário não é válido. +enterred_invalid_password=A senha que você digitou está incorreta. user_not_exist=O usuário 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 qualquer time. +cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de um time. +invalid_ssh_key=Não é possível verificar sua chave SSH: %s +invalid_gpg_key=Não é possível verificar sua chave GPG: %s +unable_verify_ssh_key=Não é possível verificar sua chave SSH; verifique novamente se há erros. auth_failed=Autenticação falhou: %v +still_own_repo=Sua conta possui um ou mais repositórios; você deve excluí-los ou transferi-los primeiro. +still_has_org=Sua conta é um membro de uma ou mais organizações; você deve deixá-las primeiro. +org_still_own_repo=Esta organização ainda possui repositórios; você deve excluí-los ou transferi-los primeiro. target_branch_not_exist=O branch de destino não existe. [user] +change_avatar=Altere seu avatar... join_on=Inscreveu-se em repositories=Repositórios activity=Atividade pública followers=Seguidores +starred=Repositórios favoritos following=Seguindo follow=Seguir unfollow=Deixar de seguir -form.name_reserved=O nome de usuário '%s' é reservado. +form.name_reserved=O nome de usuário '%s' está reservado. +form.name_pattern_not_allowed=O padrão de '%s' não é permitido em um nome de usuário. [settings] profile=Perfil @@ -176,44 +310,95 @@ security=Segurança avatar=Avatar ssh_gpg_keys=Chaves SSH / GPG social=Contas sociais +applications=Tokens de acesso +orgs=Gerenciar organizações repos=Repositórios delete=Excluir conta twofa=Autenticação de dois fatores +account_link=Contas vinculadas +organization=Organizações uid=Uid public_profile=Perfil público +profile_desc=Seu endereço de e-mail será usado para notificações e outras operações. +password_username_disabled=Usuários não-locais não podem alterar seus nomes de usuário. Por favor contate o administrador do site para mais informações. full_name=Nome completo website=Site location=Localização update_profile=Atualizar o perfil update_profile_success=Seu perfil foi atualizado. +change_username=Seu nome de usuário foi alterado. +change_username_prompt=Nota: as alterações de nome de usuário também mudam sua URL da conta. continue=Continuar cancel=Cancelar +lookup_avatar_by_mail=Procure o avatar do endereço de e-mail federated_avatar_lookup=Busca de avatar federativo enable_custom_avatar=Habilitar avatar customizado choose_new_avatar=Escolha um novo avatar +update_avatar=Atualizar o avatar delete_current_avatar=Excluir o avatar atual +uploaded_avatar_not_a_image=O arquivo enviado não é uma imagem. +update_avatar_success=Seu avatar foi atualizado. +change_password=Atualizar senha old_password=Senha Atual new_password=Nova senha +retype_new_password=Digite a nova senha novamente +password_incorrect=A senha atual está incorreta. +change_password_success=Sua senha foi atualizada. Acesse usando sua nova senha de agora em diante. +password_change_disabled=Contas não-locais não podem alterar sua senha através da interface web do Gitea. emails=Endereços de e-mail +manage_emails=Gerenciar endereços de e-mail +manage_openid=Gerencia endereços OpenID email_desc=Seu endereço de e-mail principal será usado para notificações e outras operações. primary=Principal +primary_email=Tornar privado +delete_email=Remover +email_deletion=Remover endereço de e-mail +email_deletion_desc=O endereço de e-mail e informações relacionadas serão removidos de sua conta. Commits realizados por este endereço de e-mail permanecerão inalterados. Continuar? +email_deletion_success=O endereço de e-mail foi removido. +openid_deletion=Remover endereço de OpenID +openid_deletion_desc=A exclusão deste endereço OpenID da sua conta impedirá que você acesse com ele. Continuar? +openid_deletion_success=O endereço de OpenID foi removido. +add_new_email=Adicionar novo endereço de e-mail +add_new_openid=Adicionar novo URI OpenID +add_email=Adicionar novo endereço de e-mail add_openid=Adicionar URI OpenID +add_email_confirmation_sent=Um novo e-mail de confirmação foi enviado para '%s'. Por favor verifique sua caixa de e-mail dentro de %s para confirmar seu e-mail. +add_email_success=O novo endereço de e-mail foi adicionado. +add_openid_success=O novo endereço de OpenID foi adicionado. +keep_email_private=Ocultar endereço de e-mail +keep_email_private_popup=Seu endereço de e-mail será ocultado de outros usuários. +openid_desc=OpenID permite delegar autenticação para um provedor externo. manage_ssh_keys=Gerenciar Chaves SSH manage_gpg_keys=Gerenciar chaves GPG add_key=Adicionar chave +ssh_desc=Estas chaves SSH públicas estão associados a sua conta. Chaves privadas correspondentes permitam acesso completo a seus repositórios. +gpg_desc=Essas chaves GPG públicas estão associadas à sua conta. Mantenha suas chaves privadas seguras, pois elas permitem que os commits sejam verificados. ssh_helper=Precisa de ajuda? Dê uma olhada no guia do GitHub para criar suas próprias chaves SSH ou resolver problemas comuns que você pode ter usando SSH. gpg_helper=Precisa de ajuda? Dê uma olhada no guia do GitHub sobre GPG. add_new_key=Adicionar Chave SSH add_new_gpg_key=Adicionar chave GPG +ssh_key_been_used=Esta chave SSH já foi adicionado à sua conta. +ssh_key_name_used=Uma chave SSH com o mesmo nome já foi adicionada à sua conta. +gpg_key_id_used=Uma chave GPG pública com a mesma ID já existe. +gpg_no_key_email_found=Esta chave GPG não é utilizável com qualquer endereço de e-mail associado à sua conta. subkeys=Subchaves key_id=ID da chave key_name=Nome da Chave key_content=Conteúdo +add_key_success=A chave SSH '%s' foi adicionada. +add_gpg_key_success=A chave GPG '%s' foi adicionada. +delete_key=Remover +ssh_key_deletion=Remover a chave SSH +gpg_key_deletion=Remover a chave GPG +ssh_key_deletion_desc=A exclusão de uma chave SSH revoga seu acesso à sua conta. Continuar? +gpg_key_deletion_desc=A exclusão de uma chave GPG cancela a verificação de confirmações assinadas por ela. Continuar? +ssh_key_deletion_success=A chave SSH foi removida. +gpg_key_deletion_success=A chave GPG foi removida. add_on=Adicionado em valid_until=Válido até valid_forever=Válido para sempre @@ -221,43 +406,91 @@ last_used=Última vez usado em no_activity=Nenhuma atividade recente can_read_info=Leitura can_write_info=Escrita -key_state_desc=Essa chave tem sido utilizada nos últimos 7 dias -token_state_desc=Esse token tem sido utilizado nos últimos 7 dias +key_state_desc=Esta chave tem sido utilizada nos últimos 7 dias +token_state_desc=Este token tem sido utilizado nos últimos 7 dias show_openid=Mostrar no perfil hide_openid=Ocultar no perfil +ssh_disabled=SSH desabilitado manage_social=Gerenciar contas sociais associadas +social_desc=Essas contas sociais estão vinculadas à sua conta do Gitea. Certifique-se de reconhecer todas elas, pois elas podem ser usadas para acessar a sua conta do Gitea. +unbind=Desvincular +unbind_success=A conta social foi desvinculada da sua conta do Gitea. +manage_access_token=Gerenciar tokens de acesso generate_new_token=Gerar novo token +tokens_desc=Esses tokens concedem acesso à sua conta usando a API do Gitea. +new_token_desc=Aplicações usando um token possuem acesso total à sua conta. token_name=Nome do token generate_token=Gerar token +generate_token_success=Seu novo token foi gerado. Copie-o agora, pois ele não será mostrado novamente. delete_token=Excluir +access_token_deletion=Excluir token de acesso +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. As aplicações que o utilizam já não têm acesso à sua conta. +twofa_desc=Autenticação de dois fatores melhora a segurança de sua conta. twofa_is_enrolled=Sua conta está atualmente habilitada com autenticação de dois fatores. twofa_not_enrolled=Sua conta não está atualmente inscrita para a autenticação em duas etapas. -twofa_disabled=A autenticação de dois fatores foi desativada. +twofa_disable=Desabilitar a autenticação de dois fatores +twofa_scratch_token_regenerate=Gerar novamente o token de backup +twofa_scratch_token_regenerated=Seu token de backup agora é %s. Guarde-o em um lugar seguro. +twofa_enroll=Inscrever para a autenticação de dois fatores +twofa_disable_note=Você pode desabilitar a autenticação de dois fatores se necessário. +twofa_disable_desc=Desabilitar a autenticação de dois fatores tornará sua conta menos segura. Tem certeza que deseja continuar? +regenerate_scratch_token_desc=Se você perdeu o seu token de backup, ou teve que usá-lo para realizar um acesso, você pode redefini-lo. +twofa_disabled=A autenticação de dois fatores foi desabilitada. scan_this_image=Escaneie esta imagem com o seu aplicativo de autenticação: or_enter_secret=Ou digite esse código: %s +then_enter_passcode=E insira a senha mostrada no aplicativo: +passcode_invalid=Esse código de acesso é inválido. Tente novamente. +twofa_enrolled=Sua conta foi inscrita na autenticação de dois fatores. Armazene seu token de backup (%s) em um local seguro, pois ele é exibido apenas uma vez! +manage_account_links=Gerenciar contas vinculadas +manage_account_links_desc=Estas contas externas estão vinculadas a sua conta de Gitea. +account_links_not_available=Não existem contas externas atualmente vinculadas a esta conta. +remove_account_link=Remover conta vinculada +remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar? +remove_account_link_success=A conta vinculada foi removida. orgs_none=Você não é membro de nenhuma organização. repos_none=Você não possui nenhum repositório delete_account=Excluir sua conta +delete_prompt=Esta operação irá apagar permanentemente a sua conta de usuário. Isto NÃO PODERÁ ser desfeito. confirm_delete_account=Confirmar exclusão +delete_account_title=Excluir conta de usuário +delete_account_desc=Tem certeza que deseja apagar sua conta de usuário permanentemente? [repo] -owner=Dono +owner=Proprietário repo_name=Nome do repositório +repo_name_helper=Um bom nome de repositório é composto por palavras curtas, memorizáveis e únicas. visibility=Visibilidade +visiblity_helper=Tornar este repositório privado +visiblity_helper_forced=O administrador do site força novos repositórios a serem privados. +visiblity_fork_helper=(Esta alteração irá afetar todos os forks.) +clone_helper=Precisa de ajuda com o clone? Visite a Ajuda. fork_repo=Fork do repositório fork_from=Fork de +fork_visiblity_helper=A visibilidade do fork de um repositório não pode ser alterada. repo_desc=Descrição repo_lang=Linguagem +repo_gitignore_helper=Selecione modelos do .gitignore. license=Licença +license_helper=Selecione um arquivo de licença. +readme=LEIA-ME +readme_helper=Selecione um modelo de arquivo LEIA-ME. +auto_init=Inicializar o repositório (adicionando .gitignore, licença e LEIA-ME) create_repo=Criar repositório default_branch=Branch padrão mirror_prune=Varrer +mirror_prune_desc=Remover referências obsoletas de controle remoto +mirror_interval=Intervalo do espelho (unidades de tempo válidas são 'h', 'm', 's') +mirror_interval_invalid=O intervalo do espelho não é válido. +mirror_address=Clonar de URL +mirror_address_desc=Inclua quaisquer credenciais de autorização exigida na URL. +mirror_last_synced=Última sincronização watchers=Observadores stargazers=Usuários que estrelaram forks=Forks @@ -265,39 +498,51 @@ pick_reaction=Escolha sua reação reactions_more=e %d mais form.reach_limit_of_creation=Você já atingiu o seu limite de %d repositórios. -form.name_reserved=O nome de repositório '%s' é reservado e não pode ser usado. +form.name_reserved=O nome de repositório '%s' está reservado e não pode ser usado. +form.name_pattern_not_allowed=O padrão de '%s' não é permitido em um nome de repositório. +need_auth=Autorização de clone migrate_type=Tipo de migração migrate_type_helper=Este repositório será um espelho migrate_repo=Migrar repositório +migrate.clone_address=Migrar / Clonar de URL +migrate.clone_address_desc=URL HTTP (S) ou Git 'clone' de um repositório existente +migrate.clone_local_path=ou um caminho de servidor local migrate.permission_denied=Você não pode importar repositórios locais. +migrate.invalid_local_path=O caminho local é inválido. Ele não existe ou não é um diretório. migrate.failed=Migração falhou: %v +migrate.lfs_mirror_unsupported=Espelhamento de objetos Git LFS não é suportado; ao invés use 'git lfs fetch --all' e 'git lfs push --all'. mirror_from=espelho de forked_from=feito fork de +fork_from_self=Você não pode criar um fork de um repositório que já é seu. copy_link=Copiar +copy_link_success=O link foi copiado +copy_link_error=Use ⌘-C ou Ctrl-C para copiar copied=Copiado com sucesso unwatch=Deixar de observar watch=Observar unstar=Remover favorito star=Favorito fork=Fork +download_archive=Baixar repositório no_desc=Nenhuma descrição quick_guide=Guia Rápido clone_this_repo=Clonar este repositório create_new_repo_command=Criando um novo repositório por linha de comando -push_exist_repo=Enviando um repositório existente por linha de comando -bare_message=Esse repositório está vazio. +push_exist_repo=Realizando push para um repositório existente por linha de comando +bare_message=Este repositório está vazio. code=Código +code.desc=Acesso a código-fonte, arquivos, commits e branches. branch=Branch tree=Tag filter_branch_and_tag=Filtrar branch ou tag branches=Branches tags=Tags issues=Issues -pulls=Pull Requests +pulls=Pull requests labels=Etiquetas milestones=Marcos commits=Commits @@ -307,11 +552,26 @@ file_raw=Original file_history=Histórico file_view_raw=Ver original file_permalink=Link permanente +file_too_large=O arquivo é muito grande para ser mostrado. +video_not_supported_in_browser=Seu navegador não suporta a tag 'video' do HTML5. stored_lfs=Armazenado com Git LFS +commit_graph=Gráfico de commits +editor.new_file=Novo arquivo +editor.upload_file=Enviar arquivo +editor.edit_file=Editar arquivo editor.preview_changes=Visualizar alterações +editor.cannot_edit_non_text_files=Arquivos binários não podem ser editados na interface web. +editor.edit_this_file=Editar arquivo +editor.must_be_on_a_branch=Você deve estar em um branch para propor mudanças neste arquivo. +editor.fork_before_edit=Você deve fazer um fork desse repositório para fazer ou propor alterações neste arquivo. +editor.delete_this_file=Excluir arquivo +editor.must_have_write_access=Você deve ter permissão de escrita para fazer ou propor mudanças neste arquivo. +editor.file_delete_success=O arquivo '%s' foi excluído. editor.name_your_file=Nomeie o seu arquivo… +editor.filename_help=Adicione um diretório digitando seu nome seguido por uma barra ('/'). Remova um diretório digitando o backspace no início do campo de entrada. editor.or=ou +editor.cancel_lower=Cancelar editor.commit_changes=Confirmar alterações editor.add_tmpl=Adicionar '%s/' editor.add=Adicionar '%s' @@ -322,40 +582,60 @@ editor.commit_directly_to_this_branch=Confirme diretamente no branch novo branch para este commit e crie um pull request. editor.new_branch_name_desc=Novo nome do branch... editor.cancel=Cancelar +editor.filename_cannot_be_empty=Nome do arquivo não pode ser em branco. editor.branch_already_exists=Branch '%s' já existe neste repositório. +editor.directory_is_a_file=O nome do diretório '%s' já é usado como um nome de arquivo neste repositório. +editor.file_is_a_symlink='%s' é um link simbólico. Links simbólicos não podem ser editados no editor da web +editor.filename_is_a_directory=O nome do arquivo '%s' já é usado como um nome de diretório neste repositório. +editor.file_editing_no_longer_exists=O arquivo que está sendo editado, '%s', não existe mais neste repositório. +editor.file_changed_while_editing=O conteúdo do arquivo mudou desde que você começou a editar. Clique aqui para ver o que foi editado ou clique em Commit novamemente para sobreescrever essas mudanças. +editor.file_already_exists=Um arquivo com nome '%s' já existe neste repositório. editor.no_changes_to_show=Nenhuma alteração a mostrar. editor.fail_to_update_file=Houve erro ao criar ou atualizar arquivo '%s': %v +editor.add_subdir=Adicionar um subdiretório... editor.unable_to_upload_files=Houve erro ao fazer upload de arquivos para '%s': %v editor.upload_files_to_dir=Enviar arquivos para '%s' +editor.cannot_commit_to_protected_branch=Branch '%s' está protegido para commits. +commits.desc=Veja o histórico de alterações do código de fonte. commits.commits=Commits +commits.search=Pesquisar commits... commits.find=Pesquisar +commits.search_all=Todos os branches commits.author=Autor commits.message=Mensagem commits.date=Data commits.older=Mais Antigo commits.newer=Mais recente -commits.signed_by=Assinado por +commits.signed_by=Acessado por +commits.gpg_key_id=ID da chave GPG +ext_issues=Ext. Issues +ext_issues.desc=Link para o issue tracker externo. +issues.desc=Organize relatórios de bugs, tarefas e marcos. issues.new=Nova issue issues.new.labels=Etiquetas issues.new.no_label=Sem etiqueta issues.new.clear_labels=Limpar etiquetas -issues.new.milestone=Marcos -issues.new.no_milestone=Sem Marco +issues.new.milestone=Marco +issues.new.no_milestone=Sem marco issues.new.clear_milestone=Limpar marco -issues.new.open_milestone=Marcos Abertos -issues.new.closed_milestone=Marcos Fechados +issues.new.open_milestone=Marcos abertos +issues.new.closed_milestone=Marcos fechados issues.new.assignee=Responsável issues.new.clear_assignee=Limpar responsável issues.new.no_assignee=Não atribuída -issues.no_ref=Nenhuma Branch/Tag especificado +issues.no_ref=Nenhum branch/tag especificado issues.create=Criar issue issues.new_label=Nova etiqueta +issues.new_label_placeholder=Nome da etiqueta +issues.new_label_desc_placeholder=Descrição issues.create_label=Criar etiqueta issues.label_templates.title=Carregue um conjunto de etiquetas pré-definidas +issues.label_templates.info=Ainda não existem etiquetas. Crie uma etiqueta em 'Nova etiqueta' ou use um conjunto de etiquetas predefinida: issues.label_templates.helper=Selecione um conjunto de etiquetas +issues.label_templates.use=Use o conjunto de etiquetas issues.label_templates.fail_to_load_file=Houve erro ao carregar arquivo de template '%s': %v issues.add_label_at=adicionou a etiqueta
%s
%s issues.remove_label_at=removeu a etiqueta
%s
%s @@ -371,8 +651,11 @@ issues.delete_branch_at=`excluiu branch %s %s` issues.open_tab=%d aberto issues.close_tab=%d fechado issues.filter_label=Etiqueta +issues.filter_label_no_select=Todas as etiquetas issues.filter_milestone=Marco +issues.filter_milestone_no_select=Todos os marcos issues.filter_assignee=Atribuído +issues.filter_assginee_no_select=Todos os responsáveis issues.filter_type=Tipo issues.filter_type.all_issues=Todos os issues issues.filter_type.assigned_to_you=Atribuídos a você @@ -403,7 +686,9 @@ issues.commented_at=`comentou %s` issues.delete_comment_confirm=Tem certeza que deseja excluir este comentário? issues.no_content=Ainda não há conteúdo. issues.close_issue=Fechar +issues.close_comment_issue=Comentar e fechar issues.reopen_issue=Reabrir +issues.reopen_comment_issue=Comentar e reabrir issues.create_comment=Comentar issues.closed_at=`fechou %[2]s` issues.reopened_at=`reaberto %[2]s` @@ -411,7 +696,7 @@ issues.commit_ref_at=`citou esta issue em um commit issues.poster=Autor issues.collaborator=Colaborador issues.owner=Proprietário -issues.sign_in_require_desc=Faça login para participar desta conversação. +issues.sign_in_require_desc=Acesse para participar desta conversação. issues.edit=Editar issues.cancel=Cancelar issues.save=Salvar @@ -422,6 +707,10 @@ issues.label_count=%d etiquetas issues.label_open_issues=%d issues abertas issues.label_edit=Editar issues.label_delete=Excluir +issues.label_modify=Editar etiqueta +issues.label_deletion=Excluir etiqueta +issues.label_deletion_desc=A exclusão desta etiqueta irá removê-la de todas as issues. Tem certeza que deseja continuar? +issues.label_deletion_success=A etiqueta foi excluída. issues.label.filter_sort.alphabetically=Alfabeticamente issues.label.filter_sort.reverse_alphabetically=Alfabeticamente inverso issues.label.filter_sort.by_size=Tamanho @@ -431,32 +720,55 @@ issues.attachment.open_tab=`Clique para ver "%s" em uma nova aba` issues.attachment.download=`Clique para baixar "%s"` issues.subscribe=Inscrever-se issues.unsubscribe=Desinscrever +issues.tracker=Contador de tempo issues.start_tracking_short=Iniciar +issues.start_tracking=Iniciar contador de tempo issues.start_tracking_history=`começou a trabalhar %s` issues.tracking_already_started='Você já iniciou o contador de tempo para esta issue!' issues.stop_tracking=Parar issues.stop_tracking_history=`parou de trabalhar %s` +issues.add_time=Adicionar tempo manualmente +issues.add_time_short=Adicionar tempo issues.add_time_cancel=Cancelar issues.add_time_history=`adicionou tempo gasto %s` issues.add_time_hours=Horas issues.add_time_minutes=Minutos +issues.add_time_sum_to_small=Nenhum tempo foi inserido. issues.cancel_tracking=Cancelar issues.cancel_tracking_history=`cancelou contador de tempo %s` +issues.time_spent_total=Tempo total gasto +pulls.desc=Habilitar solicitações de merge e revisões de código. pulls.new=Novo pull request +pulls.compare_changes=Novo pull request +pulls.compare_changes_desc=Selecione a branch de destino (push) e a branch de origem (pull) para o merge. +pulls.compare_base=realizar merge em +pulls.compare_compare=realizar pull de pulls.filter_branch=Filtrar branch pulls.no_results=Nada encontrado. +pulls.nothing_to_compare=Estes branches são iguais. Não há nenhuma necessidade para criar um pull request. +pulls.has_pull_request=`Um pull request entre esses branches já existe: %[2]s#%[3]d` pulls.create=Criar pull request pulls.title_desc=quer mesclar %[1]d commits de %[2]s em %[3]s -pulls.merged_title_desc=mesclou %[1]d commits de %[2]s em %[3]s %[4]s +pulls.merged_title_desc=fez merge dos %[1]d commits de %[2]s em %[3]s %[4]s pulls.tab_conversation=Conversação pulls.tab_commits=Commits +pulls.tab_files=Arquivos alterados pulls.reopen_to_merge=Por favor reabra este pull request para realizar o merge. pulls.merged=Merge realizado +pulls.has_merged=O merge deste pull request foi realizado. +pulls.data_broken=Este pull request está quebrado devido a falta de informação do fork. +pulls.is_checking=Verificação de conflitos do merge está em andamento. Tente novamente em alguns momentos. pulls.can_auto_merge_desc=O merge deste pull request pode ser aplicado automaticamente. -pulls.merge_pull_request=Aplicar merge de Pull Request +pulls.cannot_auto_merge_desc=O merge deste pull request não pode ser aplicado automaticamente pois há conflitos. +pulls.cannot_auto_merge_helper=Faça o merge manualmente para resolver os conflitos. +pulls.no_merge_desc=O merge deste pull request não pode ser aplicado porque todas as opções de mesclagem do repositório estão desabilitadas. +pulls.no_merge_helper=Habilite as opções de merge nas configurações do repositório ou faça o merge do pull request manualmente. +pulls.merge_pull_request=Realizar merge do pull request pulls.rebase_merge_pull_request=Aplicar Rebase e Merge pulls.squash_merge_pull_request=Aplicar Squash e Merge +pulls.invalid_merge_option=Você não pode usar esta opção de merge neste pull request. +pulls.open_unmerged_pull_exists=`Não é possível executar uma operação de reabertura pois há um pull request pendente (#%d) com propriedades idênticas.` milestones.new=Novo marco milestones.open_tab=%d Aberto @@ -465,13 +777,22 @@ milestones.closed=Fechado %s milestones.no_due_date=Sem prazo milestones.open=Reabrir milestones.close=Fechar -milestones.create=Criar Marco +milestones.new_subheader=Marcos organizam as issues e acompanham o progresso. +milestones.create=Criar marco milestones.title=Título milestones.desc=Descrição milestones.due_date=Prazo (opcional) milestones.clear=Limpar -milestones.edit=Editar Marco +milestones.invalid_due_date_format=Formato de data inválido; deve ser 'aaaa-mm-dd'. +milestones.create_success=O marco '%s' foi criado. +milestones.edit=Editar marco +milestones.edit_subheader=Marcos organizam as issues e acompanham o progresso. milestones.cancel=Cancelar +milestones.modify=Atualizar marco +milestones.edit_success=O marco '%s' foi atualizado. +milestones.deletion=Excluir marco +milestones.deletion_desc=A exclusão deste marco irá removê-lo de todas as issues. Tem certeza que deseja continuar? +milestones.deletion_success=O marco foi excluído. milestones.filter_sort.closest_due_date=Prazo mais próximo milestones.filter_sort.furthest_due_date=Prazo mais longe milestones.filter_sort.least_complete=Menos completo @@ -479,17 +800,26 @@ milestones.filter_sort.most_complete=Mais completo milestones.filter_sort.most_issues=Com mais issues milestones.filter_sort.least_issues=Com menos issues +ext_wiki=Ext. Wiki +ext_wiki.desc=Link para uma wiki externa. wiki=Wiki +wiki.welcome=Bem-vindo a wiki. +wiki.welcome_desc=A wiki permite que você escreva e compartilhe a documentação com os colaboradores. +wiki.desc=Escrever e compartilhar a documentação com os colaboradores. +wiki.create_first_page=Criar a primeira página wiki.page=Página wiki.filter_page=Filtrar página +wiki.new_page=Página wiki.default_commit_message=Escreva uma nota sobre a atualização nesta página (opcional). wiki.save_page=Salvar página wiki.last_commit_info=%s editou esta página %s wiki.edit_page_button=Editar wiki.new_page_button=Nova página wiki.delete_page_button=Excluir página -wiki.page_already_exists=já existe uma página de wiki com o mesmo nome. +wiki.delete_page_notice_1=A exclusão da página de wiki '%s' não pode ser desfeita. Continuar? +wiki.page_already_exists=Uma página de wiki com o mesmo nome já existe. +wiki.reserved_page=O nome da página wiki '%s' está reservada. wiki.pages=Páginas wiki.last_updated=Última atualização %s @@ -502,17 +832,17 @@ activity.period.monthly=1 mês activity.overview=Visão geral activity.active_prs_count_1=%d Pull request ativo activity.active_prs_count_n=%d Pull requests ativos -activity.merged_prs_count_1=Pull request mesclado -activity.merged_prs_count_n=Pull requests mesclados +activity.merged_prs_count_1=Pull request com merge realizado +activity.merged_prs_count_n=Pull requests com merge realizado activity.opened_prs_count_1=Pull request proposto activity.opened_prs_count_n=Pull requests propostos activity.title.user_1=%d usuário activity.title.user_n=%d usuários activity.title.prs_1=%d Pull request activity.title.prs_n=%d Pull requests -activity.title.prs_merged_by=%s mesclado por %s +activity.title.prs_merged_by=%s merge feito por %s activity.title.prs_opened_by=%s proposto por %s -activity.merged_prs_label=Mesclado +activity.merged_prs_label=Merge realizado activity.opened_prs_label=Proposto activity.active_issues_count_1=%d Issue ativa activity.active_issues_count_n=%d Issues ativas @@ -526,6 +856,9 @@ activity.closed_issue_label=Fechado activity.new_issues_count_1=Nova issue activity.new_issues_count_n=Novas issues activity.new_issue_label=Aberto +activity.title.unresolved_conv_1=%d conversa não resolvida +activity.title.unresolved_conv_n=%d conversas não resolvidas +activity.unresolved_conv_desc=Estes problemas foram recentemente alterados e pull requests ainda não foram resolvidos. activity.unresolved_conv_label=Abrir activity.title.releases_1=%d Versão activity.title.releases_n=%d Versões @@ -538,6 +871,9 @@ search.results=Resultados da pesquisa para "%s" em %s settings=Configurações settings.desc=Opções é onde você pode gerenciar as configurações para o repositório +settings.options=Repositório +settings.collaboration=Colaboradores +settings.collaboration.admin=Administrador settings.collaboration.write=Escrita settings.collaboration.read=Leitura settings.collaboration.undefined=Indefinido @@ -545,58 +881,168 @@ settings.hooks=Webhooks settings.githooks=Hooks do Git settings.basic_settings=Configurações básicas settings.mirror_settings=Opções de mirror +settings.sync_mirror=Sincronizar agora +settings.mirror_sync_in_progress=Sincronização do espelho está em andamento. Verifique novamente em um minuto. +settings.site=Site settings.update_settings=Atualizar configurações settings.advanced_settings=Configurações avançadas +settings.wiki_desc=Habilitar a wiki do repositório +settings.use_internal_wiki=Usar a wiki nativa +settings.use_external_wiki=Usar wiki externa settings.external_wiki_url=URL externa da wiki +settings.external_wiki_url_error=A URL da wiki externa não é válida. +settings.external_wiki_url_desc=Visitantes são redirecionados para a URL da wiki externa ao clicar na aba da wiki. +settings.issues_desc=Habilitar issue tracker para o repositório +settings.use_internal_issue_tracker=Usar o issue tracker nativo +settings.use_external_issue_tracker=Usar issue tracker externo settings.external_tracker_url=URL do issue tracker externo +settings.external_tracker_url_error=A URL do issue tracker externo não é válida. +settings.external_tracker_url_desc=Visitantes são redirecionados para a URL do issue tracker externo ao clicar na aba de issues. settings.tracker_url_format=Formato de URL do issue tracker externo +settings.tracker_issue_style=Formato de número do issue tracker externo settings.tracker_issue_style.numeric=Numérico settings.tracker_issue_style.alphanumeric=Alfanumérico +settings.tracker_url_format_desc=Use os espaços reservados {user}, {repo} e {index} para o nome de usuário, nome do repositório e o índice de problemas. +settings.enable_timetracker=Habilitar contador de tempo +settings.allow_only_contributors_to_track_time=Permitir que apenas os colaboradores acompanhem o contador de tempo +settings.pulls_desc=Habilitar pull requests no repositório +settings.pulls.ignore_whitespace=Ignorar espaço em branco em conflitos +settings.pulls.allow_merge_commits=Habilitar commit no merge +settings.pulls.allow_rebase_merge=Habilitar Rebasing em commits via merge +settings.pulls.allow_squash_commits=Habilitar Squashing em commits via merge +settings.admin_settings=Configurações do administrador +settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório settings.danger_zone=Zona de perigo -settings.new_owner_has_same_repo=O novo dono já tem um repositório com o mesmo nome. Por favor, escolha outro nome. +settings.new_owner_has_same_repo=O novo proprietário já tem um repositório com o mesmo nome. Por favor, escolha outro nome. +settings.convert=Converter para repositório tradicional +settings.convert_desc=Você pode converter este espelho em um repositório tradicional. Esta ação não pode ser revertida. +settings.convert_notices_1=Esta operação vai converter este repositório espelho em um repositório tradicional. Esta ação não pode ser desfeita. +settings.convert_confirm=Converter o repositório +settings.convert_succeed=O espelho foi convertido em um repositório comum. settings.transfer=Transferir propriedade +settings.transfer_desc=Transferir este repositório para outro usuário ou para uma organização onde você tem direitos de administrador. +settings.transfer_notices_1=- Você perderá o acesso ao repositório se transferir para um usuário individual. +settings.transfer_notices_2=- Você manterá acesso ao repositório se transferi-lo para uma organização que você também é proprietário. +settings.transfer_form_title=Digite o nome do repositório para confirmar: +settings.wiki_delete=Excluir dados da wiki +settings.wiki_delete_desc=A exclusão de dados da wiki é permanente e não pode ser desfeita. +settings.wiki_delete_notices_1=- Isso excluirá e desabilitará permanentemente a wiki do repositório %s. +settings.confirm_wiki_delete=Excluir dados da wiki +settings.wiki_deletion_success=Os dados da wiki do repositório foi excluídos. settings.delete=Excluir este repositório +settings.delete_desc=A exclusão de um repositório é permanente e não pode ser desfeita. settings.delete_notices_1=-Esta operação NÃO PODERÁ ser desfeita. -settings.transfer_owner=Novo dono +settings.delete_notices_2=- Essa operação excluirá permanentemente o repositório %s, incluindo código, issues, comentários, dados da wiki e configurações do colaborador. +settings.delete_notices_fork_1=- Forks deste repositório se tornarão independentes após a exclusão. +settings.deletion_success=O repositório foi excluído. +settings.update_settings_success=As configurações do repositório foram atualizadas. +settings.transfer_owner=Novo proprietário +settings.make_transfer=Executar transferência +settings.transfer_succeed=O repositório foi transferido. +settings.confirm_delete=Excluir repositório +settings.add_collaborator=Adicionar colaborador +settings.add_collaborator_success=O colaborador foi adicionado. +settings.delete_collaborator=Remover +settings.collaborator_deletion=Remover colaborador +settings.collaborator_deletion_desc=A exclusão de um colaborador irá revogar o acesso a este repositório. Continuar? +settings.remove_collaborator_success=O colaborador foi removido. settings.search_user_placeholder=Pesquisar usuário... +settings.org_not_allowed_to_be_collaborator=Organizações não podem ser adicionadas como um colaborador. +settings.user_is_org_member=O usuário é um membro da organização e não pode ser adicionado como um colaborador. settings.add_webhook=Adicionar webhook +settings.hooks_desc=Webhooks automaticamente fazem requisições de HTTP POST para um servidor quando acionados determinados eventos de Gitea. Leia mais no guia de webhooks. +settings.webhook_deletion=Remover webhook +settings.webhook_deletion_desc=A exclusão de um webhook exclui suas configurações e o histórico de entrega. Continuar? +settings.webhook_deletion_success=O webhook foi removido. settings.webhook.test_delivery=Entrega de teste +settings.webhook.test_delivery_desc=Teste este webhook com um falso evento. +settings.webhook.test_delivery_success=Um falso webhook foi adicionado a fila de envio. Pode levar alguns segundos até ele apareça no histórico de envio. settings.webhook.request=Solicitação settings.webhook.response=Resposta settings.webhook.headers=Cabeçalhos +settings.webhook.payload=Conteúdo settings.webhook.body=Corpo -settings.githook_edit_desc=Se o hook não estiver ativo, o conteúdo de exemplo será apresentado. Deixar o conteúdo em branco irá desativar esse hook. +settings.githooks_desc=Hooks do Git são ofertados pelo próprio Git, você pode editar arquivos de hooks suportados na lista abaixo para aplicar operações personalizadas. +settings.githook_edit_desc=Se o hook não estiver ativo, o conteúdo de exemplo será apresentado. Deixar o conteúdo em branco irá desabilitar esse hook. settings.githook_name=Nome do Hook settings.githook_content=Conteúdo do Hook settings.update_githook=Atualizar Hook +settings.add_webhook_desc=Gitea enviará requisições POST com um tipo de conteúdo especificado para a URL de destino. Leia mais no guia de webhooks. +settings.payload_url=URL de destino +settings.content_type=Tipo de conteúdo POST settings.secret=Senha settings.slack_username=Nome de usuário settings.slack_icon_url=URL do ícone -settings.discord_username=Usuário +settings.discord_username=Nome de usuário settings.discord_icon_url=URL do ícone settings.slack_color=Cor +settings.event_desc=Acionado em: +settings.event_push_only=Eventos de push +settings.event_send_everything=Todos os eventos +settings.event_choose=Eventos personalizados... settings.event_create=Criar +settings.event_create_desc=Branch ou tag criado. settings.event_pull_request=Pull request +settings.event_pull_request_desc=Pull request aberto, fechado, reaberto, atribuído, desatribuído, teve etiqueta atualizada ou limpada ou foi sincronizado. settings.event_push=Push +settings.event_push_desc=Git push para o repositório. settings.event_repository=Repositório +settings.event_repository_desc=Repositório criado ou excluído. +settings.active=Incluir detalhes do evento +settings.active_helper=Adicione informações sobre o evento de acionamento para requisições. +settings.add_hook_success=O webhook foi adicionado. settings.update_webhook=Atualizar webhook +settings.update_hook_success=O webhook foi atualizado. +settings.delete_webhook=Remover webhook settings.recent_deliveries=Entregas Recentes settings.hook_type=Tipo de Hook +settings.add_slack_hook_desc=Integre o Slack em seu repositório. settings.slack_token=Token settings.slack_domain=Domínio settings.slack_channel=Canal +settings.add_discord_hook_desc=Integre o Discord em seu repositório. +settings.add_dingtalk_hook_desc=Integre o Dingtalk em seu repositório. settings.deploy_keys=Chaves de Deploy settings.add_deploy_key=Nova chave +settings.deploy_key_desc=As chaves de deploy possuem somente acesso de leitura (pull) ao repositório. +settings.is_writable=Habilitar acesso de escrita +settings.is_writable_info=Permitir que esta chave de deploy faça push para o repositório. +settings.no_deploy_keys=Não há nenhuma chave de deploy ainda. settings.title=Título settings.deploy_key_content=Conteúdo da chave +settings.key_been_used=Uma chave de deploy com conteúdo idêntico já está em uso. +settings.key_name_used=Uma chave de deploy já existe com esse mesmo nome. +settings.add_key_success=A chave de deploy '%s' foi adicionada. +settings.deploy_key_deletion=Remover chave de deploy +settings.deploy_key_deletion_desc=A exclusão de uma chave de deploy irá revogar o seu acesso a este repositório. Continuar? +settings.deploy_key_deletion_success=A chave de deploy foi removida. settings.branches=Branches settings.protected_branch=Proteção de Branch settings.protected_branch_can_push=Permitir push? settings.protected_branch_can_push_yes=Você pode fazer push settings.protected_branch_can_push_no=Você não pode fazer push +settings.branch_protection=Proteção de branch para '%s' +settings.protect_this_branch=Habilitar proteção de branch +settings.protect_this_branch_desc=Evitar exclusão e desabilitar Git force pushing para o branch. +settings.protect_whitelist_committers=Habilitar lista branca de push +settings.protect_whitelist_committers_desc=Permitir que usuários ou equipes da lista branca possam contornar restrições de push. +settings.protect_whitelist_users=Usuários da lista branca permitidos para realizar push: +settings.protect_whitelist_search_users=Pesquisar usuários... +settings.protect_whitelist_teams=Equipes da lista branca permitidos para realizar push: +settings.protect_whitelist_search_teams=Pesquisar equipes... +settings.protect_merge_whitelist_committers=Habilitar lista branca de merge +settings.protect_merge_whitelist_committers_desc=Permitir que somente usuários ou equipes que estão na lista branca façam merge de pull requests neste branch. +settings.protect_merge_whitelist_users=Usuários da lista branca permitidos para realizar merge: +settings.protect_merge_whitelist_teams=Times da lista branca permitidos para realizar merge: settings.add_protected_branch=Habilitar proteção settings.delete_protected_branch=Desabilitar proteção +settings.update_protect_branch_success=Proteção do branch '%s' foi atualizada. +settings.remove_protected_branch_success=Proteção do branch '%s' foi desabilitada. +settings.protected_branch_deletion=Desabilitar proteção de branch +settings.protected_branch_deletion_desc=Desabilitar a proteção de branch permite que os usuários com permissão de escrita realizem push. Continuar? +settings.default_branch_desc=Selecione um branch padrão para pull requests e commits de código: settings.choose_branch=Escolha um branch... +settings.no_protected_branch=Não há branches protegidos. diff.browse_source=Ver código fonte diff.parent=pai @@ -611,6 +1057,7 @@ diff.view_file=Ver arquivo diff.file_suppressed=Diferenças do arquivo suprimidas por serem muito extensas diff.too_many_files=Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff +releases.desc=Acompanhe as versões e downloads do projeto. release.releases=Versões release.new_release=Nova versão release.draft=Rascunho @@ -619,26 +1066,50 @@ release.stable=Estável release.edit=editar release.ahead=%d commits para %s depois desta versão release.source_code=Código fonte +release.new_subheader=Lançamentos organizam versões do projeto. +release.edit_subheader=Lançamentos organizam versões do projeto. release.tag_name=Nome da tag release.target=Destino +release.tag_helper=Escolha uma tag existente, ou crie uma nova tag. release.title=Título release.content=Conteúdo release.write=Escrever release.preview=Visualizar release.loading=Carregando… +release.prerelease_desc=Marcar como pré-lançamento +release.prerelease_helper=Marcar esta versão como inadequada para uso em produção. release.cancel=Cancelar release.publish=Publicar versão release.save_draft=Salvar rascunho +release.edit_release=Atualizar versão +release.delete_release=Excluir versão +release.deletion=Excluir versão +release.deletion_desc=A exclusão de uma versão remove sua tag Git do repositório. Histórico e conteúdo do repositório permanecem inalterados. Continuar? release.deletion_success=A versão foi excluída. +release.tag_name_already_exist=Uma versão com esse nome de tag já existe. +release.tag_name_invalid=O nome da tag não é válido. release.downloads=Downloads +branch.name=Nome da branch branch.search=Pesquisar branches +branch.already_exists=Uma branch com o nome %s já existe. branch.delete_head=Excluir +branch.delete=Excluir branch '%s' branch.delete_html=Excluir Branch +branch.delete_desc=A exclusão de uma branch é permanente. Isto NÃO PODERÁ ser desfeito. Continuar? +branch.deletion_success=A branch '%s' foi excluída. +branch.deletion_failed=Falha ao excluir a branch %s. +branch.delete_branch_has_new_commits=A branch %s não pode ser excluída porque há novos commits após o merge. branch.create_branch=Criar branch %s branch.create_from=de %s +branch.create_success=A branch '%s' foi criada. branch.branch_already_exists=Branch '%s' já existe neste repositório. +branch.branch_name_conflict=O nome da branch '%s' está em conflito com a branch '%s'. +branch.tag_collision=A branch '%s' não pode ser criada como tag com o mesmo nome já existente neste repositório. branch.deleted_by=Excluído por %s +branch.restore_success=A branch '%s' foi restaurada. +branch.restore_failed=Falha ao restaurar a branch %s. +branch.protected_deletion_failed=A branch '%s' está protegida. Ela não pode ser excluída. topic.manage_topics=Gerenciar Tópicos topic.done=Feito @@ -646,6 +1117,7 @@ topic.done=Feito [org] org_name_holder=Nome da organização org_full_name_holder=Nome completo da organização +org_name_helper=Nomes de organização devem ser curtos e memoráveis. create_org=Criar organização repo_updated=Atualizado people=Pessoas @@ -657,22 +1129,39 @@ create_team=Criar equipe org_desc=Descrição team_name=Nome da equipe team_desc=Descrição +team_name_helper=Nomes de equipe devem ser curtos e memoráveis. +team_desc_helper=Descreva a finalidade ou o papel da equipe. +team_permission_desc=Permissão +team_unit_desc=Permitir o acesso a seções de repositório +form.name_reserved=O nome de organização '%s' está reservado. +form.name_pattern_not_allowed=O padrão de '%s' não é permitido em um nome de organização. +form.create_org_not_allowed=Você não tem permissão para criar uma organização. settings=Configurações +settings.options=Organização settings.full_name=Nome completo settings.website=Site settings.location=Localização settings.update_settings=Atualizar Configurações settings.update_setting_success=Configurações da organização foram atualizadas. +settings.change_orgname_prompt=Nota: mudar o nome da organização também altera a URL da mesma. +settings.update_avatar_success=O avatar da organização foi atualizado. settings.delete=Excluir organização settings.delete_account=Excluir esta organização +settings.delete_prompt=A organização será excluída permanentemente. Isto NÃO PODERÁ ser desfeito! settings.confirm_delete_account=Confirmar exclusão -settings.hooks_desc=Adicionar Webhooks que serão disparados para todos os repositórios desta organização. +settings.delete_org_title=Excluir organização +settings.delete_org_desc=Essa organização será excluída permanentemente. Continuar? +settings.hooks_desc=Adicionar Webhooks que serão acionados para todos os repositórios desta organização. members.membership_visibility=Visibilidade da associação: +members.public=Público +members.public_helper=tornar privado +members.private=Privado +members.private_helper=tornar público members.member_role=Categoria de membro: -members.owner=Dono +members.owner=Proprietário members.member=Membro members.remove=Remover members.leave=Sair @@ -682,13 +1171,24 @@ members.invite_now=Convidar agora teams.join=Juntar-se teams.leave=Deixar teams.read_access=Acesso de leitura +teams.read_access_helper=Os membros podem ver e clonar os repositórios da equipe. teams.write_access=Acesso de escrita +teams.write_access_helper=Os membros podem ler e realizar push para os repositórios da equipe. +teams.admin_access=Acesso de administrador +teams.admin_access_helper=Os membros podem realizar pull e push em repositórios da equipe e adicionar colaboradores a eles. teams.no_desc=Esta equipe não tem descrição teams.settings=Configurações +teams.owners_permission_desc=Proprietários tem acesso total a todos repositórios e também direitos de administrador na organização. teams.members=Membros da equipe teams.update_settings=Atualizar configurações +teams.delete_team=Excluir equipe teams.add_team_member=Adicionar membro na equipe +teams.delete_team_title=Excluir equipe +teams.delete_team_desc=A exclusão de uma equipe revoga o acesso ao repositório de seus membros. Continuar? teams.delete_team_success=A equipe foi excluída. +teams.read_permission_desc=Essa equipe concede acesso para Leitura: membros podem ver e clonar os repositórios da equipe. +teams.write_permission_desc=Esta equipe concede acesso para escrita: Membros podem ler e fazer push para os repositórios da equipe. +teams.admin_permission_desc=Esta equipe concede acesso de Administrador: Membros podem ler, fazer push e adicionar outros colaboradores para os repositórios da equipe. teams.repositories=Repositórios da equipe teams.search_repo_placeholder=Pesquisar repositório... teams.add_team_repository=Adicionar repositório da equipe @@ -697,8 +1197,10 @@ teams.add_nonexistent_repo=O repositório que você está tentando adicionar nã [admin] dashboard=Painel +users=Contas de usuário organizations=Organizações repositories=Repositórios +authentication=Fontes de autenticação config=Configuração notices=Avisos do sistema monitor=Monitoramento @@ -706,6 +1208,10 @@ first_page=Primeira last_page=Última total=Total: %d +dashboard.statistic=Resumo +dashboard.operations=Operações de manutenção +dashboard.system_status=Status do sistema +dashboard.statistic_info=O banco de dados do Gitea contém %d usuários, %d organizações, %d chaves públicas, %d repositórios, %d observadores, %d favoritos, %d ações, %d acessos, %d questões, %d comentários, %d contas sociais, %d seguidores, %d espelhos, %d versões, %d origens de login, %d Hooks da Web, %d marcos, %d etiquetas, %d tarefas hook, %d equipes, %d tarefas de atualização, %d anexos. dashboard.operation_name=Nome da operação dashboard.operation_switch=Trocar dashboard.operation_run=Executar @@ -713,16 +1219,30 @@ dashboard.clean_unbind_oauth=Limpar conexões OAuth não vinculadas dashboard.clean_unbind_oauth_success=Todas as conexões de OAuth não vinculadas foram excluídas. dashboard.delete_inactivate_accounts=Excluir todas as contas inativas dashboard.delete_inactivate_accounts_success=Todas as contas inativas foram excluídas. +dashboard.delete_repo_archives=Excluir todos os arquivos do repositório +dashboard.delete_repo_archives_success=Todos os arquivos do repositório foram excluídos. +dashboard.delete_missing_repos=Excluir todos os repositórios que não possuem seus arquivos Git +dashboard.delete_missing_repos_success=Todos os repositórios que não possuem seus arquivos Git foram excluídos. +dashboard.git_gc_repos=Coleta de lixo em todos os repositórios +dashboard.git_gc_repos_success=Todos os repositórios finalizaram a execução da coleta de lixo. +dashboard.resync_all_sshkeys=Atualizar o arquivo '.ssh/authorized_keys' com as chaves SSH do Gitea. (Não necessária para o servidor SSH nativo.) +dashboard.resync_all_sshkeys_success=As chaves públicas de SSH controladas pelo Gitea foram atualizadas. +dashboard.resync_all_hooks=Ressincronizar hooks pre-receive, update e post-receive de todos os repositórios. +dashboard.resync_all_hooks_success=Todos os hooks pre-receive, update e post-receive de todos os repositórios foram sincronizados. dashboard.reinit_missing_repos=Reinicializar todos os repositórios Git perdidos cujos registros existem dashboard.reinit_missing_repos_success=Todos os repositórios Git cujos registros existem foram reinicializados. dashboard.sync_external_users=Sincronizar dados de usuário externo +dashboard.sync_external_users_started=A sincronização de dados do usuário externo foi iniciada. dashboard.git_fsck=Execute verificações de integridade em todos os repositórios +dashboard.git_fsck_started=Verificações de integridade do repositório iniciada. dashboard.server_uptime=Tempo de atividade do Servidor dashboard.current_goroutine=Goroutines Atuais dashboard.current_memory_usage=Uso de memória atual dashboard.total_memory_allocated=Total de memória alocada dashboard.memory_obtained=Memória obtida dashboard.pointer_lookup_times=Nº de consultas a ponteiros +dashboard.memory_allocate_times=Alocações de memória +dashboard.memory_free_times=Liberações de memória dashboard.current_heap_usage=Uso atual da heap dashboard.heap_memory_obtained=Memória de heap obtida dashboard.heap_memory_idle=Memória da heap ociosa @@ -745,18 +1265,43 @@ dashboard.total_gc_pause=Pausa total do GC dashboard.last_gc_pause=Última pausa do GC dashboard.gc_times=Nº de execuções do GC +users.user_manage_panel=Gerenciamento de conta de usuário +users.new_account=Criar conta de usuário +users.name=Nome de usuário users.activated=Ativado users.admin=Administrador users.repos=Repositórios users.created=Criado +users.last_login=Último acesso +users.never_login=Nunca acessado +users.send_register_notify=Enviar notificação de cadastro de usuário +users.new_success=A conta de usuário '%s' foi criada. users.edit=Editar users.auth_source=Fonte da autenticação users.local=Local +users.auth_login_name=Nome de acesso da autenticação +users.password_helper=Deixe a senha em branco para mantê-la inalterada. +users.update_profile_success=A conta de usuário foi atualizada. +users.edit_account=Editar a conta de usuário +users.max_repo_creation=Número máximo de repositórios +users.max_repo_creation_desc=(Use -1 para usar o limite padrão global.) +users.is_activated=Conta de usuário está ativada +users.prohibit_login=Desabilitar acesso +users.is_admin=É administrador +users.allow_git_hook=Pode criar hooks Git +users.allow_import_local=Pode importar repositórios locais +users.allow_create_organization=Pode criar organizações +users.update_profile=Atualizar conta de usuário +users.delete_account=Excluir conta de usuário +users.still_own_repo=Este usuário ainda possui um ou mais repositórios. Exclua ou transfira esses repositórios primeiro. +users.still_has_org=Este usuário é membro de uma organização. Remova o usuário de qualquer organização primeiro. +users.deletion_success=A conta de usuário foi excluída. -orgs.org_manage_panel=Gerenciar Organizações +orgs.org_manage_panel=Gerenciamento da organização orgs.name=Nome orgs.teams=Equipes orgs.members=Membros +orgs.new_orga=Nova organização repos.repo_manage_panel=Gerenciamento do repositório repos.owner=Proprietário @@ -767,9 +1312,12 @@ repos.stars=Favoritos repos.issues=Issues repos.size=Tamanho +auths.auth_manage_panel=Gerenciamento de fonte de autenticação +auths.new=Adicionar fonte de autenticação auths.name=Nome auths.type=Tipo auths.enabled=Habilitado +auths.syncenabled=Habilitar sincronização de usuário auths.updated=Atualizado auths.auth_type=Tipo de autenticação auths.auth_name=Nome da autenticação @@ -779,8 +1327,15 @@ auths.host=Servidor auths.port=Porta auths.bind_dn=Vincular DN auths.bind_password=Vincular senha +auths.bind_password_helper=Atenção: Esta senha é armazenada em texto sem formatação. Se possível, use uma conta de somente leitura. auths.user_base=Base de pesquisa do usuário auths.user_dn=Usuário do DN +auths.attribute_username=Atributo nome de usuário +auths.attribute_username_placeholder=Deixe em branco para usar o nome de usuário inserido no Gitea. +auths.attribute_name=Atributo primeiro nome +auths.attribute_surname=Atributo sobrenome +auths.attribute_mail=Atributo e-mail +auths.attributes_in_bind=Buscar os atributos no contexto de Bind DN auths.filter=Filtro de usuário auths.admin_filter=Filtro de administrador auths.ms_ad_sa=Atributos de pesquisa do MS AD @@ -788,6 +1343,7 @@ auths.smtp_auth=Tipo de autenticação SMTP auths.smtphost=Host SMTP auths.smtpport=Porta SMTP auths.allowed_domains=Domínios permitidos +auths.allowed_domains_helper=Deixe em branco para permitir todos os domínios. Separe vários domínios com uma vírgula (','). auths.enable_tls=Habilitar Criptografia TLS auths.skip_tls_verify=Pular verificação de TLS auths.pam_service_name=Nome de Serviço PAM @@ -795,36 +1351,58 @@ auths.oauth2_provider=Provedor OAuth2 auths.oauth2_clientID=ID do cliente (chave) auths.oauth2_clientSecret=Senha do cliente auths.openIdConnectAutoDiscoveryURL=URL do OpenID Connect Auto Discovery +auths.oauth2_use_custom_url=Usar URLs personalizadas em vez de URLs padrão auths.oauth2_tokenURL=URL do Token auths.oauth2_authURL=URL de Authorização auths.oauth2_profileURL=URL do perfil auths.oauth2_emailURL=URL de e-mail -auths.enable_auto_register=Habilitar Registro Automático +auths.enable_auto_register=Habilitar cadastro automático auths.tips=Dicas auths.tips.oauth2.general=Autenticação OAuth2 -auths.tips.oauth2.general.tip=Ao registrar uma nova autenticação OAuth2, o retorno de chamada/redirecionamento URL deve ser: /user/oauth2//callback +auths.tips.oauth2.general.tip=Ao cadastrar uma nova autenticação OAuth2, o retorno de chamada/redirecionamento URL deve ser: /user/oauth2//callback auths.tip.oauth2_provider=Provedor OAuth2 +auths.tip.bitbucket=Cadastrar um novo consumidor de OAuth em https://bitbucket.org/account/user/ e adicionar a permissão 'Account' - 'Read' auths.tip.dropbox=Criar um novo aplicativo em https://www.dropbox.com/developers/apps -auths.tip.facebook=Registrar um novo aplicativo em https://developers.facebook.com/apps e adicionar o produto "Facebook Login -auths.tip.github=Registrar um novo aplicativo de OAuth na https://github.com/settings/applications/new -auths.tip.gitlab=Registrar um novo aplicativo em https://gitlab.com/profile/applications +auths.tip.facebook=Cadastrar um novo aplicativo em https://developers.facebook.com/apps e adicionar o produto "Facebook Login +auths.tip.github=Cadastrar um novo aplicativo de OAuth na https://github.com/settings/applications/new +auths.tip.gitlab=Cadastrar um novo aplicativo em https://gitlab.com/profile/applications +auths.tip.google_plus=Obter credenciais de cliente OAuth2 do console de API do Google em https://console.developers.google.com/ auths.tip.openid_connect=Use o OpenID Connect Discovery URL (/.well-known/openid-configuration) para especificar os endpoints +auths.tip.twitter=Vá em https://dev.twitter.com/apps, crie um aplicativo e certifique-se de que está habilitada a opção “Allow this application to be used to Sign in with Twitter“ +auths.edit=Editar fonte de autenticação +auths.activated=Esta fonte de autenticação está ativada auths.new_success=A autenticação '%s' foi adicionada. +auths.update_success=A fonte de autenticação foi atualizada. +auths.update=Atualizar fonte de autenticação +auths.delete=Excluir fonte de autenticação auths.delete_auth_title=Excluir a Fonte de Autenticação +auths.delete_auth_desc=A exclusão de uma fonte de autenticação impede que os usuários a usem para acessar. Continuar? +auths.still_in_used=A fonte de autenticação ainda está em uso. Converta ou exclua todos os usuários que usam essa fonte de autenticação primeiro. +auths.deletion_success=A fonte de autenticação foi excluída. +auths.login_source_exist=A fonte de autenticação '%s' já existe. config.server_config=Configuração do servidor +config.app_name=Título do site +config.app_ver=Versão do Gitea +config.app_url=URL base do Gitea config.custom_conf=Caminho do Arquivo de Configuração +config.domain=Domínio do servidor SSH +config.offline_mode=Modo local config.disable_router_log=Desabilitar o Log do roteador +config.run_user=Executar como nome de usuário config.run_mode=Modo de execução config.git_version=Versão do Git config.repo_root_path=Caminho raiz do repositório config.lfs_root_path=Caminho raiz do LFS config.static_file_root_path=Caminho raiz para arquivo estático +config.log_file_root_path=Caminho do log config.script_type=Tipo de script config.reverse_auth_user=Usuário de autenticação reversa config.ssh_config=Configuração de SSH config.ssh_enabled=Habilitado +config.ssh_start_builtin_server=Usar o servidor embutido +config.ssh_domain=Domínio do servidor config.ssh_port=Porta config.ssh_listen_port=Porta de escuta config.ssh_root_path=Caminho da raiz @@ -837,21 +1415,37 @@ config.db_config=Configuração do banco de dados config.db_type=Tipo config.db_host=Servidor config.db_name=Nome +config.db_user=Nome de usuário +config.db_ssl_mode=SSL config.db_ssl_mode_helper=(apenas para "postgres") config.db_path=Caminho config.db_path_helper=(para "sqlite3" e "tidb") config.service_config=Configuração do serviço -config.show_registration_button=Mostrar botão de registo -config.disable_key_size_check=Desativar verificação de tamanho mínimo da chave +config.register_email_confirm=Exigir confirmação de e-mail para se cadastrar +config.disable_register=Desabilitar auto-cadastro +config.enable_openid_signup=Habilitar o auto-cadastro via OpenID +config.enable_openid_signin=Habilitar acesso via OpenID +config.show_registration_button=Mostrar botão de cadastro +config.require_sign_in_view=Exigir acesso do usuário para a visualização de páginas +config.mail_notify=Habilitar notificações de e-mail +config.disable_key_size_check=Desabilitar verificação de tamanho mínimo da chave +config.enable_captcha=Habilitar o CAPTCHA config.active_code_lives=Ativar Code Lives config.reset_password_code_lives=Validade de códigos de redefinição de senha +config.default_keep_email_private=Ocultar endereços de e-mail por padrão +config.default_allow_create_organization=Permitir a criação de organizações por padrão +config.enable_timetracking=Habilitar contador de tempo +config.default_enable_timetracking=Habilitar o contador de tempo por padrão +config.default_allow_only_contributors_to_track_time=Permitir que apenas os colaboradores acompanhem o contador de tempo +config.no_reply_address=Ocultar domínio de e-mail config.webhook_config=Configuração de Hook da Web config.queue_length=Tamanho da fila config.deliver_timeout=Intervalo de entrega config.skip_tls_verify=Ignorar verificação de TLS +config.mailer_config=Configuração SMTP para envio de e-mail config.mailer_enabled=Habilitado config.mailer_disable_helo=Desabilitar HELO config.mailer_name=Nome @@ -859,6 +1453,10 @@ config.mailer_host=Servidor config.mailer_user=Usuário config.mailer_use_sendmail=Usar o Sendmail config.mailer_sendmail_path=Caminho do Sendmail +config.mailer_sendmail_args=Argumentos extras para o Sendmail +config.send_test_mail=Enviar e-mail de teste +config.test_mail_failed=Falha ao enviar o e-mail de teste para '%s': %v +config.test_mail_sent=O e-mail de teste foi enviado para '%s'. config.oauth_config=Configuração do OAuth config.oauth_enabled=Habilitado @@ -878,12 +1476,13 @@ config.session_life_time=Tempo de vida da sessão config.https_only=Apenas HTTPS config.cookie_life_time=Tempo de vida do cookie +config.picture_config=Configuração de imagem e avatar config.picture_service=Serviço de imagens -config.disable_gravatar=Desativar Gravatar +config.disable_gravatar=Desabilitar o gravatar config.enable_federated_avatar=Habilitar avatares federativos config.git_config=Configuração do Git -config.git_disable_diff_highlight=Desativar realce de mudanças no diff +config.git_disable_diff_highlight=Desabilitar realce de mudanças no diff config.git_max_diff_lines=Máximo de linhas mostradas no diff (para um único arquivo) config.git_max_diff_line_characters=Máximo de caracteres mostrados no diff (para uma única linha) config.git_max_diff_files=Máximo de arquivos a serem mostrados no diff @@ -902,6 +1501,7 @@ monitor.name=Nome monitor.schedule=Cronograma monitor.next=Próxima vez monitor.previous=Vez anterior +monitor.execute_times=Execuções monitor.process=Processos em execução monitor.desc=Descrição monitor.start=Hora de início @@ -932,7 +1532,7 @@ create_pull_request=`criou o pull request %s#%[2]s` close_pull_request=`fechou o pull request %s#%[2]s` reopen_pull_request=`reabriu o pull request %s#%[2]s` comment_issue=`comentou sobre a issue %s#%[2]s` -merge_pull_request=`mesclou o pull request %s#%[2]s` +merge_pull_request=`fez o merge do pull request %s#%[2]s` transfer_repo=transferiu repositório de %s para %s push_tag=fez push da tag %[2]s para %[3]s delete_tag=excluiu tag %[2]s de %[3]s @@ -962,13 +1562,17 @@ raw_seconds=segundos raw_minutes=minutos [dropzone] +default_message=Arraste e solte arquivos aqui, ou clique para selecioná-los. +invalid_input_type=Você não pode enviar arquivos deste tipo. file_too_big=Tamanho de arquivo ({{filesize}} MB) excede o máximo de ({{maxFilesize}} MB). -remove_file=Remover +remove_file=Remover arquivo [notification] notifications=Notificações unread=Não lidas read=Lidas +no_unread=Nenhuma notificação não lida. +no_read=Nenhuma notificação lida. pin=Fixar notificação mark_as_read=Marcar como lida mark_as_unread=Marcar como não lida @@ -977,8 +1581,12 @@ mark_all_as_read=Marcar todas como lidas [gpg] error.extract_sign=Falha ao extrair assinatura error.generate_hash=Falha ao gerar hash de commit +error.no_committer_account=Nenhuma conta vinculada ao e-mail do autor do commit error.no_gpg_keys_found=Nenhuma chave conhecida encontrada para esta assinatura no banco de dados error.not_signed_commit=Não é um commit assinado +error.failed_retrieval_gpg_keys=Falha em obter qualquer chave anexada à conta do autor do commit [units] +error.no_unit_allowed_repo=Você não tem permissão para acessar nenhuma seção deste repositório. +error.unit_not_allowed=Você não tem permissão para acessar esta seção do repositório. diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index ee721133c..e98486926 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -1,10 +1,15 @@ +app_desc=Зручний сервіс, власного Git хостінгу home=Головна dashboard=Панель інструментів explore=Огляд help=Довідка sign_in=Увійти +sign_in_with=Увійти через sign_out=Вийти +sign_up=Реєстрація +link_account=Прив'язати обліковий запис +link_account_signin_or_signup=Увійдіть з уже існуючими обліковими даними або зареєструйтеся для зв'язку з цим аккаунтом. register=Реєстрація website=Web-сайт version=Версія @@ -12,10 +17,17 @@ page=Сторінка template=Шаблон language=Мова notifications=Сповіщення +create_new=Створити… +user_profile_and_more=Профіль і налаштування… signed_in_as=Увійшов як +enable_javascript=Цей веб-сайт працює краще з JavaScript. username=Ім'я кристувача +email=Адреса електронної пошти password=Пароль +re_type=Введіть пароль ще раз +captcha=CAPTCHA +twofa=Двофакторна авторизація passcode=Код доступу repository=Репозиторій @@ -29,6 +41,9 @@ new_org=Нова організація manage_org=Керування організаціями account_settings=Параметри облікового запису settings=Параметри +your_profile=Профіль +your_starred=Обрані +your_settings=Параметри all=Усі sources=Джерела @@ -36,38 +51,71 @@ mirrors=Дзеркала collaborative=Співпраця forks=Відгалуження -pull_requests=Запити до злиття +activities=Дії +pull_requests=Запити на злиття issues=Питання cancel=Відміна [install] install=Встановлення +title=Початкова конфігурація +docker_helper=Якщо ви запускаєте Gitea всередині Docker, будь ласка уважно прочитайте документацію перед тим, як що-небудь змінити на цій сторінці. +requite_db_desc=Gitea потребує MySQL, PostgreSQL, MSSQL, SQLite3 або TiDB. +db_title=Налаштування бази даних +db_type=Тип бази даних +host=Хост +user=Ім'я кристувача password=Пароль db_name=Ім'я бази даних +ssl_mode=SSL path=Шлях +err_empty_db_path=Шлях до бази даних SQLite3 або TiDB не може бути порожнім. +no_admin_and_disable_registration=Ви не можете вимкнути реєстрацію до створення облікового запису адміністратора. +general_title=Загальні налаштування +app_name=Назва сайту repo_path=Кореневий шлях репозиторія +repo_path_helper=Всі вилучені Git репозиторії будуть збережені в цей каталог. +lfs_path=Кореневої шлях Git LFS +lfs_path_helper=У цій папці будуть зберігатися файли Git LFS. Залиште порожнім, щоб відключити LFS. +ssh_port=Порт SSH сервера +ssh_port_helper=Номер порту, який використовує SSH сервер. Залиште порожнім, щоб відключити SSH. +app_url=Базова URL-адреса Gitea +log_root_path=Шлях до лог файлу optional_title=Додаткові налаштування +email_title=Налаштування Email smtp_host=SMTP хост +smtp_from=Відправляти Email від імені +mailer_user=SMTP Ім'я кристувача +mailer_password=SMTP Пароль +mail_notify=Дозволити поштові повідомлення +disable_gravatar=Вимкнути Gravatar +federated_avatar_lookup=Увімкнути зовнішні аватари federated_avatar_lookup_popup=Увімкнути зовнішний Аватар за допомогою Libravatar. openid_signin=Увімкнути реєстрацію за допомогою OpenID +enable_captcha=Увімкнути CAPTCHA enable_captcha_popup=Вимагати перевірку CAPTCHA при самостійній реєстрації користувача. +admin_name=Ім'я кристувача Адміністратора admin_password=Пароль confirm_password=Підтвердження пароля +admin_email=Адреса електронної пошти install_btn_confirm=Встановлення Gitea test_git_failed=Не в змозі перевірити 'git' команду: %v save_config_failed=Не в змозі зберегти конфігурацію: %v +install_success=Ласкаво просимо! Дякуємо вам за вибір Gitea. Розважайтеся, і будьте обережні! [home] password_holder=Пароль switch_dashboard_context=Змінити дошку my_repos=Мої репозиторії +show_more_repos=Показати більше репозиторіїв… collaborative_repos=Спільні репозиторії my_orgs=Мої організації my_mirrors=Мої дзеркала view_home=Переглянути %s +search_repos=Шукати репозиторій… issues.in_your_repos=В ваших репозиторіях @@ -76,21 +124,43 @@ repos=Репозиторії users=Користувачі organizations=Організації search=Пошук +code=Код [auth] +create_new_account=Реєстрація аккаунта register_helper_msg=Вже зареєстровані? Увійдіть зараз! +disable_register_prompt=Вибачте, можливість реєстрації відключена. Будь ласка, зв'яжіться з адміністратором сайту. remember_me=Запам'ятати мене forgot_password_title=Забув пароль forgot_password=Забули пароль? +sign_up_now=Потрібен аккаунт? Зареєструватися. +confirmation_mail_sent_prompt=Новий лист для підтвердження було направлено на %s, будь ласка, перевірте вашу поштову скриньку протягом% s для завершення реєстрації. +reset_password_mail_sent_prompt=Лист для підтвердження було направлено на %s. Будь ласка, перевірте вашу поштову скриньку протягом% s для скидання пароля. active_your_account=Активувати обліковий запис +prohibit_login=Вхід заборонений +prohibit_login_desc=Вхід для вашого профілю був заборонений, будь ласка, зв'яжіться з адміністратором сайту. +resent_limit_prompt=Вибачте, ви вже запросили активацію по електронній пошті нещодавно. Будь ласка, зачекайте 3 хвилини, а потім спробуйте ще раз. +has_unconfirmed_mail=Привіт %s, у вас є непідтвердженими адреси (%s). Якщо ви не отримали підтвердження електронною поштою або треба відправити нове, будь ласка, натисніть на кнопку нижче. +resend_mail=Натисніть тут, щоб вислати лист активації знову +email_not_associate=Ця електронна пошта не пов'язана ні з одним обліковим записом. +send_reset_mail=Натисніть сюди, щоб відправити лист для скидання пароля reset_password=Скинути пароль +invalid_code=Цей код підтвердження недійсний або закінчився. reset_password_helper=Натисніть тут для скидання пароля password_too_short=Довжина пароля не може бути меншою за %d. +non_local_account=Нелокальні акаунти не можуть змінити пароль через Gitea. verify=Підтвердити +scratch_code=Одноразовий пароль +use_scratch_code=Використовувати одноразовий пароль +twofa_scratch_used=Ви використовували scratch-код. Ви були перенаправлені на сторінку налаштувань для генерації нового коду або відключення двуфакторной аутентифікації. +twofa_passcode_incorrect=Ваш пароль є невірним. Якщо ви втратили пристрій, використовуйте ваш одноразовий пароль. +twofa_scratch_token_incorrect=Невірний одноразовий пароль. +login_userpass=Увійти login_openid=OpenID openid_connect_submit=Під’єднатися openid_connect_title=Підключитися до існуючого облікового запису openid_register_title=Створити новий обліковий запис +disable_forgot_password_mail=На жаль скидання пароля відключене. Будь ласка, зв'яжіться з адміністратором сайту. [mail] activate_account=Будь ласка, активуйте ваш обліковий запис @@ -102,14 +172,17 @@ register_notify=Ласкаво просимо у Gitea [modal] yes=Так no=Ні +modify=Оновлення [form] UserName=Ім’я користувача RepoName=Назва репозиторію Email=Адреса електронної пошти Password=Пароль +Retype=Введіть пароль ще раз SSHTitle=Iм'я SSH ключа HttpsUrl=Адреса HTTPS +PayloadUrl=URL обробника TeamName=Назва команди AuthName=Назва авторизації AdminEmail=Email адміністратора @@ -121,10 +194,18 @@ TreeName=Шлях до файлу Content=Зміст require_error=` не може бути пустим.` +git_ref_name_error=` має бути правильним посилальним ім'ям Git.` +email_error=` не є адресою електронної пошти.` unknown_error=Невідома помилка: +password_not_match=Паролі не співпадають. +username_been_taken=Ім'я користувача вже зайнято. +repo_name_been_taken=Ім'я репозіторію вже використовується. +email_been_used=Ця електронна адреса вже використовується. +username_password_incorrect=Неправильне ім'я користувача або пароль. user_not_exist=Даний користувач не існує. +auth_failed=Помилка автентифікації: %v @@ -133,6 +214,7 @@ join_on=Приєднався repositories=Репозиторії activity=Публічна активність followers=Підписники +starred=Обрані Репозиторії following=Слідкувати follow=Підписатися unfollow=Відписатися @@ -144,10 +226,14 @@ profile=Профіль password=Пароль security=Безпека avatar=Аватар +ssh_gpg_keys=SSH / GPG ключи social=Соціальні акаунти +applications=Токени Доступу +orgs=Керування організаціями repos=Репозиторії delete=Видалити обліковий запис twofa=Двофакторна авторизація +organization=Організації uid=Ідентифікатор Uid public_profile=Загальнодоступний профіль @@ -159,16 +245,35 @@ update_profile_success=Профіль успішно оновлено. continue=Продовжити cancel=Відміна +federated_avatar_lookup=Знайти зовнішній аватар +enable_custom_avatar=Увімкнути користувацькі аватари +choose_new_avatar=Оберіть новий аватар +delete_current_avatar=Видалити поточний аватар +change_password=Оновити пароль old_password=Поточний пароль new_password=Новий пароль emails=Адреса електронної пошти +email_desc=Ваша основна адреса електронної пошти використовуватиметься для сповіщення та інших операцій. primary=Основний +delete_email=Видалити +manage_ssh_keys=Керувати SSH ключами +manage_gpg_keys=Керувати GPG ключами add_key=Додати ключ +ssh_helper=Потрібна допомога? Дивіться гід на GitHub з генерації ключів SSH або виправлення типових неполадок SSH. +add_new_key=Додати SSH ключ +add_new_gpg_key=Додати GPG ключ +key_id=ID ключа +key_name=Ім'я ключа key_content=Зміст +delete_key=Видалити +ssh_key_deletion=Видалити SSH ключ +gpg_key_deletion=Видалити GPG ключ add_on=Додано +valid_until=Дійсний до +valid_forever=Дійсний завжди last_used=Останнє використання no_activity=Жодної діяльності can_read_info=Читати @@ -178,7 +283,11 @@ token_state_desc=Цей токен використовувався в оста show_openid=Показати у профілю hide_openid=Не показувати у профілі +manage_social=Керувати зв'язаними аккаунтами соціальних мереж +generate_new_token=Згенерувати новий токен +token_name=Ім'я токену +generate_token=Згенерувати токен delete_token=Видалити @@ -186,37 +295,49 @@ delete_token=Видалити delete_account=Видалити ваш обліковий запис confirm_delete_account=Підтвердження видалення +delete_account_title=Видалити цей обліковий запис [repo] owner=Власник repo_name=Назва репозиторію visibility=Видимість +visiblity_helper=Зробити репозиторій приватним fork_repo=Відгалужити репозиторій fork_from=Відгалужена з repo_desc=Опис repo_lang=Мова +repo_gitignore_helper=Виберіть шаблон .gitignore. license=Ліцензія +license_helper=Виберіть ліцензійний файл. +readme_helper=Виберіть шаблон README. create_repo=Створити репозиторій default_branch=Головна гілка +mirror_prune=Очистити +watchers=Спостерігачі +form.reach_limit_of_creation=Ви досягли максимальної кількості %d створених репозиторіїв. migrate_type=Тип міграції +migrate_type_helper=Даний репозиторій буде дзеркалом migrate_repo=Перенесення репозиторія +migrate.failed=Міграція не вдалася: %v forked_from=відгалужено від copy_link=Копіювати copied=Скопійовано unwatch=Не стежити watch=Слідкувати -unstar=Зняти зірку -star=Зірка +unstar=Видалити із обраних +star=В обрані fork=Відгалуження +download_archive=Скачати репозиторій no_desc=Без опису quick_guide=Короткий посібник clone_this_repo=Кнонувати цей репозиторій create_new_repo_command=Створити новий репозиторій з командного рядка push_exist_repo=Опублікувати існуючий репозиторій з командного рядка +bare_message=Цей репозиторій порожній. code=Код branch=Гілка @@ -225,7 +346,7 @@ filter_branch_and_tag=Фільтрувати гілку або тег branches=Гілки tags=Теги issues=Питання -pulls=Запити до злиття +pulls=Запити на злиття labels=Мітки milestones=Етап commits=Зміни @@ -236,13 +357,26 @@ file_history=Історія file_view_raw=Перегляд Raw file_permalink=Постійне посилання +editor.new_file=Новий файл +editor.upload_file=Завантажити файл +editor.edit_file=Редагування файла editor.preview_changes=Попередній перегляд змін +editor.edit_this_file=Редагування файла +editor.delete_this_file=Видалити файл +editor.name_your_file=Дайте назву файлу… editor.or=або +editor.cancel_lower=Скасувати editor.commit_changes=Зафіксувати зміни +editor.add_tmpl=Додати '%s/' +editor.add=Додати '%s' +editor.update=Оновити '%s' +editor.delete=Видалити '%s' editor.cancel=Відміна +editor.upload_files_to_dir=Завантажувати файли до '%s' commits.commits=Зміни commits.find=Пошук +commits.search_all=Усі гілки commits.author=Автор commits.message=Повідомлення commits.date=Дата @@ -263,17 +397,54 @@ issues.new.assignee=Призначено issues.new.clear_assignee=Прибрати відповідального issues.new.no_assignee=Немає відповідального issues.new_label=Нова мітка +issues.new_label_placeholder=Назва мітки +issues.new_label_desc_placeholder=Опис issues.create_label=Створити мітку issues.label_templates.helper=Оберіть набір міток +issues.label_templates.fail_to_load_file=Не вдалося завантажити файл шаблона мітки '%s': %v +issues.deleted_milestone=`(видалено)` +issues.open_tab=%d відкрито +issues.close_tab=%d закрито +issues.filter_label=Мітка +issues.filter_milestone=Етап +issues.filter_milestone_no_select=Всі етапи +issues.filter_assignee=Відповідальний +issues.filter_type=Тип +issues.filter_type.all_issues=Всі проблемы +issues.filter_type.created_by_you=Створено вами +issues.filter_type.mentioning_you=Вас згадано +issues.filter_sort=Сортувати +issues.filter_sort.latest=Найновіші +issues.filter_sort.oldest=Найстаріші +issues.filter_sort.recentupdate=Нещодавно оновлено +issues.filter_sort.leastupdate=Найдавніше оновлені +issues.filter_sort.mostcomment=Найбільш коментовані +issues.filter_sort.leastcomment=Найменш коментовані +issues.action_open=Відкрити +issues.action_close=Закрити +issues.action_label=Мітка +issues.action_milestone=Етап +issues.action_milestone_no_select=Етап відсутній +issues.action_assignee=Відповідальний +issues.action_assignee_no_select=Немає відповідального +issues.opened_by=%[1]s відкрито %[3]s +issues.opened_by_fake=%[1]s відкрито %[2]s issues.previous=Попередній issues.next=Далі issues.open_title=Відкрити issues.closed_title=Закриті +issues.num_comments=%d коментарів +issues.commented_at=`відкоментовано %s` +issues.delete_comment_confirm=Ви впевнені, що хочете видалити цей коментар? issues.close_issue=Закрити +issues.close_comment_issue=Прокоментувати і закрити issues.reopen_issue=Відкрити знову issues.create_comment=Коментар +issues.closed_at=`закрито %[2]s` +issues.commit_ref_at=`згадано цю проблему в коміті %[2]s` issues.collaborator=Співавтор issues.owner=Власник +issues.sign_in_require_desc=Підпишіться щоб приєднатися до обговорення. issues.edit=Редагувати issues.cancel=Відміна issues.save=Зберегти @@ -287,18 +458,35 @@ issues.label.filter_sort.alphabetically=За абеткою issues.label.filter_sort.reverse_alphabetically=Зворотною абеткою issues.label.filter_sort.by_size=Розмір issues.label.filter_sort.reverse_by_size=Зворотний розмір +issues.num_participants=%d учасників +issues.attachment.open_tab=`Натисніть щоб побачити "%s" у новій вкладці` issues.subscribe=Підписатися issues.unsubscribe=Відписатися issues.start_tracking_short=Запустити issues.stop_tracking=Стоп +issues.add_time_short=Додати час issues.add_time_cancel=Відміна +issues.add_time_hours=Години +issues.add_time_minutes=Хвилини issues.cancel_tracking=Відміна pulls.new=Новий запит на злиття +pulls.compare_changes=Новий запит на злиття +pulls.filter_branch=Фільтр по гілці +pulls.no_results=Результатів не знайдено. pulls.create=Створити запит на злиття +pulls.title_desc=хоче злити %[1]d комітів з %[2]s до %[3]s +pulls.tab_commits=Комітів +pulls.reopen_to_merge=Будь ласка перевідкрийте цей запит щоб здіснити операцію злиття. +pulls.merged=Злито +pulls.can_auto_merge_desc=Цей запит можна об'єднати автоматично. pulls.merge_pull_request=Об'єднати запит на злиття milestones.new=Новий етап +milestones.open_tab=%d відкрито +milestones.close_tab=%d закрито +milestones.closed=Закрито %s +milestones.no_due_date=Немає дати завершення milestones.open=Відкрити milestones.close=Закрити milestones.create=Створити етап @@ -308,14 +496,31 @@ milestones.due_date=Дата завершення (опціонально) milestones.clear=Очистити milestones.edit=Редагувати етап milestones.cancel=Відміна +milestones.modify=Оновити етап wiki=Wiki wiki.page=Сторінка wiki.filter_page=Фільтр сторінок +wiki.new_page=Сторінка +wiki.save_page=Зберегти сторінку +wiki.edit_page_button=Редагувати +wiki.new_page_button=Нова сторінка +wiki.delete_page_button=Видалити сторінку +wiki.pages=Сторінки +wiki.last_updated=Останні оновлення %s +activity=Активність +activity.period.filter_label=Період: +activity.period.daily=1 день +activity.period.halfweekly=3 дні +activity.period.weekly=1 тиждень +activity.period.monthly=1 місяць +activity.overview=Огляд +activity.active_prs_count_n=%d Активні запити на злиття activity.merged_prs_count_1=Об'єднати запит на злиття activity.merged_prs_count_n=Об'єднати запити на злиття +activity.merged_prs_label=Злито activity.closed_issue_label=Закриті activity.new_issues_count_1=Нове обговорення activity.new_issues_count_n=Нове обговорення @@ -327,42 +532,114 @@ search=Пошук search.search_repo=Пошук репозиторію settings=Параметри +settings.options=Репозиторій +settings.collaboration.admin=Адміністратор settings.collaboration.write=Написати settings.collaboration.read=Читати +settings.collaboration.undefined=Не визначено +settings.hooks=Webhooks settings.basic_settings=Базові налаштування settings.mirror_settings=Налаштування дзеркала +settings.update_settings=Оновити налаштування +settings.advanced_settings=Додаткові налаштування settings.tracker_issue_style.numeric=Цифровий settings.tracker_issue_style.alphanumeric=Буквено-цифровий settings.danger_zone=Небезпечна зона settings.transfer_owner=Новий власник +settings.add_webhook=Додати Webhook +settings.webhook_deletion=Видалити Webhook +settings.webhook.request=Запит +settings.secret=Секрет +settings.slack_username=Ім'я кристувача +settings.slack_icon_url=URL іконки +settings.discord_username=Ім'я кристувача +settings.discord_icon_url=URL іконки settings.slack_color=Колір settings.event_create=Створити settings.event_pull_request=Запити до злиття +settings.event_push=Push settings.event_repository=Репозиторій +settings.update_webhook=Оновити Webhook +settings.slack_token=Токен +settings.slack_domain=Домен +settings.slack_channel=Канал +settings.deploy_keys=Ключи для розгортування +settings.add_deploy_key=Додати ключ для розгортування +settings.is_writable=Включити доступ для запису +settings.title=Заголовок +settings.branches=Гілки +settings.protected_branch_can_push=Дозволити push? +settings.protected_branch_can_push_yes=Ви можете виконувати push +settings.protected_branch_can_push_no=Ви не можете виконувати push +settings.add_protected_branch=Увімкнути захист +settings.delete_protected_branch=Вимкнути захист +settings.choose_branch=Оберіть гілку… +diff.browse_source=Переглянути джерело +diff.commit=коміт +diff.show_split_view=Розділений перегляд +diff.view_file=Переглянути файл +diff.too_many_files=Деякі файли не було показано, через те що забагато файлів було змінено +release.releases=Релізи +release.new_release=Новий реліз +release.draft=Чернетка +release.prerelease=Пре-реліз +release.stable=Стабільний +release.edit=редагувати +release.ahead=%d комітів %s після цього релізу +release.tag_name=Назва тегу +release.target=Ціль +release.title=Заголовок +release.preview=Переглянути +release.loading=Завантаження… release.cancel=Відміна +release.edit_release=Оновити реліз +release.delete_release=Видалити реліз +release.deletion=Видалити реліз +branch.delete_head=Видалити +topic.done=Готово [org] +org_name_holder=Назва організації +org_full_name_holder=Повна назва організації +settings=Налаштування +settings.update_settings=Оновити налаштування +teams.settings=Налаштування +teams.update_settings=Оновити налаштування teams.add_team_repository=Додати репозиторій команди [admin] +dashboard.delete_inactivate_accounts_success=Усі неактивні облікові записи успішно видалено. +dashboard.current_memory_usage=Поточне використання пам'яті +dashboard.memory_obtained=Отримано пам'яті + +users.name=Ім'я кристувача +config.db_config=Налаштування бази даних +config.db_type=Тип +config.db_host=Хост +config.db_name=Ім'я +config.db_user=Ім'я кристувача +config.db_ssl_mode=SSL +config.db_ssl_mode_helper=(тільки для "postgres") +config.db_path=Шлях +config.db_path_helper=(для "sqlite3" і "tidb") - +config.webhook_config=Налаштування Webhook @@ -374,12 +651,21 @@ teams.add_team_repository=Додати репозиторій команди [action] +merge_pull_request=`запит на злиття злито %s#%[2]s` [tool] [dropzone] +file_too_big=Розмір файлу ({{filesize}} MB), що більше ніж максимальний розмір: ({{maxFilesize}} MB). +remove_file=Видалити файл [notification] +notifications=Сповіщення +unread=Непрочитані +read=Прочитані +mark_as_read=Позначити як прочитане +mark_as_unread=Позначити як непрочитане +mark_all_as_read=Позначити всі як прочитані [gpg] diff --git a/public/swagger.v1.json b/public/swagger.v1.json index dec618988..86bf20a9a 100644 --- a/public/swagger.v1.json +++ b/public/swagger.v1.json @@ -1565,6 +1565,46 @@ } } }, + "/repos/{owner}/{repo}/hooks/{id}/tests": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Test a push webhook", + "operationId": "repoTestHook", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "id of the hook to test", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + } + } + } + }, "/repos/{owner}/{repo}/issue/{index}/comments": { "get": { "produces": [ diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 02606bdfd..eec55cac6 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -382,9 +382,12 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/hooks", func() { m.Combo("").Get(repo.ListHooks). Post(bind(api.CreateHookOption{}), repo.CreateHook) - m.Combo("/:id").Get(repo.GetHook). - Patch(bind(api.EditHookOption{}), repo.EditHook). - Delete(repo.DeleteHook) + m.Group("/:id", func() { + m.Combo("").Get(repo.GetHook). + Patch(bind(api.EditHookOption{}), repo.EditHook). + Delete(repo.DeleteHook) + m.Post("/tests", context.RepoRef(), repo.TestHook) + }) }, reqToken(), reqRepoWriter()) m.Group("/collaborators", func() { m.Get("", repo.ListCollaborators) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index b999d62aa..408d8921d 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -123,13 +123,10 @@ func EditTeam(ctx *context.APIContext, form api.EditTeamOption) { // responses: // "200": // "$ref": "#/responses/Team" - team := &models.Team{ - ID: ctx.Org.Team.ID, - OrgID: ctx.Org.Team.OrgID, - Name: form.Name, - Description: form.Description, - Authorize: models.ParseAccessMode(form.Permission), - } + team := ctx.Org.Team + team.Name = form.Name + team.Description = form.Description + team.Authorize = models.ParseAccessMode(form.Permission) if err := models.UpdateTeam(team, true); err != nil { ctx.Error(500, "EditTeam", err) return diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 9c39094ba..e412a7f1f 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -5,11 +5,11 @@ package repo import ( + "code.gitea.io/git" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/routers/api/v1/convert" "code.gitea.io/gitea/routers/api/v1/utils" - api "code.gitea.io/sdk/gitea" ) @@ -82,6 +82,62 @@ func GetHook(ctx *context.APIContext) { ctx.JSON(200, convert.ToHook(repo.RepoLink, hook)) } +// TestHook tests a hook +func TestHook(ctx *context.APIContext) { + // swagger:operation POST /repos/{owner}/{repo}/hooks/{id}/tests repository repoTestHook + // --- + // summary: Test a push webhook + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: id + // in: path + // description: id of the hook to test + // type: integer + // required: true + // responses: + // "204": + // "$ref": "#/responses/empty" + if ctx.Repo.Commit == nil { + // if repo does not have any commits, then don't send a webhook + ctx.Status(204) + return + } + + hookID := ctx.ParamsInt64(":id") + hook, err := utils.GetRepoHook(ctx, ctx.Repo.Repository.ID, hookID) + if err != nil { + return + } + + if err := models.PrepareWebhook(hook, ctx.Repo.Repository, models.HookEventPush, &api.PushPayload{ + Ref: git.BranchPrefix + ctx.Repo.Repository.DefaultBranch, + Before: ctx.Repo.Commit.ID.String(), + After: ctx.Repo.Commit.ID.String(), + Commits: []*api.PayloadCommit{ + convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit), + }, + Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone), + Pusher: ctx.User.APIFormat(), + Sender: ctx.User.APIFormat(), + }); err != nil { + ctx.Error(500, "PrepareWebhook: ", err) + return + } + go models.HookQueue.Add(ctx.Repo.Repository.ID) + ctx.Status(204) +} + // CreateHook create a hook for a repository func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { // swagger:operation POST /repos/{owner}/{repo}/hooks repository repoCreateHook diff --git a/routers/api/v1/repo/hook_test.go b/routers/api/v1/repo/hook_test.go new file mode 100644 index 000000000..8ed4bc4b0 --- /dev/null +++ b/routers/api/v1/repo/hook_test.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "net/http" + "testing" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/test" + + "github.com/stretchr/testify/assert" +) + +func TestTestHook(t *testing.T) { + models.PrepareTestEnv(t) + + ctx := test.MockContext(t, "user2/repo1/wiki/_pages") + ctx.SetParams(":id", "1") + test.LoadRepo(t, ctx, 1) + test.LoadRepoCommit(t, ctx) + test.LoadUser(t, ctx, 2) + TestHook(&context.APIContext{Context: ctx, Org: nil}) + assert.EqualValues(t, http.StatusNoContent, ctx.Resp.Status()) + + models.AssertExistsAndLoadBean(t, &models.HookTask{ + RepoID: 1, + HookID: 1, + }, models.Cond("is_delivered=?", false)) +} diff --git a/routers/api/v1/repo/main_test.go b/routers/api/v1/repo/main_test.go new file mode 100644 index 000000000..656758ffb --- /dev/null +++ b/routers/api/v1/repo/main_test.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "path/filepath" + "testing" + + "code.gitea.io/gitea/models" +) + +func TestMain(m *testing.M) { + models.MainTest(m, filepath.Join("..", "..", "..", "..")) +} diff --git a/routers/init.go b/routers/init.go index 3ed5fc4f5..a52f9ca1b 100644 --- a/routers/init.go +++ b/routers/init.go @@ -60,7 +60,9 @@ func GlobalInit() { log.Fatal(4, "Failed to initialize ORM engine: %v", err) } models.HasEngine = true - models.InitOAuth2() + if err := models.InitOAuth2(); err != nil { + log.Fatal(4, "Failed to initialize OAuth2 support: %v", err) + } models.LoadRepoConfig() models.NewRepoContext() diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 8d9c24d74..390257ae3 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -1171,6 +1171,12 @@ func Milestones(ctx *context.Context) { ctx.ServerError("GetMilestones", err) return } + if ctx.Repo.Repository.IsTimetrackerEnabled() { + if miles.LoadTotalTrackedTimes(); err != nil { + ctx.ServerError("LoadTotalTrackedTimes", err) + return + } + } for _, m := range miles { m.RenderedContent = string(markdown.Render([]byte(m.Content), ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas())) } diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 04a11ca5c..180a5dea6 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -198,6 +198,10 @@ {{.NumComments}} {{end}} + {{if .TotalTrackedTime}} + {{.TotalTrackedTime | Sec2Time}} + {{end}} +

{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.HomeLink .Poster.Name | Safe}} {{$tasks := .GetTasks}} diff --git a/templates/repo/issue/milestones.tmpl b/templates/repo/issue/milestones.tmpl index de52bd42f..369da2e63 100644 --- a/templates/repo/issue/milestones.tmpl +++ b/templates/repo/issue/milestones.tmpl @@ -64,6 +64,7 @@ {{$.i18n.Tr "repo.issues.open_tab" .NumOpenIssues}} {{$.i18n.Tr "repo.issues.close_tab" .NumClosedIssues}} + {{if .TotalTrackedTime}} {{.TotalTrackedTime|Sec2Time}}{{end}} {{if $.IsRepositoryWriter}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 72e0f16ba..9880d575a 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -172,7 +172,7 @@ {{if gt (len .WorkingUsers) 0}}

- {{.i18n.Tr "repo.issues.time_spent_total"}} + {{.i18n.Tr "repo.issues.time_spent_from_all_authors" ($.Issue.TotalTrackedTime | Sec2Time) | Safe}}
{{range $user, $trackedtime := .WorkingUsers}}
diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl index b41301b10..d0b6511b8 100644 --- a/templates/user/dashboard/issues.tmpl +++ b/templates/user/dashboard/issues.tmpl @@ -79,6 +79,9 @@ {{if .NumComments}} {{.NumComments}} {{end}} + {{if .TotalTrackedTime}} + {{.TotalTrackedTime | Sec2Time}} + {{end}}

{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.HomeLink .Poster.Name | Safe}} diff --git a/vendor/github.com/lafriks/xormstore/Gopkg.lock b/vendor/github.com/lafriks/xormstore/Gopkg.lock new file mode 100644 index 000000000..0d2cf03cb --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/Gopkg.lock @@ -0,0 +1,75 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/denisenkom/go-mssqldb" + packages = ["."] + revision = "ee492709d4324cdcb051d2ac266b77ddc380f5c5" + +[[projects]] + name = "github.com/go-sql-driver/mysql" + packages = ["."] + revision = "a0583e0143b1624142adab07e0e97fe106d99561" + version = "v1.3" + +[[projects]] + branch = "master" + name = "github.com/go-xorm/builder" + packages = ["."] + revision = "488224409dd8aa2ce7a5baf8d10d55764a913738" + +[[projects]] + name = "github.com/go-xorm/core" + packages = ["."] + revision = "da1adaf7a28ca792961721a34e6e04945200c890" + version = "v0.5.7" + +[[projects]] + name = "github.com/go-xorm/xorm" + packages = ["."] + revision = "1933dd69e294c0a26c0266637067f24dbb25770c" + version = "v0.6.4" + +[[projects]] + name = "github.com/gorilla/context" + packages = ["."] + revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a" + version = "v1.1" + +[[projects]] + name = "github.com/gorilla/securecookie" + packages = ["."] + revision = "e59506cc896acb7f7bf732d4fdf5e25f7ccd8983" + version = "v1.1.1" + +[[projects]] + name = "github.com/gorilla/sessions" + packages = ["."] + revision = "ca9ada44574153444b00d3fd9c8559e4cc95f896" + version = "v1.1" + +[[projects]] + branch = "master" + name = "github.com/lib/pq" + packages = [".","oid"] + revision = "88edab0803230a3898347e77b474f8c1820a1f20" + +[[projects]] + name = "github.com/mattn/go-sqlite3" + packages = ["."] + revision = "6c771bb9887719704b210e87e934f08be014bdb1" + version = "v1.6.0" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["md4"] + revision = "c7dcf104e3a7a1417abc0230cb0d5240d764159d" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "bba98a94e8c6668ae9556b4978bbffdfc5d4d535d522c8865465335bfaa2fc70" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/lafriks/xormstore/Gopkg.toml b/vendor/github.com/lafriks/xormstore/Gopkg.toml new file mode 100644 index 000000000..ea71d50ea --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/Gopkg.toml @@ -0,0 +1,50 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/go-sql-driver/mysql" + version = "1.3.0" + +[[constraint]] + name = "github.com/go-xorm/xorm" + version = "0.6.4" + +[[constraint]] + name = "github.com/gorilla/context" + version = "1.1.0" + +[[constraint]] + name = "github.com/gorilla/securecookie" + version = "1.1.1" + +[[constraint]] + name = "github.com/gorilla/sessions" + version = "1.1.0" + +[[constraint]] + branch = "master" + name = "github.com/lib/pq" + +[[constraint]] + name = "github.com/mattn/go-sqlite3" + version = "1.6.0" diff --git a/vendor/github.com/lafriks/xormstore/LICENSE b/vendor/github.com/lafriks/xormstore/LICENSE new file mode 100644 index 000000000..7a2dab6c1 --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018 Lauris Bukšis-Haberkorns, Mattias Wadman + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/lafriks/xormstore/README.md b/vendor/github.com/lafriks/xormstore/README.md new file mode 100644 index 000000000..361c5871f --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/README.md @@ -0,0 +1,48 @@ +[![GoDoc](https://godoc.org/github.com/lafriks/xormstore?status.svg)](https://godoc.org/github.com/lafriks/xormstore) +[![Build Status](https://travis-ci.org/lafriks/xormstore.svg?branch=master)](https://travis-ci.org/lafriks/xormstore) +[![codecov](https://codecov.io/gh/lafriks/xormstore/branch/master/graph/badge.svg)](https://codecov.io/gh/lafriks/xormstore) + +#### XORM backend for gorilla sessions + + go get github.com/lafriks/xormstore + +#### Example + +```go +// initialize and setup cleanup +store := xormstore.New(engine, []byte("secret")) +// db cleanup every hour +// close quit channel to stop cleanup +quit := make(chan struct{}) +go store.PeriodicCleanup(1*time.Hour, quit) +``` + +```go +// in HTTP handler +func handlerFunc(w http.ResponseWriter, r *http.Request) { + session, err := store.Get(r, "session") + session.Values["user_id"] = 123 + store.Save(r, w, session) + http.Error(w, "", http.StatusOK) +} +``` + +For more details see [xormstore godoc documentation](https://godoc.org/github.com/lafriks/xormstore). + +#### Testing + +Just sqlite3 tests: + + go test + +All databases using docker: + + ./test + +If docker is not local (docker-machine etc): + + DOCKER_IP=$(docker-machine ip dev) ./test + +#### License + +xormstore is licensed under the MIT license. See [LICENSE](LICENSE) for the full license text. diff --git a/vendor/github.com/lafriks/xormstore/test b/vendor/github.com/lafriks/xormstore/test new file mode 100755 index 000000000..4b06eae4e --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/test @@ -0,0 +1,70 @@ +#!/bin/bash + +DOCKER_IP=${DOCKER_IP:-127.0.0.1} + +sqlite3() { + DATABASE_URI="sqlite3://file:dummy?mode=memory&cache=shared" go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic + return $? +} + +postgres10() { + ID=$(docker run -p 5432 -d postgres:10-alpine) + PORT=$(docker port "$ID" 5432 | cut -d : -f 2) + DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +postgres96() { + ID=$(docker run -p 5432 -d postgres:9.6-alpine) + PORT=$(docker port "$ID" 5432 | cut -d : -f 2) + DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +postgres94() { + ID=$(docker run -p 5432 -d postgres:9.4-alpine) + PORT=$(docker port "$ID" 5432 | cut -d : -f 2) + DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +mysql57() { + ID=$(docker run \ + -e MYSQL_ROOT_PASSWORD=root \ + -e MYSQL_USER=mysql \ + -e MYSQL_PASSWORD=mysql \ + -e MYSQL_DATABASE=mysql \ + -p 3306 -d mysql:5.7) + PORT=$(docker port "$ID" 3306 | cut -d : -f 2) + DATABASE_URI="mysql://mysql:mysql@tcp($DOCKER_IP:$PORT)/mysql?charset=utf8&parseTime=True" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +mariadb10() { + ID=$(docker run \ + -e MYSQL_ROOT_PASSWORD=root \ + -e MYSQL_USER=mysql \ + -e MYSQL_PASSWORD=mysql \ + -e MYSQL_DATABASE=mysql \ + -p 3306 -d mariadb:10) + PORT=$(docker port "$ID" 3306 | cut -d : -f 2) + DATABASE_URI="mysql://mysql:mysql@tcp($DOCKER_IP:$PORT)/mysql?charset=utf8&parseTime=True" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +sqlite3 || exit 1 +postgres94 || exit 1 +postgres96 || exit 1 +postgres10 || exit 1 +mysql57 || exit 1 +mariadb10 || exit 1 diff --git a/vendor/github.com/lafriks/xormstore/util/time_stamp.go b/vendor/github.com/lafriks/xormstore/util/time_stamp.go new file mode 100644 index 000000000..2036fdf2f --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/util/time_stamp.go @@ -0,0 +1,60 @@ +package util + +import ( + "time" +) + +// TimeStamp defines a timestamp +type TimeStamp int64 + +// TimeStampNow returns now int64 +func TimeStampNow() TimeStamp { + return TimeStamp(time.Now().Unix()) +} + +// Add adds seconds and return sum +func (ts TimeStamp) Add(seconds int64) TimeStamp { + return ts + TimeStamp(seconds) +} + +// AddDuration adds time.Duration and return sum +func (ts TimeStamp) AddDuration(interval time.Duration) TimeStamp { + return ts + TimeStamp(interval/time.Second) +} + +// Year returns the time's year +func (ts TimeStamp) Year() int { + return ts.AsTime().Year() +} + +// AsTime convert timestamp as time.Time in Local locale +func (ts TimeStamp) AsTime() (tm time.Time) { + tm = time.Unix(int64(ts), 0).Local() + return +} + +// AsTimePtr convert timestamp as *time.Time in Local locale +func (ts TimeStamp) AsTimePtr() *time.Time { + tm := time.Unix(int64(ts), 0).Local() + return &tm +} + +// Format formats timestamp as +func (ts TimeStamp) Format(f string) string { + return ts.AsTime().Format(f) +} + +// FormatLong formats as RFC1123Z +func (ts TimeStamp) FormatLong() string { + return ts.Format(time.RFC1123Z) +} + +// FormatShort formats as short +func (ts TimeStamp) FormatShort() string { + return ts.Format("Jan 02, 2006") +} + +// IsZero is zero time +func (ts TimeStamp) IsZero() bool { + return ts.AsTime().IsZero() +} diff --git a/vendor/github.com/lafriks/xormstore/xormstore.go b/vendor/github.com/lafriks/xormstore/xormstore.go new file mode 100644 index 000000000..f73db2e27 --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/xormstore.go @@ -0,0 +1,251 @@ +/* +Package xormstore is a XORM backend for gorilla sessions + +Simplest form: + + store, err := xormstore.New(engine, []byte("secret-hash-key")) + +All options: + + store, err := xormstore.NewOptions( + engine, // *xorm.Engine + xormstore.Options{ + TableName: "sessions", // "sessions" is default + SkipCreateTable: false, // false is default + }, + []byte("secret-hash-key"), // 32 or 64 bytes recommended, required + []byte("secret-encyption-key")) // nil, 16, 24 or 32 bytes, optional + + if err != nil { + // xormstore can not be initialized + } + + // some more settings, see sessions.Options + store.SessionOpts.Secure = true + store.SessionOpts.HttpOnly = true + store.SessionOpts.MaxAge = 60 * 60 * 24 * 60 + +If you want periodic cleanup of expired sessions: + + quit := make(chan struct{}) + go store.PeriodicCleanup(1*time.Hour, quit) + +For more information about the keys see https://github.com/gorilla/securecookie + +For API to use in HTTP handlers see https://github.com/gorilla/sessions +*/ +package xormstore + +import ( + "encoding/base32" + "net/http" + "strings" + "time" + + "github.com/lafriks/xormstore/util" + + "github.com/go-xorm/xorm" + "github.com/gorilla/context" + "github.com/gorilla/securecookie" + "github.com/gorilla/sessions" +) + +const sessionIDLen = 32 +const defaultTableName = "sessions" +const defaultMaxAge = 60 * 60 * 24 * 30 // 30 days +const defaultPath = "/" + +// Options for xormstore +type Options struct { + TableName string + SkipCreateTable bool +} + +// Store represent a xormstore +type Store struct { + e *xorm.Engine + opts Options + Codecs []securecookie.Codec + SessionOpts *sessions.Options +} + +type xormSession struct { + ID string `xorm:"VARCHAR(400) PK NAME 'id'"` + Data string `xorm:"TEXT"` + CreatedUnix util.TimeStamp `xorm:"created"` + UpdatedUnix util.TimeStamp `xorm:"updated"` + ExpiresUnix util.TimeStamp `xorm:"INDEX"` + + tableName string `xorm:"-"` // just to store table name for easier access +} + +// Define a type for context keys so that they can't clash with anything else stored in context +type contextKey string + +func (xs *xormSession) TableName() string { + return xs.tableName +} + +// New creates a new xormstore session +func New(e *xorm.Engine, keyPairs ...[]byte) (*Store, error) { + return NewOptions(e, Options{}, keyPairs...) +} + +// NewOptions creates a new xormstore session with options +func NewOptions(e *xorm.Engine, opts Options, keyPairs ...[]byte) (*Store, error) { + st := &Store{ + e: e, + opts: opts, + Codecs: securecookie.CodecsFromPairs(keyPairs...), + SessionOpts: &sessions.Options{ + Path: defaultPath, + MaxAge: defaultMaxAge, + }, + } + if st.opts.TableName == "" { + st.opts.TableName = defaultTableName + } + + if !st.opts.SkipCreateTable { + if err := st.e.Sync2(&xormSession{tableName: st.opts.TableName}); err != nil { + return nil, err + } + } + + return st, nil +} + +// Get returns a session for the given name after adding it to the registry. +func (st *Store) Get(r *http.Request, name string) (*sessions.Session, error) { + return sessions.GetRegistry(r).Get(st, name) +} + +// New creates a session with name without adding it to the registry. +func (st *Store) New(r *http.Request, name string) (*sessions.Session, error) { + session := sessions.NewSession(st, name) + opts := *st.SessionOpts + session.Options = &opts + + st.MaxAge(st.SessionOpts.MaxAge) + + // try fetch from db if there is a cookie + if cookie, err := r.Cookie(name); err == nil { + if err := securecookie.DecodeMulti(name, cookie.Value, &session.ID, st.Codecs...); err != nil { + return session, nil + } + s := &xormSession{tableName: st.opts.TableName} + if has, err := st.e.Where("id = ? AND expires_unix >= ?", session.ID, util.TimeStampNow()).Get(s); !has || err != nil { + return session, nil + } + if err := securecookie.DecodeMulti(session.Name(), s.Data, &session.Values, st.Codecs...); err != nil { + return session, nil + } + + context.Set(r, contextKey(name), s) + } + + return session, nil +} + +// Save session and set cookie header +func (st *Store) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error { + s, _ := context.Get(r, contextKey(session.Name())).(*xormSession) + + // delete if max age is < 0 + if session.Options.MaxAge < 0 { + if s != nil { + if _, err := st.e.Delete(&xormSession{ + ID: session.ID, + tableName: st.opts.TableName, + }); err != nil { + return err + } + } + http.SetCookie(w, sessions.NewCookie(session.Name(), "", session.Options)) + return nil + } + + data, err := securecookie.EncodeMulti(session.Name(), session.Values, st.Codecs...) + if err != nil { + return err + } + now := util.TimeStampNow() + expire := now.AddDuration(time.Second * time.Duration(session.Options.MaxAge)) + + if s == nil { + // generate random session ID key suitable for storage in the db + session.ID = strings.TrimRight( + base32.StdEncoding.EncodeToString( + securecookie.GenerateRandomKey(sessionIDLen)), "=") + s = &xormSession{ + ID: session.ID, + Data: data, + CreatedUnix: now, + UpdatedUnix: now, + ExpiresUnix: expire, + tableName: st.opts.TableName, + } + if _, err := st.e.Insert(s); err != nil { + return err + } + context.Set(r, contextKey(session.Name()), s) + } else { + s.Data = data + s.UpdatedUnix = now + s.ExpiresUnix = expire + if _, err := st.e.ID(s.ID).Cols("data", "updated_unix", "expires_unix").Update(s); err != nil { + return err + } + } + + // set session id cookie + id, err := securecookie.EncodeMulti(session.Name(), session.ID, st.Codecs...) + if err != nil { + return err + } + http.SetCookie(w, sessions.NewCookie(session.Name(), id, session.Options)) + + return nil +} + +// MaxAge sets the maximum age for the store and the underlying cookie +// implementation. Individual sessions can be deleted by setting +// Options.MaxAge = -1 for that session. +func (st *Store) MaxAge(age int) { + st.SessionOpts.MaxAge = age + for _, codec := range st.Codecs { + if sc, ok := codec.(*securecookie.SecureCookie); ok { + sc.MaxAge(age) + } + } +} + +// MaxLength restricts the maximum length of new sessions to l. +// If l is 0 there is no limit to the size of a session, use with caution. +// The default is 4096 (default for securecookie) +func (st *Store) MaxLength(l int) { + for _, c := range st.Codecs { + if codec, ok := c.(*securecookie.SecureCookie); ok { + codec.MaxLength(l) + } + } +} + +// Cleanup deletes expired sessions +func (st *Store) Cleanup() { + st.e.Where("expires_unix < ?", util.TimeStampNow()).Delete(&xormSession{tableName: st.opts.TableName}) +} + +// PeriodicCleanup runs Cleanup every interval. Close quit channel to stop. +func (st *Store) PeriodicCleanup(interval time.Duration, quit <-chan struct{}) { + t := time.NewTicker(interval) + defer t.Stop() + for { + select { + case <-t.C: + st.Cleanup() + case <-quit: + return + } + } +} diff --git a/vendor/github.com/russross/blackfriday/README.md b/vendor/github.com/russross/blackfriday/README.md index 3c113cb10..e0066b0fc 100644 --- a/vendor/github.com/russross/blackfriday/README.md +++ b/vendor/github.com/russross/blackfriday/README.md @@ -1,4 +1,6 @@ -Blackfriday [![Build Status](https://travis-ci.org/russross/blackfriday.svg?branch=master)](https://travis-ci.org/russross/blackfriday) [![GoDoc](https://godoc.org/github.com/russross/blackfriday?status.svg)](https://godoc.org/github.com/russross/blackfriday) +Blackfriday +[![Build Status][BuildSVG]][BuildURL] +[![Godoc][GodocV2SVG]][GodocV2URL] =========== Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It @@ -8,7 +10,7 @@ punctuation substitutions, etc.), and it is safe for all utf-8 (unicode) input. HTML output is currently supported, along with Smartypants -extensions. An experimental LaTeX output engine is also included. +extensions. It started as a translation from C of [Sundown][3]. @@ -16,26 +18,71 @@ It started as a translation from C of [Sundown][3]. Installation ------------ -Blackfriday is compatible with Go 1. If you are using an older -release of Go, consider using v1.1 of blackfriday, which was based -on the last stable release of Go prior to Go 1. You can find it as a -tagged commit on github. +Blackfriday is compatible with any modern Go release. With Go and git installed: -With Go 1 and git installed: + go get -u gopkg.in/russross/blackfriday.v2 - go get github.com/russross/blackfriday +will download, compile, and install the package into your `$GOPATH` directory +hierarchy. -will download, compile, and install the package into your `$GOPATH` -directory hierarchy. Alternatively, you can achieve the same if you -import it into a project: - import "github.com/russross/blackfriday" +Versions +-------- + +Currently maintained and recommended version of Blackfriday is `v2`. It's being +developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the +documentation is available at +https://godoc.org/gopkg.in/russross/blackfriday.v2. + +It is `go get`-able via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`, +but we highly recommend using package management tool like [dep][7] or +[Glide][8] and make use of semantic versioning. With package management you +should import `github.com/russross/blackfriday` and specify that you're using +version 2.0.0. + +Version 2 offers a number of improvements over v1: + +* Cleaned up API +* A separate call to [`Parse`][4], which produces an abstract syntax tree for + the document +* Latest bug fixes +* Flexibility to easily add your own rendering extensions + +Potential drawbacks: + +* Our benchmarks show v2 to be slightly slower than v1. Currently in the + ballpark of around 15%. +* API breakage. If you can't afford modifying your code to adhere to the new API + and don't care too much about the new features, v2 is probably not for you. +* Several bug fixes are trailing behind and still need to be forward-ported to + v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for + tracking. + +If you are still interested in the legacy `v1`, you can import it from +`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found +here: https://godoc.org/github.com/russross/blackfriday + +### Known issue with `dep` + +There is a known problem with using Blackfriday v1 _transitively_ and `dep`. +Currently `dep` prioritizes semver versions over anything else, and picks the +latest one, plus it does not apply a `[[constraint]]` specifier to transitively +pulled in packages. So if you're using something that uses Blackfriday v1, but +that something does not use `dep` yet, you will get Blackfriday v2 pulled in and +your first dependency will fail to build. + +There are couple of fixes for it, documented here: +https://github.com/golang/dep/blob/master/docs/FAQ.md#how-do-i-constrain-a-transitive-dependencys-version + +Meanwhile, `dep` team is working on a more general solution to the constraints +on transitive dependencies problem: https://github.com/golang/dep/issues/1124. -and `go get` without parameters. Usage ----- +### v1 + For basic usage, it is as simple as getting your input into a byte slice and calling: @@ -46,34 +93,57 @@ feature set, use this instead: output := blackfriday.MarkdownCommon(input) +### v2 + +For the most sensible markdown processing, it is as simple as getting your input +into a byte slice and calling: + +```go +output := blackfriday.Run(input) +``` + +Your input will be parsed and the output rendered with a set of most popular +extensions enabled. If you want the most basic feature set, corresponding with +the bare Markdown specification, use: + +```go +output := blackfriday.Run(input, blackfriday.WithNoExtensions()) +``` + ### Sanitize untrusted content Blackfriday itself does nothing to protect against malicious content. If you are -dealing with user-supplied markdown, we recommend running blackfriday's output -through HTML sanitizer such as -[Bluemonday](https://github.com/microcosm-cc/bluemonday). +dealing with user-supplied markdown, we recommend running Blackfriday's output +through HTML sanitizer such as [Bluemonday][5]. -Here's an example of simple usage of blackfriday together with bluemonday: +Here's an example of simple usage of Blackfriday together with Bluemonday: -``` go +```go import ( "github.com/microcosm-cc/bluemonday" - "github.com/russross/blackfriday" + "gopkg.in/russross/blackfriday.v2" ) // ... -unsafe := blackfriday.MarkdownCommon(input) +unsafe := blackfriday.Run(input) html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) ``` -### Custom options +### Custom options, v1 If you want to customize the set of options, first get a renderer -(currently either the HTML or LaTeX output engines), then use it to +(currently only the HTML output engine), then use it to call the more general `Markdown` function. For examples, see the implementations of `MarkdownBasic` and `MarkdownCommon` in `markdown.go`. +### Custom options, v2 + +If you want to customize the set of options, use `blackfriday.WithExtensions`, +`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. + +### `blackfriday-tool` + You can also check out `blackfriday-tool` for a more complete example of how to use it. Download and install it using: @@ -93,6 +163,22 @@ installed in `$GOPATH/bin`. This is a statically-linked binary that can be copied to wherever you need it without worrying about dependencies and library versions. +### Sanitized anchor names + +Blackfriday includes an algorithm for creating sanitized anchor names +corresponding to a given input text. This algorithm is used to create +anchors for headings when `EXTENSION_AUTO_HEADER_IDS` is enabled. The +algorithm has a specification, so that other packages can create +compatible anchor names and links to those anchors. + +The specification is located at https://godoc.org/github.com/russross/blackfriday#hdr-Sanitized_Anchor_Names. + +[`SanitizedAnchorName`](https://godoc.org/github.com/russross/blackfriday#SanitizedAnchorName) exposes this functionality, and can be used to +create compatible links to the anchor names generated by blackfriday. +This algorithm is also implemented in a small standalone package at +[`github.com/shurcooL/sanitized_anchor_name`](https://godoc.org/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients +that want a small package and don't need full functionality of blackfriday. + Features -------- @@ -233,7 +319,7 @@ are a few of note: * [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown): provides a GitHub Flavored Markdown renderer with fenced code block - highlighting, clickable header anchor links. + highlighting, clickable heading anchor links. It's not customizable, and its goal is to produce HTML output equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), @@ -242,27 +328,18 @@ are a few of note: * [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, but for markdown. -* LaTeX output: renders output as LaTeX. This is currently part of the - main Blackfriday repository, but may be split into its own project - in the future. If you are interested in owning and maintaining the - LaTeX output component, please be in touch. - - It renders some basic documents, but is only experimental at this - point. In particular, it does not do any inline escaping, so input - that happens to look like LaTeX code will be passed through without - modification. - -* [Md2Vim](https://github.com/FooSoft/md2vim): transforms markdown files into vimdoc format. +* [LaTeX output](https://bitbucket.org/ambrevar/blackfriday-latex): + renders output as LaTeX. -Todo +TODO ---- * More unit testing -* Improve unicode support. It does not understand all unicode +* Improve Unicode support. It does not understand all Unicode rules (about what constitutes a letter, a punctuation symbol, etc.), so it may fail to detect word boundaries correctly in - some instances. It is safe on all utf-8 input. + some instances. It is safe on all UTF-8 input. License @@ -271,6 +348,16 @@ License [Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) - [1]: http://daringfireball.net/projects/markdown/ "Markdown" - [2]: http://golang.org/ "Go Language" + [1]: https://daringfireball.net/projects/markdown/ "Markdown" + [2]: https://golang.org/ "Go Language" [3]: https://github.com/vmg/sundown "Sundown" + [4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func" + [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" + [6]: https://labix.org/gopkg.in "gopkg.in" + [7]: https://github.com/golang/dep/ "dep" + [8]: https://github.com/Masterminds/glide "Glide" + + [BuildSVG]: https://travis-ci.org/russross/blackfriday.svg?branch=master + [BuildURL]: https://travis-ci.org/russross/blackfriday + [GodocV2SVG]: https://godoc.org/gopkg.in/russross/blackfriday.v2?status.svg + [GodocV2URL]: https://godoc.org/gopkg.in/russross/blackfriday.v2 diff --git a/vendor/github.com/russross/blackfriday/block.go b/vendor/github.com/russross/blackfriday/block.go index 9cf451f0b..929638aa4 100644 --- a/vendor/github.com/russross/blackfriday/block.go +++ b/vendor/github.com/russross/blackfriday/block.go @@ -15,8 +15,8 @@ package blackfriday import ( "bytes" - - "github.com/shurcooL/sanitized_anchor_name" + "strings" + "unicode" ) // Parse block-level data. @@ -93,7 +93,7 @@ func (p *parser) block(out *bytes.Buffer, data []byte) { // fenced code block: // - // ``` go + // ``` go info string here // func fact(n int) int { // if n <= 1 { // return n @@ -243,7 +243,7 @@ func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int { } if end > i { if id == "" && p.flags&EXTENSION_AUTO_HEADER_IDS != 0 { - id = sanitized_anchor_name.Create(string(data[i:end])) + id = SanitizedAnchorName(string(data[i:end])) } work := func() bool { p.inline(out, data[i:end]) @@ -563,7 +563,7 @@ func (*parser) isHRule(data []byte) bool { // and returns the end index if so, or 0 otherwise. It also returns the marker found. // If syntax is not nil, it gets set to the syntax specified in the fence line. // A final newline is mandatory to recognize the fence line, unless newlineOptional is true. -func isFenceLine(data []byte, syntax *string, oldmarker string, newlineOptional bool) (end int, marker string) { +func isFenceLine(data []byte, info *string, oldmarker string, newlineOptional bool) (end int, marker string) { i, size := 0, 0 // skip up to three spaces @@ -599,9 +599,9 @@ func isFenceLine(data []byte, syntax *string, oldmarker string, newlineOptional } // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here - // into one, always get the syntax, and discard it if the caller doesn't care. - if syntax != nil { - syn := 0 + // into one, always get the info string, and discard it if the caller doesn't care. + if info != nil { + infoLength := 0 i = skipChar(data, i, ' ') if i >= len(data) { @@ -611,14 +611,14 @@ func isFenceLine(data []byte, syntax *string, oldmarker string, newlineOptional return 0, "" } - syntaxStart := i + infoStart := i if data[i] == '{' { i++ - syntaxStart++ + infoStart++ for i < len(data) && data[i] != '}' && data[i] != '\n' { - syn++ + infoLength++ i++ } @@ -628,24 +628,24 @@ func isFenceLine(data []byte, syntax *string, oldmarker string, newlineOptional // strip all whitespace at the beginning and the end // of the {} block - for syn > 0 && isspace(data[syntaxStart]) { - syntaxStart++ - syn-- + for infoLength > 0 && isspace(data[infoStart]) { + infoStart++ + infoLength-- } - for syn > 0 && isspace(data[syntaxStart+syn-1]) { - syn-- + for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { + infoLength-- } i++ } else { - for i < len(data) && !isspace(data[i]) { - syn++ + for i < len(data) && !isverticalspace(data[i]) { + infoLength++ i++ } } - *syntax = string(data[syntaxStart : syntaxStart+syn]) + *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) } i = skipChar(data, i, ' ') @@ -663,8 +663,8 @@ func isFenceLine(data []byte, syntax *string, oldmarker string, newlineOptional // or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. // If doRender is true, a final newline is mandatory to recognize the fenced code block. func (p *parser) fencedCodeBlock(out *bytes.Buffer, data []byte, doRender bool) int { - var syntax string - beg, marker := isFenceLine(data, &syntax, "", false) + var infoString string + beg, marker := isFenceLine(data, &infoString, "", false) if beg == 0 || beg >= len(data) { return 0 } @@ -698,7 +698,7 @@ func (p *parser) fencedCodeBlock(out *bytes.Buffer, data []byte, doRender bool) } if doRender { - p.r.BlockCode(out, work.Bytes(), syntax) + p.r.BlockCode(out, work.Bytes(), infoString) } return beg @@ -1364,7 +1364,7 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int { id := "" if p.flags&EXTENSION_AUTO_HEADER_IDS != 0 { - id = sanitized_anchor_name.Create(string(data[prev:eol])) + id = SanitizedAnchorName(string(data[prev:eol])) } p.r.Header(out, work, level, id) @@ -1428,3 +1428,24 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int { p.renderParagraph(out, data[:i]) return i } + +// SanitizedAnchorName returns a sanitized anchor name for the given text. +// +// It implements the algorithm specified in the package comment. +func SanitizedAnchorName(text string) string { + var anchorName []rune + futureDash := false + for _, r := range text { + switch { + case unicode.IsLetter(r) || unicode.IsNumber(r): + if futureDash && len(anchorName) > 0 { + anchorName = append(anchorName, '-') + } + futureDash = false + anchorName = append(anchorName, unicode.ToLower(r)) + default: + futureDash = true + } + } + return string(anchorName) +} diff --git a/vendor/github.com/russross/blackfriday/doc.go b/vendor/github.com/russross/blackfriday/doc.go new file mode 100644 index 000000000..9656c42a1 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/doc.go @@ -0,0 +1,32 @@ +// Package blackfriday is a Markdown processor. +// +// It translates plain text with simple formatting rules into HTML or LaTeX. +// +// Sanitized Anchor Names +// +// Blackfriday includes an algorithm for creating sanitized anchor names +// corresponding to a given input text. This algorithm is used to create +// anchors for headings when EXTENSION_AUTO_HEADER_IDS is enabled. The +// algorithm is specified below, so that other packages can create +// compatible anchor names and links to those anchors. +// +// The algorithm iterates over the input text, interpreted as UTF-8, +// one Unicode code point (rune) at a time. All runes that are letters (category L) +// or numbers (category N) are considered valid characters. They are mapped to +// lower case, and included in the output. All other runes are considered +// invalid characters. Invalid characters that preceed the first valid character, +// as well as invalid character that follow the last valid character +// are dropped completely. All other sequences of invalid characters +// between two valid characters are replaced with a single dash character '-'. +// +// SanitizedAnchorName exposes this functionality, and can be used to +// create compatible links to the anchor names generated by blackfriday. +// This algorithm is also implemented in a small standalone package at +// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients +// that want a small package and don't need full functionality of blackfriday. +package blackfriday + +// NOTE: Keep Sanitized Anchor Name algorithm in sync with package +// github.com/shurcooL/sanitized_anchor_name. +// Otherwise, users of sanitized_anchor_name will get anchor names +// that are incompatible with those generated by blackfriday. diff --git a/vendor/github.com/russross/blackfriday/html.go b/vendor/github.com/russross/blackfriday/html.go index 74e67ee82..e0a6c69c9 100644 --- a/vendor/github.com/russross/blackfriday/html.go +++ b/vendor/github.com/russross/blackfriday/html.go @@ -42,6 +42,7 @@ const ( HTML_SMARTYPANTS_DASHES // enable smart dashes (with HTML_USE_SMARTYPANTS) HTML_SMARTYPANTS_LATEX_DASHES // enable LaTeX-style dashes (with HTML_USE_SMARTYPANTS and HTML_SMARTYPANTS_DASHES) HTML_SMARTYPANTS_ANGLED_QUOTES // enable angled double quotes (with HTML_USE_SMARTYPANTS) for double quotes rendering + HTML_SMARTYPANTS_QUOTES_NBSP // enable "French guillemets" (with HTML_USE_SMARTYPANTS) HTML_FOOTNOTE_RETURN_LINKS // generate a link at the end of a footnote to return to the source ) @@ -254,33 +255,21 @@ func (options *Html) HRule(out *bytes.Buffer) { out.WriteByte('\n') } -func (options *Html) BlockCode(out *bytes.Buffer, text []byte, lang string) { +func (options *Html) BlockCode(out *bytes.Buffer, text []byte, info string) { doubleSpace(out) - // parse out the language names/classes - count := 0 - for _, elt := range strings.Fields(lang) { - if elt[0] == '.' { - elt = elt[1:] - } - if len(elt) == 0 { - continue - } - if count == 0 { - out.WriteString("

")
 	} else {
+		out.WriteString("
")
 	}
-
 	attrEscape(out, text)
 	out.WriteString("
\n") } @@ -619,7 +608,7 @@ func (options *Html) FootnoteRef(out *bytes.Buffer, ref []byte, id int) { out.WriteString(`fnref:`) out.WriteString(options.parameters.FootnoteAnchorPrefix) out.Write(slug) - out.WriteString(`">= '0' && c <= '9' } -func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool) bool { +func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool { // edge of the buffer is likely to be a tag that we don't get to see, // so we treat it like text sometimes @@ -96,6 +96,12 @@ func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote *isOpen = false } + // Note that with the limited lookahead, this non-breaking + // space will also be appended to single double quotes. + if addNBSP && !*isOpen { + out.WriteString(" ") + } + out.WriteByte('&') if *isOpen { out.WriteByte('l') @@ -104,6 +110,11 @@ func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote } out.WriteByte(quote) out.WriteString("quo;") + + if addNBSP && *isOpen { + out.WriteString(" ") + } + return true } @@ -116,7 +127,7 @@ func smartSingleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byt if len(text) >= 3 { nextChar = text[2] } - if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote, false) { return 1 } } @@ -141,7 +152,7 @@ func smartSingleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byt if len(text) > 1 { nextChar = text[1] } - if smartQuoteHelper(out, previousChar, nextChar, 's', &smrt.inSingleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, 's', &smrt.inSingleQuote, false) { return 0 } @@ -205,13 +216,13 @@ func smartDashLatex(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, return 0 } -func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte, quote byte) int { +func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte, quote byte, addNBSP bool) int { if bytes.HasPrefix(text, []byte(""")) { nextChar := byte(0) if len(text) >= 7 { nextChar = text[6] } - if smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote, addNBSP) { return 5 } } @@ -224,12 +235,15 @@ func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte return 0 } -func smartAmp(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int { - return smartAmpVariant(out, smrt, previousChar, text, 'd') -} +func smartAmp(angledQuotes, addNBSP bool) func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int { + var quote byte = 'd' + if angledQuotes { + quote = 'a' + } -func smartAmpAngledQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int { - return smartAmpVariant(out, smrt, previousChar, text, 'a') + return func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int { + return smartAmpVariant(out, smrt, previousChar, text, quote, addNBSP) + } } func smartPeriod(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int { @@ -253,7 +267,7 @@ func smartBacktick(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, if len(text) >= 3 { nextChar = text[2] } - if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote, false) { return 1 } } @@ -337,7 +351,7 @@ func smartDoubleQuoteVariant(out *bytes.Buffer, smrt *smartypantsData, previousC if len(text) > 1 { nextChar = text[1] } - if !smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote) { + if !smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote, false) { out.WriteString(""") } @@ -367,14 +381,30 @@ type smartCallback func(out *bytes.Buffer, smrt *smartypantsData, previousChar b type smartypantsRenderer [256]smartCallback +var ( + smartAmpAngled = smartAmp(true, false) + smartAmpAngledNBSP = smartAmp(true, true) + smartAmpRegular = smartAmp(false, false) + smartAmpRegularNBSP = smartAmp(false, true) +) + func smartypants(flags int) *smartypantsRenderer { r := new(smartypantsRenderer) + addNBSP := flags&HTML_SMARTYPANTS_QUOTES_NBSP != 0 if flags&HTML_SMARTYPANTS_ANGLED_QUOTES == 0 { r['"'] = smartDoubleQuote - r['&'] = smartAmp + if !addNBSP { + r['&'] = smartAmpRegular + } else { + r['&'] = smartAmpRegularNBSP + } } else { r['"'] = smartAngledDoubleQuote - r['&'] = smartAmpAngledQuote + if !addNBSP { + r['&'] = smartAmpAngled + } else { + r['&'] = smartAmpAngledNBSP + } } r['\''] = smartSingleQuote r['('] = smartParens diff --git a/vendor/vendor.json b/vendor/vendor.json index 7d4cf1aa4..937824dc4 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -647,6 +647,18 @@ "revision": "cb6bfca970f6908083f26f39a79009d608efd5cd", "revisionTime": "2016-10-16T15:41:25Z" }, + { + "checksumSHA1": "/X7eCdN7MX8zgCjA9s0ktzgTPlA=", + "path": "github.com/lafriks/xormstore", + "revision": "3a80a383a04b29ec2e1bf61279dd948aa809335b", + "revisionTime": "2018-04-09T10:45:24Z" + }, + { + "checksumSHA1": "Vxvfs8mukr9GOLSuGIPU4ODyOZc=", + "path": "github.com/lafriks/xormstore/util", + "revision": "c0e2f3dc1ecab3536617967e4b47ee5b9e2ca229", + "revisionTime": "2018-03-11T19:16:53Z" + }, { "checksumSHA1": "QV4HZTfaXvhD+5PcGM2p+7aCYYI=", "path": "github.com/lib/pq", @@ -1174,10 +1186,10 @@ "revisionTime": "2016-09-12T16:18:15Z" }, { - "checksumSHA1": "c7jHQZk5ZEsFR9EXsWJXkszPBZA=", + "checksumSHA1": "Ne3D+KJs1TU2trnDy1UCSwlXbAE=", "path": "github.com/russross/blackfriday", - "revision": "5f33e7b7878355cd2b7e6b8eefc48a5472c69f70", - "revisionTime": "2016-10-03T16:27:22Z" + "revision": "11635eb403ff09dbc3a6b5a007ab5ab09151c229", + "revisionTime": "2018-04-28T10:25:19Z" }, { "checksumSHA1": "zmC8/3V4ls53DJlNTKDZwPSC/dA=",