// ── Internationalisation ─────────────────────────────────────────────────────── // Depends on api.js (getLang) const TRANSLATIONS = { en: { // ── Navigation ── 'nav.dashboard': 'Dashboard', 'nav.gear': 'My Gear', 'nav.reloads': 'My Reloads', 'nav.tools': 'Tools', 'nav.photos': 'Photos', 'nav.sessions': 'Sessions', 'nav.profile': 'Profile', 'nav.signout': 'Sign out', 'nav.signin': 'Sign in', 'nav.register': 'Register', 'nav.admin': 'Admin', // ── Index ── 'index.lead': 'Your all-in-one platform to manage your firearms & gear, log and analyse your shooting performance, develop custom reloads, and share your results with other shooters.', 'index.cta': 'Get started free', 'index.cta2': 'Explore tools', 'index.cta3': 'Ready to elevate your shooting?', 'index.cta4': 'Create your account', 'index.feat.title': 'Everything a serious shooter needs', 'index.feat.sub': 'From the first round to competition-level analysis.', 'index.feat.gear.title': 'Gear Inventory', 'index.feat.gear.desc': 'Catalogue every firearm, scope, suppressor, bipod and magazine you own. Build custom rigs and share them publicly.', 'index.feat.sessions.title': 'Session Logging', 'index.feat.sessions.desc': 'Log every shooting session with chrono data, shot groups, weather conditions and notes in one place.', 'index.feat.analysis.title': 'Performance Analysis', 'index.feat.analysis.desc': 'Visualise velocity SD, ES, group sizes over time and identify trends in your shooting performance.', 'index.feat.reload.title': 'Reload Development', 'index.feat.reload.desc': 'Build load recipes, vary powder charge across batches, link each batch to shot groups and find the most accurate charge.', 'index.recent.title': 'Recent Analyses', 'index.recent.subtitle': 'Publicly shared chronograph sessions — no account required to view.', 'index.recent.upload': 'Upload your own', 'index.recent.empty': 'No analyses uploaded yet. Be the first!', // ── Dashboard ── 'dash.title': 'Dashboard', 'dash.welcome': 'Welcome back!', 'dash.welcome.name': 'Welcome back, {name}!', 'dash.stat.gear': 'Gear items', 'dash.stat.rigs': 'Rigs', 'dash.stat.recipes': 'Load recipes', 'dash.stat.batches': 'Ammo batches', 'dash.quicklinks': 'Quick links', 'dash.quicklink.gears': 'Manage gears & rigs', 'dash.quicklink.reloads': 'Reload development', 'dash.quicklink.sessions': 'Shooting sessions', 'dash.quicklink.chrono': 'Chronograph analyses', 'dash.quicklink.profile': 'My profile', 'profile.link.analyses': 'My analyses', 'profile.link.sessions': 'My sessions', 'profile.link.photos': 'My photos', 'profile.link.gears': 'My gears', // ── Gear page ── 'gear.title': 'Gears & Rigs', 'gear.tab.inv': 'My Inventory', 'gear.tab.rigs': 'My Rigs', 'gear.my.gear': 'My gear', 'gear.add': 'Add gear', 'gear.my.rigs': 'My rigs', 'gear.new.rig': 'New rig', 'gear.empty.inv': "You haven't added any gear yet.", 'gear.empty.rigs': "You haven't created any rig yet.", // ── Reloads page ── 'reload.title': 'Reload Development', 'reload.recipes': 'Recipes', 'reload.no.sel': 'Select a recipe to view its batches', // ── Profile page ── 'profile.title': 'My Profile', 'profile.tab.prof': 'Profile', 'profile.tab.pw': 'Change password', 'profile.avatar.upload': 'Upload avatar', 'profile.personal.title': 'Personal information', 'profile.form.first_name': 'First name', 'profile.form.last_name': 'Last name', 'profile.form.email': 'Email', 'profile.form.email.ro': '(read-only)', 'profile.form.save': 'Save changes', 'profile.pw.title': 'Change password', 'profile.form.pw.current': 'Current password', 'profile.form.pw.new': 'New password', 'profile.form.pw.confirm': 'Confirm new password', 'profile.form.pw.change': 'Change password', 'profile.rigs.title': 'My rigs', 'profile.rigs.empty': 'You have no rigs yet.', 'profile.table.name': 'Name', 'profile.table.items': 'Items', 'profile.table.visibility': 'Visibility', // ── Admin page ── 'admin.title': 'Administration', 'admin.tab.users': 'Users', 'admin.tab.catalog': 'Gear catalog', 'admin.tab.comps': 'Reload components', 'admin.tab.calibers': 'Calibers', 'admin.add.gear': 'Add gear item', 'admin.users.new': 'New user', 'admin.users.create.title': 'Create new user', 'admin.users.username': 'Username', 'admin.users.email': 'Email', 'admin.users.password': 'Password', 'admin.users.staff': 'Staff / Admin', 'admin.users.first_name': 'First name', 'admin.users.last_name': 'Last name', 'admin.users.create.btn': 'Create user', 'admin.table.username': 'Username', 'admin.table.email': 'Email', 'admin.table.name': 'Name', 'admin.table.staff': 'Staff', 'admin.table.active': 'Active', 'admin.table.joined': 'Joined', 'admin.filter.all_types': 'All types', 'admin.filter.firearms': 'Firearms', 'admin.filter.scopes': 'Scopes', 'admin.filter.suppressors': 'Suppressors', 'admin.filter.bipods': 'Bipods', 'admin.filter.magazines': 'Magazines', 'admin.filter.all_statuses': 'All statuses', 'admin.filter.pending': 'Pending', 'admin.filter.verified': 'Verified', 'admin.filter.rejected': 'Rejected', 'admin.catalog.col.type': 'Type', 'admin.catalog.col.brand': 'Brand', 'admin.catalog.col.model': 'Model', 'admin.catalog.col.caliber': 'Caliber', 'admin.catalog.col.status': 'Status', 'admin.add.btn': 'Add to catalog', 'admin.comp.primers': 'Primers', 'admin.comp.brass': 'Brass', 'admin.comp.bullets': 'Bullets', 'admin.comp.powders': 'Powders', // ── Tools page ── 'tools.title': 'Tools', 'tools.subtitle': 'Standalone ballistics and reloading tools — no account required.', 'tools.ballistics.title': 'Ballistics Calculator', 'tools.ballistics.desc': 'Point-mass trajectory — drop, wind drift, corrections in MOA/MRAD. No account required.', 'tools.ballistics.soon': 'Coming soon — trajectory, wind drift and holdover charts.', 'tools.chrono.title': 'Chronograph Analyser', 'tools.chrono.desc': 'Upload a CSV from your chrono — get group detection, SD, ES, velocity charts and a PDF report.', 'tools.open': 'Open', 'tools.groupsize.title': 'Group Size Calculator', 'tools.groupsize.desc': 'Annotate a target photo — measure ES, mean radius and scope correction in mm and MOA.', 'tools.oal.title': 'OAL Calculator', 'tools.oal.soon': 'Coming soon — calculate optimal cartridge overall length.', // ── Sessions page ── 'sessions.title': 'Shooting Sessions', 'sessions.subtitle': 'Prepare and record PRS, free practice, or speed shooting sessions.', 'sessions.soon': 'Coming soon — session logging and analysis will be available here.', 'sessions.milestone': 'Session logging is part of the next milestone. Stay tuned!', 'sessions.tab.prs': 'PRS Match', 'sessions.tab.fp': 'Free Practice', 'sessions.tab.speed': 'Speed Shooting', 'sessions.new': 'New Session', 'sessions.none': 'Select a session or create a new one', 'sessions.empty': 'No sessions yet.', 'sessions.delete.confirm': 'Delete this session and all its data?', 'sessions.meta.competition': 'Competition', 'sessions.meta.category': 'Category', 'sessions.meta.date': 'Date', 'sessions.meta.location': 'Location', 'sessions.meta.rig': 'Rig', 'sessions.meta.ammo': 'Ammo', 'sessions.meta.distance': 'Distance', 'sessions.meta.target': 'Target', 'sessions.meta.rounds': 'Rounds fired', 'sessions.meta.format': 'Format', 'sessions.weather.title': 'Weather conditions', 'sessions.weather.temp': 'Temp (°C)', 'sessions.weather.wind': 'Wind (m/s)', 'sessions.weather.dir': 'Dir (°)', 'sessions.weather.humidity': 'Humidity (%)', 'sessions.weather.pressure': 'Pressure (hPa)', 'sessions.weather.notes': 'Notes', 'sessions.weather.save': 'Save weather', 'sessions.analysis.title': 'Linked analysis', 'sessions.analysis.none': 'No analysis linked.', 'sessions.analysis.link': 'Link analysis', 'sessions.analysis.unlink':'Unlink', 'sessions.analysis.view': 'View in Chronograph', 'sessions.analysis.photos':'Photos from this analysis', 'sessions.stages.title': 'Stages', 'sessions.stages.add': 'Add Stage', 'sessions.stages.none': 'No stages yet. Add the first stage to start planning.', 'sessions.stage.prep': 'Prep', 'sessions.stage.corrections': 'Scope corrections', 'sessions.stage.results': 'Results', 'sessions.stage.target': 'Target', 'sessions.stage.maxtime': 'Max time', 'sessions.stage.shots': 'Shots', 'sessions.stage.notes': 'Notes', 'sessions.stage.computed.elev': 'Computed elev.', 'sessions.stage.computed.wind': 'Computed wind.', 'sessions.stage.actual.elev': 'Actual elev.', 'sessions.stage.actual.wind': 'Actual wind.', 'sessions.stage.hits': 'Hits', 'sessions.stage.score': 'Score', 'sessions.stage.time': 'Time (s)', 'sessions.stage.save.corrections': 'Save', 'sessions.stage.save.results': 'Save results', 'sessions.stage.badge.done': 'Results recorded', 'sessions.stage.badge.pending': 'Pending', 'sessions.create.name': 'Session name', 'sessions.create.date': 'Date', 'sessions.create.location':'Location', 'sessions.create.competition': 'Competition name', 'sessions.create.category':'Category', 'sessions.create.distance':'Distance (m)', 'sessions.create.target': 'Target description', 'sessions.create.format': 'Format', 'sessions.create.rig': 'Rig', 'sessions.create.ammo': 'Ammo', 'sessions.create.ammo.none':'None', 'sessions.create.ammo.factory':'Factory', 'sessions.create.ammo.reload': 'Reloaded batch', 'sessions.create.ammo.suggest': "Can't find your ammo? Suggest it", 'sessions.create.ammo.suggest.note': 'Your suggestion will be visible to all once an admin verifies it.', 'sessions.stage.modal.title': 'Add Stage', 'sessions.stage.modal.order': 'Stage #', 'sessions.stage.modal.position': 'Position', 'sessions.stage.modal.distance': 'Distance (m)', 'sessions.stage.modal.maxtime': 'Max time (s)', 'sessions.stage.modal.shots': 'Shots', 'sessions.stage.modal.tw': 'Target W (cm)', 'sessions.stage.modal.th': 'Target H (cm)', 'sessions.stage.modal.notes': 'Prep notes', // ── Common ── 'btn.save': 'Save', 'btn.cancel': 'Cancel', 'btn.delete': 'Delete', 'btn.add': 'Add', 'btn.edit': 'Edit', 'btn.verify': 'Verify', 'btn.reject': 'Reject', 'btn.search': 'Search', 'btn.submit': 'Submit', }, fr: { 'nav.dashboard': 'Tableau de bord', 'nav.gear': 'Mon équipement', 'nav.reloads': 'Mes rechargements', 'nav.tools': 'Outils', 'nav.photos': 'Photos', 'nav.sessions': 'Sessions', 'nav.profile': 'Profil', 'nav.signout': 'Se déconnecter', 'nav.signin': 'Se connecter', 'nav.register': "S'inscrire", 'nav.admin': 'Administration', 'index.lead': 'Votre plateforme tout-en-un pour gérer vos armes et équipements, journaliser vos performances, développer des rechargements et partager vos résultats.', 'index.cta': 'Commencer gratuitement', 'index.cta2': 'Explorer les outils', 'index.cta3': 'Prêt à améliorer vos performances ?', 'index.cta4': 'Créer votre compte', 'index.feat.title': 'Tout ce dont un tireur sérieux a besoin', 'index.feat.sub': "Du premier tir à l'analyse de niveau compétition.", 'index.feat.gear.title': 'Inventaire équipement', 'index.feat.gear.desc': "Cataloguez chaque arme, lunette, suppresseur, bipied et chargeur que vous possédez. Créez des configurations personnalisées et partagez-les.", 'index.feat.sessions.title': 'Journal de sessions', 'index.feat.sessions.desc': 'Enregistrez chaque session de tir avec les données chrono, groupes de tirs, conditions météo et notes au même endroit.', 'index.feat.analysis.title': 'Analyse de performance', 'index.feat.analysis.desc': "Visualisez l'écart-type de vitesse, l'écart extrême, la taille des groupes dans le temps et identifiez vos tendances.", 'index.feat.reload.title': 'Développement de charges', 'index.feat.reload.desc': "Créez des recettes de charge, variez la quantité de poudre entre lots, liez chaque lot à des groupes de tirs et trouvez la charge la plus précise.", 'index.recent.title': 'Analyses récentes', 'index.recent.subtitle': 'Sessions chronographe partagées publiquement — aucun compte requis.', 'index.recent.upload': 'Importer la vôtre', 'index.recent.empty': 'Aucune analyse importée pour l\'instant. Soyez le premier !', 'dash.title': 'Tableau de bord', 'dash.welcome': 'Bon retour !', 'dash.welcome.name': 'Bon retour, {name} !', 'dash.stat.gear': 'Équipements', 'dash.stat.rigs': 'Configurations', 'dash.stat.recipes': 'Recettes de charge', 'dash.stat.batches': 'Lots de munitions', 'dash.quicklinks': 'Accès rapide', 'dash.quicklink.gears': 'Gérer équipements & configs', 'dash.quicklink.reloads': 'Développement de charges', 'dash.quicklink.sessions': 'Sessions de tir', 'dash.quicklink.chrono': 'Analyses chronographe', 'dash.quicklink.profile': 'Mon profil', 'profile.link.analyses': 'Mes analyses', 'profile.link.sessions': 'Mes sessions', 'profile.link.photos': 'Mes photos', 'profile.link.gears': 'Mes équipements', 'gear.title': 'Équipement & Configs', 'gear.tab.inv': 'Mon inventaire', 'gear.tab.rigs': 'Mes configs', 'gear.my.gear': 'Mon équipement', 'gear.add': 'Ajouter équipement', 'gear.my.rigs': 'Mes configurations', 'gear.new.rig': 'Nouvelle config', 'gear.empty.inv': "Vous n'avez pas encore ajouté d'équipement.", 'gear.empty.rigs': "Vous n'avez pas encore créé de configuration.", 'reload.title': 'Développement de charges', 'reload.recipes': 'Recettes', 'reload.no.sel': 'Sélectionnez une recette pour voir ses lots', 'profile.title': 'Mon profil', 'profile.tab.prof': 'Profil', 'profile.tab.pw': 'Changer le mot de passe', 'profile.avatar.upload': 'Charger un avatar', 'profile.personal.title': 'Informations personnelles', 'profile.form.first_name': 'Prénom', 'profile.form.last_name': 'Nom de famille', 'profile.form.email': 'E-mail', 'profile.form.email.ro': '(lecture seule)', 'profile.form.save': 'Enregistrer', 'profile.pw.title': 'Changer le mot de passe', 'profile.form.pw.current': 'Mot de passe actuel', 'profile.form.pw.new': 'Nouveau mot de passe', 'profile.form.pw.confirm': 'Confirmer le nouveau mot de passe', 'profile.form.pw.change': 'Changer le mot de passe', 'profile.rigs.title': 'Mes configurations', 'profile.rigs.empty': "Vous n'avez pas encore de configuration.", 'profile.table.name': 'Nom', 'profile.table.items': 'Éléments', 'profile.table.visibility': 'Visibilité', 'admin.title': 'Administration', 'admin.tab.users': 'Utilisateurs', 'admin.tab.catalog': 'Catalogue équipement', 'admin.tab.comps': 'Composants de rechargement', 'admin.tab.calibers': 'Calibres', 'admin.add.gear': 'Ajouter un équipement', 'admin.users.new': 'Nouvel utilisateur', 'admin.users.create.title': 'Créer un nouvel utilisateur', 'admin.users.username': "Nom d'utilisateur", 'admin.users.email': 'E-mail', 'admin.users.password': 'Mot de passe', 'admin.users.staff': 'Personnel / Admin', 'admin.users.first_name': 'Prénom', 'admin.users.last_name': 'Nom de famille', 'admin.users.create.btn': "Créer l'utilisateur", 'admin.table.username': 'Utilisateur', 'admin.table.email': 'E-mail', 'admin.table.name': 'Nom', 'admin.table.staff': 'Personnel', 'admin.table.active': 'Actif', 'admin.table.joined': 'Inscription', 'admin.filter.all_types': 'Tous types', 'admin.filter.firearms': 'Armes à feu', 'admin.filter.scopes': 'Lunettes', 'admin.filter.suppressors': 'Suppresseurs', 'admin.filter.bipods': 'Bipodes', 'admin.filter.magazines': 'Chargeurs', 'admin.filter.all_statuses': 'Tous statuts', 'admin.filter.pending': 'En attente', 'admin.filter.verified': 'Vérifié', 'admin.filter.rejected': 'Rejeté', 'admin.catalog.col.type': 'Type', 'admin.catalog.col.brand': 'Marque', 'admin.catalog.col.model': 'Modèle', 'admin.catalog.col.caliber': 'Calibre', 'admin.catalog.col.status': 'Statut', 'admin.add.btn': 'Ajouter au catalogue', 'admin.comp.primers': 'Amorces', 'admin.comp.brass': 'Douilles', 'admin.comp.bullets': 'Projectiles', 'admin.comp.powders': 'Poudres', 'tools.title': 'Outils', 'tools.subtitle': 'Outils balistiques et de rechargement — aucun compte requis.', 'tools.ballistics.title': 'Calculateur balistique', 'tools.ballistics.desc': 'Trajectoire point-masse — chute, dérive au vent, corrections MOA/MRAD. Sans compte.', 'tools.ballistics.soon': 'Bientôt — courbes de trajectoire, dérive au vent et compensations.', 'tools.chrono.title': 'Analyseur chronographe', 'tools.chrono.desc': 'Importez un CSV de votre chrono — détection de groupes, ET, ES, courbes de vitesse et rapport PDF.', 'tools.open': 'Ouvrir', 'tools.groupsize.title': 'Calculateur de groupe', 'tools.groupsize.desc': 'Annotez une photo de cible — mesurez l\'ES, le rayon moyen et la correction lunette en mm et MOA.', 'tools.oal.title': 'Calculateur OAL', 'tools.oal.soon': 'Bientôt — calculez la longueur totale optimale de la cartouche.', 'sessions.title': 'Sessions de tir', 'sessions.subtitle': 'Préparez et enregistrez vos sessions PRS, entraînement libre ou tir de vitesse.', 'sessions.soon': "Bientôt disponible — l'enregistrement et l'analyse des sessions seront disponibles ici.", 'sessions.milestone': "L'enregistrement des sessions fait partie du prochain jalon. Restez à l'écoute !", 'sessions.tab.prs': 'Match PRS', 'sessions.tab.fp': 'Entraînement libre', 'sessions.tab.speed': 'Tir de vitesse', 'sessions.new': 'Nouvelle session', 'sessions.none': 'Sélectionnez une session ou créez-en une nouvelle', 'sessions.empty': 'Aucune session.', 'sessions.delete.confirm': 'Supprimer cette session et toutes ses données ?', 'sessions.meta.competition': 'Compétition', 'sessions.meta.category': 'Catégorie', 'sessions.meta.date': 'Date', 'sessions.meta.location': 'Lieu', 'sessions.meta.rig': 'Configuration', 'sessions.meta.ammo': 'Munitions', 'sessions.meta.distance': 'Distance', 'sessions.meta.target': 'Cible', 'sessions.meta.rounds': 'Cartouches tirées', 'sessions.meta.format': 'Format', 'sessions.weather.title': 'Conditions météo', 'sessions.weather.temp': 'Temp (°C)', 'sessions.weather.wind': 'Vent (m/s)', 'sessions.weather.dir': 'Dir (°)', 'sessions.weather.humidity': 'Humidité (%)', 'sessions.weather.pressure': 'Pression (hPa)', 'sessions.weather.notes': 'Notes', 'sessions.weather.save': 'Enregistrer météo', 'sessions.analysis.title': 'Analyse liée', 'sessions.analysis.none': 'Aucune analyse liée.', 'sessions.analysis.link': 'Lier une analyse', 'sessions.analysis.unlink':'Délier', 'sessions.analysis.view': 'Voir dans le chronographe', 'sessions.analysis.photos':'Photos de cette analyse', 'sessions.stages.title': 'Stands', 'sessions.stages.add': 'Ajouter un stand', 'sessions.stages.none': 'Aucun stand. Ajoutez le premier pour commencer la préparation.', 'sessions.stage.prep': 'Préparation', 'sessions.stage.corrections': 'Corrections lunette', 'sessions.stage.results': 'Résultats', 'sessions.stage.target': 'Cible', 'sessions.stage.maxtime': 'Temps max', 'sessions.stage.shots': 'Tirs', 'sessions.stage.notes': 'Notes', 'sessions.stage.computed.elev': 'Élév. calculée', 'sessions.stage.computed.wind': 'Dérive calculée', 'sessions.stage.actual.elev': 'Élév. réelle', 'sessions.stage.actual.wind': 'Dérive réelle', 'sessions.stage.hits': 'Touches', 'sessions.stage.score': 'Score', 'sessions.stage.time': 'Temps (s)', 'sessions.stage.save.corrections': 'Enregistrer', 'sessions.stage.save.results': 'Enregistrer résultats', 'sessions.stage.badge.done': 'Résultats enregistrés', 'sessions.stage.badge.pending': 'En attente', 'sessions.create.name': 'Nom de la session', 'sessions.create.date': 'Date', 'sessions.create.location':'Lieu', 'sessions.create.competition': 'Nom de la compétition', 'sessions.create.category':'Catégorie', 'sessions.create.distance':'Distance (m)', 'sessions.create.target': 'Description de la cible', 'sessions.create.format': 'Format', 'sessions.create.rig': 'Configuration', 'sessions.create.ammo': 'Munitions', 'sessions.create.ammo.none':'Aucune', 'sessions.create.ammo.factory':'Industrielles', 'sessions.create.ammo.reload': 'Lot rechargé', 'sessions.create.ammo.suggest': 'Munitions introuvables ? Suggérez-les', 'sessions.create.ammo.suggest.note': 'Votre suggestion sera visible de tous après vérification par un administrateur.', 'sessions.stage.modal.title': 'Ajouter un stand', 'sessions.stage.modal.order': 'Stand n°', 'sessions.stage.modal.position': 'Position', 'sessions.stage.modal.distance': 'Distance (m)', 'sessions.stage.modal.maxtime': 'Temps max (s)', 'sessions.stage.modal.shots': 'Tirs', 'sessions.stage.modal.tw': 'Largeur cible (cm)', 'sessions.stage.modal.th': 'Hauteur cible (cm)', 'sessions.stage.modal.notes': 'Notes de préparation', 'btn.save': 'Enregistrer', 'btn.cancel': 'Annuler', 'btn.delete': 'Supprimer', 'btn.add': 'Ajouter', 'btn.edit': 'Modifier', 'btn.verify': 'Vérifier', 'btn.reject': 'Rejeter', 'btn.search': 'Rechercher', 'btn.submit': 'Soumettre', }, de: { 'nav.dashboard': 'Übersicht', 'nav.gear': 'Mein Equipment', 'nav.reloads': 'Meine Ladungen', 'nav.tools': 'Werkzeuge', 'nav.photos': 'Fotos', 'nav.sessions': 'Sessions', 'nav.profile': 'Profil', 'nav.signout': 'Abmelden', 'nav.signin': 'Anmelden', 'nav.register': 'Registrieren', 'nav.admin': 'Administration', 'index.lead': 'Ihre Rundum-Plattform zur Verwaltung von Waffen und Ausrüstung, Protokollierung von Schießleistungen, Ladungsentwicklung und Teilen Ihrer Ergebnisse.', 'index.cta': 'Kostenlos starten', 'index.cta2': 'Tools entdecken', 'index.cta3': 'Bereit, Ihr Schießen zu verbessern?', 'index.cta4': 'Konto erstellen', 'index.feat.title': 'Alles, was ein ernsthafter Schütze braucht', 'index.feat.sub': 'Vom ersten Schuss bis zur Wettkampfanalyse.', 'index.feat.gear.title': 'Ausrüstungsinventar', 'index.feat.gear.desc': 'Katalogisieren Sie jede Waffe, jedes Zielfernrohr, jeden Schalldämpfer, jedes Zweibein und jedes Magazin. Erstellen und teilen Sie Konfigurationen.', 'index.feat.sessions.title': 'Session-Protokoll', 'index.feat.sessions.desc': 'Protokollieren Sie jede Schießsitzung mit Chronodaten, Gruppen, Wetterbedingungen und Notizen an einem Ort.', 'index.feat.analysis.title': 'Leistungsanalyse', 'index.feat.analysis.desc': 'Visualisieren Sie Geschwindigkeits-SD, ES, Gruppengrößen über Zeit und erkennen Sie Trends in Ihrer Schießleistung.', 'index.feat.reload.title': 'Ladungsentwicklung', 'index.feat.reload.desc': 'Erstellen Sie Ladungsrezepte, variieren Sie die Pulvermenge, verknüpfen Sie Chargen mit Schussgruppen und finden Sie die genaueste Ladung.', 'index.recent.title': 'Aktuelle Analysen', 'index.recent.subtitle': 'Öffentlich geteilte Chronographen-Sitzungen — kein Konto zum Ansehen erforderlich.', 'index.recent.upload': 'Eigene hochladen', 'index.recent.empty': 'Noch keine Analysen hochgeladen. Seien Sie der Erste!', 'dash.title': 'Übersicht', 'dash.welcome': 'Willkommen zurück!', 'dash.welcome.name': 'Willkommen zurück, {name}!', 'dash.stat.gear': 'Ausrüstung', 'dash.stat.rigs': 'Konfigurationen', 'dash.stat.recipes': 'Ladungsrezepte', 'dash.stat.batches': 'Munitionschargen', 'dash.quicklinks': 'Schnellzugriff', 'dash.quicklink.gears': 'Ausrüstung & Konfigurationen', 'dash.quicklink.reloads': 'Ladungsentwicklung', 'dash.quicklink.sessions': 'Schießsitzungen', 'dash.quicklink.chrono': 'Chronographenanalysen', 'dash.quicklink.profile': 'Mein Profil', 'profile.link.analyses': 'Meine Analysen', 'profile.link.sessions': 'Meine Sitzungen', 'profile.link.photos': 'Meine Fotos', 'profile.link.gears': 'Meine Ausrüstung', 'gear.title': 'Ausrüstung & Konfigurationen', 'gear.tab.inv': 'Mein Inventar', 'gear.tab.rigs': 'Meine Konfigs', 'gear.my.gear': 'Meine Ausrüstung', 'gear.add': 'Ausrüstung hinzufügen', 'gear.my.rigs': 'Meine Konfigurationen', 'gear.new.rig': 'Neue Konfiguration', 'gear.empty.inv': 'Sie haben noch keine Ausrüstung hinzugefügt.', 'gear.empty.rigs': 'Sie haben noch keine Konfiguration erstellt.', 'reload.title': 'Ladungsentwicklung', 'reload.recipes': 'Rezepte', 'reload.no.sel': 'Wählen Sie ein Rezept aus, um die Chargen anzuzeigen', 'profile.title': 'Mein Profil', 'profile.tab.prof': 'Profil', 'profile.tab.pw': 'Passwort ändern', 'profile.avatar.upload': 'Avatar hochladen', 'profile.personal.title': 'Persönliche Angaben', 'profile.form.first_name': 'Vorname', 'profile.form.last_name': 'Nachname', 'profile.form.email': 'E-Mail', 'profile.form.email.ro': '(schreibgeschützt)', 'profile.form.save': 'Speichern', 'profile.pw.title': 'Passwort ändern', 'profile.form.pw.current': 'Aktuelles Passwort', 'profile.form.pw.new': 'Neues Passwort', 'profile.form.pw.confirm': 'Neues Passwort bestätigen', 'profile.form.pw.change': 'Passwort ändern', 'profile.rigs.title': 'Meine Konfigurationen', 'profile.rigs.empty': 'Sie haben noch keine Konfigurationen.', 'profile.table.name': 'Name', 'profile.table.items': 'Elemente', 'profile.table.visibility': 'Sichtbarkeit', 'admin.title': 'Administration', 'admin.tab.users': 'Benutzer', 'admin.tab.catalog': 'Ausrüstungskatalog', 'admin.tab.comps': 'Ladekomponenten', 'admin.tab.calibers': 'Kaliber', 'admin.add.gear': 'Ausrüstung hinzufügen', 'admin.users.new': 'Neuer Benutzer', 'admin.users.create.title': 'Neuen Benutzer erstellen', 'admin.users.username': 'Benutzername', 'admin.users.email': 'E-Mail', 'admin.users.password': 'Passwort', 'admin.users.staff': 'Mitarbeiter / Admin', 'admin.users.first_name': 'Vorname', 'admin.users.last_name': 'Nachname', 'admin.users.create.btn': 'Benutzer erstellen', 'admin.table.username': 'Benutzername', 'admin.table.email': 'E-Mail', 'admin.table.name': 'Name', 'admin.table.staff': 'Mitarbeiter', 'admin.table.active': 'Aktiv', 'admin.table.joined': 'Beigetreten', 'admin.filter.all_types': 'Alle Typen', 'admin.filter.firearms': 'Schusswaffen', 'admin.filter.scopes': 'Zielfernrohre', 'admin.filter.suppressors': 'Schalldämpfer', 'admin.filter.bipods': 'Zweibeine', 'admin.filter.magazines': 'Magazine', 'admin.filter.all_statuses': 'Alle Status', 'admin.filter.pending': 'Ausstehend', 'admin.filter.verified': 'Bestätigt', 'admin.filter.rejected': 'Abgelehnt', 'admin.catalog.col.type': 'Typ', 'admin.catalog.col.brand': 'Marke', 'admin.catalog.col.model': 'Modell', 'admin.catalog.col.caliber': 'Kaliber', 'admin.catalog.col.status': 'Status', 'admin.add.btn': 'Zum Katalog hinzufügen', 'admin.comp.primers': 'Zündhütchen', 'admin.comp.brass': 'Hülsen', 'admin.comp.bullets': 'Geschosse', 'admin.comp.powders': 'Pulver', 'tools.title': 'Werkzeuge', 'tools.subtitle': 'Ballistische Werkzeuge und Ladewerkzeuge — kein Konto erforderlich.', 'tools.ballistics.title': 'Ballistikrechner', 'tools.ballistics.desc': 'Punktmasse-Trajektorie — Abfall, Windabdrift, Korrekturen in MOA/MRAD. Ohne Konto.', 'tools.ballistics.soon': 'Demnächst — Flugbahn, Windabdrift und Haltepunktdiagramme.', 'tools.chrono.title': 'Chronograph-Analysator', 'tools.chrono.desc': 'CSV von Ihrem Chrono hochladen — Gruppenerkennung, SD, ES, Geschwindigkeitskurven und PDF-Bericht.', 'tools.open': 'Öffnen', 'tools.groupsize.title': 'Gruppengrößenrechner', 'tools.groupsize.desc': 'Zielscheibenfoto annotieren — ES, mittleren Radius und Richtkorrekturen in mm und MOA messen.', 'tools.oal.title': 'OAL-Rechner', 'tools.oal.soon': 'Demnächst — optimale Gesamtlänge der Patrone berechnen.', 'sessions.title': 'Schießsitzungen', 'sessions.subtitle': 'PRS-, Freiübungs- oder Schnellschießsitzungen vorbereiten und aufzeichnen.', 'sessions.soon': 'Demnächst — Sitzungsprotokoll und Analyse werden hier verfügbar sein.', 'sessions.milestone': 'Die Sitzungsprotokollierung ist Teil des nächsten Meilensteins. Bleiben Sie dran!', 'sessions.tab.prs': 'PRS-Match', 'sessions.tab.fp': 'Freiübung', 'sessions.tab.speed': 'Schnellschießen', 'sessions.new': 'Neue Sitzung', 'sessions.none': 'Sitzung auswählen oder neue erstellen', 'sessions.empty': 'Keine Sitzungen vorhanden.', 'sessions.delete.confirm': 'Diese Sitzung und alle Daten löschen?', 'sessions.meta.competition': 'Wettkampf', 'sessions.meta.category': 'Kategorie', 'sessions.meta.date': 'Datum', 'sessions.meta.location': 'Ort', 'sessions.meta.rig': 'Konfiguration', 'sessions.meta.ammo': 'Munition', 'sessions.meta.distance': 'Entfernung', 'sessions.meta.target': 'Ziel', 'sessions.meta.rounds': 'Abgefeuerte Schüsse', 'sessions.meta.format': 'Format', 'sessions.weather.title': 'Wetterbedingungen', 'sessions.weather.temp': 'Temp (°C)', 'sessions.weather.wind': 'Wind (m/s)', 'sessions.weather.dir': 'Richtung (°)', 'sessions.weather.humidity': 'Luftfeuchtigkeit (%)', 'sessions.weather.pressure': 'Druck (hPa)', 'sessions.weather.notes': 'Notizen', 'sessions.weather.save': 'Wetter speichern', 'sessions.analysis.title': 'Verknüpfte Analyse', 'sessions.analysis.none': 'Keine Analyse verknüpft.', 'sessions.analysis.link': 'Analyse verknüpfen', 'sessions.analysis.unlink':'Verknüpfung lösen', 'sessions.analysis.view': 'Im Chronograph anzeigen', 'sessions.analysis.photos':'Fotos dieser Analyse', 'sessions.stages.title': 'Stände', 'sessions.stages.add': 'Stand hinzufügen', 'sessions.stages.none': 'Noch keine Stände. Ersten Stand hinzufügen.', 'sessions.stage.prep': 'Vorbereitung', 'sessions.stage.corrections': 'Absehenkorrekturen', 'sessions.stage.results': 'Ergebnisse', 'sessions.stage.target': 'Ziel', 'sessions.stage.maxtime': 'Max. Zeit', 'sessions.stage.shots': 'Schüsse', 'sessions.stage.notes': 'Notizen', 'sessions.stage.computed.elev': 'Ber. Höhe', 'sessions.stage.computed.wind': 'Ber. Wind', 'sessions.stage.actual.elev': 'Tats. Höhe', 'sessions.stage.actual.wind': 'Tats. Wind', 'sessions.stage.hits': 'Treffer', 'sessions.stage.score': 'Punkte', 'sessions.stage.time': 'Zeit (s)', 'sessions.stage.save.corrections': 'Speichern', 'sessions.stage.save.results': 'Ergebnisse speichern', 'sessions.stage.badge.done': 'Ergebnisse gespeichert', 'sessions.stage.badge.pending': 'Ausstehend', 'sessions.create.name': 'Sitzungsname', 'sessions.create.date': 'Datum', 'sessions.create.location':'Ort', 'sessions.create.competition': 'Wettkampfname', 'sessions.create.category':'Kategorie', 'sessions.create.distance':'Entfernung (m)', 'sessions.create.target': 'Zielbeschreibung', 'sessions.create.format': 'Format', 'sessions.create.rig': 'Konfiguration', 'sessions.create.ammo': 'Munition', 'sessions.create.ammo.none':'Keine', 'sessions.create.ammo.factory':'Fabrikmunition', 'sessions.create.ammo.reload': 'Wiederladung', 'sessions.create.ammo.suggest': 'Munition nicht gefunden? Vorschlagen', 'sessions.create.ammo.suggest.note': 'Ihr Vorschlag wird nach Admin-Prüfung für alle sichtbar.', 'sessions.stage.modal.title': 'Stand hinzufügen', 'sessions.stage.modal.order': 'Stand-Nr.', 'sessions.stage.modal.position': 'Position', 'sessions.stage.modal.distance': 'Entfernung (m)', 'sessions.stage.modal.maxtime': 'Max. Zeit (s)', 'sessions.stage.modal.shots': 'Schüsse', 'sessions.stage.modal.tw': 'Zielbreite (cm)', 'sessions.stage.modal.th': 'Zielhöhe (cm)', 'sessions.stage.modal.notes': 'Vorbereitungsnotizen', 'btn.save': 'Speichern', 'btn.cancel': 'Abbrechen', 'btn.delete': 'Löschen', 'btn.add': 'Hinzufügen', 'btn.edit': 'Bearbeiten', 'btn.verify': 'Bestätigen', 'btn.reject': 'Ablehnen', 'btn.search': 'Suchen', 'btn.submit': 'Absenden', }, es: { 'nav.dashboard': 'Panel', 'nav.gear': 'Mi equipamiento', 'nav.reloads': 'Mis recargas', 'nav.tools': 'Herramientas', 'nav.photos': 'Fotos', 'nav.sessions': 'Sesiones', 'nav.profile': 'Perfil', 'nav.signout': 'Cerrar sesión', 'nav.signin': 'Iniciar sesión', 'nav.register': 'Registrarse', 'nav.admin': 'Administración', 'index.lead': 'Su plataforma integral para gestionar armas y equipamiento, registrar rendimiento, desarrollar recargas y compartir resultados con otros tiradores.', 'index.cta': 'Empezar gratis', 'index.cta2': 'Explorar herramientas', 'index.cta3': '¿Listo para mejorar su tiro?', 'index.cta4': 'Crear cuenta', 'index.feat.title': 'Todo lo que necesita un tirador serio', 'index.feat.sub': 'Desde el primer disparo hasta el análisis de competición.', 'index.feat.gear.title': 'Inventario de equipamiento', 'index.feat.gear.desc': 'Catalogue cada arma, mira, silenciador, bípode y cargador que posee. Cree configuraciones personalizadas y compártalas.', 'index.feat.sessions.title': 'Registro de sesiones', 'index.feat.sessions.desc': 'Registre cada sesión de tiro con datos de cronógrafo, grupos, condiciones meteorológicas y notas en un solo lugar.', 'index.feat.analysis.title': 'Análisis de rendimiento', 'index.feat.analysis.desc': 'Visualice la desviación típica, el extremo de la serie, tamaño de grupos a lo largo del tiempo e identifique tendencias.', 'index.feat.reload.title': 'Desarrollo de recargas', 'index.feat.reload.desc': 'Cree recetas de carga, varíe la carga de pólvora entre lotes, vincule cada lote a grupos de disparos y encuentre la carga más precisa.', 'index.recent.title': 'Análisis recientes', 'index.recent.subtitle': 'Sesiones de cronógrafo compartidas públicamente — no se requiere cuenta para ver.', 'index.recent.upload': 'Subir la suya', 'index.recent.empty': '¡Aún no hay análisis. Sea el primero!', 'dash.title': 'Panel', 'dash.welcome': '¡Bienvenido de nuevo!', 'dash.welcome.name': '¡Bienvenido de nuevo, {name}!', 'dash.stat.gear': 'Equipamiento', 'dash.stat.rigs': 'Configuraciones', 'dash.stat.recipes': 'Recetas de carga', 'dash.stat.batches': 'Lotes de munición', 'dash.quicklinks': 'Acceso rápido', 'dash.quicklink.gears': 'Gestionar equipamiento y configs', 'dash.quicklink.reloads': 'Desarrollo de recargas', 'dash.quicklink.sessions': 'Sesiones de tiro', 'dash.quicklink.chrono': 'Análisis de cronógrafo', 'dash.quicklink.profile': 'Mi perfil', 'profile.link.analyses': 'Mis análisis', 'profile.link.sessions': 'Mis sesiones', 'profile.link.photos': 'Mis fotos', 'profile.link.gears': 'Mi equipamiento', 'gear.title': 'Equipamiento y configs', 'gear.tab.inv': 'Mi inventario', 'gear.tab.rigs': 'Mis configs', 'gear.my.gear': 'Mi equipamiento', 'gear.add': 'Añadir equipamiento', 'gear.my.rigs': 'Mis configuraciones', 'gear.new.rig': 'Nueva config', 'gear.empty.inv': 'Aún no ha añadido equipamiento.', 'gear.empty.rigs': 'Aún no ha creado ninguna configuración.', 'reload.title': 'Desarrollo de cargas', 'reload.recipes': 'Recetas', 'reload.no.sel': 'Seleccione una receta para ver sus lotes', 'profile.title': 'Mi perfil', 'profile.tab.prof': 'Perfil', 'profile.tab.pw': 'Cambiar contraseña', 'profile.avatar.upload': 'Subir avatar', 'profile.personal.title': 'Información personal', 'profile.form.first_name': 'Nombre', 'profile.form.last_name': 'Apellido', 'profile.form.email': 'Correo electrónico', 'profile.form.email.ro': '(solo lectura)', 'profile.form.save': 'Guardar cambios', 'profile.pw.title': 'Cambiar contraseña', 'profile.form.pw.current': 'Contraseña actual', 'profile.form.pw.new': 'Nueva contraseña', 'profile.form.pw.confirm': 'Confirmar nueva contraseña', 'profile.form.pw.change': 'Cambiar contraseña', 'profile.rigs.title': 'Mis configuraciones', 'profile.rigs.empty': 'Aún no tiene configuraciones.', 'profile.table.name': 'Nombre', 'profile.table.items': 'Elementos', 'profile.table.visibility': 'Visibilidad', 'admin.title': 'Administración', 'admin.tab.users': 'Usuarios', 'admin.tab.catalog': 'Catálogo de equipamiento', 'admin.tab.comps': 'Componentes de recarga', 'admin.tab.calibers': 'Calibres', 'admin.add.gear': 'Añadir equipamiento', 'admin.users.new': 'Nuevo usuario', 'admin.users.create.title': 'Crear nuevo usuario', 'admin.users.username': 'Nombre de usuario', 'admin.users.email': 'Correo electrónico', 'admin.users.password': 'Contraseña', 'admin.users.staff': 'Personal / Admin', 'admin.users.first_name': 'Nombre', 'admin.users.last_name': 'Apellido', 'admin.users.create.btn': 'Crear usuario', 'admin.table.username': 'Usuario', 'admin.table.email': 'Correo', 'admin.table.name': 'Nombre', 'admin.table.staff': 'Personal', 'admin.table.active': 'Activo', 'admin.table.joined': 'Registro', 'admin.filter.all_types': 'Todos los tipos', 'admin.filter.firearms': 'Armas de fuego', 'admin.filter.scopes': 'Miras telescópicas', 'admin.filter.suppressors': 'Silenciadores', 'admin.filter.bipods': 'Bípodes', 'admin.filter.magazines': 'Cargadores', 'admin.filter.all_statuses': 'Todos los estados', 'admin.filter.pending': 'Pendiente', 'admin.filter.verified': 'Verificado', 'admin.filter.rejected': 'Rechazado', 'admin.catalog.col.type': 'Tipo', 'admin.catalog.col.brand': 'Marca', 'admin.catalog.col.model': 'Modelo', 'admin.catalog.col.caliber': 'Calibre', 'admin.catalog.col.status': 'Estado', 'admin.add.btn': 'Añadir al catálogo', 'admin.comp.primers': 'Cebadores', 'admin.comp.brass': 'Vainas', 'admin.comp.bullets': 'Proyectiles', 'admin.comp.powders': 'Pólvoras', 'tools.title': 'Herramientas', 'tools.subtitle': 'Herramientas balísticas y de recarga — no se requiere cuenta.', 'tools.ballistics.title': 'Calculadora balística', 'tools.ballistics.desc': 'Trayectoria de masa puntual — caída, deriva por viento, correcciones MOA/MRAD. Sin cuenta.', 'tools.ballistics.soon': 'Próximamente — trayectorias, deriva por viento y compensaciones.', 'tools.chrono.title': 'Analizador de cronógrafo', 'tools.chrono.desc': 'Suba un CSV de su cronógrafo — detección de grupos, DT, ES, gráficas de velocidad e informe PDF.', 'tools.open': 'Abrir', 'tools.groupsize.title': 'Calculadora de grupo', 'tools.groupsize.desc': 'Anote una foto de blanco — mida ES, radio medio y corrección de mira en mm y MOA.', 'tools.oal.title': 'Calculadora OAL', 'tools.oal.soon': 'Próximamente — calcule la longitud total óptima del cartucho.', 'sessions.title': 'Sesiones de tiro', 'sessions.subtitle': 'Prepare y registre sesiones de PRS, práctica libre o tiro de velocidad.', 'sessions.soon': 'Próximamente — el registro y análisis de sesiones estará disponible aquí.', 'sessions.milestone': 'El registro de sesiones forma parte del próximo hito. ¡Estén atentos!', 'sessions.tab.prs': 'Match PRS', 'sessions.tab.fp': 'Práctica libre', 'sessions.tab.speed': 'Tiro de velocidad', 'sessions.new': 'Nueva sesión', 'sessions.none': 'Seleccione una sesión o cree una nueva', 'sessions.empty': 'Sin sesiones.', 'sessions.delete.confirm': '¿Eliminar esta sesión y todos sus datos?', 'sessions.meta.competition': 'Competición', 'sessions.meta.category': 'Categoría', 'sessions.meta.date': 'Fecha', 'sessions.meta.location': 'Lugar', 'sessions.meta.rig': 'Configuración', 'sessions.meta.ammo': 'Munición', 'sessions.meta.distance': 'Distancia', 'sessions.meta.target': 'Blanco', 'sessions.meta.rounds': 'Disparos realizados', 'sessions.meta.format': 'Formato', 'sessions.weather.title': 'Condiciones meteorológicas', 'sessions.weather.temp': 'Temp (°C)', 'sessions.weather.wind': 'Viento (m/s)', 'sessions.weather.dir': 'Dir (°)', 'sessions.weather.humidity': 'Humedad (%)', 'sessions.weather.pressure': 'Presión (hPa)', 'sessions.weather.notes': 'Notas', 'sessions.weather.save': 'Guardar clima', 'sessions.analysis.title': 'Análisis vinculado', 'sessions.analysis.none': 'Ningún análisis vinculado.', 'sessions.analysis.link': 'Vincular análisis', 'sessions.analysis.unlink':'Desvincular', 'sessions.analysis.view': 'Ver en cronógrafo', 'sessions.analysis.photos':'Fotos de este análisis', 'sessions.stages.title': 'Puestos', 'sessions.stages.add': 'Añadir puesto', 'sessions.stages.none': 'Sin puestos. Añada el primero para empezar.', 'sessions.stage.prep': 'Preparación', 'sessions.stage.corrections': 'Correcciones de mira', 'sessions.stage.results': 'Resultados', 'sessions.stage.target': 'Blanco', 'sessions.stage.maxtime': 'Tiempo máx.', 'sessions.stage.shots': 'Disparos', 'sessions.stage.notes': 'Notas', 'sessions.stage.computed.elev': 'Elev. calculada', 'sessions.stage.computed.wind': 'Deriv. calculada', 'sessions.stage.actual.elev': 'Elev. real', 'sessions.stage.actual.wind': 'Deriv. real', 'sessions.stage.hits': 'Impactos', 'sessions.stage.score': 'Puntuación', 'sessions.stage.time': 'Tiempo (s)', 'sessions.stage.save.corrections': 'Guardar', 'sessions.stage.save.results': 'Guardar resultados', 'sessions.stage.badge.done': 'Resultados registrados', 'sessions.stage.badge.pending': 'Pendiente', 'sessions.create.name': 'Nombre de sesión', 'sessions.create.date': 'Fecha', 'sessions.create.location':'Lugar', 'sessions.create.competition': 'Nombre de competición', 'sessions.create.category':'Categoría', 'sessions.create.distance':'Distancia (m)', 'sessions.create.target': 'Descripción del blanco', 'sessions.create.format': 'Formato', 'sessions.create.rig': 'Configuración', 'sessions.create.ammo': 'Munición', 'sessions.create.ammo.none':'Ninguna', 'sessions.create.ammo.factory':'Comercial', 'sessions.create.ammo.reload': 'Lote recargado', 'sessions.create.ammo.suggest': '¿No encuentra su munición? Sugiérala', 'sessions.create.ammo.suggest.note': 'Su sugerencia será visible para todos tras verificación del administrador.', 'sessions.stage.modal.title': 'Añadir puesto', 'sessions.stage.modal.order': 'Puesto n°', 'sessions.stage.modal.position': 'Posición', 'sessions.stage.modal.distance': 'Distancia (m)', 'sessions.stage.modal.maxtime': 'Tiempo máx. (s)', 'sessions.stage.modal.shots': 'Disparos', 'sessions.stage.modal.tw': 'Ancho blanco (cm)', 'sessions.stage.modal.th': 'Alto blanco (cm)', 'sessions.stage.modal.notes': 'Notas de preparación', 'btn.save': 'Guardar', 'btn.cancel': 'Cancelar', 'btn.delete': 'Eliminar', 'btn.add': 'Añadir', 'btn.edit': 'Editar', 'btn.verify': 'Verificar', 'btn.reject': 'Rechazar', 'btn.search': 'Buscar', 'btn.submit': 'Enviar', }, }; function t(key) { const lang = getLang(); const dict = TRANSLATIONS[lang] || TRANSLATIONS['en']; return dict[key] || TRANSLATIONS['en'][key] || key; } function applyTranslations() { document.querySelectorAll('[data-i18n]').forEach(el => { el.textContent = t(el.dataset.i18n); }); document.querySelectorAll('[data-i18n-placeholder]').forEach(el => { el.placeholder = t(el.dataset.i18nPlaceholder); }); }