added translations export and import
This commit is contained in:
163
common.php
163
common.php
@ -1297,6 +1297,169 @@ function qdb_import_questionnaire_bundle(PDO $pdo, array $item, bool $replaceIfE
|
||||
];
|
||||
}
|
||||
|
||||
/** One translation row for a portable translations JSON bundle. */
|
||||
function qdb_translation_entry_to_bundle_row(array $e, ?string $questionnaireID = null, ?string $questionnaireName = null): array {
|
||||
$tr = $e['translations'] ?? [];
|
||||
if ($tr instanceof stdClass) {
|
||||
$tr = (array)$tr;
|
||||
}
|
||||
if (is_array($tr) && isset($tr[0]) && is_array($tr[0]) && isset($tr[0]['languageCode'])) {
|
||||
$tr = qdb_translation_rows_to_map($tr);
|
||||
}
|
||||
$row = [
|
||||
'type' => $e['type'],
|
||||
'entityId' => $e['entityId'],
|
||||
'key' => $e['key'] ?? '',
|
||||
'translations' => is_array($tr) ? $tr : [],
|
||||
];
|
||||
if (!empty($e['displayKey'])) {
|
||||
$row['displayKey'] = $e['displayKey'];
|
||||
}
|
||||
if ($questionnaireID !== null && $questionnaireID !== '') {
|
||||
$row['questionnaireID'] = $questionnaireID;
|
||||
}
|
||||
if ($questionnaireName !== null && $questionnaireName !== '') {
|
||||
$row['questionnaireName'] = $questionnaireName;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
function qdb_normalize_bundle_translations($raw): array {
|
||||
if (!is_array($raw)) {
|
||||
return [];
|
||||
}
|
||||
if (isset($raw[0]) && is_array($raw[0]) && isset($raw[0]['languageCode'])) {
|
||||
return qdb_translation_rows_to_map($raw);
|
||||
}
|
||||
$map = [];
|
||||
foreach ($raw as $lang => $text) {
|
||||
if (is_string($lang) && $lang !== '') {
|
||||
$map[$lang] = (string)$text;
|
||||
}
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
function qdb_translation_entity_exists(PDO $pdo, string $type, string $entityId): bool {
|
||||
if ($type === 'string' || $type === 'app_string') {
|
||||
return true;
|
||||
}
|
||||
if ($type === 'question') {
|
||||
$stmt = $pdo->prepare('SELECT 1 FROM question WHERE questionID = :id LIMIT 1');
|
||||
} elseif ($type === 'answer_option') {
|
||||
$stmt = $pdo->prepare('SELECT 1 FROM answer_option WHERE answerOptionID = :id LIMIT 1');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$stmt->execute([':id' => $entityId]);
|
||||
return (bool)$stmt->fetchColumn();
|
||||
}
|
||||
|
||||
/** Export all translations (languages + flat entries) as portable JSON. */
|
||||
function qdb_export_translations_bundle(PDO $pdo): array {
|
||||
$languages = $pdo->query('SELECT languageCode, name FROM language ORDER BY languageCode')
|
||||
->fetchAll(PDO::FETCH_ASSOC);
|
||||
if (!array_filter($languages, fn($l) => $l['languageCode'] === QDB_SOURCE_LANGUAGE)) {
|
||||
array_unshift($languages, ['languageCode' => QDB_SOURCE_LANGUAGE, 'name' => 'German']);
|
||||
}
|
||||
qdb_ensure_source_language($pdo);
|
||||
|
||||
$exportEntries = [];
|
||||
$appEntries = qdb_app_ui_string_entries_for_website();
|
||||
$appTranslations = qdb_load_translations_for_entries($pdo, $appEntries);
|
||||
qdb_attach_translation_texts($appEntries, $appTranslations);
|
||||
foreach ($appEntries as $e) {
|
||||
$exportEntries[] = qdb_translation_entry_to_bundle_row($e);
|
||||
}
|
||||
|
||||
$qnRows = $pdo->query('SELECT questionnaireID, name FROM questionnaire ORDER BY orderIndex, name')
|
||||
->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($qnRows as $qn) {
|
||||
$lists = qdb_translation_entry_lists($pdo, $qn['questionnaireID']);
|
||||
$entries = array_merge($lists['stringEntries'], $lists['contentEntries']);
|
||||
if (!$entries) {
|
||||
continue;
|
||||
}
|
||||
$translations = qdb_load_translations_for_entries($pdo, $entries);
|
||||
qdb_attach_translation_texts($entries, $translations);
|
||||
foreach ($entries as $e) {
|
||||
$exportEntries[] = qdb_translation_entry_to_bundle_row(
|
||||
$e,
|
||||
$qn['questionnaireID'],
|
||||
$qn['name']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'exportVersion' => 1,
|
||||
'exportedAt' => time(),
|
||||
'sourceLanguage' => QDB_SOURCE_LANGUAGE,
|
||||
'languageCount' => count($languages),
|
||||
'languages' => $languages,
|
||||
'entryCount' => count($exportEntries),
|
||||
'entries' => $exportEntries,
|
||||
];
|
||||
}
|
||||
|
||||
/** Import translations bundle (upsert languages and translation rows). */
|
||||
function qdb_import_translations_bundle(PDO $pdo, array $bundle): array {
|
||||
$entries = $bundle['entries'] ?? null;
|
||||
if (!is_array($entries)) {
|
||||
json_error('MISSING_FIELDS', 'bundle.entries array is required', 400);
|
||||
}
|
||||
|
||||
qdb_ensure_source_language($pdo);
|
||||
foreach ($bundle['languages'] ?? [] as $langRow) {
|
||||
if (!is_array($langRow)) {
|
||||
continue;
|
||||
}
|
||||
$lc = trim($langRow['languageCode'] ?? '');
|
||||
$name = trim($langRow['name'] ?? '');
|
||||
if ($lc === '' || $lc === QDB_SOURCE_LANGUAGE) {
|
||||
continue;
|
||||
}
|
||||
$pdo->prepare('INSERT INTO language (languageCode, name) VALUES (:lc, :n)
|
||||
ON CONFLICT(languageCode) DO UPDATE SET name = excluded.name')
|
||||
->execute([':lc' => $lc, ':n' => $name]);
|
||||
}
|
||||
|
||||
$validTypes = ['question', 'answer_option', 'string', 'app_string'];
|
||||
$imported = 0;
|
||||
$skipped = 0;
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
if (!is_array($entry)) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
$type = $entry['type'] ?? '';
|
||||
$entityId = trim((string)($entry['entityId'] ?? ''));
|
||||
if (!in_array($type, $validTypes, true) || $entityId === '') {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
if (!qdb_translation_entity_exists($pdo, $type, $entityId)) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
$map = qdb_normalize_bundle_translations($entry['translations'] ?? []);
|
||||
if ($map) {
|
||||
qdb_apply_translation_map($pdo, $type, $entityId, $map);
|
||||
$imported++;
|
||||
} else {
|
||||
$skipped++;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'imported' => $imported,
|
||||
'skipped' => $skipped,
|
||||
'total' => count($entries),
|
||||
];
|
||||
}
|
||||
|
||||
/** Import a full export bundle. */
|
||||
function qdb_import_questionnaires_bundle(PDO $pdo, array $bundle, bool $replaceIfExists = false): array {
|
||||
$items = $bundle['questionnaires'] ?? [];
|
||||
|
||||
Reference in New Issue
Block a user