diff --git a/api/v1/submissions/PKPSubmissionFileHandler.php b/api/v1/submissions/PKPSubmissionFileHandler.php index cbc15d48a04..ac46aa801b0 100644 --- a/api/v1/submissions/PKPSubmissionFileHandler.php +++ b/api/v1/submissions/PKPSubmissionFileHandler.php @@ -294,12 +294,12 @@ public function add($slimRequest, $response, $args) $params['submissionId'] = $submission->getId(); $params['uploaderUserId'] = (int) $request->getUser()->getId(); - $primaryLocale = $request->getContext()->getPrimaryLocale(); - $allowedLocales = $request->getContext()->getData('supportedSubmissionLocales'); + $submissionLocale = $submission->getData('locale'); + $allowedLocales = $request->getContext()->getSupportedSubmissionMetadataLocales(); // Set the name if not passed with the request if (empty($params['name'])) { - $params['name'][$primaryLocale] = $_FILES['file']['name']; + $params['name'][$submissionLocale] = $_FILES['file']['name']; } // If no genre has been set and there is only one genre possible, set it automatically @@ -318,7 +318,7 @@ public function add($slimRequest, $response, $args) null, $params, $allowedLocales, - $primaryLocale + $submissionLocale ); if (!empty($errors)) { @@ -402,15 +402,15 @@ public function edit($slimRequest, $response, $args) return $response->withStatus(400)->withJsonError('api.submissionsFiles.400.noParams'); } - $primaryLocale = $request->getContext()->getPrimaryLocale(); - $allowedLocales = $request->getContext()->getData('supportedSubmissionLocales'); + $submissionLocale = $submission->getData('locale'); + $allowedLocales = $request->getContext()->getSupportedSubmissionMetadataLocales(); $errors = Repo::submissionFile() ->validate( $submissionFile, $params, $allowedLocales, - $primaryLocale + $submissionLocale ); if (!empty($errors)) { @@ -438,7 +438,7 @@ public function edit($slimRequest, $response, $args) $params['fileId'] = $fileId; $params['uploaderUserId'] = $request->getUser()->getId(); if (empty($params['name'])) { - $params['name'][$primaryLocale] = $_FILES['file']['name']; + $params['name'][$submissionLocale] = $_FILES['file']['name']; } } diff --git a/api/v1/vocabs/PKPVocabHandler.php b/api/v1/vocabs/PKPVocabHandler.php index 9f3428817be..0ac56432f89 100644 --- a/api/v1/vocabs/PKPVocabHandler.php +++ b/api/v1/vocabs/PKPVocabHandler.php @@ -22,6 +22,7 @@ use PKP\core\PKPString; use PKP\db\DAORegistry; use PKP\facades\Locale; +use APP\facades\Repo; use PKP\handler\APIHandler; use PKP\plugins\Hook; use PKP\security\authorization\ContextAccessPolicy; @@ -84,8 +85,9 @@ public function getMany(Request $slimRequest, APIResponse $response, array $args $vocab = $requestParams['vocab'] ?? ''; $locale = $requestParams['locale'] ?? Locale::getLocale(); $term = $requestParams['term'] ?? null; + $isSubmissionPrimaryLocale = isset($requestParams['submissionId']) && $locale === (Repo::submission()->get((int) $requestParams['submissionId']))?->getData('locale'); - if (!in_array($locale, $context->getData('supportedSubmissionLocales'))) { + if (!in_array($locale, $context->getData('supportedSubmissionMetadataLocales')) && !$isSubmissionPrimaryLocale) { return $response->withStatus(400)->withJsonError('api.vocabs.400.localeNotSupported', ['locale' => $locale]); } diff --git a/classes/author/Repository.php b/classes/author/Repository.php index 094d802a5ec..26207314652 100644 --- a/classes/author/Repository.php +++ b/classes/author/Repository.php @@ -97,8 +97,9 @@ public function getSchemaMap(): maps\Schema public function validate($author, $props, Submission $submission, Context $context) { $schemaService = Services::get('schema'); - $allowedLocales = $context->getSupportedSubmissionLocales(); $primaryLocale = $submission->getData('locale'); + $allowedLocales = $context->getSupportedSubmissionMetadataLocales(); + in_array($primaryLocale, $allowedLocales) || array_push($allowedLocales, $primaryLocale); $validator = ValidatorFactory::make( $props, diff --git a/classes/author/maps/Schema.php b/classes/author/maps/Schema.php index c670ce0112d..3cdb2d7fd7e 100644 --- a/classes/author/maps/Schema.php +++ b/classes/author/maps/Schema.php @@ -106,7 +106,7 @@ protected function mapByProperties(array $props, Author $item): array } } - $output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->context->getSupportedSubmissionLocales()); + $output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->context->getSupportedSubmissionMetadataLocales()); ksort($output); diff --git a/classes/components/listPanels/ContributorsListPanel.php b/classes/components/listPanels/ContributorsListPanel.php index ecea43b9c2a..f1e0e6a3455 100644 --- a/classes/components/listPanels/ContributorsListPanel.php +++ b/classes/components/listPanels/ContributorsListPanel.php @@ -107,7 +107,7 @@ protected function getPublicationUrlFormat(): string */ protected function getLocalizedForm(): array { - uksort($this->locales, fn ($a, $b) => $a === $this->submission->getData('locale') ? -1 : 1); + usort($this->locales, fn ($a, $b) => $a['key'] === $this->submission->getData('locale') ? -1 : 1); $apiUrl = Application::get()->getRequest()->getDispatcher()->url( Application::get()->getRequest(), diff --git a/classes/context/Context.php b/classes/context/Context.php index 9049d18fe39..826e5a28aa9 100644 --- a/classes/context/Context.php +++ b/classes/context/Context.php @@ -393,6 +393,63 @@ public function getSupportedLocaleNames(int $langLocaleStatus = LocaleMetadata:: return $this->getData('supportedLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedLocales(), null, $langLocaleStatus); } + /** + * Get the supported added submission locales. + * + * @return array + */ + public function getSupportedAddedSubmissionLocales() + { + return $this->getData('supportedAddedSubmissionLocales'); + } + + /** + * Return associative array of added locales supported by submissions on the + * context. + * + * @param int $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_* + * + * @return array + */ + public function getSupportedAddedSubmissionLocaleNames(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT) + { + return $this->getData('supportedAddedSubmissionLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedAddedSubmissionLocales(), null, $langLocaleStatus); + } + + /** + * Get the supported default submission locale. + */ + public function getSupportedDefaultSubmissionLocale(): ?string + { + return $this->getData('supportedDefaultSubmissionLocale'); + } + + /** + * Return string default submission locale supported by the site. + * $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_* + */ + public function getSupportedDefaultSubmissionLocaleName(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT): string + { + return Locale::getFormattedDisplayNames($this->getSupportedDefaultSubmissionLocale(), null, $langLocaleStatus); + } + + /** + * Get the supported metadata locales. + */ + public function getSupportedSubmissionMetadataLocales(): ?array + { + return $this->getData('supportedSubmissionMetadataLocales'); + } + + /** + * Return associative array of all locales supported by submission metadata forms on the site. + * $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_* + */ + public function getSupportedSubmissionMetadataLocaleNames(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT): array + { + return Locale::getFormattedDisplayNames($this->getSupportedSubmissionMetadataLocales(), null, $langLocaleStatus); + } + /** * Return date or/and time formats available for forms, fallback to the default if not set * diff --git a/classes/galley/maps/Schema.php b/classes/galley/maps/Schema.php index c28ff66867b..c9386eb27ab 100644 --- a/classes/galley/maps/Schema.php +++ b/classes/galley/maps/Schema.php @@ -140,7 +140,10 @@ protected function mapByProperties(array $props, Galley $galley): array } } - $output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->context->getSupportedFormLocales()); + $locales = $this->context->getSupportedSubmissionMetaDataLocales(); + in_array($primaryLocale = $this->submission->getData('locale'), $locales) || array_push($locales, $primaryLocale); + + $output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $locales); ksort($output); diff --git a/classes/publication/Repository.php b/classes/publication/Repository.php index 0815cfe0c5a..b8ba2e38252 100644 --- a/classes/publication/Repository.php +++ b/classes/publication/Repository.php @@ -131,8 +131,9 @@ public function getDateBoundaries(Collector $query): object */ public function validate(?Publication $publication, array $props, Submission $submission, Context $context): array { - $allowedLocales = $context->getSupportedSubmissionLocales(); - $primaryLocale = $submission->getLocale(); + $primaryLocale = $submission->getData('locale'); + $allowedLocales = $context->getSupportedSubmissionMetadataLocales(); + in_array($primaryLocale, $allowedLocales) || array_push($allowedLocales, $primaryLocale); $errors = []; @@ -243,7 +244,7 @@ public function validate(?Publication $publication, array $props, Submission $su * wants to enforce particular publishing requirements, such as * requiring certain metadata or other information. * - * @param array $allowedLocales The context's supported submission locales + * @param array $allowedLocales The context's supported submission metadata locales * @param string $primaryLocale The submission's primary locale */ public function validatePublish(Publication $publication, Submission $submission, array $allowedLocales, string $primaryLocale): array @@ -282,7 +283,8 @@ public function add(Publication $publication): int $submissionContext = Services::get('context')->get($submission->getData('contextId')); } - $supportedLocales = $submissionContext->getSupportedSubmissionLocales(); + $supportedLocales = $submissionContext->getSupportedSubmissionMetadataLocales(); + in_array($primaryLocale = $submission->getData('locale'), $supportedLocales) || array_push($supportedLocales, $primaryLocale); foreach ($supportedLocales as $localeKey) { if (!array_key_exists($localeKey, $publication->getData('coverImage'))) { continue; @@ -377,7 +379,8 @@ public function edit(Publication $publication, array $params): Publication $submissionContext = Services::get('context')->get($submission->getData('contextId')); } - $supportedLocales = $submissionContext->getSupportedSubmissionLocales(); + $supportedLocales = $submissionContext->getSupportedSubmissionMetadataLocales(); + in_array($primaryLocale = $submission->getData('locale'), $supportedLocales) || array_push($supportedLocales, $primaryLocale); foreach ($supportedLocales as $localeKey) { if (!array_key_exists($localeKey, $params['coverImage'])) { continue; diff --git a/classes/services/PKPContextService.php b/classes/services/PKPContextService.php index 4a38335c98c..cb30b7b65b8 100644 --- a/classes/services/PKPContextService.php +++ b/classes/services/PKPContextService.php @@ -272,9 +272,11 @@ public function validate($action, $props, $allowedLocales, $primaryLocale) [ 'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'), 'primaryLocale.regex' => __('validator.localeKey'), + 'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'), 'supportedFormLocales.regex' => __('validator.localeKey'), 'supportedLocales.regex' => __('validator.localeKey'), 'supportedSubmissionLocales.*.regex' => __('validator.localeKey'), + 'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'), ] ); @@ -494,8 +496,17 @@ public function add($context, $request) if (!$context->getData('supportedFormLocales')) { $context->setData('supportedFormLocales', [$context->getData('primaryLocale')]); } + if (!$context->getData('supportedDefaultSubmissionLocale')) { + $context->setData('supportedDefaultSubmissionLocale', $context->getData('primaryLocale')); + } + if (!$context->getData('supportedAddedSubmissionLocales')) { + $context->setData('supportedAddedSubmissionLocales', [$context->getData('supportedDefaultSubmissionLocale')]); + } if (!$context->getData('supportedSubmissionLocales')) { - $context->setData('supportedSubmissionLocales', [$context->getData('primaryLocale')]); + $context->setData('supportedSubmissionLocales', [$context->getData('supportedDefaultSubmissionLocale')]); + } + if (!$context->getData('supportedSubmissionMetadataLocales')) { + $context->setData('supportedSubmissionMetadataLocales', [$context->getData('supportedDefaultSubmissionLocale')]); } $contextDao->insertObject($context); diff --git a/classes/submission/Repository.php b/classes/submission/Repository.php index 745a9c76423..490605a41e0 100644 --- a/classes/submission/Repository.php +++ b/classes/submission/Repository.php @@ -253,8 +253,9 @@ public function getWorkflowUrlByUserRoles(Submission $submission, ?int $userId = */ public function validate(?Submission $submission, array $props, Context $context): array { - $primaryLocale = $props['locale'] ?? $submission?->getLocale() ?? $context->getPrimaryLocale(); + $primaryLocale = $props['locale'] ?? $submission?->getData('locale') ?? $context->getSupportedDefaultSubmissionLocale(); $allowedLocales = $context->getSupportedSubmissionLocales(); + in_array($primaryLocale, $allowedLocales) || array_push($allowedLocales, $primaryLocale); $errors = []; @@ -542,7 +543,7 @@ public function add(Submission $submission, Publication $publication, Context $c $submission->setData('status', Submission::STATUS_QUEUED); } if (!$submission->getData('locale')) { - $submission->setData('locale', $context->getPrimaryLocale()); + $submission->setData('locale', $context->getSupportedDefaultSubmissionLocale()); } $submissionId = $this->dao->insert($submission); $submission = Repo::submission()->get($submissionId); diff --git a/classes/submissionFile/Repository.php b/classes/submissionFile/Repository.php index 5f1702aa1f4..fc6e2b26129 100644 --- a/classes/submissionFile/Repository.php +++ b/classes/submissionFile/Repository.php @@ -105,8 +105,8 @@ public function getSchemaMap(): Schema * Perform validation checks on data used to add or edit a submission file. * * @param array $props A key/value array with the new data to validate - * @param array $allowedLocales The context's supported locales - * @param string $primaryLocale The context's primary locale + * @param array $allowedLocales The supported submission metadata locales + * @param string $submissionLocale The submission's locale * * @return array A key/value array with validation errors. Empty if no errors */ @@ -114,7 +114,7 @@ public function validate( ?SubmissionFile $object, array $props, array $allowedLocales, - string $primaryLocale + string $submissionLocale ): array { $validator = ValidatorFactory::make( $props, @@ -129,7 +129,7 @@ public function validate( $this->schemaService->getRequiredProps($this->dao->schema), $this->schemaService->getMultilingualProps($this->dao->schema), $allowedLocales, - $primaryLocale + $submissionLocale ); // Check for input from disallowed locales @@ -242,7 +242,7 @@ public function validate( $object, $props, $allowedLocales, - $primaryLocale + $submissionLocale ] ); diff --git a/classes/submissionFile/maps/Schema.php b/classes/submissionFile/maps/Schema.php index afa93abd54f..183db77d3d2 100644 --- a/classes/submissionFile/maps/Schema.php +++ b/classes/submissionFile/maps/Schema.php @@ -226,10 +226,13 @@ protected function mapByProperties(array $props, SubmissionFile $submissionFile) $output[$prop] = $submissionFile->getData($prop); } + $locales = $this->context->getSupportedSubmissionMetaDataLocales(); + in_array($submissionLocale = $submissionFile->getData('locale'), $locales) || array_push($locales, $submissionLocale); + $output = $this->schemaService->addMissingMultilingualValues( $this->schema, $output, - $this->context->getSupportedFormLocales() + $locales ); ksort($output); diff --git a/classes/template/PKPTemplateManager.php b/classes/template/PKPTemplateManager.php index d2ddae8db03..e5273098c1d 100644 --- a/classes/template/PKPTemplateManager.php +++ b/classes/template/PKPTemplateManager.php @@ -765,7 +765,8 @@ public function registerJSLibraryData() $allLocales = array_merge( $context->getSupportedLocales() ?? [], $context->getSupportedFormLocales() ?? [], - $context->getSupportedSubmissionLocales() ?? [] + $context->getSupportedSubmissionLocales() ?? [], + $context->getSupportedSubmissionMetadataLocales() ?? [], ); } else { $allLocales = $this->_request->getSite()->getSupportedLocales(); diff --git a/controllers/api/file/PKPManageFileApiHandler.php b/controllers/api/file/PKPManageFileApiHandler.php index 5e72c85248a..84f3abe1708 100644 --- a/controllers/api/file/PKPManageFileApiHandler.php +++ b/controllers/api/file/PKPManageFileApiHandler.php @@ -193,7 +193,7 @@ public function editMetadataTab($args, $request) $submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE); $reviewRound = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND); $stageId = $request->getUserVar('stageId'); - $form = new SubmissionFilesMetadataForm($submissionFile, $stageId, $reviewRound); + $form = new SubmissionFilesMetadataForm($submissionFile, $stageId, $request->getContext(), $reviewRound); $form->setShowButtons(true); return new JSONMessage(true, $form->fetch($request)); } @@ -213,7 +213,7 @@ public function saveMetadata($args, $request) $submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE); $reviewRound = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND); $stageId = $request->getUserVar('stageId'); - $form = new SubmissionFilesMetadataForm($submissionFile, $stageId, $reviewRound); + $form = new SubmissionFilesMetadataForm($submissionFile, $stageId, $request->getContext(), $reviewRound); $form->readInputData(); if ($form->validate()) { $form->execute(); diff --git a/controllers/grid/admin/languages/AdminLanguageGridHandler.php b/controllers/grid/admin/languages/AdminLanguageGridHandler.php index ebdbf5ea294..03598c32712 100644 --- a/controllers/grid/admin/languages/AdminLanguageGridHandler.php +++ b/controllers/grid/admin/languages/AdminLanguageGridHandler.php @@ -166,7 +166,7 @@ protected function loadData($request, $filter) } if ($this->_canManage($request)) { - $data = $this->addManagementData($request, $data); + $data = $this->addLocaleSettingData($request, $data); } return $data; @@ -430,7 +430,8 @@ protected function _updateContextLocaleSettings($request) while ($context = $contexts->next()) { $params = []; $primaryLocale = $context->getPrimaryLocale(); - foreach (['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'] as $settingName) { + $params['supportedDefaultSubmissionLocale'] = $context->getData('supportedDefaultSubmissionLocale'); + foreach (['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales', 'supportedSubmissionMetadataLocales'] as $settingName) { $localeList = $context->getData($settingName); if (is_array($localeList)) { diff --git a/controllers/grid/languages/LanguageGridCellProvider.php b/controllers/grid/languages/LanguageGridCellProvider.php index ee61994f61a..4ddcc1c3f07 100644 --- a/controllers/grid/languages/LanguageGridCellProvider.php +++ b/controllers/grid/languages/LanguageGridCellProvider.php @@ -59,9 +59,15 @@ public function getTemplateVarsFromRowColumn($row, $column) case 'formLocale': return ['selected' => $element['supportedFormLocales'], 'disabled' => !$element['supported']]; + case 'defaultSubmissionLocale': + return ['selected' => $element['supportedDefaultSubmissionLocale'], + 'disabled' => !$element['supported']]; case 'submissionLocale': return ['selected' => $element['supportedSubmissionLocales'], 'disabled' => !$element['supported']]; + case 'submissionMetadataLocale': + return ['selected' => $element['supportedSubmissionMetadataLocales'], + 'disabled' => !$element['supported']]; default: assert(false); break; @@ -128,12 +134,27 @@ public function getCellActions($request, $row, $column, $position = GridHandler: $actionArgs['value'] = !$element['supportedFormLocales']; $actionRequest = new AjaxAction($router->url($request, null, null, 'saveLanguageSetting', null, $actionArgs)); break; + case 'defaultSubmissionLocale': + $default = $element['supportedDefaultSubmissionLocale']; + if (!$default) { + $action = 'setDefaultSubmissionLocale-' . $row->getId(); + $actionArgs['setting'] = 'supportedDefaultSubmissionLocale'; + $actionArgs['value'] = !$element['supportedDefaultSubmissionLocale']; + $actionRequest = new AjaxAction($router->url($request, null, null, 'setDefaultSubmissionLocale', null, $actionArgs)); + } + break; case 'submissionLocale': $action = 'setSubmissionLocale-' . $row->getId(); $actionArgs['setting'] = 'supportedSubmissionLocales'; $actionArgs['value'] = !$element['supportedSubmissionLocales']; $actionRequest = new AjaxAction($router->url($request, null, null, 'saveLanguageSetting', null, $actionArgs)); break; + case 'submissionMetadataLocale': + $action = 'setSubmissionMetadataLocale-' . $row->getId(); + $actionArgs['setting'] = 'supportedSubmissionMetadataLocales'; + $actionArgs['value'] = !$element['supportedSubmissionMetadataLocales']; + $actionRequest = new AjaxAction($router->url($request, null, null, 'saveLanguageSetting', null, $actionArgs)); + break; } if ($action && $actionRequest) { diff --git a/controllers/grid/languages/LanguageGridHandler.php b/controllers/grid/languages/LanguageGridHandler.php index 9449bd4eb32..74e52d0d61d 100644 --- a/controllers/grid/languages/LanguageGridHandler.php +++ b/controllers/grid/languages/LanguageGridHandler.php @@ -37,7 +37,7 @@ public function __construct() parent::__construct(); $this->addRoleAssignment( [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN], - ['saveLanguageSetting', 'setContextPrimaryLocale'] + ['saveLanguageSetting', 'setContextPrimaryLocale', 'setDefaultSubmissionLocale'] ); } @@ -90,26 +90,31 @@ public function saveLanguageSetting($args, $request) $contextService = Services::get('context'); - $permittedSettings = ['supportedFormLocales', 'supportedSubmissionLocales', 'supportedLocales']; + $permittedSettings = ['supportedFormLocales', 'supportedSubmissionLocales', 'supportedLocales', 'supportedSubmissionMetadataLocales']; if (in_array($settingName, $permittedSettings) && $locale) { $currentSettingValue = (array) $context->getData($settingName); if (Locale::isLocaleValid($locale) && array_key_exists($locale, $availableLocales)) { if ($settingValue) { - array_push($currentSettingValue, $locale); + (array_push($currentSettingValue, $locale) && sort($currentSettingValue)); if ($settingName == 'supportedFormLocales') { // reload localized default context settings $contextService->restoreLocaleDefaults($context, $request, $locale); } elseif ($settingName == 'supportedSubmissionLocales') { - // if a submission locale is enabled, and this locale is not in the form locales, add it - $supportedFormLocales = (array) $context->getData('supportedFormLocales'); - if (!in_array($locale, $supportedFormLocales)) { - array_push($supportedFormLocales, $locale); - $context = $contextService->edit($context, ['supportedFormLocales' => $supportedFormLocales], $request); + // if a submission locale is enabled, and this locale is not in the metadata locales, add it + $supportedSubmissionMetadataLocales = (array) $context->getSupportedSubmissionMetadataLocales(); + if (!in_array($locale, $supportedSubmissionMetadataLocales)) { + (array_push($supportedSubmissionMetadataLocales, $locale) && sort($supportedSubmissionMetadataLocales)); + $context = $contextService->edit($context, ['supportedSubmissionMetadataLocales' => $supportedSubmissionMetadataLocales], $request); // reload localized default context settings $contextService->restoreLocaleDefaults($context, $request, $locale); } } } else { + if (($settingName == 'supportedSubmissionLocales' || $settingName == 'supportedSubmissionMetadataLocales') && $locale === $context->getSupportedDefaultSubmissionLocale() || + ($settingName == 'supportedLocales' || $settingName == 'supportedFormLocales') && $locale === $context->getPrimaryLocale()) { + return new JSONMessage(false, __('notification.defaultLocaleSettingsCannotBeSaved')); + } + $key = array_search($locale, $currentSettingValue); if ($key !== false) { unset($currentSettingValue[$key]); @@ -119,9 +124,9 @@ public function saveLanguageSetting($args, $request) return new JSONMessage(false, __('notification.localeSettingsCannotBeSaved')); } - if ($settingName == 'supportedFormLocales') { - // if a form locale is disabled, disable it form submission locales as well - $supportedSubmissionLocales = (array) $context->getData('supportedSubmissionLocales'); + if ($settingName == 'supportedSubmissionMetadataLocales') { + // if a metadata locale is disabled, disable it form submission locales as well + $supportedSubmissionLocales = (array) $context->getSupportedSubmissionLocales(); $key = array_search($locale, $supportedSubmissionLocales); if ($key !== false) { unset($supportedSubmissionLocales[$key]); @@ -135,7 +140,7 @@ public function saveLanguageSetting($args, $request) if ($settingName == 'supportedSubmissionLocales') { // If someone tried to disable all submissions checkboxes, we should display an error message. - $supportedSubmissionLocales = (array) $context->getData('supportedSubmissionLocales'); + $supportedSubmissionLocales = (array) $context->getSupportedSubmissionLocales(); $key = array_search($locale, $supportedSubmissionLocales); if ($key !== false) { unset($supportedSubmissionLocales[$key]); @@ -186,7 +191,7 @@ public function setContextPrimaryLocale($args, $request) if (Locale::isLocaleValid($locale) && array_key_exists($locale, $availableLocales)) { // Make sure at least the primary locale is chosen as available - foreach (['supportedLocales', 'supportedSubmissionLocales', 'supportedFormLocales'] as $name) { + foreach (['supportedLocales', 'supportedFormLocales'] as $name) { $$name = $context->getData($name); if (!in_array($locale, $$name)) { array_push($$name, $locale); @@ -210,6 +215,46 @@ public function setContextPrimaryLocale($args, $request) return \PKP\db\DAO::getDataChangedEvent(); } + /** + * Set default submission locale. + */ + public function setDefaultSubmissionLocale(array $args, Request $request): JSONMessage + { + if (!$request->checkCSRF()) { + return new JSONMessage(false); + } + $locale = (string) $request->getUserVar('rowId'); + $context = $request->getContext(); + $contextService = Services::get('context'); + $availableLocales = $this->getGridDataElements($request); + + if (Locale::isLocaleValid($locale) && array_key_exists($locale, $availableLocales)) { + // Make sure at least the primary locale is chosen as available + foreach (['supportedSubmissionLocales', 'supportedSubmissionMetadataLocales'] as $name) { + $$name = $context->getData($name); + if (!in_array($locale, $$name)) { + array_push($$name, $locale); + $context = $contextService->edit($context, [$name => $$name], $request); + } + } + + $context = $contextService->edit($context, ['supportedDefaultSubmissionLocale' => $locale], $request); + + $contextDao = Application::getContextDAO(); + $contextDao->updateObject($context); + + $notificationManager = new NotificationManager(); + $user = $request->getUser(); + $notificationManager->createTrivialNotification( + $user->getId(), + PKPNotification::NOTIFICATION_TYPE_SUCCESS, + ['contents' => __('notification.localeSettingsSaved')] + ); + } + + return \PKP\db\DAO::getDataChangedEvent(); + } + // // Protected methods. // @@ -263,18 +308,16 @@ public function addLocaleCodeColumn() } /** - * Add primary column. - * - * @param string $columnId The column id. + * Add website/submission primary/default column. */ - public function addPrimaryColumn($columnId) + public function addPrimaryColumn(string $columnId, string $name = 'locale.primary') { $cellProvider = $this->getCellProvider(); $this->addColumn( new GridColumn( $columnId, - 'locale.primary', + $name, null, 'controllers/grid/common/cell/radioButtonCell.tpl', $cellProvider @@ -307,6 +350,14 @@ public function addManagementColumns() $cellProvider ) ); + } + + /** + * Add columns related to submission langauge settings. + */ + public function addSubmissionColumns(): void + { + $cellProvider = $this->getCellProvider(); $this->addColumn( new GridColumn( @@ -317,26 +368,31 @@ public function addManagementColumns() $cellProvider ) ); + + $this->addColumn( + new GridColumn( + 'submissionMetadataLocale', + 'manager.language.submissionMetadata', + null, + 'controllers/grid/common/cell/selectStatusCell.tpl', + $cellProvider + ) + ); } /** - * Add data related to management settings. - * - * @param Request $request - * @param array $data Data already loaded. - * - * @return array Same passed array, but with - * the extra management data inserted. + * Add locales data related to management settings. + * $data Data already loaded. + * Return Same passed array, but with the extra management data inserted. */ - public function addManagementData($request, $data) + public function addLocaleSettingData(Request $request, array $data, array $localeSettingNames = ['supportedFormLocales', 'supportedLocales']): array { $context = $request->getContext(); if (is_array($data)) { foreach ($data as $locale => $localeData) { - foreach (['supportedFormLocales', 'supportedSubmissionLocales', 'supportedLocales'] as $name) { + foreach ($localeSettingNames as $name) { $data[$locale][$name] = in_array($locale, $context->getData($name)); - // $data[$locale][$name] = in_array($locale, (array) $context->getData($name)); } } } else { diff --git a/controllers/grid/languages/form/AddLanguageForm.php b/controllers/grid/languages/form/AddLanguageForm.php new file mode 100644 index 00000000000..54a46444e57 --- /dev/null +++ b/controllers/grid/languages/form/AddLanguageForm.php @@ -0,0 +1,139 @@ +setData('addedLocales', ((Application::get()->getRequest())->getContext())->getSupportedAddedSubmissionLocales()); + } + + /** + * @copydoc Form::fetch() + * + * @param null|mixed $template + */ + public function fetch($request, $template = null, $display = false) + { + $allLocales =[]; + foreach(Locale::getLanguages() as $lang) { + $code = $lang->getAlpha2(); + if (!empty($code)) $allLocales[$code] = $lang->getLocalName() . " ($code)"; + } + $allLocales += Locale::getFormattedDisplayNames(null, null, LocaleMetadata::LANGUAGE_LOCALE_WITHOUT, false); + ksort($allLocales); + + + $templateMgr = TemplateManager::getManager($request); + $templateMgr->assign([ + 'allLocales' => $allLocales, + 'addedLocales' => ((Application::get()->getRequest())->getContext())->getSupportedAddedSubmissionLocales(), + ]); + + return parent::fetch($request, $template, $display); + } + + /** + * @copydoc Form::readInputData() + */ + public function readInputData() + { + parent::readInputData(); + + $request = Application::get()->getRequest(); + $localesToAdd = $request->getUserVar('localesToAdd'); + $this->setData('localesToAdd', $localesToAdd); + } + + /** + * @copydoc Form::execute() + */ + public function execute(...$functionArgs) + { + $request = Application::get()->getRequest(); + $context = $request->getContext(); + $localesToAdd = $this->getData('localesToAdd'); + + parent::execute(...$functionArgs); + + if (isset($localesToAdd) && is_array($localesToAdd)) { + $locales = array_values(array_filter($localesToAdd, fn ($locale) => Locale::isLocaleValid($locale))); + + if (!empty(count($locales))) { + sort($locales); + + $contextService = Services::get('context'); + $removedLocales = array_diff($context->getSupportedAddedSubmissionLocales(), $locales); + $submToAdd = array_values(array_diff($context->getSupportedSubmissionLocales(), $removedLocales)); + $metaToAdd = array_values(array_diff($context->getSupportedSubmissionMetadataLocales(), $removedLocales)); + + if (in_array($context->getSupportedDefaultSubmissionLocale(), $removedLocales)) { + $context = $contextService->edit($context, ['supportedDefaultSubmissionLocale' => $locales[0]], $request); + (in_array($locales[0], $submToAdd) || array_push($submToAdd, $locales[0]) && sort($submToAdd)); + (in_array($locales[0], $metaToAdd) || array_push($metaToAdd, $locales[0]) && sort($metaToAdd)); + } + + $context = $contextService->edit($context, [ + 'supportedAddedSubmissionLocales' => $locales, + 'supportedSubmissionLocales' => $submToAdd, + 'supportedSubmissionMetadataLocales' => $metaToAdd, + ], $request); + + (Application::getContextDAO())->updateObject($context); + } + } + } + + /** + * Perform additional validation checks + * + * @copydoc Form::validate + */ + public function validate($callHooks = true) + { + $localesToAdd = $this->getData('localesToAdd'); + if (!isset($localesToAdd) || !is_array($localesToAdd) || empty(count(array_filter($localesToAdd, fn ($locale) => Locale::isLocaleValid($locale))))) { + $this->addError('localesToAdd', __('manager.language.submission.from.error')); + } + return parent::validate($callHooks); + } +} diff --git a/controllers/grid/settings/languages/ManageLanguageGridHandler.php b/controllers/grid/settings/languages/ManageLanguageGridHandler.php index fcbc13bd6fd..bcb30e70a78 100644 --- a/controllers/grid/settings/languages/ManageLanguageGridHandler.php +++ b/controllers/grid/settings/languages/ManageLanguageGridHandler.php @@ -75,7 +75,7 @@ protected function loadData($request, $filter) $data[$locale]['primary'] = ($locale == $contextPrimaryLocale); } - $data = $this->addManagementData($request, $data); + $data = $this->addLocaleSettingData($request, $data); return $data; } @@ -90,6 +90,9 @@ protected function loadData($request, $filter) public function initialize($request, $args = null) { parent::initialize($request, $args); + + $this->setTitle('manager.language.websiteLanguages'); + $this->addNameColumn(); $this->addLocaleCodeColumn(); $this->addPrimaryColumn('contextPrimary'); diff --git a/controllers/grid/settings/languages/SubmissionLanguageGridHandler.php b/controllers/grid/settings/languages/SubmissionLanguageGridHandler.php new file mode 100644 index 00000000000..73769cb306e --- /dev/null +++ b/controllers/grid/settings/languages/SubmissionLanguageGridHandler.php @@ -0,0 +1,155 @@ +addRoleAssignment( + [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN], + ['addLanguages', 'addLanguageModal', 'fetchGrid', 'fetchRow'] + ); + } + + + // + // Implement methods from GridHandler. + // + /** + * @copydoc GridHandler::authorize() + */ + public function authorize($request, &$args, $roleAssignments) + { + $this->addPolicy(new ContextAccessPolicy($request, $roleAssignments)); + return parent::authorize($request, $args, $roleAssignments); + } + + /** + * @copydoc GridHandler::loadData() + */ + protected function loadData($request, $filter) + { + $context = $request->getContext(); + $allLocales = Locale::getLocales(); + + $addedLocales = $context->getSupportedAddedSubmissionLocales(); + $defaultSubmissionLocale = $context->getSupportedDefaultSubmissionLocale(); + + $data = []; + + foreach ($addedLocales as $locale) { + $formattedLocale = Locale::getFormattedDisplayNames([$locale], $allLocales); + $data[$locale] = []; + $data[$locale]['code'] = $locale; + $data[$locale]['name'] = array_shift($formattedLocale); + $data[$locale]['supported'] = true; + $data[$locale]['supportedDefaultSubmissionLocale'] = ($locale === $defaultSubmissionLocale); + } + + $data = $this->addLocaleSettingData($request, $data, ['supportedSubmissionLocales', 'supportedSubmissionMetadataLocales']); + return $data; + } + + // + // Extended methods from LanguageGridHandler. + // + /** + * @copydoc LanguageGridHandler::initialize() + * + * @param null|mixed $args + */ + public function initialize($request, $args = null): void + { + parent::initialize($request, $args); + + $this->setTitle('manager.language.submissionLanguages'); + + $this->addNameColumn(); + $this->addLocaleCodeColumn(); + $this->addPrimaryColumn('defaultSubmissionLocale', 'common.default'); + $this->addSubmissionColumns(); + + // Add grid action. + $this->addAction( + new LinkAction( + 'addLanguageModal', + new AjaxModal( + ($request->getRouter())->url($request, null, null, 'addLanguageModal', null, null), + __('manager.language.gridAction.addLangauage'), + null, + true, + 'addLanguageForm' + ), + __('manager.language.gridAction.addLangauage') + ) + ); + } + + /** + * Show the add language form. + */ + public function addLanguageModal(array $args, PKPRequest $request): JSONMessage + { + $addLanguageForm = new AddLanguageForm(); + $addLanguageForm->initData(); + return new JSONMessage(true, $addLanguageForm->fetch($request)); + } + + /** + * Add/Remove languages + */ + public function addLanguages(array $args, PKPRequest $request): JSONMessage + { + $addLanguageForm = new AddLanguageForm(); + $addLanguageForm->readInputData(); + + if ($addLanguageForm->validate()) { + $addLanguageForm->execute(); + + $notificationManager = new NotificationManager(); + $user = $request->getUser(); + $notificationManager->createTrivialNotification( + $user->getId(), + PKPNotification::NOTIFICATION_TYPE_SUCCESS, + ['contents' => __('notification.submissionLocales')] + ); + + return \PKP\db\DAO::getDataChangedEvent(); + } else { + return new JSONMessage(true, $addLanguageForm->fetch($request)); + } + } +} diff --git a/controllers/wizard/fileUpload/FileUploadWizardHandler.php b/controllers/wizard/fileUpload/FileUploadWizardHandler.php index 435f3fe02a0..9dc9c4fb9ca 100644 --- a/controllers/wizard/fileUpload/FileUploadWizardHandler.php +++ b/controllers/wizard/fileUpload/FileUploadWizardHandler.php @@ -454,13 +454,14 @@ public function editMetadata($args, $request) 'primaryLocale' => $this->getSubmission()->getLocale(), ]); + $context = $request->getContext(); $submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE); - $form = new SubmissionFilesMetadataForm($submissionFile, $this->getStageId(), $this->getReviewRound()); + $form = new SubmissionFilesMetadataForm($submissionFile, $this->getStageId(), $context, $this->getReviewRound()); $form->initData(); /** @var GenreDAO $genreDao */ $genreDao = DAORegistry::getDAO('GenreDAO'); - $fileGenres = $genreDao->getByContextId($request->getContext()->getId())->toArray(); + $fileGenres = $genreDao->getByContextId($context->getId())->toArray(); $fileData = Repo::submissionFile() ->getSchemaMap() diff --git a/controllers/wizard/fileUpload/form/SubmissionFilesMetadataForm.php b/controllers/wizard/fileUpload/form/SubmissionFilesMetadataForm.php index 523286403e8..efed3b95737 100644 --- a/controllers/wizard/fileUpload/form/SubmissionFilesMetadataForm.php +++ b/controllers/wizard/fileUpload/form/SubmissionFilesMetadataForm.php @@ -40,15 +40,19 @@ class SubmissionFilesMetadataForm extends Form * * @param SubmissionFile $submissionFile * @param int $stageId One of the WORKFLOW_STAGE_ID_* constants. + * @param Context $context * @param ReviewRound $reviewRound (optional) Current review round, if any. * @param string $template Path and filename to template file (optional). */ - public function __construct($submissionFile, $stageId, $reviewRound = null, $template = null) + public function __construct($submissionFile, $stageId, $context, $reviewRound = null, $template = null) { if ($template === null) { $template = 'controllers/wizard/fileUpload/form/submissionFileMetadataForm.tpl'; } - parent::__construct($template); + + $submissionLocale = $submissionFile->getData('locale'); + + parent::__construct($template, true, $submissionLocale, $context->getSupportedSubmissionMetadataLocaleNames()); // Initialize the object. $this->_submissionFile = $submissionFile; @@ -57,7 +61,6 @@ public function __construct($submissionFile, $stageId, $reviewRound = null, $tem $this->_reviewRound = $reviewRound; } - $submissionLocale = $submissionFile->getData('locale'); $this->setDefaultFormLocale($submissionLocale); // Add validation checks. diff --git a/locale/en/manager.po b/locale/en/manager.po index 26dfa117244..bceb87ae577 100644 --- a/locale/en/manager.po +++ b/locale/en/manager.po @@ -556,15 +556,33 @@ msgstr "Title" msgid "manager.importExport" msgstr "Import/Export Data" +msgid "manager.language.websiteLanguages" +msgstr "Website Languages" + +msgid "manager.language.submissionLanguages" +msgstr "Submission Languages" + msgid "manager.language.ui" msgstr "UI" msgid "manager.language.submissions" msgstr "Submissions" +msgid "manager.language.gridAction.addLangauage" +msgstr "Add/Remove Languages" + msgid "manager.language.forms" msgstr "Forms" +msgid "manager.language.submissionMetadata" +msgstr "Metadata" + +msgid "manager.language.submission.form.description" +msgstr "Select submission and metadata languages." + +msgid "manager.language.submission.from.error" +msgstr "At least one locale needs to be selected." + msgid "manager.language.reloadLocalizedDefaultSettings" msgstr "Reload defaults" @@ -1601,6 +1619,12 @@ msgstr "" "The language setting could not be saved. At least one language must be " "enabled for each option" +msgid "notification.defaultLocaleSettingsCannotBeSaved" +msgstr "The language setting could not be saved. All options need to be enabled." + +msgid "notification.submissionLocales" +msgstr "Submission locales updated." + msgid "notification.editedUser" msgstr "User edited." diff --git a/pages/authorDashboard/PKPAuthorDashboardHandler.php b/pages/authorDashboard/PKPAuthorDashboardHandler.php index 1aa08748243..c4a986a9a00 100644 --- a/pages/authorDashboard/PKPAuthorDashboardHandler.php +++ b/pages/authorDashboard/PKPAuthorDashboardHandler.php @@ -35,6 +35,7 @@ use PKP\core\PKPApplication; use PKP\core\PKPRequest; use PKP\db\DAORegistry; +use PKP\i18n\LocaleMetadata; use PKP\log\SubmissionEmailLogDAO; use PKP\log\SubmissionEmailLogEntry; use PKP\security\authorization\AuthorDashboardAccessPolicy; @@ -216,7 +217,8 @@ public function setupTemplate($request) } } - $locales = $submissionContext->getSupportedSubmissionLocaleNames(); + $locales = $submissionContext->getSupportedSubmissionMetadataLocaleNames() + [$submission->getData('locale') => (new LocaleMetadata($submission->getData('locale')))->getDisplayName(null, false)]; + ksort($locales); $locales = array_map(fn (string $locale, string $name) => ['key' => $locale, 'label' => $name], array_keys($locales), $locales); $latestPublication = $submission->getLatestPublication(); @@ -302,8 +304,8 @@ public function setupTemplate($request) $state = [ 'canEditPublication' => $canEditPublication, 'components' => [ - FORM_TITLE_ABSTRACT => $titleAbstractForm->getConfig(), - FORM_CITATIONS => $citationsForm->getConfig(), + FORM_TITLE_ABSTRACT => $this->getLocalizedForm($titleAbstractForm, $submission, $submissionContext), + FORM_CITATIONS => $this->getLocalizedForm($citationsForm, $submission, $submissionContext), $contributorsListPanel->id => $contributorsListPanel->getConfig(), ], 'currentPublication' => $currentPublicationProps, @@ -326,16 +328,15 @@ public function setupTemplate($request) ]; // Add the metadata form if one or more metadata fields are enabled - $vocabSuggestionUrlBase = $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $submissionContext->getData('urlPath'), 'vocabs', null, null, ['vocab' => '__vocab__']); + $vocabSuggestionUrlBase = $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $submissionContext->getData('urlPath'), 'vocabs', null, null, ['vocab' => '__vocab__', 'submissionId' => $submission->getId()]); $metadataForm = new PKPMetadataForm($latestPublicationApiUrl, $locales, $latestPublication, $submissionContext, $vocabSuggestionUrlBase, true); - $metadataFormConfig = $metadataForm->getConfig(); $metadataEnabled = count($metadataForm->fields); if ($metadataEnabled) { $templateMgr->setConstants([ 'FORM_METADATA' => FORM_METADATA, ]); - $state['components'][FORM_METADATA] = $metadataFormConfig; + $state['components'][FORM_METADATA] = $this->getLocalizedForm($metadataForm, $submission, $submissionContext); $state['publicationFormIds'][] = FORM_METADATA; } @@ -370,6 +371,40 @@ protected function getContributorsListPanel(Submission $submission, Context $con ); } + /** + * Get the form configuration data with the correct + * locale settings based on the submission's locale + * + * Uses the submission locale as the primary and + * visible locale, and puts that locale first in the + * list of supported locales. + * + * Call this instead of $form->getConfig() to display + * a form with the correct submission locales + */ + protected function getLocalizedForm(\PKP\components\forms\FormComponent $form, Submission $submission, Context $context): array + { + $config = $form->getConfig(); + + $primaryLocale = $submission->getData('locale'); + $config['primaryLocale'] = $primaryLocale; + $config['visibleLocales'] = [$primaryLocale]; + + $supportedFormLocales = []; + foreach ($context->getSupportedSubmissionMetadataLocaleNames() + [$primaryLocale => ""] as $localeKey => $name) { + $supportedFormLocales[] = [ + 'key' => $localeKey, + 'label' => (new LocaleMetadata($localeKey))->getDisplayName(null, true), + ]; + } + + usort($supportedFormLocales, fn ($a, $b) => $a['key'] === $primaryLocale ? -1 : 1); + + $config['supportedFormLocales'] = $supportedFormLocales; + + return $config; + } + /** * Get the URL for the galley/publication formats grid with a placeholder for * the publicationId value diff --git a/pages/submission/PKPSubmissionHandler.php b/pages/submission/PKPSubmissionHandler.php index 42c7c4a368e..2441bfa07ec 100644 --- a/pages/submission/PKPSubmissionHandler.php +++ b/pages/submission/PKPSubmissionHandler.php @@ -186,11 +186,11 @@ protected function showWizard(array $args, Request $request, Submission $submiss } - $supportedSubmissionLocales = $context->getSupportedSubmissionLocaleNames(); - $formLocales = array_map(fn (string $locale, string $name) => ['key' => $locale, 'label' => $name], array_keys($supportedSubmissionLocales), $supportedSubmissionLocales); + $supportedSubmissionMetadataLocales = $context->getSupportedSubmissionMetadataLocaleNames(); + $formLocales = array_map(fn (string $locale, string $name) => ['key' => $locale, 'label' => $name], array_keys($supportedSubmissionMetadataLocales), $supportedSubmissionMetadataLocales); // Order locales with submission locale first - $orderedLocales = $supportedSubmissionLocales; + $orderedLocales = $supportedSubmissionMetadataLocales; uksort($orderedLocales, fn ($a, $b) => $a === $submission->getData('locale') ? $a : $b); $userGroups = Repo::userGroup() @@ -456,7 +456,7 @@ protected function getSubmissionFilesListPanel(Request $request, Submission $sub 'dropzoneDictMaxFilesExceeded' => __('form.dropzone.dictMaxFilesExceeded'), ], 'otherLabel' => __('about.other'), - 'primaryLocale' => $request->getContext()->getPrimaryLocale(), + 'primaryLocale' => $submission->getData('locale'), 'removeConfirmLabel' => __('submission.submit.removeConfirm'), 'stageId' => WORKFLOW_STAGE_ID_SUBMISSION, 'title' => __('submission.files'), @@ -837,18 +837,19 @@ protected function getLocalizedForm(FormComponent $form, Submission $submission, { $config = $form->getConfig(); - $config['primaryLocale'] = $submission->getLocale(); - $config['visibleLocales'] = [$submission->getLocale()]; + $submissionLocale = $submission->getData('locale'); + $config['primaryLocale'] = $submissionLocale; + $config['visibleLocales'] = [$submissionLocale]; $supportedFormLocales = []; - foreach ($context->getSupportedSubmissionLocaleNames() as $localeKey => $name) { + foreach ($context->getSupportedSubmissionMetadataLocaleNames() as $localeKey => $name) { $supportedFormLocales[] = [ 'key' => $localeKey, 'label' => $name, ]; } - usort($supportedFormLocales, fn ($a, $b) => $a['key'] === $submission->getLocale() ? -1 : 1); + usort($supportedFormLocales, fn ($a, $b) => $a['key'] === $submissionLocale ? -1 : 1); $config['supportedFormLocales'] = $supportedFormLocales; diff --git a/pages/workflow/PKPWorkflowHandler.php b/pages/workflow/PKPWorkflowHandler.php index 02397ada4d3..c6ded71d0ea 100644 --- a/pages/workflow/PKPWorkflowHandler.php +++ b/pages/workflow/PKPWorkflowHandler.php @@ -37,6 +37,7 @@ use PKP\core\PKPApplication; use PKP\core\PKPRequest; use PKP\db\DAORegistry; +use PKP\i18n\LocaleMetadata; use PKP\notification\NotificationDAO; use PKP\notification\PKPNotification; use PKP\plugins\PluginRegistry; @@ -216,7 +217,8 @@ public function index($args, $request) $genreDao = DAORegistry::getDAO('GenreDAO'); $genres = $genreDao->getByContextId($submission->getData('contextId'))->toArray(); - $locales = $submissionContext->getSupportedSubmissionLocaleNames(); + $locales = $submissionContext->getSupportedSubmissionMetadataLocaleNames() + [$submission->getData('locale') => (new LocaleMetadata($submission->getData('locale')))->getDisplayName(null, false)]; + ksort($locales); $locales = array_map(fn (string $locale, string $name) => ['key' => $locale, 'label' => $name], array_keys($locales), $locales); $latestPublication = $submission->getLatestPublication(); @@ -330,8 +332,8 @@ public function index($args, $request) 'components' => [ $contributorsListPanel->id => $contributorsListPanel->getConfig(), $citationsForm->id => $citationsForm->getConfig(), - $publicationLicenseForm->id => $publicationLicenseForm->getConfig(), - $titleAbstractForm->id => $titleAbstractForm->getConfig(), + $publicationLicenseForm->id => $this->getLocalizedForm($publicationLicenseForm, $submission, $submissionContext), + $titleAbstractForm->id => $this->getLocalizedForm($titleAbstractForm, $submission, $submissionContext), ], 'currentPublication' => $currentPublicationProps, 'decisionUrl' => $decisionUrl, @@ -366,16 +368,15 @@ public function index($args, $request) ]; // Add the metadata form if one or more metadata fields are enabled - $vocabSuggestionUrlBase = $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $submissionContext->getData('urlPath'), 'vocabs', null, null, ['vocab' => '__vocab__']); + $vocabSuggestionUrlBase = $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $submissionContext->getData('urlPath'), 'vocabs', null, null, ['vocab' => '__vocab__', 'submissionId' => $submission->getId()]); $metadataForm = new PKPMetadataForm($latestPublicationApiUrl, $locales, $latestPublication, $submissionContext, $vocabSuggestionUrlBase, true); - $metadataFormConfig = $metadataForm->getConfig(); $metadataEnabled = count($metadataForm->fields); if ($metadataEnabled) { $templateMgr->setConstants([ 'FORM_METADATA' => FORM_METADATA, ]); - $state['components'][FORM_METADATA] = $metadataFormConfig; + $state['components'][FORM_METADATA] = $this->getLocalizedForm($metadataForm, $submission, $submissionContext); $state['publicationFormIds'][] = FORM_METADATA; } @@ -402,7 +403,7 @@ public function index($args, $request) $selectRevisionDecisionForm = new \PKP\components\forms\decision\SelectRevisionDecisionForm(); $selectRevisionRecommendationForm = new \PKP\components\forms\decision\SelectRevisionRecommendationForm(); $state['components'][$selectRevisionDecisionForm->id] = $selectRevisionDecisionForm->getConfig(); - $state['components'][$selectRevisionRecommendationForm->id] = $selectRevisionRecommendationForm->getConfig(); + $state['components'][$selectRevisionRecommendationForm->id] = $this->getLocalizedForm($selectRevisionRecommendationForm, $submission, $submissionContext); $templateMgr->setConstants([ 'FORM_SELECT_REVISION_DECISION' => FORM_SELECT_REVISION_DECISION, 'FORM_SELECT_REVISION_RECOMMENDATION' => FORM_SELECT_REVISION_RECOMMENDATION, @@ -822,6 +823,40 @@ protected function notificationOptionsByStage($user, $stageId, $contextId) return false; } + /** + * Get the form configuration data with the correct + * locale settings based on the submission's locale + * + * Uses the submission locale as the primary and + * visible locale, and puts that locale first in the + * list of supported locales. + * + * Call this instead of $form->getConfig() to display + * a form with the correct submission locales + */ + protected function getLocalizedForm(\PKP\components\forms\FormComponent $form, Submission $submission, Context $context): array + { + $config = $form->getConfig(); + + $primaryLocale = $submission->getData('locale'); + $config['primaryLocale'] = $primaryLocale; + $config['visibleLocales'] = [$primaryLocale]; + + $supportedFormLocales = []; + foreach ($context->getSupportedSubmissionMetadataLocaleNames() + [$primaryLocale => ""] as $localeKey => $name) { + $supportedFormLocales[] = [ + 'key' => $localeKey, + 'label' => (new LocaleMetadata($localeKey))->getDisplayName(null, true), + ]; + } + + usort($supportedFormLocales, fn ($a, $b) => $a['key'] === $primaryLocale ? -1 : 1); + + $config['supportedFormLocales'] = $supportedFormLocales; + + return $config; + } + /** * Get a label for a recommendation decision type */ diff --git a/schemas/context.json b/schemas/context.json index 862aa2bafc9..809585e22c8 100644 --- a/schemas/context.json +++ b/schemas/context.json @@ -763,6 +763,21 @@ "default": false, "description": "Whether or not submitting authors should be asked to select categories when they make a new submission." }, + "supportedAddedSubmissionLocales": { + "type": "array", + "items": { + "type": "string", + "validation": [ + "regex:/^([a-z]{2})((_[A-Z]{2})?)(@[a-z]{0,})?$/" + ] + } + }, + "supportedDefaultSubmissionLocale": { + "type": "string", + "validation": [ + "regex:/^([a-z]{2})((_[A-Z]{2})?)(@[a-z]{0,})?$/" + ] + }, "supportedFormLocales": { "type": "array", "items": { @@ -790,6 +805,15 @@ ] } }, + "supportedSubmissionMetadataLocales": { + "type": "array", + "items": { + "type": "string", + "validation": [ + "regex:/^([a-z]{2})((_[A-Z]{2})?)(@[a-z]{0,})?$/" + ] + } + }, "supportEmail": { "type": "string", "validation": [ diff --git a/templates/admin/contextSettings.tpl b/templates/admin/contextSettings.tpl index 82e22e4ac7b..367ba2a965d 100644 --- a/templates/admin/contextSettings.tpl +++ b/templates/admin/contextSettings.tpl @@ -34,6 +34,8 @@ {capture assign=languagesUrl}{url router=\PKP\core\PKPApplication::ROUTE_COMPONENT context=$editContext->getPath() component="grid.settings.languages.ManageLanguageGridHandler" op="fetchGrid" escape=false}{/capture} {load_url_in_div id="languageGridContainer" url=$languagesUrl} + {capture assign=languagesUrl}{url router=\PKP\core\PKPApplication::ROUTE_COMPONENT context=$editContext->getPath() component="grid.settings.languages.SubmissionLanguageGridHandler" op="fetchGrid" escape=false}{/capture} + {load_url_in_div id="submissionLanguageGridContainer" url=$languagesUrl} + $(function() {ldelim} + // Attach the form handler. + $('#addLanguageForm').pkpHandler('$.pkp.controllers.form.AjaxFormHandler'); + {rdelim}); + + +
+ {csrf} + {include file="controllers/notification/inPlaceNotification.tpl" notificationId="installLanguageFormNotification"} + + {fbvFormArea id="availableLocalesFormArea" title="admin.languages.availableLocales"} + {fbvFormSection list="true" description="manager.language.submission.form.description"} + {foreach $allLocales as $locale => $name} + {fbvElement type="checkbox" id="locale-$locale" name="localesToAdd[$locale]" value=$locale label=$allLocales.$locale|escape translate=false checked=in_array($locale, $addedLocales)} + {foreachelse} +

{translate key="admin.languages.noLocalesAvailable"}

+ {/foreach} + {/fbvFormSection} + {/fbvFormArea} + + {if not empty($allLocales)} + {fbvFormButtons id="installLanguageFormSubmit" submitText="common.save"} + {/if} +
diff --git a/templates/management/website.tpl b/templates/management/website.tpl index 17b0aba6f2d..c753573b565 100644 --- a/templates/management/website.tpl +++ b/templates/management/website.tpl @@ -59,6 +59,8 @@ {capture assign=languagesUrl}{url router=\PKP\core\PKPApplication::ROUTE_COMPONENT component="grid.settings.languages.ManageLanguageGridHandler" op="fetchGrid" escape=false}{/capture} {load_url_in_div id="languageGridContainer" url=$languagesUrl} + {capture assign=languagesUrl}{url router=\PKP\core\PKPApplication::ROUTE_COMPONENT component="grid.settings.languages.SubmissionLanguageGridHandler" op="fetchGrid" escape=false}{/capture} + {load_url_in_div id="submissionLanguageGridContainer" url=$languagesUrl} {capture assign=navigationMenusGridUrl}{url router=\PKP\core\PKPApplication::ROUTE_COMPONENT component="grid.navigationMenus.NavigationMenusGridHandler" op="fetchGrid" escape=false}{/capture}