Implement dynamic language handling and improve error messaging in AJAX responses

This commit enhances the AJAX functionality by introducing a new language handling mechanism, allowing for dynamic language selection based on user input. Additionally, error messages throughout the AJAX responses have been updated to utilize the new fxBibMsg function for better localization and clarity. This improves user experience by providing contextually relevant messages in the selected language. No version code change is included in this update.
This commit is contained in:
2026-06-17 15:49:47 -04:00
parent 5e31ea1129
commit 69f360eae8
4 changed files with 259 additions and 43 deletions

View File

@ -10,6 +10,10 @@ require_once('php/inc_fonctions.php');
require_once('php/inc_fx_promoteur.php');
$strLangue = $_SESSION['lang'] ?? 'fr';
$reqLang = $_REQUEST['lang'] ?? $_REQUEST['lng'] ?? '';
if (!empty($reqLang) && in_array($reqLang, ['fr', 'en'], true)) {
$strLangue = $reqLang;
}
$vPage = 'compte.php';
$vtexte_page = obtenirTextepage($vPage, $strLangue, 2);
@ -54,7 +58,7 @@ if ($action == 'create') {
echo json_encode([
'success' => false,
'message' => 'epr_id invalide'
'message' => fxBibMsg('bib_v4_ajax_epr_invalid')
]);
exit;
}
@ -80,7 +84,7 @@ if ($action == 'delete') {
if (!$range) {
echo json_encode([
'success' => false,
'message' => 'Range introuvable'
'message' => fxBibMsg('bib_v4_ajax_range_not_found')
]);
exit;
}
@ -88,7 +92,7 @@ if ($action == 'delete') {
if ((int)$range[1]['nb_utilises'] > 0) {
echo json_encode([
'success' => false,
'message' => 'Impossible de supprimer : des dossards sont déjà utilisés dans ce range'
'message' => fxBibMsg('bib_v4_ajax_delete_used')
]);
exit;
}
@ -114,7 +118,7 @@ if ($action == 'delete') {
echo json_encode([
'success' => false,
'message' => 'id invalide'
'message' => fxBibMsg('bib_v4_ajax_id_invalid')
]);
exit;
}
@ -134,7 +138,7 @@ if ($action == 'save') {
// VALIDATION 1 — epr_id
// =====================
if ($is_new && $epr_id <= 0) {
echo json_encode(['success' => false, 'message' => 'epr_id invalide']);
echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_epr_invalid')]);
exit;
}
@ -148,7 +152,7 @@ if ($action == 'save') {
// VALIDATION 2 — VALEURS NUMÉRIQUES
// =====================
if ($start <= 0 || $end <= 0) {
echo json_encode(['success' => false, 'message' => 'Valeurs invalides']);
echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_values_invalid')]);
exit;
}
@ -156,7 +160,7 @@ if ($action == 'save') {
// VALIDATION 3 — LOGIQUE INTERVALLE
// =====================
if ($start > $end) {
echo json_encode(['success' => false, 'message' => 'Début doit être < fin']);
echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_start_gt_end')]);
exit;
}
@ -169,7 +173,7 @@ if ($action == 'save') {
$epr_id = (int)$objDatabase->fxGetVar($sqlGet);
if ($epr_id <= 0) {
echo json_encode(['success' => false, 'message' => 'Range introuvable']);
echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_range_not_found')]);
exit;
}
@ -191,7 +195,7 @@ if ($action == 'save') {
if ($nbOrphans > 0) {
echo json_encode([
'success' => false,
'message' => 'Modification impossible : des dossards sortiraient du range'
'message' => fxBibMsg('bib_v4_ajax_orphans')
]);
exit;
}
@ -218,7 +222,7 @@ if ($action == 'save') {
if ($hasOverlap > 0) {
echo json_encode([
'success' => false,
'message' => 'Conflit avec un autre intervalle de dossards'
'message' => fxBibMsg('bib_v4_ajax_overlap')
]);
exit;
}
@ -272,14 +276,13 @@ if ($action == 'view') {
if ($epr_id <= 0 || $range_id < 0) {
echo json_encode([
'success' => false,
'message' => 'Paramètres invalides'
'message' => fxBibMsg('bib_v4_ajax_params_invalid')
]);
exit;
}
// TEMPORAIRE : affichage simple pour test
ob_start();
$html = renderBibView($epr_id, $range_id);
$html = renderBibView($epr_id, $range_id, $strLangue);
echo json_encode([
'success' => true,
@ -299,7 +302,7 @@ if ($action == 'batch_analysis') {
if ($epr_id <= 0) {
echo json_encode([
'success' => false,
'message' => 'epr_id invalide'
'message' => fxBibMsg('bib_v4_ajax_epr_invalid')
]);
exit;
}
@ -319,7 +322,7 @@ if ($action == 'refresh_ranges') {
if ($epr_id <= 0) {
echo json_encode([
'success' => false,
'message' => 'epr_id invalide'
'message' => fxBibMsg('bib_v4_ajax_epr_invalid')
]);
exit;
}
@ -406,7 +409,12 @@ if ($action == 'batch_go') {
$simu = fxProcessBatchAssignments($epr_id, $participants, $tabRanges, 'simulation');
$summary = fxBuildBatchSummaryFromRanges($tabRangesInfos, $participants, $epr_id);
$info = "{$summary['nb_dispo']} disponibles / {$summary['nb_participants']} à assigner → manque {$summary['nb_manque']}";
$info = fxBibMsg(
'bib_v4_ajax_sim_summary',
$summary['nb_dispo'],
$summary['nb_participants'],
$summary['nb_manque']
);
// =====================
// SIMULATION (temporaire simple)
// =====================
@ -418,10 +426,10 @@ if ($action == 'batch_go') {
$html = renderBibView(
$epr_id,
0,
'fr',
$strLangue,
'simulation',
$simu,
'Résultats de la simulation',
fxBibTexte('bib_v4_ajax_title_simulation'),
$info
);
@ -475,23 +483,23 @@ if ($action == 'batch_apply') {
}
if ($assigned === 0) {
$info = "Aucun dossard na pu être assigné.";
$info = fxBibMsg('bib_v4_ajax_assign_none');
} elseif ($assigned === $total) {
$info = "Assignation complétée : $assigned dossards assignés avec succès.";
$info = fxBibMsg('bib_v4_ajax_assign_full', $assigned);
} else {
$info = "Assignation partielle complétée : $assigned dossards assignés avec succès. $remaining participants restent à assigner.";
$info = fxBibMsg('bib_v4_ajax_assign_partial', $assigned, $remaining);
}
$html = renderBibView(
$epr_id,
0,
'fr',
$strLangue,
'execute',
$exec,
'Résultats de lassignation',
fxBibTexte('bib_v4_ajax_title_assign'),
$info,$status
);
@ -516,11 +524,11 @@ if ($action == 'reset_preview') {
$html = renderBibView(
$epr_id,
0,
'fr',
$strLangue,
'reset',
$participants,
'Prévisualisation de la réinitialisation',
count($participants) . ' dossards seront retirés',
fxBibTexte('bib_v4_ajax_title_reset_preview'),
fxBibMsg('bib_v4_ajax_reset_preview_count', count($participants)),
'warning'
);
@ -567,11 +575,11 @@ if ($action == 'reset_apply') {
$html = renderBibView(
$epr_id,
0,
'fr',
$strLangue,
'reset',
$participants,
'Réinitialisation terminée',
$count . ' dossards retirés',
fxBibTexte('bib_v4_ajax_title_reset_done'),
fxBibMsg('bib_v4_ajax_reset_done_count', $count),
'success'
);
@ -594,7 +602,7 @@ if ($action == 'save_team_mode') {
echo json_encode([
'success' => false,
'message' => 'Paramètres invalides'
'message' => fxBibMsg('bib_v4_ajax_params_invalid')
]);
exit;
@ -625,7 +633,7 @@ if ($action == 'save_auto_config') {
if (!fxBibRequirePromoteurSession()) {
echo json_encode([
'success' => false,
'message' => 'Session invalide'
'message' => fxBibMsg('bib_v4_ajax_session_invalid')
]);
exit;
}
@ -633,7 +641,7 @@ if ($action == 'save_auto_config') {
if (!fxBibValidateCsrf($_POST['csrf_token'] ?? '')) {
echo json_encode([
'success' => false,
'message' => 'Requête non autorisée'
'message' => fxBibMsg('bib_v4_ajax_unauthorized')
]);
exit;
}
@ -645,7 +653,7 @@ if ($action == 'save_auto_config') {
if ($epr_id <= 0) {
echo json_encode([
'success' => false,
'message' => 'epr_id invalide'
'message' => fxBibMsg('bib_v4_ajax_epr_invalid')
]);
exit;
}
@ -655,7 +663,7 @@ if ($action == 'save_auto_config') {
if (!$result['success']) {
echo json_encode([
'success' => false,
'message' => $result['message'] ?? 'Erreur'
'message' => $result['message'] ?? fxBibMsg('bib_v4_ajax_error')
]);
exit;
}
@ -675,6 +683,6 @@ if ($action == 'save_auto_config') {
// =====================
echo json_encode([
'success' => false,
'message' => 'Action invalide'
'message' => fxBibMsg('bib_v4_ajax_action_invalid')
]);
exit;

View File

@ -1966,6 +1966,11 @@ if ($strLangue == 'fr') {
if (moduleBib) {
function bibAjaxLangSuffix() {
var lang = moduleBib.dataset.lang || 'fr';
return '&lang=' + encodeURIComponent(lang);
}
// MSIN-4379 — Réduire / développer les blocs gestion et assignation (en-tête seul visible).
moduleBib.addEventListener('click', function (e) {
let btnToggle = e.target.closest('.epr-block-toggle');
@ -2197,6 +2202,7 @@ if ($strLangue == 'fr') {
'action=refresh_ranges'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&mode=assign'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -2238,6 +2244,7 @@ if ($strLangue == 'fr') {
'action=refresh_ranges'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&mode=auto'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -2334,7 +2341,7 @@ if ($strLangue == 'fr') {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=batch_analysis&epr_id=' + encodeURIComponent(row.dataset.eprId)
body: 'action=batch_analysis&epr_id=' + encodeURIComponent(row.dataset.eprId) + bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -2412,6 +2419,7 @@ if ($strLangue == 'fr') {
'action=save_team_mode'
+ '&epr_id=' + encodeURIComponent(box.dataset.eprId)
+ '&team_mode=' + encodeURIComponent(teamRadio.value)
+ bibAjaxLangSuffix()
});
return;
@ -2455,6 +2463,7 @@ if ($strLangue == 'fr') {
'action=refresh_ranges'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&mode=' + encodeURIComponent(row.dataset.mode || 'assign')
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -2554,7 +2563,7 @@ if ($strLangue == 'fr') {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=delete&id=' + encodeURIComponent(id)
body: 'action=delete&id=' + encodeURIComponent(id) + bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
@ -2629,6 +2638,7 @@ if ($strLangue == 'fr') {
+ '&epr_id=' + encodeURIComponent(epr_id)
+ '&start=' + encodeURIComponent(start)
+ '&end=' + encodeURIComponent(end)
+ bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
@ -2695,6 +2705,7 @@ if ($strLangue == 'fr') {
'action=view'
+ '&epr_id=' + encodeURIComponent(epr_id)
+ '&range_id=' + encodeURIComponent(range_id)
+ bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
@ -2852,6 +2863,7 @@ if ($strLangue == 'fr') {
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
+ '&ba_id=' + encodeURIComponent(ba_id)
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -2952,6 +2964,7 @@ if ($strLangue == 'fr') {
'action=refresh_ranges'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&mode=reset'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -3015,6 +3028,7 @@ if ($strLangue == 'fr') {
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
+ '&ba_id=' + encodeURIComponent(ba_id)
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -3074,6 +3088,7 @@ if ($strLangue == 'fr') {
'action=refresh_ranges'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&mode=assign'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(refresh => {
@ -3090,6 +3105,7 @@ if ($strLangue == 'fr') {
body:
'action=batch_analysis'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(stats => {
@ -3145,6 +3161,7 @@ if ($strLangue == 'fr') {
+ '&active=1'
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
+ '&csrf_token=' + encodeURIComponent(bibCsrfToken())
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -3198,6 +3215,7 @@ if ($strLangue == 'fr') {
+ '&active=0'
+ '&ranges=' + encodeURIComponent('[]')
+ '&csrf_token=' + encodeURIComponent(bibCsrfToken())
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
@ -3257,7 +3275,7 @@ if ($strLangue == 'fr') {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=create&epr_id=' + encodeURIComponent(epr_id)
body: 'action=create&epr_id=' + encodeURIComponent(epr_id) + bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {

View File

@ -2766,6 +2766,15 @@ function fxBibTexte($clef, $mem_echo = 0, $strFallback = '', $blnAllowEmptyLabel
return $str;
}
/** Message bib v4 avec placeholders sprintf (%d, %s…) — AJAX et vues dynamiques. */
function fxBibMsg($clef, ...$args) {
$str = fxBibTexte($clef, 0);
if (!empty($args)) {
return vsprintf($str, $args);
}
return $str;
}
/** Texte d'aide long bib v4 — même règle que fxBibTexte pour l'auto-création. */
function fxBibAide($clef, $mem_echo = 0) {
$row = fxBibGetInfoRow($clef);
@ -3199,7 +3208,7 @@ function fxShowBibTool4($str_code, $int_eve_id, $strLangue){
<h2><?php afficheTexte('promoteur_bib_tool')?></h2>
</div>
<div id="module-bib" class="epr-wrapper" data-csrf-token="<?php echo fxBibEsc(fxBibCsrfToken()); ?>"<?php echo fxAdminTextEditModeActive() ? ' data-bib-trad="1"' : ''; ?>>
<div id="module-bib" class="epr-wrapper" data-csrf-token="<?php echo fxBibEsc(fxBibCsrfToken()); ?>" data-lang="<?php echo fxBibEsc($strLangue); ?>"<?php echo fxAdminTextEditModeActive() ? ' data-bib-trad="1"' : ''; ?>>
<?php for($i = 1; $i <= count($tabEpreuves); $i++){ ?>
@ -3530,7 +3539,7 @@ function fxSaveBibAutoConfig($epr_id, $ranges, $active = true) {
$active = (bool)$active;
if ($epr_id <= 0) {
return ['success' => false, 'message' => 'epr_id invalide'];
return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_epr_invalid')];
}
$objDatabase->fxQuery("
@ -3544,13 +3553,13 @@ function fxSaveBibAutoConfig($epr_id, $ranges, $active = true) {
}
if (empty($ranges) || !is_array($ranges)) {
return ['success' => false, 'message' => 'Aucune séquence sélectionnée'];
return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_no_seq_selected')];
}
$ids = array_values(array_filter(array_map('intval', $ranges)));
if (empty($ids)) {
return ['success' => false, 'message' => 'Aucune séquence sélectionnée'];
return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_no_seq_selected')];
}
$strIds = implode(',', $ids);
@ -3564,7 +3573,7 @@ function fxSaveBibAutoConfig($epr_id, $ranges, $active = true) {
$nbValid = (int)$objDatabase->fxGetVar($sqlCheck);
if ($nbValid !== count($ids)) {
return ['success' => false, 'message' => 'Séquences invalides pour cette épreuve'];
return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_seq_invalid')];
}
$objDatabase->fxQuery("

View File

@ -0,0 +1,181 @@
-- MSIN-4379 — Étape 4 / i18n bib v4 — messages AJAX (ajax_bib_range.php)
-- Aucun DELETE. N'écrase pas les entrées existantes.
-- %d = entiers dans les messages dynamiques (sprintf côté PHP).
-- Erreurs générales
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_epr_invalid', 'fr', 'Identifiant d''épreuve invalide', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_epr_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_epr_invalid', 'en', 'Invalid race id', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_epr_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_id_invalid', 'fr', 'Identifiant invalide', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_id_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_id_invalid', 'en', 'Invalid id', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_id_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_range_not_found', 'fr', 'Séquence introuvable', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_range_not_found' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_range_not_found', 'en', 'Sequence not found', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_range_not_found' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_delete_used', 'fr', 'Impossible de supprimer : des dossards sont déjà utilisés dans cette séquence', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_delete_used' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_delete_used', 'en', 'Cannot delete: bibs are already in use in this sequence', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_delete_used' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_values_invalid', 'fr', 'Valeurs invalides', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_values_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_values_invalid', 'en', 'Invalid values', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_values_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_start_gt_end', 'fr', 'Le début doit être inférieur à la fin', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_start_gt_end' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_start_gt_end', 'en', 'Start must be less than end', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_start_gt_end' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_orphans', 'fr', 'Modification impossible : des dossards sortiraient de la séquence', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_orphans' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_orphans', 'en', 'Cannot update: some bibs would fall outside the sequence', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_orphans' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_overlap', 'fr', 'Conflit avec une autre séquence de dossards', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_overlap' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_overlap', 'en', 'Conflict with another bib sequence', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_overlap' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_params_invalid', 'fr', 'Paramètres invalides', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_params_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_params_invalid', 'en', 'Invalid parameters', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_params_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_session_invalid', 'fr', 'Session invalide', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_session_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_session_invalid', 'en', 'Invalid session', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_session_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_unauthorized', 'fr', 'Requête non autorisée', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_unauthorized' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_unauthorized', 'en', 'Unauthorized request', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_unauthorized' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_error', 'fr', 'Erreur', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_error' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_error', 'en', 'Error', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_error' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_action_invalid', 'fr', 'Action invalide', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_action_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_action_invalid', 'en', 'Invalid action', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_action_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_no_seq_selected', 'fr', 'Aucune séquence sélectionnée', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_no_seq_selected' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_no_seq_selected', 'en', 'No sequence selected', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_no_seq_selected' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_seq_invalid', 'fr', 'Séquences invalides pour cette épreuve', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_seq_invalid' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_seq_invalid', 'en', 'Invalid sequences for this race', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_seq_invalid' AND info_langue = 'en' AND info_prg = 'compte.php');
-- Titres vues batch / reset
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_simulation', 'fr', 'Résultats de la simulation', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_simulation' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_simulation', 'en', 'Simulation results', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_simulation' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_assign', 'fr', 'Résultats de l''assignation', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_assign' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_assign', 'en', 'Assignment results', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_assign' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_reset_preview', 'fr', 'Prévisualisation de la réinitialisation', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_reset_preview' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_reset_preview', 'en', 'Reset preview', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_reset_preview' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_reset_done', 'fr', 'Réinitialisation terminée', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_reset_done' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_title_reset_done', 'en', 'Reset completed', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_reset_done' AND info_langue = 'en' AND info_prg = 'compte.php');
-- Messages dynamiques (%d)
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_sim_summary', 'fr', '%d disponibles / %d à assigner → manque %d', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_sim_summary' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_sim_summary', 'en', '%d available / %d to assign → short %d', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_sim_summary' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_assign_none', 'fr', 'Aucun dossard n''a pu être assigné.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_assign_none' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_assign_none', 'en', 'No bib could be assigned.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_assign_none' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_assign_full', 'fr', 'Assignation complétée : %d dossards assignés avec succès.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_assign_full' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_assign_full', 'en', 'Assignment complete: %d bibs assigned successfully.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_assign_full' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_assign_partial', 'fr', 'Assignation partielle : %d dossards assignés. %d participants restent à assigner.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_assign_partial' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_assign_partial', 'en', 'Partial assignment: %d bibs assigned. %d participants still unassigned.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_assign_partial' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_reset_preview_count', 'fr', '%d dossards seront retirés', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_reset_preview_count' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_reset_preview_count', 'en', '%d bibs will be removed', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_reset_preview_count' AND info_langue = 'en' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_reset_done_count', 'fr', '%d dossards retirés', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_reset_done_count' AND info_langue = 'fr' AND info_prg = 'compte.php');
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
SELECT 'bib_v4_ajax_reset_done_count', 'en', '%d bibs removed', '', 'compte.php', '', 0, 1, '', '', '', NOW()
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_reset_done_count' AND info_langue = 'en' AND info_prg = 'compte.php');