Skip to content

Commit

Permalink
pkp#9425 Make submission language selection and metadata forms indepe…
Browse files Browse the repository at this point in the history
…ndent from website language settings
  • Loading branch information
jyhein committed Feb 5, 2024
1 parent 369166c commit cf25194
Show file tree
Hide file tree
Showing 41 changed files with 1,041 additions and 143 deletions.
16 changes: 8 additions & 8 deletions api/v1/submissions/PKPSubmissionFileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,12 @@ public function add(Request $illuminateRequest): JsonResponse
$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
Expand All @@ -344,7 +344,7 @@ public function add(Request $illuminateRequest): JsonResponse
null,
$params,
$allowedLocales,
$primaryLocale
$submissionLocale
);

if (!empty($errors)) {
Expand Down Expand Up @@ -430,15 +430,15 @@ public function edit(Request $illuminateRequest): JsonResponse
], Response::HTTP_BAD_REQUEST);
}

$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)) {
Expand Down Expand Up @@ -466,7 +466,7 @@ public function edit(Request $illuminateRequest): JsonResponse
$params['fileId'] = $fileId;
$params['uploaderUserId'] = $request->getUser()->getId();
if (empty($params['name'])) {
$params['name'][$primaryLocale] = $_FILES['file']['name'];
$params['name'][$submissionLocale] = $_FILES['file']['name'];
}
}

Expand Down
4 changes: 3 additions & 1 deletion api/v1/vocabs/PKPVocabController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
namespace PKP\API\v1\vocabs;

use APP\core\Application;
use APP\facades\Repo;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
Expand Down Expand Up @@ -106,8 +107,9 @@ public function getMany(Request $illuminateRequest): JsonResponse
$vocab = $requestParams['vocab'] ?? '';
$locale = $requestParams['locale'] ?? Locale::getLocale();
$term = $requestParams['term'] ?? null;
$locales = array_merge($context->getSupportedSubmissionMetadataLocales(), isset($requestParams['submissionId']) ? Repo::submission()->get((int) $requestParams['submissionId'])?->getPublicationLanguages() ?? [] : []);

if (!in_array($locale, $context->getData('supportedSubmissionLocales'))) {
if (!in_array($locale, $locales)) {
return response()->json([
'error' => __('api.vocabs.400.localeNotSupported', ['locale' => $locale]),
], Response::HTTP_BAD_REQUEST);
Expand Down
2 changes: 1 addition & 1 deletion classes/author/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ 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 = $submission->getPublicationLanguages($context->getSupportedSubmissionMetadataLocales());

$validator = ValidatorFactory::make(
$props,
Expand Down
4 changes: 3 additions & 1 deletion classes/author/maps/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ protected function mapByProperties(array $props, Author $item): array
}
}

$output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->context->getSupportedSubmissionLocales());
$locales = Repo::submission()->get(Repo::publication()->get($item->getData('publicationId'))->getData('submissionId'))->getPublicationLanguages($this->context->getSupportedSubmissionMetadataLocales());

$output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $locales);

ksort($output);

Expand Down
14 changes: 8 additions & 6 deletions classes/components/listPanels/ContributorsListPanel.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,22 @@ protected function getPublicationUrlFormat(): string
*/
protected function getLocalizedForm(): array
{
uksort($this->locales, fn ($a, $b) => $a === $this->submission->getData('locale') ? -1 : 1);

$apiUrl = Application::get()->getRequest()->getDispatcher()->url(
Application::get()->getRequest(),
Application::ROUTE_API,
$this->context->getPath(),
'submissions/' . $this->submission->getId() . '/publications/__publicationId__/contributors'
);

$form = $this->getForm($apiUrl);
$submissionLocale = $this->submission->getData('locale');
$data = $this->getForm($apiUrl)->getConfig();

$data = $form->getConfig();
$data['primaryLocale'] = $this->submission->getData('locale');
$data['visibleLocales'] = [$this->submission->getData('locale')];
$data['primaryLocale'] = $submissionLocale;
$data['visibleLocales'] = [$submissionLocale];
$data['supportedFormLocales'] = collect($this->locales)
->sortBy([fn (array $a, array $b) => $b['key'] === $submissionLocale ? 1 : -1])
->values()
->toArray();

return $data;
}
Expand Down
57 changes: 51 additions & 6 deletions classes/context/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,10 @@ public function getSupportedSubmissionLocales()
/**
* Return associative array of all locales supported by submissions on the
* context.
*
* @param int $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_*
*
* @return array
*/
public function getSupportedSubmissionLocaleNames(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT)
public function getSupportedSubmissionLocaleNames(): array
{
return $this->getData('supportedSubmissionLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedSubmissionLocales(), null, $langLocaleStatus);
return $this->getData('supportedSubmissionLocaleNames') ?? Locale::getSubmissionLocaleDisplayNames($this->getSupportedSubmissionLocales());
}

/**
Expand All @@ -393,6 +389,55 @@ public function getSupportedLocaleNames(int $langLocaleStatus = LocaleMetadata::
return $this->getData('supportedLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedLocales(), null, $langLocaleStatus);
}

/**
* Get the supported added submission locales.
*/
public function getSupportedAddedSubmissionLocales(): array
{
return $this->getData('supportedAddedSubmissionLocales');
}

/**
* Return associative array of added locales supported by submissions on the
* context.
*/
public function getSupportedAddedSubmissionLocaleNames(): array
{
return Locale::getSubmissionLocaleDisplayNames($this->getSupportedAddedSubmissionLocales());
}

/**
* Get the supported default submission locale.
*/
public function getSupportedDefaultSubmissionLocale(): string
{
return $this->getData('supportedDefaultSubmissionLocale');
}

/**
* Return string default submission locale supported by the site.
*/
public function getSupportedDefaultSubmissionLocaleName(): string
{
return Locale::getSubmissionLocaleDisplayNames([$l = $this->getSupportedDefaultSubmissionLocale()])[$l];
}

/**
* 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.
*/
public function getSupportedSubmissionMetadataLocaleNames(): array
{
return Locale::getSubmissionLocaleDisplayNames($this->getSupportedSubmissionMetadataLocales());
}

/**
* Return date or/and time formats available for forms, fallback to the default if not set
*
Expand Down
41 changes: 41 additions & 0 deletions classes/dev/ComposerScript.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,45 @@ public static function isoFileCheck(): void
throw new Exception("The ISO639-2b file {$iso6392bFile} does not exist.");
}
}

/**
* A post-install-cmd custom composer script that
* creates languages.json from downloaded Weblate languages.csv.
*/
public static function weblateFilesDownload(): void
{
try {
$dirPath = dirname(__FILE__, 3) . "/lib/weblateLanguages";
$urlCsvFilePath = "$dirPath/urlCsv.txt";
$langFilePath = "$dirPath/languages.json";

$urlCsv = !file_exists($urlCsvFilePath) ?: file_get_contents($urlCsvFilePath);
if (!is_string($urlCsv)) {
throw new Exception(__METHOD__ . " : File $urlCsvFilePath does not exist !");
}

$streamContext = stream_context_create(['http' => ['method' => 'HEAD']]);
$languagesCsv = !str_contains(get_headers($urlCsv, context: $streamContext)[0] ?? "", '200 OK') ?: file($urlCsv, FILE_SKIP_EMPTY_LINES);
if (!is_array($languagesCsv) || empty(count($languagesCsv))) {
throw new Exception(__METHOD__ . " : The Weblate file 'languages.csv' cannot be downloaded !");
}

array_shift($languagesCsv);
$languages = [];
foreach($languagesCsv as $languageCsv) {
$localeAndName = str_getcsv($languageCsv, ",");
if (isset($localeAndName[0], $localeAndName[1]) && preg_match('/^[\w@-]{2,50}$/', $localeAndName[0]) === 1) {
$displayName = locale_get_display_name($localeAndName[0], 'en');
$languages[$localeAndName[0]] = (($displayName && $displayName !== $localeAndName[0]) ? $displayName : $localeAndName[1]);
}
}

$languagesJson = json_encode($languages, JSON_THROW_ON_ERROR);
if (empty($languagesJson) || !file_put_contents($langFilePath, $languagesJson)) {
throw new Exception(__METHOD__ . " : Json file empty, or save unsuccessful: $langFilePath !");
}
} catch (Exception $e) {
error_log($e->getMessage());
}
}
}
27 changes: 27 additions & 0 deletions classes/galley/Galley.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@

namespace PKP\galley;

use APP\core\Services;
use APP\facades\Repo;
use PKP\facades\Locale;
use PKP\i18n\LocaleMetadata;
use PKP\services\PKPSchemaService;
use PKP\submission\Representation;
use PKP\submissionFile\SubmissionFile;

Expand Down Expand Up @@ -183,6 +186,30 @@ public function setStoredPubId($pubIdType, $pubId)
parent::setStoredPubId($pubIdType, $pubId);
}
}

/**
* Get metadata language names
*/
public function getLanguageNames(): array
{
return Locale::getSubmissionLocaleDisplayNames($this->getLanguages());
}

/**
* Get metadata languages
*/
public function getLanguages(): array
{
$props = Services::get('schema')->getMultilingualProps(PKPSchemaService::SCHEMA_GALLEY);
$locales = array_map(fn (string $prop): array => array_keys($this->getData($prop) ?? []), $props);
return collect([$this->getData('locale')])
->concat($locales)
->flatten()
->filter()
->unique()
->values()
->toArray();
}
}

if (!PKP_STRICT_MODE) {
Expand Down
4 changes: 3 additions & 1 deletion classes/galley/maps/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ protected function mapByProperties(array $props, Galley $galley): array
}
}

$output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->context->getSupportedFormLocales());
$locales = $this->publication->getLanguages($this->context->getSupportedSubmissionMetadataLocales(), $galley->getLanguages());

$output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $locales);

ksort($output);

Expand Down
69 changes: 69 additions & 0 deletions classes/i18n/Locale.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use Illuminate\Support\Facades\Cache;
use InvalidArgumentException;
use PKP\config\Config;
use PKP\core\Core;
use PKP\core\PKPRequest;
use PKP\facades\Repo;
use PKP\i18n\interfaces\LocaleInterface;
Expand Down Expand Up @@ -95,6 +96,9 @@ class Locale implements LocaleInterface
/** Keeps cached data related only to the current locale */
protected array $cache = [];

/** @var string[]|null Available submission locales cache, where key = locale and value = name */
protected ?array $submissionLocaleNames = null;

/**
* @copy \Illuminate\Contracts\Translation\Translator::get()
*
Expand Down Expand Up @@ -204,6 +208,14 @@ public function isLocaleValid(?string $locale): bool
return !empty($locale) && preg_match(LocaleInterface::LOCALE_EXPRESSION, $locale);
}

/**
* @copy LocaleInterface::isSubmissionLocaleValid()
*/
public function isSubmissionLocaleValid(?string $locale): bool
{
return !empty($locale) && preg_match(LocaleInterface::LOCALE_EXPRESSION_SUBMISSION, $locale);
}

/**
* @copy LocaleInterface::getMetadata()
*/
Expand Down Expand Up @@ -405,6 +417,38 @@ public function getUiTranslator(): UITranslator
return new UITranslator($locale, $this->paths, $localeBundleCacheKey);
}

/**
* Get appropriately localized display names for submission locales to array
* If $filterByLocales empty, return all languages.
* Add '*' (= in English) to display name if no translation available
*
* @param array $filterByLocales Optional list of locale codes/code-name-pairs to filter
* @param ?string $displayLocale Optional display locale
*
* @return array The list of locales with formatted display name
*/
public function getSubmissionLocaleDisplayNames(array $filterByLocales = [], ?string $displayLocale = null): array
{
$convDispLocale = $this->convertSubmissionLocaleCode($displayLocale ?: $this->getLocale());
return collect($this->_getSubmissionLocaleNames())
->when(!empty(count($filterByLocales)),
fn ($sln) => $sln->intersectByKeys(array_is_list($filterByLocales) ? array_flip(array_filter($filterByLocales)) : $filterByLocales))
->when($convDispLocale !== 'en', fn ($sln) => $sln->map(function ($nameEn, $l) use ($convDispLocale) {
$cl = $this->convertSubmissionLocaleCode($l);
$dn = locale_get_display_name($cl, $convDispLocale);
return ($dn && $dn !== $cl) ? $dn : "*$nameEn";
}))
->toArray();
}

/**
* Convert submission locale code
*/
public function convertSubmissionLocaleCode(string $locale): string
{
return str_replace(['@cyrillic', '@latin'], ['_Cyrl', '_Latn'], $locale);
}

/**
* Get the filtered locales by locale codes
*
Expand Down Expand Up @@ -513,4 +557,29 @@ private function _getSupportedLocales(): array
?? array_map(fn (LocaleMetadata $locale) => $locale->locale, $this->getLocales());
return $this->supportedLocales = array_combine($locales, $locales);
}

/**
* Get Weblate submission languages to array
* Combine app's language names with weblate's in English.
* Weblate's names override app's if same locale key
*
* @return string[]
*/
private function _getSubmissionLocaleNames(): array
{
return $this->submissionLocaleNames ??= (function (): array {
$file = Core::getBaseDir() . '/' . PKP_LIB_PATH . '/lib/weblateLanguages/languages.json';
$key = __METHOD__ . self::MAX_CACHE_LIFETIME . sha1($file);
$expiration = DateInterval::createFromDateString(static::MAX_CACHE_LIFETIME);
return Cache::remember($key, $expiration, fn (): array => collect($this->getLocales())
->map(function (LocaleMetadata $lm, string $l): string {
$cl = $this->convertSubmissionLocaleCode($l);
$n = locale_get_display_name($cl, 'en');
return ($n && $n !== $cl) ? $n : $lm->getDisplayName('en', true);
})
->merge(json_decode(file_get_contents($file), true) ?: [])
->sortKeys()
->toArray());
})();
}
}
Loading

0 comments on commit cf25194

Please sign in to comment.