Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport from edge: added support for language locales in apps #3303

Merged
merged 1 commit into from
Oct 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions changelog/unreleased/lang-supp-in-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Enhancement: added support for configuring language locales in apps

This is a partial backport from edge: we introduce a language option
in the appprovider, which if set is passed as appropriate parameter
to the external apps in order to force a given localization. In particular,
for Microsoft Office 365 the DC_LLCC option is set as well.
The default behavior is unset, where apps try and resolve the
localization from the browser headers.

https://github.com/cs3org/reva/pull/3303
1 change: 1 addition & 0 deletions examples/storage-references/gateway.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mime_types = [

[grpc.services.appprovider]
mime_types = ["text/plain"]
language = "en-GB"

[http.services.datagateway]
[http.services.prometheus]
Expand Down
3 changes: 2 additions & 1 deletion internal/grpc/services/appprovider/appprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type config struct {
GatewaySvc string `mapstructure:"gatewaysvc"`
MimeTypes []string `mapstructure:"mime_types"`
Priority uint64 `mapstructure:"priority"`
Language string `mapstructure:"language"`
}

func (c *config) init() {
Expand Down Expand Up @@ -170,7 +171,7 @@ func getProvider(c *config) (app.Provider, error) {
}

func (s *service) OpenInApp(ctx context.Context, req *providerpb.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) {
appURL, err := s.provider.GetAppURL(ctx, req.ResourceInfo, req.ViewMode, req.AccessToken)
appURL, err := s.provider.GetAppURL(ctx, req.ResourceInfo, req.ViewMode, req.AccessToken, s.conf.Language)
if err != nil {
res := &providerpb.OpenInAppResponse{
Status: status.NewInternal(ctx, errors.New("appprovider: error calling GetAppURL"), err.Error()),
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ type Registry interface {
// Provider is the interface that application providers implement
// for interacting with external apps that serve the requested resource.
type Provider interface {
GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error)
GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token, language string) (*appprovider.OpenInAppURL, error)
GetAppProviderInfo(ctx context.Context) (*registry.ProviderInfo, error)
}
4 changes: 2 additions & 2 deletions pkg/app/provider/demo/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ type demoProvider struct {
iframeUIProvider string
}

func (p *demoProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error) {
url := fmt.Sprintf("<iframe src=%s/open/%s?view-mode=%s&access-token=%s />", p.iframeUIProvider, resource.Id.StorageId+":"+resource.Id.OpaqueId, viewMode.String(), token)
func (p *demoProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token, language string) (*appprovider.OpenInAppURL, error) {
url := fmt.Sprintf("<iframe src=%s/open/%s?view-mode=%s&access-token=%s&lang=%s />", p.iframeUIProvider, resource.Id.StorageId+":"+resource.Id.OpaqueId, viewMode.String(), token, language)
return &appprovider.OpenInAppURL{
AppUrl: url,
Method: "GET",
Expand Down
15 changes: 14 additions & 1 deletion pkg/app/provider/wopi/wopi.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func New(m map[string]interface{}) (app.Provider, error) {
}, nil
}

func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error) {
func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token, language string) (*appprovider.OpenInAppURL, error) {
log := appctx.GetLogger(ctx)

ext := path.Ext(resource.Path)
Expand Down Expand Up @@ -238,6 +238,19 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc

appFullURL := result["app-url"].(string)

if language != "" {
url, err := url.Parse(appFullURL)
if err != nil {
return nil, err
}
urlQuery := url.Query()
urlQuery.Set("ui", language) // OnlyOffice + Office365
urlQuery.Set("lang", language) // Collabora
urlQuery.Set("rs", language) // Office365, https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/online/discovery#dc_llcc
url.RawQuery = urlQuery.Encode()
appFullURL = url.String()
}

// Depending on whether wopi server returned any form parameters or not,
// we decide whether the request method is POST or GET
var formParams map[string]string
Expand Down
2 changes: 2 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ func GetViewMode(viewMode string) gateway.OpenInAppRequest_ViewMode {
return gateway.OpenInAppRequest_VIEW_MODE_READ_ONLY
case "write":
return gateway.OpenInAppRequest_VIEW_MODE_READ_WRITE
case "preview":
return gateway.OpenInAppRequest_VIEW_MODE_PREVIEW
default:
return gateway.OpenInAppRequest_VIEW_MODE_INVALID
}
Expand Down