mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 01:10:20 -06:00
feat(activitylog): translations
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
@@ -14,6 +14,9 @@ import (
|
||||
micrometadata "go-micro.dev/v4/metadata"
|
||||
)
|
||||
|
||||
// HeaderAcceptLanguage is the header key for the accept-language header
|
||||
var HeaderAcceptLanguage = "Accept-Language"
|
||||
|
||||
// Template marks a string as translatable
|
||||
func Template(s string) string { return s }
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
SHELL := bash
|
||||
NAME := activitylog
|
||||
|
||||
# Where to write the files generated by this makefile.
|
||||
OUTPUT_DIR = ./pkg/service/l10n
|
||||
TEMPLATE_FILE = ./pkg/service/l10n/activitylog.pot
|
||||
|
||||
include ../../.make/recursion.mk
|
||||
|
||||
############ tooling ############
|
||||
@@ -29,6 +33,26 @@ ci-go-generate: # CI runs ci-node-generate automatically before this target
|
||||
.PHONY: ci-node-generate
|
||||
ci-node-generate:
|
||||
|
||||
############ translations ########
|
||||
.PHONY: l10n-pull
|
||||
l10n-pull:
|
||||
cd $(OUTPUT_DIR) && tx pull --all --force --skip --minimum-perc=75
|
||||
|
||||
.PHONY: l10n-push
|
||||
l10n-push:
|
||||
cd $(OUTPUT_DIR) && tx push -s --skip
|
||||
|
||||
.PHONY: l10n-read
|
||||
l10n-read: $(GO_XGETTEXT)
|
||||
go-xgettext -o $(OUTPUT_DIR)/userlog.pot --keyword=l10n.Template -s pkg/service/response.go
|
||||
|
||||
.PHONY: l10n-write
|
||||
l10n-write:
|
||||
|
||||
.PHONY: l10n-clean
|
||||
l10n-clean:
|
||||
rm -f $(TEMPLATE_FILE);
|
||||
|
||||
############ licenses ############
|
||||
.PHONY: ci-node-check-licenses
|
||||
ci-node-check-licenses:
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/version"
|
||||
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/config/parser"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/logging"
|
||||
@@ -119,6 +120,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
}
|
||||
|
||||
hClient := ehsvc.NewEventHistoryService("com.owncloud.api.eventhistory", grpcClient)
|
||||
vClient := settingssvc.NewValueService("com.owncloud.api.settings", grpcClient)
|
||||
|
||||
{
|
||||
svc, err := http.Server(
|
||||
@@ -130,7 +132,8 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
http.RegisteredEvents(_registeredEvents),
|
||||
http.Store(evStore),
|
||||
http.GatewaySelector(gatewaySelector),
|
||||
http.History(hClient),
|
||||
http.HistoryClient(hClient),
|
||||
http.ValueClient(vClient),
|
||||
http.RegisteredEvents(_registeredEvents),
|
||||
)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/metrics"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -31,6 +32,7 @@ type Options struct {
|
||||
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
TraceProvider trace.TracerProvider
|
||||
HistoryClient ehsvc.EventHistoryService
|
||||
ValueClient settingssvc.ValueService
|
||||
RegisteredEvents []events.Unmarshaller
|
||||
}
|
||||
|
||||
@@ -108,8 +110,8 @@ func GatewaySelector(gatewaySelector pool.Selectable[gateway.GatewayAPIClient])
|
||||
}
|
||||
}
|
||||
|
||||
// History provides a function to configure the event history client
|
||||
func History(h ehsvc.EventHistoryService) Option {
|
||||
// HistoryClient provides a function to configure the event history client
|
||||
func HistoryClient(h ehsvc.EventHistoryService) Option {
|
||||
return func(o *Options) {
|
||||
o.HistoryClient = h
|
||||
}
|
||||
@@ -128,3 +130,10 @@ func TraceProvider(val trace.TracerProvider) Option {
|
||||
o.TraceProvider = val
|
||||
}
|
||||
}
|
||||
|
||||
// ValueClient provides a function to set the ValueClient options
|
||||
func ValueClient(val settingssvc.ValueService) Option {
|
||||
return func(o *Options) {
|
||||
o.ValueClient = val
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ func Server(opts ...Option) (http.Service, error) {
|
||||
svc.GatewaySelector(options.GatewaySelector),
|
||||
svc.TraceProvider(options.TraceProvider),
|
||||
svc.HistoryClient(options.HistoryClient),
|
||||
svc.ValueClient(options.ValueClient),
|
||||
svc.RegisteredEvents(options.RegisteredEvents),
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
revactx "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
|
||||
ehmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/eventhistory/v0"
|
||||
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed l10n/locale
|
||||
_localeFS embed.FS
|
||||
|
||||
// subfolder where the translation files are stored
|
||||
_localeSubPath = "l10n/locale"
|
||||
|
||||
// domain of the activitylog service (transifex)
|
||||
_domain = "activitylog"
|
||||
)
|
||||
|
||||
// ServeHTTP implements the http.Handler interface.
|
||||
func (s *ActivitylogService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.mux.ServeHTTP(w, r)
|
||||
@@ -22,6 +36,12 @@ func (s *ActivitylogService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// HandleGetItemActivities handles the request to get the activities of an item.
|
||||
func (s *ActivitylogService) HandleGetItemActivities(w http.ResponseWriter, r *http.Request) {
|
||||
activeUser, ok := revactx.ContextGetUser(r.Context())
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Compare driveid with itemid to avoid bad requests
|
||||
rid, err := parseIDParam(r, "item-id")
|
||||
if err != nil {
|
||||
@@ -68,49 +88,49 @@ func (s *ActivitylogService) HandleGetItemActivities(w http.ResponseWriter, r *h
|
||||
// error already logged in unwrapEvent
|
||||
continue
|
||||
case events.UploadReady:
|
||||
message = "{user} created {resource}"
|
||||
message = MessageResourceCreated
|
||||
res, act, ts, err = s.ResponseData(ev.FileRef, ev.ExecutingUser.GetId(), ev.ExecutingUser.GetDisplayName(), utils.TSToTime(ev.Timestamp))
|
||||
case events.FileTouched:
|
||||
message = "{user} created {resource}"
|
||||
message = MessageResourceCreated
|
||||
res, act, ts, err = s.ResponseData(ev.Ref, ev.Executant, "", utils.TSToTime(ev.Timestamp))
|
||||
case events.ContainerCreated:
|
||||
message = "{user} created {resource}"
|
||||
message = MessageResourceCreated
|
||||
res, act, ts, err = s.ResponseData(ev.Ref, ev.Executant, "", utils.TSToTime(ev.Timestamp))
|
||||
case events.ItemTrashed:
|
||||
message = "{user} trashed {resource}"
|
||||
message = MessageResourceTrashed
|
||||
res, act, ts, err = s.ResponseData(ev.Ref, ev.Executant, "", utils.TSToTime(ev.Timestamp))
|
||||
case events.ItemPurged:
|
||||
message = "{user} purged {resource}"
|
||||
message = MessageResourcePurged
|
||||
res, act, ts, err = s.ResponseData(ev.Ref, ev.Executant, "", utils.TSToTime(ev.Timestamp))
|
||||
case events.ItemMoved:
|
||||
message = "{user} moved {resource}"
|
||||
message = MessageResourceMoved
|
||||
res, act, ts, err = s.ResponseData(ev.Ref, ev.Executant, "", utils.TSToTime(ev.Timestamp))
|
||||
case events.ShareCreated:
|
||||
message = "{user} shared {resource}"
|
||||
message = MessageShareCreated
|
||||
res, act, ts, err = s.ResponseData(toRef(ev.ItemID), ev.Executant, "", utils.TSToTime(ev.CTime))
|
||||
case events.ShareUpdated:
|
||||
message = "{user} updated share of {resource}"
|
||||
message = MessageShareUpdated
|
||||
res, act, ts, err = s.ResponseData(toRef(ev.ItemID), ev.Executant, "", utils.TSToTime(ev.MTime))
|
||||
case events.ShareRemoved:
|
||||
message = "{user} removed share of {resource}"
|
||||
message = MessageShareDeleted
|
||||
res, act, ts, err = s.ResponseData(toRef(ev.ItemID), ev.Executant, "", ev.Timestamp)
|
||||
case events.LinkCreated:
|
||||
message = "{user} created link to {resource}"
|
||||
message = MessageLinkCreated
|
||||
res, act, ts, err = s.ResponseData(toRef(ev.ItemID), ev.Executant, "", utils.TSToTime(ev.CTime))
|
||||
case events.LinkUpdated:
|
||||
message = "{user} updated link to {resource}"
|
||||
message = MessageLinkUpdated
|
||||
res, act, ts, err = s.ResponseData(toRef(ev.ItemID), ev.Executant, "", utils.TSToTime(ev.CTime))
|
||||
case events.LinkRemoved:
|
||||
message = "{user} removed link to {resource}"
|
||||
message = MessageLinkDeleted
|
||||
res, act, ts, err = s.ResponseData(toRef(ev.ItemID), ev.Executant, "", utils.TSToTime(ev.Timestamp))
|
||||
case events.SpaceShared:
|
||||
message = "{user} shared space {resource}"
|
||||
message = MessageSpaceShared
|
||||
res, act, ts, err = s.ResponseData(sToRef(ev.ID), ev.Executant, "", ev.Timestamp)
|
||||
case events.SpaceShareUpdated:
|
||||
message = "{user} updated share of space {resource}"
|
||||
message = MessageSpaceShareUpdated
|
||||
res, act, ts, err = s.ResponseData(sToRef(ev.ID), ev.Executant, "", ev.Timestamp)
|
||||
case events.SpaceUnshared:
|
||||
message = "{user} unshared space {resource}"
|
||||
message = MessageSpaceUnshared
|
||||
res, act, ts, err = s.ResponseData(sToRef(ev.ID), ev.Executant, "", ev.Timestamp)
|
||||
}
|
||||
|
||||
@@ -119,7 +139,11 @@ func (s *ActivitylogService) HandleGetItemActivities(w http.ResponseWriter, r *h
|
||||
continue
|
||||
}
|
||||
|
||||
resp.Activities = append(resp.Activities, NewActivity(message, res, act, ts.RecordedTime, e.GetId()))
|
||||
// todo: configurable default locale?
|
||||
loc := l10n.MustGetUserLocale(r.Context(), activeUser.GetId().GetOpaqueId(), r.Header.Get(l10n.HeaderAcceptLanguage), s.valService)
|
||||
t := l10n.NewTranslatorFromCommonConfig("en", _domain, "", _localeFS, _localeSubPath)
|
||||
|
||||
resp.Activities = append(resp.Activities, NewActivity(t.Translate(message, loc), res, act, ts, e.GetId()))
|
||||
}
|
||||
|
||||
b, err := json.Marshal(resp)
|
||||
|
||||
22
services/activitylog/pkg/service/l10n/userlog.pot
Normal file
22
services/activitylog/pkg/service/l10n/userlog.pot
Normal file
@@ -0,0 +1,22 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2024-06-14 15:29+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: pkg/service/response.go:15
|
||||
msgid "{user} created {resource}"
|
||||
msgstr ""
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/config"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
@@ -26,6 +27,7 @@ type Options struct {
|
||||
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
Mux *chi.Mux
|
||||
HistoryClient ehsvc.EventHistoryService
|
||||
ValueClient settingssvc.ValueService
|
||||
}
|
||||
|
||||
// Logger configures a logger for the activitylog service
|
||||
@@ -90,3 +92,10 @@ func HistoryClient(hc ehsvc.EventHistoryService) Option {
|
||||
o.HistoryClient = hc
|
||||
}
|
||||
}
|
||||
|
||||
// ValueClient adds a grpc client for the value service
|
||||
func ValueClient(vs settingssvc.ValueService) Option {
|
||||
return func(o *Options) {
|
||||
o.ValueClient = vs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,24 @@ import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
|
||||
)
|
||||
|
||||
// Translations
|
||||
var (
|
||||
MessageResourceCreated = l10n.Template("{user} created {resource}")
|
||||
MessageResourceTrashed = l10n.Template("{user} trashed {resource}")
|
||||
MessageResourcePurged = l10n.Template("{user} purged {resource}")
|
||||
MessageResourceMoved = l10n.Template("{user} moved {resource}")
|
||||
MessageShareCreated = l10n.Template("{user} shared {resource}")
|
||||
MessageShareUpdated = l10n.Template("{user} updated share of {resource}")
|
||||
MessageShareDeleted = l10n.Template("{user} deleted share of {resource}")
|
||||
MessageLinkCreated = l10n.Template("{user} created link to {resource}")
|
||||
MessageLinkUpdated = l10n.Template("{user} updated link to {resource}")
|
||||
MessageLinkDeleted = l10n.Template("{user} deleted link to {resource}")
|
||||
MessageSpaceShared = l10n.Template("{user} shared space {resource}")
|
||||
MessageSpaceShareUpdated = l10n.Template("{user} updated share of space {resource}")
|
||||
MessageSpaceUnshared = l10n.Template("{user} unshared space {resource}")
|
||||
)
|
||||
|
||||
// GetActivitiesResponse is the response on GET activities requests
|
||||
@@ -45,12 +63,10 @@ type Template struct {
|
||||
}
|
||||
|
||||
// NewActivity creates a new activity
|
||||
func NewActivity(message string, res Resource, user Actor, ts time.Time, eventID string) Activity {
|
||||
func NewActivity(message string, res Resource, user Actor, ts Times, eventID string) Activity {
|
||||
return Activity{
|
||||
ID: eventID,
|
||||
Times: Times{
|
||||
RecordedTime: ts,
|
||||
},
|
||||
ID: eventID,
|
||||
Times: ts,
|
||||
Template: Template{
|
||||
Message: message,
|
||||
Variables: map[string]interface{}{
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/activitylog/pkg/config"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
)
|
||||
@@ -30,13 +31,14 @@ type RawActivity struct {
|
||||
|
||||
// ActivitylogService logs events per resource
|
||||
type ActivitylogService struct {
|
||||
cfg *config.Config
|
||||
log log.Logger
|
||||
events <-chan events.Event
|
||||
store microstore.Store
|
||||
gws pool.Selectable[gateway.GatewayAPIClient]
|
||||
mux *chi.Mux
|
||||
evHistory ehsvc.EventHistoryService
|
||||
cfg *config.Config
|
||||
log log.Logger
|
||||
events <-chan events.Event
|
||||
store microstore.Store
|
||||
gws pool.Selectable[gateway.GatewayAPIClient]
|
||||
mux *chi.Mux
|
||||
evHistory ehsvc.EventHistoryService
|
||||
valService settingssvc.ValueService
|
||||
|
||||
registeredEvents map[string]events.Unmarshaller
|
||||
}
|
||||
@@ -69,6 +71,7 @@ func New(opts ...Option) (*ActivitylogService, error) {
|
||||
gws: o.GatewaySelector,
|
||||
mux: o.Mux,
|
||||
evHistory: o.HistoryClient,
|
||||
valService: o.ValueClient,
|
||||
registeredEvents: make(map[string]events.Unmarshaller),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user