From 4e049bccb63e26b072f710921211904b56e0b3d9 Mon Sep 17 00:00:00 2001 From: Elizabeth Danzberger Date: Fri, 4 Sep 2026 18:27:28 -0400 Subject: [PATCH] refactor(l10n): move language tag logic to backend Moving the Nextcloud language + locale to BCP 47 language tag logic to the backend makes sense because it exists in two places when it should really exist in one. This keeps it maintainable. The backend is the natural place because requests to Collabora happen there, and the logic can be injected into the frontend via initial state. Assisted-by: ClaudeCode:claude-sonnet-5 Signed-off-by: Elizabeth Danzberger --- lib/Conversion/ConversionProvider.php | 11 +--- lib/Service/InitialStateService.php | 2 + lib/Service/LanguageService.php | 58 ++++++++++++++++++ src/components/CoolFrame.vue | 4 +- src/helpers/index.js | 47 -------------- src/helpers/url.js | 3 +- src/services/config.tsx | 1 + .../lib/Conversion/ConversionProviderTest.php | 12 ++-- tests/lib/Service/LanguageServiceTest.php | 61 +++++++++++++++++++ 9 files changed, 136 insertions(+), 63 deletions(-) create mode 100644 lib/Service/LanguageService.php create mode 100644 tests/lib/Service/LanguageServiceTest.php diff --git a/lib/Conversion/ConversionProvider.php b/lib/Conversion/ConversionProvider.php index 75c38bb423..195e2ff38b 100644 --- a/lib/Conversion/ConversionProvider.php +++ b/lib/Conversion/ConversionProvider.php @@ -9,6 +9,7 @@ namespace OCA\Richdocuments\Conversion; +use OCA\Richdocuments\Service\LanguageService; use OCA\Richdocuments\Service\RemoteService; use OCA\Richdocuments\Service\SecureViewService; use OCP\Files\Conversion\ConversionMimeProvider; @@ -56,6 +57,7 @@ public function __construct( private LoggerInterface $logger, IFactory $l10nFactory, private SecureViewService $secureViewService, + private LanguageService $languageService, ) { $this->l10n = $l10nFactory->get('richdocuments'); } @@ -168,17 +170,10 @@ public function convertFile(File $file, string $targetMimeType): mixed { return $this->remoteService->convertFileTo( $file, $targetFileExtension, - conversionOptions: ['lang' => $this->getConversionLanguage()] + conversionOptions: ['lang' => $this->languageService->getBCP47LanguageTag()] ); } - private function getConversionLanguage(): string { - $locale = $this->l10n->getLocaleCode(); - $language = $locale !== '' ? $locale : $this->l10n->getLanguageCode(); - - return str_replace('_', '-', $language); - } - private function getMimeProvidersFor(array $inputMimeTypes, string $outputMimeType): array { $outputMimeInfo = $this->getMimeInfoFor($outputMimeType); if ($outputMimeInfo === null) { diff --git a/lib/Service/InitialStateService.php b/lib/Service/InitialStateService.php index 7eef2b47ae..00826ff041 100644 --- a/lib/Service/InitialStateService.php +++ b/lib/Service/InitialStateService.php @@ -28,6 +28,7 @@ public function __construct( private TemplateManager $templateManager, private CapabilitiesService $capabilitiesService, private IConfig $config, + private LanguageService $languageService, private ?string $userId, ) { } @@ -42,6 +43,7 @@ public function provideCapabilities(): void { $this->initialState->provideInitialState('hasNextcloudBranding', $this->capabilitiesService->hasNextcloudBranding()); $this->initialState->provideInitialState('instanceId', $this->config->getSystemValue('instanceid')); $this->initialState->provideInitialState('wopi_callback_url', $this->appConfig->getNextcloudUrl()); + $this->initialState->provideInitialState('bcp47Language', $this->languageService->getBCP47LanguageTag()); $this->provideOptions(); $this->hasProvidedCapabilities = true; diff --git a/lib/Service/LanguageService.php b/lib/Service/LanguageService.php new file mode 100644 index 0000000000..8b00aaad04 --- /dev/null +++ b/lib/Service/LanguageService.php @@ -0,0 +1,58 @@ + [ + 'de_CH' => 'de-CH', + 'gsw' => 'de-CH', + 'gsw_CH' => 'de-CH', + ], + 'fr' => [ + 'fr_CH' => 'fr-CH', + ], + 'it' => [ + 'it_CH' => 'it-CH', + ], + ]; + + public function __construct( + private IFactory $l10nFactory, + ) { + } + + /** + * Converts the current user's Nextcloud language/locale settings into the + * BCP 47 language tag Collabora Online expects. + */ + public function getBCP47LanguageTag(): string { + $l10n = $this->l10nFactory->get(Application::APPNAME); + + // getLanguageCode()/getLocaleCode() mirror @nextcloud/l10n's getLanguage()/getLocale() + $language = str_replace('_', '-', $l10n->getLanguageCode()); + $locale = $l10n->getLocaleCode(); + + $language = match ($language) { + 'de-DE' => 'de', // German formal should just be treated as 'de' + 'es-419' => 'es-MX', // not a valid locale string in COOL + default => $language, + }; + + if ($language === 'en-GB' && $locale === 'en_AU') { + $language = 'en-AU'; + } + + return self::LOCALE_OVERRIDES[$language][$locale] ?? $language; + } +} diff --git a/src/components/CoolFrame.vue b/src/components/CoolFrame.vue index 579a153030..81b0f49c23 100644 --- a/src/components/CoolFrame.vue +++ b/src/components/CoolFrame.vue @@ -28,7 +28,7 @@