Repository: pimcore/pimcore (language: php)

Issue:
Only one language mandatory
Hi,

For a client (for several projects even) need to make only one language mandatory on the set of localized fields. Assuming that my content is localized in 3 languages (FR, EN, ES), we would like only one of these 3 languages to be required during registration and publication.

Cheers,


Discussion / hints:
set field as optional and implement **onObjectPreUpdate** event with your own rules
and throw exception if problem
````
throw new ValidationException("Empty title value (sk_SK)");
````
Yes, it's a solution, but an improvement in the configuration of the class would be more flexible for non-developer users
Had this requirement many times. Will be practical says my experience.
Will be great to be able to mark what languages are required on both - field-level and on global level. Field has higher priority than global.
Any news about this feature request?
Thanks a lot for reporting the issue. The issue was not considered by us as "Priority" or "Backlog", so we're not gonna work on that anytime soon. In case this is a bug report, please create a pull request fixing the issue, we'll then review it as soon as possible. If you're interested in contributing a feature, please contact us first here before creating a pull request, we'll then decide whether we'd accept it or not. Thanks for your understanding.


Fix patch:
diff --git a/bundles/CoreBundle/src/DependencyInjection/Configuration.php b/bundles/CoreBundle/src/DependencyInjection/Configuration.php
index c2d632cca74..6f6800bc9d0 100644
--- a/bundles/CoreBundle/src/DependencyInjection/Configuration.php
+++ b/bundles/CoreBundle/src/DependencyInjection/Configuration.php
@@ -223,6 +223,14 @@ private function addGeneralNode(ArrayNodeDefinition $rootNode): void
                     ->defaultValue(['en', 'de', 'fr'])
                     ->prototype('scalar')->end()
                 ->end()
+                ->arrayNode('required_languages')
+                    ->info('String or array format are supported.')
+                    ->beforeNormalization()
+                    ->ifString()
+                        ->then(fn ($v) => explode(',', $v))
+                    ->end()
+                    ->prototype('scalar')->end()
+                ->end()
                 ->arrayNode('fallback_languages')
                     ->performNoDeepMerging()
                     ->beforeNormalization()
diff --git a/doc/05_Objects/01_Object_Classes/01_Data_Types/50_Localized_Fields.md b/doc/05_Objects/01_Object_Classes/01_Data_Types/50_Localized_Fields.md
index ee3dee496e5..d3d3bd335f9 100644
--- a/doc/05_Objects/01_Object_Classes/01_Data_Types/50_Localized_Fields.md
+++ b/doc/05_Objects/01_Object_Classes/01_Data_Types/50_Localized_Fields.md
@@ -33,6 +33,11 @@ You can do this in `Settings` -> `System Settings` -> `Localization & Internatio
 
 ![Add languages](../../../img/Objects_LocalizedFields_add_language.png)
 
+## Definition of required Languages
+If you want to have mandatory fields in the localized fields but they are not mandatory for all languages, you can define
+which languages are required in `Settings` -> `System Settings` -> `Localization & Internationalization` with the `Mandatory language` checkbox on each language.
+
+
 ## Inheritance
 
 Fallback and inherited values are evaluated in a vertical way first. This is contrary to the [Classification Store](15_Classification_Store.md) where the evaluation is done in a horizontal way. If no value for the current language is found, the parent level is checked. 
diff --git a/doc/img/Objects_LocalizedFields_add_language.png b/doc/img/Objects_LocalizedFields_add_language.png
index ff19f1d90a6..293d80e63a3 100644
Binary files a/doc/img/Objects_LocalizedFields_add_language.png and b/doc/img/Objects_LocalizedFields_add_language.png differ
diff --git a/lib/SystemSettingsConfig.php b/lib/SystemSettingsConfig.php
index a3043698c32..466e0abf7d8 100644
--- a/lib/SystemSettingsConfig.php
+++ b/lib/SystemSettingsConfig.php
@@ -146,6 +146,7 @@ private function prepareSystemConfig(array $values): array
         $fallbackLanguages = [];
         $localizedErrorPages = [];
         $languages = explode(',', $values['general.validLanguages']);
+        $requiredLanguages = explode(',', $values['general.requiredLanguages']);
         $filteredLanguages = [];
         $existingValues = self::get();
 
@@ -175,6 +176,7 @@ private function prepareSystemConfig(array $values): array
                 'redirect_to_maindomain' => $values['general.redirect_to_maindomain'],
                 'valid_languages' => $filteredLanguages,
                 'fallback_languages' => $fallbackLanguages,
+                'required_languages' => $requiredLanguages,
                 'default_language' => $values['general.defaultLanguage'],
                 'debug_admin_translations' => $values['general.debug_admin_translations'],
             ],
diff --git a/lib/Tool.php b/lib/Tool.php
index 84b10a7e641..6e012ed889f 100644
--- a/lib/Tool.php
+++ b/lib/Tool.php
@@ -35,6 +35,8 @@ final class Tool
 
     protected static array $validLanguages = [];
 
+    protected static array $requiredLanguages = [];
+
     /**
      * Sets the current request to operate on
      *
@@ -111,6 +113,26 @@ public static function getValidLanguages(): array
         return self::$validLanguages;
     }
 
+    public static function getRequiredLanguages(): array
+    {
+        if (empty(self::$requiredLanguages) === true) {
+            $config = SystemSettingsConfig::get()['general'];
+            if (empty($config['required_languages'])) {
+                return Tool::getValidLanguages();
+            }
+
+            $requiredLanguages = $config['required_languages'];
+
+            if (!is_array($requiredLanguages)) {
+                $requiredLanguages = Tool::getValidLanguages();
+            }
+
+            self::$requiredLanguages = $requiredLanguages;
+        }
+
+        return self::$requiredLanguages;
+    }
+
     /**
      * @return string[]
      *
diff --git a/models/DataObject/ClassDefinition/Data/Localizedfields.php b/models/DataObject/ClassDefinition/Data/Localizedfields.php
index 19860c5130e..fbc26d12e20 100644
--- a/models/DataObject/ClassDefinition/Data/Localizedfields.php
+++ b/models/DataObject/ClassDefinition/Data/Localizedfields.php
@@ -634,7 +634,7 @@ public function getRegion(): string
 
     public function checkValidity(mixed $data, bool $omitMandatoryCheck = false, array $params = []): void
     {
-        $languages = Tool::getValidLanguages();
+        $languages = Tool::getRequiredLanguages();
 
         $dataForValidityCheck = $this->getDataForValidity($data, $languages);
         $validationExceptions = [];


Test patch: