From 02e02778f796d2cd8ad99d3d5a84557cd20debcb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:09:38 +0000 Subject: [PATCH 1/3] Initial plan From 44a8bfeeb68b1296dd3d31d70bfdc34e515a3483 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:29:04 +0000 Subject: [PATCH 2/3] Improve translation quality: AI_MUST_REPLACE detection, domain-split dictionary, workflow update Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/b182ac4a-002b-47f8-9b70-bf0a7c41f4b8 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com> --- .github/workflows/news-translate.md | 33 + scripts/check-banned-patterns.ts | 11 + .../translation-dictionary-committee-names.ts | 199 +++ scripts/translation-dictionary-party-names.ts | 214 ++++ .../translation-dictionary-political-terms.ts | 737 +++++++++++ scripts/translation-dictionary.ts | 1111 +---------------- scripts/validate-news-translations.ts | 83 +- tests/validate-news-translations.test.ts | 81 ++ 8 files changed, 1370 insertions(+), 1099 deletions(-) create mode 100644 scripts/translation-dictionary-committee-names.ts create mode 100644 scripts/translation-dictionary-party-names.ts create mode 100644 scripts/translation-dictionary-political-terms.ts diff --git a/.github/workflows/news-translate.md b/.github/workflows/news-translate.md index 49cf20b371..5733103455 100644 --- a/.github/workflows/news-translate.md +++ b/.github/workflows/news-translate.md @@ -654,6 +654,39 @@ The TypeScript script generates **structural baselines only** — it translates 3. **Raw Swedish API text** — Interpellation excerpts, proposition summaries that come from the Riksdag API are often pasted as-is. You MUST translate these to the target language or summarize them. 4. **English boilerplate phrases** — Remove or translate phrases like "Read the full proposition", "Live intelligence platform for Swedish Parliament monitoring" 5. **Section headings** that were not covered by CONTENT_LABELS (e.g., specific policy domain names used as h3/h4 headings) +6. **🚨 AI_MUST_REPLACE HTML comments** — SCAN every HTML comment in the source article. If any contains `AI_MUST_REPLACE`, you MUST generate replacement content in the target language. See critical section below. + +#### 🚨 CRITICAL: AI_MUST_REPLACE Comment Handling + +The content generator embeds placeholder HTML comments in the form: +```html + +``` + +**These comments MUST be replaced with real content before publication.** Leaving them in the article is a hard CI failure (exit 1). The translation workflow MUST: + +1. **SCAN every HTML comment** in the translated article for `AI_MUST_REPLACE` +2. **For each marker found**, read the `DATA:` hint inside the comment to understand what content to generate +3. **Replace the entire `` comment** with genuine, specific analysis written in the **target language** (not English) +4. **Use actual document data** (party names, vote counts, document titles) — NOT generic templates +5. **Verify zero markers remain** before creating a PR + +**Detection command (run before PR creation):** +```bash +grep -r 'AI_MUST_REPLACE' news/${ARTICLE_DATE}-*-${lang}.html && echo "❌ MARKERS FOUND — must replace before PR" || echo "✅ No markers found" +``` + +**Common marker types and required output:** +- `timeline_context` → Analysis of scheduling significance and political timing +- `why_matters` → Specific explanation of why these documents matter politically +- `political_impact` → Named-party analysis of political impact with vote arithmetic +- `consequences` → Specific implementation consequences and next steps +- `coalition_instability` → Current coalition stability indicators with evidence +- `critical_assessment` → Critical evaluation of intent vs. likely outcomes +- `single_party_dominance` → Analysis of why one party dominates +- `debate_analysis` → Insights from debate data +- `majority_impact` → Effect of thin majority on specific legislation +- `winners_losers_analysis` → Political winners and losers analysis #### Translation Completeness Check Process: diff --git a/scripts/check-banned-patterns.ts b/scripts/check-banned-patterns.ts index 2f98c1966c..3e76c39e79 100644 --- a/scripts/check-banned-patterns.ts +++ b/scripts/check-banned-patterns.ts @@ -3,6 +3,7 @@ * * Sources banned patterns from the canonical BANNED_PATTERNS list in shared.ts * so the bash script does not maintain a duplicate pattern set. + * Also detects unresolved AI_MUST_REPLACE markers in HTML comments. * * Usage: npx tsx scripts/check-banned-patterns.ts news/*.html * Exit code: number of articles containing banned patterns (0 = clean) @@ -12,6 +13,9 @@ import { readFileSync } from 'fs'; import { detectBannedPatterns } from './data-transformers/content-generators/shared.js'; +/** Regex for unresolved AI_MUST_REPLACE placeholders in HTML comments. */ +const AI_MUST_REPLACE_RE = //; + const files = process.argv.slice(2); let count = 0; @@ -19,6 +23,13 @@ for (const file of files) { try { const html = readFileSync(file, 'utf-8'); const labels = detectBannedPatterns(html); + + // Detect AI_MUST_REPLACE markers inside HTML comments — these are + // unresolved template placeholders that must never reach production. + if (AI_MUST_REPLACE_RE.test(html)) { + labels.push('aiMustReplaceComment: Unresolved AI_MUST_REPLACE placeholder in HTML comment'); + } + if (labels.length > 0) { count++; // Machine-readable output for the bash wrapper diff --git a/scripts/translation-dictionary-committee-names.ts b/scripts/translation-dictionary-committee-names.ts new file mode 100644 index 0000000000..b3f436d31e --- /dev/null +++ b/scripts/translation-dictionary-committee-names.ts @@ -0,0 +1,199 @@ +/** + * @module Translation Dictionary — Committee Names + * @description Committee names and Swedish parliamentary institution names + * for all 14 supported languages. + * + * Split from translation-dictionary.ts for maintainability. + * Imported and combined in translation-dictionary.ts. + */ + +import type { Language } from './types/language.js'; + +/** + * Swedish parliamentary institution names and committee names. + * Each entry: [Swedish term, per-language translations]. + */ +export const COMMITTEE_NAME_TERMS: ReadonlyArray]> = [ + // ---- Swedish parliamentary institution names ---- + [ + 'riksdagen', + { + sv: 'riksdagen', en: 'the Riksdag', da: 'Riksdag', no: 'Riksdag', + fi: 'Riksdag', de: 'Riksdag', fr: 'le Riksdag', es: 'el Riksdag', + nl: 'de Riksdag', ar: 'البرلمان السويدي', he: 'הריקסדאג', + ja: 'スウェーデン国会', ko: '스웨덴 의회', zh: '瑞典议会', + }, + ], + [ + 'regeringen', + { + sv: 'regeringen', en: 'the Government', da: 'regeringen', no: 'regjeringen', + fi: 'hallitus', de: 'die Regierung', fr: 'le gouvernement', es: 'el gobierno', + nl: 'de regering', ar: 'الحكومة', he: 'הממשלה', + ja: '政府', ko: '정부', zh: '政府', + }, + ], + // ---- Committee names ---- + [ + 'arbetsmarknadsutskottet', + { + sv: 'arbetsmarknadsutskottet', en: 'Committee on Labour Market Affairs', + da: 'Arbejdsmarkedsudvalget', no: 'Arbeidsmarkedskomiteen', + fi: 'Työvaliokunta', de: 'Ausschuss für Arbeitsmarktangelegenheiten', + fr: 'Comité du marché du travail', es: 'Comité de Mercado Laboral', + nl: 'Commissie voor Arbeidsmarktzaken', ar: 'لجنة سوق العمل', + he: 'ועדת שוק העבודה', ja: '労働市場委員会', ko: '노동시장위원회', zh: '劳动市场委员会', + }, + ], + [ + 'civilutskottet', + { + sv: 'civilutskottet', en: 'Committee on Civil Affairs', + da: 'Civiludvalget', no: 'Sivilkomiteen', fi: 'Siviiliasioiden valiokunta', + de: 'Ausschuss für Zivilrecht', fr: 'Comité des affaires civiles', + es: 'Comité de Asuntos Civiles', nl: 'Commissie voor Burgerlijke Zaken', + ar: 'لجنة الشؤون المدنية', he: 'ועדת ענייני אזרחות', + ja: '市民問題委員会', ko: '민사문제위원회', zh: '民事委员会', + }, + ], + [ + 'finansutskottet', + { + sv: 'finansutskottet', en: 'Committee on Finance', + da: 'Finansudvalget', no: 'Finanskomiteen', fi: 'Valtiovarainvaliokunta', + de: 'Finanzausschuss', fr: 'Comité des finances', + es: 'Comité de Finanzas', nl: 'Financiëncommissie', + ar: 'لجنة المالية', he: 'ועדת האוצר', + ja: '財政委員会', ko: '재정위원회', zh: '财政委员会', + }, + ], + [ + 'försvarsutskottet', + { + sv: 'försvarsutskottet', en: 'Committee on Defence', + da: 'Forsvarsudvalget', no: 'Forsvarskomiteen', fi: 'Puolustusvaliokunta', + de: 'Verteidigungsausschuss', fr: 'Comité de la défense', + es: 'Comité de Defensa', nl: 'Defensiecommissie', + ar: 'لجنة الدفاع', he: 'ועדת הביטחון', ja: '防衛委員会', ko: '방위위원회', zh: '国防委员会', + }, + ], + [ + 'justitieutskottet', + { + sv: 'justitieutskottet', en: 'Committee on Justice', + da: 'Retsudvalget', no: 'Justiskomiteen', fi: 'Lakivaliokunta', + de: 'Rechtsausschuss', fr: 'Comité de justice', + es: 'Comité de Justicia', nl: 'Justitiecommissie', + ar: 'لجنة العدل', he: 'ועדת המשפטים', ja: '司法委員会', ko: '법무위원회', zh: '司法委员会', + }, + ], + [ + 'konstitutionsutskottet', + { + sv: 'konstitutionsutskottet', en: 'Committee on the Constitution', + da: 'Forfatningsudvalget', no: 'Konstitusjonskomiteen', fi: 'Perustuslakivaliokunta', + de: 'Verfassungsausschuss', fr: 'Comité de la Constitution', + es: 'Comité Constitucional', nl: 'Grondwetcommissie', + ar: 'لجنة الدستور', he: 'ועדת החוקה', ja: '憲法委員会', ko: '헌법위원회', zh: '宪法委员会', + }, + ], + [ + 'kulturutskottet', + { + sv: 'kulturutskottet', en: 'Committee on Cultural Affairs', + da: 'Kulturudvalget', no: 'Kulturkomiteen', fi: 'Kulttuurivaliokunta', + de: 'Kulturausschuss', fr: 'Comité de la culture', + es: 'Comité de Cultura', nl: 'Cultuurcommissie', + ar: 'لجنة الثقافة', he: 'ועדת התרבות', ja: '文化委員会', ko: '문화위원회', zh: '文化委员会', + }, + ], + [ + 'miljö- och jordbruksutskottet', + { + sv: 'miljö- och jordbruksutskottet', en: 'Committee on Environment and Agriculture', + da: 'Miljø- og Landbrugsudvalget', no: 'Miljø- og Landbrukskomiteen', + fi: 'Ympäristö- ja maatalousvaliokunta', + de: 'Ausschuss für Umwelt und Landwirtschaft', + fr: 'Comité de l\'environnement et de l\'agriculture', + es: 'Comité de Medio Ambiente y Agricultura', + nl: 'Commissie voor Milieu en Landbouw', + ar: 'لجنة البيئة والزراعة', he: 'ועדת הסביבה והחקלאות', + ja: '環境農業委員会', ko: '환경농업위원회', zh: '环境农业委员会', + }, + ], + [ + 'näringsutskottet', + { + sv: 'näringsutskottet', en: 'Committee on Industry and Trade', + da: 'Erhvervsudvalget', no: 'Næringskomiteen', fi: 'Talousvaliokunta', + de: 'Ausschuss für Wirtschaft und Handel', fr: 'Comité de l\'industrie et du commerce', + es: 'Comité de Industria y Comercio', nl: 'Commissie voor Industrie en Handel', + ar: 'لجنة الصناعة والتجارة', he: 'ועדת התעשייה והמסחר', + ja: '産業貿易委員会', ko: '산업통상위원회', zh: '工业贸易委员会', + }, + ], + [ + 'skatteutskottet', + { + sv: 'skatteutskottet', en: 'Committee on Taxation', + da: 'Skatteudvalget', no: 'Skattekomiteen', fi: 'Verovaliokunta', + de: 'Steuerausschuss', fr: 'Comité de la fiscalité', + es: 'Comité Fiscal', nl: 'Belastingcommissie', + ar: 'لجنة الضرائب', he: 'ועדת המיסים', ja: '税制委員会', ko: '세금위원회', zh: '税务委员会', + }, + ], + [ + 'socialförsäkringsutskottet', + { + sv: 'socialförsäkringsutskottet', en: 'Committee on Social Insurance', + da: 'Socialforsikringsudvalget', no: 'Sosialforsikringskomiteen', + fi: 'Sosiaalivakuutusvaliokunta', + de: 'Ausschuss für Sozialversicherung', fr: 'Comité de l\'assurance sociale', + es: 'Comité de Seguro Social', nl: 'Commissie voor Sociale Verzekering', + ar: 'لجنة التأمين الاجتماعي', he: 'ועדת הביטוח הסוציאלי', + ja: '社会保険委員会', ko: '사회보험위원회', zh: '社会保险委员会', + }, + ], + [ + 'socialutskottet', + { + sv: 'socialutskottet', en: 'Committee on Social Affairs', + da: 'Socialudvalget', no: 'Sosialkomiteen', fi: 'Sosiaaliasioiden valiokunta', + de: 'Sozialausschuss', fr: 'Comité des affaires sociales', + es: 'Comité de Asuntos Sociales', nl: 'Sociale Commissie', + ar: 'لجنة الشؤون الاجتماعية', he: 'ועדת הרווחה', + ja: '社会問題委員会', ko: '사회문제위원회', zh: '社会事务委员会', + }, + ], + [ + 'trafikutskottet', + { + sv: 'trafikutskottet', en: 'Committee on Transport', + da: 'Trafikudvalget', no: 'Transportkomiteen', fi: 'Liikennevaliokunta', + de: 'Verkehrsausschuss', fr: 'Comité des transports', + es: 'Comité de Transporte', nl: 'Transportcommissie', + ar: 'لجنة المواصلات', he: 'ועדת התחבורה', ja: '交通委員会', ko: '교통위원회', zh: '交通委员会', + }, + ], + [ + 'utbildningsutskottet', + { + sv: 'utbildningsutskottet', en: 'Committee on Education', + da: 'Uddannelsesudvalget', no: 'Utdanningskomiteen', fi: 'Koulutusvaliokunta', + de: 'Bildungsausschuss', fr: 'Comité de l\'éducation', + es: 'Comité de Educación', nl: 'Onderwijscommissie', + ar: 'لجنة التعليم', he: 'ועדת החינוך', ja: '教育委員会', ko: '교육위원회', zh: '教育委员会', + }, + ], + [ + 'utrikesutskottet', + { + sv: 'utrikesutskottet', en: 'Committee on Foreign Affairs', + da: 'Udenrigsudvalget', no: 'Utenrikskomiteen', fi: 'Ulkoasiainvaliokunta', + de: 'Außenpolitischer Ausschuss', fr: 'Comité des affaires étrangères', + es: 'Comité de Asuntos Exteriores', nl: 'Commissie voor Buitenlandse Zaken', + ar: 'لجنة الشؤون الخارجية', he: 'ועדת החוץ', + ja: '外務委員会', ko: '외무위원회', zh: '外交委员会', + }, + ], +]; diff --git a/scripts/translation-dictionary-party-names.ts b/scripts/translation-dictionary-party-names.ts new file mode 100644 index 0000000000..5f014d32af --- /dev/null +++ b/scripts/translation-dictionary-party-names.ts @@ -0,0 +1,214 @@ +/** + * @module Translation Dictionary — Party and Ministry Names + * @description Swedish political party names and ministry names + * for all 14 supported languages. + * + * Split from translation-dictionary.ts for maintainability. + * Imported and combined in translation-dictionary.ts. + */ + +import type { Language } from './types/language.js'; + +/** + * Swedish ministry names and political party group names. + * Each entry: [Swedish term, per-language translations]. + */ +export const PARTY_NAME_TERMS: ReadonlyArray]> = [ + // ---- Swedish Ministry names (11 ministries) ---- + [ + 'finansdepartementet', + { + sv: 'finansdepartementet', en: 'Ministry of Finance', da: 'Finansministeriet', + no: 'Finansdepartementet', fi: 'Valtiovarainministeriö', de: 'Finanzministerium', + fr: 'Ministère des Finances', es: 'Ministerio de Hacienda', + nl: 'Ministerie van Financiën', ar: 'وزارة المالية', he: 'משרד האוצר', + ja: '財務省', ko: '재무부', zh: '财政部', + }, + ], + [ + 'justitiedepartementet', + { + sv: 'justitiedepartementet', en: 'Ministry of Justice', da: 'Justitsministeriet', + no: 'Justisdepartementet', fi: 'Oikeusministeriö', de: 'Justizministerium', + fr: 'Ministère de la Justice', es: 'Ministerio de Justicia', + nl: 'Ministerie van Justitie', ar: 'وزارة العدل', he: 'משרד המשפטים', + ja: '法務省', ko: '법무부', zh: '司法部', + }, + ], + [ + 'utrikesdepartementet', + { + sv: 'utrikesdepartementet', en: 'Ministry for Foreign Affairs', da: 'Udenrigsministeriet', + no: 'Utenriksdepartementet', fi: 'Ulkoministeriö', de: 'Außenministerium', + fr: 'Ministère des Affaires étrangères', es: 'Ministerio de Asuntos Exteriores', + nl: 'Ministerie van Buitenlandse Zaken', ar: 'وزارة الخارجية', he: 'משרד החוץ', + ja: '外務省', ko: '외교부', zh: '外交部', + }, + ], + [ + 'försvarsdepartementet', + { + sv: 'försvarsdepartementet', en: 'Ministry of Defence', da: 'Forsvarsministeriet', + no: 'Forsvarsdepartementet', fi: 'Puolustusministeriö', de: 'Verteidigungsministerium', + fr: 'Ministère de la Défense', es: 'Ministerio de Defensa', + nl: 'Ministerie van Defensie', ar: 'وزارة الدفاع', he: 'משרד הביטחון', + ja: '防衛省', ko: '국방부', zh: '国防部', + }, + ], + [ + 'socialdepartementet', + { + sv: 'socialdepartementet', en: 'Ministry of Health and Social Affairs', + da: 'Socialministeriet', no: 'Sosialdepartementet', fi: 'Sosiaali- ja terveysministeriö', + de: 'Ministerium für Gesundheit und Soziales', fr: 'Ministère de la Santé et des Affaires sociales', + es: 'Ministerio de Salud y Asuntos Sociales', nl: 'Ministerie van Volksgezondheid en Sociale Zaken', + ar: 'وزارة الصحة والشؤون الاجتماعية', he: 'משרד הבריאות והרווחה', + ja: '保健社会省', ko: '보건사회부', zh: '卫生和社会事务部', + }, + ], + [ + 'utbildningsdepartementet', + { + sv: 'utbildningsdepartementet', en: 'Ministry of Education and Research', + da: 'Uddannelsesministeriet', no: 'Utdanningsdepartementet', + fi: 'Opetus- ja kulttuuriministeriö', de: 'Ministerium für Bildung und Forschung', + fr: 'Ministère de l\'Éducation et de la Recherche', es: 'Ministerio de Educación e Investigación', + nl: 'Ministerie van Onderwijs en Onderzoek', ar: 'وزارة التعليم والبحث العلمي', + he: 'משרד החינוך והמחקר', ja: '教育研究省', ko: '교육연구부', zh: '教育研究部', + }, + ], + [ + 'miljödepartementet', + { + sv: 'miljödepartementet', en: 'Ministry of Climate and Enterprise', + da: 'Miljøministeriet', no: 'Miljødepartementet', fi: 'Ympäristöministeriö', + de: 'Ministerium für Klima und Wirtschaft', fr: 'Ministère du Climat et de l\'Entreprise', + es: 'Ministerio de Clima y Empresa', nl: 'Ministerie van Klimaat en Onderneming', + ar: 'وزارة المناخ والأعمال', he: 'משרד האקלים והיזמות', + ja: '気候企業省', ko: '기후기업부', zh: '气候和企业部', + }, + ], + [ + 'näringsdepartementet', + { + sv: 'näringsdepartementet', en: 'Ministry of Enterprise and Innovation', + da: 'Erhvervsministeriet', no: 'Næringsdepartementet', fi: 'Työ- ja elinkeinoministeriö', + de: 'Ministerium für Wirtschaft und Innovation', fr: 'Ministère de l\'Entreprise et de l\'Innovation', + es: 'Ministerio de Empresa e Innovación', nl: 'Ministerie van Economische Zaken', + ar: 'وزارة المؤسسات والابتكار', he: 'משרד הכלכלה והחדשנות', + ja: '企業革新省', ko: '기업혁신부', zh: '企业创新部', + }, + ], + [ + 'kulturdepartementet', + { + sv: 'kulturdepartementet', en: 'Ministry of Culture', da: 'Kulturministeriet', + no: 'Kulturdepartementet', fi: 'Kulttuuriministeriö', de: 'Kulturministerium', + fr: 'Ministère de la Culture', es: 'Ministerio de Cultura', + nl: 'Ministerie van Cultuur', ar: 'وزارة الثقافة', he: 'משרד התרבות', + ja: '文化省', ko: '문화부', zh: '文化部', + }, + ], + [ + 'infrastrukturdepartementet', + { + sv: 'infrastrukturdepartementet', en: 'Ministry of Infrastructure', + da: 'Infrastrukturministeriet', no: 'Infrastrukturdepartementet', + fi: 'Infrastruktuuriministeriö', de: 'Infrastrukturministerium', + fr: 'Ministère de l\'Infrastructure', es: 'Ministerio de Infraestructura', + nl: 'Ministerie van Infrastructuur', ar: 'وزارة البنية التحتية', + he: 'משרד התשתיות', ja: 'インフラ省', ko: '인프라부', zh: '基础设施部', + }, + ], + [ + 'arbetsmarknadsdepartementet', + { + sv: 'arbetsmarknadsdepartementet', en: 'Ministry of Employment', + da: 'Beskæftigelsesministeriet', no: 'Arbeids- og inkluderingsdepartementet', + fi: 'Työministeriö', de: 'Arbeitsministerium', fr: 'Ministère de l\'Emploi', + es: 'Ministerio de Empleo', nl: 'Ministerie van Werkgelegenheid', + ar: 'وزارة العمل', he: 'משרד העבודה', ja: '雇用省', ko: '고용부', zh: '就业部', + }, + ], + // ---- Swedish political party group names (8 parliamentary parties) ---- + [ + 'socialdemokraterna', + { + sv: 'Socialdemokraterna', en: 'Social Democrats', da: 'Socialdemokraterne', + no: 'Sosialdemokratene', fi: 'Sosiaalidemokraatit', de: 'Sozialdemokraten', + fr: 'Sociaux-démocrates', es: 'Socialdemócratas', nl: 'Sociaaldemocraten', + ar: 'الاشتراكيون الديمقراطيون', he: 'סוציאל-דמוקרטים', + ja: '社会民主党', ko: '사회민주당', zh: '社会民主党', + }, + ], + [ + 'moderaterna', + { + sv: 'Moderaterna', en: 'Moderate Party', da: 'Moderaterne', + no: 'Moderatene', fi: 'Maltillinen kokoomus', de: 'Moderate Sammlungspartei', + fr: 'Parti modéré', es: 'Partido Moderado', nl: 'Gematigde Partij', + ar: 'حزب المحافظين', he: 'המפלגה המתונה', + ja: '穏健党', ko: '온건당', zh: '温和党', + }, + ], + [ + 'sverigedemokraterna', + { + sv: 'Sverigedemokraterna', en: 'Sweden Democrats', da: 'Sverigedemokraterne', + no: 'Sverigedemokratene', fi: 'Ruotsidemokraatit', de: 'Schwedendemokraten', + fr: 'Démocrates de Suède', es: 'Demócratas de Suecia', nl: 'Zweden-Democraten', + ar: 'ديمقراطيو السويد', he: 'דמוקרטים שבדים', + ja: 'スウェーデン民主党', ko: '스웨덴민주당', zh: '瑞典民主党', + }, + ], + [ + 'centerpartiet', + { + sv: 'Centerpartiet', en: 'Centre Party', da: 'Centerpartiet', + no: 'Senterpartiet', fi: 'Keskustapuolue', de: 'Zentrumspartei', + fr: 'Parti du Centre', es: 'Partido de Centro', nl: 'Centrumpartij', + ar: 'حزب الوسط', he: 'מפלגת המרכז', + ja: '中央党', ko: '중앙당', zh: '中间党', + }, + ], + [ + 'vänsterpartiet', + { + sv: 'Vänsterpartiet', en: 'Left Party', da: 'Venstrepartiet', + no: 'Venstrepartiet', fi: 'Vasemmistopuolue', de: 'Linkspartei', + fr: 'Parti de gauche', es: 'Partido de Izquierda', nl: 'Linkse Partij', + ar: 'حزب اليسار', he: 'מפלגת השמאל', + ja: '左翼党', ko: '좌파당', zh: '左翼党', + }, + ], + [ + 'kristdemokraterna', + { + sv: 'Kristdemokraterna', en: 'Christian Democrats', da: 'Kristendemokraterne', + no: 'Kristeligdemokratene', fi: 'Kristillisdemokraatit', de: 'Christdemokraten', + fr: 'Chrétiens-démocrates', es: 'Demócratas Cristianos', nl: 'Christendemocraten', + ar: 'الديمقراطيون المسيحيون', he: 'דמוקרטים נוצרים', + ja: 'キリスト教民主党', ko: '기독민주당', zh: '基督教民主党', + }, + ], + [ + 'liberalerna', + { + sv: 'Liberalerna', en: 'Liberals', da: 'Liberalerne', + no: 'Liberalerne', fi: 'Liberaalit', de: 'Liberale', + fr: 'Libéraux', es: 'Liberales', nl: 'Liberalen', + ar: 'الليبراليون', he: 'ליברלים', + ja: '自由党', ko: '자유당', zh: '自由党', + }, + ], + [ + 'miljöpartiet', + { + sv: 'Miljöpartiet', en: 'Green Party', da: 'Miljøpartiet', + no: 'Miljøpartiet', fi: 'Ympäristöpuolue', de: 'Grüne Partei', + fr: 'Parti Vert', es: 'Partido Verde', nl: 'Groene Partij', + ar: 'حزب البيئة', he: 'המפלגה הירוקה', + ja: '緑の党', ko: '녹색당', zh: '绿党', + }, + ], +]; diff --git a/scripts/translation-dictionary-political-terms.ts b/scripts/translation-dictionary-political-terms.ts new file mode 100644 index 0000000000..34ad6566af --- /dev/null +++ b/scripts/translation-dictionary-political-terms.ts @@ -0,0 +1,737 @@ +/** + * @module Translation Dictionary — Political and Procedural Terms + * @description Parliamentary procedure terms, budget/fiscal terms, EU and + * international terms, geographic terms, government agencies, legal terms, + * and policy domain terms for all 14 supported languages. + * + * Split from translation-dictionary.ts for maintainability. + * Imported and combined in translation-dictionary.ts. + */ + +import type { Language } from './types/language.js'; + +/** + * Parliamentary procedure, budget/fiscal, EU, geographic, legal and policy terms. + * Each entry: [Swedish term, per-language translations]. + */ +export const POLITICAL_TERMS: ReadonlyArray]> = [ + // ---- Parliamentary procedure terms ---- + [ + 'anmälan', + { + sv: 'anmälan', en: 'notification', da: 'anmeldelse', no: 'anmeldelse', + fi: 'ilmoitus', de: 'Anmeldung', fr: 'notification', es: 'notificación', + nl: 'melding', ar: 'إخطار', he: 'הודעה', ja: '届出', ko: '신고', zh: '通知', + }, + ], + [ + 'besvarat', + { + sv: 'besvarat', en: 'answered', da: 'besvaret', no: 'besvart', + fi: 'vastattu', de: 'beantwortet', fr: 'répondu', es: 'respondido', + nl: 'beantwoord', ar: 'تمت الإجابة', he: 'הושב', ja: '回答済み', ko: '답변됨', zh: '已答复', + }, + ], + [ + 'granskning', + { + sv: 'granskning', en: 'review', da: 'gennemgang', no: 'gjennomgang', + fi: 'tarkastus', de: 'Überprüfung', fr: 'examen', es: 'revisión', + nl: 'beoordeling', ar: 'مراجعة', he: 'ביקורת', ja: '審査', ko: '심사', zh: '审查', + }, + ], + [ + 'yttrande', + { + sv: 'yttrande', en: 'opinion', da: 'udtalelse', no: 'uttalelse', + fi: 'lausunto', de: 'Stellungnahme', fr: 'avis', es: 'dictamen', + nl: 'advies', ar: 'رأي', he: 'חוות דעת', ja: '意見書', ko: '의견서', zh: '意见', + }, + ], + [ + 'bordläggning', + { + sv: 'bordläggning', en: 'tabling', da: 'bordlæggelse', no: 'bordlegging', + fi: 'pöydällepano', de: 'Vertagung', fr: 'ajournement', es: 'aplazamiento', + nl: 'verdaging', ar: 'تأجيل', he: 'דחייה', ja: '延期', ko: '보류', zh: '搁置', + }, + ], + [ + 'tillkännagivande', + { + sv: 'tillkännagivande', en: 'announcement', da: 'meddelelse', no: 'kunngjøring', + fi: 'tiedonanto', de: 'Bekanntmachung', fr: 'communication', es: 'comunicado', + nl: 'mededeling', ar: 'إعلان', he: 'הודעה', ja: '告示', ko: '공고', zh: '公告', + }, + ], + [ + 'reservation', + { + sv: 'reservation', en: 'reservation', da: 'reservation', no: 'reservasjon', + fi: 'varaus', de: 'Vorbehalt', fr: 'réserve', es: 'reserva', + nl: 'voorbehoud', ar: 'تحفظ', he: 'הסתייגות', ja: '留保', ko: '유보', zh: '保留意见', + }, + ], + [ + 'avslag', + { + sv: 'avslag', en: 'rejection', da: 'afslag', no: 'avslag', + fi: 'hylkäys', de: 'Ablehnung', fr: 'rejet', es: 'rechazo', + nl: 'afwijzing', ar: 'رفض', he: 'דחייה', ja: '否決', ko: '기각', zh: '否决', + }, + ], + [ + 'bifall', + { + sv: 'bifall', en: 'approval', da: 'bifald', no: 'bifall', + fi: 'hyväksyminen', de: 'Zustimmung', fr: 'approbation', es: 'aprobación', + nl: 'goedkeuring', ar: 'موافقة', he: 'אישור', ja: '承認', ko: '승인', zh: '批准', + }, + ], + [ + 'sakfråga', + { + sv: 'sakfråga', en: 'subject matter', da: 'sagsspørgsmål', no: 'saksspørsmål', + fi: 'asiakysymys', de: 'Sachfrage', fr: 'question de fond', es: 'cuestión de fondo', + nl: 'zaaksvraag', ar: 'مسألة موضوعية', he: 'שאלת עניין', + ja: '実質的事項', ko: '실질적 사항', zh: '实质问题', + }, + ], + [ + 'ärende', + { + sv: 'ärende', en: 'matter', da: 'sag', no: 'sak', + fi: 'asia', de: 'Angelegenheit', fr: 'affaire', es: 'asunto', + nl: 'zaak', ar: 'شأن', he: 'עניין', ja: '案件', ko: '안건', zh: '事项', + }, + ], + [ + 'beredning', + { + sv: 'beredning', en: 'preparation', da: 'forberedelse', no: 'forberedelse', + fi: 'valmistelu', de: 'Vorbereitung', fr: 'préparation', es: 'preparación', + nl: 'voorbereiding', ar: 'إعداد', he: 'הכנה', ja: '準備', ko: '준비', zh: '准备', + }, + ], + [ + 'utlåtande', + { + sv: 'utlåtande', en: 'statement', da: 'udtalelse', no: 'uttalelse', + fi: 'lausunto', de: 'Erklärung', fr: 'déclaration', es: 'declaración', + nl: 'verklaring', ar: 'بيان', he: 'הצהרה', ja: '声明', ko: '성명', zh: '声明', + }, + ], + [ + 'lagförslag', + { + sv: 'lagförslag', en: 'legislative proposal', da: 'lovforslag', no: 'lovforslag', + fi: 'lakiehdotus', de: 'Gesetzesvorschlag', fr: 'proposition de loi', + es: 'propuesta legislativa', nl: 'wetsvoorstel', + ar: 'مقترح تشريعي', he: 'הצעת חוק', ja: '法案', ko: '법률안', zh: '立法提案', + }, + ], + [ + 'lagstiftning', + { + sv: 'lagstiftning', en: 'legislation', da: 'lovgivning', no: 'lovgivning', + fi: 'lainsäädäntö', de: 'Gesetzgebung', fr: 'législation', es: 'legislación', + nl: 'wetgeving', ar: 'تشريع', he: 'חקיקה', ja: '立法', ko: '입법', zh: '立法', + }, + ], + [ + 'sammanträde', + { + sv: 'sammanträde', en: 'meeting', da: 'møde', no: 'møte', + fi: 'kokous', de: 'Sitzung', fr: 'réunion', es: 'reunión', + nl: 'vergadering', ar: 'اجتماع', he: 'ישיבה', ja: '会議', ko: '회의', zh: '会议', + }, + ], + [ + 'protokoll', + { + sv: 'protokoll', en: 'minutes', da: 'protokol', no: 'protokoll', + fi: 'pöytäkirja', de: 'Protokoll', fr: 'procès-verbal', es: 'acta', + nl: 'notulen', ar: 'محضر', he: 'פרוטוקול', ja: '議事録', ko: '의사록', zh: '会议记录', + }, + ], + [ + 'anförande', + { + sv: 'anförande', en: 'speech', da: 'tale', no: 'innlegg', + fi: 'puheenvuoro', de: 'Rede', fr: 'discours', es: 'discurso', + nl: 'toespraak', ar: 'خطاب', he: 'נאום', ja: '演説', ko: '연설', zh: '演讲', + }, + ], + [ + 'kammaren', + { + sv: 'kammaren', en: 'the Chamber', da: 'kammeret', no: 'kammeret', + fi: 'istuntosali', de: 'die Kammer', fr: 'la Chambre', es: 'la Cámara', + nl: 'de Kamer', ar: 'الغرفة', he: 'האולם', ja: '議場', ko: '본회의장', zh: '议会厅', + }, + ], + [ + 'talman', + { + sv: 'talman', en: 'Speaker', da: 'formand', no: 'stortingspresident', + fi: 'puhemies', de: 'Parlamentspräsident', fr: 'Président du Parlement', + es: 'Presidente del Parlamento', nl: 'Parlementsvoorzitter', + ar: 'رئيس البرلمان', he: 'יושב ראש הפרלמנט', ja: '議長', ko: '의장', zh: '议长', + }, + ], + [ + 'vice talman', + { + sv: 'vice talman', en: 'Deputy Speaker', da: 'næstformand', + no: 'visepresident', fi: 'varapuhemies', de: 'Vizepräsident', + fr: 'Vice-président du Parlement', es: 'Vicepresidente del Parlamento', + nl: 'Vicevoorzitter', ar: 'نائب رئيس البرلمان', he: 'סגן יושב ראש', + ja: '副議長', ko: '부의장', zh: '副议长', + }, + ], + // ---- Budget and fiscal terms ---- + [ + 'anslag', + { + sv: 'anslag', en: 'appropriation', da: 'bevilling', no: 'bevilgning', + fi: 'määräraha', de: 'Bewilligung', fr: 'crédit budgétaire', es: 'asignación', + nl: 'begrotingspost', ar: 'اعتماد مالي', he: 'הקצבה', + ja: '歳出', ko: '세출', zh: '拨款', + }, + ], + [ + 'utgiftsområde', + { + sv: 'utgiftsområde', en: 'expenditure area', da: 'udgiftsområde', + no: 'utgiftsområde', fi: 'menolaji', de: 'Ausgabenbereich', + fr: 'domaine de dépenses', es: 'área de gasto', nl: 'uitgavengebied', + ar: 'مجال الإنفاق', he: 'תחום הוצאה', ja: '歳出分野', ko: '지출분야', zh: '支出领域', + }, + ], + [ + 'rambeslutet', + { + sv: 'rambeslutet', en: 'the framework decision', da: 'rammebeslutningen', + no: 'rammevedtaket', fi: 'kehyspäätös', de: 'der Rahmenbeschluss', + fr: 'la décision-cadre', es: 'la decisión marco', nl: 'het kaderbesluit', + ar: 'القرار الإطاري', he: 'ההחלטה המסגרתית', + ja: '枠組み決定', ko: '기본결정', zh: '框架决定', + }, + ], + [ + 'utgiftstak', + { + sv: 'utgiftstak', en: 'expenditure ceiling', da: 'udgiftsloft', + no: 'utgiftstak', fi: 'menokatto', de: 'Ausgabenobergrenze', + fr: 'plafond de dépenses', es: 'techo de gasto', nl: 'uitgavenplafond', + ar: 'سقف الإنفاق', he: 'תקרת הוצאה', ja: '歳出上限', ko: '지출한도', zh: '支出上限', + }, + ], + [ + 'skatteutgift', + { + sv: 'skatteutgift', en: 'tax expenditure', da: 'skatteudgift', + no: 'skatteutgift', fi: 'verotuki', de: 'Steuerausgabe', + fr: 'dépense fiscale', es: 'gasto fiscal', nl: 'belastinguitgave', + ar: 'نفقات ضريبية', he: 'הוצאת מס', ja: '租税支出', ko: '조세지출', zh: '税收支出', + }, + ], + [ + 'budgetpropositionen', + { + sv: 'budgetpropositionen', en: 'the Budget Bill', da: 'finanslovsforslaget', + no: 'budsjettproposisjonen', fi: 'talousarvioesitys', de: 'der Haushaltsentwurf', + fr: 'le projet de loi de finances', es: 'el proyecto de presupuesto', + nl: 'de begrotingswet', ar: 'مشروع الميزانية', he: 'הצעת התקציב', + ja: '予算案', ko: '예산안', zh: '预算法案', + }, + ], + [ + 'vårpropositionen', + { + sv: 'vårpropositionen', en: 'the Spring Fiscal Policy Bill', + da: 'forårsforslaget', no: 'vårproposisjonen', fi: 'kevätesitys', + de: 'der Frühjahrshaushaltsentwurf', fr: 'le projet de loi de finances de printemps', + es: 'el proyecto de presupuesto de primavera', nl: 'de voorjaarsbegroting', + ar: 'مشروع ميزانية الربيع', he: 'הצעת תקציב האביב', + ja: '春季財政法案', ko: '봄 예산안', zh: '春季财政法案', + }, + ], + [ + 'statsbudgeten', + { + sv: 'statsbudgeten', en: 'the central government budget', da: 'statsbudgettet', + no: 'statsbudsjettet', fi: 'valtion talousarvio', de: 'der Staatshaushalt', + fr: 'le budget de l\'État', es: 'el presupuesto estatal', nl: 'de rijksbegroting', + ar: 'ميزانية الدولة', he: 'תקציב המדינה', + ja: '国家予算', ko: '국가예산', zh: '国家预算', + }, + ], + [ + 'finansplan', + { + sv: 'finansplan', en: 'fiscal policy plan', da: 'finansplan', no: 'finansplan', + fi: 'finanssisuunnitelma', de: 'Finanzplan', fr: 'plan financier', + es: 'plan fiscal', nl: 'financieel plan', + ar: 'خطة مالية', he: 'תוכנית פיסקלית', ja: '財政計画', ko: '재정계획', zh: '财政计划', + }, + ], + [ + 'riksgälden', + { + sv: 'riksgälden', en: 'Swedish National Debt Office', da: 'Riksgælden', + no: 'Riksgjelden', fi: 'Valtiokonttori', de: 'Schwedische Reichsschuldenverwaltung', + fr: 'Office de la dette publique suédoise', es: 'Oficina de Deuda Nacional sueca', + nl: 'Zweedse Rijksschuld', ar: 'مكتب الدين العام السويدي', + he: 'משרד החוב הלאומי השבדי', ja: 'スウェーデン国債局', ko: '스웨덴 국가부채국', zh: '瑞典国债局', + }, + ], + // ---- Interpellation and response terms ---- + [ + 'statsråd', + { + sv: 'statsråd', en: 'cabinet minister', da: 'minister', no: 'statsråd', + fi: 'ministeri', de: 'Kabinettsmitglied', fr: 'ministre du gouvernement', + es: 'ministro del gobierno', nl: 'minister', + ar: 'وزير في الحكومة', he: 'שר ממשלה', ja: '閣僚', ko: '각료', zh: '内阁部长', + }, + ], + [ + 'statsrådet', + { + sv: 'statsrådet', en: 'the cabinet minister', da: 'ministeren', no: 'statsrådet', + fi: 'ministeri', de: 'der Kabinettsmitglied', fr: 'le ministre', + es: 'el ministro', nl: 'de minister', + ar: 'الوزير', he: 'השר', ja: '閣僚', ko: '각료', zh: '部长', + }, + ], + [ + 'skriftlig fråga', + { + sv: 'skriftlig fråga', en: 'written question', da: 'skriftligt spørgsmål', + no: 'skriftlig spørsmål', fi: 'kirjallinen kysymys', de: 'schriftliche Anfrage', + fr: 'question écrite', es: 'pregunta escrita', nl: 'schriftelijke vraag', + ar: 'سؤال كتابي', he: 'שאלה בכתב', ja: '書面質問', ko: '서면질문', zh: '书面提问', + }, + ], + [ + 'svar', + { + sv: 'svar', en: 'answer', da: 'svar', no: 'svar', + fi: 'vastaus', de: 'Antwort', fr: 'réponse', es: 'respuesta', + nl: 'antwoord', ar: 'جواب', he: 'תשובה', ja: '回答', ko: '답변', zh: '答复', + }, + ], + [ + 'debattinlägg', + { + sv: 'debattinlägg', en: 'debate contribution', da: 'debatindlæg', + no: 'debattinnlegg', fi: 'keskustelupuheenvuoro', de: 'Debattenbeitrag', + fr: 'intervention dans le débat', es: 'intervención en el debate', + nl: 'debatbijdrage', ar: 'مداخلة في النقاش', he: 'תרומה לדיון', + ja: '討論への寄与', ko: '토론 기여', zh: '辩论发言', + }, + ], + [ + 'replik', + { + sv: 'replik', en: 'reply', da: 'replik', no: 'replikk', + fi: 'vastapuheenvuoro', de: 'Erwiderung', fr: 'réplique', es: 'réplica', + nl: 'repliek', ar: 'رد', he: 'תשובה', ja: '反論', ko: '반론', zh: '回应', + }, + ], + // ---- EU and international terms ---- + [ + 'ordförandeskap', + { + sv: 'ordförandeskap', en: 'presidency', da: 'formandskab', no: 'formannskap', + fi: 'puheenjohtajuus', de: 'Vorsitz', fr: 'présidence', es: 'presidencia', + nl: 'voorzitterschap', ar: 'رئاسة', he: 'נשיאות', ja: '議長国', ko: '의장국', zh: '轮值主席国', + }, + ], + [ + 'subsidiaritetsgranskning', + { + sv: 'subsidiaritetsgranskning', en: 'subsidiarity review', + da: 'subsidiaritetskontrol', no: 'subsidiaritetskontroll', + fi: 'toissijaisuustarkastus', de: 'Subsidiaritätsprüfung', + fr: 'contrôle de subsidiarité', es: 'control de subsidiariedad', + nl: 'subsidiariteitstoets', ar: 'مراجعة التبعية', he: 'בדיקת סובסידיאריות', + ja: '補完性審査', ko: '보충성 심사', zh: '辅助性审查', + }, + ], + [ + 'europeiska unionen', + { + sv: 'Europeiska unionen', en: 'European Union', da: 'Den Europæiske Union', + no: 'Den europeiske union', fi: 'Euroopan unioni', de: 'Europäische Union', + fr: 'Union européenne', es: 'Unión Europea', nl: 'Europese Unie', + ar: 'الاتحاد الأوروبي', he: 'האיחוד האירופי', + ja: '欧州連合', ko: '유럽연합', zh: '欧盟', + }, + ], + [ + 'eu-nämnden', + { + sv: 'EU-nämnden', en: 'Committee on EU Affairs', da: 'EU-udvalget', + no: 'EU-komiteen', fi: 'EU-valiokunta', de: 'EU-Ausschuss', + fr: 'Comité des affaires européennes', es: 'Comité de Asuntos de la UE', + nl: 'EU-commissie', ar: 'لجنة شؤون الاتحاد الأوروبي', + he: 'ועדת ענייני האיחוד האירופי', ja: 'EU委員会', ko: 'EU위원회', zh: '欧盟事务委员会', + }, + ], + [ + 'europaparlamentet', + { + sv: 'Europaparlamentet', en: 'European Parliament', da: 'Europa-Parlamentet', + no: 'Europaparlamentet', fi: 'Euroopan parlamentti', de: 'Europäisches Parlament', + fr: 'Parlement européen', es: 'Parlamento Europeo', nl: 'Europees Parlement', + ar: 'البرلمان الأوروبي', he: 'הפרלמנט האירופי', + ja: '欧州議会', ko: '유럽의회', zh: '欧洲议会', + }, + ], + [ + 'europarådet', + { + sv: 'Europarådet', en: 'Council of Europe', da: 'Europarådet', + no: 'Europarådet', fi: 'Euroopan neuvosto', de: 'Europarat', + fr: 'Conseil de l\'Europe', es: 'Consejo de Europa', nl: 'Raad van Europa', + ar: 'مجلس أوروبا', he: 'מועצת אירופה', + ja: '欧州評議会', ko: '유럽평의회', zh: '欧洲委员会', + }, + ], + [ + 'nordiska rådet', + { + sv: 'Nordiska rådet', en: 'Nordic Council', da: 'Nordisk Råd', + no: 'Nordisk råd', fi: 'Pohjoismaiden neuvosto', de: 'Nordischer Rat', + fr: 'Conseil nordique', es: 'Consejo Nórdico', nl: 'Noordse Raad', + ar: 'المجلس الشمالي', he: 'המועצה הנורדית', + ja: '北欧理事会', ko: '북유럽이사회', zh: '北欧理事会', + }, + ], + // ---- Geographic and regional terms ---- + [ + 'landsting', + { + sv: 'landsting', en: 'county council', da: 'amt', no: 'fylkesting', + fi: 'maakäräjät', de: 'Provinzialrat', fr: 'conseil départemental', + es: 'consejo provincial', nl: 'provinciale raad', + ar: 'مجلس المقاطعة', he: 'מועצת המחוז', ja: '県議会', ko: '주의회', zh: '省议会', + }, + ], + [ + 'region', + { + sv: 'region', en: 'region', da: 'region', no: 'region', + fi: 'alue', de: 'Region', fr: 'région', es: 'región', + nl: 'regio', ar: 'منطقة', he: 'אזור', ja: '地域', ko: '지역', zh: '地区', + }, + ], + [ + 'kommunalförbund', + { + sv: 'kommunalförbund', en: 'municipal federation', da: 'kommuneforbund', + no: 'kommuneforbund', fi: 'kuntayhtymä', de: 'Kommunalverband', + fr: 'fédération de communes', es: 'federación municipal', + nl: 'gemeentefederatie', ar: 'اتحاد بلديات', he: 'איגוד רשויות', + ja: '市町村連合', ko: '지방자치단체연합', zh: '市政联盟', + }, + ], + [ + 'kommun', + { + sv: 'kommun', en: 'municipality', da: 'kommune', no: 'kommune', + fi: 'kunta', de: 'Gemeinde', fr: 'commune', es: 'municipio', + nl: 'gemeente', ar: 'بلدية', he: 'עירייה', ja: '自治体', ko: '지방자치단체', zh: '市镇', + }, + ], + [ + 'län', + { + sv: 'län', en: 'county', da: 'len', no: 'fylke', + fi: 'lääni', de: 'Provinz', fr: 'comté', es: 'condado', + nl: 'provincie', ar: 'مقاطعة', he: 'מחוז', ja: '県', ko: '주', zh: '省', + }, + ], + [ + 'landsbygd', + { + sv: 'landsbygd', en: 'rural area', da: 'landdistrikt', no: 'landsbygd', + fi: 'maaseutu', de: 'ländliches Gebiet', fr: 'zone rurale', es: 'zona rural', + nl: 'platteland', ar: 'منطقة ريفية', he: 'אזור כפרי', + ja: '農村地域', ko: '농촌 지역', zh: '农村地区', + }, + ], + // ---- Government agencies and institutions ---- + [ + 'riksbanken', + { + sv: 'Riksbanken', en: 'Swedish Central Bank', da: 'Riksbanken', + no: 'Riksbanken', fi: 'Ruotsin keskuspankki', de: 'Schwedische Reichsbank', + fr: 'Banque centrale de Suède', es: 'Banco Central de Suecia', + nl: 'Zweedse Rijksbank', ar: 'البنك المركزي السويدي', he: 'הבנק המרכזי השבדי', + ja: 'スウェーデン国立銀行', ko: '스웨덴 중앙은행', zh: '瑞典央行', + }, + ], + [ + 'riksrevisionen', + { + sv: 'Riksrevisionen', en: 'Swedish National Audit Office', da: 'Rigsrevisionen', + no: 'Riksrevisjonen', fi: 'Ruotsin tarkastusvirasto', de: 'Schwedischer Rechnungshof', + fr: 'Cour des comptes suédoise', es: 'Tribunal de Cuentas sueco', + nl: 'Zweedse Rekenkamer', ar: 'ديوان المراجعة السويدي', he: 'מבקר המדינה השבדי', + ja: 'スウェーデン会計検査院', ko: '스웨덴 감사원', zh: '瑞典审计署', + }, + ], + [ + 'justitieombudsmannen', + { + sv: 'Justitieombudsmannen', en: 'Parliamentary Ombudsman', da: 'Ombudsmanden', + no: 'Sivilombudet', fi: 'Eduskunnan oikeusasiamies', de: 'Parlamentarischer Ombudsmann', + fr: 'Médiateur parlementaire', es: 'Defensor del Pueblo parlamentario', + nl: 'Parlementaire Ombudsman', ar: 'أمين المظالم البرلماني', he: 'נציב הביקורת', + ja: '議会オンブズマン', ko: '의회 옴부즈만', zh: '议会监察专员', + }, + ], + [ + 'valmyndigheten', + { + sv: 'Valmyndigheten', en: 'Swedish Election Authority', da: 'Valgmyndigheden', + no: 'Valgmyndigheten', fi: 'Ruotsin vaaliviranomainen', de: 'Schwedische Wahlbehörde', + fr: 'Autorité électorale suédoise', es: 'Autoridad Electoral sueca', + nl: 'Zweedse Kiesraad', ar: 'هيئة الانتخابات السويدية', he: 'רשות הבחירות השבדית', + ja: 'スウェーデン選挙管理委員会', ko: '스웨덴 선거관리위원회', zh: '瑞典选举管理局', + }, + ], + [ + 'myndigheten', + { + sv: 'myndigheten', en: 'the authority', da: 'myndigheden', no: 'myndigheten', + fi: 'viranomainen', de: 'die Behörde', fr: 'l\'autorité', es: 'la autoridad', + nl: 'de autoriteit', ar: 'السلطة', he: 'הרשות', ja: '当局', ko: '당국', zh: '当局', + }, + ], + [ + 'myndighet', + { + sv: 'myndighet', en: 'authority', da: 'myndighed', no: 'myndighet', + fi: 'viranomainen', de: 'Behörde', fr: 'autorité', es: 'autoridad', + nl: 'autoriteit', ar: 'سلطة', he: 'רשות', ja: '機関', ko: '기관', zh: '机构', + }, + ], + // ---- Legal and constitutional terms ---- + [ + 'grundlag', + { + sv: 'grundlag', en: 'constitution', da: 'grundlov', no: 'grunnlov', + fi: 'perustuslaki', de: 'Verfassung', fr: 'constitution', es: 'constitución', + nl: 'grondwet', ar: 'دستور', he: 'חוקה', ja: '憲法', ko: '헌법', zh: '宪法', + }, + ], + [ + 'riksdagsordningen', + { + sv: 'riksdagsordningen', en: 'the Riksdag Act', da: 'riksdagsordningen', + no: 'stortingsordningen', fi: 'valtiopäiväjärjestys', de: 'die Reichstagsordnung', + fr: 'le règlement du Riksdag', es: 'el reglamento del Riksdag', + nl: 'het Riksdag-reglement', ar: 'نظام البرلمان', he: 'חוק הריקסדאג', + ja: '国会法', ko: '국회법', zh: '国会法', + }, + ], + [ + 'tryckfrihet', + { + sv: 'tryckfrihet', en: 'freedom of the press', da: 'pressefrihed', + no: 'pressefrihet', fi: 'painovapaus', de: 'Pressefreiheit', + fr: 'liberté de la presse', es: 'libertad de prensa', nl: 'persvrijheid', + ar: 'حرية الصحافة', he: 'חופש העיתונות', ja: '報道の自由', ko: '언론의 자유', zh: '新闻自由', + }, + ], + [ + 'yttrandefrihet', + { + sv: 'yttrandefrihet', en: 'freedom of expression', da: 'ytringsfrihed', + no: 'ytringsfrihet', fi: 'sananvapaus', de: 'Meinungsfreiheit', + fr: 'liberté d\'expression', es: 'libertad de expresión', nl: 'vrijheid van meningsuiting', + ar: 'حرية التعبير', he: 'חופש הביטוי', ja: '表現の自由', ko: '표현의 자유', zh: '言论自由', + }, + ], + [ + 'offentlighetsprincipen', + { + sv: 'offentlighetsprincipen', en: 'principle of public access', + da: 'offentlighedsprincippet', no: 'offentlighetsprinsippet', + fi: 'julkisuusperiaate', de: 'Öffentlichkeitsprinzip', + fr: 'principe de transparence', es: 'principio de publicidad', + nl: 'openbaarheidsbeginsel', ar: 'مبدأ الشفافية', he: 'עקרון הגישה הציבורית', + ja: '情報公開原則', ko: '공개원칙', zh: '信息公开原则', + }, + ], + [ + 'förordning', + { + sv: 'förordning', en: 'ordinance', da: 'forordning', no: 'forskrift', + fi: 'asetus', de: 'Verordnung', fr: 'ordonnance', es: 'ordenanza', + nl: 'verordening', ar: 'مرسوم', he: 'תקנה', ja: '政令', ko: '시행령', zh: '法令', + }, + ], + [ + 'direktiv', + { + sv: 'direktiv', en: 'directive', da: 'direktiv', no: 'direktiv', + fi: 'direktiivi', de: 'Richtlinie', fr: 'directive', es: 'directiva', + nl: 'richtlijn', ar: 'توجيه', he: 'הנחיה', ja: '指令', ko: '지침', zh: '指令', + }, + ], + // ---- Policy domain terms ---- + [ + 'arbetsmarknad', + { + sv: 'arbetsmarknad', en: 'labour market', da: 'arbejdsmarked', no: 'arbeidsmarked', + fi: 'työmarkkinat', de: 'Arbeitsmarkt', fr: 'marché du travail', + es: 'mercado laboral', nl: 'arbeidsmarkt', ar: 'سوق العمل', he: 'שוק העבודה', + ja: '労働市場', ko: '노동시장', zh: '劳动市场', + }, + ], + [ + 'infrastruktur', + { + sv: 'infrastruktur', en: 'infrastructure', da: 'infrastruktur', + no: 'infrastruktur', fi: 'infrastruktuuri', de: 'Infrastruktur', + fr: 'infrastructure', es: 'infraestructura', nl: 'infrastructuur', + ar: 'بنية تحتية', he: 'תשתית', ja: 'インフラ', ko: '인프라', zh: '基础设施', + }, + ], + [ + 'näringsliv', + { + sv: 'näringsliv', en: 'business', da: 'erhvervsliv', no: 'næringsliv', + fi: 'elinkeinoelämä', de: 'Wirtschaft', fr: 'secteur privé', es: 'sector empresarial', + nl: 'bedrijfsleven', ar: 'قطاع الأعمال', he: 'מגזר עסקי', + ja: '産業界', ko: '산업계', zh: '商业', + }, + ], + [ + 'jordbruk', + { + sv: 'jordbruk', en: 'agriculture', da: 'landbrug', no: 'landbruk', + fi: 'maatalous', de: 'Landwirtschaft', fr: 'agriculture', es: 'agricultura', + nl: 'landbouw', ar: 'زراعة', he: 'חקלאות', ja: '農業', ko: '농업', zh: '农业', + }, + ], + [ + 'transport', + { + sv: 'transport', en: 'transport', da: 'transport', no: 'transport', + fi: 'liikenne', de: 'Verkehr', fr: 'transport', es: 'transporte', + nl: 'vervoer', ar: 'نقل', he: 'תחבורה', ja: '交通', ko: '교통', zh: '交通', + }, + ], + [ + 'socialförsäkring', + { + sv: 'socialförsäkring', en: 'social insurance', da: 'socialforsikring', + no: 'sosialforsikring', fi: 'sosiaalivakuutus', de: 'Sozialversicherung', + fr: 'assurance sociale', es: 'seguro social', nl: 'sociale verzekering', + ar: 'تأمين اجتماعي', he: 'ביטוח סוציאלי', ja: '社会保険', ko: '사회보험', zh: '社会保险', + }, + ], + [ + 'rättsväsende', + { + sv: 'rättsväsende', en: 'judiciary', da: 'retsvæsen', no: 'rettsvesen', + fi: 'oikeuslaitos', de: 'Justizwesen', fr: 'système judiciaire', + es: 'sistema judicial', nl: 'rechterlijke macht', + ar: 'الجهاز القضائي', he: 'מערכת המשפט', ja: '司法制度', ko: '사법부', zh: '司法机构', + }, + ], + [ + 'forskning', + { + sv: 'forskning', en: 'research', da: 'forskning', no: 'forskning', + fi: 'tutkimus', de: 'Forschung', fr: 'recherche', es: 'investigación', + nl: 'onderzoek', ar: 'بحث', he: 'מחקר', ja: '研究', ko: '연구', zh: '研究', + }, + ], + [ + 'kultur', + { + sv: 'kultur', en: 'culture', da: 'kultur', no: 'kultur', + fi: 'kulttuuri', de: 'Kultur', fr: 'culture', es: 'cultura', + nl: 'cultuur', ar: 'ثقافة', he: 'תרבות', ja: '文化', ko: '문화', zh: '文化', + }, + ], + [ + 'bistånd', + { + sv: 'bistånd', en: 'development aid', da: 'bistand', no: 'bistand', + fi: 'kehitysapu', de: 'Entwicklungshilfe', fr: 'aide au développement', + es: 'ayuda al desarrollo', nl: 'ontwikkelingshulp', + ar: 'مساعدات تنمية', he: 'סיוע לפיתוח', ja: '開発援助', ko: '개발원조', zh: '发展援助', + }, + ], + [ + 'pension', + { + sv: 'pension', en: 'pension', da: 'pension', no: 'pensjon', + fi: 'eläke', de: 'Rente', fr: 'pension', es: 'pensión', + nl: 'pensioen', ar: 'معاش', he: 'פנסיה', ja: '年金', ko: '연금', zh: '养老金', + }, + ], + [ + 'invandring', + { + sv: 'invandring', en: 'immigration', da: 'indvandring', no: 'innvandring', + fi: 'maahanmuutto', de: 'Einwanderung', fr: 'immigration', es: 'inmigración', + nl: 'immigratie', ar: 'هجرة', he: 'הגירה', ja: '移民', ko: '이민', zh: '移民', + }, + ], + [ + 'integration', + { + sv: 'integration', en: 'integration', da: 'integration', no: 'integrasjon', + fi: 'integraatio', de: 'Integration', fr: 'intégration', es: 'integración', + nl: 'integratie', ar: 'اندماج', he: 'שילוב', ja: '統合', ko: '통합', zh: '融合', + }, + ], + [ + 'jämställdhet', + { + sv: 'jämställdhet', en: 'gender equality', da: 'ligestilling', no: 'likestilling', + fi: 'tasa-arvo', de: 'Gleichstellung', fr: 'égalité des genres', + es: 'igualdad de género', nl: 'gendergelijkheid', + ar: 'المساواة بين الجنسين', he: 'שוויון מגדרי', + ja: 'ジェンダー平等', ko: '성평등', zh: '性别平等', + }, + ], + [ + 'säkerhetspolitik', + { + sv: 'säkerhetspolitik', en: 'security policy', da: 'sikkerhedspolitik', + no: 'sikkerhetspolitikk', fi: 'turvallisuuspolitiikka', de: 'Sicherheitspolitik', + fr: 'politique de sécurité', es: 'política de seguridad', + nl: 'veiligheidsbeleid', ar: 'سياسة أمنية', he: 'מדיניות ביטחון', + ja: '安全保障政策', ko: '안보정책', zh: '安全政策', + }, + ], + [ + 'utrikespolitik', + { + sv: 'utrikespolitik', en: 'foreign policy', da: 'udenrigspolitik', + no: 'utenrikspolitikk', fi: 'ulkopolitiikka', de: 'Außenpolitik', + fr: 'politique étrangère', es: 'política exterior', nl: 'buitenlands beleid', + ar: 'سياسة خارجية', he: 'מדיניות חוץ', ja: '外交政策', ko: '외교정책', zh: '外交政策', + }, + ], + [ + 'socialpolitik', + { + sv: 'socialpolitik', en: 'social policy', da: 'socialpolitik', + no: 'sosialpolitikk', fi: 'sosiaalipolitiikka', de: 'Sozialpolitik', + fr: 'politique sociale', es: 'política social', nl: 'sociaal beleid', + ar: 'سياسة اجتماعية', he: 'מדיניות חברתית', + ja: '社会政策', ko: '사회정책', zh: '社会政策', + }, + ], +]; diff --git a/scripts/translation-dictionary.ts b/scripts/translation-dictionary.ts index 44b370ca13..f8cc15a048 100644 --- a/scripts/translation-dictionary.ts +++ b/scripts/translation-dictionary.ts @@ -10,9 +10,17 @@ * * Supported languages: en, da, no, fi, de, fr, es, nl, ar, he, ja, ko, zh * (Swedish 'sv' articles keep original text and only have the attribute removed.) + * + * Domain-specific sub-dictionaries (split for maintainability): + * - translation-dictionary-committee-names.ts — institution + committee names + * - translation-dictionary-party-names.ts — ministry + party group names + * - translation-dictionary-political-terms.ts — procedure, budget, EU, legal, policy terms */ import type { Language } from './types/language.js'; +import { COMMITTEE_NAME_TERMS } from './translation-dictionary-committee-names.js'; +import { PARTY_NAME_TERMS } from './translation-dictionary-party-names.js'; +import { POLITICAL_TERMS } from './translation-dictionary-political-terms.js'; /** * Per-language dictionary of Swedish term → translated term. @@ -90,188 +98,9 @@ const TERMS: ReadonlyArray]> = [ // ---- Document type prefixes ---- ['med anledning av prop.', motionResponsePropPrefix], ['med anledning av skr.', motionResponseSkrPrefix], - // ---- Swedish parliamentary institution names ---- - [ - 'riksdagen', - { - sv: 'riksdagen', en: 'the Riksdag', da: 'Riksdag', no: 'Riksdag', - fi: 'Riksdag', de: 'Riksdag', fr: 'le Riksdag', es: 'el Riksdag', - nl: 'de Riksdag', ar: 'البرلمان السويدي', he: 'הריקסדאג', - ja: 'スウェーデン国会', ko: '스웨덴 의회', zh: '瑞典议会', - }, - ], - [ - 'regeringen', - { - sv: 'regeringen', en: 'the Government', da: 'regeringen', no: 'regjeringen', - fi: 'hallitus', de: 'die Regierung', fr: 'le gouvernement', es: 'el gobierno', - nl: 'de regering', ar: 'الحكومة', he: 'הממשלה', - ja: '政府', ko: '정부', zh: '政府', - }, - ], - // ---- Committee names ---- - [ - 'arbetsmarknadsutskottet', - { - sv: 'arbetsmarknadsutskottet', en: 'Committee on Labour Market Affairs', - da: 'Arbejdsmarkedsudvalget', no: 'Arbeidsmarkedskomiteen', - fi: 'Työvaliokunta', de: 'Ausschuss für Arbeitsmarktangelegenheiten', - fr: 'Comité du marché du travail', es: 'Comité de Mercado Laboral', - nl: 'Commissie voor Arbeidsmarktzaken', ar: 'لجنة سوق العمل', - he: 'ועדת שוק העבודה', ja: '労働市場委員会', ko: '노동시장위원회', zh: '劳动市场委员会', - }, - ], - [ - 'civilutskottet', - { - sv: 'civilutskottet', en: 'Committee on Civil Affairs', - da: 'Civiludvalget', no: 'Sivilkomiteen', fi: 'Siviiliasioiden valiokunta', - de: 'Ausschuss für Zivilrecht', fr: 'Comité des affaires civiles', - es: 'Comité de Asuntos Civiles', nl: 'Commissie voor Burgerlijke Zaken', - ar: 'لجنة الشؤون المدنية', he: 'ועדת ענייני אזרחות', - ja: '市民問題委員会', ko: '민사문제위원회', zh: '民事委员会', - }, - ], - [ - 'finansutskottet', - { - sv: 'finansutskottet', en: 'Committee on Finance', - da: 'Finansudvalget', no: 'Finanskomiteen', fi: 'Valtiovarainvaliokunta', - de: 'Finanzausschuss', fr: 'Comité des finances', - es: 'Comité de Finanzas', nl: 'Financiëncommissie', - ar: 'لجنة المالية', he: 'ועדת האוצר', - ja: '財政委員会', ko: '재정위원회', zh: '财政委员会', - }, - ], - [ - 'försvarsutskottet', - { - sv: 'försvarsutskottet', en: 'Committee on Defence', - da: 'Forsvarsudvalget', no: 'Forsvarskomiteen', fi: 'Puolustusvaliokunta', - de: 'Verteidigungsausschuss', fr: 'Comité de la défense', - es: 'Comité de Defensa', nl: 'Defensiecommissie', - ar: 'لجنة الدفاع', he: 'ועדת הביטחון', ja: '防衛委員会', ko: '방위위원회', zh: '国防委员会', - }, - ], - [ - 'justitieutskottet', - { - sv: 'justitieutskottet', en: 'Committee on Justice', - da: 'Retsudvalget', no: 'Justiskomiteen', fi: 'Lakivaliokunta', - de: 'Rechtsausschuss', fr: 'Comité de justice', - es: 'Comité de Justicia', nl: 'Justitiecommissie', - ar: 'لجنة العدل', he: 'ועדת המשפטים', ja: '司法委員会', ko: '법무위원회', zh: '司法委员会', - }, - ], - [ - 'konstitutionsutskottet', - { - sv: 'konstitutionsutskottet', en: 'Committee on the Constitution', - da: 'Forfatningsudvalget', no: 'Konstitusjonskomiteen', fi: 'Perustuslakivaliokunta', - de: 'Verfassungsausschuss', fr: 'Comité de la Constitution', - es: 'Comité Constitucional', nl: 'Grondwetcommissie', - ar: 'لجنة الدستور', he: 'ועדת החוקה', ja: '憲法委員会', ko: '헌법위원회', zh: '宪法委员会', - }, - ], - [ - 'kulturutskottet', - { - sv: 'kulturutskottet', en: 'Committee on Cultural Affairs', - da: 'Kulturudvalget', no: 'Kulturkomiteen', fi: 'Kulttuurivaliokunta', - de: 'Kulturausschuss', fr: 'Comité de la culture', - es: 'Comité de Cultura', nl: 'Cultuurcommissie', - ar: 'لجنة الثقافة', he: 'ועדת התרבות', ja: '文化委員会', ko: '문화위원회', zh: '文化委员会', - }, - ], - [ - 'miljö- och jordbruksutskottet', - { - sv: 'miljö- och jordbruksutskottet', en: 'Committee on Environment and Agriculture', - da: 'Miljø- og Landbrugsudvalget', no: 'Miljø- og Landbrukskomiteen', - fi: 'Ympäristö- ja maatalousvaliokunta', - de: 'Ausschuss für Umwelt und Landwirtschaft', - fr: 'Comité de l\'environnement et de l\'agriculture', - es: 'Comité de Medio Ambiente y Agricultura', - nl: 'Commissie voor Milieu en Landbouw', - ar: 'لجنة البيئة والزراعة', he: 'ועדת הסביבה והחקלאות', - ja: '環境農業委員会', ko: '환경농업위원회', zh: '环境农业委员会', - }, - ], - [ - 'näringsutskottet', - { - sv: 'näringsutskottet', en: 'Committee on Industry and Trade', - da: 'Erhvervsudvalget', no: 'Næringskomiteen', fi: 'Talousvaliokunta', - de: 'Ausschuss für Wirtschaft und Handel', fr: 'Comité de l\'industrie et du commerce', - es: 'Comité de Industria y Comercio', nl: 'Commissie voor Industrie en Handel', - ar: 'لجنة الصناعة والتجارة', he: 'ועדת התעשייה והמסחר', - ja: '産業貿易委員会', ko: '산업통상위원회', zh: '工业贸易委员会', - }, - ], - [ - 'skatteutskottet', - { - sv: 'skatteutskottet', en: 'Committee on Taxation', - da: 'Skatteudvalget', no: 'Skattekomiteen', fi: 'Verovaliokunta', - de: 'Steuerausschuss', fr: 'Comité de la fiscalité', - es: 'Comité Fiscal', nl: 'Belastingcommissie', - ar: 'لجنة الضرائب', he: 'ועדת המיסים', ja: '税制委員会', ko: '세금위원회', zh: '税务委员会', - }, - ], - [ - 'socialförsäkringsutskottet', - { - sv: 'socialförsäkringsutskottet', en: 'Committee on Social Insurance', - da: 'Socialforsikringsudvalget', no: 'Sosialforsikringskomiteen', - fi: 'Sosiaalivakuutusvaliokunta', - de: 'Ausschuss für Sozialversicherung', fr: 'Comité de l\'assurance sociale', - es: 'Comité de Seguro Social', nl: 'Commissie voor Sociale Verzekering', - ar: 'لجنة التأمين الاجتماعي', he: 'ועדת הביטוח הסוציאלי', - ja: '社会保険委員会', ko: '사회보험위원회', zh: '社会保险委员会', - }, - ], - [ - 'socialutskottet', - { - sv: 'socialutskottet', en: 'Committee on Social Affairs', - da: 'Socialudvalget', no: 'Sosialkomiteen', fi: 'Sosiaaliasioiden valiokunta', - de: 'Sozialausschuss', fr: 'Comité des affaires sociales', - es: 'Comité de Asuntos Sociales', nl: 'Sociale Commissie', - ar: 'لجنة الشؤون الاجتماعية', he: 'ועדת הרווחה', - ja: '社会問題委員会', ko: '사회문제위원회', zh: '社会事务委员会', - }, - ], - [ - 'trafikutskottet', - { - sv: 'trafikutskottet', en: 'Committee on Transport', - da: 'Trafikudvalget', no: 'Transportkomiteen', fi: 'Liikennevaliokunta', - de: 'Verkehrsausschuss', fr: 'Comité des transports', - es: 'Comité de Transporte', nl: 'Transportcommissie', - ar: 'لجنة المواصلات', he: 'ועדת התחבורה', ja: '交通委員会', ko: '교통위원회', zh: '交通委员会', - }, - ], - [ - 'utbildningsutskottet', - { - sv: 'utbildningsutskottet', en: 'Committee on Education', - da: 'Uddannelsesudvalget', no: 'Utdanningskomiteen', fi: 'Koulutusvaliokunta', - de: 'Bildungsausschuss', fr: 'Comité de l\'éducation', - es: 'Comité de Educación', nl: 'Onderwijscommissie', - ar: 'لجنة التعليم', he: 'ועדת החינוך', ja: '教育委員会', ko: '교육위원회', zh: '教育委员会', - }, - ], - [ - 'utrikesutskottet', - { - sv: 'utrikesutskottet', en: 'Committee on Foreign Affairs', - da: 'Udenrigsudvalget', no: 'Utenrikskomiteen', fi: 'Ulkoasiainvaliokunta', - de: 'Außenpolitischer Ausschuss', fr: 'Comité des affaires étrangères', - es: 'Comité de Asuntos Exteriores', nl: 'Commissie voor Buitenlandse Zaken', - ar: 'لجنة الشؤون الخارجية', he: 'ועדת החוץ', - ja: '外務委員会', ko: '외무위원회', zh: '外交委员会', - }, - ], + // Institutional, committee and party names are defined in domain-specific files; + // they are imported and spread here to keep this file maintainable. + ...COMMITTEE_NAME_TERMS, // ---- Document types ---- [ 'proposition', @@ -614,922 +443,8 @@ const TERMS: ReadonlyArray]> = [ nl: 'handel', ar: 'تجارة', he: 'מסחר', ja: '貿易', ko: '무역', zh: '贸易', }, ], - // ---- Swedish Ministry names (11 ministries) ---- - [ - 'finansdepartementet', - { - sv: 'finansdepartementet', en: 'Ministry of Finance', da: 'Finansministeriet', - no: 'Finansdepartementet', fi: 'Valtiovarainministeriö', de: 'Finanzministerium', - fr: 'Ministère des Finances', es: 'Ministerio de Hacienda', - nl: 'Ministerie van Financiën', ar: 'وزارة المالية', he: 'משרד האוצר', - ja: '財務省', ko: '재무부', zh: '财政部', - }, - ], - [ - 'justitiedepartementet', - { - sv: 'justitiedepartementet', en: 'Ministry of Justice', da: 'Justitsministeriet', - no: 'Justisdepartementet', fi: 'Oikeusministeriö', de: 'Justizministerium', - fr: 'Ministère de la Justice', es: 'Ministerio de Justicia', - nl: 'Ministerie van Justitie', ar: 'وزارة العدل', he: 'משרד המשפטים', - ja: '法務省', ko: '법무부', zh: '司法部', - }, - ], - [ - 'utrikesdepartementet', - { - sv: 'utrikesdepartementet', en: 'Ministry for Foreign Affairs', da: 'Udenrigsministeriet', - no: 'Utenriksdepartementet', fi: 'Ulkoministeriö', de: 'Außenministerium', - fr: 'Ministère des Affaires étrangères', es: 'Ministerio de Asuntos Exteriores', - nl: 'Ministerie van Buitenlandse Zaken', ar: 'وزارة الخارجية', he: 'משרד החוץ', - ja: '外務省', ko: '외교부', zh: '外交部', - }, - ], - [ - 'försvarsdepartementet', - { - sv: 'försvarsdepartementet', en: 'Ministry of Defence', da: 'Forsvarsministeriet', - no: 'Forsvarsdepartementet', fi: 'Puolustusministeriö', de: 'Verteidigungsministerium', - fr: 'Ministère de la Défense', es: 'Ministerio de Defensa', - nl: 'Ministerie van Defensie', ar: 'وزارة الدفاع', he: 'משרד הביטחון', - ja: '防衛省', ko: '국방부', zh: '国防部', - }, - ], - [ - 'socialdepartementet', - { - sv: 'socialdepartementet', en: 'Ministry of Health and Social Affairs', - da: 'Socialministeriet', no: 'Sosialdepartementet', fi: 'Sosiaali- ja terveysministeriö', - de: 'Ministerium für Gesundheit und Soziales', fr: 'Ministère de la Santé et des Affaires sociales', - es: 'Ministerio de Salud y Asuntos Sociales', nl: 'Ministerie van Volksgezondheid en Sociale Zaken', - ar: 'وزارة الصحة والشؤون الاجتماعية', he: 'משרד הבריאות והרווחה', - ja: '保健社会省', ko: '보건사회부', zh: '卫生和社会事务部', - }, - ], - [ - 'utbildningsdepartementet', - { - sv: 'utbildningsdepartementet', en: 'Ministry of Education and Research', - da: 'Uddannelsesministeriet', no: 'Utdanningsdepartementet', - fi: 'Opetus- ja kulttuuriministeriö', de: 'Ministerium für Bildung und Forschung', - fr: 'Ministère de l\'Éducation et de la Recherche', es: 'Ministerio de Educación e Investigación', - nl: 'Ministerie van Onderwijs en Onderzoek', ar: 'وزارة التعليم والبحث العلمي', - he: 'משרד החינוך והמחקר', ja: '教育研究省', ko: '교육연구부', zh: '教育研究部', - }, - ], - [ - 'miljödepartementet', - { - sv: 'miljödepartementet', en: 'Ministry of Climate and Enterprise', - da: 'Miljøministeriet', no: 'Miljødepartementet', fi: 'Ympäristöministeriö', - de: 'Ministerium für Klima und Wirtschaft', fr: 'Ministère du Climat et de l\'Entreprise', - es: 'Ministerio de Clima y Empresa', nl: 'Ministerie van Klimaat en Onderneming', - ar: 'وزارة المناخ والأعمال', he: 'משרד האקלים והיזמות', - ja: '気候企業省', ko: '기후기업부', zh: '气候和企业部', - }, - ], - [ - 'näringsdepartementet', - { - sv: 'näringsdepartementet', en: 'Ministry of Enterprise and Innovation', - da: 'Erhvervsministeriet', no: 'Næringsdepartementet', fi: 'Työ- ja elinkeinoministeriö', - de: 'Ministerium für Wirtschaft und Innovation', fr: 'Ministère de l\'Entreprise et de l\'Innovation', - es: 'Ministerio de Empresa e Innovación', nl: 'Ministerie van Economische Zaken', - ar: 'وزارة المؤسسات والابتكار', he: 'משרד הכלכלה והחדשנות', - ja: '企業革新省', ko: '기업혁신부', zh: '企业创新部', - }, - ], - [ - 'kulturdepartementet', - { - sv: 'kulturdepartementet', en: 'Ministry of Culture', da: 'Kulturministeriet', - no: 'Kulturdepartementet', fi: 'Kulttuuriministeriö', de: 'Kulturministerium', - fr: 'Ministère de la Culture', es: 'Ministerio de Cultura', - nl: 'Ministerie van Cultuur', ar: 'وزارة الثقافة', he: 'משרד התרבות', - ja: '文化省', ko: '문화부', zh: '文化部', - }, - ], - [ - 'infrastrukturdepartementet', - { - sv: 'infrastrukturdepartementet', en: 'Ministry of Infrastructure', - da: 'Infrastrukturministeriet', no: 'Infrastrukturdepartementet', - fi: 'Infrastruktuuriministeriö', de: 'Infrastrukturministerium', - fr: 'Ministère de l\'Infrastructure', es: 'Ministerio de Infraestructura', - nl: 'Ministerie van Infrastructuur', ar: 'وزارة البنية التحتية', - he: 'משרד התשתיות', ja: 'インフラ省', ko: '인프라부', zh: '基础设施部', - }, - ], - [ - 'arbetsmarknadsdepartementet', - { - sv: 'arbetsmarknadsdepartementet', en: 'Ministry of Employment', - da: 'Beskæftigelsesministeriet', no: 'Arbeids- og inkluderingsdepartementet', - fi: 'Työministeriö', de: 'Arbeitsministerium', fr: 'Ministère de l\'Emploi', - es: 'Ministerio de Empleo', nl: 'Ministerie van Werkgelegenheid', - ar: 'وزارة العمل', he: 'משרד העבודה', ja: '雇用省', ko: '고용부', zh: '就业部', - }, - ], - // ---- Swedish political party group names (8 parliamentary parties) ---- - [ - 'socialdemokraterna', - { - sv: 'Socialdemokraterna', en: 'Social Democrats', da: 'Socialdemokraterne', - no: 'Sosialdemokratene', fi: 'Sosiaalidemokraatit', de: 'Sozialdemokraten', - fr: 'Sociaux-démocrates', es: 'Socialdemócratas', nl: 'Sociaaldemocraten', - ar: 'الاشتراكيون الديمقراطيون', he: 'סוציאל-דמוקרטים', - ja: '社会民主党', ko: '사회민주당', zh: '社会民主党', - }, - ], - [ - 'moderaterna', - { - sv: 'Moderaterna', en: 'Moderate Party', da: 'Moderaterne', - no: 'Moderatene', fi: 'Maltillinen kokoomus', de: 'Moderate Sammlungspartei', - fr: 'Parti modéré', es: 'Partido Moderado', nl: 'Gematigde Partij', - ar: 'حزب المحافظين', he: 'המפלגה המתונה', - ja: '穏健党', ko: '온건당', zh: '温和党', - }, - ], - [ - 'sverigedemokraterna', - { - sv: 'Sverigedemokraterna', en: 'Sweden Democrats', da: 'Sverigedemokraterne', - no: 'Sverigedemokratene', fi: 'Ruotsidemokraatit', de: 'Schwedendemokraten', - fr: 'Démocrates de Suède', es: 'Demócratas de Suecia', nl: 'Zweden-Democraten', - ar: 'ديمقراطيو السويد', he: 'דמוקרטים שבדים', - ja: 'スウェーデン民主党', ko: '스웨덴민주당', zh: '瑞典民主党', - }, - ], - [ - 'centerpartiet', - { - sv: 'Centerpartiet', en: 'Centre Party', da: 'Centerpartiet', - no: 'Senterpartiet', fi: 'Keskustapuolue', de: 'Zentrumspartei', - fr: 'Parti du Centre', es: 'Partido de Centro', nl: 'Centrumpartij', - ar: 'حزب الوسط', he: 'מפלגת המרכז', - ja: '中央党', ko: '중앙당', zh: '中间党', - }, - ], - [ - 'vänsterpartiet', - { - sv: 'Vänsterpartiet', en: 'Left Party', da: 'Venstrepartiet', - no: 'Venstrepartiet', fi: 'Vasemmistopuolue', de: 'Linkspartei', - fr: 'Parti de gauche', es: 'Partido de Izquierda', nl: 'Linkse Partij', - ar: 'حزب اليسار', he: 'מפלגת השמאל', - ja: '左翼党', ko: '좌파당', zh: '左翼党', - }, - ], - [ - 'kristdemokraterna', - { - sv: 'Kristdemokraterna', en: 'Christian Democrats', da: 'Kristendemokraterne', - no: 'Kristeligdemokratene', fi: 'Kristillisdemokraatit', de: 'Christdemokraten', - fr: 'Chrétiens-démocrates', es: 'Demócratas Cristianos', nl: 'Christendemocraten', - ar: 'الديمقراطيون المسيحيون', he: 'דמוקרטים נוצרים', - ja: 'キリスト教民主党', ko: '기독민주당', zh: '基督教民主党', - }, - ], - [ - 'liberalerna', - { - sv: 'Liberalerna', en: 'Liberals', da: 'Liberalerne', - no: 'Liberalerne', fi: 'Liberaalit', de: 'Liberale', - fr: 'Libéraux', es: 'Liberales', nl: 'Liberalen', - ar: 'الليبراليون', he: 'ליברלים', - ja: '自由党', ko: '자유당', zh: '自由党', - }, - ], - [ - 'miljöpartiet', - { - sv: 'Miljöpartiet', en: 'Green Party', da: 'Miljøpartiet', - no: 'Miljøpartiet', fi: 'Ympäristöpuolue', de: 'Grüne Partei', - fr: 'Parti Vert', es: 'Partido Verde', nl: 'Groene Partij', - ar: 'حزب البيئة', he: 'המפלגה הירוקה', - ja: '緑の党', ko: '녹색당', zh: '绿党', - }, - ], - // ---- Parliamentary procedure terms ---- - [ - 'anmälan', - { - sv: 'anmälan', en: 'notification', da: 'anmeldelse', no: 'anmeldelse', - fi: 'ilmoitus', de: 'Anmeldung', fr: 'notification', es: 'notificación', - nl: 'melding', ar: 'إخطار', he: 'הודעה', ja: '届出', ko: '신고', zh: '通知', - }, - ], - [ - 'besvarat', - { - sv: 'besvarat', en: 'answered', da: 'besvaret', no: 'besvart', - fi: 'vastattu', de: 'beantwortet', fr: 'répondu', es: 'respondido', - nl: 'beantwoord', ar: 'تمت الإجابة', he: 'הושב', ja: '回答済み', ko: '답변됨', zh: '已答复', - }, - ], - [ - 'granskning', - { - sv: 'granskning', en: 'review', da: 'gennemgang', no: 'gjennomgang', - fi: 'tarkastus', de: 'Überprüfung', fr: 'examen', es: 'revisión', - nl: 'beoordeling', ar: 'مراجعة', he: 'ביקורת', ja: '審査', ko: '심사', zh: '审查', - }, - ], - [ - 'yttrande', - { - sv: 'yttrande', en: 'opinion', da: 'udtalelse', no: 'uttalelse', - fi: 'lausunto', de: 'Stellungnahme', fr: 'avis', es: 'dictamen', - nl: 'advies', ar: 'رأي', he: 'חוות דעת', ja: '意見書', ko: '의견서', zh: '意见', - }, - ], - [ - 'bordläggning', - { - sv: 'bordläggning', en: 'tabling', da: 'bordlæggelse', no: 'bordlegging', - fi: 'pöydällepano', de: 'Vertagung', fr: 'ajournement', es: 'aplazamiento', - nl: 'verdaging', ar: 'تأجيل', he: 'דחייה', ja: '延期', ko: '보류', zh: '搁置', - }, - ], - [ - 'tillkännagivande', - { - sv: 'tillkännagivande', en: 'announcement', da: 'meddelelse', no: 'kunngjøring', - fi: 'tiedonanto', de: 'Bekanntmachung', fr: 'communication', es: 'comunicado', - nl: 'mededeling', ar: 'إعلان', he: 'הודעה', ja: '告示', ko: '공고', zh: '公告', - }, - ], - [ - 'reservation', - { - sv: 'reservation', en: 'reservation', da: 'reservation', no: 'reservasjon', - fi: 'varaus', de: 'Vorbehalt', fr: 'réserve', es: 'reserva', - nl: 'voorbehoud', ar: 'تحفظ', he: 'הסתייגות', ja: '留保', ko: '유보', zh: '保留意见', - }, - ], - [ - 'avslag', - { - sv: 'avslag', en: 'rejection', da: 'afslag', no: 'avslag', - fi: 'hylkäys', de: 'Ablehnung', fr: 'rejet', es: 'rechazo', - nl: 'afwijzing', ar: 'رفض', he: 'דחייה', ja: '否決', ko: '기각', zh: '否决', - }, - ], - [ - 'bifall', - { - sv: 'bifall', en: 'approval', da: 'bifald', no: 'bifall', - fi: 'hyväksyminen', de: 'Zustimmung', fr: 'approbation', es: 'aprobación', - nl: 'goedkeuring', ar: 'موافقة', he: 'אישור', ja: '承認', ko: '승인', zh: '批准', - }, - ], - [ - 'sakfråga', - { - sv: 'sakfråga', en: 'subject matter', da: 'sagsspørgsmål', no: 'saksspørsmål', - fi: 'asiakysymys', de: 'Sachfrage', fr: 'question de fond', es: 'cuestión de fondo', - nl: 'zaaksvraag', ar: 'مسألة موضوعية', he: 'שאלת עניין', - ja: '実質的事項', ko: '실질적 사항', zh: '实质问题', - }, - ], - [ - 'ärende', - { - sv: 'ärende', en: 'matter', da: 'sag', no: 'sak', - fi: 'asia', de: 'Angelegenheit', fr: 'affaire', es: 'asunto', - nl: 'zaak', ar: 'شأن', he: 'עניין', ja: '案件', ko: '안건', zh: '事项', - }, - ], - [ - 'beredning', - { - sv: 'beredning', en: 'preparation', da: 'forberedelse', no: 'forberedelse', - fi: 'valmistelu', de: 'Vorbereitung', fr: 'préparation', es: 'preparación', - nl: 'voorbereiding', ar: 'إعداد', he: 'הכנה', ja: '準備', ko: '준비', zh: '准备', - }, - ], - [ - 'utlåtande', - { - sv: 'utlåtande', en: 'statement', da: 'udtalelse', no: 'uttalelse', - fi: 'lausunto', de: 'Erklärung', fr: 'déclaration', es: 'declaración', - nl: 'verklaring', ar: 'بيان', he: 'הצהרה', ja: '声明', ko: '성명', zh: '声明', - }, - ], - [ - 'lagförslag', - { - sv: 'lagförslag', en: 'legislative proposal', da: 'lovforslag', no: 'lovforslag', - fi: 'lakiehdotus', de: 'Gesetzesvorschlag', fr: 'proposition de loi', - es: 'propuesta legislativa', nl: 'wetsvoorstel', - ar: 'مقترح تشريعي', he: 'הצעת חוק', ja: '法案', ko: '법률안', zh: '立法提案', - }, - ], - [ - 'lagstiftning', - { - sv: 'lagstiftning', en: 'legislation', da: 'lovgivning', no: 'lovgivning', - fi: 'lainsäädäntö', de: 'Gesetzgebung', fr: 'législation', es: 'legislación', - nl: 'wetgeving', ar: 'تشريع', he: 'חקיקה', ja: '立法', ko: '입법', zh: '立法', - }, - ], - [ - 'sammanträde', - { - sv: 'sammanträde', en: 'meeting', da: 'møde', no: 'møte', - fi: 'kokous', de: 'Sitzung', fr: 'réunion', es: 'reunión', - nl: 'vergadering', ar: 'اجتماع', he: 'ישיבה', ja: '会議', ko: '회의', zh: '会议', - }, - ], - [ - 'protokoll', - { - sv: 'protokoll', en: 'minutes', da: 'protokol', no: 'protokoll', - fi: 'pöytäkirja', de: 'Protokoll', fr: 'procès-verbal', es: 'acta', - nl: 'notulen', ar: 'محضر', he: 'פרוטוקול', ja: '議事録', ko: '의사록', zh: '会议记录', - }, - ], - [ - 'anförande', - { - sv: 'anförande', en: 'speech', da: 'tale', no: 'innlegg', - fi: 'puheenvuoro', de: 'Rede', fr: 'discours', es: 'discurso', - nl: 'toespraak', ar: 'خطاب', he: 'נאום', ja: '演説', ko: '연설', zh: '演讲', - }, - ], - [ - 'kammaren', - { - sv: 'kammaren', en: 'the Chamber', da: 'kammeret', no: 'kammeret', - fi: 'istuntosali', de: 'die Kammer', fr: 'la Chambre', es: 'la Cámara', - nl: 'de Kamer', ar: 'الغرفة', he: 'האולם', ja: '議場', ko: '본회의장', zh: '议会厅', - }, - ], - [ - 'talman', - { - sv: 'talman', en: 'Speaker', da: 'formand', no: 'stortingspresident', - fi: 'puhemies', de: 'Parlamentspräsident', fr: 'Président du Parlement', - es: 'Presidente del Parlamento', nl: 'Parlementsvoorzitter', - ar: 'رئيس البرلمان', he: 'יושב ראש הפרלמנט', ja: '議長', ko: '의장', zh: '议长', - }, - ], - [ - 'vice talman', - { - sv: 'vice talman', en: 'Deputy Speaker', da: 'næstformand', - no: 'visepresident', fi: 'varapuhemies', de: 'Vizepräsident', - fr: 'Vice-président du Parlement', es: 'Vicepresidente del Parlamento', - nl: 'Vicevoorzitter', ar: 'نائب رئيس البرلمان', he: 'סגן יושב ראש', - ja: '副議長', ko: '부의장', zh: '副议长', - }, - ], - // ---- Budget and fiscal terms ---- - [ - 'anslag', - { - sv: 'anslag', en: 'appropriation', da: 'bevilling', no: 'bevilgning', - fi: 'määräraha', de: 'Bewilligung', fr: 'crédit budgétaire', es: 'asignación', - nl: 'begrotingspost', ar: 'اعتماد مالي', he: 'הקצבה', - ja: '歳出', ko: '세출', zh: '拨款', - }, - ], - [ - 'utgiftsområde', - { - sv: 'utgiftsområde', en: 'expenditure area', da: 'udgiftsområde', - no: 'utgiftsområde', fi: 'menolaji', de: 'Ausgabenbereich', - fr: 'domaine de dépenses', es: 'área de gasto', nl: 'uitgavengebied', - ar: 'مجال الإنفاق', he: 'תחום הוצאה', ja: '歳出分野', ko: '지출분야', zh: '支出领域', - }, - ], - [ - 'rambeslutet', - { - sv: 'rambeslutet', en: 'the framework decision', da: 'rammebeslutningen', - no: 'rammevedtaket', fi: 'kehyspäätös', de: 'der Rahmenbeschluss', - fr: 'la décision-cadre', es: 'la decisión marco', nl: 'het kaderbesluit', - ar: 'القرار الإطاري', he: 'ההחלטה המסגרתית', - ja: '枠組み決定', ko: '기본결정', zh: '框架决定', - }, - ], - [ - 'utgiftstak', - { - sv: 'utgiftstak', en: 'expenditure ceiling', da: 'udgiftsloft', - no: 'utgiftstak', fi: 'menokatto', de: 'Ausgabenobergrenze', - fr: 'plafond de dépenses', es: 'techo de gasto', nl: 'uitgavenplafond', - ar: 'سقف الإنفاق', he: 'תקרת הוצאה', ja: '歳出上限', ko: '지출한도', zh: '支出上限', - }, - ], - [ - 'skatteutgift', - { - sv: 'skatteutgift', en: 'tax expenditure', da: 'skatteudgift', - no: 'skatteutgift', fi: 'verotuki', de: 'Steuerausgabe', - fr: 'dépense fiscale', es: 'gasto fiscal', nl: 'belastinguitgave', - ar: 'نفقات ضريبية', he: 'הוצאת מס', ja: '租税支出', ko: '조세지출', zh: '税收支出', - }, - ], - [ - 'budgetpropositionen', - { - sv: 'budgetpropositionen', en: 'the Budget Bill', da: 'finanslovsforslaget', - no: 'budsjettproposisjonen', fi: 'talousarvioesitys', de: 'der Haushaltsentwurf', - fr: 'le projet de loi de finances', es: 'el proyecto de presupuesto', - nl: 'de begrotingswet', ar: 'مشروع الميزانية', he: 'הצעת התקציב', - ja: '予算案', ko: '예산안', zh: '预算法案', - }, - ], - [ - 'vårpropositionen', - { - sv: 'vårpropositionen', en: 'the Spring Fiscal Policy Bill', - da: 'forårsforslaget', no: 'vårproposisjonen', fi: 'kevätesitys', - de: 'der Frühjahrshaushaltsentwurf', fr: 'le projet de loi de finances de printemps', - es: 'el proyecto de presupuesto de primavera', nl: 'de voorjaarsbegroting', - ar: 'مشروع ميزانية الربيع', he: 'הצעת תקציב האביב', - ja: '春季財政法案', ko: '봄 예산안', zh: '春季财政法案', - }, - ], - [ - 'statsbudgeten', - { - sv: 'statsbudgeten', en: 'the central government budget', da: 'statsbudgettet', - no: 'statsbudsjettet', fi: 'valtion talousarvio', de: 'der Staatshaushalt', - fr: 'le budget de l\'État', es: 'el presupuesto estatal', nl: 'de rijksbegroting', - ar: 'ميزانية الدولة', he: 'תקציב המדינה', - ja: '国家予算', ko: '국가예산', zh: '国家预算', - }, - ], - [ - 'finansplan', - { - sv: 'finansplan', en: 'fiscal policy plan', da: 'finansplan', no: 'finansplan', - fi: 'finanssisuunnitelma', de: 'Finanzplan', fr: 'plan financier', - es: 'plan fiscal', nl: 'financieel plan', - ar: 'خطة مالية', he: 'תוכנית פיסקלית', ja: '財政計画', ko: '재정계획', zh: '财政计划', - }, - ], - [ - 'riksgälden', - { - sv: 'riksgälden', en: 'Swedish National Debt Office', da: 'Riksgælden', - no: 'Riksgjelden', fi: 'Valtiokonttori', de: 'Schwedische Reichsschuldenverwaltung', - fr: 'Office de la dette publique suédoise', es: 'Oficina de Deuda Nacional sueca', - nl: 'Zweedse Rijksschuld', ar: 'مكتب الدين العام السويدي', - he: 'משרד החוב הלאומי השבדי', ja: 'スウェーデン国債局', ko: '스웨덴 국가부채국', zh: '瑞典国债局', - }, - ], - // ---- Interpellation and response terms ---- - [ - 'statsråd', - { - sv: 'statsråd', en: 'cabinet minister', da: 'minister', no: 'statsråd', - fi: 'ministeri', de: 'Kabinettsmitglied', fr: 'ministre du gouvernement', - es: 'ministro del gobierno', nl: 'minister', - ar: 'وزير في الحكومة', he: 'שר ממשלה', ja: '閣僚', ko: '각료', zh: '内阁部长', - }, - ], - [ - 'statsrådet', - { - sv: 'statsrådet', en: 'the cabinet minister', da: 'ministeren', no: 'statsrådet', - fi: 'ministeri', de: 'der Kabinettsmitglied', fr: 'le ministre', - es: 'el ministro', nl: 'de minister', - ar: 'الوزير', he: 'השר', ja: '閣僚', ko: '각료', zh: '部长', - }, - ], - [ - 'skriftlig fråga', - { - sv: 'skriftlig fråga', en: 'written question', da: 'skriftligt spørgsmål', - no: 'skriftlig spørsmål', fi: 'kirjallinen kysymys', de: 'schriftliche Anfrage', - fr: 'question écrite', es: 'pregunta escrita', nl: 'schriftelijke vraag', - ar: 'سؤال كتابي', he: 'שאלה בכתב', ja: '書面質問', ko: '서면질문', zh: '书面提问', - }, - ], - [ - 'svar', - { - sv: 'svar', en: 'answer', da: 'svar', no: 'svar', - fi: 'vastaus', de: 'Antwort', fr: 'réponse', es: 'respuesta', - nl: 'antwoord', ar: 'جواب', he: 'תשובה', ja: '回答', ko: '답변', zh: '答复', - }, - ], - [ - 'debattinlägg', - { - sv: 'debattinlägg', en: 'debate contribution', da: 'debatindlæg', - no: 'debattinnlegg', fi: 'keskustelupuheenvuoro', de: 'Debattenbeitrag', - fr: 'intervention dans le débat', es: 'intervención en el debate', - nl: 'debatbijdrage', ar: 'مداخلة في النقاش', he: 'תרומה לדיון', - ja: '討論への寄与', ko: '토론 기여', zh: '辩论发言', - }, - ], - [ - 'replik', - { - sv: 'replik', en: 'reply', da: 'replik', no: 'replikk', - fi: 'vastapuheenvuoro', de: 'Erwiderung', fr: 'réplique', es: 'réplica', - nl: 'repliek', ar: 'رد', he: 'תשובה', ja: '反論', ko: '반론', zh: '回应', - }, - ], - // ---- EU and international terms ---- - [ - 'ordförandeskap', - { - sv: 'ordförandeskap', en: 'presidency', da: 'formandskab', no: 'formannskap', - fi: 'puheenjohtajuus', de: 'Vorsitz', fr: 'présidence', es: 'presidencia', - nl: 'voorzitterschap', ar: 'رئاسة', he: 'נשיאות', ja: '議長国', ko: '의장국', zh: '轮值主席国', - }, - ], - [ - 'subsidiaritetsgranskning', - { - sv: 'subsidiaritetsgranskning', en: 'subsidiarity review', - da: 'subsidiaritetskontrol', no: 'subsidiaritetskontroll', - fi: 'toissijaisuustarkastus', de: 'Subsidiaritätsprüfung', - fr: 'contrôle de subsidiarité', es: 'control de subsidiariedad', - nl: 'subsidiariteitstoets', ar: 'مراجعة التبعية', he: 'בדיקת סובסידיאריות', - ja: '補完性審査', ko: '보충성 심사', zh: '辅助性审查', - }, - ], - [ - 'europeiska unionen', - { - sv: 'Europeiska unionen', en: 'European Union', da: 'Den Europæiske Union', - no: 'Den europeiske union', fi: 'Euroopan unioni', de: 'Europäische Union', - fr: 'Union européenne', es: 'Unión Europea', nl: 'Europese Unie', - ar: 'الاتحاد الأوروبي', he: 'האיחוד האירופי', - ja: '欧州連合', ko: '유럽연합', zh: '欧盟', - }, - ], - [ - 'eu-nämnden', - { - sv: 'EU-nämnden', en: 'Committee on EU Affairs', da: 'EU-udvalget', - no: 'EU-komiteen', fi: 'EU-valiokunta', de: 'EU-Ausschuss', - fr: 'Comité des affaires européennes', es: 'Comité de Asuntos de la UE', - nl: 'EU-commissie', ar: 'لجنة شؤون الاتحاد الأوروبي', - he: 'ועדת ענייני האיחוד האירופי', ja: 'EU委員会', ko: 'EU위원회', zh: '欧盟事务委员会', - }, - ], - [ - 'europaparlamentet', - { - sv: 'Europaparlamentet', en: 'European Parliament', da: 'Europa-Parlamentet', - no: 'Europaparlamentet', fi: 'Euroopan parlamentti', de: 'Europäisches Parlament', - fr: 'Parlement européen', es: 'Parlamento Europeo', nl: 'Europees Parlement', - ar: 'البرلمان الأوروبي', he: 'הפרלמנט האירופי', - ja: '欧州議会', ko: '유럽의회', zh: '欧洲议会', - }, - ], - [ - 'europarådet', - { - sv: 'Europarådet', en: 'Council of Europe', da: 'Europarådet', - no: 'Europarådet', fi: 'Euroopan neuvosto', de: 'Europarat', - fr: 'Conseil de l\'Europe', es: 'Consejo de Europa', nl: 'Raad van Europa', - ar: 'مجلس أوروبا', he: 'מועצת אירופה', - ja: '欧州評議会', ko: '유럽평의회', zh: '欧洲委员会', - }, - ], - [ - 'nordiska rådet', - { - sv: 'Nordiska rådet', en: 'Nordic Council', da: 'Nordisk Råd', - no: 'Nordisk råd', fi: 'Pohjoismaiden neuvosto', de: 'Nordischer Rat', - fr: 'Conseil nordique', es: 'Consejo Nórdico', nl: 'Noordse Raad', - ar: 'المجلس الشمالي', he: 'המועצה הנורדית', - ja: '北欧理事会', ko: '북유럽이사회', zh: '北欧理事会', - }, - ], - // ---- Geographic and regional terms ---- - [ - 'landsting', - { - sv: 'landsting', en: 'county council', da: 'amt', no: 'fylkesting', - fi: 'maakäräjät', de: 'Provinzialrat', fr: 'conseil départemental', - es: 'consejo provincial', nl: 'provinciale raad', - ar: 'مجلس المقاطعة', he: 'מועצת המחוז', ja: '県議会', ko: '주의회', zh: '省议会', - }, - ], - [ - 'region', - { - sv: 'region', en: 'region', da: 'region', no: 'region', - fi: 'alue', de: 'Region', fr: 'région', es: 'región', - nl: 'regio', ar: 'منطقة', he: 'אזור', ja: '地域', ko: '지역', zh: '地区', - }, - ], - [ - 'kommunalförbund', - { - sv: 'kommunalförbund', en: 'municipal federation', da: 'kommuneforbund', - no: 'kommuneforbund', fi: 'kuntayhtymä', de: 'Kommunalverband', - fr: 'fédération de communes', es: 'federación municipal', - nl: 'gemeentefederatie', ar: 'اتحاد بلديات', he: 'איגוד רשויות', - ja: '市町村連合', ko: '지방자치단체연합', zh: '市政联盟', - }, - ], - [ - 'kommun', - { - sv: 'kommun', en: 'municipality', da: 'kommune', no: 'kommune', - fi: 'kunta', de: 'Gemeinde', fr: 'commune', es: 'municipio', - nl: 'gemeente', ar: 'بلدية', he: 'עירייה', ja: '自治体', ko: '지방자치단체', zh: '市镇', - }, - ], - [ - 'län', - { - sv: 'län', en: 'county', da: 'len', no: 'fylke', - fi: 'lääni', de: 'Provinz', fr: 'comté', es: 'condado', - nl: 'provincie', ar: 'مقاطعة', he: 'מחוז', ja: '県', ko: '주', zh: '省', - }, - ], - [ - 'landsbygd', - { - sv: 'landsbygd', en: 'rural area', da: 'landdistrikt', no: 'landsbygd', - fi: 'maaseutu', de: 'ländliches Gebiet', fr: 'zone rurale', es: 'zona rural', - nl: 'platteland', ar: 'منطقة ريفية', he: 'אזור כפרי', - ja: '農村地域', ko: '농촌 지역', zh: '农村地区', - }, - ], - // ---- Government agencies and institutions ---- - [ - 'riksbanken', - { - sv: 'Riksbanken', en: 'Swedish Central Bank', da: 'Riksbanken', - no: 'Riksbanken', fi: 'Ruotsin keskuspankki', de: 'Schwedische Reichsbank', - fr: 'Banque centrale de Suède', es: 'Banco Central de Suecia', - nl: 'Zweedse Rijksbank', ar: 'البنك المركزي السويدي', he: 'הבנק המרכזי השבדי', - ja: 'スウェーデン国立銀行', ko: '스웨덴 중앙은행', zh: '瑞典央行', - }, - ], - [ - 'riksrevisionen', - { - sv: 'Riksrevisionen', en: 'Swedish National Audit Office', da: 'Rigsrevisionen', - no: 'Riksrevisjonen', fi: 'Ruotsin tarkastusvirasto', de: 'Schwedischer Rechnungshof', - fr: 'Cour des comptes suédoise', es: 'Tribunal de Cuentas sueco', - nl: 'Zweedse Rekenkamer', ar: 'ديوان المراجعة السويدي', he: 'מבקר המדינה השבדי', - ja: 'スウェーデン会計検査院', ko: '스웨덴 감사원', zh: '瑞典审计署', - }, - ], - [ - 'justitieombudsmannen', - { - sv: 'Justitieombudsmannen', en: 'Parliamentary Ombudsman', da: 'Ombudsmanden', - no: 'Sivilombudet', fi: 'Eduskunnan oikeusasiamies', de: 'Parlamentarischer Ombudsmann', - fr: 'Médiateur parlementaire', es: 'Defensor del Pueblo parlamentario', - nl: 'Parlementaire Ombudsman', ar: 'أمين المظالم البرلماني', he: 'נציב הביקורת', - ja: '議会オンブズマン', ko: '의회 옴부즈만', zh: '议会监察专员', - }, - ], - [ - 'valmyndigheten', - { - sv: 'Valmyndigheten', en: 'Swedish Election Authority', da: 'Valgmyndigheden', - no: 'Valgmyndigheten', fi: 'Ruotsin vaaliviranomainen', de: 'Schwedische Wahlbehörde', - fr: 'Autorité électorale suédoise', es: 'Autoridad Electoral sueca', - nl: 'Zweedse Kiesraad', ar: 'هيئة الانتخابات السويدية', he: 'רשות הבחירות השבדית', - ja: 'スウェーデン選挙管理委員会', ko: '스웨덴 선거관리위원회', zh: '瑞典选举管理局', - }, - ], - [ - 'myndigheten', - { - sv: 'myndigheten', en: 'the authority', da: 'myndigheden', no: 'myndigheten', - fi: 'viranomainen', de: 'die Behörde', fr: 'l\'autorité', es: 'la autoridad', - nl: 'de autoriteit', ar: 'السلطة', he: 'הרשות', ja: '当局', ko: '당국', zh: '当局', - }, - ], - [ - 'myndighet', - { - sv: 'myndighet', en: 'authority', da: 'myndighed', no: 'myndighet', - fi: 'viranomainen', de: 'Behörde', fr: 'autorité', es: 'autoridad', - nl: 'autoriteit', ar: 'سلطة', he: 'רשות', ja: '機関', ko: '기관', zh: '机构', - }, - ], - // ---- Legal and constitutional terms ---- - [ - 'grundlag', - { - sv: 'grundlag', en: 'constitution', da: 'grundlov', no: 'grunnlov', - fi: 'perustuslaki', de: 'Verfassung', fr: 'constitution', es: 'constitución', - nl: 'grondwet', ar: 'دستور', he: 'חוקה', ja: '憲法', ko: '헌법', zh: '宪法', - }, - ], - [ - 'riksdagsordningen', - { - sv: 'riksdagsordningen', en: 'the Riksdag Act', da: 'riksdagsordningen', - no: 'stortingsordningen', fi: 'valtiopäiväjärjestys', de: 'die Reichstagsordnung', - fr: 'le règlement du Riksdag', es: 'el reglamento del Riksdag', - nl: 'het Riksdag-reglement', ar: 'نظام البرلمان', he: 'חוק הריקסדאג', - ja: '国会法', ko: '국회법', zh: '国会法', - }, - ], - [ - 'tryckfrihet', - { - sv: 'tryckfrihet', en: 'freedom of the press', da: 'pressefrihed', - no: 'pressefrihet', fi: 'painovapaus', de: 'Pressefreiheit', - fr: 'liberté de la presse', es: 'libertad de prensa', nl: 'persvrijheid', - ar: 'حرية الصحافة', he: 'חופש העיתונות', ja: '報道の自由', ko: '언론의 자유', zh: '新闻自由', - }, - ], - [ - 'yttrandefrihet', - { - sv: 'yttrandefrihet', en: 'freedom of expression', da: 'ytringsfrihed', - no: 'ytringsfrihet', fi: 'sananvapaus', de: 'Meinungsfreiheit', - fr: 'liberté d\'expression', es: 'libertad de expresión', nl: 'vrijheid van meningsuiting', - ar: 'حرية التعبير', he: 'חופש הביטוי', ja: '表現の自由', ko: '표현의 자유', zh: '言论自由', - }, - ], - [ - 'offentlighetsprincipen', - { - sv: 'offentlighetsprincipen', en: 'principle of public access', - da: 'offentlighedsprincippet', no: 'offentlighetsprinsippet', - fi: 'julkisuusperiaate', de: 'Öffentlichkeitsprinzip', - fr: 'principe de transparence', es: 'principio de publicidad', - nl: 'openbaarheidsbeginsel', ar: 'مبدأ الشفافية', he: 'עקרון הגישה הציבורית', - ja: '情報公開原則', ko: '공개원칙', zh: '信息公开原则', - }, - ], - [ - 'förordning', - { - sv: 'förordning', en: 'ordinance', da: 'forordning', no: 'forskrift', - fi: 'asetus', de: 'Verordnung', fr: 'ordonnance', es: 'ordenanza', - nl: 'verordening', ar: 'مرسوم', he: 'תקנה', ja: '政令', ko: '시행령', zh: '法令', - }, - ], - [ - 'direktiv', - { - sv: 'direktiv', en: 'directive', da: 'direktiv', no: 'direktiv', - fi: 'direktiivi', de: 'Richtlinie', fr: 'directive', es: 'directiva', - nl: 'richtlijn', ar: 'توجيه', he: 'הנחיה', ja: '指令', ko: '지침', zh: '指令', - }, - ], - // ---- Policy domain terms ---- - [ - 'arbetsmarknad', - { - sv: 'arbetsmarknad', en: 'labour market', da: 'arbejdsmarked', no: 'arbeidsmarked', - fi: 'työmarkkinat', de: 'Arbeitsmarkt', fr: 'marché du travail', - es: 'mercado laboral', nl: 'arbeidsmarkt', ar: 'سوق العمل', he: 'שוק העבודה', - ja: '労働市場', ko: '노동시장', zh: '劳动市场', - }, - ], - [ - 'infrastruktur', - { - sv: 'infrastruktur', en: 'infrastructure', da: 'infrastruktur', - no: 'infrastruktur', fi: 'infrastruktuuri', de: 'Infrastruktur', - fr: 'infrastructure', es: 'infraestructura', nl: 'infrastructuur', - ar: 'بنية تحتية', he: 'תשתית', ja: 'インフラ', ko: '인프라', zh: '基础设施', - }, - ], - [ - 'näringsliv', - { - sv: 'näringsliv', en: 'business', da: 'erhvervsliv', no: 'næringsliv', - fi: 'elinkeinoelämä', de: 'Wirtschaft', fr: 'secteur privé', es: 'sector empresarial', - nl: 'bedrijfsleven', ar: 'قطاع الأعمال', he: 'מגזר עסקי', - ja: '産業界', ko: '산업계', zh: '商业', - }, - ], - [ - 'jordbruk', - { - sv: 'jordbruk', en: 'agriculture', da: 'landbrug', no: 'landbruk', - fi: 'maatalous', de: 'Landwirtschaft', fr: 'agriculture', es: 'agricultura', - nl: 'landbouw', ar: 'زراعة', he: 'חקלאות', ja: '農業', ko: '농업', zh: '农业', - }, - ], - [ - 'transport', - { - sv: 'transport', en: 'transport', da: 'transport', no: 'transport', - fi: 'liikenne', de: 'Verkehr', fr: 'transport', es: 'transporte', - nl: 'vervoer', ar: 'نقل', he: 'תחבורה', ja: '交通', ko: '교통', zh: '交通', - }, - ], - [ - 'socialförsäkring', - { - sv: 'socialförsäkring', en: 'social insurance', da: 'socialforsikring', - no: 'sosialforsikring', fi: 'sosiaalivakuutus', de: 'Sozialversicherung', - fr: 'assurance sociale', es: 'seguro social', nl: 'sociale verzekering', - ar: 'تأمين اجتماعي', he: 'ביטוח סוציאלי', ja: '社会保険', ko: '사회보험', zh: '社会保险', - }, - ], - [ - 'rättsväsende', - { - sv: 'rättsväsende', en: 'judiciary', da: 'retsvæsen', no: 'rettsvesen', - fi: 'oikeuslaitos', de: 'Justizwesen', fr: 'système judiciaire', - es: 'sistema judicial', nl: 'rechterlijke macht', - ar: 'الجهاز القضائي', he: 'מערכת המשפט', ja: '司法制度', ko: '사법부', zh: '司法机构', - }, - ], - [ - 'forskning', - { - sv: 'forskning', en: 'research', da: 'forskning', no: 'forskning', - fi: 'tutkimus', de: 'Forschung', fr: 'recherche', es: 'investigación', - nl: 'onderzoek', ar: 'بحث', he: 'מחקר', ja: '研究', ko: '연구', zh: '研究', - }, - ], - [ - 'kultur', - { - sv: 'kultur', en: 'culture', da: 'kultur', no: 'kultur', - fi: 'kulttuuri', de: 'Kultur', fr: 'culture', es: 'cultura', - nl: 'cultuur', ar: 'ثقافة', he: 'תרבות', ja: '文化', ko: '문화', zh: '文化', - }, - ], - [ - 'bistånd', - { - sv: 'bistånd', en: 'development aid', da: 'bistand', no: 'bistand', - fi: 'kehitysapu', de: 'Entwicklungshilfe', fr: 'aide au développement', - es: 'ayuda al desarrollo', nl: 'ontwikkelingshulp', - ar: 'مساعدات تنمية', he: 'סיוע לפיתוח', ja: '開発援助', ko: '개발원조', zh: '发展援助', - }, - ], - [ - 'pension', - { - sv: 'pension', en: 'pension', da: 'pension', no: 'pensjon', - fi: 'eläke', de: 'Rente', fr: 'pension', es: 'pensión', - nl: 'pensioen', ar: 'معاش', he: 'פנסיה', ja: '年金', ko: '연금', zh: '养老金', - }, - ], - [ - 'invandring', - { - sv: 'invandring', en: 'immigration', da: 'indvandring', no: 'innvandring', - fi: 'maahanmuutto', de: 'Einwanderung', fr: 'immigration', es: 'inmigración', - nl: 'immigratie', ar: 'هجرة', he: 'הגירה', ja: '移民', ko: '이민', zh: '移民', - }, - ], - [ - 'integration', - { - sv: 'integration', en: 'integration', da: 'integration', no: 'integrasjon', - fi: 'integraatio', de: 'Integration', fr: 'intégration', es: 'integración', - nl: 'integratie', ar: 'اندماج', he: 'שילוב', ja: '統合', ko: '통합', zh: '融合', - }, - ], - [ - 'jämställdhet', - { - sv: 'jämställdhet', en: 'gender equality', da: 'ligestilling', no: 'likestilling', - fi: 'tasa-arvo', de: 'Gleichstellung', fr: 'égalité des genres', - es: 'igualdad de género', nl: 'gendergelijkheid', - ar: 'المساواة بين الجنسين', he: 'שוויון מגדרי', - ja: 'ジェンダー平等', ko: '성평등', zh: '性别平等', - }, - ], - [ - 'säkerhetspolitik', - { - sv: 'säkerhetspolitik', en: 'security policy', da: 'sikkerhedspolitik', - no: 'sikkerhetspolitikk', fi: 'turvallisuuspolitiikka', de: 'Sicherheitspolitik', - fr: 'politique de sécurité', es: 'política de seguridad', - nl: 'veiligheidsbeleid', ar: 'سياسة أمنية', he: 'מדיניות ביטחון', - ja: '安全保障政策', ko: '안보정책', zh: '安全政策', - }, - ], - [ - 'utrikespolitik', - { - sv: 'utrikespolitik', en: 'foreign policy', da: 'udenrigspolitik', - no: 'utenrikspolitikk', fi: 'ulkopolitiikka', de: 'Außenpolitik', - fr: 'politique étrangère', es: 'política exterior', nl: 'buitenlands beleid', - ar: 'سياسة خارجية', he: 'מדיניות חוץ', ja: '外交政策', ko: '외교정책', zh: '外交政策', - }, - ], - [ - 'socialpolitik', - { - sv: 'socialpolitik', en: 'social policy', da: 'socialpolitik', - no: 'sosialpolitikk', fi: 'sosiaalipolitiikka', de: 'Sozialpolitik', - fr: 'politique sociale', es: 'política social', nl: 'sociaal beleid', - ar: 'سياسة اجتماعية', he: 'מדיניות חברתית', - ja: '社会政策', ko: '사회정책', zh: '社会政策', - }, - ], + ...PARTY_NAME_TERMS, + ...POLITICAL_TERMS, // ---- Additional common parliamentary vocabulary ---- [ 'riksdagsledamot', diff --git a/scripts/validate-news-translations.ts b/scripts/validate-news-translations.ts index f5472f3fa6..8d4330bfea 100644 --- a/scripts/validate-news-translations.ts +++ b/scripts/validate-news-translations.ts @@ -92,6 +92,14 @@ interface ContentLeakageRecord { readonly samples: string[]; } +/** Record for files containing unresolved AI_MUST_REPLACE markers in HTML comments */ +interface AIMarkerFileRecord { + readonly filename: string; + readonly lang: string; + readonly markerCount: number; + readonly samples: string[]; +} + // --------------------------------------------------------------------------- // English / Swedish body-content leakage detection // --------------------------------------------------------------------------- @@ -424,6 +432,46 @@ function checkFileForUntranslatedContent(filepath: string): CheckResult { } } +/** + * Regex to detect unresolved AI_MUST_REPLACE markers in HTML comments. + * These markers are embedded by content generators and MUST be replaced + * by AI agents before publication. They should never appear in translated articles. + * + * Pattern matches: + */ +const AI_MUST_REPLACE_COMMENT_RE = //g; + +/** + * Check if a file contains unresolved AI_MUST_REPLACE markers in HTML comments. + * These are quality failures that must be fixed before publication. + */ +function checkFileForAIMustReplaceMarkers(filepath: string): AIMarkerFileRecord | null { + try { + const content = readFileSync(filepath, 'utf-8'); + AI_MUST_REPLACE_COMMENT_RE.lastIndex = 0; + const allMatches = content.match(AI_MUST_REPLACE_COMMENT_RE); + if (!allMatches || allMatches.length === 0) return null; + + const filename = basename(filepath); + const lang = getLanguageCode(filename) ?? ''; + + // Collect up to 3 sample marker names for reporting + const samples: string[] = []; + const nameRe = /AI_MUST_REPLACE:\s*([\w_]+)/g; + let m: RegExpExecArray | null; + while ((m = nameRe.exec(content)) !== null && samples.length < 3) { + const name = m[1] ?? ''; + if (name && !samples.includes(name)) { + samples.push(name); + } + } + + return { filename, lang, markerCount: allMatches.length, samples }; + } catch { + return null; + } +} + /** * Get all HTML files in a directory (recursive). */ @@ -482,8 +530,10 @@ function validateNewsTranslations(directory: string = 'news'): number { let totalErrors = 0; let totalBCP47Errors = 0; let totalContentLeakage = 0; + let totalAIMarkers = 0; const failedFiles: FailedFileRecord[] = []; const leakageFiles: ContentLeakageRecord[] = []; + const aiMarkerFiles: AIMarkerFileRecord[] = []; for (const filepath of nonSwedishFiles) { const filename = basename(filepath); @@ -500,6 +550,18 @@ function validateNewsTranslations(directory: string = 'news'): number { } } + // AI_MUST_REPLACE marker check — unresolved placeholders in HTML comments + // are a hard failure: they indicate the AI did not replace template content. + const aiMarkerRecord = checkFileForAIMustReplaceMarkers(filepath); + if (aiMarkerRecord) { + aiMarkerFiles.push(aiMarkerRecord); + totalAIMarkers += aiMarkerRecord.markerCount; + const sampleStr = aiMarkerRecord.samples.length > 0 + ? ` [${aiMarkerRecord.samples.join(', ')}]` + : ''; + console.log(`${colors.red}✗ AI_MUST_REPLACE: ${filename} — ${aiMarkerRecord.markerCount} unresolved marker(s)${sampleStr}${colors.reset}`); + } + // Body content leakage check (EN/SV text in non-EN/SV articles) // Leakage is computed here but only counted in summary totals for // marker-passed files (see below) to keep the summary math correct. @@ -585,11 +647,15 @@ function validateNewsTranslations(directory: string = 'news'): number { console.log(`${colors.red}✗ BCP-47 inconsistencies: ${totalBCP47Errors}${colors.reset}`); } + if (totalAIMarkers > 0) { + console.log(`${colors.red}✗ Unresolved AI_MUST_REPLACE markers: ${totalAIMarkers} in ${aiMarkerFiles.length} article(s)${colors.reset}`); + } + if (totalContentLeakage > 0) { console.log(`${colors.yellow}⚠ Articles with EN/SV body content leakage: ${totalContentLeakage}${colors.reset}`); } - const hasHardFailures = totalFailed > 0 || totalBCP47Errors > 0; + const hasHardFailures = totalFailed > 0 || totalBCP47Errors > 0 || aiMarkerFiles.length > 0; // Content leakage is a warning that will become a hard failure when translation // workflows are updated. For now, report but don't block. @@ -612,6 +678,21 @@ function validateNewsTranslations(directory: string = 'news'): number { console.log(`5. Consult TRANSLATION_GUIDE.md for terminology\n`); } + if (aiMarkerFiles.length > 0) { + console.log(`\n${colors.yellow}AI_MUST_REPLACE Action Required:${colors.reset}`); + console.log(`The following articles contain unresolved AI_MUST_REPLACE placeholders in HTML comments.`); + console.log(`The AI translation agent MUST replace these with genuine content in the target language:\n`); + aiMarkerFiles.forEach(({ filename, markerCount, samples }) => { + const sampleStr = samples.length > 0 ? ` [${samples.join(', ')}]` : ''; + console.log(` ${colors.red}✗${colors.reset} ${filename} - ${markerCount} marker(s)${sampleStr}`); + }); + console.log(`\n${colors.yellow}Fix:${colors.reset}`); + console.log(`1. Open the source EN article and the translated article`); + console.log(`2. Find every comment`); + console.log(`3. Replace the entire comment with genuine analysis in the target language`); + console.log(`4. Re-run the translation workflow with updated prompts\n`); + } + if (totalBCP47Errors > 0) { console.log(`\n${colors.yellow}BCP-47 Action Required:${colors.reset}`); console.log(`Ensure html[lang], og:locale, and inLanguage are consistent per article.`); diff --git a/tests/validate-news-translations.test.ts b/tests/validate-news-translations.test.ts index 27f2511850..cd335209c9 100644 --- a/tests/validate-news-translations.test.ts +++ b/tests/validate-news-translations.test.ts @@ -550,4 +550,85 @@ describe('validate-news-translations.ts', () => { expect(result).not.toContain('Content leakage'); }); }); + + describe('AI_MUST_REPLACE marker detection', () => { + it('should detect AI_MUST_REPLACE markers in HTML comments and fail CI', () => { + const esContent = ` + + + +

Este es un párrafo en español sobre política sueca.

+ +

Otro párrafo de análisis político.

+ +`; + writeFileSync(`${testDir}/2026-04-09-test-es.html`, esContent); + + let exitCode = 0; + let output = ''; + try { + output = execSync(`node scripts/validate-news-translations.ts ${testDir}`, { + encoding: 'utf-8' + }); + } catch (error: unknown) { + exitCode = (error as ExecSyncError).status; + output = (error as ExecSyncError).stdout ?? ''; + } + + expect(exitCode).toBe(1); + expect(output).toContain('AI_MUST_REPLACE'); + expect(output).toContain('VALIDATION FAILED'); + }); + + it('should report sample marker names from AI_MUST_REPLACE comments', () => { + const deContent = ` + + + +

Dies ist ein deutscher Absatz.

+ + + +`; + writeFileSync(`${testDir}/2026-04-09-test-de.html`, deContent); + + let exitCode = 0; + let output = ''; + try { + output = execSync(`node scripts/validate-news-translations.ts ${testDir}`, { + encoding: 'utf-8' + }); + } catch (error: unknown) { + exitCode = (error as ExecSyncError).status; + output = (error as ExecSyncError).stdout ?? ''; + } + + expect(exitCode).toBe(1); + expect(output).toContain('coalition_instability'); + expect(output).toContain('2 unresolved marker(s)'); + }); + + it('should pass validation for articles with no AI_MUST_REPLACE markers', () => { + const fiContent = ` + + + +

Tämä on suomenkielinen artikkeli ruotsin parlamentista.

+

Koalitiodynamiikka osoittaa merkittäviä jännitteitä hallituspuolueiden välillä.

+ +`; + writeFileSync(`${testDir}/2026-04-09-test-fi.html`, fiContent); + + let exitCode = 0; + try { + execSync(`node scripts/validate-news-translations.ts ${testDir}`, { + encoding: 'utf-8' + }); + } catch (error: unknown) { + exitCode = (error as ExecSyncError).status; + } + + expect(exitCode).toBe(0); + }); + }); }); From 76868ec57c20ffb9c357d29279f0f290fefeb894 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:38:35 +0000 Subject: [PATCH 3/3] Address PR review: surface read errors, exclude AI marker files from passed count, fix lint, fix prompt consistency Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/ad9025e1-7491-4238-a5bf-98f4704dd8a6 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com> --- .github/workflows/news-translate.md | 2 +- scripts/validate-news-translations.ts | 17 ++++++++++++----- tests/validate-news-translations.test.ts | 4 ++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/news-translate.md b/.github/workflows/news-translate.md index 5733103455..6215f5a663 100644 --- a/.github/workflows/news-translate.md +++ b/.github/workflows/news-translate.md @@ -654,7 +654,7 @@ The TypeScript script generates **structural baselines only** — it translates 3. **Raw Swedish API text** — Interpellation excerpts, proposition summaries that come from the Riksdag API are often pasted as-is. You MUST translate these to the target language or summarize them. 4. **English boilerplate phrases** — Remove or translate phrases like "Read the full proposition", "Live intelligence platform for Swedish Parliament monitoring" 5. **Section headings** that were not covered by CONTENT_LABELS (e.g., specific policy domain names used as h3/h4 headings) -6. **🚨 AI_MUST_REPLACE HTML comments** — SCAN every HTML comment in the source article. If any contains `AI_MUST_REPLACE`, you MUST generate replacement content in the target language. See critical section below. +6. **🚨 AI_MUST_REPLACE HTML comments** — SCAN every HTML comment in the **translated** article. If any contains `AI_MUST_REPLACE`, you MUST generate replacement content in the target language. See critical section below. #### 🚨 CRITICAL: AI_MUST_REPLACE Comment Handling diff --git a/scripts/validate-news-translations.ts b/scripts/validate-news-translations.ts index 8d4330bfea..845e4e5388 100644 --- a/scripts/validate-news-translations.ts +++ b/scripts/validate-news-translations.ts @@ -467,8 +467,9 @@ function checkFileForAIMustReplaceMarkers(filepath: string): AIMarkerFileRecord } return { filename, lang, markerCount: allMatches.length, samples }; - } catch { - return null; + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error); + throw new Error(`Failed to validate AI_MUST_REPLACE markers in ${filepath}: ${message}`, { cause: error }); } } @@ -590,10 +591,16 @@ function validateNewsTranslations(directory: string = 'news'): number { console.log(` ${colors.red}${result.error}${colors.reset}\n`); totalErrors++; } else if (result.passed) { - console.log(`${colors.green}✓ ${filename} (${(lang ?? '').toUpperCase()})${colors.reset}`); - totalPassed++; + // Files with AI_MUST_REPLACE markers are NOT counted as passed — they + // are a separate hard failure reported via aiMarkerFiles. + if (aiMarkerRecord) { + // Already logged above; don't double-count as passed. + } else { + console.log(`${colors.green}✓ ${filename} (${(lang ?? '').toUpperCase()})${colors.reset}`); + totalPassed++; + } // Only count leakage toward summary totals for marker-passed files - if (fileLeakage) { + if (fileLeakage && !aiMarkerRecord) { totalContentLeakage++; } } else { diff --git a/tests/validate-news-translations.test.ts b/tests/validate-news-translations.test.ts index cd335209c9..edd7ec13b0 100644 --- a/tests/validate-news-translations.test.ts +++ b/tests/validate-news-translations.test.ts @@ -567,7 +567,7 @@ describe('validate-news-translations.ts', () => { let exitCode = 0; let output = ''; try { - output = execSync(`node scripts/validate-news-translations.ts ${testDir}`, { + execSync(`node scripts/validate-news-translations.ts ${testDir}`, { encoding: 'utf-8' }); } catch (error: unknown) { @@ -595,7 +595,7 @@ describe('validate-news-translations.ts', () => { let exitCode = 0; let output = ''; try { - output = execSync(`node scripts/validate-news-translations.ts ${testDir}`, { + execSync(`node scripts/validate-news-translations.ts ${testDir}`, { encoding: 'utf-8' }); } catch (error: unknown) {