make translationpath configurable

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2023-03-13 10:19:44 +01:00
parent 495d507ce1
commit 3e090c557f
6 changed files with 35 additions and 14 deletions

View File

@@ -44,7 +44,7 @@ l10n-push:
.PHONY: l10n-read
l10n-read:
go-xgettext -o $(OUTPUT_DIR)/locale/default.pot --keyword=Template -s pkg/service/templates.go
go-xgettext -o $(OUTPUT_DIR)/locale/userlog.pot --keyword=Template -s pkg/service/templates.go
.PHONY: l10n-write
l10n-write:

View File

@@ -31,3 +31,17 @@ The `userlog` service provides an API to retrieve configured events. For now, th
## Deleting
To delete events for an user, use a `DELETE` request to `ocs/v2.php/apps/notifications/api/v1/notifications` containing the IDs to delete.
## Translations
The `userlog` service uses embedded translations to provide full functionality even in the single binary case. The service supports using custom translations instead. Set `USERLOG_TRANSLATION_PATH` to a folder that contains the translation files. In this folder translation files need to be named `userlog.po` (or `userlog.mo`) and need to be stored in a folder defining their language code. In general the pattern for a translation file needs to be:
```
{USERLOG_TRANSLATION_PATH}/{language-code}/LC_MESSAGES/userlog.po
```
So for example for language `en_US` one needs to place the corresponding translation files to `{USERLOG_TRANSLATION_PATH}/en_US/LC_MESSAGES/userlog.po`.
If a requested translation is not available the service falls back to the language default (so for example if `en_US` is not available, the service would fall back to translations in `en` folder).
If the default language is also not available (for example the language code is `de_DE` and neither `de_DE` nor `de` folder is available, the service falls back to system default (dev `en`)
It is currently not possible to mix custom and default translations.

View File

@@ -22,6 +22,7 @@ type Config struct {
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;USERLOG_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary to access resources from other services."`
RevaGateway string `yaml:"reva_gateway" env:"REVA_GATEWAY" desc:"CS3 gateway used to look up user metadata"`
TranslationPath string `yaml:"translation_path" env:"USERLOG_TRANSLATION_PATH" desc:"(optional) Set this to a path with custom translations to overwrite buildin translations. See readme for details"`
Events Events `yaml:"events"`
Store Store `yaml:"store"`

View File

@@ -27,9 +27,7 @@ var (
_resourceTypeSpace = "storagespace"
_resourceTypeShare = "share"
// TODO: from config
_pathToLocales = "/home/jkoberg/ocis/services/userlog/l10n/locale"
_domain = "default"
_domain = "userlog"
)
// OC10Notification is the oc10 style representation of an event
@@ -55,6 +53,7 @@ type Converter struct {
machineAuthAPIKey string
serviceName string
registeredEvents map[string]events.Unmarshaller
translationPath string
// cached within one request not to query other service too much
spaces map[string]*storageprovider.StorageSpace
@@ -64,13 +63,14 @@ type Converter struct {
}
// NewConverter returns a new Converter
func NewConverter(loc string, gwc gateway.GatewayAPIClient, machineAuthAPIKey string, name string, registeredEvents map[string]events.Unmarshaller) *Converter {
func NewConverter(loc string, gwc gateway.GatewayAPIClient, machineAuthAPIKey string, name string, translationPath string, registeredEvents map[string]events.Unmarshaller) *Converter {
return &Converter{
locale: loc,
gwClient: gwc,
machineAuthAPIKey: machineAuthAPIKey,
serviceName: name,
registeredEvents: registeredEvents,
translationPath: translationPath,
spaces: make(map[string]*storageprovider.StorageSpace),
users: make(map[string]*user.User),
resources: make(map[string]*storageprovider.ResourceInfo),
@@ -123,7 +123,7 @@ func (c *Converter) spaceDeletedMessage(eventid string, executant *user.UserId,
return OC10Notification{}, err
}
subj, subjraw, msg, msgraw, err := composeMessage(SpaceDeleted, c.locale, map[string]interface{}{
subj, subjraw, msg, msgraw, err := composeMessage(SpaceDeleted, c.locale, c.translationPath, map[string]interface{}{
"username": usr.GetDisplayName(),
"spacename": spacename,
})
@@ -164,7 +164,7 @@ func (c *Converter) spaceMessage(eventid string, nt NotificationTemplate, execut
return OC10Notification{}, err
}
subj, subjraw, msg, msgraw, err := composeMessage(nt, c.locale, map[string]interface{}{
subj, subjraw, msg, msgraw, err := composeMessage(nt, c.locale, c.translationPath, map[string]interface{}{
"username": usr.GetDisplayName(),
"spacename": space.GetName(),
})
@@ -203,7 +203,7 @@ func (c *Converter) shareMessage(eventid string, nt NotificationTemplate, execut
return OC10Notification{}, err
}
subj, subjraw, msg, msgraw, err := composeMessage(nt, c.locale, map[string]interface{}{
subj, subjraw, msg, msgraw, err := composeMessage(nt, c.locale, c.translationPath, map[string]interface{}{
"username": usr.GetDisplayName(),
"resourcename": info.GetName(),
})
@@ -270,8 +270,8 @@ func (c *Converter) getUser(ctx context.Context, userID *user.UserId) (*user.Use
return usr, err
}
func composeMessage(nt NotificationTemplate, locale string, vars map[string]interface{}) (string, string, string, string, error) {
subjectraw, messageraw := loadTemplates(nt, locale)
func composeMessage(nt NotificationTemplate, locale string, path string, vars map[string]interface{}) (string, string, string, string, error) {
subjectraw, messageraw := loadTemplates(nt, locale, path)
subject, err := executeTemplate(subjectraw, vars)
if err != nil {
@@ -283,10 +283,15 @@ func composeMessage(nt NotificationTemplate, locale string, vars map[string]inte
}
func loadTemplates(nt NotificationTemplate, locale string) (string, string) {
func loadTemplates(nt NotificationTemplate, locale string, path string) (string, string) {
// Create Locale with library path and language code and load default domain
l := gotext.NewLocaleFS("l10n/locale", locale, _translationFS)
l.AddDomain(_domain)
var l *gotext.Locale
if path == "" {
l = gotext.NewLocaleFS("l10n/locale", locale, _translationFS)
} else { // use custom path instead
l = gotext.NewLocale(path, locale)
}
l.AddDomain(_domain) // make domain configurable only if needed
return l.Get(nt.Subject), l.Get(nt.Message)
}

View File

@@ -31,7 +31,7 @@ func (ul *UserlogService) HandleGetEvents(w http.ResponseWriter, r *http.Request
return
}
conv := NewConverter(r.Header.Get(HeaderPreferedLanguage), ul.gwClient, ul.cfg.MachineAuthAPIKey, ul.cfg.Service.Name, ul.registeredEvents)
conv := NewConverter(r.Header.Get(HeaderPreferedLanguage), ul.gwClient, ul.cfg.MachineAuthAPIKey, ul.cfg.Service.Name, ul.cfg.TranslationPath, ul.registeredEvents)
resp := GetEventResponseOC10{}
for _, e := range evs {

View File

@@ -33,6 +33,7 @@ type UserlogService struct {
historyClient ehsvc.EventHistoryService
gwClient gateway.GatewayAPIClient
registeredEvents map[string]events.Unmarshaller
translationPath string
}
// NewUserlogService returns an EventHistory service