diff --git a/felsokning/app/src/felsokning/__tests__/sprak.test.ts b/felsokning/app/src/felsokning/__tests__/sprak.test.ts new file mode 100644 index 0000000..81051be --- /dev/null +++ b/felsokning/app/src/felsokning/__tests__/sprak.test.ts @@ -0,0 +1,199 @@ +// @vitest-environment node +// ALVA-SPEC-060 · Språk. +// +// ---- Vad som faktiskt prövas här ---------------------------------------- +// +// Ett översättningstest som bara räknar nycklar är nästan värdelöst: det +// går att få grönt genom att kopiera engelskan till tio filer. Testet +// nedan prövar därför fyra saker som var och en kan gå sönder tyst i +// drift, och som ingen upptäcker förrän en tekniker läser fel: +// +// 1. Att katalogen är komplett — ingen nyckel faller tyst tillbaka. +// 2. Att strukturen INTE är översatt — faser och statusord är ALVA:s +// ram och ska stå likadant i en rumänsk rapport som i en tysk. +// 3. Att inget språk är engelska i förklädnad — en fil som fortfarande +// innehåller källtexten är inte översatt, den är bara komplett. +// 4. Att variabelhållarna överlevde översättningen. {procent} som blev +// {percent} i den franska filen ger inte ett fel, den ger "{percent} +// % de l'interface" på skärmen, för alltid. +import { describe, expect, it } from "vitest"; +import { + INVARIANTA, + KATALOGER, + SPRAK, + STANDARD, + arInvariant, + metodikvarning, + otillatna, + overflodiga, + saknade, + t, + tackning, + valjSprak, + oversattare, +} from "../../../../services/gemensam/sprak/index.mjs"; +import { EN } from "../../../../services/gemensam/sprak/en.mjs"; + +const OVRIGA = SPRAK.map((s) => s.kod).filter((k) => k !== "en"); +const NYCKLAR = Object.keys(EN); +const OVERSATTBARA = NYCKLAR.filter((n) => !arInvariant(n)); + +describe("katalogen", () => { + it("har en fil för varje språk i SPRAK, och inget språk utan fil", () => { + expect(Object.keys(KATALOGER).sort()).toEqual(SPRAK.map((s) => s.kod).sort()); + }); + + it("har engelska som standard- och källspråk", () => { + expect(STANDARD).toBe("en"); + expect(SPRAK.find((s) => s.kod === "en")?.granskat).toBe(true); + }); + + it.each(OVRIGA)("%s saknar ingen översättbar nyckel", (kod) => { + expect(saknade(KATALOGER[kod])).toEqual([]); + }); + + it.each(OVRIGA)("%s har inga nycklar utan original i engelskan", (kod) => { + expect(overflodiga(KATALOGER[kod])).toEqual([]); + }); + + it("engelskan innehåller något att översätta", () => { + // Motvikt mot de tomma listorna ovan: om EN blir tom passerar de + // alla, och katalogen vore "komplett" på tio språk utan innehåll. + expect(OVERSATTBARA.length).toBeGreaterThan(60); + }); +}); + +describe("strukturen översätts inte", () => { + it("faser och statusord räknas som invarianta", () => { + expect(INVARIANTA).toContain("fas."); + expect(INVARIANTA).toContain("status."); + expect(arInvariant("fas.analys")).toBe(true); + expect(arInvariant("status.passed")).toBe(true); + expect(arInvariant("grind.slutsats")).toBe(false); + }); + + it.each(OVRIGA)("%s definierar ingen invariant nyckel", (kod) => { + expect(otillatna(KATALOGER[kod])).toEqual([]); + }); + + it.each(SPRAK.map((s) => s.kod))("%s visar faserna på engelska", (kod) => { + expect(t(kod, "fas.analys")).toBe("Analysis"); + expect(t(kod, "fas.lokalisering")).toBe("Localization"); + expect(t(kod, "fas.verifiering")).toBe("Verification"); + expect(t(kod, "fas.atgard")).toBe("Action"); + expect(t(kod, "status.passed")).toBe("Passed"); + }); + + it("hämtar invarianta ur engelskan även om en katalog vore förgiftad", () => { + // Regeln ska hålla i drift och inte bara i testet: `t()` frågar + // aldrig katalogen efter en invariant nyckel. + const forgiftad = { ...KATALOGER.de, "status.passed": "Bestanden" }; + const egna = { ...KATALOGER, de: forgiftad }; + expect(egna.de["status.passed"]).toBe("Bestanden"); + expect(t("de", "status.passed")).toBe("Passed"); + }); +}); + +describe("översättningarna är översättningar", () => { + // Hur många strängar som får vara identiska med engelskan innan filen + // rimligen inte är översatt. Vissa SKA vara det: "Document", "No", + // "Responsable", produktnamn. Men inte hälften. + const TAK = 0.25; + + it.each(OVRIGA)("%s är inte engelska i förklädnad", (kod) => { + const lika = OVERSATTBARA.filter((n) => KATALOGER[kod][n] === EN[n]); + const andel = lika.length / OVERSATTBARA.length; + expect(andel, `identiska med engelskan: ${lika.slice(0, 8).join(", ")}`).toBeLessThan(TAK); + }); + + it.each(OVRIGA)("%s behåller variabelhållarna i varje sträng", (kod) => { + const hallare = (s: string) => (String(s).match(/\{(\w+)\}/g) ?? []).sort(); + for (const n of OVERSATTBARA) { + expect(hallare(KATALOGER[kod][n]), `${kod}: ${n}`).toEqual(hallare(EN[n])); + } + }); + + it.each(OVRIGA)("%s har full täckning", (kod) => { + expect(tackning(kod)).toBe(1); + }); + + it("täckningen är noll för ett okänt språk", () => { + expect(tackning("xx")).toBe(0); + }); +}); + +describe("uppslagning", () => { + it("faller tillbaka på engelska för en okänd språkkod", () => { + expect(t("xx", "handling.spara")).toBe(EN["handling.spara"]); + }); + + it("visar nyckeln när den saknas överallt hellre än tomhet", () => { + expect(t("de", "finns.inte")).toBe("finns.inte"); + }); + + it("sätter in variabler", () => { + expect(t("sv", "sprak.tackning", { procent: 100 })).toBe("100 % av gränssnittet"); + }); + + it("lämnar hållaren orörd när variabeln inte skickats", () => { + // Hellre synligt {procent} än "undefined %", som ser ut som ett + // värde och läses som ett. + expect(t("sv", "sprak.tackning")).toContain("{procent}"); + }); + + it("bunden översättare ger samma svar", () => { + const o = oversattare("de"); + expect(o("handling.spara")).toBe(t("de", "handling.spara")); + }); +}); + +describe("språkval", () => { + it("låter användarens val gå före allt annat", () => { + expect(valjSprak({ anvandare: "pl", organisation: "de", webblasare: ["fr"] })).toBe("pl"); + }); + + it("låter organisationen gå före webbläsaren", () => { + // Rapporten ska inte byta språk beroende på vem som skrev raden. + expect(valjSprak({ organisation: "de", webblasare: ["pl", "en"] })).toBe("de"); + }); + + it("tar webbläsarens första kända språk", () => { + expect(valjSprak({ webblasare: ["ja", "ro", "de"] })).toBe("ro"); + }); + + it("klipper regionvarianter", () => { + expect(valjSprak({ anvandare: "de-AT" })).toBe("de"); + expect(valjSprak({ webblasare: ["pt-BR"] })).toBe("pt"); + }); + + it("landar på engelska när ingenting är känt", () => { + expect(valjSprak({})).toBe(STANDARD); + expect(valjSprak()).toBe(STANDARD); + expect(valjSprak({ anvandare: "ja", webblasare: ["ko"] })).toBe(STANDARD); + }); +}); + +describe("metodikvarningen", () => { + it("tiger för granskade språk", () => { + expect(metodikvarning("en")).toBeNull(); + expect(metodikvarning("sv")).toBeNull(); + }); + + it.each(SPRAK.filter((s) => !s.granskat).map((s) => s.kod))("varnar på %s", (kod) => { + const text = metodikvarning(kod)!; + expect(text).toBeTruthy(); + // Varningen ska stå på användarens eget språk — en varning på + // engelska om att texten är på engelska hjälper ingen. + expect(text).toBe(KATALOGER[kod]["metodik.ogranskad"].replace("{sprak}", egetNamn(kod))); + // Och den ska namnge språket, inte vara en allmän brasklapp. + expect(text).toContain(egetNamn(kod)); + }); + + it("tiger för ett okänt språk i stället för att varna om ingenting", () => { + expect(metodikvarning("xx")).toBeNull(); + }); +}); + +function egetNamn(kod: string): string { + return SPRAK.find((s) => s.kod === kod)!.egetNamn; +} diff --git a/felsokning/services/gemensam/sprak/de.mjs b/felsokning/services/gemensam/sprak/de.mjs new file mode 100644 index 0000000..0d1e065 --- /dev/null +++ b/felsokning/services/gemensam/sprak/de.mjs @@ -0,0 +1,121 @@ +// ALVA-SPEC-060 · Deutsch. +// +// Anweisungen stehen im Infinitiv, nicht in der Anrede: "Kilometerzähler +// fotografieren", nicht "Fotografieren Sie den Kilometerzähler". Das ist +// der Registerton technischer Anweisungen im deutschen Sprachraum und +// entspricht ALVA-SPEC-001 §7 — das System meldet einen Zustand, es +// wendet sich nicht an den Benutzer. +// +// `granskat: false`: die Oberfläche ist übersetzt, der Verfahrenstext +// ist nicht von einer Fachkraft geprüft. Siehe index.mjs. + +export const DE = { + // ---- Evidenzgrade ------------------------------------------------------- + "evidens.E1": "Beobachtung", + "evidens.E2": "Fotografie", + "evidens.E3": "Video mit Ton", + "evidens.E4": "Messung, kalibriertes Messmittel", + "evidens.E5": "Dokument", + "evidens.ej_kalibrerad": "Kalibrierung fehlt oder ist abgelaufen", + "evidens.ej_angivet": "Messmittel nicht angegeben", + "evidens.ej_fotograferad": "eingetragen, nicht fotografiert", + + // ---- Qualitätsschranke -------------------------------------------------- + "grind.objekt": "Identität des Fahrzeugs oder Objekts verifiziert", + "grind.historik": "Fahrzeughistorie geprüft oder begründet", + "grind.historik.nekad": "Eine abgelehnte Historienprüfung erfordert eine angegebene Begründung.", + "grind.historik.saknas": "Keine Historienprüfung dokumentiert.", + "grind.matarstallning.ingaende": "Kilometerstand bei Annahme fotografiert", + "grind.matarstallning.utgaende": "Kilometerstand bei Ausgabe fotografiert", + "grind.matarstallning.saknas": "Kein Kilometerstand dokumentiert.", + "grind.matarstallning.ej_foto": + "Der Kilometerstand ist eingetragen, aber nicht fotografiert. Kilometerzähler fotografieren, oder angeben, warum dies nicht möglich ist.", + "grind.reproducering": "Symptomverifizierung: reproduziert oder als nicht reproduzierbar dokumentiert", + "grind.felorsak": "Fehlerursachenanalyse dokumentiert", + "grind.atgard": "Maßnahme dokumentiert oder begründet", + "grind.atgard.saknas": "Weder eine durchgeführte Maßnahme noch ein Grund für deren Ausbleiben ist dokumentiert.", + "grind.kundbeslut": "Kundenentscheidung zum Vorschlag erfasst", + "grind.kundbeslut.avbojt": "Arbeit trotz abgelehntem Vorschlag durchgeführt", + "grind.kundbeslut.avbojt.detalj": + "Der Kunde hat den Vorschlag abgelehnt, es ist jedoch durchgeführte Arbeit dokumentiert.", + "grind.kvalitetskontroll": "Qualitätskontrolle durchgeführt — Symptom verifiziert", + "grind.kontroller": "Prüfpunkte der Methodik: Evidenz oder dokumentierte Ausnahme", + "grind.foton": "Fotos für die Prüfpunkte vorhanden, die sie erfordern", + "grind.slutsats": "Abschlussfeststellung (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Hochvolt-Qualifikation bestätigt", + "grind.hogvolt.spanningslos": "Fahrzeug nach Herstellerverfahren spannungsfrei geschaltet", + "grind.regelpaket": "Signatur des Regelpakets stimmt nicht — Abschluss gesperrt.", + "grind.regelpaket.osignerat": "Ein externes Regelpaket wird ohne Signatur verwendet — Abschluss gesperrt.", + + // ---- Abschlussfeststellung (ALVA-RULE-200) ------------------------------ + "slutsats.rubrik": "Abschlussfeststellung", + "slutsats.konstaterat": "Was festgestellt wurde", + "slutsats.evidens": "Welche Evidenz dies trägt", + "slutsats.avfardat": "Welche Hypothesen verworfen wurden, und warum", + "slutsats.osakert": "Was unsicher bleibt", + "slutsats.ickesvar": + "Das ist keine Feststellung. Angeben, was festgestellt wurde und welche Evidenz dies trägt.", + + // ---- Vorgangsablauf ----------------------------------------------------- + "arende.nytt": "Neuer Vorgang", + "arende.oppna": "Offene Vorgänge", + "arende.avslutade": "Abgeschlossene Vorgänge", + "arende.avsluta": "Vorgang abschließen", + "arende.avslutat": "Vorgang abgeschlossen", + "arende.kan_ej_avslutas": "Der Vorgang kann noch nicht abgeschlossen werden", + "arende.hinder": "Vor dem Abschluss offen", + "arende.overlamna": "Übergeben", + "arende.ansvarig": "Verantwortlich", + + // ---- Vorprüfung --------------------------------------------------------- + "pre.rubrik": "Vorprüfung — vor Arbeitsbeginn", + "pre.historik.fraga": + "Ist die Fahrzeughistorie geprüft? (frühere Arbeiten, wiederkehrende Fehler, TSB, Rückrufaktionen)", + "pre.historik.ja": "Ja — geprüft", + "pre.historik.nej": "Nein", + "pre.historik.skal": "Grund, warum die Historie nicht geprüft wurde (erforderlich)", + "pre.historik.relevant": "Relevante frühere Arbeiten (optional — Ursachenkette)", + "pre.matarstallning": "Kilometerstand", + "pre.fotografera": "Kombiinstrument fotografieren", + "pre.felbeskrivning": "Fehlerbeschreibung des Kunden verifiziert", + "pre.observationer": "Sonstiges bei der Annahme?", + + // ---- Handlungen --------------------------------------------------------- + "handling.spara": "Speichern", + "handling.avbryt": "Abbrechen", + "handling.fortsatt": "Weiter", + "handling.tillbaka": "Zurück", + "handling.dokumentera": "Dokumentieren", + "handling.fotografera": "Fotografieren", + "handling.spela_in": "Video aufnehmen", + "handling.undantag": "Ausnahme dokumentieren", + "handling.undantag.skal": "Begründung der Ausnahme (erforderlich)", + "handling.exportera": "Exportieren", + "handling.skriv_ut": "Drucken", + + // ---- Messung ------------------------------------------------------------ + "matning.varde": "Wert", + "matning.enhet": "Einheit", + "matning.matdon": "Messmittel", + "matning.matdon.valj": "Messmittel wählen", + "matning.matdon.okant": "Unbekanntes Messmittel. Vor dem Speichern der Messung registrieren.", + "matning.kalibrerad_till": "Kalibriert bis", + + // ---- Bericht ------------------------------------------------------------ + "rapport.rubrik": "Vorgangsbericht", + "rapport.sammanfattning": "Zusammenfassung", + "rapport.evidens": "Evidenz", + "rapport.atgarder": "Maßnahmen", + "rapport.harledd": + "Aus dem Vorgangsprotokoll abgeleitet. Beobachtungen und Messungen werden ohne Schlussfolgerungen wiedergegeben, denen die Grundlage fehlt.", + + // ---- Sprache ------------------------------------------------------------ + "sprak.valj": "Sprache", + "sprak.granskat": "Geprüft", + "sprak.ogranskat": "Nicht geprüft", + "sprak.tackning": "{procent} % der Oberfläche", + + "metodik.ogranskad": + "Der Verfahrenstext wurde nicht von einer Fachkraft auf {sprak} geprüft. Schritte und Prüfpunkte werden auf Englisch angezeigt, wo keine geprüfte Übersetzung vorliegt — eine ungeprüfte Übersetzung einer Sicherheitsanweisung ist schlechter als eine fremdsprachige, weil sie nicht fremd aussieht.", + "metodik.pa_engelska": "Auf Englisch angezeigt — keine geprüfte Übersetzung auf {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/en.mjs b/felsokning/services/gemensam/sprak/en.mjs new file mode 100644 index 0000000..e0634b5 --- /dev/null +++ b/felsokning/services/gemensam/sprak/en.mjs @@ -0,0 +1,148 @@ +// ALVA-SPEC-060 · English — the source language. +// +// Every key that exists lives here first. A key added to another +// catalogue but not to this one is not a translation; it is a string +// with no original, and the test refuses it. +// +// ---- Naming -------------------------------------------------------------- +// +// `område.sak` — the prefix says where the string is used, so a +// translator can read the file in the order the user meets it rather +// than alphabetically. +// +// ---- Tone --------------------------------------------------------------- +// +// The status language of ALVA-SPEC-001 §7 applies to every string here: +// the system reports state, it does not address the user. "Verification +// passed", not "Well done!". A translator who makes it friendlier has +// made it wrong. + +export const EN = { + // ---- Phases (ALVA) ---------------------------------------------------- + "fas.analys": "Analysis", + "fas.lokalisering": "Localization", + "fas.verifiering": "Verification", + "fas.atgard": "Action", + + // ---- Status ------------------------------------------------------------ + "status.pending": "Pending", + "status.in_progress": "In progress", + "status.complete": "Complete", + "status.passed": "Passed", + "status.failed": "Failed", + "status.blocked": "Blocked", + "status.incomplete": "Incomplete", + "status.not_applicable": "Not applicable", + + // ---- Evidence grades ---------------------------------------------------- + "evidens.E1": "Observation", + "evidens.E2": "Photograph", + "evidens.E3": "Video with sound", + "evidens.E4": "Measurement, calibrated instrument", + "evidens.E5": "Document", + "evidens.ej_kalibrerad": "calibration missing or expired", + "evidens.ej_angivet": "instrument not stated", + "evidens.ej_fotograferad": "entered, not photographed", + + // ---- The quality gate --------------------------------------------------- + // + // These are the highest-stakes strings in the product. Each one is the + // reason a technician cannot close a case, so it has to say what is + // missing — not that something is missing. + "grind.objekt": "Vehicle or object identification verified", + "grind.historik": "Vehicle history checked or justified", + "grind.historik.nekad": "A declined history check requires a stated reason.", + "grind.historik.saknas": "No history check documented.", + "grind.matarstallning.ingaende": "Incoming odometer reading photographed", + "grind.matarstallning.utgaende": "Outgoing odometer reading photographed", + "grind.matarstallning.saknas": "No odometer reading documented.", + "grind.matarstallning.ej_foto": + "The reading is entered but not photographed. Photograph the odometer, or state why that is not possible.", + "grind.reproducering": "Symptom verification: reproduced, or documented as not reproducible", + "grind.felorsak": "Root cause analysis documented", + "grind.atgard": "Corrective action documented or justified", + "grind.atgard.saknas": "Neither a performed action nor a reason for its absence is documented.", + "grind.kundbeslut": "Customer decision on the proposal recorded", + "grind.kundbeslut.avbojt": "Work performed despite a declined proposal", + "grind.kundbeslut.avbojt.detalj": "The customer declined the proposal, but work has been documented as performed.", + "grind.kvalitetskontroll": "Quality check performed — symptom verified", + "grind.kontroller": "Methodology checks: evidence, or a documented exemption", + "grind.foton": "Photographs present for checks that require them", + "grind.slutsats": "Closing statement (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "High-voltage authorisation confirmed", + "grind.hogvolt.spanningslos": "Vehicle de-energised per the manufacturer's procedure", + "grind.regelpaket": "Rule package signature does not match — closing blocked.", + "grind.regelpaket.osignerat": "An external rule package is in use without a signature — closing blocked.", + + // ---- The closing statement (ALVA-RULE-200) ------------------------------ + "slutsats.rubrik": "Closing statement", + "slutsats.konstaterat": "What was established", + "slutsats.evidens": "Which evidence carries it", + "slutsats.avfardat": "Which hypotheses were dismissed, and why", + "slutsats.osakert": "What remains uncertain", + "slutsats.ickesvar": "That is not an answer. State what was established and which evidence carries it.", + + // ---- Case flow ----------------------------------------------------------- + "arende.nytt": "New case", + "arende.oppna": "Open cases", + "arende.avslutade": "Closed cases", + "arende.avsluta": "Close case", + "arende.avslutat": "Case closed", + "arende.kan_ej_avslutas": "The case cannot be closed yet", + "arende.hinder": "Outstanding before closing", + "arende.overlamna": "Hand over", + "arende.ansvarig": "Responsible", + + // ---- Pre-diagnostics ------------------------------------------------------ + "pre.rubrik": "Pre-diagnostics — before the work begins", + "pre.historik.fraga": "Has the vehicle's history been checked? (previous work, recurring faults, TSBs, campaigns)", + "pre.historik.ja": "Yes — checked", + "pre.historik.nej": "No", + "pre.historik.skal": "Reason the history was not checked (required)", + "pre.historik.relevant": "Relevant previous work (optional — causal chain)", + "pre.matarstallning": "Odometer reading", + "pre.fotografera": "Photograph the instrument panel", + "pre.felbeskrivning": "Customer's description verified", + "pre.observationer": "Anything else on receipt?", + + // ---- Common actions -------------------------------------------------------- + "handling.spara": "Save", + "handling.avbryt": "Cancel", + "handling.fortsatt": "Continue", + "handling.tillbaka": "Back", + "handling.dokumentera": "Document", + "handling.fotografera": "Photograph", + "handling.spela_in": "Record video", + "handling.undantag": "Document an exemption", + "handling.undantag.skal": "Reason for the exemption (required)", + "handling.exportera": "Export", + "handling.skriv_ut": "Print", + + // ---- Measurement ------------------------------------------------------------- + "matning.varde": "Value", + "matning.enhet": "Unit", + "matning.matdon": "Instrument", + "matning.matdon.valj": "Select instrument", + "matning.matdon.okant": "Unknown instrument. Register it before saving the measurement.", + "matning.kalibrerad_till": "Calibrated until", + + // ---- Report -------------------------------------------------------------------- + "rapport.rubrik": "Case report", + "rapport.sammanfattning": "Summary", + "rapport.evidens": "Evidence", + "rapport.atgarder": "Actions", + "rapport.harledd": "Generated from the case log. Observations and measurements are reported without conclusions that lack support.", + + // ---- Language ---------------------------------------------------------------------- + "sprak.valj": "Language", + "sprak.granskat": "Reviewed", + "sprak.ogranskat": "Not reviewed", + "sprak.tackning": "{procent} % of the interface", + + // Shown when the methodology content has not been reviewed by a + // specialist in the user's language. Deliberately specific: a general + // disclaimer is read by nobody. + "metodik.ogranskad": + "Procedure text has not been reviewed by a technical specialist in {sprak}. Steps and checks are shown in English where no reviewed translation exists — an unreviewed translation of a safety instruction is worse than a foreign-language one, because it does not look foreign.", + "metodik.pa_engelska": "Shown in English — no reviewed translation in {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/es.mjs b/felsokning/services/gemensam/sprak/es.mjs new file mode 100644 index 0000000..c7e0ba8 --- /dev/null +++ b/felsokning/services/gemensam/sprak/es.mjs @@ -0,0 +1,119 @@ +// ALVA-SPEC-060 · Español. +// +// Las instrucciones van en infinitivo, sin dirigirse al usuario: +// «Fotografiar el cuentakilómetros», no «Fotografíe el cuentakilómetros». +// Es el registro de las instrucciones técnicas y respeta ALVA-SPEC-001 §7 +// — el sistema informa de un estado, no se dirige al operario. +// +// `granskat: false`: la interfaz está traducida; el texto de +// procedimiento no está revisado por un especialista. Véase index.mjs. + +export const ES = { + // ---- Grados de evidencia ------------------------------------------------ + "evidens.E1": "Observación", + "evidens.E2": "Fotografía", + "evidens.E3": "Vídeo con sonido", + "evidens.E4": "Medición, instrumento calibrado", + "evidens.E5": "Documento", + "evidens.ej_kalibrerad": "calibración ausente o caducada", + "evidens.ej_angivet": "instrumento no indicado", + "evidens.ej_fotograferad": "introducido, no fotografiado", + + // ---- El control de cierre ----------------------------------------------- + "grind.objekt": "Identificación del vehículo u objeto verificada", + "grind.historik": "Historial del vehículo comprobado o justificado", + "grind.historik.nekad": "Una comprobación de historial rechazada exige un motivo indicado.", + "grind.historik.saknas": "No hay ninguna comprobación de historial documentada.", + "grind.matarstallning.ingaende": "Kilometraje de entrada fotografiado", + "grind.matarstallning.utgaende": "Kilometraje de salida fotografiado", + "grind.matarstallning.saknas": "No hay ningún kilometraje documentado.", + "grind.matarstallning.ej_foto": + "El kilometraje está introducido pero no fotografiado. Fotografiar el cuentakilómetros, o indicar por qué no es posible.", + "grind.reproducering": "Verificación del síntoma: reproducido, o documentado como no reproducible", + "grind.felorsak": "Análisis de la causa raíz documentado", + "grind.atgard": "Acción correctiva documentada o justificada", + "grind.atgard.saknas": "No está documentada ni una acción realizada ni un motivo de su ausencia.", + "grind.kundbeslut": "Decisión del cliente sobre la propuesta registrada", + "grind.kundbeslut.avbojt": "Trabajo realizado pese a una propuesta rechazada", + "grind.kundbeslut.avbojt.detalj": + "El cliente rechazó la propuesta, pero hay trabajo documentado como realizado.", + "grind.kvalitetskontroll": "Control de calidad realizado — síntoma verificado", + "grind.kontroller": "Puntos de control de la metodología: evidencia, o exención documentada", + "grind.foton": "Hay fotografías para los controles que las exigen", + "grind.slutsats": "Conclusión (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Habilitación de alta tensión confirmada", + "grind.hogvolt.spanningslos": "Vehículo sin tensión según el procedimiento del fabricante", + "grind.regelpaket": "La firma del paquete de reglas no coincide — cierre bloqueado.", + "grind.regelpaket.osignerat": "Se utiliza un paquete de reglas externo sin firma — cierre bloqueado.", + + // ---- La conclusión (ALVA-RULE-200) -------------------------------------- + "slutsats.rubrik": "Conclusión", + "slutsats.konstaterat": "Qué se ha establecido", + "slutsats.evidens": "Qué evidencia lo sustenta", + "slutsats.avfardat": "Qué hipótesis se han descartado, y por qué", + "slutsats.osakert": "Qué sigue siendo incierto", + "slutsats.ickesvar": "Eso no es una conclusión. Indicar qué se ha establecido y qué evidencia lo sustenta.", + + // ---- Flujo del expediente ----------------------------------------------- + "arende.nytt": "Nuevo expediente", + "arende.oppna": "Expedientes abiertos", + "arende.avslutade": "Expedientes cerrados", + "arende.avsluta": "Cerrar el expediente", + "arende.avslutat": "Expediente cerrado", + "arende.kan_ej_avslutas": "El expediente todavía no se puede cerrar", + "arende.hinder": "Pendiente antes del cierre", + "arende.overlamna": "Transferir", + "arende.ansvarig": "Responsable", + + // ---- Comprobación previa ------------------------------------------------ + "pre.rubrik": "Comprobación previa — antes de iniciar el trabajo", + "pre.historik.fraga": + "¿Se ha comprobado el historial del vehículo? (trabajos anteriores, fallos recurrentes, TSB, campañas)", + "pre.historik.ja": "Sí — comprobado", + "pre.historik.nej": "No", + "pre.historik.skal": "Motivo por el que no se ha comprobado el historial (obligatorio)", + "pre.historik.relevant": "Trabajos anteriores relevantes (opcional — cadena causal)", + "pre.matarstallning": "Kilometraje", + "pre.fotografera": "Fotografiar el cuadro de instrumentos", + "pre.felbeskrivning": "Descripción del fallo del cliente verificada", + "pre.observationer": "¿Algo más en la recepción?", + + // ---- Acciones ----------------------------------------------------------- + "handling.spara": "Guardar", + "handling.avbryt": "Cancelar", + "handling.fortsatt": "Continuar", + "handling.tillbaka": "Atrás", + "handling.dokumentera": "Documentar", + "handling.fotografera": "Fotografiar", + "handling.spela_in": "Grabar vídeo", + "handling.undantag": "Documentar una exención", + "handling.undantag.skal": "Motivo de la exención (obligatorio)", + "handling.exportera": "Exportar", + "handling.skriv_ut": "Imprimir", + + // ---- Medición ----------------------------------------------------------- + "matning.varde": "Valor", + "matning.enhet": "Unidad", + "matning.matdon": "Instrumento", + "matning.matdon.valj": "Seleccionar instrumento", + "matning.matdon.okant": "Instrumento desconocido. Registrarlo antes de guardar la medición.", + "matning.kalibrerad_till": "Calibrado hasta", + + // ---- Informe ------------------------------------------------------------ + "rapport.rubrik": "Informe del expediente", + "rapport.sammanfattning": "Resumen", + "rapport.evidens": "Evidencia", + "rapport.atgarder": "Acciones", + "rapport.harledd": + "Derivado del registro del expediente. Las observaciones y las mediciones se presentan sin conclusiones que carezcan de sustento.", + + // ---- Idioma ------------------------------------------------------------- + "sprak.valj": "Idioma", + "sprak.granskat": "Revisado", + "sprak.ogranskat": "Sin revisar", + "sprak.tackning": "{procent} % de la interfaz", + + "metodik.ogranskad": + "El texto de procedimiento no ha sido revisado por un especialista técnico en {sprak}. Los pasos y los puntos de control se muestran en inglés cuando no existe una traducción revisada — una traducción sin revisar de una instrucción de seguridad es peor que una en lengua extranjera, porque no parece extranjera.", + "metodik.pa_engelska": "Mostrado en inglés — no hay traducción revisada en {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/fr.mjs b/felsokning/services/gemensam/sprak/fr.mjs new file mode 100644 index 0000000..8e7e81b --- /dev/null +++ b/felsokning/services/gemensam/sprak/fr.mjs @@ -0,0 +1,120 @@ +// ALVA-SPEC-060 · Français. +// +// Les instructions sont à l'infinitif, sans s'adresser à l'utilisateur : +// « Photographier le compteur », et non « Photographiez le compteur ». +// C'est le registre des consignes techniques, et cela respecte +// ALVA-SPEC-001 §7 — le système signale un état, il ne s'adresse pas à +// l'opérateur. +// +// `granskat: false` : l'interface est traduite, le texte de procédure +// n'est pas relu par un spécialiste. Voir index.mjs. + +export const FR = { + // ---- Degrés de preuve --------------------------------------------------- + "evidens.E1": "Observation", + "evidens.E2": "Photographie", + "evidens.E3": "Vidéo avec son", + "evidens.E4": "Mesure, instrument étalonné", + "evidens.E5": "Document", + "evidens.ej_kalibrerad": "étalonnage manquant ou expiré", + "evidens.ej_angivet": "instrument non indiqué", + "evidens.ej_fotograferad": "saisi, non photographié", + + // ---- Le contrôle de clôture --------------------------------------------- + "grind.objekt": "Identification du véhicule ou de l'objet vérifiée", + "grind.historik": "Historique du véhicule vérifié ou justifié", + "grind.historik.nekad": "Un contrôle d'historique refusé exige un motif indiqué.", + "grind.historik.saknas": "Aucun contrôle d'historique documenté.", + "grind.matarstallning.ingaende": "Kilométrage à la réception photographié", + "grind.matarstallning.utgaende": "Kilométrage à la restitution photographié", + "grind.matarstallning.saknas": "Aucun kilométrage documenté.", + "grind.matarstallning.ej_foto": + "Le kilométrage est saisi mais non photographié. Photographier le compteur, ou indiquer pourquoi cela n'est pas possible.", + "grind.reproducering": "Vérification du symptôme : reproduit, ou documenté comme non reproductible", + "grind.felorsak": "Analyse de la cause racine documentée", + "grind.atgard": "Action corrective documentée ou justifiée", + "grind.atgard.saknas": "Ni action réalisée ni motif de son absence n'est documenté.", + "grind.kundbeslut": "Décision du client sur la proposition enregistrée", + "grind.kundbeslut.avbojt": "Travaux réalisés malgré une proposition refusée", + "grind.kundbeslut.avbojt.detalj": + "Le client a refusé la proposition, mais des travaux sont documentés comme réalisés.", + "grind.kvalitetskontroll": "Contrôle qualité effectué — symptôme vérifié", + "grind.kontroller": "Points de contrôle de la méthode : preuve, ou dérogation documentée", + "grind.foton": "Photographies présentes pour les contrôles qui l'exigent", + "grind.slutsats": "Conclusion (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Habilitation haute tension confirmée", + "grind.hogvolt.spanningslos": "Véhicule consigné hors tension selon la procédure du constructeur", + "grind.regelpaket": "La signature du paquet de règles ne correspond pas — clôture bloquée.", + "grind.regelpaket.osignerat": "Un paquet de règles externe est utilisé sans signature — clôture bloquée.", + + // ---- La conclusion (ALVA-RULE-200) -------------------------------------- + "slutsats.rubrik": "Conclusion", + "slutsats.konstaterat": "Ce qui est établi", + "slutsats.evidens": "Quelles preuves l'étayent", + "slutsats.avfardat": "Quelles hypothèses ont été écartées, et pourquoi", + "slutsats.osakert": "Ce qui reste incertain", + "slutsats.ickesvar": "Ce n'est pas une conclusion. Indiquer ce qui est établi et quelles preuves l'étayent.", + + // ---- Flux du dossier ---------------------------------------------------- + "arende.nytt": "Nouveau dossier", + "arende.oppna": "Dossiers ouverts", + "arende.avslutade": "Dossiers clôturés", + "arende.avsluta": "Clôturer le dossier", + "arende.avslutat": "Dossier clôturé", + "arende.kan_ej_avslutas": "Le dossier ne peut pas encore être clôturé", + "arende.hinder": "Reste avant clôture", + "arende.overlamna": "Transmettre", + "arende.ansvarig": "Responsable", + + // ---- Contrôle préalable ------------------------------------------------- + "pre.rubrik": "Contrôle préalable — avant le début des travaux", + "pre.historik.fraga": + "L'historique du véhicule a-t-il été vérifié ? (travaux antérieurs, défauts récurrents, TSB, campagnes)", + "pre.historik.ja": "Oui — vérifié", + "pre.historik.nej": "Non", + "pre.historik.skal": "Motif pour lequel l'historique n'a pas été vérifié (obligatoire)", + "pre.historik.relevant": "Travaux antérieurs pertinents (facultatif — chaîne causale)", + "pre.matarstallning": "Kilométrage", + "pre.fotografera": "Photographier le tableau de bord", + "pre.felbeskrivning": "Description du défaut par le client vérifiée", + "pre.observationer": "Autre chose à la réception ?", + + // ---- Actions ------------------------------------------------------------ + "handling.spara": "Enregistrer", + "handling.avbryt": "Annuler", + "handling.fortsatt": "Continuer", + "handling.tillbaka": "Retour", + "handling.dokumentera": "Documenter", + "handling.fotografera": "Photographier", + "handling.spela_in": "Enregistrer une vidéo", + "handling.undantag": "Documenter une dérogation", + "handling.undantag.skal": "Motif de la dérogation (obligatoire)", + "handling.exportera": "Exporter", + "handling.skriv_ut": "Imprimer", + + // ---- Mesure ------------------------------------------------------------- + "matning.varde": "Valeur", + "matning.enhet": "Unité", + "matning.matdon": "Instrument", + "matning.matdon.valj": "Sélectionner un instrument", + "matning.matdon.okant": "Instrument inconnu. L'enregistrer avant de sauvegarder la mesure.", + "matning.kalibrerad_till": "Étalonné jusqu'au", + + // ---- Rapport ------------------------------------------------------------ + "rapport.rubrik": "Rapport de dossier", + "rapport.sammanfattning": "Synthèse", + "rapport.evidens": "Preuves", + "rapport.atgarder": "Actions", + "rapport.harledd": + "Dérivé du journal du dossier. Les observations et les mesures sont rapportées sans conclusions dépourvues de fondement.", + + // ---- Langue ------------------------------------------------------------- + "sprak.valj": "Langue", + "sprak.granskat": "Relu", + "sprak.ogranskat": "Non relu", + "sprak.tackning": "{procent} % de l'interface", + + "metodik.ogranskad": + "Le texte de procédure n'a pas été relu par un spécialiste technique en {sprak}. Les étapes et les points de contrôle sont affichés en anglais lorsqu'aucune traduction relue n'existe — une traduction non relue d'une consigne de sécurité est pire qu'une consigne en langue étrangère, parce qu'elle n'a pas l'air étrangère.", + "metodik.pa_engelska": "Affiché en anglais — aucune traduction relue en {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/index.mjs b/felsokning/services/gemensam/sprak/index.mjs new file mode 100644 index 0000000..bdcc18d --- /dev/null +++ b/felsokning/services/gemensam/sprak/index.mjs @@ -0,0 +1,189 @@ +// ALVA-SPEC-060 · Språk. +// +// ---- Två sorters text, och de behandlas olika --------------------------- +// +// GRÄNSSNITTSTEXT är etiketter, knappar, statusar och grindens hinder. +// Den är ändlig, den ändras sällan, och en engelsk sträng som slinker +// igenom till en tysk användare är irriterande men ofarlig. +// +// METODIKINNEHÅLL är instruktioner för arbete på ett fordon: "kontrollera +// bromsvätskans kokpunkt", "säkerställ att fordonet är spänningslöst". +// Där är en oöversatt eller halvöversatt sträng inte irriterande utan +// farlig, och en maskinöversättning som ingen fackman läst är värre än +// engelska — därför att engelska SYNS som ett annat språk, medan en +// felaktig översättning ser ut som en instruktion. +// +// Modulen behandlar dem därför olika. Gränssnittstext faller tillbaka på +// engelska tyst. Metodikinnehåll gör det ALDRIG tyst: det märks som +// oöversatt, med språk och granskningsstatus, så att teknikern vet att +// den läser något som inte är skrivet för dess marknad. +// +// ---- Källspråket är engelska -------------------------------------------- +// +// Inte därför att engelska är bäst, utan därför att ALVA:s struktur redan +// är engelsk och oföränderlig (ALVA-SPEC-001 §2). Ett system där +// strukturen är engelsk och källtexten svensk har två källor att hålla +// synkade, och den ena vinner alltid tyst. +// +// ---- Katalogen är stängd ------------------------------------------------- +// +// Varje nyckel måste finnas i varje språk. Ett test låser det, av samma +// skäl som händelseschemat är stängt: en saknad nyckel som tyst faller +// tillbaka blir aldrig upptäckt, och blir aldrig översatt. +// +// ---- Och en del av den får INTE översättas ------------------------------ +// +// ALVA-SPEC-001 §2 slår fast att fasnamn och statusord är strukturen och +// skrivs likadant i varje land — precis som ett ISO-krav inte blir +// "internationell standard 9001" på svenska. En tysk rapport och en +// rumänsk ska visa samma fyra faser och samma statusord, så att en +// revisor kan läsa båda utan att veta vilket språk verkstaden arbetar på. +// +// Det hade gått att skriva in dem oöversatta i varje katalog och låsa +// dem med ett test. Det är svagare: en översättare som ser "Passed" i +// den polska filen översätter den, och testet blir en tvist i stället +// för en regel. I stället saknas nycklarna helt i översättningarna, och +// `t()` hämtar dem alltid ur engelskan. Då finns det ingenting att +// översätta fel. + +import { EN } from "./en.mjs"; +import { SV } from "./sv.mjs"; +import { DE } from "./de.mjs"; +import { FR } from "./fr.mjs"; +import { ES } from "./es.mjs"; +import { IT } from "./it.mjs"; +import { PL } from "./pl.mjs"; +import { NL } from "./nl.mjs"; +import { PT } from "./pt.mjs"; +import { RO } from "./ro.mjs"; + +/** + * Språken. + * + * Urvalet är EU:s största modersmål plus svenska, som är hemmamarknaden. + * `granskat` säger om en fackman har läst igenom METODIKINNEHÅLLET på + * språket — inte gränssnittet. Se filhuvudet: det är den skillnaden som + * betyder något. + */ +export const SPRAK = [ + { kod: "en", namn: "English", egetNamn: "English", granskat: true }, + { kod: "de", namn: "German", egetNamn: "Deutsch", granskat: false }, + { kod: "fr", namn: "French", egetNamn: "Français", granskat: false }, + { kod: "es", namn: "Spanish", egetNamn: "Español", granskat: false }, + { kod: "it", namn: "Italian", egetNamn: "Italiano", granskat: false }, + { kod: "pl", namn: "Polish", egetNamn: "Polski", granskat: false }, + { kod: "nl", namn: "Dutch", egetNamn: "Nederlands", granskat: false }, + { kod: "pt", namn: "Portuguese", egetNamn: "Português", granskat: false }, + { kod: "ro", namn: "Romanian", egetNamn: "Română", granskat: false }, + { kod: "sv", namn: "Swedish", egetNamn: "Svenska", granskat: true }, +]; + +/** Standardspråket. Även källspråket. */ +export const STANDARD = "en"; + +export const KATALOGER = { en: EN, sv: SV, de: DE, fr: FR, es: ES, it: IT, pl: PL, nl: NL, pt: PT, ro: RO }; + +/** + * Nyckelområden som är ALVA:s struktur och därför aldrig översätts. + * + * `fas.` — de fyra faserna. `status.` — statusorden. Se filhuvudet. + */ +export const INVARIANTA = ["fas.", "status."]; + +/** Om nyckeln tillhör strukturen och alltid ska hämtas ur engelskan. */ +export const arInvariant = (nyckel) => INVARIANTA.some((p) => String(nyckel).startsWith(p)); + +/** + * Slår upp en gränssnittssträng. + * + * Invarianta nycklar hämtas alltid ur engelskan, oavsett språk och + * oavsett vad en katalog råkar innehålla. + * + * Faller i övrigt tillbaka på engelska när nyckeln saknas i språket, och + * på nyckeln själv när den saknas överallt — det sista ska aldrig hända + * och fångas av testet, men en tom sträng i gränssnittet vore värre än + * en synlig nyckel. + * + * `variabler` ersätter {namn} i strängen. Ingen ordning antas: språk + * sätter satsdelar i olika ordning, och en översättning som tvingas följa + * engelskans ordföljd blir fel svenska, tyska och polska på en gång. + */ +export function t(sprak, nyckel, variabler = {}) { + const katalog = arInvariant(nyckel) ? EN : (KATALOGER[sprak] ?? EN); + const rå = katalog[nyckel] ?? EN[nyckel] ?? nyckel; + return String(rå).replace(/\{(\w+)\}/g, (_, n) => (n in variabler ? String(variabler[n]) : `{${n}}`)); +} + +/** Bunden variant, så en vy slipper skicka språket i varje anrop. */ +export const oversattare = (sprak) => (nyckel, variabler) => t(sprak, nyckel, variabler); + +/** + * Vilka nycklar som saknas per språk. + * + * Används av testet — men är exporterad även för driften, som kan visa + * täckningsgraden i stället för att påstå att ett språk är klart. + */ +export function saknade(katalog) { + const nycklar = Object.keys(EN).filter((n) => !arInvariant(n)); + return nycklar.filter((n) => !(n in katalog) || !String(katalog[n]).trim()); +} + +/** + * Invarianta nycklar som en katalog felaktigt definierar. + * + * Tom lista är det normala. En träff betyder att någon har översatt + * strukturen, och det ska stoppa bygget — inte tyst ignoreras av `t()`, + * även om `t()` ignorerar det. + */ +export function otillatna(katalog) { + return Object.keys(katalog).filter(arInvariant); +} + +/** + * Nycklar som finns i katalogen men inte i engelskan. + * + * En sträng utan original. Den kan aldrig visas — `t()` slår upp mot + * EN:s nycklar — så den är antingen ett stavfel eller en kvarleva. + */ +export function overflodiga(katalog) { + return Object.keys(katalog).filter((n) => !arInvariant(n) && !(n in EN)); +} + +/** Andel av gränssnittet som finns på språket. */ +export function tackning(kod) { + const katalog = KATALOGER[kod]; + if (!katalog) return 0; + const totalt = Object.keys(EN).filter((n) => !arInvariant(n)).length; + return totalt === 0 ? 1 : (totalt - saknade(katalog).length) / totalt; +} + +/** + * Väljer språk ur det som finns att gå på. + * + * Ordningen är avsiktlig: användarens eget val väger tyngst, därefter + * organisationens, därefter webbläsarens, sist engelska. Organisationen + * går före webbläsaren därför att en verkstad i Tyskland med en polsk + * tekniker ska kunna ha ett gemensamt dokumentationsspråk — rapporten ska + * inte byta språk beroende på vem som råkade skriva raden. + */ +export function valjSprak({ anvandare, organisation, webblasare } = {}) { + const kanda = new Set(SPRAK.map((s) => s.kod)); + const forsta = [anvandare, organisation, ...(webblasare ?? [])] + .filter(Boolean) + .map((k) => String(k).slice(0, 2).toLowerCase()) + .find((k) => kanda.has(k)); + return forsta ?? STANDARD; +} + +/** + * Besked om metodikinnehåll som inte är granskat på användarens språk. + * + * Returnerar null när allt är i sin ordning. Annars en text som säger + * VAD som inte är granskat och VILKET språk texten faktiskt är på — inte + * en allmän brasklapp, som ingen läser. + */ +export function metodikvarning(sprak) { + const s = SPRAK.find((x) => x.kod === sprak); + if (!s || s.granskat) return null; + return t(sprak, "metodik.ogranskad", { sprak: s.egetNamn }); +} diff --git a/felsokning/services/gemensam/sprak/it.mjs b/felsokning/services/gemensam/sprak/it.mjs new file mode 100644 index 0000000..7644b92 --- /dev/null +++ b/felsokning/services/gemensam/sprak/it.mjs @@ -0,0 +1,120 @@ +// ALVA-SPEC-060 · Italiano. +// +// I pulsanti usano l'imperativo breve («Salva», «Annulla»), come vuole +// la convenzione delle interfacce italiane; le istruzioni all'interno +// delle frasi restano all'infinito («Fotografare il contachilometri»), +// senza rivolgersi all'operatore — ALVA-SPEC-001 §7. +// +// `granskat: false`: l'interfaccia è tradotta, il testo delle procedure +// non è revisionato da uno specialista. Vedi index.mjs. + +export const IT = { + // ---- Gradi di evidenza -------------------------------------------------- + "evidens.E1": "Osservazione", + "evidens.E2": "Fotografia", + "evidens.E3": "Video con audio", + "evidens.E4": "Misurazione, strumento tarato", + "evidens.E5": "Documento", + "evidens.ej_kalibrerad": "taratura mancante o scaduta", + "evidens.ej_angivet": "strumento non indicato", + "evidens.ej_fotograferad": "inserito, non fotografato", + + // ---- Il controllo di chiusura ------------------------------------------- + "grind.objekt": "Identificazione del veicolo o dell'oggetto verificata", + "grind.historik": "Storico del veicolo verificato o motivato", + "grind.historik.nekad": "Un controllo dello storico rifiutato richiede un motivo indicato.", + "grind.historik.saknas": "Nessun controllo dello storico documentato.", + "grind.matarstallning.ingaende": "Chilometraggio in accettazione fotografato", + "grind.matarstallning.utgaende": "Chilometraggio alla riconsegna fotografato", + "grind.matarstallning.saknas": "Nessun chilometraggio documentato.", + "grind.matarstallning.ej_foto": + "Il chilometraggio è inserito ma non fotografato. Fotografare il contachilometri, oppure indicare perché non è possibile.", + "grind.reproducering": "Verifica del sintomo: riprodotto, oppure documentato come non riproducibile", + "grind.felorsak": "Analisi della causa radice documentata", + "grind.atgard": "Intervento documentato o motivato", + "grind.atgard.saknas": "Non è documentato né un intervento eseguito né un motivo della sua assenza.", + "grind.kundbeslut": "Decisione del cliente sulla proposta registrata", + "grind.kundbeslut.avbojt": "Lavoro eseguito nonostante una proposta rifiutata", + "grind.kundbeslut.avbojt.detalj": + "Il cliente ha rifiutato la proposta, ma risulta documentato del lavoro come eseguito.", + "grind.kvalitetskontroll": "Controllo qualità eseguito — sintomo verificato", + "grind.kontroller": "Punti di controllo della metodologia: evidenza, oppure deroga documentata", + "grind.foton": "Fotografie presenti per i controlli che le richiedono", + "grind.slutsats": "Conclusione (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Abilitazione alta tensione confermata", + "grind.hogvolt.spanningslos": "Veicolo messo fuori tensione secondo la procedura del costruttore", + "grind.regelpaket": "La firma del pacchetto di regole non corrisponde — chiusura bloccata.", + "grind.regelpaket.osignerat": "È in uso un pacchetto di regole esterno privo di firma — chiusura bloccata.", + + // ---- La conclusione (ALVA-RULE-200) ------------------------------------- + "slutsats.rubrik": "Conclusione", + "slutsats.konstaterat": "Che cosa è stato accertato", + "slutsats.evidens": "Quale evidenza lo sostiene", + "slutsats.avfardat": "Quali ipotesi sono state escluse, e perché", + "slutsats.osakert": "Che cosa resta incerto", + "slutsats.ickesvar": + "Questa non è una conclusione. Indicare che cosa è stato accertato e quale evidenza lo sostiene.", + + // ---- Flusso della pratica ----------------------------------------------- + "arende.nytt": "Nuova pratica", + "arende.oppna": "Pratiche aperte", + "arende.avslutade": "Pratiche chiuse", + "arende.avsluta": "Chiudi la pratica", + "arende.avslutat": "Pratica chiusa", + "arende.kan_ej_avslutas": "La pratica non può ancora essere chiusa", + "arende.hinder": "Da completare prima della chiusura", + "arende.overlamna": "Trasferisci", + "arende.ansvarig": "Responsabile", + + // ---- Controllo preliminare ---------------------------------------------- + "pre.rubrik": "Controllo preliminare — prima dell'inizio del lavoro", + "pre.historik.fraga": + "Lo storico del veicolo è stato verificato? (lavori precedenti, guasti ricorrenti, TSB, campagne)", + "pre.historik.ja": "Sì — verificato", + "pre.historik.nej": "No", + "pre.historik.skal": "Motivo per cui lo storico non è stato verificato (obbligatorio)", + "pre.historik.relevant": "Lavori precedenti rilevanti (facoltativo — catena causale)", + "pre.matarstallning": "Chilometraggio", + "pre.fotografera": "Fotografa il quadro strumenti", + "pre.felbeskrivning": "Descrizione del guasto del cliente verificata", + "pre.observationer": "Altro in fase di accettazione?", + + // ---- Azioni ------------------------------------------------------------- + "handling.spara": "Salva", + "handling.avbryt": "Annulla", + "handling.fortsatt": "Continua", + "handling.tillbaka": "Indietro", + "handling.dokumentera": "Documenta", + "handling.fotografera": "Fotografa", + "handling.spela_in": "Registra video", + "handling.undantag": "Documenta una deroga", + "handling.undantag.skal": "Motivo della deroga (obbligatorio)", + "handling.exportera": "Esporta", + "handling.skriv_ut": "Stampa", + + // ---- Misurazione -------------------------------------------------------- + "matning.varde": "Valore", + "matning.enhet": "Unità", + "matning.matdon": "Strumento", + "matning.matdon.valj": "Seleziona strumento", + "matning.matdon.okant": "Strumento sconosciuto. Registrarlo prima di salvare la misurazione.", + "matning.kalibrerad_till": "Tarato fino al", + + // ---- Rapporto ----------------------------------------------------------- + "rapport.rubrik": "Rapporto della pratica", + "rapport.sammanfattning": "Sintesi", + "rapport.evidens": "Evidenze", + "rapport.atgarder": "Interventi", + "rapport.harledd": + "Derivato dal registro della pratica. Le osservazioni e le misurazioni sono riportate senza conclusioni prive di fondamento.", + + // ---- Lingua ------------------------------------------------------------- + "sprak.valj": "Lingua", + "sprak.granskat": "Revisionato", + "sprak.ogranskat": "Non revisionato", + "sprak.tackning": "{procent} % dell'interfaccia", + + "metodik.ogranskad": + "Il testo delle procedure non è stato revisionato da uno specialista tecnico in {sprak}. I passaggi e i punti di controllo sono mostrati in inglese dove non esiste una traduzione revisionata — una traduzione non revisionata di un'istruzione di sicurezza è peggiore di una in lingua straniera, perché non sembra straniera.", + "metodik.pa_engelska": "Mostrato in inglese — nessuna traduzione revisionata in {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/nl.mjs b/felsokning/services/gemensam/sprak/nl.mjs new file mode 100644 index 0000000..0c7c511 --- /dev/null +++ b/felsokning/services/gemensam/sprak/nl.mjs @@ -0,0 +1,119 @@ +// ALVA-SPEC-060 · Nederlands. +// +// Knoppen staan in de infinitief («Opslaan», «Annuleren»), zoals de +// Nederlandse interfaceconventie voorschrijft. Instructies binnen een +// zin richten zich niet tot de gebruiker — ALVA-SPEC-001 §7: het systeem +// meldt een toestand. +// +// `granskat: false`: de interface is vertaald, de proceduretekst is niet +// door een vakspecialist gecontroleerd. Zie index.mjs. + +export const NL = { + // ---- Bewijsgraden ------------------------------------------------------- + "evidens.E1": "Waarneming", + "evidens.E2": "Foto", + "evidens.E3": "Video met geluid", + "evidens.E4": "Meting, gekalibreerd meetmiddel", + "evidens.E5": "Document", + "evidens.ej_kalibrerad": "kalibratie ontbreekt of is verlopen", + "evidens.ej_angivet": "meetmiddel niet opgegeven", + "evidens.ej_fotograferad": "ingevoerd, niet gefotografeerd", + + // ---- De afsluitcontrole ------------------------------------------------- + "grind.objekt": "Identificatie van voertuig of object geverifieerd", + "grind.historik": "Voertuighistorie gecontroleerd of gemotiveerd", + "grind.historik.nekad": "Een geweigerde historiecontrole vereist een opgegeven reden.", + "grind.historik.saknas": "Geen historiecontrole gedocumenteerd.", + "grind.matarstallning.ingaende": "Kilometerstand bij inname gefotografeerd", + "grind.matarstallning.utgaende": "Kilometerstand bij aflevering gefotografeerd", + "grind.matarstallning.saknas": "Geen kilometerstand gedocumenteerd.", + "grind.matarstallning.ej_foto": + "De kilometerstand is ingevoerd maar niet gefotografeerd. Kilometerteller fotograferen, of aangeven waarom dat niet mogelijk is.", + "grind.reproducering": "Symptoomverificatie: gereproduceerd, of gedocumenteerd als niet reproduceerbaar", + "grind.felorsak": "Analyse van de grondoorzaak gedocumenteerd", + "grind.atgard": "Corrigerende maatregel gedocumenteerd of gemotiveerd", + "grind.atgard.saknas": "Noch een uitgevoerde maatregel noch een reden voor het uitblijven ervan is gedocumenteerd.", + "grind.kundbeslut": "Klantbeslissing over het voorstel vastgelegd", + "grind.kundbeslut.avbojt": "Werk uitgevoerd ondanks een afgewezen voorstel", + "grind.kundbeslut.avbojt.detalj": + "De klant heeft het voorstel afgewezen, maar er is werk gedocumenteerd als uitgevoerd.", + "grind.kvalitetskontroll": "Kwaliteitscontrole uitgevoerd — symptoom geverifieerd", + "grind.kontroller": "Controlepunten van de methodiek: bewijs, of een gedocumenteerde uitzondering", + "grind.foton": "Foto's aanwezig bij de controles die dat vereisen", + "grind.slutsats": "Eindconclusie (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Hoogspanningsbevoegdheid bevestigd", + "grind.hogvolt.spanningslos": "Voertuig spanningsloos gemaakt volgens de procedure van de fabrikant", + "grind.regelpaket": "Handtekening van het regelpakket komt niet overeen — afsluiten geblokkeerd.", + "grind.regelpaket.osignerat": "Er wordt een extern regelpakket zonder handtekening gebruikt — afsluiten geblokkeerd.", + + // ---- De eindconclusie (ALVA-RULE-200) ----------------------------------- + "slutsats.rubrik": "Eindconclusie", + "slutsats.konstaterat": "Wat is vastgesteld", + "slutsats.evidens": "Welk bewijs dat draagt", + "slutsats.avfardat": "Welke hypothesen zijn verworpen, en waarom", + "slutsats.osakert": "Wat onzeker blijft", + "slutsats.ickesvar": "Dat is geen conclusie. Aangeven wat is vastgesteld en welk bewijs dat draagt.", + + // ---- Zaakverloop -------------------------------------------------------- + "arende.nytt": "Nieuwe zaak", + "arende.oppna": "Openstaande zaken", + "arende.avslutade": "Afgesloten zaken", + "arende.avsluta": "Zaak afsluiten", + "arende.avslutat": "Zaak afgesloten", + "arende.kan_ej_avslutas": "De zaak kan nog niet worden afgesloten", + "arende.hinder": "Openstaand vóór afsluiting", + "arende.overlamna": "Overdragen", + "arende.ansvarig": "Verantwoordelijke", + + // ---- Vooronderzoek ------------------------------------------------------ + "pre.rubrik": "Vooronderzoek — voordat het werk begint", + "pre.historik.fraga": + "Is de voertuighistorie gecontroleerd? (eerdere werkzaamheden, terugkerende storingen, TSB's, campagnes)", + "pre.historik.ja": "Ja — gecontroleerd", + "pre.historik.nej": "Nee", + "pre.historik.skal": "Reden waarom de historie niet is gecontroleerd (verplicht)", + "pre.historik.relevant": "Relevante eerdere werkzaamheden (optioneel — oorzakelijke keten)", + "pre.matarstallning": "Kilometerstand", + "pre.fotografera": "Instrumentenpaneel fotograferen", + "pre.felbeskrivning": "Storingsbeschrijving van de klant geverifieerd", + "pre.observationer": "Nog iets bij de inname?", + + // ---- Handelingen -------------------------------------------------------- + "handling.spara": "Opslaan", + "handling.avbryt": "Annuleren", + "handling.fortsatt": "Doorgaan", + "handling.tillbaka": "Terug", + "handling.dokumentera": "Documenteren", + "handling.fotografera": "Fotograferen", + "handling.spela_in": "Video opnemen", + "handling.undantag": "Een uitzondering documenteren", + "handling.undantag.skal": "Reden voor de uitzondering (verplicht)", + "handling.exportera": "Exporteren", + "handling.skriv_ut": "Afdrukken", + + // ---- Meting ------------------------------------------------------------- + "matning.varde": "Waarde", + "matning.enhet": "Eenheid", + "matning.matdon": "Meetmiddel", + "matning.matdon.valj": "Meetmiddel kiezen", + "matning.matdon.okant": "Onbekend meetmiddel. Registreren voordat de meting wordt opgeslagen.", + "matning.kalibrerad_till": "Gekalibreerd tot", + + // ---- Rapport ------------------------------------------------------------ + "rapport.rubrik": "Zaakrapport", + "rapport.sammanfattning": "Samenvatting", + "rapport.evidens": "Bewijs", + "rapport.atgarder": "Maatregelen", + "rapport.harledd": + "Afgeleid uit het zaaklogboek. Waarnemingen en metingen worden weergegeven zonder conclusies waarvoor de onderbouwing ontbreekt.", + + // ---- Taal --------------------------------------------------------------- + "sprak.valj": "Taal", + "sprak.granskat": "Gecontroleerd", + "sprak.ogranskat": "Niet gecontroleerd", + "sprak.tackning": "{procent} % van de interface", + + "metodik.ogranskad": + "De proceduretekst is niet gecontroleerd door een technisch specialist in het {sprak}. Stappen en controlepunten worden in het Engels weergegeven waar geen gecontroleerde vertaling bestaat — een ongecontroleerde vertaling van een veiligheidsinstructie is slechter dan een anderstalige, omdat die er niet anderstalig uitziet.", + "metodik.pa_engelska": "Weergegeven in het Engels — geen gecontroleerde vertaling in het {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/pl.mjs b/felsokning/services/gemensam/sprak/pl.mjs new file mode 100644 index 0000000..b85a42b --- /dev/null +++ b/felsokning/services/gemensam/sprak/pl.mjs @@ -0,0 +1,121 @@ +// ALVA-SPEC-060 · Polski. +// +// ---- Odmiana nazwy języka ------------------------------------------------ +// +// {sprak} wstawia własną nazwę języka — «Polski» — w mianowniku. Po +// polsku «w języku Polski» jest błędem, a odmienić wstawianego wyrazu +// nie sposób bez tablicy przypadków dla dziesięciu języków. Dlatego +// zdania są tak sformułowane, by nazwa stała w nawiasie jako etykieta: +// «w tym języku ({sprak})». To wybór świadomy, nie niedopatrzenie. +// +// `granskat: false`: interfejs jest przetłumaczony, tekst procedur nie +// został sprawdzony przez specjalistę. Zob. index.mjs. + +export const PL = { + // ---- Stopnie dowodu ----------------------------------------------------- + "evidens.E1": "Obserwacja", + "evidens.E2": "Fotografia", + "evidens.E3": "Wideo z dźwiękiem", + "evidens.E4": "Pomiar, przyrząd wzorcowany", + "evidens.E5": "Dokument", + "evidens.ej_kalibrerad": "brak wzorcowania lub wzorcowanie wygasło", + "evidens.ej_angivet": "nie podano przyrządu", + "evidens.ej_fotograferad": "wprowadzono, nie sfotografowano", + + // ---- Kontrola zamknięcia ------------------------------------------------ + "grind.objekt": "Identyfikacja pojazdu lub obiektu zweryfikowana", + "grind.historik": "Historia pojazdu sprawdzona lub uzasadniona", + "grind.historik.nekad": "Odmowa sprawdzenia historii wymaga podania powodu.", + "grind.historik.saknas": "Nie udokumentowano sprawdzenia historii.", + "grind.matarstallning.ingaende": "Stan licznika przy przyjęciu sfotografowany", + "grind.matarstallning.utgaende": "Stan licznika przy wydaniu sfotografowany", + "grind.matarstallning.saknas": "Nie udokumentowano stanu licznika.", + "grind.matarstallning.ej_foto": + "Stan licznika został wprowadzony, ale nie sfotografowany. Sfotografować licznik lub podać, dlaczego nie jest to możliwe.", + "grind.reproducering": "Weryfikacja objawu: odtworzony lub udokumentowany jako nieodtwarzalny", + "grind.felorsak": "Analiza przyczyny źródłowej udokumentowana", + "grind.atgard": "Działanie naprawcze udokumentowane lub uzasadnione", + "grind.atgard.saknas": "Nie udokumentowano ani wykonanego działania, ani powodu jego braku.", + "grind.kundbeslut": "Decyzja klienta w sprawie propozycji zarejestrowana", + "grind.kundbeslut.avbojt": "Praca wykonana mimo odrzuconej propozycji", + "grind.kundbeslut.avbojt.detalj": "Klient odrzucił propozycję, ale praca jest udokumentowana jako wykonana.", + "grind.kvalitetskontroll": "Kontrola jakości wykonana — objaw zweryfikowany", + "grind.kontroller": "Punkty kontrolne metodyki: dowód lub udokumentowane odstępstwo", + "grind.foton": "Fotografie obecne przy kontrolach, które ich wymagają", + "grind.slutsats": "Wniosek końcowy (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Uprawnienia wysokonapięciowe potwierdzone", + "grind.hogvolt.spanningslos": "Pojazd odłączony od napięcia zgodnie z procedurą producenta", + "grind.regelpaket": "Podpis pakietu reguł nie zgadza się — zamknięcie zablokowane.", + "grind.regelpaket.osignerat": "Używany jest zewnętrzny pakiet reguł bez podpisu — zamknięcie zablokowane.", + + // ---- Wniosek końcowy (ALVA-RULE-200) ------------------------------------ + "slutsats.rubrik": "Wniosek końcowy", + "slutsats.konstaterat": "Co zostało ustalone", + "slutsats.evidens": "Jakie dowody to potwierdzają", + "slutsats.avfardat": "Które hipotezy odrzucono i dlaczego", + "slutsats.osakert": "Co pozostaje niepewne", + "slutsats.ickesvar": "To nie jest wniosek. Podać, co zostało ustalone i jakie dowody to potwierdzają.", + + // ---- Przebieg sprawy ---------------------------------------------------- + "arende.nytt": "Nowa sprawa", + "arende.oppna": "Sprawy otwarte", + "arende.avslutade": "Sprawy zamknięte", + "arende.avsluta": "Zamknij sprawę", + "arende.avslutat": "Sprawa zamknięta", + "arende.kan_ej_avslutas": "Sprawy nie można jeszcze zamknąć", + "arende.hinder": "Do wykonania przed zamknięciem", + "arende.overlamna": "Przekaż", + "arende.ansvarig": "Odpowiedzialny", + + // ---- Kontrola wstępna --------------------------------------------------- + "pre.rubrik": "Kontrola wstępna — przed rozpoczęciem pracy", + "pre.historik.fraga": + "Czy historia pojazdu została sprawdzona? (wcześniejsze naprawy, powtarzające się usterki, TSB, akcje serwisowe)", + "pre.historik.ja": "Tak — sprawdzona", + "pre.historik.nej": "Nie", + "pre.historik.skal": "Powód niesprawdzenia historii (wymagane)", + "pre.historik.relevant": "Istotne wcześniejsze naprawy (opcjonalnie — łańcuch przyczynowy)", + "pre.matarstallning": "Stan licznika", + "pre.fotografera": "Sfotografuj zestaw wskaźników", + "pre.felbeskrivning": "Opis usterki podany przez klienta zweryfikowany", + "pre.observationer": "Coś jeszcze przy przyjęciu?", + + // ---- Czynności ---------------------------------------------------------- + "handling.spara": "Zapisz", + "handling.avbryt": "Anuluj", + "handling.fortsatt": "Dalej", + "handling.tillbaka": "Wstecz", + "handling.dokumentera": "Udokumentuj", + "handling.fotografera": "Sfotografuj", + "handling.spela_in": "Nagraj wideo", + "handling.undantag": "Udokumentuj odstępstwo", + "handling.undantag.skal": "Powód odstępstwa (wymagane)", + "handling.exportera": "Eksportuj", + "handling.skriv_ut": "Drukuj", + + // ---- Pomiar ------------------------------------------------------------- + "matning.varde": "Wartość", + "matning.enhet": "Jednostka", + "matning.matdon": "Przyrząd", + "matning.matdon.valj": "Wybierz przyrząd", + "matning.matdon.okant": "Nieznany przyrząd. Zarejestrować go przed zapisaniem pomiaru.", + "matning.kalibrerad_till": "Wzorcowany do", + + // ---- Raport ------------------------------------------------------------- + "rapport.rubrik": "Raport sprawy", + "rapport.sammanfattning": "Podsumowanie", + "rapport.evidens": "Dowody", + "rapport.atgarder": "Działania", + "rapport.harledd": + "Wyprowadzony z dziennika sprawy. Obserwacje i pomiary są przedstawiane bez wniosków pozbawionych podstaw.", + + // ---- Język -------------------------------------------------------------- + "sprak.valj": "Język", + "sprak.granskat": "Sprawdzony", + "sprak.ogranskat": "Niesprawdzony", + "sprak.tackning": "{procent} % interfejsu", + + "metodik.ogranskad": + "Tekst procedur nie został sprawdzony przez specjalistę technicznego w tym języku ({sprak}). Kroki i punkty kontrolne są wyświetlane po angielsku tam, gdzie nie ma sprawdzonego tłumaczenia — niesprawdzone tłumaczenie instrukcji bezpieczeństwa jest gorsze niż instrukcja w obcym języku, ponieważ nie wygląda obco.", + "metodik.pa_engelska": "Wyświetlane po angielsku — brak sprawdzonego tłumaczenia w tym języku ({sprak})", +}; diff --git a/felsokning/services/gemensam/sprak/pt.mjs b/felsokning/services/gemensam/sprak/pt.mjs new file mode 100644 index 0000000..ab92182 --- /dev/null +++ b/felsokning/services/gemensam/sprak/pt.mjs @@ -0,0 +1,119 @@ +// ALVA-SPEC-060 · Português. +// +// Português europeu (pt-PT), sem o Acordo aplicado às formas em que as +// duas normas divergem de maneira visível para um técnico: «contacto», +// «registo», «conta-quilómetros». Se surgir um mercado brasileiro, é uma +// entrada nova no catálogo — «pt-BR» — e não uma emenda a esta. +// +// `granskat: false`: a interface está traduzida, o texto dos +// procedimentos não foi revisto por um especialista. Ver index.mjs. + +export const PT = { + // ---- Graus de evidência ------------------------------------------------- + "evidens.E1": "Observação", + "evidens.E2": "Fotografia", + "evidens.E3": "Vídeo com som", + "evidens.E4": "Medição, instrumento calibrado", + "evidens.E5": "Documento", + "evidens.ej_kalibrerad": "calibração em falta ou expirada", + "evidens.ej_angivet": "instrumento não indicado", + "evidens.ej_fotograferad": "introduzido, não fotografado", + + // ---- O controlo de encerramento ----------------------------------------- + "grind.objekt": "Identificação do veículo ou do objeto verificada", + "grind.historik": "Histórico do veículo verificado ou justificado", + "grind.historik.nekad": "Uma verificação de histórico recusada exige um motivo indicado.", + "grind.historik.saknas": "Nenhuma verificação de histórico documentada.", + "grind.matarstallning.ingaende": "Quilometragem à entrada fotografada", + "grind.matarstallning.utgaende": "Quilometragem à saída fotografada", + "grind.matarstallning.saknas": "Nenhuma quilometragem documentada.", + "grind.matarstallning.ej_foto": + "A quilometragem está introduzida mas não fotografada. Fotografar o conta-quilómetros, ou indicar por que motivo não é possível.", + "grind.reproducering": "Verificação do sintoma: reproduzido, ou documentado como não reproduzível", + "grind.felorsak": "Análise da causa raiz documentada", + "grind.atgard": "Ação corretiva documentada ou justificada", + "grind.atgard.saknas": "Não está documentada nem uma ação realizada nem um motivo para a sua ausência.", + "grind.kundbeslut": "Decisão do cliente sobre a proposta registada", + "grind.kundbeslut.avbojt": "Trabalho realizado apesar de uma proposta recusada", + "grind.kundbeslut.avbojt.detalj": "O cliente recusou a proposta, mas há trabalho documentado como realizado.", + "grind.kvalitetskontroll": "Controlo de qualidade efetuado — sintoma verificado", + "grind.kontroller": "Pontos de controlo da metodologia: evidência, ou uma exceção documentada", + "grind.foton": "Fotografias presentes nos controlos que as exigem", + "grind.slutsats": "Conclusão (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Habilitação de alta tensão confirmada", + "grind.hogvolt.spanningslos": "Veículo colocado fora de tensão segundo o procedimento do fabricante", + "grind.regelpaket": "A assinatura do pacote de regras não corresponde — encerramento bloqueado.", + "grind.regelpaket.osignerat": + "Está a ser utilizado um pacote de regras externo sem assinatura — encerramento bloqueado.", + + // ---- A conclusão (ALVA-RULE-200) ---------------------------------------- + "slutsats.rubrik": "Conclusão", + "slutsats.konstaterat": "O que foi estabelecido", + "slutsats.evidens": "Que evidência o sustenta", + "slutsats.avfardat": "Que hipóteses foram afastadas, e porquê", + "slutsats.osakert": "O que permanece incerto", + "slutsats.ickesvar": "Isso não é uma conclusão. Indicar o que foi estabelecido e que evidência o sustenta.", + + // ---- Fluxo do processo -------------------------------------------------- + "arende.nytt": "Novo processo", + "arende.oppna": "Processos abertos", + "arende.avslutade": "Processos encerrados", + "arende.avsluta": "Encerrar o processo", + "arende.avslutat": "Processo encerrado", + "arende.kan_ej_avslutas": "O processo ainda não pode ser encerrado", + "arende.hinder": "Pendente antes do encerramento", + "arende.overlamna": "Transferir", + "arende.ansvarig": "Responsável", + + // ---- Verificação prévia ------------------------------------------------- + "pre.rubrik": "Verificação prévia — antes do início do trabalho", + "pre.historik.fraga": + "O histórico do veículo foi verificado? (trabalhos anteriores, avarias recorrentes, TSB, campanhas)", + "pre.historik.ja": "Sim — verificado", + "pre.historik.nej": "Não", + "pre.historik.skal": "Motivo pelo qual o histórico não foi verificado (obrigatório)", + "pre.historik.relevant": "Trabalhos anteriores relevantes (opcional — cadeia causal)", + "pre.matarstallning": "Quilometragem", + "pre.fotografera": "Fotografar o painel de instrumentos", + "pre.felbeskrivning": "Descrição da avaria pelo cliente verificada", + "pre.observationer": "Mais alguma coisa na receção?", + + // ---- Ações -------------------------------------------------------------- + "handling.spara": "Guardar", + "handling.avbryt": "Cancelar", + "handling.fortsatt": "Continuar", + "handling.tillbaka": "Voltar", + "handling.dokumentera": "Documentar", + "handling.fotografera": "Fotografar", + "handling.spela_in": "Gravar vídeo", + "handling.undantag": "Documentar uma exceção", + "handling.undantag.skal": "Motivo da exceção (obrigatório)", + "handling.exportera": "Exportar", + "handling.skriv_ut": "Imprimir", + + // ---- Medição ------------------------------------------------------------ + "matning.varde": "Valor", + "matning.enhet": "Unidade", + "matning.matdon": "Instrumento", + "matning.matdon.valj": "Selecionar instrumento", + "matning.matdon.okant": "Instrumento desconhecido. Registá-lo antes de guardar a medição.", + "matning.kalibrerad_till": "Calibrado até", + + // ---- Relatório ---------------------------------------------------------- + "rapport.rubrik": "Relatório do processo", + "rapport.sammanfattning": "Resumo", + "rapport.evidens": "Evidência", + "rapport.atgarder": "Ações", + "rapport.harledd": + "Derivado do registo do processo. As observações e as medições são apresentadas sem conclusões que careçam de fundamento.", + + // ---- Idioma ------------------------------------------------------------- + "sprak.valj": "Idioma", + "sprak.granskat": "Revisto", + "sprak.ogranskat": "Não revisto", + "sprak.tackning": "{procent} % da interface", + + "metodik.ogranskad": + "O texto dos procedimentos não foi revisto por um especialista técnico em {sprak}. Os passos e os pontos de controlo são apresentados em inglês onde não existe tradução revista — uma tradução não revista de uma instrução de segurança é pior do que uma em língua estrangeira, porque não parece estrangeira.", + "metodik.pa_engelska": "Apresentado em inglês — sem tradução revista em {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/ro.mjs b/felsokning/services/gemensam/sprak/ro.mjs new file mode 100644 index 0000000..79ddfc5 --- /dev/null +++ b/felsokning/services/gemensam/sprak/ro.mjs @@ -0,0 +1,125 @@ +// ALVA-SPEC-060 · Română. +// +// Imperativul persoanei a II-a singular este folosit consecvent, atât +// pe butoane («Salvează») cât și în instrucțiuni («Fotografiază +// kilometrajul»). Amestecul dintre singular și plural este cea mai +// frecventă inconsecvență din interfețele traduse în română, iar aici +// este evitat deliberat. +// +// Diacriticele sunt cele corecte — ș și ț cu virgulă (U+0219, U+021B), +// nu cu sedilă. Un raport tipărit cu sedile arată ca un document +// netradus. +// +// `granskat: false`: interfața este tradusă, textul procedurilor nu este +// verificat de un specialist. A se vedea index.mjs. + +export const RO = { + // ---- Grade de dovadă ---------------------------------------------------- + "evidens.E1": "Observație", + "evidens.E2": "Fotografie", + "evidens.E3": "Videoclip cu sunet", + "evidens.E4": "Măsurare, instrument etalonat", + "evidens.E5": "Document", + "evidens.ej_kalibrerad": "etalonare lipsă sau expirată", + "evidens.ej_angivet": "instrument neindicat", + "evidens.ej_fotograferad": "introdus, nefotografiat", + + // ---- Controlul de închidere --------------------------------------------- + "grind.objekt": "Identificarea vehiculului sau a obiectului verificată", + "grind.historik": "Istoricul vehiculului verificat sau justificat", + "grind.historik.nekad": "O verificare a istoricului refuzată necesită un motiv indicat.", + "grind.historik.saknas": "Nicio verificare a istoricului documentată.", + "grind.matarstallning.ingaende": "Kilometrajul la primire fotografiat", + "grind.matarstallning.utgaende": "Kilometrajul la predare fotografiat", + "grind.matarstallning.saknas": "Niciun kilometraj documentat.", + "grind.matarstallning.ej_foto": + "Kilometrajul este introdus, dar nu este fotografiat. Fotografiază contorul de kilometraj sau indică de ce acest lucru nu este posibil.", + "grind.reproducering": "Verificarea simptomului: reprodus sau documentat ca nereproductibil", + "grind.felorsak": "Analiza cauzei-rădăcină documentată", + "grind.atgard": "Acțiune corectivă documentată sau justificată", + "grind.atgard.saknas": "Nu este documentată nici o acțiune efectuată, nici un motiv pentru absența acesteia.", + "grind.kundbeslut": "Decizia clientului privind propunerea înregistrată", + "grind.kundbeslut.avbojt": "Lucrare efectuată în pofida unei propuneri refuzate", + "grind.kundbeslut.avbojt.detalj": + "Clientul a refuzat propunerea, dar există lucrări documentate ca fiind efectuate.", + "grind.kvalitetskontroll": "Control de calitate efectuat — simptom verificat", + "grind.kontroller": "Punctele de control ale metodologiei: dovadă sau o excepție documentată", + "grind.foton": "Fotografii prezente pentru controalele care le impun", + "grind.slutsats": "Concluzie finală (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Autorizarea pentru înaltă tensiune confirmată", + "grind.hogvolt.spanningslos": "Vehicul scos de sub tensiune conform procedurii producătorului", + "grind.regelpaket": "Semnătura pachetului de reguli nu corespunde — închiderea este blocată.", + "grind.regelpaket.osignerat": + "Se utilizează un pachet de reguli extern fără semnătură — închiderea este blocată.", + + // ---- Concluzia finală (ALVA-RULE-200) ----------------------------------- + "slutsats.rubrik": "Concluzie finală", + "slutsats.konstaterat": "Ce a fost stabilit", + "slutsats.evidens": "Ce dovezi susțin acest lucru", + "slutsats.avfardat": "Ce ipoteze au fost înlăturate și de ce", + "slutsats.osakert": "Ce rămâne incert", + "slutsats.ickesvar": "Aceasta nu este o concluzie. Indică ce a fost stabilit și ce dovezi susțin acest lucru.", + + // ---- Parcursul cazului -------------------------------------------------- + "arende.nytt": "Caz nou", + "arende.oppna": "Cazuri deschise", + "arende.avslutade": "Cazuri închise", + "arende.avsluta": "Închide cazul", + "arende.avslutat": "Caz închis", + "arende.kan_ej_avslutas": "Cazul nu poate fi încă închis", + "arende.hinder": "Rămâne de rezolvat înainte de închidere", + "arende.overlamna": "Predă", + "arende.ansvarig": "Responsabil", + + // ---- Verificare prealabilă ---------------------------------------------- + "pre.rubrik": "Verificare prealabilă — înainte de începerea lucrării", + "pre.historik.fraga": + "A fost verificat istoricul vehiculului? (lucrări anterioare, defecte recurente, TSB, campanii)", + "pre.historik.ja": "Da — verificat", + "pre.historik.nej": "Nu", + "pre.historik.skal": "Motivul pentru care istoricul nu a fost verificat (obligatoriu)", + "pre.historik.relevant": "Lucrări anterioare relevante (opțional — lanț cauzal)", + "pre.matarstallning": "Kilometraj", + "pre.fotografera": "Fotografiază panoul de bord", + "pre.felbeskrivning": "Descrierea defectului de către client verificată", + "pre.observationer": "Altceva la primire?", + + // ---- Acțiuni ------------------------------------------------------------ + "handling.spara": "Salvează", + "handling.avbryt": "Anulează", + "handling.fortsatt": "Continuă", + "handling.tillbaka": "Înapoi", + "handling.dokumentera": "Documentează", + "handling.fotografera": "Fotografiază", + "handling.spela_in": "Înregistrează video", + "handling.undantag": "Documentează o excepție", + "handling.undantag.skal": "Motivul excepției (obligatoriu)", + "handling.exportera": "Exportă", + "handling.skriv_ut": "Tipărește", + + // ---- Măsurare ----------------------------------------------------------- + "matning.varde": "Valoare", + "matning.enhet": "Unitate", + "matning.matdon": "Instrument", + "matning.matdon.valj": "Selectează instrumentul", + "matning.matdon.okant": "Instrument necunoscut. Înregistrează-l înainte de salvarea măsurării.", + "matning.kalibrerad_till": "Etalonat până la", + + // ---- Raport ------------------------------------------------------------- + "rapport.rubrik": "Raportul cazului", + "rapport.sammanfattning": "Rezumat", + "rapport.evidens": "Dovezi", + "rapport.atgarder": "Acțiuni", + "rapport.harledd": + "Derivat din jurnalul cazului. Observațiile și măsurările sunt prezentate fără concluzii lipsite de temei.", + + // ---- Limbă -------------------------------------------------------------- + "sprak.valj": "Limbă", + "sprak.granskat": "Verificat", + "sprak.ogranskat": "Neverificat", + "sprak.tackning": "{procent} % din interfață", + + "metodik.ogranskad": + "Textul procedurilor nu a fost verificat de un specialist tehnic în limba {sprak}. Pașii și punctele de control sunt afișate în engleză acolo unde nu există o traducere verificată — o traducere neverificată a unei instrucțiuni de siguranță este mai gravă decât una într-o limbă străină, pentru că nu arată ca fiind străină.", + "metodik.pa_engelska": "Afișat în engleză — nicio traducere verificată în limba {sprak}", +}; diff --git a/felsokning/services/gemensam/sprak/sv.mjs b/felsokning/services/gemensam/sprak/sv.mjs new file mode 100644 index 0000000..ba58a3a --- /dev/null +++ b/felsokning/services/gemensam/sprak/sv.mjs @@ -0,0 +1,117 @@ +// ALVA-SPEC-060 · Svenska. +// +// Hemmamarknadens språk och det enda utöver engelska där metodik- +// innehållet är läst av någon som kan yrket. Därför `granskat: true` i +// SPRAK — inte för att svenskan är bättre skriven än tyskan här, utan +// för att den är kontrollerad av en fackman och tyskan inte är det. +// +// Fas- och statusord saknas medvetet. De är ALVA:s struktur och skrivs +// likadant på varje språk (ALVA-SPEC-001 §2). Se index.mjs. + +export const SV = { + // ---- Evidensgrader ------------------------------------------------------ + "evidens.E1": "Observation", + "evidens.E2": "Fotografi", + "evidens.E3": "Video med ljud", + "evidens.E4": "Mätning, kalibrerat mätdon", + "evidens.E5": "Dokument", + "evidens.ej_kalibrerad": "kalibrering saknas eller har gått ut", + "evidens.ej_angivet": "mätdon ej angivet", + "evidens.ej_fotograferad": "inmatad, ej fotograferad", + + // ---- Kvalitetsgrinden --------------------------------------------------- + "grind.objekt": "Fordonets eller objektets identitet verifierad", + "grind.historik": "Fordonets historik kontrollerad eller motiverad", + "grind.historik.nekad": "En nekad historikkontroll kräver ett angivet skäl.", + "grind.historik.saknas": "Ingen historikkontroll dokumenterad.", + "grind.matarstallning.ingaende": "Ingående mätarställning fotograferad", + "grind.matarstallning.utgaende": "Utgående mätarställning fotograferad", + "grind.matarstallning.saknas": "Ingen mätarställning dokumenterad.", + "grind.matarstallning.ej_foto": + "Mätarställningen är inmatad men inte fotograferad. Fotografera mätaren, eller ange varför det inte är möjligt.", + "grind.reproducering": "Symtomverifiering: reproducerat, eller dokumenterat som ej reproducerbart", + "grind.felorsak": "Felorsaksanalys dokumenterad", + "grind.atgard": "Åtgärd dokumenterad eller motiverad", + "grind.atgard.saknas": "Varken utförd åtgärd eller skäl till att den uteblivit är dokumenterat.", + "grind.kundbeslut": "Kundens beslut om förslaget registrerat", + "grind.kundbeslut.avbojt": "Arbete utfört trots avböjt förslag", + "grind.kundbeslut.avbojt.detalj": "Kunden avböjde förslaget, men arbete är dokumenterat som utfört.", + "grind.kvalitetskontroll": "Kvalitetskontroll utförd — symtomet verifierat", + "grind.kontroller": "Metodikens kontrollpunkter: evidens, eller dokumenterat undantag", + "grind.foton": "Foton finns för de kontroller som kräver det", + "grind.slutsats": "Slutsats (ALVA-RULE-200)", + "grind.hogvolt.behorighet": "Högvoltsbehörighet bekräftad", + "grind.hogvolt.spanningslos": "Fordonet spänningslöst enligt tillverkarens metod", + "grind.regelpaket": "Regelpaketets signatur stämmer inte — avslut spärrat.", + "grind.regelpaket.osignerat": "Ett externt regelpaket används utan signatur — avslut spärrat.", + + // ---- Slutsatsen (ALVA-RULE-200) ----------------------------------------- + "slutsats.rubrik": "Slutsats", + "slutsats.konstaterat": "Vad som är konstaterat", + "slutsats.evidens": "Vilken evidens som bär det", + "slutsats.avfardat": "Vilka hypoteser som avfärdats, och varför", + "slutsats.osakert": "Vad som fortfarande är osäkert", + "slutsats.ickesvar": "Det är inte ett svar. Ange vad som är konstaterat och vilken evidens som bär det.", + + // ---- Ärendeflödet ------------------------------------------------------- + "arende.nytt": "Nytt ärende", + "arende.oppna": "Öppna ärenden", + "arende.avslutade": "Avslutade ärenden", + "arende.avsluta": "Avsluta ärendet", + "arende.avslutat": "Ärendet avslutat", + "arende.kan_ej_avslutas": "Ärendet kan inte avslutas än", + "arende.hinder": "Kvarstår före avslut", + "arende.overlamna": "Lämna över", + "arende.ansvarig": "Ansvarig", + + // ---- Förkontroll -------------------------------------------------------- + "pre.rubrik": "Förkontroll — innan arbetet börjar", + "pre.historik.fraga": "Är fordonets historik kontrollerad? (tidigare arbeten, återkommande fel, TSB:er, kampanjer)", + "pre.historik.ja": "Ja — kontrollerad", + "pre.historik.nej": "Nej", + "pre.historik.skal": "Skäl till att historiken inte kontrollerats (obligatoriskt)", + "pre.historik.relevant": "Relevanta tidigare arbeten (valfritt — orsakskedja)", + "pre.matarstallning": "Mätarställning", + "pre.fotografera": "Fotografera instrumentpanelen", + "pre.felbeskrivning": "Kundens felbeskrivning verifierad", + "pre.observationer": "Något annat vid mottagandet?", + + // ---- Handlingar --------------------------------------------------------- + "handling.spara": "Spara", + "handling.avbryt": "Avbryt", + "handling.fortsatt": "Fortsätt", + "handling.tillbaka": "Tillbaka", + "handling.dokumentera": "Dokumentera", + "handling.fotografera": "Fotografera", + "handling.spela_in": "Spela in video", + "handling.undantag": "Dokumentera ett undantag", + "handling.undantag.skal": "Skäl till undantaget (obligatoriskt)", + "handling.exportera": "Exportera", + "handling.skriv_ut": "Skriv ut", + + // ---- Mätning ------------------------------------------------------------ + "matning.varde": "Värde", + "matning.enhet": "Enhet", + "matning.matdon": "Mätdon", + "matning.matdon.valj": "Välj mätdon", + "matning.matdon.okant": "Okänt mätdon. Registrera det innan mätningen sparas.", + "matning.kalibrerad_till": "Kalibrerad till", + + // ---- Rapport ------------------------------------------------------------ + "rapport.rubrik": "Ärenderapport", + "rapport.sammanfattning": "Sammanfattning", + "rapport.evidens": "Evidens", + "rapport.atgarder": "Åtgärder", + "rapport.harledd": + "Härledd ur ärendeloggen. Observationer och mätningar redovisas utan slutsatser som saknar stöd.", + + // ---- Språk -------------------------------------------------------------- + "sprak.valj": "Språk", + "sprak.granskat": "Granskat", + "sprak.ogranskat": "Ej granskat", + "sprak.tackning": "{procent} % av gränssnittet", + + "metodik.ogranskad": + "Metodiktexten är inte granskad av en fackman på {sprak}. Steg och kontrollpunkter visas på engelska där ingen granskad översättning finns — en ogranskad översättning av en säkerhetsinstruktion är sämre än en på främmande språk, därför att den inte ser främmande ut.", + "metodik.pa_engelska": "Visas på engelska — ingen granskad översättning på {sprak}", +};