diff --git a/docs/v1.yaml b/docs/v1.yaml index 97f09d9..b90ab12 100644 --- a/docs/v1.yaml +++ b/docs/v1.yaml @@ -26,6 +26,43 @@ servers: default: "" paths: + /v1/project/{project}/languages: + parameters: + - schema: + type: integer + format: int32 + description: Project id in POEditor + name: project + in: path + required: true + get: + tags: + - project + responses: + "200": + description: "Successful" + content: + application/json: + schema: + type: object + properties: + languages: + type: array + items: + type: object + properties: + name: + type: string + code: + type: string + translations: + type: integer + percentage: + type: number + updated: + type: string + "400": + description: "Invalid project id" /v1/project/{project}/language/{language}: parameters: - schema: diff --git a/internal/project/service.go b/internal/project/service.go index 41ae7fd..cf4ce02 100644 --- a/internal/project/service.go +++ b/internal/project/service.go @@ -23,6 +23,7 @@ type Translation struct { type Service interface { GetTranslation(ctx context.Context, projectID int, languageCode, format string) (trans *Translation, err error) + GetLanguages(ctx context.Context, projectID int) (languages []poedit.Language, err error) PurgeTranslation(ctx context.Context, projectID int, languageCode string) (err error) PurgeProject(ctx context.Context, projectID int) (err error) RegisterChecks(h gosundheit.Health) (err error) @@ -90,6 +91,28 @@ func (s *ServiceImpl) GetTranslation(ctx context.Context, projectID int, languag }, nil } +func (s *ServiceImpl) GetLanguages(ctx context.Context, projectID int) ([]poedit.Language, error) { + resp, err := s.Client.ListProjectLanguages(ctx, poedit.ListProjectLanguagesRequest{ + ID: projectID, + }) + if err != nil { + return nil, err + } + + languages := make([]poedit.Language, len(resp.Result.Languages)) + for i, lang := range resp.Result.Languages { + languages[i] = poedit.Language{ + Name: lang.Name, + Code: lang.Code, + Translations: lang.Translations, + Percentage: lang.Percentage, + Updated: lang.Updated, + } + } + + return languages, nil +} + func (s *ServiceImpl) PurgeTranslation(ctx context.Context, projectID int, languageCode string) error { return errors.New("Not implemented") } diff --git a/internal/rest/v1/project.go b/internal/rest/v1/project.go index 25d1204..96a4c2f 100644 --- a/internal/rest/v1/project.go +++ b/internal/rest/v1/project.go @@ -90,3 +90,49 @@ func (h *Handlers) getProjectLanguage(ctx echo.Context, l *logrus.Entry) error { return ctx.Stream(http.StatusOK, contentMeta.Type, bytes.NewReader(trans.Data)) } + +type getProjectLanguagesRequest struct { + Project int `param:"project" validate:"required"` +} + +func (h *Handlers) getProjectLanguages(ctx echo.Context, l *logrus.Entry) error { + req := new(getProjectLanguagesRequest) + if err := ctx.Bind(req); err != nil { + l.WithError(err).Error("Error binding request") + + return echo.ErrBadRequest + } + + l = l.WithFields(logrus.Fields{ + "project": req.Project, + }) + + if err := ctx.Validate(req); err != nil { + l.WithError(err).Error("Error validating request") + + return echo.ErrBadRequest + } + + languages, err := h.ProjectService.GetLanguages( + ctx.Request().Context(), + req.Project, + ) + if errors.Is(err, context.Canceled) { + return echo.NewHTTPError(499, "client closed request") + } + + if err != nil { + switch err.(type) { + case *poedit.ErrProjectPermissionDenied: + return echo.ErrBadRequest + default: + l.WithError(err).Error("Error retrieving languages") + + return echo.ErrInternalServerError + } + } + + return ctx.JSON(http.StatusOK, map[string]interface{}{ + "languages": languages, + }) +} diff --git a/internal/rest/v1/routes.go b/internal/rest/v1/routes.go index a909869..2fff677 100644 --- a/internal/rest/v1/routes.go +++ b/internal/rest/v1/routes.go @@ -29,6 +29,7 @@ func Register(e *echo.Echo, l *logrus.Entry, projectService project.Service, ena g.Use(prom) } + g.GET("/project/:project/languages", wrap(h.getProjectLanguages, l)) g.GET("/project/:project/language/:language", wrap(h.getProjectLanguage, l)) } diff --git a/pkg/poedit/client.go b/pkg/poedit/client.go index 860e336..49f91ae 100644 --- a/pkg/poedit/client.go +++ b/pkg/poedit/client.go @@ -10,6 +10,7 @@ import ( // Client is an interface to poeditors api type Client interface { ExportProject(ctx context.Context, req ExportProjectRequest) (result *ExportProjectResponse, err error) + ListProjectLanguages(ctx context.Context, req ListProjectLanguagesRequest) (result *ListProjectLanguagesResponse, err error) } // ClientImpl is an implementation of the poeditor client interface diff --git a/pkg/poedit/languages.go b/pkg/poedit/languages.go index 5147917..6d7037e 100644 --- a/pkg/poedit/languages.go +++ b/pkg/poedit/languages.go @@ -7,6 +7,15 @@ import ( "github.com/pkg/errors" ) +// Language represents a language in a POEditor project +type Language struct { + Name string `json:"name"` + Code string `json:"code"` + Translations int64 `json:"translations"` + Percentage float64 `json:"percentage"` + Updated string `json:"updated"` +} + type ListAvailableLanguagesResponse struct { Response struct { Status string `json:"status"`