1 Commits
main ... dev

Author SHA1 Message Date
c212155f61 Neues Branding und Text-Konzept
All checks were successful
release-tag / release-image (push) Successful in 1m52s
2026-07-26 20:59:38 +02:00
15 changed files with 515 additions and 52 deletions

View File

@@ -12,7 +12,7 @@
LISTEN_ADDRESS=:8080 LISTEN_ADDRESS=:8080
BASE_URL=http://localhost:8080 BASE_URL=http://localhost:8080
OUTPUT_BASE_URL=http://localhost:8080 OUTPUT_BASE_URL=http://localhost:8080
PUBLIC_NAME=UCNG AI Usage Disclosure PUBLIC_NAME=UCNG
CONTACT_URL=https://b1tsblog.org/page/ai CONTACT_URL=https://b1tsblog.org/page/ai
DEFAULT_LANGUAGE=de DEFAULT_LANGUAGE=de

View File

@@ -2,13 +2,13 @@ name: release-tag
on: on:
push: push:
branches: branches:
- 'main' - 'dev'
jobs: jobs:
release-image: release-image:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
DOCKER_ORG: sendnrw DOCKER_ORG: sendnrw
DOCKER_LATEST: latest DOCKER_LATEST: dev
RUNNER_TOOL_CACHE: /toolcache RUNNER_TOOL_CACHE: /toolcache
steps: steps:
- name: Checkout - name: Checkout

View File

@@ -2,13 +2,13 @@ name: release-tag
on: on:
push: push:
branches: branches:
- 'main' - 'dev'
jobs: jobs:
release-image: release-image:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
DOCKER_ORG: sendnrw DOCKER_ORG: sendnrw
DOCKER_LATEST: latest DOCKER_LATEST: dev
RUNNER_TOOL_CACHE: /toolcache RUNNER_TOOL_CACHE: /toolcache
steps: steps:
- name: Checkout - name: Checkout

53
UCNG-CONTENT-TEST.md Normal file
View File

@@ -0,0 +1,53 @@
# UCNG Content Test Version
Diese Fassung ist für einen separaten Test-Branch gedacht und setzt die in den **UCNG Brand & Identity Guidelines, Version 0.1** definierte Content-Positionierung auf die bestehende Anwendung um.
## Leitlinie
- Kernsprache der Anwendung: Deutsch
- Primärer Claim: **Declare how content was made.**
- UCNG wird als offenes, neutrales Notationssystem für Content-Declarations positioniert.
- Die Declaration beschreibt den deklarierten Entstehungs- und Transformationskontext; sie bewertet weder Wahrheit noch Qualität.
- Human-readable Declaration und Machine Layer werden als zwei Darstellungen derselben Angaben kommuniziert.
- Regulatorischer Kontext, insbesondere EU AI Act / Artikel 50, bleibt als optionale Entscheidungshilfe von der UCNG-Kernaussage getrennt.
- `Declared`, `Attested` und `Verified` werden begrifflich nicht gleichgesetzt.
## Bewusst unverändert
Diese Content-Testfassung verändert **nicht**:
- API-Endpunkte oder Query-Parameter
- das JSON-LD-Datenmodell
- `AIUsageDeclaration` als bestehenden technischen `@type`
- Schema-Version 1.2
- die bestehenden Enum-Werte für `aiExtent`
- Lizenz-, Deployment- oder Validierungslogik
## Anzeige-Mapping der bestehenden aiExtent-Werte
Da das bestehende technische Schema noch nicht die vollständigen UCNG-Klassen als eigene Werte modelliert, wird nur die sichtbare Bezeichnung angepasst:
| Bestehender Wert | Sichtbare UCNG-Einordnung |
|---|---|
| `none` | `HUMAN` |
| `assisted` | `AI ASSISTED` |
| `partial` | `MIXED · teilweise generiert` |
| `mostly` | `AI GENERATED · überwiegend` |
| `full` | `AI GENERATED` |
**AI TRANSFORMED** wurde absichtlich nicht als neue allgemeine Datenklasse eingeführt. Das wäre eine Änderung des technischen Modells und gehört in eine spätere UCNG-Spezifikations-/Schema-Iteration, nicht in einen reinen Content-Test.
## Sprachen
Die vorhandenen Locales bleiben erhalten:
- Deutsch
- Englisch
- Französisch
- Spanisch
- Italienisch
- Niederländisch
- Portugiesisch
- Polnisch
Deutsch ist die Leitfassung. Der offizielle englische Claim und die standardnahen Klassennamen (`HUMAN`, `AI ASSISTED`, `AI GENERATED`, `MIXED`, `Declared`, `Verified`) bleiben sprachübergreifend konsistent, während erklärende UI-Texte lokalisiert sind.

View File

@@ -79,7 +79,7 @@ func ConfigFromEnv() Config {
ListenAddress: env("LISTEN_ADDRESS", ":8080"), ListenAddress: env("LISTEN_ADDRESS", ":8080"),
BaseURL: baseURL, BaseURL: baseURL,
OutputBaseURL: strings.TrimRight(env("OUTPUT_BASE_URL", baseURL), "/"), OutputBaseURL: strings.TrimRight(env("OUTPUT_BASE_URL", baseURL), "/"),
PublicName: env("PUBLIC_NAME", "UCNG AI Usage Disclosure"), PublicName: env("PUBLIC_NAME", "UCNG"),
ContactURL: contactURL, ContactURL: contactURL,
DefaultLanguage: env("DEFAULT_LANGUAGE", "de"), DefaultLanguage: env("DEFAULT_LANGUAGE", "de"),
TrustProxy: boolEnv("TRUST_PROXY", false), TrustProxy: boolEnv("TRUST_PROXY", false),

View File

@@ -902,14 +902,14 @@ func declarationSummary(d declaration.Declaration, locale i18n.Locale) []string
return nil return nil
} }
intro := map[string]string{ intro := map[string]string{
"de": "Diese Erklärung dokumentiert nachvollziehbar, in welchen Bereichen künstliche Intelligenz bei der Erstellung und Veröffentlichung des gekennzeichneten Inhalts eingesetzt wurde.", "de": "Diese UCNG Declaration beschreibt den angegebenen Entstehungs- und Transformationsprozess des deklarierten Inhalts. Sie dokumentiert, in welchen Bereichen KI beteiligt war, ohne Qualität oder Wahrheit des Inhalts zu bewerten.",
"en": "This declaration documents, in a transparent and traceable form, where artificial intelligence was used in creating and publishing the labelled content.", "en": "This UCNG Declaration describes the stated creation and transformation process of the declared content. It records where AI was involved without judging the quality or truth of the content.",
"fr": "Cette claration documente de manière transparente et traçable les domaines dans lesquels lintelligence artificielle a été utilisée pour créer et publier le contenu identifié.", "fr": "Cette UCNG Declaration décrit le processus déclaré de création et de transformation du contenu et documente les domaines dans lesquels lintelligence artificielle a été impliquée, sans juger la qualité ni la véracité du contenu.",
"es": "Esta declaración documenta de forma transparente y trazable en qué áreas se utilizó inteligencia artificial para crear y publicar el contenido identificado.", "es": "Esta UCNG Declaration describe el proceso declarado de creación y transformación del contenido y documenta dónde intervino la inteligencia artificial, sin juzgar la calidad ni la veracidad del contenido.",
"it": "La presente dichiarazione documenta in modo trasparente e tracciabile gli ambiti in cui lintelligenza artificiale è stata utilizzata per creare e pubblicare il contenuto indicato.", "it": "Questa UCNG Declaration descrive il processo dichiarato di creazione e trasformazione del contenuto e documenta dove è intervenuta lintelligenza artificiale, senza giudicare qualità o veridicità del contenuto.",
"nl": "Deze verklaring documenteert op transparante en navolgbare wijze op welke onderdelen kunstmatige intelligentie is gebruikt bij het maken en publiceren van de aangeduide inhoud.", "nl": "Deze UCNG Declaration beschrijft het gedeclareerde creatie- en transformatieproces en legt vast waar AI betrokken was, zonder de kwaliteit of waarheid van de inhoud te beoordelen.",
"pt": "Esta declaração documenta, de forma transparente e rastreável, as áreas em que a inteligência artificial foi utilizada na criação e publicação do conteúdo identificado.", "pt": "Esta UCNG Declaration descreve o processo declarado de criação e transformação do conteúdo e documenta onde a inteligência artificial esteve envolvida, sem avaliar a qualidade ou a veracidade do conteúdo.",
"pl": "Niniejsza deklaracja w przejrzysty i możliwy do prześledzenia sposób dokumentuje obszary, w których wykorzystano sztuczną inteligencję podczas tworzenia i publikacji oznaczonej treści.", "pl": "Ta UCNG Declaration opisuje zadeklarowany proces tworzenia i przekształcania treści oraz dokumentuje, gdzie uczestniczyła AI, bez oceniania jakości ani prawdziwości treści.",
} }
lang := locale.Code lang := locale.Code
if intro[lang] == "" { if intro[lang] == "" {
@@ -925,12 +925,12 @@ func declarationSummary(d declaration.Declaration, locale i18n.Locale) []string
} }
closing := map[string][]string{ closing := map[string][]string{
"de": { "de": {
"Sämtliche Angaben werden unter einem gemeinsamen Link veröffentlicht und stehen zusätzlich als maschinenlesbares JSON-LD zur Verfügung.", "Die Angaben werden unter einem gemeinsamen Link veröffentlicht und stehen zusätzlich als maschinenlesbares JSON-LD zur Verfügung.",
"Die Erklärung gibt die von der veröffentlichenden Person oder Organisation bereitgestellten Angaben wieder; eine rechtliche Einordnung erfolgt nicht automatisch.", "Die UCNG Declaration gibt bereitgestellte Angaben wieder. Sie bedeutet nicht automatisch verified, zertifiziert, authentisch, korrekt, wahr oder rechtskonform.",
}, },
"en": { "en": {
"All information is published under a single link and is also available as machine-readable JSON-LD.", "The declaration is published under a single link and is also available as machine-readable JSON-LD.",
"The declaration reflects the information supplied by the publishing person or organisation; it does not itself constitute a legal determination.", "The UCNG Declaration reflects supplied information. It does not automatically mean verified, certified, authentic, accurate, true or legally compliant.",
}, },
"fr": { "fr": {
"Toutes les informations sont publiées sous un lien unique et sont également disponibles au format JSON-LD lisible par machine.", "Toutes les informations sont publiées sous un lien unique et sont également disponibles au format JSON-LD lisible par machine.",
@@ -1021,15 +1021,15 @@ func componentSummaryStatement(locale i18n.Locale, name string, component declar
func germanExtentPhrase(extent string) string { func germanExtentPhrase(extent string) string {
switch extent { switch extent {
case "assisted": case "assisted":
return "eine KI-unterstützte Nutzung" return "AI ASSISTED (unterstützende KI-Nutzung)"
case "partial": case "partial":
return "eine teilweise KI-generierte Erstellung" return "MIXED (gemischte Entstehung mit teilweise KI-generierten Anteilen)"
case "mostly": case "mostly":
return "eine überwiegend KI-generierte Erstellung" return "AI GENERATED (überwiegend KI-generierte Erstellung)"
case "full": case "full":
return "eine vollständig KI-generierte Erstellung" return "AI GENERATED (KI-generierte Erstellung)"
default: default:
return "eine KI-Nutzung" return "eine dokumentierte KI-Rolle"
} }
} }

View File

@@ -36,7 +36,7 @@ func TestPresetBadgeFrench(t *testing.T) {
if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, "image/svg+xml") { if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, "image/svg+xml") {
t.Fatalf("content type %q", ct) t.Fatalf("content type %q", ct)
} }
if !strings.Contains(w.Body.String(), "Aide à la recherche") { if !strings.Contains(w.Body.String(), "AI ASSISTED") {
t.Fatal("missing localized preset") t.Fatal("missing localized preset")
} }
} }
@@ -90,7 +90,7 @@ func TestMarketingPageGerman(t *testing.T) {
t.Fatalf("status %d: %s", w.Code, w.Body.String()) t.Fatalf("status %d: %s", w.Code, w.Body.String())
} }
body := w.Body.String() body := w.Body.String()
for _, expected := range []string{"KI-Nutzung transparent kennzeichnen", "Docker Compose", "JSON-LD"} { for _, expected := range []string{"Declare how content was made.", "Docker Compose", "JSON-LD"} {
if !strings.Contains(body, expected) { if !strings.Contains(body, expected) {
t.Fatalf("marketing page missing %q", expected) t.Fatalf("marketing page missing %q", expected)
} }
@@ -105,7 +105,7 @@ func TestMarketingPageLanguageNegotiation(t *testing.T) {
if w.Code != http.StatusOK { if w.Code != http.StatusOK {
t.Fatalf("status %d: %s", w.Code, w.Body.String()) t.Fatalf("status %d: %s", w.Code, w.Body.String())
} }
if !strings.Contains(w.Body.String(), "Déclarez lusage de lIA") { if !strings.Contains(w.Body.String(), "Declare how content was made.") {
t.Fatal("missing French marketing content") t.Fatal("missing French marketing content")
} }
} }
@@ -183,7 +183,7 @@ func TestGeneratorExposesAssuranceSelection(t *testing.T) {
`value="technicallyRecorded"`, `value="technicallyRecorded"`,
`value="signed"`, `value="signed"`,
`value="verified"`, `value="verified"`,
`Nachweisgrundlage`, `Declaration Status`,
} { } {
if !strings.Contains(body, expected) { if !strings.Contains(body, expected) {
t.Fatalf("generator missing %q", expected) t.Fatalf("generator missing %q", expected)
@@ -201,7 +201,7 @@ func TestDeclarationUsesSelectedAssurance(t *testing.T) {
body := w.Body.String() body := w.Body.String()
for _, expected := range []string{ for _, expected := range []string{
`"assurance":"technicallyRecorded"`, `"assurance":"technicallyRecorded"`,
`Als Nachweisgrundlage ist eine technische Protokollierung im Erstellungs- oder Veröffentlichungsprozess angegeben.`, `Status: Declared; die Angaben sind zusätzlich technisch protokolliert. Daraus folgt keine automatische Verifikation.`,
`<colgroup>`, `<colgroup>`,
`scope="col"`, `scope="col"`,
} { } {
@@ -232,9 +232,9 @@ func TestBackgroundPageGerman(t *testing.T) {
} }
body := w.Body.String() body := w.Body.String()
for _, expected := range []string{ for _, expected := range []string{
"Warum KI-Nutzung gekennzeichnet wird", "Content needs context.",
"Artikel 50 gilt ab 2. August 2026", "Regulatorischer Kontext: EU AI Act, Artikel 50",
"keine allgemeine Kennzeichnungspflicht", "UCNG ist kein offizielles System der Europäischen Union",
"KI-generierter Text zu Angelegenheiten von öffentlichem Interesse", "KI-generierter Text zu Angelegenheiten von öffentlichem Interesse",
"Leitlinien zu Transparenzpflichten", "Leitlinien zu Transparenzpflichten",
`hreflang="en"`, `hreflang="en"`,
@@ -254,7 +254,7 @@ func TestBackgroundPageFrenchNegotiation(t *testing.T) {
if w.Code != http.StatusOK { if w.Code != http.StatusOK {
t.Fatalf("status %d: %s", w.Code, w.Body.String()) t.Fatalf("status %d: %s", w.Code, w.Body.String())
} }
if !strings.Contains(w.Body.String(), "Pourquoi signaler lutilisation de lIA") { if !strings.Contains(w.Body.String(), "Content needs context.") {
t.Fatal("missing French background content") t.Fatal("missing French background content")
} }
} }
@@ -283,7 +283,7 @@ func TestGeneratorExposesArticle50Context(t *testing.T) {
for _, expected := range []string{ for _, expected := range []string{
`id="public-interest-text"`, `id="deepfake"`, `id="substantial-review"`, `id="public-interest-text"`, `id="deepfake"`, `id="substantial-review"`,
`id="editorial-responsibility-confirmed"`, `id="first-exposure-disclosure"`, `id="editorial-responsibility-confirmed"`, `id="first-exposure-disclosure"`,
`Regulatorischer Kontext (EU AI Act, Artikel 50)`, `Optionaler regulatorischer Kontext (EU AI Act, Artikel 50)`,
} { } {
if !strings.Contains(w.Body.String(), expected) { if !strings.Contains(w.Body.String(), expected) {
t.Fatalf("generator missing %q", expected) t.Fatalf("generator missing %q", expected)
@@ -298,7 +298,7 @@ func TestArticle50AssessmentEndpoint(t *testing.T) {
if w.Code != http.StatusOK { if w.Code != http.StatusOK {
t.Fatalf("status %d: %s", w.Code, w.Body.String()) t.Fatalf("status %d: %s", w.Code, w.Body.String())
} }
for _, expected := range []string{`"code":"public_interest_text_disclosure_relevant"`, `"potentiallyApplicable":true`, `Nicht bindende Entscheidungshilfe`} { for _, expected := range []string{`"code":"public_interest_text_disclosure_relevant"`, `"potentiallyApplicable":true`, `Nicht bindende technische Entscheidungshilfe`} {
if !strings.Contains(w.Body.String(), expected) { if !strings.Contains(w.Body.String(), expected) {
t.Fatalf("assessment response missing %q: %s", expected, w.Body.String()) t.Fatalf("assessment response missing %q: %s", expected, w.Body.String())
} }
@@ -312,7 +312,7 @@ func TestRegulatoryDeclarationUsesExplicitBadge(t *testing.T) {
if w.Code != http.StatusOK { if w.Code != http.StatusOK {
t.Fatalf("status %d: %s", w.Code, w.Body.String()) t.Fatalf("status %d: %s", w.Code, w.Body.String())
} }
if !strings.Contains(w.Body.String(), "KI-generierter Text") || !strings.Contains(w.Body.String(), `fill="#b45309"`) { if !strings.Contains(w.Body.String(), "AI GENERATED") || !strings.Contains(w.Body.String(), `fill="#b45309"`) {
t.Fatalf("regulatory badge not explicit/amber: %s", w.Body.String()) t.Fatalf("regulatory badge not explicit/amber: %s", w.Body.String())
} }
} }
@@ -324,7 +324,7 @@ func TestDeclarationRendersRegulatoryAssessment(t *testing.T) {
if w.Code != http.StatusOK { if w.Code != http.StatusOK {
t.Fatalf("status %d: %s", w.Code, w.Body.String()) t.Fatalf("status %d: %s", w.Code, w.Body.String())
} }
for _, expected := range []string{`Technische Artikel-50-Einordnung`, `Mögliche Ausnahme für redaktionell kontrollierten Text`, `Example Redaktion`, `"regulatoryContext"`} { for _, expected := range []string{`Regulatorische Einordnung`, `Mögliche Ausnahme für redaktionell kontrollierten Text`, `Example Redaktion`, `"regulatoryContext"`} {
if !strings.Contains(w.Body.String(), expected) { if !strings.Contains(w.Body.String(), expected) {
t.Fatalf("declaration missing %q", expected) t.Fatalf("declaration missing %q", expected)
} }

View File

@@ -77,7 +77,148 @@ func Build(lang string) Page {
page = pages()["en"] page = pages()["en"]
} }
page.Sources = officialSources(lang) page.Sources = officialSources(lang)
return page return applyUCNGPositioning(page, lang)
}
func applyUCNGPositioning(p Page, lang string) Page {
switch lang {
case "de":
p.MetaDescription = "Hintergrund zu UCNG Content Declarations, Content-Transparenz und optionalem regulatorischem Kontext nach dem EU AI Act."
p.Eyebrow, p.Title = "UCNG · Content Transparency", "Content needs context."
p.Lead = "Digitale Inhalte entstehen heute auf unterschiedliche Weise: Menschen schreiben, Systeme unterstützen, Modelle generieren und Werkzeuge transformieren. UCNG schafft eine gemeinsame Sprache, mit der Inhalte ihren deklarierten Entstehungs- und Transformationskontext transparent machen können."
p.StatusKicker, p.StatusTitle = "Grundprinzip", "UCNG deklariert Herkunft. UCNG bewertet keine Wahrheit."
p.StatusText = "Eine UCNG Declaration beschreibt, wie ein Inhalt nach den bereitgestellten Angaben entstanden oder verändert worden ist. Sie ist kein Fact-Check, kein KI-Detektor und nicht automatisch eine Verifikation, Zertifizierung oder Feststellung rechtlicher Compliance."
p.ContentsTitle = "Auf dieser Seite"
p.Contents = []string{"Warum Content Kontext braucht", "Das UCNG Declaration System", "Regulatorischer Kontext: EU AI Act", "Declaration vs Verification", "Rolle dieser Referenzimplementierung", "Offizielle Quellen"}
p.OverviewTitle = "Warum Content Kontext braucht"
p.OverviewParagraphs = []string{
"Das Ergebnis eines digitalen Inhalts zeigt häufig nicht, welche Menschen, Werkzeuge oder generativen Systeme an seiner Entstehung beteiligt waren. UCNG setzt deshalb nicht bei einer Bewertung des Inhalts an, sondern beim deklarierten Entstehungskontext.",
"Die Leitidee lautet: Content should declare how it was made. Eine Declaration soll denselben Kontext sowohl für Menschen als auch in strukturierter, maschinenlesbarer Form verfügbar machen.",
"UCNG ist bewusst plattform-, medien-, anbieter- und jurisdiktionsunabhängig gedacht. Text, Bild, Audio, Video, Code und multimodale Inhalte können nach derselben Grundidee beschrieben werden.",
}
p.ScopeTitle = "Das UCNG Declaration System"
p.ScopeLead = "UCNG beschreibt Rollen und Prozesse statt vermeintlich exakter KI-Prozentwerte. Eine vollständige Declaration kann mehrere Dimensionen verbinden."
p.Obligations = []Card{
{Kicker: "Origin", Title: "Woher stammt der wesentliche Inhalt?", Description: "Die Herkunft kann beispielsweise als Human, AI, Mixed oder Unknown beschrieben werden."},
{Kicker: "AI Role", Title: "Welche Rolle hatte KI?", Description: "Die Rolle wird als None, Assist, Transform oder Generate beschrieben, statt einen schwer objektivierbaren Prozentwert zu behaupten."},
{Kicker: "Human Review", Title: "Welche menschliche Prüfung fand statt?", Description: "Eine Declaration kann unterscheiden, ob keine Prüfung, Review, Bearbeitung oder redaktionelle Verantwortung dokumentiert ist."},
{Kicker: "Source & Provenance", Title: "Wer deklariert und welche Herkunftsdaten existieren?", Description: "Declaration Source und Provenance schaffen zusätzlichen Kontext, ohne automatisch eine Verifikation zu behaupten."},
}
p.ArticleTitle = "Regulatorischer Kontext: EU AI Act, Artikel 50"
p.ArticleLead = "UCNG ist kein offizielles System der Europäischen Union und keine Compliance-Zertifizierung. Artikel 50 ist ein möglicher regulatorischer Kontext, in dem interoperable, sichtbare und maschinenlesbare Transparenzinformationen relevant sein können."
// Existing scenario details are retained because they describe the optional
// Article 50 decision-support context of this implementation.
p.RequirementsTitle = "Declaration ist nicht Verification"
p.RequirementsLead = "Die UCNG Guidelines unterscheiden terminologisch zwischen einer abgegebenen Erklärung und einer zusätzlichen Prüfung. Diese Ebenen dürfen nicht synonym verwendet werden."
p.Principles = []Card{
{Kicker: "Declared", Title: "Eine Angabe wurde deklariert", Description: "Jemand hat Informationen zum Entstehungsprozess bereitgestellt. Das ist die Grundbedeutung einer UCNG Declaration."},
{Kicker: "Attested", Title: "Eine identifizierbare Stelle übernimmt Verantwortung", Description: "Attestation bedeutet mehr als eine bloße Declaration und muss als eigene Ebene kenntlich gemacht werden."},
{Kicker: "Verified", Title: "Bestimmte Angaben wurden überprüft", Description: "Verified darf nur verwendet werden, wenn konkrete Angaben technisch oder organisatorisch nach einem dokumentierten Verfahren geprüft wurden."},
{Kicker: "Nicht impliziert", Title: "Kein Wahrheits- oder Compliance-Siegel", Description: "Ein UCNG Badge bedeutet nicht automatisch true, safe, fact checked, copyright cleared, EU compliant oder certified."},
}
p.ProjectTitle = "Wie diese Referenzimplementierung einzuordnen ist"
p.ProjectParagraphs = []string{
"Diese Anwendung setzt die UCNG-Idee praktisch um: Aus strukturierten Angaben entstehen eine menschenlesbare Declaration, ein kompaktes Badge und eine maschinenlesbare JSON-LD-Darstellung. Ein gemeinsamer Link kann die Angaben für einzelne Inhalte oder mehrere Content-Bestandteile zusammenführen.",
"Die aktuelle technische Schema-Version der Anwendung wird durch diese Textfassung nicht verändert. Deshalb werden keine neuen Datenklassen künstlich eingeführt. Die formale UCNG Specification und ihre Versionierung sollten wie in den Guidelines vorgesehen getrennt vom Branding und von dieser Referenzimplementierung weiterentwickelt werden.",
}
p.ProjectItems = []string{
"Human-readable Declaration und Machine Layer aus denselben Angaben",
"Komponentenbezogene Angaben für Text, Bild, Recherche, Übersetzung, Audio, Video und Code",
"Kompaktes UCNG Badge als Einstieg in die ausführliche Declaration",
"Optionaler regulatorischer Kontext getrennt von der UCNG-Kernaussage",
"Keine automatische Verifikation, Zertifizierung, Wahrheitsbewertung oder Feststellung rechtlicher Compliance",
}
p.SourcesTitle = "Regulatorischer Kontext: offizielle EU-Quellen"
p.SourcesLead = "Die folgenden Quellen gehören zum optionalen EU-AI-Act-Kontext dieser Anwendung. Sie definieren UCNG nicht und machen UCNG nicht zu einem offiziellen System der Europäischen Union."
p.DisclaimerTitle = "Wichtiger Hinweis"
p.DisclaimerText = "UCNG ist eine unabhängige offene Initiative und weder Institution, Behörde noch offizielles Zertifizierungssystem der Europäischen Union. UCNG Declarations informieren über den deklarierten Erstellungs- und Transformationsprozess von Inhalten. Eine UCNG Declaration begründet für sich allein keine Rechtskonformität, Authentizität, Genauigkeit oder Wahrhaftigkeit."
p.CTATitle, p.CTALead, p.CTAButton = "Declare how content was made.", "Erstelle eine UCNG Declaration und mache den angegebenen Entstehungskontext für Menschen und Maschinen lesbar.", "Declaration erstellen"
p.Footer = "UCNG · Content transparency · Keine Rechtsberatung"
case "en":
p.MetaDescription = "Background on UCNG content declarations, content transparency and optional EU AI Act regulatory context."
p.Eyebrow, p.Title = "UCNG · Content Transparency", "Content needs context."
p.Lead = "Digital content is created in many ways: humans write, systems assist, models generate and tools transform. UCNG provides a common language for making the declared creation and transformation context of content transparent."
p.StatusKicker, p.StatusTitle = "Core principle", "UCNG declares origin. UCNG does not judge truth."
p.StatusText = "A UCNG Declaration describes how content was created or transformed according to the information supplied. It is not a fact-check, AI detector, automatic verification, certification or finding of legal compliance."
p.Contents = []string{"Why content needs context", "The UCNG Declaration System", "Regulatory context: EU AI Act", "Declaration vs verification", "Role of this reference implementation", "Official sources"}
p.OverviewTitle = "Why content needs context"
p.OverviewParagraphs = []string{"The finished content often does not reveal which people, tools or generative systems shaped it. UCNG therefore focuses on the declared creation context rather than judging the content itself.", "The guiding idea is simple: Content should declare how it was made. The same context should be understandable to people and available in a structured machine-readable form.", "UCNG is intended to be platform-, media-, vendor- and jurisdiction-independent. Text, image, audio, video, code and multimodal content can follow the same basic declaration model."}
p.ScopeTitle = "The UCNG Declaration System"
p.ScopeLead = "UCNG describes roles and processes rather than claiming precise AI percentages. A full declaration can combine several dimensions."
p.Obligations = []Card{{Kicker: "Origin", Title: "Where does the substantial content come from?", Description: "Origin can be described as Human, AI, Mixed or Unknown."}, {Kicker: "AI Role", Title: "What role did AI play?", Description: "The role is described as None, Assist, Transform or Generate rather than as a hard-to-define percentage."}, {Kicker: "Human Review", Title: "What human review took place?", Description: "A declaration can distinguish review, editing and editorial responsibility."}, {Kicker: "Source & Provenance", Title: "Who declares, and what provenance exists?", Description: "Declaration source and provenance add context without automatically claiming verification."}}
p.ArticleTitle = "Regulatory context: EU AI Act, Article 50"
p.ArticleLead = "UCNG is not an official European Union system or a compliance certification. Article 50 is one regulatory context in which interoperable, visible and machine-readable transparency information may be relevant."
p.RequirementsTitle = "Declaration is not verification"
p.RequirementsLead = "The UCNG Guidelines distinguish terminology for a declaration and for additional checking. These levels must not be treated as synonyms."
p.Principles = []Card{{Kicker: "Declared", Title: "Information has been declared", Description: "Someone supplied information about the creation process. This is the basic meaning of a UCNG Declaration."}, {Kicker: "Attested", Title: "An identifiable organisation assumes responsibility", Description: "Attestation is a separate level beyond a declaration and should be identified as such."}, {Kicker: "Verified", Title: "Specified information has been checked", Description: "Verified should only be used when particular claims have been technically or organisationally checked under a documented procedure."}, {Kicker: "Not implied", Title: "No truth or compliance seal", Description: "A UCNG badge does not automatically mean true, safe, fact checked, copyright cleared, EU compliant or certified."}}
p.ProjectTitle = "How to understand this reference implementation"
p.ProjectParagraphs = []string{"This application implements the UCNG idea in practice: structured inputs generate a human-readable declaration, a compact badge and a machine-readable JSON-LD representation. One shared link can combine information for single or multi-component content.", "This content revision does not change the application's current technical schema. No new data classes are invented in copy. As described in the Guidelines, the formal UCNG Specification and its versioning should evolve separately from branding and this reference implementation."}
p.ProjectItems = []string{"Human-readable declaration and machine layer from the same data", "Component-level details for text, image, research, translation, audio, video and code", "Compact UCNG badge as an entry point to the full declaration", "Optional regulatory context kept separate from the core UCNG claim", "No automatic verification, certification, truth assessment or finding of legal compliance"}
p.SourcesTitle = "Regulatory context: official EU sources"
p.SourcesLead = "The following sources belong to the optional EU AI Act context of this application. They do not define UCNG or make UCNG an official European Union system."
p.DisclaimerTitle = "Important notice"
p.DisclaimerText = "UCNG is an independent open initiative and is not an institution, agency or official certification scheme of the European Union. UCNG declarations provide information about the declared creation and transformation process of content. A UCNG declaration does not by itself establish legal compliance, authenticity, accuracy or truthfulness."
p.CTATitle, p.CTALead, p.CTAButton = "Declare how content was made.", "Create a UCNG Declaration and make the stated creation context readable to people and machines.", "Create a declaration"
p.Footer = "UCNG · Content transparency · Not legal advice"
default:
// Keep detailed legal copy in the existing translation, while moving the
// top-level framing and project identity to UCNG.
p.Title = "Content needs context."
p.StatusTitle = "UCNG does not judge content. UCNG describes how content was created."
p.ProjectTitle = "UCNG · Universal Content Notation Guidelines"
p.Footer = "UCNG · Universal Content Notation Guidelines"
switch lang {
case "fr":
p.Eyebrow = "UCNG · Transparence des contenus"
p.Lead = "UCNG fournit un langage commun pour déclarer comment un contenu numérique a été créé ou transformé, lisible par les personnes et par les machines."
p.ProjectParagraphs = []string{"Cette implémentation de référence transforme des informations structurées en UCNG Declaration lisible, badge compact et représentation JSON-LD lisible par machine.", "Le contexte réglementaire reste séparé de la déclaration UCNG. Le logiciel ne constitue ni une certification, ni un fact-check, ni une décision juridique."}
p.ProjectItems = []string{"Déclaration lisible par les personnes et couche lisible par machine", "Informations par composant pour texte, image, recherche, traduction, audio, vidéo et code", "Badge UCNG compact donnant accès à la déclaration détaillée", "Contexte réglementaire facultatif séparé de lénoncé central UCNG", "Aucune vérification, certification ou conclusion de conformité juridique automatique"}
p.CTATitle, p.CTALead = "Declare how content was made.", "Créez une UCNG Declaration et rendez le contexte de création déclaré lisible par les personnes et les machines."
p.DisclaimerText = "UCNG est une initiative ouverte et indépendante, et non un organisme ni un système officiel de certification de lUnion européenne. Une UCNG Declaration nétablit pas à elle seule la conformité juridique, lauthenticité, lexactitude ou la véracité."
p.CTAButton = "Créer une déclaration"
case "es":
p.Eyebrow = "UCNG · Transparencia del contenido"
p.Lead = "UCNG ofrece un lenguaje común para declarar cómo se creó o transformó contenido digital, comprensible para personas y legible por máquinas."
p.ProjectParagraphs = []string{"Esta implementación de referencia convierte datos estructurados en una UCNG Declaration legible, un badge compacto y una representación JSON-LD legible por máquinas.", "El contexto regulatorio se mantiene separado de la declaración UCNG. El software no es una certificación, un fact-check ni una decisión jurídica."}
p.ProjectItems = []string{"Declaración legible por personas y capa legible por máquinas", "Datos por componente para texto, imagen, investigación, traducción, audio, vídeo y código", "Badge UCNG compacto como acceso a la declaración detallada", "Contexto regulatorio opcional separado de la afirmación central de UCNG", "Sin verificación, certificación ni determinación automática de cumplimiento legal"}
p.CTATitle, p.CTALead = "Declare how content was made.", "Crea una UCNG Declaration y haz que el contexto de creación declarado sea legible para personas y máquinas."
p.DisclaimerText = "UCNG es una iniciativa abierta e independiente y no es un organismo ni un sistema oficial de certificación de la Unión Europea. Una UCNG Declaration no establece por sí sola cumplimiento legal, autenticidad, exactitud o veracidad."
p.CTAButton = "Crear una declaración"
case "it":
p.Eyebrow = "UCNG · Trasparenza dei contenuti"
p.Lead = "UCNG offre un linguaggio comune per dichiarare come i contenuti digitali sono stati creati o trasformati, comprensibile alle persone e leggibile dalle macchine."
p.ProjectParagraphs = []string{"Questa implementazione di riferimento trasforma dati strutturati in una UCNG Declaration leggibile, un badge compatto e una rappresentazione JSON-LD leggibile dalle macchine.", "Il contesto normativo resta separato dalla dichiarazione UCNG. Il software non è una certificazione, un fact-check o una decisione giuridica."}
p.ProjectItems = []string{"Dichiarazione leggibile dalle persone e machine layer", "Informazioni per componente per testo, immagine, ricerca, traduzione, audio, video e codice", "Badge UCNG compatto come accesso alla dichiarazione completa", "Contesto normativo opzionale separato dallaffermazione centrale UCNG", "Nessuna verifica, certificazione o determinazione automatica di conformità legale"}
p.CTATitle, p.CTALead = "Declare how content was made.", "Crea una UCNG Declaration e rendi il contesto di creazione dichiarato leggibile da persone e macchine."
p.DisclaimerText = "UCNG è uniniziativa aperta e indipendente e non è un organismo né un sistema ufficiale di certificazione dellUnione europea. Una UCNG Declaration non stabilisce da sola conformità legale, autenticità, accuratezza o veridicità."
p.CTAButton = "Crea una dichiarazione"
case "nl":
p.Eyebrow = "UCNG · Contenttransparantie"
p.Lead = "UCNG biedt een gemeenschappelijke taal om te verklaren hoe digitale inhoud is gemaakt of getransformeerd, leesbaar voor mensen en machines."
p.ProjectParagraphs = []string{"Deze referentie-implementatie zet gestructureerde gegevens om in een leesbare UCNG Declaration, een compacte badge en een machineleesbare JSON-LD-weergave.", "De regelgevingscontext blijft gescheiden van de UCNG-declaratie. De software is geen certificering, factcheck of juridische beslissing."}
p.ProjectItems = []string{"Menselijk leesbare declaratie en machineleesbare laag", "Informatie per component voor tekst, beeld, onderzoek, vertaling, audio, video en code", "Compacte UCNG-badge als toegang tot de volledige declaratie", "Optionele regelgevingscontext gescheiden van de kernclaim van UCNG", "Geen automatische verificatie, certificering of juridische conformiteitsvaststelling"}
p.CTATitle, p.CTALead = "Declare how content was made.", "Maak een UCNG Declaration en maak de gedeclareerde creatiecontext leesbaar voor mensen en machines."
p.DisclaimerText = "UCNG is een onafhankelijk open initiatief en geen instantie of officieel certificeringsstelsel van de Europese Unie. Een UCNG Declaration stelt op zichzelf geen juridische naleving, authenticiteit, nauwkeurigheid of waarheid vast."
p.CTAButton = "Maak een declaratie"
case "pt":
p.Eyebrow = "UCNG · Transparência de conteúdos"
p.Lead = "UCNG oferece uma linguagem comum para declarar como conteúdos digitais foram criados ou transformados, compreensível para pessoas e legível por máquinas."
p.ProjectParagraphs = []string{"Esta implementação de referência transforma dados estruturados numa UCNG Declaration legível, num badge compacto e numa representação JSON-LD legível por máquinas.", "O contexto regulamentar permanece separado da declaração UCNG. O software não constitui certificação, fact-check nem decisão jurídica."}
p.ProjectItems = []string{"Declaração legível por pessoas e camada legível por máquinas", "Informação por componente para texto, imagem, pesquisa, tradução, áudio, vídeo e código", "Badge UCNG compacto como acesso à declaração completa", "Contexto regulamentar opcional separado da afirmação central da UCNG", "Sem verificação, certificação ou determinação automática de conformidade legal"}
p.CTATitle, p.CTALead = "Declare how content was made.", "Crie uma UCNG Declaration e torne o contexto de criação declarado legível para pessoas e máquinas."
p.DisclaimerText = "UCNG é uma iniciativa aberta e independente e não é uma instituição nem um sistema oficial de certificação da União Europeia. Uma UCNG Declaration não estabelece, por si só, conformidade legal, autenticidade, exatidão ou veracidade."
p.CTAButton = "Criar uma declaração"
case "pl":
p.Eyebrow = "UCNG · Przejrzystość treści"
p.Lead = "UCNG zapewnia wspólny język do deklarowania, jak treści cyfrowe zostały utworzone lub przekształcone, czytelny dla ludzi i maszyn."
p.ProjectParagraphs = []string{"Ta implementacja referencyjna przekształca ustrukturyzowane dane w czytelną UCNG Declaration, kompaktowy badge oraz maszynowo czytelną reprezentację JSON-LD.", "Kontekst regulacyjny pozostaje oddzielony od deklaracji UCNG. Oprogramowanie nie jest certyfikacją, fact-checkiem ani decyzją prawną."}
p.ProjectItems = []string{"Deklaracja czytelna dla ludzi i warstwa maszynowa", "Informacje według komponentów dla tekstu, obrazu, badań, tłumaczenia, audio, wideo i kodu", "Kompaktowy badge UCNG jako wejście do pełnej deklaracji", "Opcjonalny kontekst regulacyjny oddzielony od głównego komunikatu UCNG", "Brak automatycznej weryfikacji, certyfikacji lub stwierdzenia zgodności prawnej"}
p.CTATitle, p.CTALead = "Declare how content was made.", "Utwórz UCNG Declaration i udostępnij deklarowany kontekst tworzenia w formie czytelnej dla ludzi i maszyn."
p.DisclaimerText = "UCNG jest niezależną otwartą inicjatywą, a nie instytucją ani oficjalnym systemem certyfikacji Unii Europejskiej. Sama UCNG Declaration nie potwierdza zgodności prawnej, autentyczności, dokładności ani prawdziwości."
p.CTAButton = "Utwórz deklarację"
}
}
return p
} }
func normalize(lang string) string { func normalize(lang string) string {

View File

@@ -42,7 +42,7 @@ func TestGermanPageDistinguishesLegalAndVoluntaryDisclosure(t *testing.T) {
func TestUnknownLanguageFallsBackToEnglish(t *testing.T) { func TestUnknownLanguageFallsBackToEnglish(t *testing.T) {
page := Build("xx") page := Build("xx")
if page.Title != "Why AI use is disclosed" { if page.Title != "Content needs context." {
t.Fatalf("unexpected fallback title %q", page.Title) t.Fatalf("unexpected fallback title %q", page.Title)
} }
} }

View File

@@ -27,7 +27,7 @@ var extentColors = map[string]string{
func Render(o Options) ([]byte, string) { func Render(o Options) ([]byte, string) {
label := truncate(strings.TrimSpace(o.Label), 40) label := truncate(strings.TrimSpace(o.Label), 40)
if label == "" { if label == "" {
label = "AI use" label = "UCNG"
} }
message := truncate(strings.TrimSpace(o.Message), 80) message := truncate(strings.TrimSpace(o.Message), 80)
if message == "" { if message == "" {

View File

@@ -137,6 +137,7 @@ func init() {
applyAssuranceTranslations() applyAssuranceTranslations()
applyArticle50Translations() applyArticle50Translations()
applyBulkTranslations() applyBulkTranslations()
applyUCNGBrandCopy()
} }
func applyArticleTranslations() { func applyArticleTranslations() {
@@ -597,6 +598,204 @@ func Resolve(explicit, acceptLanguage, fallback string) string {
return "en" return "en"
} }
// applyUCNGBrandCopy aligns the public wording with the UCNG Brand & Identity
// Guidelines without changing the declaration schema or API semantics.
func applyUCNGBrandCopy() {
type brandCopy struct {
text map[string]string
presets map[string]PresetText
extents map[string]string
assurances map[string]string
}
copies := map[string]brandCopy{
"de": {
text: map[string]string{
"meta_description": "UCNG ist ein offenes Notationssystem für transparente, menschen- und maschinenlesbare Content-Deklarationen.",
"standard_eyebrow": "UCNG · Universal Content Notation Guidelines",
"hero_title": "Declare how content was made.",
"hero_lead": "UCNG ist ein offenes Notationssystem für transparente Content-Deklarationen verständlich für Menschen und maschinenlesbar für Plattformen und Systeme. Diese Anwendung erzeugt Declaration, Badge und JSON-LD aus denselben Angaben.",
"generator_eyebrow": "UCNG Declaration",
"generator_title": "Content-Deklaration erstellen",
"generator_intro": "Wähle eine Vorlage oder beschreibe den Entstehungskontext eines Inhalts strukturiert nach Bestandteilen. Die Declaration dokumentiert Rollen und Prozesse einschließlich KI-Beteiligung ohne Qualität oder Wahrheit des Inhalts zu bewerten.",
"field_mode": "Art der Declaration", "mode_single": "Einzelner Inhalt", "mode_article": "Mehrteiligen Inhalt deklarieren",
"field_preset": "Declaration-Vorlage", "option_custom": "Eigene Struktur", "field_component": "Content-Bestandteil", "field_extent": "UCNG Einordnung", "field_review": "Human Review",
"field_activities": "Rolle / Tätigkeit", "activities_help": "Optionale Prozessangaben, zum Beispiel research, summarisation, translation oder generation.",
"field_subject": "URL des deklarierten Inhalts", "field_language": "Sprache der Declaration",
"declaration_eyebrow": "UCNG Declaration", "fact_component": "Content", "fact_extent": "UCNG Einordnung", "fact_activities": "Rolle / Tätigkeit", "fact_review": "Human Review", "fact_subject": "Deklarierter Inhalt",
"fact_assurance": "Declaration Status", "field_assurance": "Declaration Status",
"transparency_label": "Zur Einordnung:",
"transparency_text": "Diese UCNG Declaration beschreibt den deklarierten Entstehungs- und Transformationsprozess des Inhalts. Sie bewertet weder Wahrheit noch Qualität und begründet für sich allein keine Rechtskonformität, Authentizität, Genauigkeit oder Verifikation.",
"manifest": "Maschinenlesbare Declaration", "ai_label": "UCNG",
"api_badge_title": "UCNG Badge", "api_badge_desc": "Das Badge ist die kompakte Darstellung einer UCNG Declaration. Es zeigt, dass eine Declaration verfügbar ist; es bedeutet nicht automatisch verified, zertifiziert oder rechtskonform.",
"api_manifest_title": "Machine Layer", "api_manifest_desc": "Die strukturierte JSON-LD-Darstellung transportiert dieselben Deklarationsdaten maschinenlesbar für Plattformen, Systeme und Build-Prozesse.",
"article_fields": "Content-Bestandteile", "article_help": "Deklariere für jeden Bestandteil, wie er entstanden oder verändert worden ist und welche Rolle KI dabei hatte.",
"article_title": "UCNG Content Declaration", "article_summary_heading": "Human-readable Declaration", "article_table_heading": "Declaration Details", "table_component": "Content", "table_extent": "UCNG Einordnung", "table_activities": "Rolle / Tätigkeit", "table_review": "Human Review", "badge_article": "DECLARATION",
"component_text": "Text", "component_research": "Recherche", "component_cover_image": "Titelbild", "component_images": "Bilder", "component_translation": "Übersetzung", "component_audio": "Audio", "component_video": "Video", "component_code": "Code",
"regulatory_api_label": "Regulatorischer Kontext API",
"article50_section_title": "Optionaler regulatorischer Kontext (EU AI Act, Artikel 50)",
"article50_section_intro": "Diese optionalen Angaben dokumentieren Tatsachen, die für Transparenzpflichten nach Artikel 50 relevant sein können. Sie sind eine technische Entscheidungshilfe und nicht Teil der UCNG-Kernaussage oder eine Rechtsberatung.",
"assessment_heading": "Regulatorische Einordnung", "assessment_disclaimer": "Nicht bindende technische Entscheidungshilfe. Eine UCNG Declaration ist keine Feststellung rechtlicher Compliance.",
"assessment_not_assessed_text": "Die UCNG Declaration enthält keinen zusätzlichen regulatorischen Kontext nach Artikel 50.",
"badge_article50_deepfake": "AI TRANSFORMED", "badge_article50_text": "AI GENERATED",
"bulk_meta_description": "Stapelverarbeitung für strukturierte UCNG Content Declarations.",
"bulk_title": "Viele Inhalte. Eine gemeinsame Deklarationssprache.",
"bulk_intro": "Erzeuge strukturierte UCNG Declarations für ganze Content-Bestände. Ein gemeinsames Profil kann auf viele URLs angewendet oder als individuelles JSON verarbeitet werden.",
"bulk_workspace_intro": "Füge Inhalte zeilenweise ein und definiere ihren gemeinsamen Entstehungskontext einmal. Abweichende Datensätze können im erweiterten JSON-Modus verarbeitet werden.",
"bulk_profile_title": "Gemeinsames Declaration-Profil", "bulk_article50_title": "Optionaler regulatorischer Kontext / Artikel 50", "bulk_link_declaration": "UCNG Declaration",
},
presets: map[string]PresetText{
"no-ai": {"HUMAN", "Der wesentliche Inhalt wurde von Menschen erstellt. Normale technische Hilfsmittel und nicht-generative Standardbearbeitung ändern diese Einordnung nicht automatisch."},
"research": {"AI ASSISTED", "KI wurde unterstützend für Recherche oder Quellenfindung eingesetzt. Der wesentliche kreative beziehungsweise redaktionelle Inhalt stammt von Menschen und wurde menschlich verantwortet."},
"summary": {"AI ASSISTED", "KI wurde unterstützend zur Zusammenfassung von Ausgangsmaterial eingesetzt. Auswahl, Einordnung und Endfassung wurden von Menschen verantwortet."},
"full": {"AI GENERATED", "Der wesentliche Inhalt wurde mit einem generativen KI-System erzeugt. Eine dokumentierte menschliche Prüfung wird separat ausgewiesen."},
},
extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · teilweise generiert", "mostly": "AI GENERATED · überwiegend", "full": "AI GENERATED"},
assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · technisch protokolliert", "signed": "Declared · signiert", "verified": "Verified"},
},
"en": {
text: map[string]string{
"meta_description": "UCNG is an open notation framework for transparent, human-readable and machine-readable content declarations.",
"standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.",
"hero_lead": "UCNG is an open notation framework for transparent content declarations readable by humans and machine-readable for platforms and systems. This application generates the declaration, badge and JSON-LD from the same information.",
"generator_eyebrow": "UCNG Declaration", "generator_title": "Create a content declaration", "generator_intro": "Choose a preset or describe the creation context of content by component. The declaration records roles and processes, including AI involvement, without judging the quality or truth of the content.",
"field_mode": "Declaration type", "mode_single": "Single content item", "mode_article": "Declare multi-part content", "field_preset": "Declaration preset", "option_custom": "Custom structure", "field_component": "Content component", "field_extent": "UCNG classification", "field_review": "Human review", "field_activities": "Role / activity", "field_subject": "URL of declared content", "field_language": "Declaration language",
"declaration_eyebrow": "UCNG Declaration", "fact_component": "Content", "fact_extent": "UCNG classification", "fact_activities": "Role / activity", "fact_review": "Human review", "fact_subject": "Declared content", "fact_assurance": "Declaration status", "field_assurance": "Declaration status",
"transparency_label": "About this declaration:", "transparency_text": "This UCNG Declaration describes the declared creation and transformation process of the content. It does not judge truth or quality and does not by itself establish legal compliance, authenticity, accuracy or verification.",
"manifest": "Machine-readable declaration", "ai_label": "UCNG",
"api_badge_title": "UCNG badge", "api_badge_desc": "The badge is the compact representation of a UCNG Declaration. It indicates that a declaration exists; it does not automatically mean verified, certified or legally compliant.",
"api_manifest_title": "Machine layer", "api_manifest_desc": "The structured JSON-LD representation carries the same declaration data in a machine-readable form for platforms, systems and build workflows.",
"article_fields": "Content components", "article_help": "For each component, declare how it was created or transformed and what role AI played.", "article_title": "UCNG Content Declaration", "article_summary_heading": "Human-readable declaration", "article_table_heading": "Declaration details", "table_component": "Content", "table_extent": "UCNG classification", "table_activities": "Role / activity", "table_review": "Human review", "badge_article": "DECLARATION",
"component_text": "Text", "component_research": "Research", "component_cover_image": "Cover image", "component_images": "Images", "component_translation": "Translation", "component_audio": "Audio", "component_video": "Video", "component_code": "Code", "regulatory_api_label": "Regulatory context API",
"article50_section_title": "Optional regulatory context (EU AI Act, Article 50)", "article50_section_intro": "These optional fields record facts that may be relevant to Article 50 transparency obligations. They are technical decision support, not the core UCNG claim and not legal advice.",
"assessment_heading": "Regulatory context", "assessment_disclaimer": "Non-binding technical decision support. A UCNG Declaration is not a finding of legal compliance.", "assessment_not_assessed_text": "The UCNG Declaration contains no additional Article 50 regulatory context.", "badge_article50_deepfake": "AI TRANSFORMED", "badge_article50_text": "AI GENERATED",
"bulk_meta_description": "Batch processing for structured UCNG content declarations.", "bulk_title": "Many items. One common declaration language.", "bulk_intro": "Generate structured UCNG Declarations for complete content inventories. Apply one shared profile to many URLs or process individual records as JSON.", "bulk_workspace_intro": "Paste content line by line and define its shared creation context once. Records that differ can be processed through advanced JSON mode.", "bulk_profile_title": "Shared declaration profile", "bulk_article50_title": "Optional regulatory context / Article 50", "bulk_link_declaration": "UCNG Declaration",
},
presets: map[string]PresetText{
"no-ai": {"HUMAN", "The substantial content was created by a human. Ordinary technical tools and non-generative standard editing do not automatically change this classification."},
"research": {"AI ASSISTED", "AI was used to assist research or source discovery. The substantial creative or editorial content remained human-created and human-responsible."},
"summary": {"AI ASSISTED", "AI was used to assist with summarising source material. Selection, contextual assessment and the final version remained under human responsibility."},
"full": {"AI GENERATED", "The substantial content was generated by a generative AI system. Any documented human review is stated separately."},
},
extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · partly generated", "mostly": "AI GENERATED · mostly", "full": "AI GENERATED"},
assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · technically recorded", "signed": "Declared · signed", "verified": "Verified"},
},
}
// Localised UI copy. The UCNG class names remain English by design so the
// compact labels travel consistently across languages.
local := map[string]brandCopy{
"fr": {text: map[string]string{"meta_description": "UCNG est un cadre de notation ouvert pour des déclarations de contenu transparentes, lisibles par lhumain et la machine.", "standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.", "hero_lead": "UCNG fournit un langage commun pour déclarer comment un contenu numérique a été créé ou transformé, lisible par les personnes et par les machines.", "generator_eyebrow": "UCNG Declaration", "generator_title": "Créer une déclaration de contenu", "generator_intro": "Décrivez le contexte de création par composant, y compris le rôle de lIA, sans juger la qualité ni la véracité du contenu.", "field_extent": "Classification UCNG", "fact_extent": "Classification UCNG", "table_extent": "Classification UCNG", "field_subject": "URL du contenu déclaré", "fact_subject": "Contenu déclaré", "declaration_eyebrow": "UCNG Declaration", "transparency_label": "À propos de cette déclaration :", "transparency_text": "Cette UCNG Declaration décrit le processus déclaré de création et de transformation du contenu. Elle ne constitue pas à elle seule une vérification, une certification, une preuve dauthenticité, dexactitude, de vérité ou de conformité juridique.", "ai_label": "UCNG", "article_title": "UCNG Content Declaration", "article_summary_heading": "Déclaration lisible par lhumain", "article_table_heading": "Détails de la déclaration", "badge_article": "DECLARATION", "assessment_heading": "Contexte réglementaire", "component_text": "Texte", "component_research": "Recherche", "component_cover_image": "Image de couverture", "component_images": "Images", "component_translation": "Traduction", "component_audio": "Audio", "component_video": "Vidéo", "component_code": "Code", "regulatory_api_label": "API de contexte réglementaire"}, presets: map[string]PresetText{"no-ai": {"HUMAN", "Le contenu substantiel a été créé par une personne."}, "research": {"AI ASSISTED", "LIA a été utilisée comme assistance à la recherche; le contenu substantiel reste dorigine humaine."}, "summary": {"AI ASSISTED", "LIA a assisté la synthèse; la sélection et la version finale restent sous responsabilité humaine."}, "full": {"AI GENERATED", "Le contenu substantiel a été produit par un système dIA générative; le contrôle humain est indiqué séparément."}}, extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · partiellement généré", "mostly": "AI GENERATED · majoritairement", "full": "AI GENERATED"}, assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · enregistré techniquement", "signed": "Declared · signé", "verified": "Verified"}},
"es": {text: map[string]string{"meta_description": "UCNG es un marco abierto de notación para declaraciones de contenido transparentes, legibles por personas y máquinas.", "standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.", "hero_lead": "UCNG ofrece un lenguaje común para declarar cómo se creó o transformó contenido digital, comprensible para personas y legible por máquinas.", "generator_eyebrow": "UCNG Declaration", "generator_title": "Crear una declaración de contenido", "generator_intro": "Describe el contexto de creación por componente, incluido el papel de la IA, sin juzgar la calidad ni la veracidad del contenido.", "field_extent": "Clasificación UCNG", "fact_extent": "Clasificación UCNG", "table_extent": "Clasificación UCNG", "field_subject": "URL del contenido declarado", "fact_subject": "Contenido declarado", "declaration_eyebrow": "UCNG Declaration", "transparency_label": "Sobre esta declaración:", "transparency_text": "Esta UCNG Declaration describe el proceso declarado de creación y transformación del contenido. Por sí sola no establece verificación, certificación, autenticidad, exactitud, veracidad ni cumplimiento legal.", "ai_label": "UCNG", "article_title": "UCNG Content Declaration", "article_summary_heading": "Declaración legible por personas", "article_table_heading": "Detalles de la declaración", "badge_article": "DECLARATION", "assessment_heading": "Contexto regulatorio", "component_text": "Texto", "component_research": "Investigación", "component_cover_image": "Imagen de portada", "component_images": "Imágenes", "component_translation": "Traducción", "component_audio": "Audio", "component_video": "Vídeo", "component_code": "Código", "regulatory_api_label": "API de contexto regulatorio"}, presets: map[string]PresetText{"no-ai": {"HUMAN", "El contenido sustancial fue creado por una persona."}, "research": {"AI ASSISTED", "La IA se utilizó como apoyo a la investigación; el contenido sustancial sigue siendo de origen humano."}, "summary": {"AI ASSISTED", "La IA ayudó a resumir material; la selección y la versión final permanecen bajo responsabilidad humana."}, "full": {"AI GENERATED", "El contenido sustancial fue generado por un sistema de IA generativa; la revisión humana se indica por separado."}}, extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · parcialmente generado", "mostly": "AI GENERATED · mayoritariamente", "full": "AI GENERATED"}, assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · registrado técnicamente", "signed": "Declared · firmado", "verified": "Verified"}},
"it": {text: map[string]string{"meta_description": "UCNG è un framework di notazione aperto per dichiarazioni trasparenti, leggibili da persone e macchine.", "standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.", "hero_lead": "UCNG offre un linguaggio comune per dichiarare come i contenuti digitali sono stati creati o trasformati, comprensibile alle persone e leggibile dalle macchine.", "generator_eyebrow": "UCNG Declaration", "generator_title": "Crea una dichiarazione del contenuto", "generator_intro": "Descrivi il contesto di creazione per componente, incluso il ruolo dellIA, senza giudicare qualità o veridicità del contenuto.", "field_extent": "Classificazione UCNG", "fact_extent": "Classificazione UCNG", "table_extent": "Classificazione UCNG", "field_subject": "URL del contenuto dichiarato", "fact_subject": "Contenuto dichiarato", "declaration_eyebrow": "UCNG Declaration", "transparency_label": "Informazioni sulla dichiarazione:", "transparency_text": "Questa UCNG Declaration descrive il processo dichiarato di creazione e trasformazione del contenuto. Da sola non stabilisce verifica, certificazione, autenticità, accuratezza, veridicità o conformità legale.", "ai_label": "UCNG", "article_title": "UCNG Content Declaration", "article_summary_heading": "Dichiarazione leggibile", "article_table_heading": "Dettagli della dichiarazione", "badge_article": "DECLARATION", "assessment_heading": "Contesto normativo", "component_text": "Testo", "component_research": "Ricerca", "component_cover_image": "Immagine di copertina", "component_images": "Immagini", "component_translation": "Traduzione", "component_audio": "Audio", "component_video": "Video", "component_code": "Codice", "regulatory_api_label": "API del contesto normativo"}, presets: map[string]PresetText{"no-ai": {"HUMAN", "Il contenuto sostanziale è stato creato da una persona."}, "research": {"AI ASSISTED", "LIA è stata usata come supporto alla ricerca; il contenuto sostanziale resta di origine umana."}, "summary": {"AI ASSISTED", "LIA ha assistito la sintesi; selezione e versione finale restano sotto responsabilità umana."}, "full": {"AI GENERATED", "Il contenuto sostanziale è stato generato da un sistema di IA generativa; la revisione umana è indicata separatamente."}}, extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · parzialmente generato", "mostly": "AI GENERATED · prevalentemente", "full": "AI GENERATED"}, assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · registrato tecnicamente", "signed": "Declared · firmato", "verified": "Verified"}},
"nl": {text: map[string]string{"meta_description": "UCNG is een open notatiekader voor transparante contentdeclaraties die leesbaar zijn voor mensen en machines.", "standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.", "hero_lead": "UCNG biedt een gemeenschappelijke taal om te verklaren hoe digitale inhoud is gemaakt of getransformeerd, leesbaar voor mensen en machines.", "generator_eyebrow": "UCNG Declaration", "generator_title": "Maak een contentdeclaratie", "generator_intro": "Beschrijf de creatiecontext per onderdeel, inclusief de rol van AI, zonder kwaliteit of waarheid van de inhoud te beoordelen.", "field_extent": "UCNG-classificatie", "fact_extent": "UCNG-classificatie", "table_extent": "UCNG-classificatie", "field_subject": "URL van gedeclareerde inhoud", "fact_subject": "Gedeclareerde inhoud", "declaration_eyebrow": "UCNG Declaration", "transparency_label": "Over deze declaratie:", "transparency_text": "Deze UCNG Declaration beschrijft het gedeclareerde creatie- en transformatieproces. Zij stelt op zichzelf geen verificatie, certificering, authenticiteit, nauwkeurigheid, waarheid of juridische naleving vast.", "ai_label": "UCNG", "article_title": "UCNG Content Declaration", "article_summary_heading": "Menselijk leesbare declaratie", "article_table_heading": "Declaratiedetails", "badge_article": "DECLARATION", "assessment_heading": "Regelgevingscontext", "component_text": "Tekst", "component_research": "Onderzoek", "component_cover_image": "Omslagafbeelding", "component_images": "Afbeeldingen", "component_translation": "Vertaling", "component_audio": "Audio", "component_video": "Video", "component_code": "Code", "regulatory_api_label": "API voor regelgevingscontext"}, presets: map[string]PresetText{"no-ai": {"HUMAN", "De wezenlijke inhoud is door een mens gemaakt."}, "research": {"AI ASSISTED", "AI is gebruikt als onderzoeksondersteuning; de wezenlijke inhoud blijft van menselijke oorsprong."}, "summary": {"AI ASSISTED", "AI hielp bij samenvatten; selectie en eindversie blijven onder menselijke verantwoordelijkheid."}, "full": {"AI GENERATED", "De wezenlijke inhoud is gegenereerd door een generatief AI-systeem; menselijke beoordeling wordt afzonderlijk vermeld."}}, extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · gedeeltelijk gegenereerd", "mostly": "AI GENERATED · grotendeels", "full": "AI GENERATED"}, assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · technisch vastgelegd", "signed": "Declared · ondertekend", "verified": "Verified"}},
"pt": {text: map[string]string{"meta_description": "UCNG é um quadro aberto de notação para declarações transparentes, legíveis por pessoas e máquinas.", "standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.", "hero_lead": "UCNG oferece uma linguagem comum para declarar como conteúdos digitais foram criados ou transformados, compreensível para pessoas e legível por máquinas.", "generator_eyebrow": "UCNG Declaration", "generator_title": "Criar uma declaração de conteúdo", "generator_intro": "Descreva o contexto de criação por componente, incluindo o papel da IA, sem avaliar a qualidade ou a veracidade do conteúdo.", "field_extent": "Classificação UCNG", "fact_extent": "Classificação UCNG", "table_extent": "Classificação UCNG", "field_subject": "URL do conteúdo declarado", "fact_subject": "Conteúdo declarado", "declaration_eyebrow": "UCNG Declaration", "transparency_label": "Sobre esta declaração:", "transparency_text": "Esta UCNG Declaration descreve o processo declarado de criação e transformação do conteúdo. Por si só, não estabelece verificação, certificação, autenticidade, exatidão, veracidade ou conformidade legal.", "ai_label": "UCNG", "article_title": "UCNG Content Declaration", "article_summary_heading": "Declaração legível por pessoas", "article_table_heading": "Detalhes da declaração", "badge_article": "DECLARATION", "assessment_heading": "Contexto regulamentar", "component_text": "Texto", "component_research": "Pesquisa", "component_cover_image": "Imagem de capa", "component_images": "Imagens", "component_translation": "Tradução", "component_audio": "Áudio", "component_video": "Vídeo", "component_code": "Código", "regulatory_api_label": "API de contexto regulamentar"}, presets: map[string]PresetText{"no-ai": {"HUMAN", "O conteúdo substancial foi criado por uma pessoa."}, "research": {"AI ASSISTED", "A IA foi usada para apoiar a pesquisa; o conteúdo substancial continua a ser de origem humana."}, "summary": {"AI ASSISTED", "A IA ajudou a resumir material; a seleção e a versão final permanecem sob responsabilidade humana."}, "full": {"AI GENERATED", "O conteúdo substancial foi gerado por um sistema de IA generativa; a revisão humana é indicada separadamente."}}, extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · parcialmente gerado", "mostly": "AI GENERATED · maioritariamente", "full": "AI GENERATED"}, assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · registado tecnicamente", "signed": "Declared · assinado", "verified": "Verified"}},
"pl": {text: map[string]string{"meta_description": "UCNG to otwarte ramy notacji dla przejrzystych deklaracji treści czytelnych dla ludzi i maszyn.", "standard_eyebrow": "UCNG · Universal Content Notation Guidelines", "hero_title": "Declare how content was made.", "hero_lead": "UCNG zapewnia wspólny język do deklarowania, jak treści cyfrowe zostały utworzone lub przekształcone, czytelny dla ludzi i maszyn.", "generator_eyebrow": "UCNG Declaration", "generator_title": "Utwórz deklarację treści", "generator_intro": "Opisz kontekst tworzenia według elementów, w tym rolę AI, bez oceniania jakości ani prawdziwości treści.", "field_extent": "Klasyfikacja UCNG", "fact_extent": "Klasyfikacja UCNG", "table_extent": "Klasyfikacja UCNG", "field_subject": "URL zadeklarowanej treści", "fact_subject": "Zadeklarowana treść", "declaration_eyebrow": "UCNG Declaration", "transparency_label": "O tej deklaracji:", "transparency_text": "Ta UCNG Declaration opisuje zadeklarowany proces tworzenia i przekształcania treści. Sama w sobie nie stanowi weryfikacji, certyfikacji, potwierdzenia autentyczności, dokładności, prawdziwości ani zgodności prawnej.", "ai_label": "UCNG", "article_title": "UCNG Content Declaration", "article_summary_heading": "Deklaracja czytelna dla człowieka", "article_table_heading": "Szczegóły deklaracji", "badge_article": "DECLARATION", "assessment_heading": "Kontekst regulacyjny", "component_text": "Tekst", "component_research": "Badania", "component_cover_image": "Obraz okładkowy", "component_images": "Obrazy", "component_translation": "Tłumaczenie", "component_audio": "Audio", "component_video": "Wideo", "component_code": "Kod", "regulatory_api_label": "API kontekstu regulacyjnego"}, presets: map[string]PresetText{"no-ai": {"HUMAN", "Zasadnicza treść została utworzona przez człowieka."}, "research": {"AI ASSISTED", "AI wykorzystano do wsparcia badań; zasadnicza treść pozostaje pochodzenia ludzkiego."}, "summary": {"AI ASSISTED", "AI wspomagała streszczanie; wybór i wersja końcowa pozostają pod odpowiedzialnością człowieka."}, "full": {"AI GENERATED", "Zasadnicza treść została wygenerowana przez generatywny system AI; przegląd człowieka jest wskazywany oddzielnie."}}, extents: map[string]string{"none": "HUMAN", "assisted": "AI ASSISTED", "partial": "MIXED · częściowo wygenerowane", "mostly": "AI GENERATED · w większości", "full": "AI GENERATED"}, assurances: map[string]string{"selfDeclared": "Declared", "technicallyRecorded": "Declared · zapisane technicznie", "signed": "Declared · podpisane", "verified": "Verified"}},
}
for code, v := range local {
copies[code] = v
}
for code, copy := range copies {
l := catalogs[code]
for key, value := range copy.text {
l.Text[key] = value
}
for key, value := range copy.presets {
l.Presets[key] = value
}
for key, value := range copy.extents {
l.Extents[key] = value
}
for key, value := range copy.assurances {
l.Assurances[key] = value
}
catalogs[code] = l
}
// Additional status copy used by the human-readable declaration.
statusText := map[string]map[string]string{
"de": {
"assurance_selfDeclared_description": "Declared: Die Angaben wurden von der veröffentlichenden Person oder Organisation deklariert; eine unabhängige Prüfung ist damit nicht verbunden.",
"assurance_technicallyRecorded_description": "Declared: Die Angaben werden zusätzlich im Erstellungs- oder Veröffentlichungsprozess technisch protokolliert. Das ist noch keine Verifikation.",
"assurance_signed_description": "Declared: Die Declaration ist digital signiert. Eine Signatur kann Herkunft und Unverändertheit der Declaration absichern, nicht automatisch die Richtigkeit des Inhalts.",
"assurance_verified_description": "Verified: Bestimmte Angaben der Declaration wurden nach einem dokumentierten technischen oder organisatorischen Prüfverfahren zusätzlich überprüft.",
"assurance_selfDeclared_statement": "Status: Declared. Die Angaben wurden von der veröffentlichenden Person oder Organisation bereitgestellt.",
"assurance_technicallyRecorded_statement": "Status: Declared; die Angaben sind zusätzlich technisch protokolliert. Daraus folgt keine automatische Verifikation.",
"assurance_signed_statement": "Status: Declared; die Declaration ist digital signiert, sodass Herkunft und Unverändertheit der Declaration geprüft werden können.",
"assurance_verified_statement": "Status: Verified. Bestimmte Angaben wurden nach einem dokumentierten Prüfverfahren zusätzlich überprüft.",
},
"en": {
"assurance_selfDeclared_description": "Declared: the information was declared by the publishing person or organisation; this does not include independent verification.",
"assurance_technicallyRecorded_description": "Declared: the information is also technically recorded during the creation or publication workflow. This is not verification by itself.",
"assurance_signed_description": "Declared: the declaration is digitally signed. A signature can protect the declaration's origin and integrity, not automatically the accuracy of the content.",
"assurance_verified_description": "Verified: specified declaration data has been additionally checked under a documented technical or organisational procedure.",
"assurance_selfDeclared_statement": "Status: Declared. The information was supplied by the publishing person or organisation.",
"assurance_technicallyRecorded_statement": "Status: Declared; the information is also technically recorded. This does not automatically constitute verification.",
"assurance_signed_statement": "Status: Declared; the declaration is digitally signed so that its origin and integrity can be checked.",
"assurance_verified_statement": "Status: Verified. Specified information was additionally checked under a documented procedure.",
},
}
for code, values := range statusText {
l := catalogs[code]
for key, value := range values {
l.Text[key] = value
}
catalogs[code] = l
}
localizedExtras := map[string]map[string]string{
"fr": {
"field_assurance": "Statut de la déclaration", "fact_assurance": "Statut de la déclaration",
"bulk_title": "Plusieurs contenus. Un langage de déclaration commun.",
"bulk_intro": "Générez des UCNG Declarations structurées pour des ensembles complets de contenus.",
"bulk_workspace_intro": "Ajoutez les contenus ligne par ligne et définissez une seule fois leur contexte de création commun.",
"bulk_profile_title": "Profil de déclaration commun", "bulk_link_declaration": "UCNG Declaration",
},
"es": {
"field_assurance": "Estado de la declaración", "fact_assurance": "Estado de la declaración",
"bulk_title": "Muchos contenidos. Un lenguaje común de declaración.",
"bulk_intro": "Genera UCNG Declarations estructuradas para conjuntos completos de contenidos.",
"bulk_workspace_intro": "Añade contenidos línea por línea y define una sola vez su contexto común de creación.",
"bulk_profile_title": "Perfil común de declaración", "bulk_link_declaration": "UCNG Declaration",
},
"it": {
"field_assurance": "Stato della dichiarazione", "fact_assurance": "Stato della dichiarazione",
"bulk_title": "Molti contenuti. Un linguaggio comune di dichiarazione.",
"bulk_intro": "Genera UCNG Declarations strutturate per interi insiemi di contenuti.",
"bulk_workspace_intro": "Aggiungi i contenuti riga per riga e definisci una sola volta il loro contesto di creazione comune.",
"bulk_profile_title": "Profilo di dichiarazione comune", "bulk_link_declaration": "UCNG Declaration",
},
"nl": {
"field_assurance": "Declaratiestatus", "fact_assurance": "Declaratiestatus",
"bulk_title": "Veel content. Eén gemeenschappelijke declaratietaal.",
"bulk_intro": "Maak gestructureerde UCNG Declarations voor complete contentverzamelingen.",
"bulk_workspace_intro": "Voeg content regel voor regel toe en leg de gemeenschappelijke creatiecontext één keer vast.",
"bulk_profile_title": "Gemeenschappelijk declaratieprofiel", "bulk_link_declaration": "UCNG Declaration",
},
"pt": {
"field_assurance": "Estado da declaração", "fact_assurance": "Estado da declaração",
"bulk_title": "Muitos conteúdos. Uma linguagem comum de declaração.",
"bulk_intro": "Gere UCNG Declarations estruturadas para conjuntos completos de conteúdos.",
"bulk_workspace_intro": "Adicione conteúdos linha a linha e defina uma vez o contexto de criação comum.",
"bulk_profile_title": "Perfil comum de declaração", "bulk_link_declaration": "UCNG Declaration",
},
"pl": {
"field_assurance": "Status deklaracji", "fact_assurance": "Status deklaracji",
"bulk_title": "Wiele treści. Jeden wspólny język deklaracji.",
"bulk_intro": "Twórz ustrukturyzowane UCNG Declarations dla całych zbiorów treści.",
"bulk_workspace_intro": "Dodawaj treści wiersz po wierszu i raz określ ich wspólny kontekst tworzenia.",
"bulk_profile_title": "Wspólny profil deklaracji", "bulk_link_declaration": "UCNG Declaration",
},
}
for code, values := range localizedExtras {
l := catalogs[code]
for key, value := range values {
l.Text[key] = value
}
catalogs[code] = l
}
}
func Get(code string) Locale { func Get(code string) Locale {
if l, ok := catalogs[Normalize(code)]; ok { if l, ok := catalogs[Normalize(code)]; ok {
return cloneLocale(l) return cloneLocale(l)

View File

@@ -130,7 +130,7 @@ curl -fsS http://localhost:8080/readyz`},
docker run -d --name ai-disclosure \ docker run -d --name ai-disclosure \
-p 8080:8080 \ -p 8080:8080 \
-e BASE_URL=https://ai.example.org \ -e BASE_URL=https://ai.example.org \
-e PUBLIC_NAME="AI Usage Disclosure" \ -e PUBLIC_NAME="UCNG" \
--read-only --tmpfs /tmp \ --read-only --tmpfs /tmp \
ai-disclosure-standard:2.0.2`}, ai-disclosure-standard:2.0.2`},
{ID: "kubernetes", Title: copy.InstallTitles[2], Summary: copy.InstallSummaries[2], Code: `# Image, domain and TLS secret in deploy/kubernetes.yaml ersetzen {ID: "kubernetes", Title: copy.InstallTitles[2], Summary: copy.InstallSummaries[2], Code: `# Image, domain and TLS secret in deploy/kubernetes.yaml ersetzen
@@ -145,7 +145,7 @@ docker stack deploy -c deploy/swarm-stack.yaml ai-disclosure
{ID: "go", Title: copy.InstallTitles[4], Summary: copy.InstallSummaries[4], Code: `go test ./... {ID: "go", Title: copy.InstallTitles[4], Summary: copy.InstallSummaries[4], Code: `go test ./...
go build -trimpath -o bin/server ./cmd/server go build -trimpath -o bin/server ./cmd/server
BASE_URL=http://localhost:8080 \ BASE_URL=http://localhost:8080 \
PUBLIC_NAME="AI Usage Disclosure" \ PUBLIC_NAME="UCNG" \
./bin/server`}, ./bin/server`},
} }
@@ -241,6 +241,76 @@ func neutralize(c copySet, lang string) copySet {
c.FinalTitle = "Start with your own declaration." c.FinalTitle = "Start with your own declaration."
c.FinalLead = "The generator works without registration, cookies or external resources." c.FinalLead = "The generator works without registration, cookies or external resources."
} }
return applyUCNGPositioning(c, lang)
}
func applyUCNGPositioning(c copySet, lang string) copySet {
type localCopy struct {
meta, eyebrow, title, lead, primary, featuresEyebrow, featuresTitle, featuresLead, finalTitle, finalLead, finalPrimary, footer string
proof []string
features []Feature
faqs []FAQ
}
copies := map[string]localCopy{
"de": {
meta: "UCNG offenes Notationssystem für transparente, menschen- und maschinenlesbare Content-Deklarationen.",
eyebrow: "UCNG · Open by design", title: "Declare how content was made.",
lead: "UCNG schafft eine gemeinsame Sprache dafür, wie digitale Inhalte entstanden oder verändert worden sind. Die Referenzimplementierung verbindet eine verständliche Declaration mit maschinenlesbaren Daten plattform-, anbieter- und medienunabhängig.",
primary: "Declaration erstellen", proof: []string{"Human-readable", "Machine-readable", "Vendor-neutral", "Self-hostable"},
featuresEyebrow: "Content transparency", featuresTitle: "Eine Declaration. Zwei Zielgruppen.", featuresLead: "UCNG beschreibt Herkunft und Transformation. Es bewertet weder Wahrheit noch Qualität eines Inhalts.",
features: []Feature{
{"01", "Content needs context.", "Digitale Inhalte entstehen nicht mehr auf nur eine Weise. UCNG macht den deklarierten Entstehungskontext transportierbar."},
{"02", "Human-readable", "Kompakte Labels und verständliche Declaration-Seiten erklären den angegebenen Erstellungs- und Transformationsprozess."},
{"03", "Machine-readable", "Dieselben Angaben stehen strukturiert als JSON-LD zur Verfügung und können von Plattformen, Systemen und Build-Prozessen verarbeitet werden."},
{"04", "Simple labels. Detailed metadata.", "HUMAN, AI ASSISTED, MIXED und AI GENERATED geben eine kompakte Einordnung; Detailangaben dokumentieren Tätigkeit, Human Review und Declaration Status."},
{"Open", "Platform-independent", "Die Anwendung ist selbst hostbar und bindet die Declaration nicht an einen bestimmten Publisher, KI-Anbieter oder eine Plattform."},
{"Neutral", "Declaration ≠ Verification", "Ein UCNG Badge zeigt, dass eine Declaration vorhanden ist. Es bedeutet nicht automatisch verified, zertifiziert, wahr oder rechtskonform."},
{"Interoperabel", "Ein Format, mehrere Medien", "Text, Bild, Audio, Video, Code und mehr können in derselben Deklarationslogik beschrieben werden."},
},
faqs: []FAQ{
{"Bewertet UCNG, ob ein Inhalt wahr oder falsch ist?", "Nein. UCNG beschreibt den deklarierten Entstehungs- und Transformationsprozess. Ein UCNG Badge bedeutet nicht automatisch verified, zertifiziert, wahr oder rechtskonform."},
{"Ist UCNG ein offizielles System der Europäischen Union?", "Nein. UCNG ist als unabhängiges offenes Framework positioniert. Regulatorischer Kontext kann dokumentiert werden, ist aber nicht mit einer UCNG Declaration gleichzusetzen."},
},
finalTitle: "Content deserves context.", finalLead: "Erstelle eine UCNG Declaration und mache den angegebenen Entstehungskontext für Menschen und Maschinen lesbar.", finalPrimary: "Declaration erstellen", footer: "UCNG · Universal Content Notation Guidelines · An open notation framework for transparent content declarations.",
},
"en": {
meta: "UCNG an open notation framework for transparent, human-readable and machine-readable content declarations.",
eyebrow: "UCNG · Open by design", title: "Declare how content was made.",
lead: "UCNG provides a common language for describing how digital content was created or transformed. The reference implementation combines a human-readable declaration with machine-readable data independent of platform, vendor and medium.",
primary: "Create a declaration", proof: []string{"Human-readable", "Machine-readable", "Vendor-neutral", "Self-hostable"},
featuresEyebrow: "Content transparency", featuresTitle: "One declaration. Two audiences.", featuresLead: "UCNG describes origin and transformation. It does not judge the truth or quality of content.",
features: []Feature{
{"01", "Content needs context.", "Digital content is no longer created in one way. UCNG makes the declared creation context portable."},
{"02", "Human-readable", "Compact labels and readable declaration pages explain the stated creation and transformation process."},
{"03", "Machine-readable", "The same information is available as structured JSON-LD for platforms, systems and build workflows."},
{"04", "Simple labels. Detailed metadata.", "HUMAN, AI ASSISTED, MIXED and AI GENERATED provide a compact classification; details record activity, human review and declaration status."},
{"Open", "Platform-independent", "The application is self-hostable and does not bind a declaration to a particular publisher, AI vendor or platform."},
{"Neutral", "Declaration ≠ Verification", "A UCNG badge indicates that a declaration exists. It does not automatically mean verified, certified, true or legally compliant."},
{"Interoperable", "One model, multiple media", "Text, image, audio, video, code and more can be described using the same declaration logic."},
},
faqs: []FAQ{
{"Does UCNG decide whether content is true or false?", "No. UCNG describes the declared creation and transformation process. A UCNG badge does not automatically mean verified, certified, true or legally compliant."},
{"Is UCNG an official European Union system?", "No. UCNG is positioned as an independent open framework. Regulatory context can be documented, but it is not the same as a UCNG Declaration."},
},
finalTitle: "Content deserves context.", finalLead: "Create a UCNG Declaration and make the stated creation context readable to people and machines.", finalPrimary: "Create a declaration", footer: "UCNG · Universal Content Notation Guidelines · An open notation framework for transparent content declarations.",
},
}
if v, ok := copies[lang]; ok {
c.MetaDescription, c.HeroEyebrow, c.HeroTitle, c.HeroLead, c.PrimaryCTA = v.meta, v.eyebrow, v.title, v.lead, v.primary
c.Proof = v.proof
c.FeaturesEyebrow, c.FeaturesTitle, c.FeaturesLead, c.Features = v.featuresEyebrow, v.featuresTitle, v.featuresLead, v.features
c.FAQEyebrow, c.FAQTitle, c.FAQs = "FAQ", map[string]string{"de": "Häufige Fragen", "en": "Common questions"}[lang], v.faqs
c.FinalTitle, c.FinalLead, c.FinalPrimary, c.Footer = v.finalTitle, v.finalLead, v.finalPrimary, v.footer
return c
}
// Other supported UI languages retain their translated technical content,
// while the brand-level claim and terminology stay consistent.
c.HeroTitle = "Declare how content was made."
c.HeroEyebrow = "UCNG · Open by design"
c.PrimaryCTA = map[string]string{"fr": "Créer une déclaration", "es": "Crear una declaración", "it": "Crea una dichiarazione", "nl": "Maak een declaratie", "pt": "Criar uma declaração", "pl": "Utwórz deklarację"}[lang]
c.FinalPrimary = c.PrimaryCTA
c.Footer = "UCNG · Universal Content Notation Guidelines · An open notation framework for transparent content declarations."
return c return c
} }

View File

@@ -97,7 +97,7 @@
badgeParams.set('link', declarationURL); badgeParams.set('link', declarationURL);
const badgeURL = `${base}/v1/badge.svg?${badgeParams}`; const badgeURL = `${base}/v1/badge.svg?${badgeParams}`;
const manifestURL = `${base}/v1/declaration.json?${params}`; const manifestURL = `${base}/v1/declaration.json?${params}`;
let alt = articleMode ? (locale.text.badge_article || 'Article transparency') : (locale.text.ai_label || 'AI usage disclosure'); let alt = articleMode ? (locale.text.badge_article || 'Article transparency') : (locale.text.ai_label || 'UCNG');
if ($('deepfake')?.checked) alt = locale.text.badge_article50_deepfake || alt; if ($('deepfake')?.checked) alt = locale.text.badge_article50_deepfake || alt;
else if ($('public-interest-text')?.checked && !($('substantial-review')?.checked && $('editorial-responsibility-confirmed')?.checked)) alt = locale.text.badge_article50_text || alt; else if ($('public-interest-text')?.checked && !($('substantial-review')?.checked && $('editorial-responsibility-confirmed')?.checked)) alt = locale.text.badge_article50_text || alt;

View File

@@ -52,7 +52,7 @@
<section class="regulatory-section" aria-labelledby="regulatory-title"> <section class="regulatory-section" aria-labelledby="regulatory-title">
<div class="section-heading-row"> <div class="section-heading-row">
<div> <div>
<p class="eyebrow">EU AI Act · Article 50</p> <p class="eyebrow">{{index .Text "article50_section_title"}}</p>
<h2 id="regulatory-title">{{index .Text "assessment_heading"}}</h2> <h2 id="regulatory-title">{{index .Text "assessment_heading"}}</h2>
</div> </div>
<span class="assessment-status assessment-{{.Assessment.Severity}}">{{.Assessment.Title}}</span> <span class="assessment-status assessment-{{.Assessment.Severity}}">{{.Assessment.Title}}</span>

View File

@@ -72,14 +72,14 @@
<legend>{{index .Text "article_fields"}}</legend> <legend>{{index .Text "article_fields"}}</legend>
<p>{{index .Text "article_help"}}</p> <p>{{index .Text "article_help"}}</p>
<div class="article-component-grid"> <div class="article-component-grid">
<div class="article-component"><label>Text<select id="article-text" data-review="article-text-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-text-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_text"}}<select id="article-text" data-review="article-text-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-text-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>{{index .Text "fact_activities"}} / Recherche<select id="article-research" data-review="article-research-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "assisted"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-research-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "editorial"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_research"}}<select id="article-research" data-review="article-research-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "assisted"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-research-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "editorial"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>Cover / {{index .Text "fact_component"}}<select id="article-cover-image" data-review="article-cover-image-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-cover-image-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_cover_image"}}<select id="article-cover-image" data-review="article-cover-image-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-cover-image-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>Images<select id="article-image" data-review="article-image-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "full"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-image-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "editorial"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_images"}}<select id="article-image" data-review="article-image-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "full"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-image-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "editorial"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>Translation<select id="article-translation" data-review="article-translation-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-translation-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_translation"}}<select id="article-translation" data-review="article-translation-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-translation-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>Audio<select id="article-audio" data-review="article-audio-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-audio-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_audio"}}<select id="article-audio" data-review="article-audio-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-audio-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>Video<select id="article-video" data-review="article-video-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-video-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_video"}}<select id="article-video" data-review="article-video-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-video-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
<div class="article-component"><label>Code<select id="article-code" data-review="article-code-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-code-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div> <div class="article-component"><label>{{index .Text "component_code"}}<select id="article-code" data-review="article-code-review">{{range .Extents}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label><label>{{index .Text "field_review"}}<select id="article-code-review">{{range .Reviews}}<option value="{{.Value}}" {{if eq .Value "none"}}selected{{end}}>{{.Label}}</option>{{end}}</select></label></div>
</div> </div>
</fieldset> </fieldset>
<label>{{index .Text "field_language"}} <label>{{index .Text "field_language"}}
@@ -152,7 +152,7 @@
<label>HTML<textarea id="html-code" readonly></textarea></label> <label>HTML<textarea id="html-code" readonly></textarea></label>
<label>Markdown<textarea id="markdown-code" readonly></textarea></label> <label>Markdown<textarea id="markdown-code" readonly></textarea></label>
<label>JSON-LD URL<textarea id="json-code" readonly></textarea></label> <label>JSON-LD URL<textarea id="json-code" readonly></textarea></label>
<label>Article 50 API<textarea id="assessment-code" readonly></textarea></label> <label>{{index .Text "regulatory_api_label"}}<textarea id="assessment-code" readonly></textarea></label>
</div> </div>
<button id="copy-html" type="button">{{index .Text "copy_html"}}</button> <button id="copy-html" type="button">{{index .Text "copy_html"}}</button>
</div> </div>