Skip to content

Commit 85d419e

Browse files
committed
Backport from edge: added support for language locales in apps
1 parent 9b39f5f commit 85d419e

File tree

6 files changed

+99
-5
lines changed

6 files changed

+99
-5
lines changed
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Enhancement: added support for language locales in apps
2+
3+
This is a backport of code in the edge branch
4+
5+
https://github.com/cs3org/reva/pull/3303
6+

internal/grpc/services/appprovider/appprovider.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/cs3org/reva/pkg/rgrpc/status"
3838
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
3939
"github.com/cs3org/reva/pkg/sharedconf"
40+
"github.com/cs3org/reva/pkg/utils"
4041
"github.com/juliangruber/go-intersect"
4142
"github.com/mitchellh/mapstructure"
4243
"google.golang.org/grpc"
@@ -170,7 +171,7 @@ func getProvider(c *config) (app.Provider, error) {
170171
}
171172

172173
func (s *service) OpenInApp(ctx context.Context, req *providerpb.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) {
173-
appURL, err := s.provider.GetAppURL(ctx, req.ResourceInfo, req.ViewMode, req.AccessToken)
174+
appURL, err := s.provider.GetAppURL(ctx, req.ResourceInfo, req.ViewMode, req.AccessToken, utils.ReadPlainFromOpaque(req.Opaque, "lang"))
174175
if err != nil {
175176
res := &providerpb.OpenInAppResponse{
176177
Status: status.NewInternal(ctx, errors.New("appprovider: error calling GetAppURL"), err.Error()),

pkg/app/app.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ type Registry interface {
4040
// Provider is the interface that application providers implement
4141
// for interacting with external apps that serve the requested resource.
4242
type Provider interface {
43-
GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error)
43+
GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token, language string) (*appprovider.OpenInAppURL, error)
4444
GetAppProviderInfo(ctx context.Context) (*registry.ProviderInfo, error)
4545
}

pkg/app/provider/demo/demo.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ type demoProvider struct {
3838
iframeUIProvider string
3939
}
4040

41-
func (p *demoProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error) {
42-
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)
41+
func (p *demoProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token, language string) (*appprovider.OpenInAppURL, error) {
42+
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)
4343
return &appprovider.OpenInAppURL{
4444
AppUrl: url,
4545
Method: "GET",

pkg/app/provider/wopi/wopi.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func New(m map[string]interface{}) (app.Provider, error) {
125125
}, nil
126126
}
127127

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

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

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

241+
if language != "" {
242+
url, err := url.Parse(appFullURL)
243+
if err != nil {
244+
return nil, err
245+
}
246+
urlQuery := url.Query()
247+
urlQuery.Set("ui", language) // OnlyOffice
248+
urlQuery.Set("lang", language) // Collabora
249+
urlQuery.Set("UI_LLCC", language) // Office365
250+
url.RawQuery = urlQuery.Encode()
251+
appFullURL = url.String()
252+
}
253+
241254
// Depending on whether wopi server returned any form parameters or not,
242255
// we decide whether the request method is POST or GET
243256
var formParams map[string]string

pkg/utils/utils.go

+74
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"net"
2525
"net/http"
2626
"net/url"
27+
"os"
2728
"os/user"
2829
"path"
2930
"path/filepath"
@@ -348,7 +349,80 @@ func GetViewMode(viewMode string) gateway.OpenInAppRequest_ViewMode {
348349
return gateway.OpenInAppRequest_VIEW_MODE_READ_ONLY
349350
case "write":
350351
return gateway.OpenInAppRequest_VIEW_MODE_READ_WRITE
352+
case "preview":
353+
return gateway.OpenInAppRequest_VIEW_MODE_PREVIEW
351354
default:
352355
return gateway.OpenInAppRequest_VIEW_MODE_INVALID
353356
}
354357
}
358+
359+
// AppendPlainToOpaque adds a new key value pair as a plain string on the given opaque and returns it
360+
func AppendPlainToOpaque(o *types.Opaque, key, value string) *types.Opaque {
361+
o = ensureOpaque(o)
362+
363+
o.Map[key] = &types.OpaqueEntry{
364+
Decoder: "plain",
365+
Value: []byte(value),
366+
}
367+
return o
368+
}
369+
370+
// ReadPlainFromOpaque reads a plain string from the given opaque map
371+
func ReadPlainFromOpaque(o *types.Opaque, key string) string {
372+
if o.GetMap() == nil {
373+
return ""
374+
}
375+
if e, ok := o.Map[key]; ok && e.Decoder == "plain" {
376+
return string(e.Value)
377+
}
378+
return ""
379+
}
380+
381+
// ExistsInOpaque returns true if the key exists in the opaque (ignoring the value)
382+
func ExistsInOpaque(o *types.Opaque, key string) bool {
383+
if o.GetMap() == nil {
384+
return false
385+
}
386+
387+
_, ok := o.Map[key]
388+
return ok
389+
}
390+
391+
// MergeOpaques will merge the opaques. If a key exists in both opaques
392+
// the values from the first opaque will be taken
393+
func MergeOpaques(o *types.Opaque, p *types.Opaque) *types.Opaque {
394+
p = ensureOpaque(p)
395+
for k, v := range o.GetMap() {
396+
p.Map[k] = v
397+
}
398+
return p
399+
}
400+
401+
// ensures the opaque is initialized
402+
func ensureOpaque(o *types.Opaque) *types.Opaque {
403+
if o == nil {
404+
o = &types.Opaque{}
405+
}
406+
if o.Map == nil {
407+
o.Map = map[string]*types.OpaqueEntry{}
408+
}
409+
return o
410+
}
411+
412+
// RemoveItem removes the given item, its children and all empty parent folders
413+
func RemoveItem(path string) error {
414+
if err := os.RemoveAll(path); err != nil {
415+
return err
416+
}
417+
418+
for {
419+
path = filepath.Dir(path)
420+
if err := os.Remove(path); err != nil {
421+
// remove will fail when the dir is not empty.
422+
// We can exit in that case
423+
return nil
424+
}
425+
426+
}
427+
428+
}

0 commit comments

Comments
 (0)