feat(settings): translate notifications settings
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
@@ -38,6 +38,7 @@ type Config struct {
|
||||
ServiceAccountIDs []string `yaml:"service_account_ids" env:"SETTINGS_SERVICE_ACCOUNT_IDS;OCIS_SERVICE_ACCOUNT_ID" desc:"The list of all service account IDs. These will be assigned the hidden 'service-account' role. Note: When using 'OCIS_SERVICE_ACCOUNT_ID' this will contain only one value while 'SETTINGS_SERVICE_ACCOUNT_IDS' can have multiple. See the 'auth-service' service description for more details about service accounts." introductionVersion:"5.0"`
|
||||
|
||||
DefaultLanguage string `yaml:"default_language" env:"OCIS_DEFAULT_LANGUAGE" desc:"The default language used by services and the WebUI. If not defined, English will be used as default. See the documentation for more details." introductionVersion:"5.0"`
|
||||
TranslationPath string `yaml:"translation_path" env:"OCIS_TRANSLATION_PATH;SETTINGS_TRANSLATION_PATH" desc:"(optional) Set this to a path with custom translations to overwrite the builtin translations. Note that file and folder naming rules apply, see the documentation for more details." introductionVersion:"7.0"`
|
||||
|
||||
Context context.Context `yaml:"-"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[o:owncloud-org:p:owncloud:r:ocis-settings]
|
||||
file_filter = locale/<lang>/LC_MESSAGES/settings.po
|
||||
minimum_perc = 75
|
||||
resource_name = ocis-settings
|
||||
source_file = settings.pot
|
||||
source_lang = en
|
||||
type = PO
|
||||
@@ -2,13 +2,17 @@ package svc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
cs3permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
|
||||
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/roles"
|
||||
@@ -23,6 +27,11 @@ import (
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
//go:embed l10n/locale
|
||||
var _translationFS embed.FS
|
||||
|
||||
var _domain = "settings"
|
||||
|
||||
// Service represents a service.
|
||||
type Service struct {
|
||||
id string
|
||||
@@ -134,18 +143,29 @@ func (g Service) ListBundles(ctx context.Context, req *settingssvc.ListBundlesRe
|
||||
if validationError := validateListBundles(req); validationError != nil {
|
||||
return merrors.BadRequest(g.id, "%s", validationError)
|
||||
}
|
||||
bundles, err := g.manager.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, req.BundleIds)
|
||||
bundles, err := g.manager.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, req.GetBundleIds())
|
||||
if err != nil {
|
||||
return merrors.NotFound(g.id, "%s", err)
|
||||
}
|
||||
roleIDs := g.getRoleIDs(ctx)
|
||||
|
||||
// find user locale
|
||||
var locale string
|
||||
if u, ok := ctxpkg.ContextGetUser(ctx); ok {
|
||||
var err error
|
||||
locale, err = g.getUserLocale(ctx, u.GetId().GetOpaqueId())
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Str("userid", u.GetId().GetOpaqueId()).Msg("failed to get user locale")
|
||||
}
|
||||
}
|
||||
|
||||
// filter settings in bundles that are allowed according to roles
|
||||
var filteredBundles []*settingsmsg.Bundle
|
||||
for _, bundle := range bundles {
|
||||
filteredBundle := g.getFilteredBundle(roleIDs, bundle)
|
||||
if len(filteredBundle.Settings) > 0 {
|
||||
filteredBundles = append(filteredBundles, filteredBundle)
|
||||
if len(filteredBundle.GetSettings()) > 0 {
|
||||
t := l10n.NewTranslatorFromCommonConfig(g.config.DefaultLanguage, _domain, g.config.TranslationPath, _translationFS, "l10n/locale").Locale(locale)
|
||||
filteredBundles = append(filteredBundles, translateBundle(filteredBundle, t))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,7 +662,58 @@ func (g Service) canManageRoles(ctx context.Context) bool {
|
||||
return g.hasStaticPermission(ctx, RoleManagementPermissionID)
|
||||
}
|
||||
|
||||
func (g Service) getUserLocale(ctx context.Context, userID string) (string, error) {
|
||||
var resp settingssvc.GetValueResponse
|
||||
err := g.GetValueByUniqueIdentifiers(
|
||||
ctx,
|
||||
&settingssvc.GetValueByUniqueIdentifiersRequest{
|
||||
AccountUuid: userID,
|
||||
SettingId: defaults.SettingUUIDProfileLanguage,
|
||||
},
|
||||
&resp,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
val := resp.GetValue().GetValue().GetListValue().GetValues()
|
||||
if len(val) == 0 {
|
||||
return "", errors.New("no language setting found")
|
||||
}
|
||||
return val[0].GetStringValue(), nil
|
||||
}
|
||||
|
||||
func formatPermissionName(setting *settingsmsg.Setting) string {
|
||||
constraint := strings.TrimPrefix(setting.GetPermissionValue().GetConstraint().String(), "CONSTRAINT_")
|
||||
return setting.Name + "." + strings.ToLower(constraint)
|
||||
}
|
||||
|
||||
func translateBundle(bundle *settingsmsg.Bundle, t *gotext.Locale) *settingsmsg.Bundle {
|
||||
for i, set := range bundle.GetSettings() {
|
||||
switch set.GetId() {
|
||||
default:
|
||||
continue
|
||||
case defaults.SettingUUIDProfileEmailSendingInterval:
|
||||
// translate interval names ('Instant', 'Daily', 'Weekly', 'Never')
|
||||
value := set.GetSingleChoiceValue()
|
||||
for i, v := range value.GetOptions() {
|
||||
value.Options[i].DisplayValue = t.Get(v.GetDisplayValue())
|
||||
}
|
||||
set.Value = &settingsmsg.Setting_SingleChoiceValue{SingleChoiceValue: value}
|
||||
fallthrough
|
||||
case defaults.SettingUUIDProfileEventShareCreated,
|
||||
defaults.SettingUUIDProfileEventShareRemoved,
|
||||
defaults.SettingUUIDProfileEventShareExpired,
|
||||
defaults.SettingUUIDProfileEventSpaceShared,
|
||||
defaults.SettingUUIDProfileEventSpaceUnshared,
|
||||
defaults.SettingUUIDProfileEventSpaceMembershipExpired,
|
||||
defaults.SettingUUIDProfileEventSpaceDisabled,
|
||||
defaults.SettingUUIDProfileEventSpaceDeleted:
|
||||
// translate event names ('Share Received', 'Share Removed', ...)
|
||||
set.DisplayName = t.Get(set.GetDisplayName())
|
||||
// translate event descriptions ('Notify me when I receive a share', ...)
|
||||
set.Description = t.Get(set.GetDescription())
|
||||
bundle.Settings[i] = set
|
||||
}
|
||||
}
|
||||
return bundle
|
||||
}
|
||||
|
||||
@@ -282,8 +282,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEmailSendingInterval,
|
||||
Name: "email-sending-interval-options",
|
||||
DisplayName: "Email Notifications options",
|
||||
Description: "Email notifications options",
|
||||
DisplayName: TemplateEmailSendingInterval,
|
||||
Description: TemplateEmailSendingIntervalDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -292,8 +292,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventShareCreated,
|
||||
Name: "event-share-created-options",
|
||||
DisplayName: "Share created",
|
||||
Description: "Share created",
|
||||
DisplayName: TemplateShareCreated,
|
||||
Description: TemplateShareCreatedDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -309,8 +309,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventShareRemoved,
|
||||
Name: "event-share-removed-options",
|
||||
DisplayName: "Share removed",
|
||||
Description: "Share removed",
|
||||
DisplayName: TemplateShareRemoved,
|
||||
Description: TemplateShareRemovedDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -326,8 +326,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventShareExpired,
|
||||
Name: "event-share-expired-options",
|
||||
DisplayName: "Share expired",
|
||||
Description: "Share expired",
|
||||
DisplayName: TemplateShareExpired,
|
||||
Description: TemplateShareExpiredDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -343,8 +343,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventSpaceShared,
|
||||
Name: "event-space-shared-options",
|
||||
DisplayName: "Space shared",
|
||||
Description: "Space shared",
|
||||
DisplayName: TemplateSpaceShared,
|
||||
Description: TemplateSpaceSharedDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -360,8 +360,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventSpaceUnshared,
|
||||
Name: "event-space-unshared-options",
|
||||
DisplayName: "Space unshared",
|
||||
Description: "Space unshared",
|
||||
DisplayName: TemplateSpaceUnshared,
|
||||
Description: TemplateSpaceUnsharedDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -377,8 +377,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventSpaceMembershipExpired,
|
||||
Name: "event-space-membership-expired-options",
|
||||
DisplayName: "Space membership expired",
|
||||
Description: "Space membership expired",
|
||||
DisplayName: TemplateSpaceMembershipExpired,
|
||||
Description: TemplateSpaceMembershipExpiredDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -394,8 +394,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventSpaceDisabled,
|
||||
Name: "event-space-disabled-options",
|
||||
DisplayName: "Space disabled",
|
||||
Description: "Space disabled",
|
||||
DisplayName: TemplateSpaceDisabled,
|
||||
Description: TemplateSpaceDisabledDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -411,8 +411,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventSpaceDeleted,
|
||||
Name: "event-space-deleted-options",
|
||||
DisplayName: "Space deleted",
|
||||
Description: "Space deleted",
|
||||
DisplayName: TemplateSpaceDeleted,
|
||||
Description: TemplateSpaceDeletedDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -428,8 +428,8 @@ func generateBundleProfileRequest() *settingsmsg.Bundle {
|
||||
{
|
||||
Id: SettingUUIDProfileEventPostprocessingStepFinished,
|
||||
Name: "event-postprocessing-step-finished-options",
|
||||
DisplayName: "Postprocessing Step Finished",
|
||||
Description: "Postprocessing Step Finished",
|
||||
DisplayName: TemplateFileRejected,
|
||||
Description: TemplateFileRejectedDescription,
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_USER,
|
||||
},
|
||||
@@ -455,7 +455,7 @@ var sendEmailOptions = settingsmsg.Setting_SingleChoiceValue{
|
||||
StringValue: "instant",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Instant",
|
||||
DisplayValue: TemplateIntervalInstant,
|
||||
Default: true,
|
||||
},
|
||||
{
|
||||
@@ -464,7 +464,7 @@ var sendEmailOptions = settingsmsg.Setting_SingleChoiceValue{
|
||||
StringValue: "daily",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Daily",
|
||||
DisplayValue: TemplateIntervalDaily,
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
@@ -472,7 +472,7 @@ var sendEmailOptions = settingsmsg.Setting_SingleChoiceValue{
|
||||
StringValue: "weekly",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Weekly",
|
||||
DisplayValue: TemplateIntervalWeekly,
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
@@ -480,7 +480,7 @@ var sendEmailOptions = settingsmsg.Setting_SingleChoiceValue{
|
||||
StringValue: "never",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Never",
|
||||
DisplayValue: TemplateIntervalNever,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package defaults
|
||||
|
||||
import "github.com/owncloud/ocis/v2/ocis-pkg/l10n"
|
||||
|
||||
// Translatable configuration options
|
||||
var (
|
||||
// name of the notification option 'Share Received'
|
||||
TemplateShareCreated = l10n.Template("Share Received")
|
||||
// description of the notification option 'Share Received'
|
||||
TemplateShareCreatedDescription = l10n.Template("Notify me when I receive a share")
|
||||
// name of the notification option 'Share Removed'
|
||||
TemplateShareRemoved = l10n.Template("Share Removed")
|
||||
// description of the notification option 'Share Removed'
|
||||
TemplateShareRemovedDescription = l10n.Template("Notify me when my shares are removed")
|
||||
// name of the notification option 'Share Expired'
|
||||
TemplateShareExpired = l10n.Template("Share Expired")
|
||||
// description of the notification option 'Share Expired'
|
||||
TemplateShareExpiredDescription = l10n.Template("Notify me when my shares expire")
|
||||
// name of the notification option 'Space Shared'
|
||||
TemplateSpaceShared = l10n.Template("Added as space member")
|
||||
// description of the notification option 'Space Shared'
|
||||
TemplateSpaceSharedDescription = l10n.Template("Notify me when I am added as a member to a space")
|
||||
// name of the notification option 'Space Unshared'
|
||||
TemplateSpaceUnshared = l10n.Template("Removed as space member")
|
||||
// description of the notification option 'Space Unshared'
|
||||
TemplateSpaceUnsharedDescription = l10n.Template("Notify me when I am removed as a member from a space")
|
||||
// name of the notification option 'Space Membership Expired'
|
||||
TemplateSpaceMembershipExpired = l10n.Template("Space membership expired")
|
||||
// description of the notification option 'Space Membership Expired'
|
||||
TemplateSpaceMembershipExpiredDescription = l10n.Template("Notify me when my membership of a space expires")
|
||||
// name of the notification option 'Space Disabled'
|
||||
TemplateSpaceDisabled = l10n.Template("Space disabled")
|
||||
// description of the notification option 'Space Disabled'
|
||||
TemplateSpaceDisabledDescription = l10n.Template("Notify me when a space I am a member of is disabled")
|
||||
// name of the notification option 'Space Deleted'
|
||||
TemplateSpaceDeleted = l10n.Template("Space deleted")
|
||||
// description of the notification option 'Space Deleted'
|
||||
TemplateSpaceDeletedDescription = l10n.Template("Notify me when a space I am a member of is deleted")
|
||||
// name of the notification option 'File Rejected'
|
||||
TemplateFileRejected = l10n.Template("File rejected")
|
||||
// description of the notification option 'File Rejected'
|
||||
TemplateFileRejectedDescription = l10n.Template("Notify me when a file I uploaded is rejected because of virus infection or policy violation")
|
||||
// name of the notification option 'Email Interval'
|
||||
TemplateEmailSendingInterval = l10n.Template("Email sending interval")
|
||||
// description of the notification option 'Email Interval'
|
||||
TemplateEmailSendingIntervalDescription = l10n.Template("Notifiy me via email:")
|
||||
// translation for the 'instant' email interval option
|
||||
TemplateIntervalInstant = l10n.Template("Instant")
|
||||
// translation for the 'daily' email interval option
|
||||
TemplateIntervalDaily = l10n.Template("Daily")
|
||||
// translation for the 'weekly' email interval option
|
||||
TemplateIntervalWeekly = l10n.Template("Weekly")
|
||||
// translation for the 'never' email interval option
|
||||
TemplateIntervalNever = l10n.Template("Never")
|
||||
)
|
||||
Reference in New Issue
Block a user