From b21cda335d31dd26be48e6614d9716ffd6070045 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Sun, 26 Oct 2025 16:41:54 +1300 Subject: [PATCH] feat(i18n): add multilingual support to case-submission and media-inquiry pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds German and French translations for form submission pages with dynamic message handling and language selector integration. **Pages Updated:** - case-submission.html: Added data-i18n attributes and language selector - media-inquiry.html: Added data-i18n attributes and language selector **Translation Files Created:** - EN/DE/FR for case-submission (form labels, help text, dynamic messages) - EN/DE/FR for media-inquiry (form labels, help text, dynamic messages) **JavaScript Updates:** - case-submission.js: Added i18n translation helper for dynamic content - media-inquiry.js: Added i18n translation helper for dynamic content - Submit buttons and error messages now translate based on selected language **Features:** - Language flags visible in navbar for easy switching - Form labels and help text translate on language change - Submit button text updates during submission ("Submitting..." → "Einreichen..." in DE) - Success/error messages display in user's selected language - All translations via DeepL API for professional quality **Technical Details:** - Uses cache-busting timestamps for translation fetches (prevents stale cache) - Submit buttons use for translatable content - Form JavaScript uses window.i18nTranslations for dynamic text 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- public/case-submission.html | 48 ++++++++++++++------------ public/js/case-submission.js | 23 +++++++++--- public/js/media-inquiry.js | 23 +++++++++--- public/locales/de/case-submission.json | 45 ++++++++++++++++++++++++ public/locales/de/media-inquiry.json | 29 ++++++++++++++++ public/locales/en/case-submission.json | 45 ++++++++++++++++++++++++ public/locales/en/media-inquiry.json | 29 ++++++++++++++++ public/locales/fr/case-submission.json | 45 ++++++++++++++++++++++++ public/locales/fr/media-inquiry.json | 29 ++++++++++++++++ public/media-inquiry.html | 32 +++++++++-------- 10 files changed, 300 insertions(+), 48 deletions(-) create mode 100644 public/locales/de/case-submission.json create mode 100644 public/locales/de/media-inquiry.json create mode 100644 public/locales/en/case-submission.json create mode 100644 public/locales/en/media-inquiry.json create mode 100644 public/locales/fr/case-submission.json create mode 100644 public/locales/fr/media-inquiry.json diff --git a/public/case-submission.html b/public/case-submission.html index a9c9afed..72f96b72 100644 --- a/public/case-submission.html +++ b/public/case-submission.html @@ -1,9 +1,9 @@ - + - Submit Case Study | Tractatus AI Safety + Submit Case Study | Tractatus AI Safety @@ -79,23 +79,24 @@ +
-

Submit Case Study

+

Submit Case Study

Share real-world examples of AI safety failures that could have been prevented by the Tractatus Framework.

-

What makes a good case study?

+

What makes a good case study?

    -
  • • Documented failure: Real incident with evidence (not hypothetical)
  • -
  • • Clear failure mode: Specific way the AI system went wrong
  • -
  • • Tractatus relevance: Shows how framework boundaries could have helped
  • -
  • • Public interest: Contributes to AI safety knowledge
  • +
  • • Documented failure: Real incident with evidence (not hypothetical)
  • +
  • • Clear failure mode: Specific way the AI system went wrong
  • +
  • • Tractatus relevance: Shows how framework boundaries could have helped
  • +
  • • Public interest: Contributes to AI safety knowledge
@@ -109,26 +110,26 @@
-

Your Information

+

Your Information

-

We'll only use this to follow up on your submission

+

We'll only use this to follow up on your submission

@@ -137,21 +138,21 @@
-

Leave unchecked to remain anonymous

+

Leave unchecked to remain anonymous

-

Case Study Details

+

Case Study Details

-

Brief, descriptive title (e.g., "ChatGPT Port 27027 Failure")

+

Brief, descriptive title (e.g., "ChatGPT Port 27027 Failure")

@@ -159,12 +160,12 @@ Detailed Description * -

What happened? Provide context, timeline, and outcomes

+

What happened? Provide context, timeline, and outcomes

@@ -174,7 +175,7 @@

@@ -184,7 +185,7 @@

@@ -195,7 +196,7 @@

We review all submissions. High-quality case studies are published with attribution (if consented). @@ -217,6 +218,7 @@

+ diff --git a/public/js/case-submission.js b/public/js/case-submission.js index b178b188..e042e114 100644 --- a/public/js/case-submission.js +++ b/public/js/case-submission.js @@ -7,6 +7,19 @@ const submitButton = document.getElementById('submit-button'); const successMessage = document.getElementById('success-message'); const errorMessage = document.getElementById('error-message'); +// Helper to get translated text +function t(key) { + if (window.i18nTranslations) { + const keys = key.split('.'); + let value = window.i18nTranslations; + for (const k of keys) { + value = value?.[k]; + } + return value || key; + } + return key; +} + form.addEventListener('submit', async (e) => { e.preventDefault(); @@ -16,7 +29,7 @@ form.addEventListener('submit', async (e) => { // Disable submit button submitButton.disabled = true; - submitButton.textContent = 'Submitting...'; + submitButton.querySelector('span').textContent = t('messages.submitting'); // Collect form data const evidenceText = document.getElementById('case-evidence').value; @@ -54,25 +67,25 @@ form.addEventListener('submit', async (e) => { if (response.ok) { // Success - successMessage.textContent = data.message || 'Thank you for your submission. We will review it shortly.'; + successMessage.textContent = data.message || t('messages.success'); successMessage.style.display = 'block'; form.reset(); window.scrollTo({ top: 0, behavior: 'smooth' }); } else { // Error - errorMessage.textContent = data.message || 'An error occurred. Please try again.'; + errorMessage.textContent = data.message || t('messages.error'); errorMessage.style.display = 'block'; window.scrollTo({ top: 0, behavior: 'smooth' }); } } catch (error) { console.error('Submit error:', error); - errorMessage.textContent = 'Network error. Please check your connection and try again.'; + errorMessage.textContent = t('messages.network_error'); errorMessage.style.display = 'block'; window.scrollTo({ top: 0, behavior: 'smooth' }); } finally { // Re-enable submit button submitButton.disabled = false; - submitButton.textContent = 'Submit Case Study'; + submitButton.querySelector('span').textContent = t('form.submit_button'); } }); diff --git a/public/js/media-inquiry.js b/public/js/media-inquiry.js index 8abc2afe..63729e98 100644 --- a/public/js/media-inquiry.js +++ b/public/js/media-inquiry.js @@ -7,6 +7,19 @@ const submitButton = document.getElementById('submit-button'); const successMessage = document.getElementById('success-message'); const errorMessage = document.getElementById('error-message'); +// Helper to get translated text +function t(key) { + if (window.i18nTranslations) { + const keys = key.split('.'); + let value = window.i18nTranslations; + for (const k of keys) { + value = value?.[k]; + } + return value || key; + } + return key; +} + form.addEventListener('submit', async (e) => { e.preventDefault(); @@ -16,7 +29,7 @@ form.addEventListener('submit', async (e) => { // Disable submit button submitButton.disabled = true; - submitButton.textContent = 'Submitting...'; + submitButton.querySelector('span').textContent = t('messages.submitting'); // Collect form data const formData = { @@ -47,25 +60,25 @@ form.addEventListener('submit', async (e) => { if (response.ok) { // Success - successMessage.textContent = data.message || 'Thank you for your inquiry. We will review and respond shortly.'; + successMessage.textContent = data.message || t('messages.success'); successMessage.style.display = 'block'; form.reset(); window.scrollTo({ top: 0, behavior: 'smooth' }); } else { // Error - errorMessage.textContent = data.message || 'An error occurred. Please try again.'; + errorMessage.textContent = data.message || t('messages.error'); errorMessage.style.display = 'block'; window.scrollTo({ top: 0, behavior: 'smooth' }); } } catch (error) { console.error('Submit error:', error); - errorMessage.textContent = 'Network error. Please check your connection and try again.'; + errorMessage.textContent = t('messages.network_error'); errorMessage.style.display = 'block'; window.scrollTo({ top: 0, behavior: 'smooth' }); } finally { // Re-enable submit button submitButton.disabled = false; - submitButton.textContent = 'Submit Inquiry'; + submitButton.querySelector('span').textContent = t('form.submit_button'); } }); diff --git a/public/locales/de/case-submission.json b/public/locales/de/case-submission.json new file mode 100644 index 00000000..cd7e3292 --- /dev/null +++ b/public/locales/de/case-submission.json @@ -0,0 +1,45 @@ +{ + "page": { + "title": "Fallstudie einreichen | Tractatus AI Safety", + "heading": "Fallstudie einreichen", + "description": "Teilen Sie reale Beispiele von KI-Sicherheitsfehlern, die durch das Tractatus Framework hätten verhindert werden können." + }, + "good_case_study": { + "heading": "Was macht eine gute Fallstudie aus?", + "criteria": [ + "Dokumentiertes Versagen: Reales Ereignis mit Beweisen (nicht hypothetisch)", + "Eindeutiger Fehlermodus: Spezifische Art und Weise, wie das KI-System schiefgelaufen ist", + "Relevanz des Tractatus: Zeigt, wie Rahmengrenzen geholfen haben könnten", + "Öffentliches Interesse: Trägt zum Wissen über AI-Sicherheit bei" + ] + }, + "form": { + "submitter_info_heading": "Your Information", + "submitter_name_label": "Your Name", + "submitter_email_label": "E-Mail Adresse", + "submitter_email_help": "Wir verwenden diese Angaben nur, um Ihren Antrag weiterzuverfolgen", + "submitter_organization_label": "Organisation (fakultativ)", + "submitter_public_label": "Ich bin damit einverstanden, dass mein Name mit dieser Fallstudie veröffentlicht wird", + "submitter_public_help": "Unmarkiert lassen, um anonym zu bleiben", + "case_details_heading": "Details zur Fallstudie", + "case_title_label": "Titel der Fallstudie", + "case_title_help": "Kurzer, beschreibender Titel (z. B. \"ChatGPT Port 27027 Failure\")", + "case_description_label": "Detaillierte Beschreibung", + "case_description_help": "Was ist passiert? Geben Sie den Kontext, den Zeitrahmen und die Ergebnisse an", + "case_failure_mode_label": "Fehlermodus", + "case_failure_mode_help": "Wie hat das KI-System versagt? Welches spezifische Verhalten ging schief?", + "case_tractatus_label": "Tractatus Anwendbarkeit", + "case_tractatus_help": "Welche Grenzen des Tractatus hätten diesen Fehler verhindern können? (z.B. Abschnitt 12.1 Werte, CrossReferenceValidator, usw.)", + "case_evidence_label": "Beweise/Quellen", + "case_evidence_help": "Links zu Dokumentation, Screenshots, Artikeln oder anderen Beweisen (einer pro Zeile)", + "submit_button": "Fallstudie einreichen", + "submit_help": "Wir prüfen alle Einsendungen. Qualitativ hochwertige Fallstudien werden mit Quellenangabe veröffentlicht (sofern die Zustimmung vorliegt)." + }, + "privacy_note": "Ihre Einsendung wird nach unseren Datenschutzgrundsätzen behandelt. Alle Fallstudien werden vor der Veröffentlichung von Menschen geprüft.", + "messages": { + "submitting": "Einreichen...", + "success": "Vielen Dank für Ihren Beitrag. Wir werden sie in Kürze prüfen.", + "error": "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.", + "network_error": "Netzwerkfehler. Bitte überprüfen Sie Ihre Verbindung und versuchen Sie es erneut." + } +} \ No newline at end of file diff --git a/public/locales/de/media-inquiry.json b/public/locales/de/media-inquiry.json new file mode 100644 index 00000000..08bf84a8 --- /dev/null +++ b/public/locales/de/media-inquiry.json @@ -0,0 +1,29 @@ +{ + "page": { + "title": "Medienrecherche | Tractatus AI Sicherheit", + "heading": "Medien-Anfrage", + "description": "Presse- und Medienanfragen über den Tractatus-Rahmen. Wir prüfen alle Anfragen und antworten umgehend." + }, + "form": { + "contact_info_heading": "Kontaktinformationen", + "contact_name_label": "Your Name", + "contact_email_label": "E-Mail Adresse", + "contact_outlet_label": "Medienvertrieb/Organisation", + "contact_outlet_help": "Veröffentlichung, Website, Podcast oder Organisation, die Sie vertreten", + "contact_phone_label": "Telefonnummer (optional)", + "inquiry_details_heading": "Anfrage Details", + "inquiry_subject_label": "Thema", + "inquiry_message_label": "Nachricht", + "inquiry_deadline_label": "Frist (falls zutreffend)", + "inquiry_deadline_help": "Bis wann benötigen Sie eine Antwort?", + "submit_button": "Anfrage einreichen", + "submit_help": "Wir prüfen alle Medienanfragen und antworten in der Regel innerhalb von 24-48 Stunden." + }, + "privacy_note": "Ihre Kontaktinformationen werden nach unseren Datenschutzgrundsätzen behandelt. Wir geben Medienanfragen niemals an Dritte weiter.", + "messages": { + "submitting": "Einreichen...", + "success": "Vielen Dank für Ihre Anfrage. Wir werden sie prüfen und in Kürze beantworten.", + "error": "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.", + "network_error": "Netzwerkfehler. Bitte überprüfen Sie Ihre Verbindung und versuchen Sie es erneut." + } +} \ No newline at end of file diff --git a/public/locales/en/case-submission.json b/public/locales/en/case-submission.json new file mode 100644 index 00000000..0b8ff267 --- /dev/null +++ b/public/locales/en/case-submission.json @@ -0,0 +1,45 @@ +{ + "page": { + "title": "Submit Case Study | Tractatus AI Safety", + "heading": "Submit Case Study", + "description": "Share real-world examples of AI safety failures that could have been prevented by the Tractatus Framework." + }, + "good_case_study": { + "heading": "What makes a good case study?", + "criteria": [ + "Documented failure: Real incident with evidence (not hypothetical)", + "Clear failure mode: Specific way the AI system went wrong", + "Tractatus relevance: Shows how framework boundaries could have helped", + "Public interest: Contributes to AI safety knowledge" + ] + }, + "form": { + "submitter_info_heading": "Your Information", + "submitter_name_label": "Your Name", + "submitter_email_label": "Email Address", + "submitter_email_help": "We'll only use this to follow up on your submission", + "submitter_organization_label": "Organization (optional)", + "submitter_public_label": "I consent to my name being published with this case study", + "submitter_public_help": "Leave unchecked to remain anonymous", + "case_details_heading": "Case Study Details", + "case_title_label": "Case Study Title", + "case_title_help": "Brief, descriptive title (e.g., \"ChatGPT Port 27027 Failure\")", + "case_description_label": "Detailed Description", + "case_description_help": "What happened? Provide context, timeline, and outcomes", + "case_failure_mode_label": "Failure Mode", + "case_failure_mode_help": "How did the AI system fail? What specific behavior went wrong?", + "case_tractatus_label": "Tractatus Applicability", + "case_tractatus_help": "Which Tractatus boundaries could have prevented this failure? (e.g., Section 12.1 Values, CrossReferenceValidator, etc.)", + "case_evidence_label": "Evidence/Sources", + "case_evidence_help": "Links to documentation, screenshots, articles, or other evidence (one per line)", + "submit_button": "Submit Case Study", + "submit_help": "We review all submissions. High-quality case studies are published with attribution (if consented)." + }, + "privacy_note": "Your submission is handled according to our privacy principles. All case studies undergo human review before publication.", + "messages": { + "submitting": "Submitting...", + "success": "Thank you for your submission. We will review it shortly.", + "error": "An error occurred. Please try again.", + "network_error": "Network error. Please check your connection and try again." + } +} diff --git a/public/locales/en/media-inquiry.json b/public/locales/en/media-inquiry.json new file mode 100644 index 00000000..709f231a --- /dev/null +++ b/public/locales/en/media-inquiry.json @@ -0,0 +1,29 @@ +{ + "page": { + "title": "Media Inquiry | Tractatus AI Safety", + "heading": "Media Inquiry", + "description": "Press and media inquiries about the Tractatus Framework. We review all inquiries and respond promptly." + }, + "form": { + "contact_info_heading": "Contact Information", + "contact_name_label": "Your Name", + "contact_email_label": "Email Address", + "contact_outlet_label": "Media Outlet/Organization", + "contact_outlet_help": "Publication, website, podcast, or organization you represent", + "contact_phone_label": "Phone Number (optional)", + "inquiry_details_heading": "Inquiry Details", + "inquiry_subject_label": "Subject", + "inquiry_message_label": "Message", + "inquiry_deadline_label": "Deadline (if applicable)", + "inquiry_deadline_help": "When do you need a response by?", + "submit_button": "Submit Inquiry", + "submit_help": "We review all media inquiries and typically respond within 24-48 hours." + }, + "privacy_note": "Your contact information is handled according to our privacy principles. We never share media inquiries with third parties.", + "messages": { + "submitting": "Submitting...", + "success": "Thank you for your inquiry. We will review and respond shortly.", + "error": "An error occurred. Please try again.", + "network_error": "Network error. Please check your connection and try again." + } +} diff --git a/public/locales/fr/case-submission.json b/public/locales/fr/case-submission.json new file mode 100644 index 00000000..3a0fccb7 --- /dev/null +++ b/public/locales/fr/case-submission.json @@ -0,0 +1,45 @@ +{ + "page": { + "title": "Soumettre une étude de cas | Tractatus AI Safety", + "heading": "Soumettre une étude de cas", + "description": "Partager des exemples concrets d'échecs en matière de sécurité de l'IA qui auraient pu être évités grâce au cadre Tractatus." + }, + "good_case_study": { + "heading": "Qu'est-ce qui fait une bonne étude de cas ?", + "criteria": [ + "Échec documenté : Incident réel avec preuves (pas hypothétique)", + "Mode d'échec clair : Façon spécifique dont le système d'intelligence artificielle a échoué", + "Pertinence du Tractatus : Montre comment les limites du cadre auraient pu être utiles", + "Intérêt public : Contribue à la connaissance de la sécurité de l'IA" + ] + }, + "form": { + "submitter_info_heading": "Your Information", + "submitter_name_label": "Votre nom", + "submitter_email_label": "Adresse électronique", + "submitter_email_help": "Nous ne l'utiliserons que pour donner suite à votre demande", + "submitter_organization_label": "Organisation (facultatif)", + "submitter_public_label": "Je consens à ce que mon nom soit publié avec cette étude de cas", + "submitter_public_help": "Ne pas cocher pour rester anonyme", + "case_details_heading": "Détails de l'étude de cas", + "case_title_label": "Titre de l'étude de cas", + "case_title_help": "Titre bref et descriptif (par exemple, \"ChatGPT Port 27027 Failure\")", + "case_description_label": "Description détaillée", + "case_description_help": "Que s'est-il passé ? Présenter le contexte, la chronologie et les résultats", + "case_failure_mode_label": "Mode de défaillance", + "case_failure_mode_help": "Comment le système d'intelligence artificielle a-t-il échoué ? Quel est le comportement spécifique qui n'a pas fonctionné ?", + "case_tractatus_label": "Tractatus Applicabilité", + "case_tractatus_help": "Quelles sont les limites du Tractatus qui auraient pu empêcher cet échec ? (par exemple, Section 12.1 Values, CrossReferenceValidator, etc.)", + "case_evidence_label": "Preuves/Sources", + "case_evidence_help": "Liens vers des documents, des captures d'écran, des articles ou d'autres preuves (un par ligne)", + "submit_button": "Soumettre une étude de cas", + "submit_help": "Nous examinons toutes les propositions. Les études de cas de grande qualité sont publiées avec mention de l'auteur (s'il a donné son accord)." + }, + "privacy_note": "Votre demande est traitée conformément à nos principes en matière de protection de la vie privée. Toutes les études de cas font l'objet d'un examen humain avant d'être publiées.", + "messages": { + "submitting": "Soumettre...", + "success": "Nous vous remercions pour votre demande. Nous l'examinerons sous peu.", + "error": "Une erreur s'est produite. Veuillez réessayer.", + "network_error": "Erreur de réseau. Veuillez vérifier votre connexion et réessayer." + } +} \ No newline at end of file diff --git a/public/locales/fr/media-inquiry.json b/public/locales/fr/media-inquiry.json new file mode 100644 index 00000000..16f5f748 --- /dev/null +++ b/public/locales/fr/media-inquiry.json @@ -0,0 +1,29 @@ +{ + "page": { + "title": "Interrogation des médias | Tractatus AI Safety", + "heading": "Enquête auprès des médias", + "description": "Demandes de renseignements de la part de la presse et des médias sur le cadre Tractatus. Nous examinons toutes les demandes et y répondons rapidement." + }, + "form": { + "contact_info_heading": "Informations sur le contact", + "contact_name_label": "Votre nom", + "contact_email_label": "Adresse électronique", + "contact_outlet_label": "Point de vente des médias/organisation", + "contact_outlet_help": "Publication, site web, podcast ou organisation que vous représentez", + "contact_phone_label": "Numéro de téléphone (facultatif)", + "inquiry_details_heading": "Détails de la demande", + "inquiry_subject_label": "Sujet", + "inquiry_message_label": "Message", + "inquiry_deadline_label": "Date limite (le cas échéant)", + "inquiry_deadline_help": "Quelle est la date limite de réponse ?", + "submit_button": "Soumettre une demande", + "submit_help": "Nous examinons toutes les demandes des médias et y répondons généralement dans les 24 à 48 heures." + }, + "privacy_note": "Vos coordonnées sont traitées conformément à nos principes de confidentialité. Nous ne transmettons jamais les demandes des médias à des tiers.", + "messages": { + "submitting": "Soumettre...", + "success": "Nous vous remercions de votre demande. Nous l'examinerons et vous répondrons dans les plus brefs délais.", + "error": "Une erreur s'est produite. Veuillez réessayer.", + "network_error": "Erreur de réseau. Veuillez vérifier votre connexion et réessayer." + } +} \ No newline at end of file diff --git a/public/media-inquiry.html b/public/media-inquiry.html index 8ede1fee..0b1bf1c1 100644 --- a/public/media-inquiry.html +++ b/public/media-inquiry.html @@ -1,9 +1,9 @@ - + - Media Inquiry | Tractatus AI Safety + Media Inquiry | Tractatus AI Safety @@ -69,13 +69,14 @@ +
-

Media Inquiry

+

Media Inquiry

Press and media inquiries about the Tractatus Framework. We review all inquiries and respond promptly.

@@ -90,66 +91,66 @@ -

Contact Information

+

Contact Information

-

Publication, website, podcast, or organization you represent

+

Publication, website, podcast, or organization you represent

-

Inquiry Details

+

Inquiry Details

-

When do you need a response by?

+

When do you need a response by?

We review all media inquiries and typically respond within 24-48 hours. @@ -171,6 +172,7 @@

+