From afae9414c24ea7e2056beb672d3b18e318d60425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Baki=20Burak=20=C3=96=C4=9F=C3=BCn?= Date: Thu, 9 Apr 2026 00:43:19 +0300 Subject: [PATCH] fix: use static language list instead of l10nFactory for translation providers When force_language is set in config.php, l10nFactory->getLanguages() returns only the forced language, causing translation providers to offer an empty or single-language list. AI translation services can translate any language regardless of installed Nextcloud UI languages. Introduce a shared LanguageList helper class with common ISO 639 languages. Both OldTranslationProvider and TranslateProvider now use this static list instead of depending on l10nFactory for determining available translation languages. Fixes #357 --- .../Translation/TranslationProvider.php | 11 +- lib/TaskProcessing/TranslateProvider.php | 11 +- lib/Translation/LanguageList.php | 127 ++++++++++++++++++ 3 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 lib/Translation/LanguageList.php diff --git a/lib/OldProcessing/Translation/TranslationProvider.php b/lib/OldProcessing/Translation/TranslationProvider.php index b3973836..c8766d70 100644 --- a/lib/OldProcessing/Translation/TranslationProvider.php +++ b/lib/OldProcessing/Translation/TranslationProvider.php @@ -13,6 +13,7 @@ use OCA\OpenAi\AppInfo\Application; use OCA\OpenAi\Service\OpenAiAPIService; use OCA\OpenAi\Service\OpenAiSettingsService; +use OCA\OpenAi\Translation\LanguageList; use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\L10N\IFactory; @@ -46,8 +47,7 @@ public function getAvailableLanguages(): array { }, $cached); } - $coreL = $this->l10nFactory->getLanguages(); - $languages = array_merge($coreL['commonLanguages'], $coreL['otherLanguages']); + $languages = LanguageList::getLanguages(); $availableLanguages = []; foreach ($languages as $sourceLanguage) { @@ -90,12 +90,7 @@ public function detectLanguage(string $text): ?string { } private function getCoreLanguagesByCode(): array { - $coreL = $this->l10nFactory->getLanguages(); - $coreLanguages = array_reduce(array_merge($coreL['commonLanguages'], $coreL['otherLanguages']), function ($carry, $val) { - $carry[$val['code']] = $val['name']; - return $carry; - }); - return $coreLanguages; + return LanguageList::getLanguagesByCode(); } public function translate(?string $fromLanguage, string $toLanguage, string $text): string { diff --git a/lib/TaskProcessing/TranslateProvider.php b/lib/TaskProcessing/TranslateProvider.php index 2325d40e..67154af9 100644 --- a/lib/TaskProcessing/TranslateProvider.php +++ b/lib/TaskProcessing/TranslateProvider.php @@ -14,6 +14,7 @@ use OCA\OpenAi\Service\ChunkService; use OCA\OpenAi\Service\OpenAiAPIService; use OCA\OpenAi\Service\OpenAiSettingsService; +use OCA\OpenAi\Translation\LanguageList; use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\IL10N; @@ -82,8 +83,7 @@ public function getExpectedRuntime(): int { } public function getInputShapeEnumValues(): array { - $coreL = $this->l10nFactory->getLanguages(); - $languages = array_merge($coreL['commonLanguages'], $coreL['otherLanguages']); + $languages = LanguageList::getLanguages(); $languageEnumValues = array_map(static function (array $language) { return new ShapeEnumValue($language['name'], $language['code']); }, $languages); @@ -144,12 +144,7 @@ public function getOptionalOutputShapeEnumValues(): array { } private function getCoreLanguagesByCode(): array { - $coreL = $this->l10nFactory->getLanguages(); - $coreLanguages = array_reduce(array_merge($coreL['commonLanguages'], $coreL['otherLanguages']), function ($carry, $val) { - $carry[$val['code']] = $val['name']; - return $carry; - }); - return $coreLanguages; + return LanguageList::getLanguagesByCode(); } public function process(?string $userId, array $input, callable $reportProgress): array { diff --git a/lib/Translation/LanguageList.php b/lib/Translation/LanguageList.php new file mode 100644 index 00000000..0ddc7891 --- /dev/null +++ b/lib/Translation/LanguageList.php @@ -0,0 +1,127 @@ +getLanguages() + * breaks when force_language is set (returns only the forced language). + * + * @see https://github.com/nextcloud/integration_openai/issues/357 + */ +class LanguageList { + + /** + * Returns a comprehensive list of common languages with English display names. + * + * @return array + */ + public static function getLanguages(): array { + return [ + ['code' => 'af', 'name' => 'Afrikaans'], + ['code' => 'sq', 'name' => 'Albanian'], + ['code' => 'am', 'name' => 'Amharic'], + ['code' => 'ar', 'name' => 'Arabic'], + ['code' => 'hy', 'name' => 'Armenian'], + ['code' => 'az', 'name' => 'Azerbaijani'], + ['code' => 'eu', 'name' => 'Basque'], + ['code' => 'be', 'name' => 'Belarusian'], + ['code' => 'bn', 'name' => 'Bengali'], + ['code' => 'bs', 'name' => 'Bosnian'], + ['code' => 'bg', 'name' => 'Bulgarian'], + ['code' => 'my', 'name' => 'Burmese'], + ['code' => 'ca', 'name' => 'Catalan'], + ['code' => 'zh', 'name' => 'Chinese (Simplified)'], + ['code' => 'zh_TW', 'name' => 'Chinese (Traditional)'], + ['code' => 'hr', 'name' => 'Croatian'], + ['code' => 'cs', 'name' => 'Czech'], + ['code' => 'da', 'name' => 'Danish'], + ['code' => 'nl', 'name' => 'Dutch'], + ['code' => 'en', 'name' => 'English'], + ['code' => 'et', 'name' => 'Estonian'], + ['code' => 'fi', 'name' => 'Finnish'], + ['code' => 'fr', 'name' => 'French'], + ['code' => 'gl', 'name' => 'Galician'], + ['code' => 'ka', 'name' => 'Georgian'], + ['code' => 'de', 'name' => 'German'], + ['code' => 'el', 'name' => 'Greek'], + ['code' => 'gu', 'name' => 'Gujarati'], + ['code' => 'ha', 'name' => 'Hausa'], + ['code' => 'he', 'name' => 'Hebrew'], + ['code' => 'hi', 'name' => 'Hindi'], + ['code' => 'hu', 'name' => 'Hungarian'], + ['code' => 'is', 'name' => 'Icelandic'], + ['code' => 'id', 'name' => 'Indonesian'], + ['code' => 'ga', 'name' => 'Irish'], + ['code' => 'it', 'name' => 'Italian'], + ['code' => 'ja', 'name' => 'Japanese'], + ['code' => 'kn', 'name' => 'Kannada'], + ['code' => 'kk', 'name' => 'Kazakh'], + ['code' => 'km', 'name' => 'Khmer'], + ['code' => 'ko', 'name' => 'Korean'], + ['code' => 'ku', 'name' => 'Kurdish'], + ['code' => 'ky', 'name' => 'Kyrgyz'], + ['code' => 'lo', 'name' => 'Lao'], + ['code' => 'lv', 'name' => 'Latvian'], + ['code' => 'lt', 'name' => 'Lithuanian'], + ['code' => 'mk', 'name' => 'Macedonian'], + ['code' => 'ms', 'name' => 'Malay'], + ['code' => 'ml', 'name' => 'Malayalam'], + ['code' => 'mt', 'name' => 'Maltese'], + ['code' => 'mn', 'name' => 'Mongolian'], + ['code' => 'ne', 'name' => 'Nepali'], + ['code' => 'no', 'name' => 'Norwegian'], + ['code' => 'ps', 'name' => 'Pashto'], + ['code' => 'fa', 'name' => 'Persian'], + ['code' => 'pl', 'name' => 'Polish'], + ['code' => 'pt', 'name' => 'Portuguese'], + ['code' => 'pt_BR', 'name' => 'Portuguese (Brazil)'], + ['code' => 'pa', 'name' => 'Punjabi'], + ['code' => 'ro', 'name' => 'Romanian'], + ['code' => 'ru', 'name' => 'Russian'], + ['code' => 'sr', 'name' => 'Serbian'], + ['code' => 'si', 'name' => 'Sinhala'], + ['code' => 'sk', 'name' => 'Slovak'], + ['code' => 'sl', 'name' => 'Slovenian'], + ['code' => 'so', 'name' => 'Somali'], + ['code' => 'es', 'name' => 'Spanish'], + ['code' => 'sw', 'name' => 'Swahili'], + ['code' => 'sv', 'name' => 'Swedish'], + ['code' => 'tl', 'name' => 'Tagalog'], + ['code' => 'ta', 'name' => 'Tamil'], + ['code' => 'te', 'name' => 'Telugu'], + ['code' => 'th', 'name' => 'Thai'], + ['code' => 'tr', 'name' => 'Turkish'], + ['code' => 'tk', 'name' => 'Turkmen'], + ['code' => 'uk', 'name' => 'Ukrainian'], + ['code' => 'ur', 'name' => 'Urdu'], + ['code' => 'uz', 'name' => 'Uzbek'], + ['code' => 'vi', 'name' => 'Vietnamese'], + ['code' => 'cy', 'name' => 'Welsh'], + ['code' => 'yo', 'name' => 'Yoruba'], + ['code' => 'zu', 'name' => 'Zulu'], + ]; + } + + /** + * Returns a code => name map of all supported languages. + * + * @return array + */ + public static function getLanguagesByCode(): array { + $map = []; + foreach (self::getLanguages() as $lang) { + $map[$lang['code']] = $lang['name']; + } + return $map; + } +}