From 95dad675cac1f1e58957804dccc8494b7166a0a0 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 14:01:39 +0200 Subject: [PATCH 01/11] Init --- packages/web-pkg/src/configuration/manager.ts | 10 +++++++ packages/web-pkg/src/configuration/types.ts | 4 +++ packages/web-runtime/src/index.ts | 27 ++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/web-pkg/src/configuration/manager.ts b/packages/web-pkg/src/configuration/manager.ts index c02b73cc628..89575a297f8 100644 --- a/packages/web-pkg/src/configuration/manager.ts +++ b/packages/web-pkg/src/configuration/manager.ts @@ -1,4 +1,5 @@ import { + CustomTranslation, OAuth2Configuration, OIDCConfiguration, OptionsConfiguration, @@ -14,6 +15,7 @@ export interface RawConfig { auth?: any openIdConnect?: any options?: OptionsConfiguration + customTranslations?: Array } export class ConfigurationManager { @@ -35,6 +37,7 @@ export class ConfigurationManager { ? (rawConfig.openIdConnect as OIDCConfiguration) : null this.logoutUrl = rawConfig.options?.logoutUrl + this.customTranslations = rawConfig.customTranslations } set logoutUrl(url: string) { @@ -56,6 +59,13 @@ export class ConfigurationManager { return this.runtimeConfiguration.serverUrl } + set customTranslations(customTranslations: Array) { + this.runtimeConfiguration.customTranslations = customTranslations || [] + } + get customTranslations(): Array { + return this.runtimeConfiguration.customTranslations + } + get isOAuth2(): boolean { return !isNil(this.oAuth2Configuration) } diff --git a/packages/web-pkg/src/configuration/types.ts b/packages/web-pkg/src/configuration/types.ts index 41c202704d1..51973be0f1d 100644 --- a/packages/web-pkg/src/configuration/types.ts +++ b/packages/web-pkg/src/configuration/types.ts @@ -1,5 +1,9 @@ +export interface CustomTranslation { + url: string +} export interface RuntimeConfiguration { serverUrl: string + customTranslations?: Array } export interface RoutingOptionsConfiguration { diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 223cd05e600..81d324abdfe 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -4,6 +4,8 @@ import { configurationManager } from 'web-pkg/src/configuration' import { createHead } from '@vueuse/head' import { abilitiesPlugin } from '@casl/vue' import { createMongoAbility } from '@casl/ability' +import merge from 'lodash-es/merge' +import { v4 as uuidV4 } from 'uuid' import { announceConfiguration, @@ -39,6 +41,7 @@ import PortalVue, { createWormhole } from 'portal-vue' import Avatar from './components/Avatar.vue' import focusMixin from './mixins/focusMixin' +import fs from 'fs' export const bootstrapApp = async (configurationPath: string): Promise => { const app = createApp(pages.success) @@ -60,8 +63,30 @@ export const bootstrapApp = async (configurationPath: string): Promise => }) const themePromise = announceTheme({ store, app, designSystem, runtimeConfiguration }) await Promise.all([applicationsPromise, themePromise]) + const customTranslations = {} + + for (const customTranslation of configurationManager.customTranslations) { + const customTranslationResponse = await fetch(customTranslation.url, { + headers: { 'X-Request-ID': uuidV4() } + }) + if (customTranslationResponse.status !== 200) { + throw new Error( + `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` + ) + } + try { + const customTranslationJSON = await customTranslationResponse.json() + merge(customTranslations, customTranslationJSON) + } catch (e) { + throw new Error(`translation file ${customTranslation} could not be parsed. ${e}`) + } + } - announceTranslations({ app, availableLanguages: supportedLanguages, translations }) + announceTranslations({ + app, + availableLanguages: supportedLanguages, + translations: merge(translations, customTranslations) + }) announceClientService({ app, runtimeConfiguration, configurationManager, store }) announceUppyService({ app }) announceLoadingService({ app }) From 97b88dcfd72c8b6ffbb121780d334d951174c5ee Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 14:11:15 +0200 Subject: [PATCH 02/11] rm unused import --- packages/web-runtime/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 81d324abdfe..944b21a4839 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -41,7 +41,6 @@ import PortalVue, { createWormhole } from 'portal-vue' import Avatar from './components/Avatar.vue' import focusMixin from './mixins/focusMixin' -import fs from 'fs' export const bootstrapApp = async (configurationPath: string): Promise => { const app = createApp(pages.success) From 249304417f51f5a3197f354f49b4b41a95ec1b68 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 15:41:34 +0200 Subject: [PATCH 03/11] don't throw --- packages/web-runtime/src/index.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 944b21a4839..e1f49c6d32c 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -65,19 +65,20 @@ export const bootstrapApp = async (configurationPath: string): Promise => const customTranslations = {} for (const customTranslation of configurationManager.customTranslations) { - const customTranslationResponse = await fetch(customTranslation.url, { - headers: { 'X-Request-ID': uuidV4() } - }) - if (customTranslationResponse.status !== 200) { - throw new Error( - `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` - ) - } try { + const customTranslationResponse = await fetch(customTranslation.url, { + headers: { 'X-Request-ID': uuidV4() } + }) + if (customTranslationResponse.status !== 200) { + console.error( + `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` + ) + break + } const customTranslationJSON = await customTranslationResponse.json() merge(customTranslations, customTranslationJSON) } catch (e) { - throw new Error(`translation file ${customTranslation} could not be parsed. ${e}`) + console.error(`translation file ${customTranslation} could not be parsed. ${e}`) } } From bd195f6519c25f0631e7afde3c11ce72fb3a52ce Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 15:52:06 +0200 Subject: [PATCH 04/11] add changelog item --- changelog/unreleased/enhancement-custom-translations | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog/unreleased/enhancement-custom-translations diff --git a/changelog/unreleased/enhancement-custom-translations b/changelog/unreleased/enhancement-custom-translations new file mode 100644 index 00000000000..9a8b0afec84 --- /dev/null +++ b/changelog/unreleased/enhancement-custom-translations @@ -0,0 +1,7 @@ +Enhancement: Custom translations + +We have added the possibility to include own translations. +To inject custom translations add the following property to your `config.json`, `"customTranslation": [{ "url": "https://localhost:9200/translations.json" }]`. + +https://github.com/owncloud/web/pull/8790 +https://github.com/owncloud/web/issues/8791 From 255d92e94483563c9c6ae4850ed00e672b200686 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 15:52:56 +0200 Subject: [PATCH 05/11] add changelog item --- changelog/unreleased/enhancement-custom-translations | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/unreleased/enhancement-custom-translations b/changelog/unreleased/enhancement-custom-translations index 9a8b0afec84..2d50a626269 100644 --- a/changelog/unreleased/enhancement-custom-translations +++ b/changelog/unreleased/enhancement-custom-translations @@ -1,6 +1,6 @@ Enhancement: Custom translations -We have added the possibility to include own translations. +We have added the possibility to include own translations to override existing translations. To inject custom translations add the following property to your `config.json`, `"customTranslation": [{ "url": "https://localhost:9200/translations.json" }]`. https://github.com/owncloud/web/pull/8790 From 2fb5a94b6f92e25602d4b57ba258613d4cf7cf07 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 15:55:08 +0200 Subject: [PATCH 06/11] Continue --- packages/web-runtime/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index e1f49c6d32c..2ee35049cc6 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -73,7 +73,7 @@ export const bootstrapApp = async (configurationPath: string): Promise => console.error( `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` ) - break + continue } const customTranslationJSON = await customTranslationResponse.json() merge(customTranslations, customTranslationJSON) From 6347365c76fdfeeba9706ee3fc1a0decc46bcf23 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 16:06:47 +0200 Subject: [PATCH 07/11] Docs --- docs/getting-started.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/getting-started.md b/docs/getting-started.md index 51a06d7a3e3..badf3a54641 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -40,6 +40,8 @@ Please refer to the [build documentation for Web]({{< ref "./building.md" >}}). Depending on the backend you are using, there are sample config files provided in the [config folder](https://github.com/owncloud/web/tree/master/config) of the ownCloud Web git repository. See below for available backends. Also, find some of the configuration details below. +- `customTranslations` You can specify one or multiple files to overwrite existing translations. For example set this option to `[{url: "https://localhost:9200/customTranslations.json"}]`. + #### Options - `options.homeFolder` You can specify a folder that is used when the user navigates `home`. Navigating home gets triggered by clicking on the `All files` menu item. The user will not be jailed in that directory. It simply serves as a default location. You can either provide a static location, or you can use From 91ca4f7bdd019e1c2df9031912f05bca4f15b821 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 11 Apr 2023 16:08:33 +0200 Subject: [PATCH 08/11] enhancements --- packages/web-runtime/src/index.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 2ee35049cc6..0022569d417 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -65,16 +65,16 @@ export const bootstrapApp = async (configurationPath: string): Promise => const customTranslations = {} for (const customTranslation of configurationManager.customTranslations) { + const customTranslationResponse = await fetch(customTranslation.url, { + headers: { 'X-Request-ID': uuidV4() } + }) + if (customTranslationResponse.status !== 200) { + console.error( + `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` + ) + continue + } try { - const customTranslationResponse = await fetch(customTranslation.url, { - headers: { 'X-Request-ID': uuidV4() } - }) - if (customTranslationResponse.status !== 200) { - console.error( - `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` - ) - continue - } const customTranslationJSON = await customTranslationResponse.json() merge(customTranslations, customTranslationJSON) } catch (e) { From 4ad399158390b1a7f2df1bb7e2d95beb13bf1d3a Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 12 Apr 2023 04:46:29 +0200 Subject: [PATCH 09/11] Add new helper --- .../src/helpers/customTranslations.ts | 29 +++++++++++++++++++ packages/web-runtime/src/index.ts | 21 ++------------ 2 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 packages/web-runtime/src/helpers/customTranslations.ts diff --git a/packages/web-runtime/src/helpers/customTranslations.ts b/packages/web-runtime/src/helpers/customTranslations.ts new file mode 100644 index 00000000000..20badfba0ca --- /dev/null +++ b/packages/web-runtime/src/helpers/customTranslations.ts @@ -0,0 +1,29 @@ +import { ConfigurationManager } from 'web-pkg' +import { v4 as uuidV4 } from 'uuid' +import merge from 'lodash-es/merge' + +export const loadCustomTranslations = async ({ + configurationManager +}: { + configurationManager: ConfigurationManager +}): Promise => { + const customTranslations = {} + for (const customTranslation of configurationManager.customTranslations) { + const customTranslationResponse = await fetch(customTranslation.url, { + headers: { 'X-Request-ID': uuidV4() } + }) + if (customTranslationResponse.status !== 200) { + console.error( + `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` + ) + continue + } + try { + const customTranslationJSON = await customTranslationResponse.json() + merge(customTranslations, customTranslationJSON) + } catch (e) { + console.error(`translation file ${customTranslation} could not be parsed. ${e}`) + } + } + return customTranslations +} diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 0022569d417..89aeafd5479 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -34,6 +34,7 @@ import { isPublicSpaceResource, Resource } from 'web-client/src/helpers' +import { loadCustomTranslations } from 'web-runtime/src/helpers/customTranslations' import { WebDAV } from 'web-client/src/webdav' import { DavProperty } from 'web-client/src/webdav/constants' import { createApp } from 'vue' @@ -60,27 +61,9 @@ export const bootstrapApp = async (configurationPath: string): Promise => router, translations }) + const customTranslations = await loadCustomTranslations({ configurationManager }) const themePromise = announceTheme({ store, app, designSystem, runtimeConfiguration }) await Promise.all([applicationsPromise, themePromise]) - const customTranslations = {} - - for (const customTranslation of configurationManager.customTranslations) { - const customTranslationResponse = await fetch(customTranslation.url, { - headers: { 'X-Request-ID': uuidV4() } - }) - if (customTranslationResponse.status !== 200) { - console.error( - `translation file ${customTranslation} could not be loaded. HTTP status-code ${customTranslationResponse.status}` - ) - continue - } - try { - const customTranslationJSON = await customTranslationResponse.json() - merge(customTranslations, customTranslationJSON) - } catch (e) { - console.error(`translation file ${customTranslation} could not be parsed. ${e}`) - } - } announceTranslations({ app, From 0f794ea40eb151dafa2320cf229f073a55a38cbd Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 12 Apr 2023 04:48:15 +0200 Subject: [PATCH 10/11] Re-order --- packages/web-runtime/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 89aeafd5479..01db5cf512d 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -61,9 +61,9 @@ export const bootstrapApp = async (configurationPath: string): Promise => router, translations }) - const customTranslations = await loadCustomTranslations({ configurationManager }) const themePromise = announceTheme({ store, app, designSystem, runtimeConfiguration }) await Promise.all([applicationsPromise, themePromise]) + const customTranslations = await loadCustomTranslations({ configurationManager }) announceTranslations({ app, From f796f20b0c8a5ac6371c83df3c184d0f2f650986 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 12 Apr 2023 16:32:42 +0200 Subject: [PATCH 11/11] Enhacement --- packages/web-runtime/src/index.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 01db5cf512d..324d9b5d089 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -5,7 +5,6 @@ import { createHead } from '@vueuse/head' import { abilitiesPlugin } from '@casl/vue' import { createMongoAbility } from '@casl/ability' import merge from 'lodash-es/merge' -import { v4 as uuidV4 } from 'uuid' import { announceConfiguration, @@ -52,7 +51,7 @@ export const bootstrapApp = async (configurationPath: string): Promise => const store = await announceStore({ runtimeConfiguration }) app.use(abilitiesPlugin, createMongoAbility([]), { useGlobalProperties: true }) - const applicationsPromise = await initializeApplications({ + const applicationsPromise = initializeApplications({ app, runtimeConfiguration, configurationManager, @@ -61,9 +60,13 @@ export const bootstrapApp = async (configurationPath: string): Promise => router, translations }) + const customTranslationsPromise = loadCustomTranslations({ configurationManager }) const themePromise = announceTheme({ store, app, designSystem, runtimeConfiguration }) - await Promise.all([applicationsPromise, themePromise]) - const customTranslations = await loadCustomTranslations({ configurationManager }) + const [customTranslations] = await Promise.all([ + customTranslationsPromise, + applicationsPromise, + themePromise + ]) announceTranslations({ app,