Phase 2 complete: - Seed registration dictionary phrases - Update public and admin registration templates to use translations - Document PAUL plan, apply, summary, and changelog
201 lines
7.2 KiB
PHP
201 lines
7.2 KiB
PHP
<?php
|
|
/**
|
|
* One-off dictionary phrase seed for XXXV Konferencja registration labels.
|
|
*
|
|
* Usage:
|
|
* - Browser: /_rejestracja/sql/apply-2026-04-24-registration-dictionary-phrases.php?run=20260424
|
|
* - CLI: php apply-2026-04-24-registration-dictionary-phrases.php --run
|
|
*
|
|
* Remove this file from the server after a successful production run.
|
|
*/
|
|
|
|
ini_set('display_errors', 1);
|
|
error_reporting(E_ALL);
|
|
|
|
$phrases = array(
|
|
'registration_yes' => 'Tak',
|
|
'registration_no' => 'Nie',
|
|
'registration_missing' => 'brak',
|
|
'registration_invoice_data' => 'Dane do wystawienia faktury',
|
|
'registration_participant_data' => 'Dane uczestnika',
|
|
'registration_institution_data' => 'Dane instytucji',
|
|
'registration_presentation_data' => 'Dane wystąpienia',
|
|
'registration_submit_talk' => 'Zgłaszam referat',
|
|
'registration_submit_poster' => 'Zgłaszam poster',
|
|
'registration_topic' => 'Temat',
|
|
'registration_abstract' => 'Streszczenie',
|
|
'registration_author' => 'Autor',
|
|
'registration_amount_information' => 'Informacja o kwocie do zapłaty',
|
|
'registration_selected_options' => 'Wybrane opcje',
|
|
'registration_fee_discount_2026' => 'Opłata obniżona (płatność do 03.10.2026)',
|
|
'registration_fee_normal_2026' => 'Opłata zwykła (płatność po 03.10.2026)',
|
|
'registration_net_price' => 'Cena netto',
|
|
'registration_net_price_no_vat' => 'Cena netto (bez VAT)',
|
|
'registration_gross_price' => 'Cena brutto',
|
|
'registration_gross_price_vat' => 'Cena brutto (z VAT)',
|
|
'registration_total_to_pay' => 'Razem do zapłaty',
|
|
'registration_full_conference_label' => 'Cała konferencja',
|
|
'registration_participation_full_cta' => 'Biorę udział w całej konferencji',
|
|
'registration_participation_one_day_lodging_cta' => 'Biorę udział w jednym dniu konferencji (z noclegiem)',
|
|
'registration_participation_one_day_no_lodging_cta' => 'Biorę udział w jednym dniu konferencji (bez noclegu)',
|
|
'registration_participation_full' => 'cała konferencja',
|
|
'registration_participation_one_day_lodging' => 'jeden dzień konferencji (z noclegiem)',
|
|
'registration_participation_one_day_no_lodging' => 'jeden dzień konferencji (bez noclegu)',
|
|
'registration_select_day' => 'Proszę zaznaczyć dzień',
|
|
'registration_selected_presence_days' => 'Wskazane dni obecności',
|
|
'registration_full_conference_presence' => 'Obecność podczas całej konferencji.',
|
|
'registration_single_room_surcharge' => 'Dopłata do pokoju 1-osobowego',
|
|
'registration_accompanying_driver_fee' => 'Opłata za pobyt osoby towarzyszącej lub kierowcy w pokoju dwuosobowym',
|
|
'registration_accompanying_driver' => 'Osoba towarzysząca/kierowca',
|
|
'registration_participation_preferences' => 'Udział i preferencje',
|
|
'registration_diet_preferences' => 'Preferencje żywieniowe',
|
|
'registration_diet_standard' => 'dieta standardowa',
|
|
'registration_diet_special' => 'dieta specjalna',
|
|
'registration_diet_standard_short' => 'standardowa',
|
|
'registration_diet_special_short' => 'specjalna',
|
|
'registration_diet_which' => 'Jaka?',
|
|
'registration_conference_price' => 'Cena za konferencję',
|
|
'registration_consents_expressed' => 'Wyrażono zgody',
|
|
'registration_consent_data' => 'Zgoda na przetwarzanie danych',
|
|
'registration_consent_image' => 'Zgoda na przetwarzanie wizerunku',
|
|
'registration_selected_participation_option' => 'Wybrana opcja udziału',
|
|
'registration_participation_type' => 'Typ udziału',
|
|
'registration_days' => 'Dni',
|
|
'registration_diet' => 'Dieta',
|
|
'registration_payment_status' => 'Status opłaty',
|
|
'registration_paid' => 'opłacone',
|
|
'registration_unpaid' => 'nie opłacone',
|
|
'registration_edit' => 'edytuj',
|
|
'registration_delete' => 'usuń',
|
|
'registration_cancel' => 'Anuluj',
|
|
'registration_save' => 'Zapisz',
|
|
);
|
|
|
|
$isCli = PHP_SAPI === 'cli';
|
|
$approved = $isCli
|
|
? in_array('--run', $argv, true)
|
|
: (isset($_GET['run']) && $_GET['run'] === '20260424');
|
|
|
|
header_safe('Content-Type: text/plain; charset=utf-8');
|
|
|
|
if (!$approved) {
|
|
echo "DRY RUN ONLY\n";
|
|
echo "To apply dictionary seed, run with ?run=20260424 in browser or --run in CLI.\n";
|
|
echo "No database changes were made.\n";
|
|
exit;
|
|
}
|
|
|
|
$configPath = __DIR__ . '/../core/config/Strona/db.config.ini';
|
|
if (!is_file($configPath)) {
|
|
fail("Config file not found: " . $configPath);
|
|
}
|
|
|
|
$config = parse_ini_file($configPath, true);
|
|
if (!isset($config['db'])) {
|
|
fail("Missing [db] section in config.");
|
|
}
|
|
|
|
$dbConfig = $config['db'];
|
|
foreach (array('prodHost', 'prodUser', 'prodPass', 'prodDb') as $key) {
|
|
if (!array_key_exists($key, $dbConfig)) {
|
|
fail("Missing db config key: " . $key);
|
|
}
|
|
}
|
|
|
|
$mysqli = new mysqli(
|
|
$dbConfig['prodHost'],
|
|
$dbConfig['prodUser'],
|
|
$dbConfig['prodPass'],
|
|
$dbConfig['prodDb']
|
|
);
|
|
|
|
if ($mysqli->connect_errno) {
|
|
fail("MySQL connection failed: " . $mysqli->connect_error);
|
|
}
|
|
|
|
$mysqli->set_charset('utf8');
|
|
$langs = get_dictionary_langs($mysqli);
|
|
|
|
echo "Applying dictionary phrase seed...\n";
|
|
echo "Languages: " . implode(', ', $langs) . "\n";
|
|
|
|
$inserted = 0;
|
|
$skipped = 0;
|
|
|
|
foreach ($phrases as $keyword => $replacementPl) {
|
|
foreach ($langs as $lang) {
|
|
if (dictionary_phrase_exists($mysqli, $keyword, $lang)) {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
$replacement = $lang === 'pl' ? $replacementPl : $lang . '_' . $keyword;
|
|
insert_dictionary_phrase($mysqli, $keyword, $lang, $replacement);
|
|
$inserted++;
|
|
}
|
|
}
|
|
|
|
echo "Dictionary seed complete.\n";
|
|
echo "Inserted: " . $inserted . "\n";
|
|
echo "Skipped: " . $skipped . "\n";
|
|
$mysqli->close();
|
|
|
|
function get_dictionary_langs(mysqli $mysqli) {
|
|
$langs = array('pl');
|
|
$result = $mysqli->query("SELECT DISTINCT lang FROM mf_dictionary WHERE lang <> ''");
|
|
if (!$result) {
|
|
fail("Could not load dictionary languages: " . $mysqli->error);
|
|
}
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
if (!in_array($row['lang'], $langs, true)) {
|
|
$langs[] = $row['lang'];
|
|
}
|
|
}
|
|
|
|
return $langs;
|
|
}
|
|
|
|
function dictionary_phrase_exists(mysqli $mysqli, $keyword, $lang) {
|
|
$stmt = $mysqli->prepare("SELECT COUNT(*) AS cnt FROM mf_dictionary WHERE keyword = ? AND lang = ?");
|
|
if (!$stmt) {
|
|
fail("Prepare failed: " . $mysqli->error);
|
|
}
|
|
|
|
$stmt->bind_param('ss', $keyword, $lang);
|
|
if (!$stmt->execute()) {
|
|
fail("Dictionary check failed: " . $stmt->error);
|
|
}
|
|
|
|
$result = $stmt->get_result();
|
|
$row = $result->fetch_assoc();
|
|
$stmt->close();
|
|
|
|
return isset($row['cnt']) && (int)$row['cnt'] > 0;
|
|
}
|
|
|
|
function insert_dictionary_phrase(mysqli $mysqli, $keyword, $lang, $replacement) {
|
|
$stmt = $mysqli->prepare("INSERT INTO mf_dictionary (keyword, lang, replacement) VALUES (?, ?, ?)");
|
|
if (!$stmt) {
|
|
fail("Prepare failed: " . $mysqli->error);
|
|
}
|
|
|
|
$stmt->bind_param('sss', $keyword, $lang, $replacement);
|
|
if (!$stmt->execute()) {
|
|
fail("Insert failed for " . $keyword . " / " . $lang . ": " . $stmt->error);
|
|
}
|
|
|
|
$stmt->close();
|
|
}
|
|
|
|
function fail($message) {
|
|
echo "ERROR: " . $message . "\n";
|
|
exit(1);
|
|
}
|
|
|
|
function header_safe($header) {
|
|
if (!headers_sent() && PHP_SAPI !== 'cli') {
|
|
header($header);
|
|
}
|
|
}
|