feat(ai-act-kompass): FR/IT/ES locales, EN fallback architecture, PWA install support
- Full UI dictionaries for French, Italian and Spanish (all views, wizard, legal gate, templates); browser-language auto-detection extended to all five locales - Fallback architecture: LText now carries optional fr/it/es entries; regulatory legal texts (content pack, classify reasons, document strings) fall back to English until legal translations land — clearly stated in the language setting - Locale-aware date formatting (DE dots, FR/IT/ES slashes, EN ISO) - PWA: web app manifest, network-first service worker with offline cache fallback, generated icons (512/192/apple-touch) — installable on phone home screen and macOS dock - 2 new tests incl. dictionary-completeness check for FR/IT/ES (58 total) Claude-Session: https://claude.ai/code/session_017YjohVNx1ZGNM4MX7tHpfv
This commit is contained in:
parent
45c8c9557d
commit
08968a85a1
@ -4,6 +4,10 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="AI-Act-Kompass — EU AI Act Compliance-Toolkit für KMU. Local-first, keine Cloud." />
|
||||
<meta name="theme-color" content="#14120e" />
|
||||
<link rel="manifest" href="./manifest.webmanifest" />
|
||||
<link rel="icon" type="image/png" href="./icon-192.png" />
|
||||
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
||||
<title>AI-Act-Kompass</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
BIN
ai-act-kompass/public/apple-touch-icon.png
Normal file
BIN
ai-act-kompass/public/apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
BIN
ai-act-kompass/public/icon-192.png
Normal file
BIN
ai-act-kompass/public/icon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
BIN
ai-act-kompass/public/icon-512.png
Normal file
BIN
ai-act-kompass/public/icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
14
ai-act-kompass/public/manifest.webmanifest
Normal file
14
ai-act-kompass/public/manifest.webmanifest
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "AI-Act-Kompass",
|
||||
"short_name": "AI-Act-Kompass",
|
||||
"description": "EU AI Act Compliance-Toolkit für KMU — local-first, mehrsprachig, keine Cloud.",
|
||||
"start_url": "./",
|
||||
"scope": "./",
|
||||
"display": "standalone",
|
||||
"background_color": "#f4f1ea",
|
||||
"theme_color": "#14120e",
|
||||
"icons": [
|
||||
{ "src": "icon-192.png", "sizes": "192x192", "type": "image/png" },
|
||||
{ "src": "icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
|
||||
]
|
||||
}
|
||||
46
ai-act-kompass/public/sw.js
Normal file
46
ai-act-kompass/public/sw.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Service Worker des AI-Act-Kompass.
|
||||
* Strategie: Network-first mit Cache-Fallback — die App bleibt offline
|
||||
* nutzbar (Handy/Mac), lädt aber online immer die aktuelle Version.
|
||||
* Es werden ausschließlich eigene (same-origin) GET-Antworten gecacht.
|
||||
*/
|
||||
const CACHE = 'ai-act-kompass-v1';
|
||||
|
||||
self.addEventListener('install', () => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
caches
|
||||
.keys()
|
||||
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
||||
.then(() => self.clients.claim()),
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
const { request } = event;
|
||||
if (request.method !== 'GET' || new URL(request.url).origin !== location.origin) {
|
||||
return;
|
||||
}
|
||||
event.respondWith(
|
||||
caches.open(CACHE).then(async (cache) => {
|
||||
try {
|
||||
const fresh = await fetch(request);
|
||||
if (fresh.ok) {
|
||||
cache.put(request, fresh.clone());
|
||||
}
|
||||
return fresh;
|
||||
} catch (err) {
|
||||
const cached = await cache.match(request, { ignoreSearch: true });
|
||||
if (cached) return cached;
|
||||
if (request.mode === 'navigate') {
|
||||
const shell = await cache.match('./index.html');
|
||||
if (shell) return shell;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}),
|
||||
);
|
||||
});
|
||||
@ -5,6 +5,7 @@ import type {
|
||||
NationalPack,
|
||||
Obligation,
|
||||
} from '../engine/types';
|
||||
import { resolveText } from '../i18n/types';
|
||||
import type { Locale, LText } from '../i18n/types';
|
||||
import {
|
||||
AI_DEFINITION_CRITERIA,
|
||||
@ -39,18 +40,18 @@ const LEGAL_BASIS: LText = {
|
||||
function resolveItem(src: ContentItemSrc, locale: Locale): ContentItem {
|
||||
return {
|
||||
id: src.id,
|
||||
label: src.label[locale],
|
||||
label: resolveText(src.label, locale),
|
||||
legalRef: src.legalRef,
|
||||
...(src.hint ? { hint: src.hint[locale] } : {}),
|
||||
...(src.hint ? { hint: resolveText(src.hint, locale) } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function resolveObligation(src: ObligationSrc, locale: Locale): Obligation {
|
||||
return {
|
||||
id: src.id,
|
||||
title: src.title[locale],
|
||||
title: resolveText(src.title, locale),
|
||||
articles: src.articles,
|
||||
description: src.description[locale],
|
||||
description: resolveText(src.description, locale),
|
||||
deadline: src.deadline,
|
||||
roles: src.roles,
|
||||
riskClasses: src.riskClasses,
|
||||
@ -61,16 +62,16 @@ function resolveDeadline(src: DeadlineSrc, locale: Locale): Deadline {
|
||||
return {
|
||||
id: src.id,
|
||||
date: src.date,
|
||||
label: src.label[locale],
|
||||
description: src.description[locale],
|
||||
label: resolveText(src.label, locale),
|
||||
description: resolveText(src.description, locale),
|
||||
};
|
||||
}
|
||||
|
||||
function resolveNational(src: NationalPackSrc, locale: Locale): NationalPack {
|
||||
return {
|
||||
code: src.code,
|
||||
country: src.country[locale],
|
||||
authority: src.authority[locale],
|
||||
country: resolveText(src.country, locale),
|
||||
authority: resolveText(src.authority, locale),
|
||||
items: src.items.map((i) => resolveObligation(i, locale)),
|
||||
};
|
||||
}
|
||||
@ -85,7 +86,7 @@ export function getContentPack(locale: Locale): ContentPack {
|
||||
return {
|
||||
version: VERSION,
|
||||
releasedAt: RELEASED_AT,
|
||||
legalBasis: LEGAL_BASIS[locale],
|
||||
legalBasis: resolveText(LEGAL_BASIS, locale),
|
||||
aiDefinitionCriteria: AI_DEFINITION_CRITERIA.map((i) => resolveItem(i, locale)),
|
||||
prohibitedPractices: PROHIBITED_PRACTICES.map((i) => resolveItem(i, locale)),
|
||||
annexIIICategories: ANNEX_III_CATEGORIES.map((i) => resolveItem(i, locale)),
|
||||
|
||||
@ -12,7 +12,7 @@ interface ClassifyStrings {
|
||||
readonly minimal: string;
|
||||
}
|
||||
|
||||
const STRINGS: Readonly<Record<Locale, ClassifyStrings>> = {
|
||||
const STRINGS: Readonly<Partial<Record<Locale, ClassifyStrings>>> = {
|
||||
de: {
|
||||
outOfScope:
|
||||
'Das System erfüllt die KI-Definition nach Art. 3 Nr. 1 nicht — der AI Act ist nicht anwendbar.',
|
||||
@ -66,7 +66,8 @@ export function classify(
|
||||
pack: ContentPack,
|
||||
locale: Locale = 'de',
|
||||
): Classification {
|
||||
const s = STRINGS[locale];
|
||||
// Rechtstexte liegen in DE/EN vor; übrige Sprachen fallen auf EN zurück.
|
||||
const s = STRINGS[locale] ?? (STRINGS.en as ClassifyStrings);
|
||||
const reasons: string[] = [];
|
||||
const transparencyDuties = answers.transparencyTriggers.length > 0;
|
||||
|
||||
|
||||
@ -188,14 +188,18 @@ const EN: DocStrings = {
|
||||
todo: '_[TO BE COMPLETED]_',
|
||||
};
|
||||
|
||||
/** Liefert die Dokument-Strings für die gewünschte Sprache. */
|
||||
/**
|
||||
* Liefert die Dokument-Strings für die gewünschte Sprache.
|
||||
* Rechtstexte liegen in DE/EN vor; übrige Sprachen fallen auf EN zurück.
|
||||
*/
|
||||
export function docStrings(locale: Locale): DocStrings {
|
||||
return locale === 'en' ? EN : DE;
|
||||
return locale === 'de' ? DE : EN;
|
||||
}
|
||||
|
||||
/** Formatiert ein ISO-Datum landesüblich (DE: TT.MM.JJJJ, EN: ISO). */
|
||||
/** Formatiert ein ISO-Datum landesüblich (DE: TT.MM.JJJJ, FR/IT/ES: TT/MM/JJJJ, EN: ISO). */
|
||||
export function formatDocDate(iso: string, locale: Locale): string {
|
||||
if (locale === 'en') return iso;
|
||||
const [y, m, d] = iso.split('-');
|
||||
return d && m && y ? `${d}.${m}.${y}` : iso;
|
||||
if (!d || !m || !y) return iso;
|
||||
return locale === 'de' ? `${d}.${m}.${y}` : `${d}/${m}/${y}`;
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ export function actionPlan(
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
const ANNEX_IV_SECTIONS: Readonly<Record<Locale, readonly (readonly [string, readonly string[]])[]>> = {
|
||||
const ANNEX_IV_SECTIONS: Readonly<Record<'de' | 'en', readonly (readonly [string, readonly string[]])[]>> = {
|
||||
de: [
|
||||
['1. Allgemeine Beschreibung des KI-Systems', [
|
||||
'Zweckbestimmung', 'Anbieter', 'Versionen und Datum des Inverkehrbringens',
|
||||
@ -206,11 +206,11 @@ export function annexIVSkeleton(
|
||||
const lines = [header(title, system, pack, today, locale, profile)];
|
||||
|
||||
const prefilled: Readonly<Record<string, string>> = {
|
||||
[ANNEX_IV_SECTIONS[locale][0]?.[1][0] ?? '']: system.purpose,
|
||||
[ANNEX_IV_SECTIONS[locale][0]?.[1][1] ?? '']: system.vendor,
|
||||
[ANNEX_IV_SECTIONS[locale === 'de' ? 'de' : 'en'][0]?.[1][0] ?? '']: system.purpose,
|
||||
[ANNEX_IV_SECTIONS[locale === 'de' ? 'de' : 'en'][0]?.[1][1] ?? '']: system.vendor,
|
||||
};
|
||||
|
||||
for (const [section, items] of ANNEX_IV_SECTIONS[locale]) {
|
||||
for (const [section, items] of ANNEX_IV_SECTIONS[locale === 'de' ? 'de' : 'en']) {
|
||||
lines.push(`## ${section}`, '');
|
||||
for (const item of items) {
|
||||
const value = prefilled[item];
|
||||
|
||||
@ -89,7 +89,7 @@ export function procurementSpec(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const p = PROC[locale];
|
||||
const p = PROC[locale === 'de' ? 'de' : 'en'];
|
||||
const high = system.classification.riskClass === 'high';
|
||||
const requirements = REQUIREMENTS.filter((r) => high || !r.highOnly);
|
||||
|
||||
@ -113,7 +113,7 @@ export function procurementSpec(
|
||||
'|---|---|---|---|',
|
||||
];
|
||||
for (const r of requirements) {
|
||||
lines.push(`| ${r.id} | ${r[locale]} | ${r.must ? p.must : p.should} | ${p.fulfilled} |`);
|
||||
lines.push(`| ${r.id} | ${r[locale === 'de' ? 'de' : 'en']} | ${r.must ? p.must : p.should} | ${p.fulfilled} |`);
|
||||
}
|
||||
lines.push('', p.note);
|
||||
return lines.join('\n');
|
||||
@ -171,7 +171,7 @@ export function conformityDeclaration(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const d = DECL[locale];
|
||||
const d = DECL[locale === 'de' ? 'de' : 'en'];
|
||||
const provider =
|
||||
profile && profile.name.trim() !== ''
|
||||
? [profile.name, profile.street, profile.zipCity].filter((x) => x.trim() !== '').join(', ')
|
||||
|
||||
@ -70,6 +70,29 @@ describe('mehrsprachiger Content-Pack', () => {
|
||||
expect(result.riskClass).toBe('high');
|
||||
expect(result.reasons[0]).toContain('Annex III area');
|
||||
});
|
||||
|
||||
it('fällt für FR/IT/ES bei Rechtstexten auf Englisch zurück', () => {
|
||||
const fr = getContentPack('fr');
|
||||
const en = getContentPack('en');
|
||||
expect(fr.obligations.map((o) => o.id)).toEqual(en.obligations.map((o) => o.id));
|
||||
expect(fr.obligations[0]?.title).toBe(en.obligations[0]?.title);
|
||||
const result = classify({ ...base, annexIIICategories: ['a3-employment'] }, fr, 'fr');
|
||||
expect(result.riskClass).toBe('high');
|
||||
expect(result.reasons[0]).toContain('Annex III area'); // EN-Fallback
|
||||
});
|
||||
});
|
||||
|
||||
describe('UI-Wörterbücher FR/IT/ES', () => {
|
||||
it('sind vollständig (gleiche Schlüssel wie Deutsch)', async () => {
|
||||
const { uiStrings } = await import('../i18n/ui');
|
||||
const deKeys = Object.keys(uiStrings('de')).sort();
|
||||
for (const locale of ['fr', 'it', 'es'] as const) {
|
||||
const dict = uiStrings(locale) as Record<string, string>;
|
||||
expect(Object.keys(dict).sort()).toEqual(deKeys);
|
||||
// Stichprobe: tatsächlich übersetzt, nicht kopiert
|
||||
expect(dict['btnSave']).not.toBe(uiStrings('de').btnSave);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('nationale Module', () => {
|
||||
|
||||
@ -30,7 +30,7 @@ export function aiPolicy(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Internal AI policy (draft framework)',
|
||||
sections: [
|
||||
@ -77,7 +77,7 @@ export function trainingPlan(
|
||||
profile?: CompanyProfile,
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'AI literacy training plan & record (Art. 4)',
|
||||
intro: 'Art. 4 EU AI Act requires a sufficient level of AI literacy for staff dealing with AI systems — in force since 2 February 2025. This document plans the measures and serves as evidence.',
|
||||
@ -134,7 +134,7 @@ export function worksAgreement(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Works agreement on the use of AI systems (draft framework, Germany)',
|
||||
parties: 'Between the employer [company] and the works council of [site], the following works agreement is concluded pursuant to Sec. 87 (1) No. 6, Sec. 90 BetrVG:',
|
||||
|
||||
@ -32,7 +32,7 @@ export function reportingPolicy(
|
||||
profile?: CompanyProfile,
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Internal reporting and escalation policy for AI incidents (draft)',
|
||||
sections: [
|
||||
@ -75,7 +75,7 @@ export function approvalRequest(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Approval request for a new AI system (internal form)',
|
||||
intro: 'To be completed by the requesting department before any productive use of a new AI system or a substantial change to an existing one. Approval is granted by [AI officer / management].',
|
||||
@ -125,7 +125,7 @@ export function auditChecklist(
|
||||
profile?: CompanyProfile,
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Internal AI compliance audit checklist (periodic self-review)',
|
||||
intro: 'Recommended interval: every [6] months and after material changes. Auditor: [AI officer]. Result to management.',
|
||||
|
||||
@ -41,7 +41,7 @@ export function worksCouncilInfo(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Information to the works council pursuant to Sec. 90 BetrVG (draft)',
|
||||
to: 'To the works council of',
|
||||
@ -96,7 +96,7 @@ export function employeeInfo(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Employee information on the use of an AI system (draft)',
|
||||
body: 'Dear colleagues,\n\nwe hereby inform you that the AI system described below will be used in our company. This information is provided pursuant to Art. 26(7) of the EU AI Act and applicable national law.',
|
||||
@ -137,7 +137,7 @@ export function friaTemplate(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Fundamental rights impact assessment (FRIA, Art. 27) — working template',
|
||||
sections: [
|
||||
@ -181,7 +181,7 @@ export function incidentReportForm(
|
||||
locale: Locale = 'de',
|
||||
): string {
|
||||
const s = docStrings(locale);
|
||||
const T = locale === 'en'
|
||||
const T = locale !== 'de'
|
||||
? {
|
||||
title: 'Serious incident report (Art. 73) — internal form',
|
||||
note: 'Deadlines: report to the market surveillance authority immediately after establishing the causal link, at the latest within 15 days; death of a person: 10 days; widespread infringement / critical infrastructure: 2 days.',
|
||||
|
||||
@ -3,40 +3,62 @@
|
||||
*
|
||||
* Die App ist für europäische Unternehmen gedacht — alle Inhalte
|
||||
* (UI, Regel-Engine, Content-Pack, Dokumente) sind lokalisierbar.
|
||||
* Aktuell vollständig: Deutsch und Englisch; weitere EU-Sprachen
|
||||
* werden durch Erweitern von {@link LText} und den Wörterbüchern ergänzt.
|
||||
* Vollständig übersetzt: UI in DE/EN/FR/IT/ES; regulatorische
|
||||
* Rechtstexte (Content-Pack, Dokumente) in DE/EN mit Fallback auf
|
||||
* Englisch für die übrigen Sprachen, bis die Fachübersetzung vorliegt.
|
||||
*/
|
||||
|
||||
/** Unterstützte Sprachen. */
|
||||
export type Locale = 'de' | 'en';
|
||||
export type Locale = 'de' | 'en' | 'fr' | 'it' | 'es';
|
||||
|
||||
/** Alle unterstützten Sprachen in Anzeigereihenfolge. */
|
||||
export const LOCALES: readonly Locale[] = ['de', 'en'];
|
||||
export const LOCALES: readonly Locale[] = ['de', 'en', 'fr', 'it', 'es'];
|
||||
|
||||
/** Lokalisierter Text — eine Fassung je unterstützter Sprache. */
|
||||
/** Anzeigenamen der Sprachen (Eigenbezeichnung). */
|
||||
export const LOCALE_NAMES: Readonly<Record<Locale, string>> = {
|
||||
de: 'Deutsch',
|
||||
en: 'English',
|
||||
fr: 'Français',
|
||||
it: 'Italiano',
|
||||
es: 'Español',
|
||||
};
|
||||
|
||||
/**
|
||||
* Lokalisierter Text. Deutsch und Englisch sind Pflicht; weitere
|
||||
* Sprachen optional — fehlt eine Übersetzung, greift der Fallback
|
||||
* auf Englisch (siehe {@link resolveText}).
|
||||
*/
|
||||
export interface LText {
|
||||
readonly de: string;
|
||||
readonly en: string;
|
||||
readonly fr?: string;
|
||||
readonly it?: string;
|
||||
readonly es?: string;
|
||||
}
|
||||
|
||||
/** Kurzform zum Anlegen lokalisierter Texte. */
|
||||
/** Kurzform zum Anlegen lokalisierter Texte (DE/EN-Basis). */
|
||||
export function lt(de: string, en: string): LText {
|
||||
return { de, en };
|
||||
}
|
||||
|
||||
/** Löst einen lokalisierten Text in der gewünschten Sprache auf. */
|
||||
/** Löst einen lokalisierten Text auf; Fallback: Englisch. */
|
||||
export function resolveText(text: LText, locale: Locale): string {
|
||||
return text[locale];
|
||||
return text[locale] ?? text.en;
|
||||
}
|
||||
|
||||
const LOCALE_KEY = 'ai-act-kompass/locale/v1';
|
||||
|
||||
/** Lädt die gespeicherte Sprache (Fallback: Browser-Sprache, sonst Deutsch). */
|
||||
function isLocale(value: string | null): value is Locale {
|
||||
return value !== null && (LOCALES as readonly string[]).includes(value);
|
||||
}
|
||||
|
||||
/** Lädt die gespeicherte Sprache (Fallback: Browser-Sprache, sonst Englisch). */
|
||||
export function loadLocale(): Locale {
|
||||
try {
|
||||
const stored = localStorage.getItem(LOCALE_KEY);
|
||||
if (stored === 'de' || stored === 'en') return stored;
|
||||
return navigator.language.toLowerCase().startsWith('de') ? 'de' : 'en';
|
||||
if (isLocale(stored)) return stored;
|
||||
const nav = navigator.language.slice(0, 2).toLowerCase();
|
||||
return isLocale(nav) ? nav : 'en';
|
||||
} catch {
|
||||
return 'de';
|
||||
}
|
||||
|
||||
173
ai-act-kompass/src/i18n/ui.es.ts
Normal file
173
ai-act-kompass/src/i18n/ui.es.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import type { UIStrings } from './ui';
|
||||
|
||||
/** Spanisches UI-Wörterbuch. */
|
||||
export const ES: UIStrings = {
|
||||
brandTag: 'Cumplimiento del Reglamento de IA de la UE para pymes · local-first',
|
||||
navDashboard: 'Panel & inventario',
|
||||
navTasks: 'Tareas & plazos',
|
||||
navNew: 'Evaluar un nuevo sistema',
|
||||
navTemplates: 'Plantillas & formularios',
|
||||
navSettings: 'Ajustes & copia de seguridad',
|
||||
footPrivacy: 'Sin nube. Sin telemetría.',
|
||||
footLocal: 'Todos los datos permanecen en este dispositivo.',
|
||||
footNoAdvice: 'No constituye asesoramiento jurídico.',
|
||||
|
||||
dashTitle: 'Panel',
|
||||
dashSub: 'Su cumplimiento del Reglamento de IA de la UE de un vistazo. Todos los datos permanecen en local en este dispositivo.',
|
||||
statSystems: 'Sistemas de IA en el inventario',
|
||||
statHigh: 'Sistemas de alto riesgo',
|
||||
statProhibited: 'Prácticas prohibidas',
|
||||
statOpen: 'Tareas abiertas',
|
||||
deadlinesTitle: 'Plazos de aplicación del Reglamento de IA',
|
||||
inventoryTitle: 'Inventario de sistemas de IA',
|
||||
inventoryPrint: 'Imprimir inventario / PDF',
|
||||
newSystem: '+ Evaluar sistema',
|
||||
emptyInventory:
|
||||
'Aún no hay sistemas de IA registrados. Empiece evaluando su primer sistema — p. ej. su chatbot, su preselección de candidatos o una herramienta de IA adquirida.',
|
||||
colSystem: 'Sistema',
|
||||
colRole: 'Rol',
|
||||
colRisk: 'Clase de riesgo',
|
||||
colOwner: 'Responsable',
|
||||
colUpdated: 'Última evaluación',
|
||||
disclaimerLine:
|
||||
'AI-Act-Kompass es una herramienta de trabajo estructurada basada en el Reglamento (UE) 2024/1689 — no es asesoramiento jurídico. Content pack v{version}.',
|
||||
|
||||
tasksTitle: 'Tareas & plazos',
|
||||
tasksSub: 'Todas las obligaciones de todos los sistemas como lista de verificación — qué está hecho, qué vence ahora y qué está por venir.',
|
||||
tasksProgress: '{done} de {total} tareas completadas',
|
||||
tasksDueNow: 'Vence ahora',
|
||||
tasksUpcoming: 'Próximamente',
|
||||
tasksResolved: 'Completado',
|
||||
tasksEmpty: 'No hay tareas — evalúe primero un sistema de IA.',
|
||||
tasksAllDone: 'Todo hecho en este grupo.',
|
||||
tasksDue: 'Plazo',
|
||||
|
||||
wizardTitleNew: 'Evaluar un nuevo sistema de IA',
|
||||
wizardTitleRe: 'Reevaluación: {name}',
|
||||
wizardSub: 'Responda a las preguntas — la clase de riesgo se determina automáticamente según la sistemática del Reglamento de IA.',
|
||||
stepBasics: 'Datos básicos',
|
||||
stepDefinition: 'Definición de IA',
|
||||
stepProhibited: 'Prohibiciones',
|
||||
stepHighRisk: 'Alto riesgo',
|
||||
stepTransparency: 'Transparencia & GPAI',
|
||||
stepResult: 'Resultado',
|
||||
fieldName: 'Nombre del sistema *',
|
||||
fieldNamePh: 'p. ej. herramienta de cribado de candidatos',
|
||||
fieldPurpose: 'Finalidad prevista',
|
||||
fieldPurposePh: '¿Para qué se utiliza el sistema?',
|
||||
fieldVendor: 'Fabricante / proveedor',
|
||||
fieldOwner: 'Persona responsable (interna)',
|
||||
fieldRole: 'Rol de su empresa',
|
||||
roleHint: 'Proveedor = desarrolla/comercializa el sistema con su propio nombre. Responsable del despliegue = utiliza un sistema de terceros (caso más frecuente en pymes).',
|
||||
defTitle: '¿Cumple el sistema la definición de IA (art. 3, punto 1)?',
|
||||
defHint: 'El sistema solo entra en el Reglamento de IA si se cumplen todos los criterios.',
|
||||
defWarn: 'No se cumplen todos los criterios → el sistema no es un sistema de IA; el Reglamento de IA no se aplica.',
|
||||
prohTitle: 'Prácticas prohibidas (art. 5)',
|
||||
prohHint: 'Si alguno de estos puntos se aplica, el uso está prohibido desde el 2 de febrero de 2025.',
|
||||
hrTitle: 'Clasificación de alto riesgo (art. 6)',
|
||||
annexILabel: 'El sistema es un componente de seguridad de un producto regulado (p. ej. producto sanitario, máquina, ascensor) o es él mismo dicho producto.',
|
||||
annexIIITitle: 'Ámbitos de uso según el anexo III',
|
||||
exceptionTitle: 'Posible excepción (art. 6, apdo. 3)',
|
||||
profilingLabel: 'El sistema realiza elaboración de perfiles de personas físicas.',
|
||||
profilingRef: 'La elaboración de perfiles excluye la excepción — siempre alto riesgo.',
|
||||
art63Label: 'El sistema solo realiza una tarea procedimental limitada o preparatoria, o únicamente mejora el resultado de una actividad humana ya concluida — sin riesgo significativo para la salud, la seguridad o los derechos fundamentales.',
|
||||
art63Ref: 'Art. 6, apdo. 3 — la evaluación debe documentarse (art. 6, apdo. 4).',
|
||||
trTitle: 'Obligaciones de transparencia (art. 50)',
|
||||
gpaiTitle: 'IA de uso general (GPAI)',
|
||||
gpaiLabel: 'Proporcionamos nuestro propio modelo GPAI (p. ej. modelo base autoentrenado o sustancialmente modificado).',
|
||||
gpaiRef: 'Art. 51 y ss. — el mero uso de GPT/Claude vía API no cuenta.',
|
||||
resultTitle: 'Resultado:',
|
||||
resultGpai: 'Se aplican además las obligaciones de los modelos GPAI (art. 53 y ss.).',
|
||||
resultProhibited: 'El uso de este sistema está prohibido según el art. 5 (multa de hasta 35 M€ o el 7 % de la facturación anual mundial). Cese el uso y consulte a un abogado.',
|
||||
btnCancel: 'Cancelar',
|
||||
btnBack: 'Atrás',
|
||||
btnNext: 'Siguiente',
|
||||
btnSave: 'Guardar',
|
||||
|
||||
detailBack: '← Volver al panel',
|
||||
detailNoPurpose: 'Sin finalidad registrada',
|
||||
detailReasons: 'Motivación de la clasificación',
|
||||
detailReassess: 'Reevaluar',
|
||||
detailDelete: 'Eliminar sistema',
|
||||
detailObligations: 'Obligaciones',
|
||||
detailNational: 'incl. módulos nacionales: {codes}',
|
||||
detailDocs: 'Generar documentos',
|
||||
docShow: 'ver',
|
||||
docHide: 'ocultar',
|
||||
docPrint: 'Imprimir / PDF',
|
||||
docRisk: 'Informe de riesgo',
|
||||
docPlan: 'Plan de acción',
|
||||
docAnnexIV: 'Documentación anexo IV',
|
||||
docProcurement: 'Pliego de compra de IA',
|
||||
docConformity: 'Declaración UE de conformidad',
|
||||
confirmDeleteSystem: '¿Eliminar realmente «{name}»?',
|
||||
systemNotFound: 'Sistema no encontrado.',
|
||||
statusOpen: 'Abierto',
|
||||
statusInProgress: 'En curso',
|
||||
statusDone: 'Hecho',
|
||||
statusNA: 'No aplicable',
|
||||
|
||||
settingsTitle: 'Ajustes',
|
||||
settingsSub: 'Soberanía de los datos: todo permanece en local en este navegador — sin sincronización en la nube, sin telemetría.',
|
||||
langTitle: 'Sprache / Language / Idioma',
|
||||
langHint: 'Interfaz en DE/EN/FR/IT/ES. Los textos normativos y los documentos generados están disponibles en alemán e inglés; los demás idiomas usan el inglés hasta que exista la traducción jurídica.',
|
||||
profileTitle: 'Perfil de empresa (membrete para informes & impresión PDF)',
|
||||
profileHint: 'Estos datos aparecen en el encabezado y pie de página de todos los documentos generados e impresos. El logotipo se guarda en local y nunca sale del dispositivo.',
|
||||
pfName: 'Razón social', pfStreet: 'Calle & número', pfZip: 'CP & ciudad',
|
||||
pfContact: 'Persona de contacto', pfEmail: 'Correo electrónico', pfPhone: 'Teléfono', pfWeb: 'Sitio web',
|
||||
logoNone: 'Sin logotipo guardado.',
|
||||
logoUpload: 'Subir logotipo',
|
||||
logoRemove: 'Quitar logotipo',
|
||||
logoTaken: 'Logotipo aplicado.',
|
||||
logoTooBig: 'Logotipo demasiado grande — use un archivo de menos de 300 KB.',
|
||||
logoNotImage: 'Elija un archivo de imagen (PNG, JPG o SVG).',
|
||||
countriesTitle: 'Módulos nacionales (requisitos adicionales)',
|
||||
countriesHint: 'Active los países de la UE en los que su empresa ofrece u opera sistemas de IA. Las obligaciones nacionales (autoridades, derecho laboral, leyes especiales) aparecerán en las listas y documentos. Cooperación transfronteriza: active todos los países implicados.',
|
||||
authorityLabel: 'Autoridad',
|
||||
packTitle: 'Content pack normativo',
|
||||
packStand: 'Actualizado a',
|
||||
packHint: 'El content pack (prohibiciones, ámbitos del anexo III, obligaciones UE, módulos nacionales, plazos) está modelado como paquete de datos sustituible. Las actualizaciones llegan con nuevas versiones de la app y, en el futuro, mediante un feed firmado.',
|
||||
backupTitle: 'Copia de seguridad',
|
||||
backupExport: 'Exportar copia (JSON)',
|
||||
backupImport: 'Importar copia',
|
||||
importOk: 'Importación completada: {count} sistema(s){profile}.',
|
||||
importProfileSuffix: ' incl. perfil de empresa',
|
||||
importFail: 'Error de importación: {error}',
|
||||
deleteTitle: 'Eliminar todos los datos',
|
||||
deleteHint: 'Elimina irrevocablemente de este navegador todos los sistemas de IA registrados y el perfil de empresa.',
|
||||
deleteBtn: 'Eliminar todo',
|
||||
deleteConfirm: '¿Eliminar realmente y de forma irrevocable todos los datos locales?',
|
||||
deleteDone: 'Todos los datos han sido eliminados.',
|
||||
|
||||
legalGateTitle: 'Aviso legal importante',
|
||||
legalGateBody1:
|
||||
'AI-Act-Kompass es una herramienta de trabajo estructurada destinada a facilitar la aplicación del Reglamento (UE) 2024/1689 (Reglamento de IA) y de las disposiciones nacionales pertinentes.',
|
||||
legalGateBody2:
|
||||
'Esta aplicación no presta servicios jurídicos y no constituye asesoramiento jurídico, información jurídica ni instrucción jurídicamente vinculante. Todas las clasificaciones, listas y documentos generados son evaluaciones preliminares no vinculantes y borradores, sin garantía de exactitud, integridad o actualidad.',
|
||||
legalGateBody3:
|
||||
'La interpretación vinculante del Reglamento de IA corresponde exclusivamente a las autoridades y tribunales competentes. Esta herramienta no sustituye la valoración jurídica de su caso concreto — consulte a un asesor jurídico cualificado. El uso es bajo su propio riesgo; se excluye la responsabilidad por decisiones basadas en esta herramienta en la medida permitida por la ley.',
|
||||
legalGateAccept: 'Entendido — usar como herramienta de trabajo',
|
||||
legalNoticeTitle: 'Aviso legal (no es asesoramiento jurídico)',
|
||||
resultDisclaimer:
|
||||
'Esta clasificación es una evaluación preliminar automatizada y no vinculante basada en sus respuestas — no es asesoramiento jurídico. Haga revisar el resultado por un jurista antes de decisiones importantes.',
|
||||
|
||||
templatesTitle: 'Plantillas & formularios',
|
||||
templatesSub: 'Borradores a nivel de empresa para la implementación interna y externa — imprimibles con membrete. Los formularios específicos de sistema (comité de empresa, información a empleados, FRIA, notificación de incidentes) están en la vista de cada sistema.',
|
||||
templatesHint: 'Todas las plantillas son borradores con campos por completar — adáptelas y hágalas revisar jurídicamente antes de usarlas.',
|
||||
tplPolicy: 'Política interna de IA',
|
||||
tplPolicyDesc: 'Reglas de uso de la IA en la empresa: aprobaciones, prohibiciones, supervisión, transparencia, incidentes.',
|
||||
tplTraining: 'Plan de formación en competencia de IA (art. 4)',
|
||||
tplTrainingDesc: 'Matriz de formación y registro continuo — obligatorio desde el 02/02/2025.',
|
||||
tplWorksAgreement: 'Acuerdo de empresa sobre IA (marco)',
|
||||
tplWorksAgreementDesc: 'Borrador según el derecho alemán (§ 87, § 90 BetrVG): limitación de finalidad, sin decisiones de RR. HH. automatizadas, derechos del comité de empresa.',
|
||||
docWorksCouncil: 'Información al comité de empresa (§ 90 BetrVG)',
|
||||
docEmployeeInfo: 'Información a los empleados sobre el uso de IA',
|
||||
docFria: 'Plantilla FRIA (art. 27)',
|
||||
docIncident: 'Notificación de incidente (art. 73)',
|
||||
tplReporting: 'Política interna de notificación & escalado',
|
||||
tplReportingDesc: 'Obligación interna de notificar incidentes de IA: canales, plazos de 24 h/48 h, niveles de escalado, registro — prepara la notificación del art. 73.',
|
||||
tplApproval: 'Solicitud de aprobación de sistema de IA',
|
||||
tplApprovalDesc: 'Formulario interno para aprobar nuevas herramientas de IA — contra la shadow AI, con bloque de decisión.',
|
||||
tplAudit: 'Lista de auditoría interna de cumplimiento de IA',
|
||||
tplAuditDesc: 'Autoevaluación periódica (inventario, formaciones, registros, incidentes, documentos de proveedores) con firma.',
|
||||
};
|
||||
173
ai-act-kompass/src/i18n/ui.fr.ts
Normal file
173
ai-act-kompass/src/i18n/ui.fr.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import type { UIStrings } from './ui';
|
||||
|
||||
/** Französisches UI-Wörterbuch. */
|
||||
export const FR: UIStrings = {
|
||||
brandTag: 'Conformité au règlement IA de l’UE pour PME · local-first',
|
||||
navDashboard: 'Tableau de bord & inventaire',
|
||||
navTasks: 'Tâches & échéances',
|
||||
navNew: 'Évaluer un nouveau système',
|
||||
navTemplates: 'Modèles & formulaires',
|
||||
navSettings: 'Paramètres & sauvegarde',
|
||||
footPrivacy: 'Pas de cloud. Pas de télémétrie.',
|
||||
footLocal: 'Toutes les données restent sur cet appareil.',
|
||||
footNoAdvice: 'Ne constitue pas un conseil juridique.',
|
||||
|
||||
dashTitle: 'Tableau de bord',
|
||||
dashSub: 'Votre conformité au règlement IA de l’UE en un coup d’œil. Toutes les données restent en local sur cet appareil.',
|
||||
statSystems: 'Systèmes d’IA à l’inventaire',
|
||||
statHigh: 'Systèmes à haut risque',
|
||||
statProhibited: 'Pratiques interdites',
|
||||
statOpen: 'Tâches ouvertes',
|
||||
deadlinesTitle: 'Échéances d’application du règlement IA',
|
||||
inventoryTitle: 'Inventaire des systèmes d’IA',
|
||||
inventoryPrint: 'Imprimer l’inventaire / PDF',
|
||||
newSystem: '+ Évaluer un système',
|
||||
emptyInventory:
|
||||
'Aucun système d’IA enregistré. Commencez par évaluer votre premier système — p. ex. votre chatbot, votre présélection de candidatures ou un outil d’IA acheté.',
|
||||
colSystem: 'Système',
|
||||
colRole: 'Rôle',
|
||||
colRisk: 'Classe de risque',
|
||||
colOwner: 'Responsable',
|
||||
colUpdated: 'Dernière évaluation',
|
||||
disclaimerLine:
|
||||
'AI-Act-Kompass est une aide de travail structurée fondée sur le règlement (UE) 2024/1689 — pas un conseil juridique. Pack de contenu v{version}.',
|
||||
|
||||
tasksTitle: 'Tâches & échéances',
|
||||
tasksSub: 'Toutes les obligations de tous les systèmes sous forme de liste à cocher — ce qui est fait, ce qui est dû maintenant et ce qui arrive.',
|
||||
tasksProgress: '{done} tâches sur {total} accomplies',
|
||||
tasksDueNow: 'À traiter maintenant',
|
||||
tasksUpcoming: 'À venir',
|
||||
tasksResolved: 'Accompli',
|
||||
tasksEmpty: 'Aucune tâche — évaluez d’abord un système d’IA.',
|
||||
tasksAllDone: 'Tout est fait dans ce groupe.',
|
||||
tasksDue: 'Échéance',
|
||||
|
||||
wizardTitleNew: 'Évaluer un nouveau système d’IA',
|
||||
wizardTitleRe: 'Réévaluation : {name}',
|
||||
wizardSub: 'Répondez aux questions — la classe de risque est déterminée automatiquement selon la systématique du règlement IA.',
|
||||
stepBasics: 'Données de base',
|
||||
stepDefinition: 'Définition de l’IA',
|
||||
stepProhibited: 'Interdictions',
|
||||
stepHighRisk: 'Haut risque',
|
||||
stepTransparency: 'Transparence & GPAI',
|
||||
stepResult: 'Résultat',
|
||||
fieldName: 'Nom du système *',
|
||||
fieldNamePh: 'p. ex. outil de présélection de candidatures',
|
||||
fieldPurpose: 'Destination',
|
||||
fieldPurposePh: 'À quoi sert le système ?',
|
||||
fieldVendor: 'Fabricant / fournisseur',
|
||||
fieldOwner: 'Personne responsable (interne)',
|
||||
fieldRole: 'Rôle de votre entreprise',
|
||||
roleHint: 'Fournisseur = développe/commercialise le système sous son propre nom. Déployeur = utilise un système tiers (cas le plus fréquent pour les PME).',
|
||||
defTitle: 'Le système répond-il à la définition de l’IA (art. 3, point 1) ?',
|
||||
defHint: 'Le système ne relève du règlement IA que si tous les critères s’appliquent.',
|
||||
defWarn: 'Tous les critères ne sont pas remplis → le système n’est pas un système d’IA ; le règlement IA ne s’applique pas.',
|
||||
prohTitle: 'Pratiques interdites (art. 5)',
|
||||
prohHint: 'Si l’un de ces points s’applique, l’utilisation est interdite depuis le 2 février 2025.',
|
||||
hrTitle: 'Classification à haut risque (art. 6)',
|
||||
annexILabel: 'Le système est un composant de sécurité d’un produit réglementé (p. ex. dispositif médical, machine, ascenseur) ou un tel produit lui-même.',
|
||||
annexIIITitle: 'Domaines d’utilisation selon l’annexe III',
|
||||
exceptionTitle: 'Exception possible (art. 6, par. 3)',
|
||||
profilingLabel: 'Le système effectue un profilage de personnes physiques.',
|
||||
profilingRef: 'Le profilage exclut l’exception — toujours haut risque.',
|
||||
art63Label: 'Le système n’accomplit qu’une tâche procédurale étroite ou préparatoire, ou ne fait qu’améliorer le résultat d’une activité humaine déjà achevée — sans risque important pour la santé, la sécurité ou les droits fondamentaux.',
|
||||
art63Ref: 'Art. 6, par. 3 — l’appréciation doit être documentée (art. 6, par. 4).',
|
||||
trTitle: 'Obligations de transparence (art. 50)',
|
||||
gpaiTitle: 'IA à usage général (GPAI)',
|
||||
gpaiLabel: 'Nous fournissons notre propre modèle GPAI (p. ex. modèle de base auto-entraîné ou substantiellement modifié).',
|
||||
gpaiRef: 'Art. 51 et s. — la simple utilisation de GPT/Claude via API ne compte pas.',
|
||||
resultTitle: 'Résultat :',
|
||||
resultGpai: 'Les obligations relatives aux modèles GPAI (art. 53 et s.) s’appliquent en outre.',
|
||||
resultProhibited: 'L’utilisation de ce système est interdite en vertu de l’art. 5 (amende jusqu’à 35 M€ ou 7 % du chiffre d’affaires annuel mondial). Cessez l’utilisation et consultez un juriste.',
|
||||
btnCancel: 'Annuler',
|
||||
btnBack: 'Retour',
|
||||
btnNext: 'Suivant',
|
||||
btnSave: 'Enregistrer',
|
||||
|
||||
detailBack: '← Retour au tableau de bord',
|
||||
detailNoPurpose: 'Aucune destination renseignée',
|
||||
detailReasons: 'Motivation de la classification',
|
||||
detailReassess: 'Réévaluer',
|
||||
detailDelete: 'Supprimer le système',
|
||||
detailObligations: 'Obligations',
|
||||
detailNational: 'incl. modules nationaux : {codes}',
|
||||
detailDocs: 'Générer des documents',
|
||||
docShow: 'afficher',
|
||||
docHide: 'masquer',
|
||||
docPrint: 'Imprimer / PDF',
|
||||
docRisk: 'Rapport de risque',
|
||||
docPlan: 'Plan d’action',
|
||||
docAnnexIV: 'Documentation annexe IV',
|
||||
docProcurement: 'Cahier des charges achat d’IA',
|
||||
docConformity: 'Déclaration UE de conformité',
|
||||
confirmDeleteSystem: 'Supprimer vraiment « {name} » ?',
|
||||
systemNotFound: 'Système introuvable.',
|
||||
statusOpen: 'Ouvert',
|
||||
statusInProgress: 'En cours',
|
||||
statusDone: 'Fait',
|
||||
statusNA: 'Non applicable',
|
||||
|
||||
settingsTitle: 'Paramètres',
|
||||
settingsSub: 'Souveraineté des données : tout reste en local dans ce navigateur — pas de synchronisation cloud, pas de télémétrie.',
|
||||
langTitle: 'Sprache / Language / Langue',
|
||||
langHint: 'Interface en DE/EN/FR/IT/ES. Les textes réglementaires et les documents générés sont disponibles en allemand et en anglais ; les autres langues utilisent l’anglais en attendant la traduction juridique.',
|
||||
profileTitle: 'Profil d’entreprise (en-tête pour rapports & impression PDF)',
|
||||
profileHint: 'Ces informations apparaissent dans l’en-tête et le pied de page de tous les documents générés et imprimés. Le logo reste stocké en local et ne quitte jamais l’appareil.',
|
||||
pfName: 'Raison sociale', pfStreet: 'Rue & numéro', pfZip: 'Code postal & ville',
|
||||
pfContact: 'Personne de contact', pfEmail: 'E-mail', pfPhone: 'Téléphone', pfWeb: 'Site web',
|
||||
logoNone: 'Aucun logo enregistré.',
|
||||
logoUpload: 'Téléverser un logo',
|
||||
logoRemove: 'Supprimer le logo',
|
||||
logoTaken: 'Logo appliqué.',
|
||||
logoTooBig: 'Logo trop volumineux — utilisez un fichier de moins de 300 Ko.',
|
||||
logoNotImage: 'Veuillez choisir un fichier image (PNG, JPG ou SVG).',
|
||||
countriesTitle: 'Modules nationaux (exigences supplémentaires)',
|
||||
countriesHint: 'Activez les pays de l’UE dans lesquels votre entreprise propose ou exploite des systèmes d’IA. Les obligations nationales (autorités, droit du travail, lois spéciales) apparaissent alors dans les checklists et documents. Coopération transfrontalière : activez tous les pays concernés.',
|
||||
authorityLabel: 'Autorité',
|
||||
packTitle: 'Pack de contenu réglementaire',
|
||||
packStand: 'État',
|
||||
packHint: 'Le pack de contenu (interdictions, domaines annexe III, obligations UE, modules nationaux, échéances) est modélisé comme un paquet de données remplaçable. Les mises à jour arrivent avec les nouvelles versions de l’app et, à l’avenir, via un flux signé.',
|
||||
backupTitle: 'Sauvegarde',
|
||||
backupExport: 'Exporter la sauvegarde (JSON)',
|
||||
backupImport: 'Importer une sauvegarde',
|
||||
importOk: 'Import terminé : {count} système(s){profile}.',
|
||||
importProfileSuffix: ' incl. profil d’entreprise',
|
||||
importFail: 'Échec de l’import : {error}',
|
||||
deleteTitle: 'Supprimer toutes les données',
|
||||
deleteHint: 'Supprime irrévocablement tous les systèmes d’IA enregistrés et le profil d’entreprise de ce navigateur.',
|
||||
deleteBtn: 'Tout supprimer',
|
||||
deleteConfirm: 'Supprimer vraiment et irrévocablement toutes les données locales ?',
|
||||
deleteDone: 'Toutes les données ont été supprimées.',
|
||||
|
||||
legalGateTitle: 'Avertissement juridique important',
|
||||
legalGateBody1:
|
||||
'AI-Act-Kompass est une aide de travail structurée destinée à faciliter la mise en œuvre du règlement (UE) 2024/1689 (règlement IA) et des dispositions nationales pertinentes.',
|
||||
legalGateBody2:
|
||||
'Cette application ne fournit pas de services juridiques et ne constitue ni un conseil juridique, ni un renseignement juridique, ni une instruction juridiquement contraignante. Toutes les classifications, checklists et documents générés sont des évaluations préliminaires non contraignantes et des projets, sans garantie d’exactitude, d’exhaustivité ou d’actualité.',
|
||||
legalGateBody3:
|
||||
'L’interprétation contraignante du règlement IA appartient exclusivement aux autorités et juridictions compétentes. Cet outil ne remplace pas l’appréciation juridique de votre cas particulier — consultez un conseil juridique qualifié. L’utilisation se fait à vos risques ; toute responsabilité pour des décisions fondées sur cet outil est exclue dans la mesure permise par la loi.',
|
||||
legalGateAccept: 'Compris — utiliser comme aide de travail',
|
||||
legalNoticeTitle: 'Avertissement juridique (pas un conseil juridique)',
|
||||
resultDisclaimer:
|
||||
'Cette classification est une évaluation préliminaire automatisée et non contraignante fondée sur vos réponses — pas un conseil juridique. Faites vérifier le résultat par un juriste avant toute décision importante.',
|
||||
|
||||
templatesTitle: 'Modèles & formulaires',
|
||||
templatesSub: 'Projets à l’échelle de l’entreprise pour la mise en œuvre interne et externe — imprimables avec en-tête. Les formulaires liés à un système (comité d’entreprise, information des salariés, FRIA, signalement d’incident) se trouvent dans la vue du système concerné.',
|
||||
templatesHint: 'Tous les modèles sont des projets avec des champs à compléter — à adapter et à faire vérifier juridiquement avant utilisation.',
|
||||
tplPolicy: 'Politique interne d’IA',
|
||||
tplPolicyDesc: 'Règles d’utilisation de l’IA dans l’entreprise : validations, interdictions, supervision, transparence, incidents.',
|
||||
tplTraining: 'Plan de formation à la maîtrise de l’IA (art. 4)',
|
||||
tplTrainingDesc: 'Matrice de formation et registre continu — obligatoire depuis le 02/02/2025.',
|
||||
tplWorksAgreement: 'Accord d’entreprise sur l’IA (cadre)',
|
||||
tplWorksAgreementDesc: 'Projet selon le droit allemand (§ 87, § 90 BetrVG) : limitation des finalités, pas de décisions RH automatisées, droits du comité d’entreprise.',
|
||||
docWorksCouncil: 'Information du comité d’entreprise (§ 90 BetrVG)',
|
||||
docEmployeeInfo: 'Information des salariés sur l’usage de l’IA',
|
||||
docFria: 'Modèle FRIA (art. 27)',
|
||||
docIncident: 'Signalement d’incident (art. 73)',
|
||||
tplReporting: 'Politique interne de signalement & escalade',
|
||||
tplReportingDesc: 'Obligation interne de signalement des incidents d’IA : canaux, délais 24 h/48 h, niveaux d’escalade, registre — prépare le signalement art. 73.',
|
||||
tplApproval: 'Demande de validation d’un système d’IA',
|
||||
tplApprovalDesc: 'Formulaire interne de validation des nouveaux outils d’IA — contre l’IA fantôme, avec bloc de décision.',
|
||||
tplAudit: 'Checklist d’audit interne de conformité IA',
|
||||
tplAuditDesc: 'Auto-contrôle périodique (inventaire, formations, journaux, incidents, documents fournisseurs) avec visa.',
|
||||
};
|
||||
173
ai-act-kompass/src/i18n/ui.it.ts
Normal file
173
ai-act-kompass/src/i18n/ui.it.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import type { UIStrings } from './ui';
|
||||
|
||||
/** Italienisches UI-Wörterbuch. */
|
||||
export const IT: UIStrings = {
|
||||
brandTag: 'Conformità al regolamento IA dell’UE per PMI · local-first',
|
||||
navDashboard: 'Dashboard & inventario',
|
||||
navTasks: 'Attività & scadenze',
|
||||
navNew: 'Valutare un nuovo sistema',
|
||||
navTemplates: 'Modelli & moduli',
|
||||
navSettings: 'Impostazioni & backup',
|
||||
footPrivacy: 'Nessun cloud. Nessuna telemetria.',
|
||||
footLocal: 'Tutti i dati restano su questo dispositivo.',
|
||||
footNoAdvice: 'Non costituisce consulenza legale.',
|
||||
|
||||
dashTitle: 'Dashboard',
|
||||
dashSub: 'La conformità al regolamento IA dell’UE a colpo d’occhio. Tutti i dati restano in locale su questo dispositivo.',
|
||||
statSystems: 'Sistemi di IA in inventario',
|
||||
statHigh: 'Sistemi ad alto rischio',
|
||||
statProhibited: 'Pratiche vietate',
|
||||
statOpen: 'Attività aperte',
|
||||
deadlinesTitle: 'Scadenze di applicazione del regolamento IA',
|
||||
inventoryTitle: 'Inventario dei sistemi di IA',
|
||||
inventoryPrint: 'Stampare l’inventario / PDF',
|
||||
newSystem: '+ Valutare un sistema',
|
||||
emptyInventory:
|
||||
'Nessun sistema di IA registrato. Iniziate valutando il vostro primo sistema — p. es. il vostro chatbot, la preselezione dei candidati o uno strumento di IA acquistato.',
|
||||
colSystem: 'Sistema',
|
||||
colRole: 'Ruolo',
|
||||
colRisk: 'Classe di rischio',
|
||||
colOwner: 'Responsabile',
|
||||
colUpdated: 'Ultima valutazione',
|
||||
disclaimerLine:
|
||||
'AI-Act-Kompass è uno strumento di lavoro strutturato basato sul regolamento (UE) 2024/1689 — non è consulenza legale. Content pack v{version}.',
|
||||
|
||||
tasksTitle: 'Attività & scadenze',
|
||||
tasksSub: 'Tutti gli obblighi di tutti i sistemi come lista da spuntare — cosa è fatto, cosa scade ora e cosa arriverà.',
|
||||
tasksProgress: '{done} attività su {total} completate',
|
||||
tasksDueNow: 'In scadenza ora',
|
||||
tasksUpcoming: 'In arrivo',
|
||||
tasksResolved: 'Completato',
|
||||
tasksEmpty: 'Nessuna attività — valutate prima un sistema di IA.',
|
||||
tasksAllDone: 'Tutto fatto in questo gruppo.',
|
||||
tasksDue: 'Scadenza',
|
||||
|
||||
wizardTitleNew: 'Valutare un nuovo sistema di IA',
|
||||
wizardTitleRe: 'Rivalutazione: {name}',
|
||||
wizardSub: 'Rispondete alle domande — la classe di rischio viene determinata automaticamente secondo la sistematica del regolamento IA.',
|
||||
stepBasics: 'Dati di base',
|
||||
stepDefinition: 'Definizione di IA',
|
||||
stepProhibited: 'Divieti',
|
||||
stepHighRisk: 'Alto rischio',
|
||||
stepTransparency: 'Trasparenza & GPAI',
|
||||
stepResult: 'Risultato',
|
||||
fieldName: 'Nome del sistema *',
|
||||
fieldNamePh: 'p. es. strumento di screening dei candidati',
|
||||
fieldPurpose: 'Finalità prevista',
|
||||
fieldPurposePh: 'A cosa serve il sistema?',
|
||||
fieldVendor: 'Produttore / fornitore',
|
||||
fieldOwner: 'Persona responsabile (interna)',
|
||||
fieldRole: 'Ruolo della vostra azienda',
|
||||
roleHint: 'Fornitore = sviluppa/commercializza il sistema con il proprio nome. Deployer = utilizza un sistema di terzi (caso più frequente per le PMI).',
|
||||
defTitle: 'Il sistema soddisfa la definizione di IA (art. 3, punto 1)?',
|
||||
defHint: 'Il sistema rientra nel regolamento IA solo se tutti i criteri sono soddisfatti.',
|
||||
defWarn: 'Non tutti i criteri sono soddisfatti → il sistema non è un sistema di IA; il regolamento IA non si applica.',
|
||||
prohTitle: 'Pratiche vietate (art. 5)',
|
||||
prohHint: 'Se uno di questi punti si applica, l’uso è vietato dal 2 febbraio 2025.',
|
||||
hrTitle: 'Classificazione ad alto rischio (art. 6)',
|
||||
annexILabel: 'Il sistema è un componente di sicurezza di un prodotto regolamentato (p. es. dispositivo medico, macchina, ascensore) o è esso stesso un tale prodotto.',
|
||||
annexIIITitle: 'Ambiti di utilizzo secondo l’allegato III',
|
||||
exceptionTitle: 'Possibile eccezione (art. 6, par. 3)',
|
||||
profilingLabel: 'Il sistema effettua profilazione di persone fisiche.',
|
||||
profilingRef: 'La profilazione esclude l’eccezione — sempre alto rischio.',
|
||||
art63Label: 'Il sistema svolge solo un compito procedurale ristretto o preparatorio, oppure migliora soltanto il risultato di un’attività umana già conclusa — senza rischio significativo per salute, sicurezza o diritti fondamentali.',
|
||||
art63Ref: 'Art. 6, par. 3 — la valutazione deve essere documentata (art. 6, par. 4).',
|
||||
trTitle: 'Obblighi di trasparenza (art. 50)',
|
||||
gpaiTitle: 'IA per finalità generali (GPAI)',
|
||||
gpaiLabel: 'Forniamo un nostro modello GPAI (p. es. modello di base auto-addestrato o sostanzialmente modificato).',
|
||||
gpaiRef: 'Art. 51 e segg. — il semplice uso di GPT/Claude via API non conta.',
|
||||
resultTitle: 'Risultato:',
|
||||
resultGpai: 'Si applicano inoltre gli obblighi per i modelli GPAI (art. 53 e segg.).',
|
||||
resultProhibited: 'L’uso di questo sistema è vietato ai sensi dell’art. 5 (sanzione fino a 35 mln € o al 7 % del fatturato annuo mondiale). Cessate l’uso e consultate un legale.',
|
||||
btnCancel: 'Annulla',
|
||||
btnBack: 'Indietro',
|
||||
btnNext: 'Avanti',
|
||||
btnSave: 'Salva',
|
||||
|
||||
detailBack: '← Torna alla dashboard',
|
||||
detailNoPurpose: 'Nessuna finalità registrata',
|
||||
detailReasons: 'Motivazione della classificazione',
|
||||
detailReassess: 'Rivalutare',
|
||||
detailDelete: 'Eliminare il sistema',
|
||||
detailObligations: 'Obblighi',
|
||||
detailNational: 'incl. moduli nazionali: {codes}',
|
||||
detailDocs: 'Generare documenti',
|
||||
docShow: 'mostra',
|
||||
docHide: 'nascondi',
|
||||
docPrint: 'Stampa / PDF',
|
||||
docRisk: 'Rapporto di rischio',
|
||||
docPlan: 'Piano d’azione',
|
||||
docAnnexIV: 'Documentazione allegato IV',
|
||||
docProcurement: 'Capitolato acquisto IA',
|
||||
docConformity: 'Dichiarazione UE di conformità',
|
||||
confirmDeleteSystem: 'Eliminare davvero «{name}»?',
|
||||
systemNotFound: 'Sistema non trovato.',
|
||||
statusOpen: 'Aperto',
|
||||
statusInProgress: 'In corso',
|
||||
statusDone: 'Fatto',
|
||||
statusNA: 'Non applicabile',
|
||||
|
||||
settingsTitle: 'Impostazioni',
|
||||
settingsSub: 'Sovranità dei dati: tutto resta in locale in questo browser — nessuna sincronizzazione cloud, nessuna telemetria.',
|
||||
langTitle: 'Sprache / Language / Lingua',
|
||||
langHint: 'Interfaccia in DE/EN/FR/IT/ES. I testi normativi e i documenti generati sono disponibili in tedesco e inglese; le altre lingue usano l’inglese in attesa della traduzione giuridica.',
|
||||
profileTitle: 'Profilo aziendale (intestazione per report & stampa PDF)',
|
||||
profileHint: 'Questi dati compaiono nell’intestazione e nel piè di pagina di tutti i documenti generati e stampati. Il logo resta salvato in locale e non lascia mai il dispositivo.',
|
||||
pfName: 'Ragione sociale', pfStreet: 'Via & numero civico', pfZip: 'CAP & città',
|
||||
pfContact: 'Referente', pfEmail: 'E-mail', pfPhone: 'Telefono', pfWeb: 'Sito web',
|
||||
logoNone: 'Nessun logo salvato.',
|
||||
logoUpload: 'Caricare un logo',
|
||||
logoRemove: 'Rimuovere il logo',
|
||||
logoTaken: 'Logo applicato.',
|
||||
logoTooBig: 'Logo troppo grande — usate un file sotto i 300 KB.',
|
||||
logoNotImage: 'Scegliete un file immagine (PNG, JPG o SVG).',
|
||||
countriesTitle: 'Moduli nazionali (requisiti aggiuntivi)',
|
||||
countriesHint: 'Attivate i paesi UE in cui la vostra azienda offre o utilizza sistemi di IA. Gli obblighi nazionali (autorità, diritto del lavoro, leggi speciali) compariranno in checklist e documenti. Cooperazione transfrontaliera: attivate tutti i paesi coinvolti.',
|
||||
authorityLabel: 'Autorità',
|
||||
packTitle: 'Content pack normativo',
|
||||
packStand: 'Aggiornato al',
|
||||
packHint: 'Il content pack (divieti, ambiti allegato III, obblighi UE, moduli nazionali, scadenze) è modellato come pacchetto dati sostituibile. Gli aggiornamenti arrivano con le nuove versioni dell’app e, in futuro, tramite un feed firmato.',
|
||||
backupTitle: 'Backup',
|
||||
backupExport: 'Esportare il backup (JSON)',
|
||||
backupImport: 'Importare un backup',
|
||||
importOk: 'Import completato: {count} sistema/i{profile}.',
|
||||
importProfileSuffix: ' incl. profilo aziendale',
|
||||
importFail: 'Import non riuscito: {error}',
|
||||
deleteTitle: 'Eliminare tutti i dati',
|
||||
deleteHint: 'Rimuove irrevocabilmente da questo browser tutti i sistemi di IA registrati e il profilo aziendale.',
|
||||
deleteBtn: 'Eliminare tutto',
|
||||
deleteConfirm: 'Eliminare davvero e irrevocabilmente tutti i dati locali?',
|
||||
deleteDone: 'Tutti i dati sono stati eliminati.',
|
||||
|
||||
legalGateTitle: 'Avvertenza legale importante',
|
||||
legalGateBody1:
|
||||
'AI-Act-Kompass è uno strumento di lavoro strutturato inteso a facilitare l’attuazione del regolamento (UE) 2024/1689 (regolamento IA) e delle pertinenti disposizioni nazionali.',
|
||||
legalGateBody2:
|
||||
'Questa applicazione non fornisce servizi legali e non costituisce consulenza legale, informazione legale né istruzione giuridicamente vincolante. Tutte le classificazioni, checklist e i documenti generati sono valutazioni preliminari non vincolanti e bozze, senza garanzia di correttezza, completezza o attualità.',
|
||||
legalGateBody3:
|
||||
'L’interpretazione vincolante del regolamento IA spetta esclusivamente alle autorità e ai giudici competenti. Questo strumento non sostituisce la valutazione legale del vostro caso specifico — rivolgetevi a una consulenza legale qualificata. L’uso avviene a proprio rischio; la responsabilità per decisioni basate su questo strumento è esclusa nella misura consentita dalla legge.',
|
||||
legalGateAccept: 'Capito — usare come strumento di lavoro',
|
||||
legalNoticeTitle: 'Avvertenza legale (non è consulenza legale)',
|
||||
resultDisclaimer:
|
||||
'Questa classificazione è una valutazione preliminare automatizzata e non vincolante basata sulle vostre risposte — non è consulenza legale. Fate verificare il risultato da un legale prima di decisioni importanti.',
|
||||
|
||||
templatesTitle: 'Modelli & moduli',
|
||||
templatesSub: 'Bozze a livello aziendale per l’attuazione interna ed esterna — stampabili con intestazione. I moduli specifici di sistema (consiglio aziendale, informazione ai dipendenti, FRIA, segnalazione incidenti) si trovano nella vista del rispettivo sistema.',
|
||||
templatesHint: 'Tutti i modelli sono bozze con segnaposto — adattare e far verificare legalmente prima dell’uso.',
|
||||
tplPolicy: 'Policy interna sull’IA',
|
||||
tplPolicyDesc: 'Regole d’uso dell’IA in azienda: approvazioni, divieti, supervisione, trasparenza, incidenti.',
|
||||
tplTraining: 'Piano di formazione all’alfabetizzazione IA (art. 4)',
|
||||
tplTrainingDesc: 'Matrice formativa e registro continuo — obbligatorio dal 02/02/2025.',
|
||||
tplWorksAgreement: 'Accordo aziendale sull’IA (quadro)',
|
||||
tplWorksAgreementDesc: 'Bozza secondo il diritto tedesco (§ 87, § 90 BetrVG): vincolo di finalità, nessuna decisione HR automatizzata, diritti del consiglio aziendale.',
|
||||
docWorksCouncil: 'Informazione al consiglio aziendale (§ 90 BetrVG)',
|
||||
docEmployeeInfo: 'Informazione ai dipendenti sull’uso dell’IA',
|
||||
docFria: 'Modello FRIA (art. 27)',
|
||||
docIncident: 'Segnalazione di incidente (art. 73)',
|
||||
tplReporting: 'Policy interna di segnalazione & escalation',
|
||||
tplReportingDesc: 'Obbligo interno di segnalazione degli incidenti IA: canali, termini 24 h/48 h, livelli di escalation, registro — prepara la segnalazione ex art. 73.',
|
||||
tplApproval: 'Richiesta di approvazione sistema IA',
|
||||
tplApprovalDesc: 'Modulo interno per l’approvazione di nuovi strumenti di IA — contro la shadow AI, con blocco decisionale.',
|
||||
tplAudit: 'Checklist di audit interno conformità IA',
|
||||
tplAuditDesc: 'Autoverifica periodica (inventario, formazioni, log, incidenti, documenti dei fornitori) con firma.',
|
||||
};
|
||||
@ -346,7 +346,11 @@ const EN: UIStrings = {
|
||||
tplAuditDesc: 'Periodic self-review (inventory, trainings, logs, incidents, provider documents) with sign-off.',
|
||||
};
|
||||
|
||||
const DICTS: Readonly<Record<Locale, UIStrings>> = { de: DE, en: EN };
|
||||
import { ES } from './ui.es';
|
||||
import { FR } from './ui.fr';
|
||||
import { IT } from './ui.it';
|
||||
|
||||
const DICTS: Readonly<Record<Locale, UIStrings>> = { de: DE, en: EN, fr: FR, it: IT, es: ES };
|
||||
|
||||
/** Liefert das UI-Wörterbuch für die Sprache. */
|
||||
export function uiStrings(locale: Locale): UIStrings {
|
||||
|
||||
@ -16,3 +16,12 @@ createRoot(container).render(
|
||||
</I18nProvider>
|
||||
</StrictMode>,
|
||||
);
|
||||
|
||||
// PWA: Offline-Fähigkeit und Installierbarkeit auf Handy/Mac.
|
||||
if ('serviceWorker' in navigator && import.meta.env.PROD) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('./sw.js').catch(() => {
|
||||
// Ohne Service Worker läuft die App normal weiter — nur nicht offline.
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import type { AISystem, CompanyProfile } from '../engine/types';
|
||||
import { useI18n } from '../i18n/context';
|
||||
import { LOCALES } from '../i18n/types';
|
||||
import { LOCALE_NAMES, LOCALES } from '../i18n/types';
|
||||
import { fmt } from '../i18n/ui';
|
||||
import { clearAll, exportData, importData } from '../store/storage';
|
||||
import { downloadText, todayISO } from './common';
|
||||
@ -96,7 +96,7 @@ export function SettingsView({
|
||||
className={l === locale ? 'primary' : 'ghost'}
|
||||
onClick={() => setLocale(l)}
|
||||
>
|
||||
{l === 'de' ? 'Deutsch' : 'English'}
|
||||
{LOCALE_NAMES[l]}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -18,12 +18,36 @@ export const RISK_UI: Readonly<Record<Locale, Readonly<Record<RiskClass, string>
|
||||
limited: 'Limited risk',
|
||||
minimal: 'Minimal risk',
|
||||
},
|
||||
fr: {
|
||||
'out-of-scope': 'Hors champ',
|
||||
prohibited: 'Interdit',
|
||||
high: 'Haut risque',
|
||||
limited: 'Risque limité',
|
||||
minimal: 'Risque minimal',
|
||||
},
|
||||
it: {
|
||||
'out-of-scope': 'Fuori ambito',
|
||||
prohibited: 'Vietato',
|
||||
high: 'Alto rischio',
|
||||
limited: 'Rischio limitato',
|
||||
minimal: 'Rischio minimo',
|
||||
},
|
||||
es: {
|
||||
'out-of-scope': 'Fuera de ámbito',
|
||||
prohibited: 'Prohibido',
|
||||
high: 'Alto riesgo',
|
||||
limited: 'Riesgo limitado',
|
||||
minimal: 'Riesgo mínimo',
|
||||
},
|
||||
};
|
||||
|
||||
/** Kurze UI-Labels für Rollen je Sprache. */
|
||||
export const ROLE_UI: Readonly<Record<Locale, Readonly<Record<Role, string>>>> = {
|
||||
de: { provider: 'Anbieter', deployer: 'Betreiber', importer: 'Einführer', distributor: 'Händler' },
|
||||
en: { provider: 'Provider', deployer: 'Deployer', importer: 'Importer', distributor: 'Distributor' },
|
||||
fr: { provider: 'Fournisseur', deployer: 'Déployeur', importer: 'Importateur', distributor: 'Distributeur' },
|
||||
it: { provider: 'Fornitore', deployer: 'Deployer', importer: 'Importatore', distributor: 'Distributore' },
|
||||
es: { provider: 'Proveedor', deployer: 'Responsable del despliegue', importer: 'Importador', distributor: 'Distribuidor' },
|
||||
};
|
||||
|
||||
/** Farbiges Stempel-Badge für die Risikoklasse eines Systems. */
|
||||
@ -54,8 +78,9 @@ export function todayISO(): string {
|
||||
return new Date().toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
/** Formatiert ein ISO-Datum für die UI (DE: TT.MM.JJJJ, EN: ISO). */
|
||||
/** Formatiert ein ISO-Datum für die UI (DE: TT.MM.JJJJ, FR/IT/ES: TT/MM/JJJJ, EN: ISO). */
|
||||
export function uiDate(iso: string, locale: Locale): string {
|
||||
if (locale === 'en') return iso;
|
||||
return iso.split('-').reverse().join('.');
|
||||
const sep = locale === 'de' ? '.' : '/';
|
||||
return iso.split('-').reverse().join(sep);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user