Add redact doc pages; update timeline docs to remove GPU references

- New: redact-about.php, redact-guide.php, redact-tech.php with full
  two-pass pipeline docs, regional rule sets, output format comparison
- New: translations/redact-{about,guide,tech}.php (en + no)
- redact.php: add About/Guide/How-it-works doc links
- timeline-guide.php: remove GPU/cuttlefish engine row
- timeline-tech.php: remove GPU row, replace fine-tuned LLM section
  with SSE streaming + DOCX export section, stat4 3→2 engines
- timeline-about.php: replace dbn-legal-agent spotlight with
  SSE/DOCX export highlight
- translations/timeline-{about,guide,tech}.php: remove all GPU/
  cuttlefish references across all 4 languages; add stream_* and
  export_* keys; fix upload copy (5 files → 1 file)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 09:53:54 +02:00
parent d47024ed67
commit 1d1bbeb69f
13 changed files with 1524 additions and 68 deletions
+237
View File
@@ -0,0 +1,237 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/bootstrap.php';
$uiLang = dbnToolsCurrentLanguage();
$isAuthed = dbnToolsIsAuthenticated();
$langPath = '/redact-about.php';
$toolsLogin = 'https://dobetternorge.no/tools-login.php?return=' . urlencode('/redact.php');
$registerUrl = 'https://dobetternorge.no/register.php';
$ctaUrl = $isAuthed ? '/redact.php' : $toolsLogin;
$_pt = require __DIR__ . '/translations/redact-about.php';
$t = $_pt[$uiLang] ?? $_pt['en'];
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Redact — Remove names and protect identities in Norwegian legal documents · Do Better Norge Tools</title>
<meta name="description" content="Redact replaces names, organisations, addresses, and ID numbers in Norwegian case notes and court decisions with contextual role tags, generic labels, or pseudonyms. Download as Word.">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://tools.dobetternorge.no/redact-about.php">
<meta property="og:title" content="Redact — AI anonymisation for Norwegian legal documents">
<meta property="og:description" content="Two-pass redaction: deterministic regex patterns + GPT-4o sweep. Contextual role tags, regional rule sets, Word export.">
<meta property="og:type" content="website">
<meta name="theme-color" content="#00205B">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap">
<link rel="stylesheet" href="assets/css/tools.css">
<link rel="stylesheet" href="assets/css/dbn-tools-redesign.css">
</head>
<body class="kdoc-page">
<header class="lt-nav">
<a href="https://dobetternorge.no" class="lt-nav__brand">
<picture>
<source srcset="assets/images/logo-header.webp" type="image/webp">
<img class="lt-nav__logo" src="assets/images/logo-header.png" alt="Do Better Norge" width="140" height="36" loading="eager">
</picture>
<span class="lt-nav__badge">Legal Tools</span>
</a>
<div class="lt-nav__right">
<nav class="shell-lang-switcher" aria-label="Language">
<?php foreach (dbnToolsSupportedLanguages() as $langCode): ?>
<a href="<?= htmlspecialchars($langPath . '?lang=' . $langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
<?php endforeach; ?>
</nav>
<?php if ($isAuthed): ?>
<a href="/redact.php" class="lt-nav__cta lt-nav__cta--enter"><?= htmlspecialchars($t['nav_open']) ?></a>
<?php else: ?>
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="lt-nav__cta"><?= htmlspecialchars($t['nav_signin']) ?></a>
<?php endif; ?>
</div>
</header>
<nav class="kdoc-doc-nav" aria-label="Redact documentation">
<div class="kdoc-doc-nav__inner">
<a href="/redact-about.php" class="is-active"><?= htmlspecialchars($t['nav_about']) ?></a>
<a href="/redact-guide.php"><?= htmlspecialchars($t['nav_guide']) ?></a>
<a href="/redact-tech.php"><?= htmlspecialchars($t['nav_howit']) ?></a>
<?php if ($isAuthed): ?>
<a href="/redact.php"><?= htmlspecialchars($t['nav_opentool']) ?></a>
<?php endif; ?>
</div>
</nav>
<!-- Hero -->
<section class="kdoc-hero" style="background: linear-gradient(rgba(0,20,60,0.82),rgba(0,20,60,0.88)), url('assets/images/timeline/hero-marketing.png') center/cover no-repeat;">
<div class="kdoc-hero__inner">
<p class="kdoc-hero__kicker"><?= htmlspecialchars($t['hero_kicker']) ?></p>
<h1 class="kdoc-hero__title"><?= htmlspecialchars($t['hero_title']) ?></h1>
<p class="kdoc-hero__sub"><?= htmlspecialchars($t['hero_sub']) ?></p>
<div class="kdoc-hero__stats">
<div class="kdoc-hero__stat">
<strong>2</strong>
<span><?= htmlspecialchars($t['stat_engines']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>4</strong>
<span><?= htmlspecialchars($t['stat_regions']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>3</strong>
<span><?= htmlspecialchars($t['stat_formats']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>2</strong>
<span><?= htmlspecialchars($t['stat_passes']) ?></span>
</div>
</div>
<div class="kdoc-hero__ctas">
<a href="<?= htmlspecialchars($ctaUrl) ?>" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_try']) ?></a>
<a href="/redact-guide.php" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_guide']) ?></a>
<a href="/redact-tech.php" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_howit']) ?></a>
</div>
</div>
</section>
<!-- What you get -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['what_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['what_title']) ?></h2>
<div class="kdoc-features">
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#128274;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['f1_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= $t['f1_body_html'] ?></p>
</div>
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#127991;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['f2_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= htmlspecialchars($t['f2_body']) ?></p>
</div>
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#128196;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['f3_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= htmlspecialchars($t['f3_body']) ?></p>
</div>
</div>
</div>
</section>
<!-- How it works (3-step) -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['how_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['how_title']) ?></h2>
<p class="kdoc-section__sub"><?= htmlspecialchars($t['how_sub']) ?></p>
<div class="kdoc-steps">
<div class="kdoc-step-card">
<span class="kdoc-step-card__num">1</span>
<h3 class="kdoc-step-card__title"><?= htmlspecialchars($t['s1_title']) ?></h3>
<p class="kdoc-step-card__body"><?= htmlspecialchars($t['s1_body']) ?></p>
<p class="kdoc-step-card__example"><?= htmlspecialchars($t['s1_example']) ?></p>
</div>
<span class="kdoc-step-arrow" aria-hidden="true">&rarr;</span>
<div class="kdoc-step-card">
<span class="kdoc-step-card__num">2</span>
<h3 class="kdoc-step-card__title"><?= htmlspecialchars($t['s2_title']) ?></h3>
<p class="kdoc-step-card__body"><?= htmlspecialchars($t['s2_body']) ?></p>
<p class="kdoc-step-card__example"><?= htmlspecialchars($t['s2_example']) ?></p>
</div>
<span class="kdoc-step-arrow" aria-hidden="true">&rarr;</span>
<div class="kdoc-step-card">
<span class="kdoc-step-card__num">3</span>
<h3 class="kdoc-step-card__title"><?= htmlspecialchars($t['s3_title']) ?></h3>
<p class="kdoc-step-card__body"><?= htmlspecialchars($t['s3_body']) ?></p>
<p class="kdoc-step-card__example"><?= htmlspecialchars($t['s3_example']) ?></p>
</div>
</div>
</div>
<!-- Output formats spotlight -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['output_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['output_title']) ?></h2>
<div class="kdoc-llm-spotlight">
<div>
<span class="kdoc-llm-spotlight__badge"><?= htmlspecialchars($t['output_badge']) ?></span>
<h3 class="kdoc-llm-spotlight__title"><?= htmlspecialchars($t['output_h1']) ?></h3>
<p class="kdoc-llm-spotlight__body"><?= $t['output_body_html'] ?></p>
</div>
<div class="kdoc-llm-stats">
<div class="kdoc-llm-stat">
<strong>[FATHER]</strong>
<span><?= htmlspecialchars($t['output_s1']) ?></span>
</div>
<div class="kdoc-llm-stat">
<strong>[PERSON]</strong>
<span><?= htmlspecialchars($t['output_s2']) ?></span>
</div>
<div class="kdoc-llm-stat">
<strong>Ola N.</strong>
<span><?= htmlspecialchars($t['output_s3']) ?></span>
</div>
<div class="kdoc-llm-stat">
<strong>3</strong>
<span><?= htmlspecialchars($t['output_s4']) ?></span>
</div>
</div>
</div>
</div>
</section>
<!-- Regional rule sets showcase -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['region_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['region_title']) ?></h2>
<p class="kdoc-section__sub"><?= htmlspecialchars($t['region_sub']) ?></p>
<div class="kdoc-features">
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#127475;&#127476;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['rr1_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= htmlspecialchars($t['rr1_body']) ?></p>
</div>
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#127466;&#127482;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['rr2_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= htmlspecialchars($t['rr2_body']) ?></p>
</div>
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#9878;&#65039;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['rr3_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= htmlspecialchars($t['rr3_body']) ?></p>
</div>
<div class="kdoc-feature-card">
<span class="kdoc-feature-card__icon">&#127758;</span>
<h3 class="kdoc-feature-card__title"><?= htmlspecialchars($t['rr4_title']) ?></h3>
<p class="kdoc-feature-card__body"><?= htmlspecialchars($t['rr4_body']) ?></p>
</div>
</div>
</div>
<!-- CTA strip -->
<section class="kdoc-cta-strip">
<h2 class="kdoc-cta-strip__title"><?= htmlspecialchars($t['cta_title']) ?></h2>
<p class="kdoc-cta-strip__sub"><?= htmlspecialchars($t['cta_sub']) ?></p>
<div class="kdoc-hero__ctas">
<?php if ($isAuthed): ?>
<a href="/redact.php" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_open']) ?></a>
<?php else: ?>
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_signin_cta']) ?></a>
<a href="<?= htmlspecialchars($registerUrl) ?>" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_register']) ?></a>
<?php endif; ?>
</div>
</section>
<?php require_once __DIR__ . '/includes/footer.php'; ?>
<script src="assets/js/tools.js" defer></script>
</body>
</html>
+334
View File
@@ -0,0 +1,334 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/bootstrap.php';
$uiLang = dbnToolsCurrentLanguage();
$isAuthed = dbnToolsIsAuthenticated();
$langPath = '/redact-guide.php';
$toolsLogin = 'https://dobetternorge.no/tools-login.php?return=' . urlencode('/redact.php');
$registerUrl = 'https://dobetternorge.no/register.php';
$_pt = require __DIR__ . '/translations/redact-guide.php';
$t = $_pt[$uiLang] ?? $_pt['en'];
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Redact User Guide — How to anonymise Norwegian legal documents</title>
<meta name="description" content="Step-by-step guide to using Redact: choose an engine, set mode and region, configure entity types, add aliases, upload documents, and download the redacted Word file.">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://tools.dobetternorge.no/redact-guide.php">
<meta property="og:title" content="Redact User Guide">
<meta property="og:description" content="How to use Redact to anonymise Norwegian case notes, court decisions, and correspondence — contextual role tags, pseudonyms, Word export.">
<meta name="theme-color" content="#00205B">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap">
<link rel="stylesheet" href="assets/css/tools.css">
<link rel="stylesheet" href="assets/css/dbn-tools-redesign.css">
</head>
<body class="kdoc-page">
<header class="lt-nav">
<a href="https://dobetternorge.no" class="lt-nav__brand">
<picture>
<source srcset="assets/images/logo-header.webp" type="image/webp">
<img class="lt-nav__logo" src="assets/images/logo-header.png" alt="Do Better Norge" width="140" height="36" loading="eager">
</picture>
<span class="lt-nav__badge">Legal Tools</span>
</a>
<div class="lt-nav__right">
<nav class="shell-lang-switcher" aria-label="Language">
<?php foreach (dbnToolsSupportedLanguages() as $langCode): ?>
<a href="<?= htmlspecialchars($langPath . '?lang=' . $langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
<?php endforeach; ?>
</nav>
<?php if ($isAuthed): ?>
<a href="/redact.php" class="lt-nav__cta lt-nav__cta--enter"><?= htmlspecialchars($t['nav_open']) ?></a>
<?php else: ?>
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="lt-nav__cta"><?= htmlspecialchars($t['nav_signin']) ?></a>
<?php endif; ?>
</div>
</header>
<nav class="kdoc-doc-nav" aria-label="Redact documentation">
<div class="kdoc-doc-nav__inner">
<a href="/redact-about.php"><?= htmlspecialchars($t['nav_about']) ?></a>
<a href="/redact-guide.php" class="is-active"><?= htmlspecialchars($t['nav_guide']) ?></a>
<a href="/redact-tech.php"><?= htmlspecialchars($t['nav_howit']) ?></a>
<?php if ($isAuthed): ?><a href="/redact.php"><?= htmlspecialchars($t['nav_opentool']) ?></a><?php endif; ?>
</div>
</nav>
<!-- Hero -->
<section class="kdoc-hero" style="background: linear-gradient(rgba(0,20,60,0.78),rgba(0,20,60,0.86)), url('assets/images/timeline/hero-guide.png') center/cover no-repeat;">
<div class="kdoc-hero__inner">
<p class="kdoc-hero__kicker"><?= htmlspecialchars($t['hero_kicker']) ?></p>
<h1 class="kdoc-hero__title"><?= htmlspecialchars($t['hero_title']) ?></h1>
<p class="kdoc-hero__sub"><?= htmlspecialchars($t['hero_sub']) ?></p>
</div>
</section>
<!-- TOC + content -->
<div class="kdoc-section">
<div class="kdoc-toc">
<p class="kdoc-toc__title"><?= htmlspecialchars($t['toc_title']) ?></p>
<ol>
<li><a href="#engine"><?= htmlspecialchars($t['toc_1']) ?></a></li>
<li><a href="#mode"><?= htmlspecialchars($t['toc_2']) ?></a></li>
<li><a href="#region"><?= htmlspecialchars($t['toc_3']) ?></a></li>
<li><a href="#entities"><?= htmlspecialchars($t['toc_4']) ?></a></li>
<li><a href="#officials"><?= htmlspecialchars($t['toc_5']) ?></a></li>
<li><a href="#output"><?= htmlspecialchars($t['toc_6']) ?></a></li>
<li><a href="#exempt"><?= htmlspecialchars($t['toc_7']) ?></a></li>
<li><a href="#aliases"><?= htmlspecialchars($t['toc_8']) ?></a></li>
<li><a href="#upload"><?= htmlspecialchars($t['toc_9']) ?></a></li>
<li><a href="#reading"><?= htmlspecialchars($t['toc_10']) ?></a></li>
</ol>
</div>
<!-- Step 1: Engine -->
<div class="kdoc-guide-step" id="engine">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">1</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step1_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= htmlspecialchars($t['step1_intro']) ?></p>
</div>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_engine']) ?></th>
<th><?= htmlspecialchars($t['th_cost']) ?></th>
<th><?= htmlspecialchars($t['th_best']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Azure gpt-4o-mini &#9733;</td>
<td><?= htmlspecialchars($t['eng1_cost']) ?></td>
<td><?= htmlspecialchars($t['eng1_best']) ?></td>
</tr>
<tr>
<td>Azure gpt-4o</td>
<td><?= htmlspecialchars($t['eng2_cost']) ?></td>
<td><?= htmlspecialchars($t['eng2_best']) ?></td>
</tr>
</tbody>
</table>
</div>
<!-- Step 2: Mode -->
<div class="kdoc-guide-step" id="mode">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">2</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step2_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= htmlspecialchars($t['step2_intro']) ?></p>
</div>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_mode']) ?></th>
<th><?= htmlspecialchars($t['th_does']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Standard &#9733;</td>
<td><?= htmlspecialchars($t['mode1_does']) ?></td>
</tr>
<tr>
<td>Strict</td>
<td><?= htmlspecialchars($t['mode2_does']) ?></td>
</tr>
</tbody>
</table>
</div>
<!-- Step 3: Region -->
<div class="kdoc-guide-step" id="region">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">3</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step3_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= htmlspecialchars($t['step3_intro']) ?></p>
</div>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_region']) ?></th>
<th><?= htmlspecialchars($t['th_targets']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Nordic &#9733;</td>
<td><?= htmlspecialchars($t['reg1_targets']) ?></td>
</tr>
<tr>
<td>European</td>
<td><?= htmlspecialchars($t['reg2_targets']) ?></td>
</tr>
<tr>
<td>ECHR</td>
<td><?= htmlspecialchars($t['reg3_targets']) ?></td>
</tr>
<tr>
<td>Global</td>
<td><?= htmlspecialchars($t['reg4_targets']) ?></td>
</tr>
</tbody>
</table>
</div>
<!-- Step 4: What to redact -->
<div class="kdoc-guide-step" id="entities">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">4</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step4_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= htmlspecialchars($t['step4_intro']) ?></p>
</div>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_entity']) ?></th>
<th><?= htmlspecialchars($t['th_entity_desc']) ?></th>
</tr>
</thead>
<tbody>
<tr><td>Names &#9733;</td><td><?= htmlspecialchars($t['ent1_desc']) ?></td></tr>
<tr><td>Organisations &#9733;</td><td><?= htmlspecialchars($t['ent2_desc']) ?></td></tr>
<tr><td>Places &#9733;</td><td><?= htmlspecialchars($t['ent3_desc']) ?></td></tr>
<tr><td>Dates &#9733;</td><td><?= htmlspecialchars($t['ent4_desc']) ?></td></tr>
</tbody>
</table>
</div>
<!-- Step 5: Officials -->
<div class="kdoc-guide-step" id="officials">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">5</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step5_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= $t['step5_p1_html'] ?></p>
<p style="margin-top:0.8rem;"><?= $t['step5_p2_html'] ?></p>
</div>
</div>
<!-- Step 6: Output format -->
<div class="kdoc-guide-step" id="output">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">6</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step6_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= htmlspecialchars($t['step6_intro']) ?></p>
</div>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_format']) ?></th>
<th><?= htmlspecialchars($t['th_result']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Contextual tags &#9733;</td>
<td><?= htmlspecialchars($t['fmt1_result']) ?></td>
</tr>
<tr>
<td>Generic tags</td>
<td><?= htmlspecialchars($t['fmt2_result']) ?></td>
</tr>
<tr>
<td>Pseudonyms</td>
<td><?= htmlspecialchars($t['fmt3_result']) ?></td>
</tr>
</tbody>
</table>
</div>
<!-- Step 7: Exempt names -->
<div class="kdoc-guide-step" id="exempt">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">7</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step7_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= $t['step7_p1_html'] ?></p>
<p style="margin-top:0.8rem;"><?= $t['step7_p2_html'] ?></p>
</div>
</div>
<!-- Step 8: Aliases -->
<div class="kdoc-guide-step" id="aliases">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">8</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step8_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= $t['step8_p1_html'] ?></p>
<p style="margin-top:0.8rem;"><?= $t['step8_p2_html'] ?></p>
</div>
</div>
<!-- Step 9: Upload -->
<div class="kdoc-guide-step" id="upload">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">9</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step9_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= $t['step9_p1_html'] ?></p>
<p style="margin-top:0.8rem;"><?= $t['step9_p2_html'] ?></p>
<p style="margin-top:0.8rem;"><?= htmlspecialchars($t['step9_p3']) ?></p>
</div>
</div>
<!-- Step 10: Reading & downloading -->
<div class="kdoc-guide-step" id="reading">
<div class="kdoc-guide-step__header">
<span class="kdoc-guide-step__num">10</span>
<h2 class="kdoc-guide-step__title"><?= htmlspecialchars($t['step10_title']) ?></h2>
</div>
<div class="kdoc-guide-step__body">
<p><?= htmlspecialchars($t['step10_intro']) ?></p>
<ul style="padding-left:1.4rem; font-size:0.9rem; line-height:1.8; margin-top:0.5rem;">
<li><?= $t['dl1_html'] ?></li>
<li><?= $t['dl2_html'] ?></li>
<li><?= $t['dl3_html'] ?></li>
</ul>
</div>
</div>
</div><!-- /kdoc-section -->
<!-- CTA -->
<section class="kdoc-cta-strip">
<h2 class="kdoc-cta-strip__title"><?= htmlspecialchars($t['cta_title']) ?></h2>
<p class="kdoc-cta-strip__sub"><?= htmlspecialchars($t['cta_sub']) ?></p>
<div class="kdoc-hero__ctas">
<?php if ($isAuthed): ?>
<a href="/redact.php" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_open']) ?></a>
<?php else: ?>
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_signin_cta']) ?></a>
<a href="<?= htmlspecialchars($registerUrl) ?>" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_register']) ?></a>
<?php endif; ?>
<a href="/redact-tech.php" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_techlink']) ?></a>
</div>
</section>
<?php require_once __DIR__ . '/includes/footer.php'; ?>
<script src="assets/js/tools.js" defer></script>
</body>
</html>
+319
View File
@@ -0,0 +1,319 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/bootstrap.php';
$uiLang = dbnToolsCurrentLanguage();
$isAuthed = dbnToolsIsAuthenticated();
$langPath = '/redact-tech.php';
$toolsLogin = 'https://dobetternorge.no/tools-login.php?return=' . urlencode('/redact.php');
$registerUrl = 'https://dobetternorge.no/register.php';
$_pt = require __DIR__ . '/translations/redact-tech.php';
$t = $_pt[$uiLang] ?? $_pt['en'];
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How Redact works — Two-pass pipeline, regional patterns, entity classification</title>
<meta name="description" content="Technical deep-dive: how Redact uses a two-pass pipeline combining deterministic regex patterns with GPT-4o entity recognition to anonymise Norwegian legal documents.">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://tools.dobetternorge.no/redact-tech.php">
<meta property="og:title" content="How Redact works — Two-pass redaction pipeline">
<meta property="og:description" content="Pass 1: regex pattern matching. Pass 2: LLM entity sweep. Regional rule sets, output format generation, alias substitution.">
<meta name="theme-color" content="#00205B">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap">
<link rel="stylesheet" href="assets/css/tools.css">
<link rel="stylesheet" href="assets/css/dbn-tools-redesign.css">
</head>
<body class="kdoc-page">
<header class="lt-nav">
<a href="https://dobetternorge.no" class="lt-nav__brand">
<picture>
<source srcset="assets/images/logo-header.webp" type="image/webp">
<img class="lt-nav__logo" src="assets/images/logo-header.png" alt="Do Better Norge" width="140" height="36" loading="eager">
</picture>
<span class="lt-nav__badge">Legal Tools</span>
</a>
<div class="lt-nav__right">
<nav class="shell-lang-switcher" aria-label="Language">
<?php foreach (dbnToolsSupportedLanguages() as $langCode): ?>
<a href="<?= htmlspecialchars($langPath . '?lang=' . $langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
<?php endforeach; ?>
</nav>
<?php if ($isAuthed): ?>
<a href="/redact.php" class="lt-nav__cta lt-nav__cta--enter"><?= htmlspecialchars($t['nav_open']) ?></a>
<?php else: ?>
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="lt-nav__cta"><?= htmlspecialchars($t['nav_signin']) ?></a>
<?php endif; ?>
</div>
</header>
<nav class="kdoc-doc-nav" aria-label="Redact documentation">
<div class="kdoc-doc-nav__inner">
<a href="/redact-about.php"><?= htmlspecialchars($t['nav_about']) ?></a>
<a href="/redact-guide.php"><?= htmlspecialchars($t['nav_guide']) ?></a>
<a href="/redact-tech.php" class="is-active"><?= htmlspecialchars($t['nav_howit']) ?></a>
<?php if ($isAuthed): ?><a href="/redact.php"><?= htmlspecialchars($t['nav_opentool']) ?></a><?php endif; ?>
</div>
</nav>
<!-- Hero -->
<section class="kdoc-hero" style="background: linear-gradient(rgba(5,15,40,0.85),rgba(5,15,40,0.92)), url('assets/images/timeline/hero-tech.png') center/cover no-repeat;">
<div class="kdoc-hero__inner">
<p class="kdoc-hero__kicker"><?= htmlspecialchars($t['hero_kicker']) ?></p>
<h1 class="kdoc-hero__title"><?= htmlspecialchars($t['hero_title']) ?></h1>
<p class="kdoc-hero__sub"><?= htmlspecialchars($t['hero_sub']) ?></p>
<div class="kdoc-hero__stats">
<div class="kdoc-hero__stat">
<strong>2</strong>
<span><?= htmlspecialchars($t['stat1']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>4</strong>
<span><?= htmlspecialchars($t['stat2']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>3</strong>
<span><?= htmlspecialchars($t['stat3']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>2</strong>
<span><?= htmlspecialchars($t['stat4']) ?></span>
</div>
</div>
</div>
</section>
<!-- Architecture overview -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['arch_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['arch_title']) ?></h2>
<p class="kdoc-section__sub"><?= htmlspecialchars($t['arch_sub']) ?></p>
<div class="kdoc-pipeline">
<div class="kdoc-pipeline__pass">
<span class="kdoc-pipeline__pass-badge kdoc-pipeline__pass-badge--mini">Pass 1 &middot; PHP / regex</span>
<h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass1_title']) ?></h3>
<p class="kdoc-pipeline__pass-body"><?= $t['pass1_p1_html'] ?></p>
<ul>
<li><?= $t['pass1_li1_html'] ?></li>
<li><?= htmlspecialchars($t['pass1_li2']) ?></li>
<li><?= htmlspecialchars($t['pass1_li3']) ?></li>
<li><?= htmlspecialchars($t['pass1_li4']) ?></li>
<li><?= htmlspecialchars($t['pass1_li5']) ?></li>
</ul>
<p class="kdoc-pipeline__pass-body" style="margin-top:0.7rem;"><?= htmlspecialchars($t['pass1_p2']) ?></p>
</div>
<div class="kdoc-pipeline__arrow-down" aria-hidden="true">&rarr;</div>
<div class="kdoc-pipeline__pass">
<span class="kdoc-pipeline__pass-badge">Pass 2 &middot; gpt-4o-mini / gpt-4o</span>
<h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass2_title']) ?></h3>
<p class="kdoc-pipeline__pass-body"><?= $t['pass2_p1_html'] ?></p>
<ul>
<li><?= htmlspecialchars($t['pass2_li1']) ?></li>
<li><?= htmlspecialchars($t['pass2_li2']) ?></li>
<li><?= htmlspecialchars($t['pass2_li3']) ?></li>
<li><?= htmlspecialchars($t['pass2_li4']) ?></li>
</ul>
<p class="kdoc-pipeline__pass-body" style="margin-top:0.7rem;"><?= htmlspecialchars($t['pass2_p2']) ?></p>
</div>
<div class="kdoc-pipeline__arrow-down" aria-hidden="true">&rarr;</div>
<div class="kdoc-pipeline__pass">
<span class="kdoc-pipeline__pass-badge kdoc-pipeline__pass-badge--optional">Pass 3 &middot; PHP post-processor</span>
<h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass3_title']) ?></h3>
<p class="kdoc-pipeline__pass-body"><?= $t['pass3_p1_html'] ?></p>
<ul>
<li><?= $t['pass3_f1_html'] ?></li>
<li><?= $t['pass3_f2_html'] ?></li>
<li><?= $t['pass3_f3_html'] ?></li>
<li><?= $t['pass3_f4_html'] ?></li>
</ul>
<p class="kdoc-pipeline__pass-body" style="margin-top:0.7rem;"><?= $t['pass3_p2_html'] ?></p>
</div>
</div>
</div>
<!-- Regional patterns -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['date_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['date_title']) ?></h2>
<p class="kdoc-section__sub"><?= htmlspecialchars($t['date_sub']) ?></p>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_region']) ?></th>
<th><?= htmlspecialchars($t['th_patterns']) ?></th>
<th><?= htmlspecialchars($t['th_notes']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Nordic &#9733;</td>
<td>Fødselsnummer, D-number, +47 phone, email, Norwegian address</td>
<td><?= htmlspecialchars($t['rn1']) ?></td>
</tr>
<tr>
<td>European</td>
<td>+ IBAN, Swedish personnummer, Danish CPR, Finnish HETU, UK NI</td>
<td><?= htmlspecialchars($t['rn2']) ?></td>
</tr>
<tr>
<td>ECHR</td>
<td>+ ECHR application numbers, DOB phrases, ECtHR case references</td>
<td><?= htmlspecialchars($t['rn3']) ?></td>
</tr>
<tr>
<td>Global</td>
<td>+ US SSN, driver's licence formats, generic document numbers</td>
<td><?= htmlspecialchars($t['rn4']) ?></td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- Classification schema -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['class_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['class_title']) ?></h2>
<h3 style="font-family:'Crimson Pro',serif; font-size:1.15rem; font-weight:700; margin:0 0 0.8rem; color:var(--dbn-blue);"><?= htmlspecialchars($t['class_h1']) ?></h3>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_entity']) ?></th>
<th><?= htmlspecialchars($t['th_definition']) ?></th>
<th><?= htmlspecialchars($t['th_output']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>person</code></td>
<td><?= htmlspecialchars($t['et1_def']) ?></td>
<td><?= htmlspecialchars($t['et1_out']) ?></td>
</tr>
<tr>
<td><code>organisation</code></td>
<td><?= htmlspecialchars($t['et2_def']) ?></td>
<td><?= htmlspecialchars($t['et2_out']) ?></td>
</tr>
<tr>
<td><code>place</code></td>
<td><?= htmlspecialchars($t['et3_def']) ?></td>
<td><?= htmlspecialchars($t['et3_out']) ?></td>
</tr>
<tr>
<td><code>date</code></td>
<td><?= htmlspecialchars($t['et4_def']) ?></td>
<td><?= htmlspecialchars($t['et4_out']) ?></td>
</tr>
</tbody>
</table>
<h3 style="font-family:'Crimson Pro',serif; font-size:1.15rem; font-weight:700; margin:2rem 0 0.8rem; color:var(--dbn-blue);"><?= htmlspecialchars($t['class_h2']) ?></h3>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_format']) ?></th>
<th><?= htmlspecialchars($t['th_person_ex']) ?></th>
<th><?= htmlspecialchars($t['th_org_ex']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Contextual &#9733;</td>
<td><code><?= htmlspecialchars($t['fmt1_person']) ?></code></td>
<td><code><?= htmlspecialchars($t['fmt1_org']) ?></code></td>
</tr>
<tr>
<td>Generic</td>
<td><code><?= htmlspecialchars($t['fmt2_person']) ?></code></td>
<td><code><?= htmlspecialchars($t['fmt2_org']) ?></code></td>
</tr>
<tr>
<td>Pseudonym</td>
<td><em><?= htmlspecialchars($t['fmt3_person']) ?></em></td>
<td><em><?= htmlspecialchars($t['fmt3_org']) ?></em></td>
</tr>
</tbody>
</table>
</div>
<!-- Multi-engine -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['eng_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['eng_title']) ?></h2>
<p class="kdoc-section__sub"><?= htmlspecialchars($t['eng_sub']) ?></p>
<table class="kdoc-table">
<thead>
<tr>
<th><?= htmlspecialchars($t['th_engine']) ?></th>
<th><?= htmlspecialchars($t['th_model']) ?></th>
<th><?= htmlspecialchars($t['th_latency']) ?></th>
<th><?= htmlspecialchars($t['th_best']) ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Azure gpt-4o-mini &#9733;</td>
<td><code>gpt-4o-mini</code> (Azure West Europe)</td>
<td>~15 s</td>
<td><?= htmlspecialchars($t['eng1_best']) ?></td>
</tr>
<tr>
<td>Azure gpt-4o</td>
<td><code>gpt-4o</code> (Azure West Europe)</td>
<td>~45 s</td>
<td><?= htmlspecialchars($t['eng2_best']) ?></td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- Privacy by design -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['priv_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['priv_title']) ?></h2>
<div class="kdoc-privacy">
<p class="kdoc-privacy__title"><?= htmlspecialchars($t['priv_badge']) ?></p>
<ul>
<li><?= $t['priv_1_html'] ?></li>
<li><?= htmlspecialchars($t['priv_2']) ?></li>
<li><?= $t['priv_3_html'] ?></li>
<li><?= $t['priv_4_html'] ?></li>
<li><?= $t['priv_5_html'] ?></li>
</ul>
</div>
</div>
<!-- CTA -->
<section class="kdoc-cta-strip">
<h2 class="kdoc-cta-strip__title"><?= htmlspecialchars($t['cta_title']) ?></h2>
<p class="kdoc-cta-strip__sub"><?= htmlspecialchars($t['cta_sub']) ?></p>
<div class="kdoc-hero__ctas">
<?php if ($isAuthed): ?>
<a href="/redact.php" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_open']) ?></a>
<?php else: ?>
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_signin_cta']) ?></a>
<a href="<?= htmlspecialchars($registerUrl) ?>" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_register']) ?></a>
<?php endif; ?>
<a href="/redact-guide.php" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_guide']) ?></a>
</div>
</section>
<?php require_once __DIR__ . '/includes/footer.php'; ?>
<script src="assets/js/tools.js" defer></script>
</body>
</html>
+8
View File
@@ -8,6 +8,14 @@ require_once __DIR__ . '/includes/layout.php';
?>
<form id="toolForm" class="tool-form" novalidate>
<div class="korr-doc-links">
<a href="/redact-about.php" target="_blank">About this tool</a>
<span aria-hidden="true">&middot;</span>
<a href="/redact-guide.php" target="_blank">User guide</a>
<span aria-hidden="true">&middot;</span>
<a href="/redact-tech.php" target="_blank">How it works</a>
</div>
<div class="lang-switcher" id="redactLangSwitcher" role="group" aria-label="UI language">
<button type="button" class="lang-btn is-active" data-lang="en">&#127468;&#127463; EN</button>
<button type="button" class="lang-btn" data-lang="no">&#127475;&#127476; NO</button>
+14 -14
View File
@@ -182,32 +182,32 @@ $t = $_pt[$uiLang] ?? $_pt['en'];
</div>
</section>
<!-- Fine-tuned LLM spotlight -->
<!-- Export & live progress spotlight -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['hood_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['hood_title']) ?></h2>
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['export_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['export_title']) ?></h2>
<div class="kdoc-llm-spotlight">
<div>
<span class="kdoc-llm-spotlight__badge"><?= htmlspecialchars($t['llm_badge']) ?></span>
<h3 class="kdoc-llm-spotlight__title">dbn-legal-agent</h3>
<p class="kdoc-llm-spotlight__body"><?= $t['llm_body_html'] ?></p>
<span class="kdoc-llm-spotlight__badge"><?= htmlspecialchars($t['export_badge']) ?></span>
<h3 class="kdoc-llm-spotlight__title"><?= htmlspecialchars($t['export_h1']) ?></h3>
<p class="kdoc-llm-spotlight__body"><?= $t['export_body_html'] ?></p>
</div>
<div class="kdoc-llm-stats">
<div class="kdoc-llm-stat">
<strong>QLoRA</strong>
<span><?= htmlspecialchars($t['llm_s1']) ?></span>
<strong>SSE</strong>
<span><?= htmlspecialchars($t['export_s1']) ?></span>
</div>
<div class="kdoc-llm-stat">
<strong>12+</strong>
<span><?= htmlspecialchars($t['llm_s2']) ?></span>
<strong>DOCX</strong>
<span><?= htmlspecialchars($t['export_s2']) ?></span>
</div>
<div class="kdoc-llm-stat">
<strong>5</strong>
<span><?= htmlspecialchars($t['llm_s3']) ?></span>
<strong>Azure</strong>
<span><?= htmlspecialchars($t['export_s3']) ?></span>
</div>
<div class="kdoc-llm-stat">
<strong>GPU</strong>
<span><?= htmlspecialchars($t['llm_s4']) ?></span>
<strong>2</strong>
<span><?= htmlspecialchars($t['export_s4']) ?></span>
</div>
</div>
</div>
-5
View File
@@ -118,11 +118,6 @@ $t = $_pt[$uiLang] ?? $_pt['en'];
<td><?= htmlspecialchars($t['eng2_speed']) ?></td>
<td><?= htmlspecialchars($t['eng2_best']) ?></td>
</tr>
<tr>
<td>GPU / cuttlefish</td>
<td><?= htmlspecialchars($t['eng3_speed']) ?></td>
<td><?= htmlspecialchars($t['eng3_best']) ?></td>
</tr>
</tbody>
</table>
</div>
+14 -22
View File
@@ -83,7 +83,7 @@ $t = $_pt[$uiLang] ?? $_pt['en'];
<span><?= htmlspecialchars($t['stat3']) ?></span>
</div>
<div class="kdoc-hero__stat">
<strong>3</strong>
<strong>2</strong>
<span><?= htmlspecialchars($t['stat4']) ?></span>
</div>
</div>
@@ -111,7 +111,7 @@ $t = $_pt[$uiLang] ?? $_pt['en'];
</div>
<div class="kdoc-pipeline__arrow-down" aria-hidden="true">&rarr;</div>
<div class="kdoc-pipeline__pass">
<span class="kdoc-pipeline__pass-badge">Pass 2 &middot; gpt-4o-mini / gpt-4o / dbn-legal-agent</span>
<span class="kdoc-pipeline__pass-badge">Pass 2 &middot; gpt-4o-mini / gpt-4o</span>
<h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass2_title']) ?></h3>
<p class="kdoc-pipeline__pass-body"><?= $t['pass2_p1_html'] ?></p>
<ul>
@@ -350,35 +350,27 @@ $t = $_pt[$uiLang] ?? $_pt['en'];
<td>~45 s</td>
<td><?= htmlspecialchars($t['eng2_best']) ?></td>
</tr>
<tr>
<td>GPU / cuttlefish</td>
<td><code>dbn-legal-agent</code> via LiteLLM proxy</td>
<td>~25 s</td>
<td><?= htmlspecialchars($t['eng3_best']) ?></td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- Fine-tuned LLM -->
<!-- Streaming & export -->
<div class="kdoc-section">
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['ft_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['ft_title']) ?></h2>
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['stream_eyebrow']) ?></p>
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['stream_title']) ?></h2>
<div class="kdoc-finetune">
<span class="kdoc-finetune__badge"><?= htmlspecialchars($t['ft_badge']) ?></span>
<h3 class="kdoc-finetune__title">dbn-legal-agent</h3>
<p class="kdoc-finetune__body"><?= htmlspecialchars($t['ft_p1']) ?></p>
<p class="kdoc-finetune__body" style="margin-top:0.8rem;"><?= htmlspecialchars($t['ft_p2']) ?></p>
<span class="kdoc-finetune__badge">SSE + DOCX</span>
<h3 class="kdoc-finetune__title"><?= htmlspecialchars($t['stream_h1']) ?></h3>
<p class="kdoc-finetune__body"><?= htmlspecialchars($t['stream_p1']) ?></p>
<p class="kdoc-finetune__body" style="margin-top:0.8rem;"><?= htmlspecialchars($t['stream_p2']) ?></p>
<div class="kdoc-finetune__chips">
<span class="kdoc-finetune__chip">QLoRA</span>
<span class="kdoc-finetune__chip">Norwegian legal corpus</span>
<span class="kdoc-finetune__chip">case notes</span>
<span class="kdoc-finetune__chip">court decisions</span>
<span class="kdoc-finetune__chip">Barnevernet</span>
<span class="kdoc-finetune__chip">Fylkesnemnda</span>
<span class="kdoc-finetune__chip">LiteLLM proxy</span>
<span class="kdoc-finetune__chip">Server-Sent Events</span>
<span class="kdoc-finetune__chip">OOXML / .docx</span>
<span class="kdoc-finetune__chip">ZipArchive</span>
<span class="kdoc-finetune__chip">live progress</span>
<span class="kdoc-finetune__chip">Save to My Docs</span>
</div>
</div>
</div>
+143
View File
@@ -0,0 +1,143 @@
<?php
return array (
'en' =>
array (
'nav_about' => 'About',
'nav_guide' => 'User guide',
'nav_howit' => 'How it works',
'nav_opentool' => '← Open the tool',
'nav_signin' => 'Sign in',
'nav_open' => 'Open Redact →',
'hero_kicker' => 'Anonymisation · Privacy · Legal Documents',
'hero_title' => 'Remove names. Keep meaning.',
'hero_sub' => 'Redact reads Norwegian case notes, court decisions, and correspondence — then replaces names, organisations, addresses, and ID numbers with contextual role tags, generic labels, or plausible pseudonyms. Ready for court submission in seconds.',
'stat_engines' => 'AI engines',
'stat_regions' => 'regional rule sets',
'stat_formats' => 'output formats',
'stat_passes' => 'processing passes',
'btn_try' => 'Try Redact free →',
'btn_guide' => 'User guide',
'btn_howit' => 'How it works',
'what_eyebrow' => 'What you get',
'what_title' => 'Three things that change how you protect a case.',
'f1_title' => 'Pattern + LLM hybrid redaction',
'f1_body_html' => 'A deterministic first pass catches Norwegian ID numbers, phone numbers, emails, and addresses using regex patterns. The LLM then sweeps for names, organisations, places, and anything the patterns missed — combining predictability with language intelligence.',
'f2_title' => 'Contextual role tags',
'f2_body' => 'Instead of [PERSON], you get [FATHER], [JUDGE: Andersen], [SOCIAL WORKER]. Each person keeps a functional label so you can follow the narrative without knowing who they are. Names are gone; roles remain.',
'f3_title' => 'Export-ready Word document',
'f3_body' => 'Download the redacted document as a .docx file in one click. No formatting loss, correct typography. Ready to attach to a court submission, share with a lawyer, or include in a complaint file.',
'how_eyebrow' => 'How it works',
'how_title' => 'Upload → configure → download. Under a minute.',
'how_sub' => 'Three steps from raw sensitive document to a clean, submission-ready redacted version.',
's1_title' => 'Upload or paste the document',
's1_body' => 'Upload one file (PDF, DOCX, or TXT) or paste up to 128,000 characters of text. The raw content is never written to disk — all processing happens in memory.',
's1_example' => 'Supports: case notes, court decisions, Barnevernet letters, NAV correspondence, medical records.',
's2_title' => 'Configure what to redact',
's2_body' => 'Choose your engine, redaction mode (Standard or Strict), regional rule set (Nordic, European, ECHR, or Global), which entity types to redact, and whether to keep official names. Add exempt names or custom aliases if needed.',
's2_example' => 'E.g. keep the judge\'s name but redact all parties. Or replace "Ola Nordmann" with [FATHER] throughout.',
's3_title' => 'Review and download',
's3_body' => 'The redacted text appears with all protected content replaced. Download as .docx, save to My Docs, or copy the text directly. Review the redaction log for a summary of what was replaced.',
's3_example' => 'Download as Word → Save to My Docs → Copy text',
'ss_eyebrow' => 'Screenshots',
'ss_title' => 'See it in action.',
'g1_caption' => 'The form: engine selector, mode, region, entity toggles, output format, and file upload zone.',
'g2_caption' => 'Redacted output with contextual role tags: [FATHER], [SOCIAL WORKER], [JUDGE: Hansen].',
'g3_caption' => 'Pseudonym output: names replaced with plausible Norwegian substitutes, phone numbers rewritten.',
'g4_caption' => 'Save to My Docs or download as .docx — submission-ready in one click.',
'output_eyebrow' => 'Output formats',
'output_title' => 'Three ways to protect identities.',
'output_badge' => 'Choose your style',
'output_h1' => 'Contextual · Generic · Pseudonym',
'output_body_html' => 'Choose <strong>Contextual tags</strong> to replace each person with their role — [FATHER], [JUDGE: Andersen] — keeping the narrative readable without exposing identities. Choose <strong>Generic tags</strong> for maximum anonymisation ([PERSON], [ORG]). Choose <strong>Pseudonyms</strong> to substitute plausible Norwegian names, phone numbers, and addresses throughout — useful when a human-readable document is needed.',
'output_s1' => 'contextual',
'output_s2' => 'generic',
'output_s3' => 'pseudonym',
'output_s4' => 'output formats',
'region_eyebrow' => 'Regional rule sets',
'region_title' => 'Redaction rules that match your jurisdiction.',
'region_sub' => 'Four regional profiles configure which identifier patterns the regex first-pass targets. The LLM pass always runs on top of whichever profile is active.',
'rr1_title' => 'Nordic ★',
'rr1_body' => 'Norwegian fødselsnummer (11-digit), D-number, phone numbers (+47 format), email addresses, Norwegian postal addresses (postnummer + poststed). Default for Norwegian case material.',
'rr2_title' => 'European',
'rr2_body' => 'Adds IBAN, Swedish personnummer, Danish CPR-nummer, Finnish HETU, and UK National Insurance number to the Nordic set.',
'rr3_title' => 'ECHR',
'rr3_body' => 'Adds ECHR application numbers, date-of-birth phrases, and ECtHR case references. Use for complaints to the European Court of Human Rights.',
'rr4_title' => 'Global',
'rr4_body' => 'Adds US Social Security Number, driver\'s licence formats, and generic document number patterns. Use for documents involving non-European jurisdictions.',
'cta_title' => 'Ready to protect your documents?',
'cta_sub' => 'Free for Do Better Norge members. No credit card required.',
'btn_open' => 'Open Redact →',
'btn_signin_cta' => 'Sign in to use Redact →',
'btn_register' => 'Register free',
),
'no' =>
array (
'nav_about' => 'Om',
'nav_guide' => 'Brukerveiledning',
'nav_howit' => 'Slik fungerer det',
'nav_opentool' => '← Åpne verktøyet',
'nav_signin' => 'Logg inn',
'nav_open' => 'Åpne Sladding →',
'hero_kicker' => 'Anonymisering · Personvern · Juridiske dokumenter',
'hero_title' => 'Fjern navn. Behold mening.',
'hero_sub' => 'Sladding leser norske saksnotater, rettsavgjørelser og korrespondanse — og erstatter deretter navn, organisasjoner, adresser og ID-numre med kontekstuelle rollekoder, generiske etiketter eller plausible pseudonymer. Klar til innsending i løpet av sekunder.',
'stat_engines' => 'AI-motorer',
'stat_regions' => 'regionale regelsett',
'stat_formats' => 'utdataformater',
'stat_passes' => 'behandlingspass',
'btn_try' => 'Prøv Sladding gratis →',
'btn_guide' => 'Brukerveiledning',
'btn_howit' => 'Slik fungerer det',
'what_eyebrow' => 'Hva du får',
'what_title' => 'Tre ting som endrer hvordan du beskytter en sak.',
'f1_title' => 'Mønster + LLM hybrid sladding',
'f1_body_html' => 'Et deterministisk første pass fanger opp norske ID-numre, telefonnumre, e-postadresser og adresser ved hjelp av regex-mønstre. LLM søker deretter etter navn, organisasjoner, steder og alt mønstrene gikk glipp av.',
'f2_title' => 'Kontekstuelle rollekoder',
'f2_body' => 'I stedet for [PERSON] får du [FAR], [DOMMER: Andersen], [SAKSBEHANDLER]. Hver person beholder en funksjonell etikett slik at du kan følge narrativet uten å vite hvem de er.',
'f3_title' => 'Eksportklart Word-dokument',
'f3_body' => 'Last ned det sladdede dokumentet som .docx-fil med ett klikk. Klar til å legges ved en rettssak, deles med en advokat eller inkluderes i en klagesak.',
'how_eyebrow' => 'Slik fungerer det',
'how_title' => 'Last opp → konfigurer → last ned. Under ett minutt.',
'how_sub' => 'Tre steg fra et sensitivt råmateriale til en ren, klargjo̊rt sladdversjon.',
's1_title' => 'Last opp eller lim inn dokumentet',
's1_body' => 'Last opp én fil (PDF, DOCX eller TXT) eller lim inn opptil 128 000 tegn med tekst. Råinnholdet skrives aldri til disk — all behandling skjer i minnet.',
's1_example' => 'Støtter: saksnotater, rettsavgjørelser, Barnevernet-brev, NAV-korrespondanse, medisinske journaler.',
's2_title' => 'Konfigurer hva som skal sladdes',
's2_body' => 'Velg motor, sladdmodus (Standard eller Streng), regionalt regelsett (Nordisk, Europeisk, EMD eller Global), hvilke enhetstyper som skal sladdes, og om offisielle navn skal beholdes.',
's2_example' => 'F.eks. behold dommernavn, men sladd alle parter. Eller erstatt «Ola Nordmann» med [FAR] overalt.',
's3_title' => 'Gjennomgå og last ned',
's3_body' => 'Den sladdede teksten vises med alt beskyttet innhold erstattet. Last ned som .docx, lagre i Mine Dok eller kopier teksten direkte.',
's3_example' => 'Last ned som Word → Lagre i Mine Dok → Kopier tekst',
'ss_eyebrow' => 'Skjermbilder',
'ss_title' => 'Se det i aksjon.',
'g1_caption' => 'Skjemaet: motorvalg, modus, region, enhetsveksler, utdataformat og filopplastingssone.',
'g2_caption' => 'Sladdede utdata med kontekstuelle rollekoder: [FAR], [SAKSBEHANDLER], [DOMMER: Hansen].',
'g3_caption' => 'Pseudonymutdata: navn erstattet med plausible norske substitusjoner, telefonnumre omskrevet.',
'g4_caption' => 'Lagre i Mine Dok eller last ned som .docx — klart til innsending med ett klikk.',
'output_eyebrow' => 'Utdataformater',
'output_title' => 'Tre måter å beskytte identiteter på.',
'output_badge' => 'Velg din stil',
'output_h1' => 'Kontekstuell · Generisk · Pseudonym',
'output_body_html' => 'Velg <strong>Kontekstuelle koder</strong> for å erstatte hver person med rollen sin — [FAR], [DOMMER: Andersen] — slik at narrativet forblir lesbart uten å avsløre identiteter. Velg <strong>Generiske koder</strong> for maksimal anonymisering ([PERSON], [ORG]). Velg <strong>Pseudonymer</strong> for å sette inn plausible norske navn, telefonnumre og adresser.',
'output_s1' => 'kontekstuell',
'output_s2' => 'generisk',
'output_s3' => 'pseudonym',
'output_s4' => 'utdataformater',
'region_eyebrow' => 'Regionale regelsett',
'region_title' => 'Sladderegler tilpasset din jurisdiksjon.',
'region_sub' => 'Fire regionale profiler konfigurerer hvilke identifikatormønstre regex-første-passet retter seg mot.',
'rr1_title' => 'Nordisk ★',
'rr1_body' => 'Norsk fødselsnummer (11 sifre), D-nummer, telefonnumre (+47-format), e-postadresser, norske postadresser. Standard for norsk saksmateriale.',
'rr2_title' => 'Europeisk',
'rr2_body' => 'Legger til IBAN, svensk personnummer, dansk CPR-nummer, finsk HETU og britisk National Insurance-nummer til det nordiske settet.',
'rr3_title' => 'EMD',
'rr3_body' => 'Legger til EMD-saksnumre, fødselsdatofraser og EMD-saksreferanser. Bruk for klager til Den europeiske menneskerettighetsdomstolen.',
'rr4_title' => 'Global',
'rr4_body' => 'Legger til amerikanske SSN-numre, førerkortsformater og generiske dokumentnummermønstre. Bruk for dokumenter som involverer ikke-europeiske jurisdiksjoner.',
'cta_title' => 'Klar til å beskytte dokumentene dine?',
'cta_sub' => 'Gratis for Do Better Norge-medlemmer. Ingen kredittkort nødvendig.',
'btn_open' => 'Åpne Sladding →',
'btn_signin_cta' => 'Logg inn for å bruke Sladding →',
'btn_register' => 'Registrer gratis',
),
);
+173
View File
@@ -0,0 +1,173 @@
<?php
return array (
'en' =>
array (
'nav_about' => 'About',
'nav_guide' => 'User guide',
'nav_howit' => 'How it works',
'nav_opentool' => '← Open the tool',
'nav_signin' => 'Sign in',
'nav_open' => 'Open Redact →',
'hero_kicker' => 'User Guide · Redact',
'hero_title' => 'How to use Redact.',
'hero_sub' => 'A step-by-step walkthrough of every control — from choosing your engine and region to reading the redacted output, downloading as Word, and saving to My Docs.',
'toc_title' => 'In this guide',
'toc_1' => 'Choose your engine',
'toc_2' => 'Redaction mode',
'toc_3' => 'Region',
'toc_4' => 'What to redact',
'toc_5' => 'Officials toggle',
'toc_6' => 'Output format',
'toc_7' => 'Exempt names',
'toc_8' => 'Name aliases',
'toc_9' => 'Upload or paste',
'toc_10' => 'Reading the output & downloading',
'step1_title' => 'Choose your engine',
'step1_intro' => 'The engine controls the AI model used for the LLM redaction sweep. Both engines use Azure OpenAI (West Europe). gpt-4o-mini costs 1 credit and handles most documents well; gpt-4o costs 2 credits and is better for dense, complex, or multi-person documents.',
'th_engine' => 'Engine',
'th_cost' => 'Cost',
'th_best' => 'Best for',
'eng1_cost' => '1 credit',
'eng1_best' => 'Default. Everyday redaction, single-person documents, standard case notes.',
'eng2_cost' => '2 credits',
'eng2_best' => 'Complex documents with many named parties, overlapping roles, or poor formatting.',
'step2_title' => 'Redaction mode',
'step2_intro' => 'Mode controls how aggressively the tool redacts. Found in the Advanced settings panel.',
'th_mode' => 'Mode',
'th_does' => 'What it does',
'mode1_does' => 'Pattern matching + LLM sweep for known entity types (names, orgs, places, ID numbers). Balanced accuracy and precision.',
'mode2_does' => 'Also replaces any capitalised two-word phrase as a potential name. More aggressive — use when you need certainty over precision. May produce false positives in formal text.',
'step3_title' => 'Region',
'step3_intro' => 'Region configures which identifier patterns the regex first-pass targets. The LLM pass always runs regardless of region.',
'th_region' => 'Region',
'th_targets' => 'Targets',
'reg1_targets' => 'Norwegian fødselsnummer, D-number, +47 phone, email, Norwegian addresses',
'reg2_targets' => 'Adds IBAN, Swedish personnummer, Danish CPR, Finnish HETU, UK NI',
'reg3_targets' => 'Adds ECHR application numbers, DOB phrases, ECtHR case references',
'reg4_targets' => 'Adds US SSN, driver\'s licence formats, generic document numbers',
'step4_title' => 'What to redact',
'step4_intro' => 'Four checkboxes toggle which entity types the LLM looks for. All are checked by default.',
'th_entity' => 'Entity type',
'th_entity_desc' => 'What is replaced',
'ent1_desc' => 'Personal names — first name, surname, or full name of any individual',
'ent2_desc' => 'Organisations — companies, agencies, authorities, institutions',
'ent3_desc' => 'Places — cities, streets, addresses, countries, regions',
'ent4_desc' => 'Dates — dates of birth, age references, specific personal dates',
'step5_title' => 'Officials toggle',
'step5_p1_html' => '<strong>Default: OFF (unchecked).</strong> When unchecked, all names — including judges, experts, social workers, and lawyers — are replaced with generic role tags like [PERSON] or contextual tags like [JUDGE].',
'step5_p2_html' => '<strong>When to check:</strong> tick "Keep official names (judges, experts)" to preserve the names of named officials in a labelled tag: <em>[JUDGE: Andersen]</em>, <em>[EXPERT WITNESS: Dr. Hansen]</em>. Use this when the official\'s identity is legally relevant and must remain visible in the redacted version — for example, when submitting to a court that knows the judge.',
'step6_title' => 'Output format',
'step6_intro' => 'Three options control how redacted content is represented in the output.',
'th_format' => 'Format',
'th_result' => 'Result',
'fmt1_result' => 'Each person gets a descriptive role tag. [FATHER], [MOTHER], [JUDGE: Name if officials kept]. Narrative remains readable. Best for most legal filings.',
'fmt2_result' => 'All persons become [PERSON], organisations [ORG], places [PLACE]. Maximum anonymisation with no role context.',
'fmt3_result' => 'Names replaced with plausible Norwegian substitutes (Ola Nordmann, Kari Hansen). Phone numbers rewritten. Addresses replaced with fictional Norwegian addresses. Best when a human-readable document is required.',
'step7_title' => 'Exempt names',
'step7_p1_html' => '<strong>Names listed here are never redacted</strong> — even if the AI would otherwise remove them. Use this for names that must remain visible in the output, such as a public figure, a quoted source, or an institution name that is part of the case reference.',
'step7_p2_html' => 'Add each name on its own row. The match is case-insensitive. Partial matches are not supported — enter the name exactly as it appears in the document.',
'step8_title' => 'Name aliases',
'step8_p1_html' => '<strong>Replace a specific name with a custom bracketed label.</strong> For example: "David Jr" → [Junior], or "Kari Pettersen" → [SISTER]. Useful when the document uses a name that the LLM might not recognise as a person, or when you want a specific label instead of the AI\'s default choice.',
'step8_p2_html' => 'Aliases are applied as a final substitution step after both redaction passes complete. They override whatever the LLM assigned to that name.',
'step9_title' => 'Upload or paste',
'step9_p1_html' => 'Drag a file onto the upload zone or click <strong>browse</strong>. Supported formats: <strong>PDF</strong>, <strong>DOCX</strong>, <strong>TXT</strong>. One file per run.',
'step9_p2_html' => 'You can also paste text directly into the main text area — or combine a file and pasted text. All sources are processed together as a single input.',
'step9_p3' => 'Files are extracted to text in memory. Nothing is written to disk or retained after the session ends.',
'step10_title' => 'Reading the output & downloading',
'step10_intro' => 'After the tool runs, the redacted text appears in the results section. What you can do from here:',
'dl1_html' => '<strong>Export to Word</strong> — downloads a formatted .docx with the full redacted text, ready to attach to a submission.',
'dl2_html' => '<strong>Save to My Docs</strong> — saves the redacted version to your My Docs library for later retrieval and use in other tools.',
'dl3_html' => '<strong>Copy text</strong> — copies the plain redacted text to the clipboard for pasting into another document.',
'cta_title' => 'Ready to try it on your documents?',
'cta_sub' => 'Free for Do Better Norge members.',
'btn_open' => 'Open Redact →',
'btn_signin_cta' => 'Sign in to use Redact →',
'btn_register' => 'Register free',
'btn_techlink' => 'How it works →',
),
'no' =>
array (
'nav_about' => 'Om',
'nav_guide' => 'Brukerveiledning',
'nav_howit' => 'Slik fungerer det',
'nav_opentool' => '← Åpne verktøyet',
'nav_signin' => 'Logg inn',
'nav_open' => 'Åpne Sladding →',
'hero_kicker' => 'Brukerveiledning · Sladding',
'hero_title' => 'Slik bruker du Sladding.',
'hero_sub' => 'En trinnvis gjennomgang av alle kontroller — fra valg av motor og region til å lese sladdede utdata, laste ned som Word og lagre i Mine Dok.',
'toc_title' => 'I denne veiledningen',
'toc_1' => 'Velg motor',
'toc_2' => 'Sladdmodus',
'toc_3' => 'Region',
'toc_4' => 'Hva som skal sladdes',
'toc_5' => 'Offisielle veksler',
'toc_6' => 'Utdataformat',
'toc_7' => 'Unntak for navn',
'toc_8' => 'Navnaliaser',
'toc_9' => 'Last opp eller lim inn',
'toc_10' => 'Les utdata og last ned',
'step1_title' => 'Velg motor',
'step1_intro' => 'Motoren kontrollerer AI-modellen som brukes for LLM-sladdsøk. Begge motorer bruker Azure OpenAI (Vest-Europa). gpt-4o-mini koster 1 kreditt og håndterer de fleste dokumenter godt; gpt-4o koster 2 kreditter og er bedre for tette, komplekse eller fler-persons dokumenter.',
'th_engine' => 'Motor',
'th_cost' => 'Kostnad',
'th_best' => 'Best for',
'eng1_cost' => '1 kreditt',
'eng1_best' => 'Standard. Hverdagssladding, enkeltpersonsdokumenter, standard saksnotater.',
'eng2_cost' => '2 kreditter',
'eng2_best' => 'Komplekse dokumenter med mange navngitte parter, overlappende roller eller dårlig formatering.',
'step2_title' => 'Sladdmodus',
'step2_intro' => 'Modus kontrollerer hvor aggressivt verktøyet sladder. Finnes i panelet for avanserte innstillinger.',
'th_mode' => 'Modus',
'th_does' => 'Hva det gjør',
'mode1_does' => 'Mønstermatching + LLM-søk for kjente enhetstyper (navn, organisasjoner, steder, ID-numre). Balansert nøyaktighet og presisjon.',
'mode2_does' => 'Erstatter også store to-ords fraser som potensielle navn. Mer aggressiv — bruk når du trenger sikkerhet over presisjon.',
'step3_title' => 'Region',
'step3_intro' => 'Region konfigurerer hvilke identifikatormønstre regex-første-passet retter seg mot. LLM-passet kjører alltid uavhengig av region.',
'th_region' => 'Region',
'th_targets' => 'Mål',
'reg1_targets' => 'Norsk fødselsnummer, D-nummer, +47-telefon, e-post, norske adresser',
'reg2_targets' => 'Legger til IBAN, svensk personnummer, dansk CPR, finsk HETU, britisk NI',
'reg3_targets' => 'Legger til EMD-saksnumre, fødselsdatofraser, EMD-saksreferanser',
'reg4_targets' => 'Legger til amerikanske SSN-numre, førerkortsformater, generiske dokumentnumre',
'step4_title' => 'Hva som skal sladdes',
'step4_intro' => 'Fire avkrysningsbokser aktiverer hvilke enhetstyper LLM-en ser etter. Alle er merket av som standard.',
'th_entity' => 'Enhetstype',
'th_entity_desc' => 'Hva som erstattes',
'ent1_desc' => 'Personnavn — fornavn, etternavn eller fullt navn på enhver person',
'ent2_desc' => 'Organisasjoner — selskaper, etater, myndigheter, institusjoner',
'ent3_desc' => 'Steder — byer, gater, adresser, land, regioner',
'ent4_desc' => 'Datoer — fødselsdatoer, aldersreferanser, spesifikke personlige datoer',
'step5_title' => 'Offisielle veksler',
'step5_p1_html' => '<strong>Standard: AV (ikke avkrysset).</strong> Når ikke avkrysset, erstattes alle navn — inkludert dommere, eksperter, saksbehandlere og advokater — med generiske rollekoder som [PERSON] eller kontekstuelle koder som [DOMMER].',
'step5_p2_html' => '<strong>Når du skal krysse av:</strong> kryss av «Behold offisielle navn (dommere, eksperter)» for å bevare navnene på navngitte tjenestemenn i en merket kode: <em>[DOMMER: Andersen]</em>. Bruk dette når tjenestmannens identitet er juridisk relevant.',
'step6_title' => 'Utdataformat',
'step6_intro' => 'Tre alternativer styrer hvordan sladdede innhold representeres i utdataene.',
'th_format' => 'Format',
'th_result' => 'Resultat',
'fmt1_result' => 'Hver person får en beskrivende rollekode. [FAR], [MOR], [DOMMER: Navn hvis offisielle beholdes]. Narrativet forblir lesbart.',
'fmt2_result' => 'Alle personer blir [PERSON], organisasjoner [ORG], steder [STED]. Maksimal anonymisering uten rollekontekst.',
'fmt3_result' => 'Navn erstattet med plausible norske substitutter (Ola Nordmann, Kari Hansen). Telefonnumre omskrevet. Adresser erstattet med fiktive norske adresser.',
'step7_title' => 'Unntak for navn',
'step7_p1_html' => '<strong>Navn listet her sladdes aldri</strong> — selv om AI-en ellers ville fjerne dem. Bruk dette for navn som må forbli synlige i utdataene.',
'step7_p2_html' => 'Legg til hvert navn på sin egen rad. Treffet er ikke-skriftssensitivt. Delvise treff støttes ikke — skriv inn navnet nøyaktig slik det vises i dokumentet.',
'step8_title' => 'Navnaliaser',
'step8_p1_html' => '<strong>Erstatt et spesifikt navn med en egendefinert merket etikett.</strong> F.eks.: «David Jr» → [Junior], eller «Kari Pettersen» → [SØSTER].',
'step8_p2_html' => 'Aliaser brukes som et siste substitusjonstrinn etter at begge sladdpassene er fullført. De overstyrer hva LLM-en tildelte det navnet.',
'step9_title' => 'Last opp eller lim inn',
'step9_p1_html' => 'Dra en fil til opplastingssonen eller klikk <strong>bla gjennom</strong>. Støttede formater: <strong>PDF</strong>, <strong>DOCX</strong>, <strong>TXT</strong>. Én fil per kjøring.',
'step9_p2_html' => 'Du kan også lime inn tekst direkte i tekstfeltet — eller kombinere en fil og limt inn tekst. Alle kilder behandles sammen som én inngang.',
'step9_p3' => 'Filer ekstraheres til tekst i minnet. Ingenting skrives til disk eller beholdes etter at sesjonen avsluttes.',
'step10_title' => 'Les utdata og last ned',
'step10_intro' => 'Etter at verktøyet kjøres, vises den sladdede teksten i resultatdelen. Det du kan gjøre herfra:',
'dl1_html' => '<strong>Eksporter til Word</strong> — laster ned en formatert .docx med full sladddet tekst, klar til å legges ved en innsending.',
'dl2_html' => '<strong>Lagre i Mine Dok</strong> — lagrer den sladdede versjonen i Mine Dok-biblioteket ditt for senere henting.',
'dl3_html' => '<strong>Kopier tekst</strong> — kopierer den rene sladdede teksten til utklippstavlen.',
'cta_title' => 'Klar til å prøve det på dokumentene dine?',
'cta_sub' => 'Gratis for Do Better Norge-medlemmer.',
'btn_open' => 'Åpne Sladding →',
'btn_signin_cta' => 'Logg inn for å bruke Sladding →',
'btn_register' => 'Registrer gratis',
'btn_techlink' => 'Slik fungerer det →',
),
);
+199
View File
@@ -0,0 +1,199 @@
<?php
return array (
'en' =>
array (
'nav_about' => 'About',
'nav_guide' => 'User guide',
'nav_howit' => 'How it works',
'nav_opentool' => '← Open the tool',
'nav_signin' => 'Sign in',
'nav_open' => 'Open Redact →',
'hero_kicker' => 'Technical Showcase · How the AI protects documents',
'hero_title' => 'How Redact knows what to replace.',
'hero_sub' => 'A full walkthrough of the two-pass redaction pipeline, regional pattern recognition, entity classification, output format generation, and privacy architecture.',
'stat1' => 'processing passes',
'stat2' => 'regional rule sets',
'stat3' => 'output formats',
'stat4' => 'engine options',
'arch_eyebrow' => 'Architecture',
'arch_title' => 'Two passes. Deterministic first, intelligent second.',
'arch_sub' => 'The pipeline is intentionally layered — Pass 1 catches everything that can be caught by rules alone; Pass 2 handles context-dependent entities that rules cannot identify.',
'pass1_title' => 'Detect & replace known patterns',
'pass1_p1_html' => 'A deterministic regex pass runs before any LLM call. It scans the full input for identifiers matching the active regional profile:',
'pass1_li1_html' => 'Norwegian <code>fødselsnummer</code> (11-digit) and D-number',
'pass1_li2' => 'Phone numbers in +47 format, Norwegian mobile (4xx/9xx) and landline patterns',
'pass1_li3' => 'Email addresses (RFC 5322 simplified)',
'pass1_li4' => 'Norwegian postal addresses: street name + number + postnummer + poststed',
'pass1_li5' => 'Additional patterns per region (IBAN, CPR, ECHR numbers, SSN, etc.)',
'pass1_p2' => 'Pattern-matched tokens are replaced immediately and marked as already redacted so the LLM pass does not double-process them.',
'pass2_title' => 'Sweep for named entities',
'pass2_p1_html' => 'The LLM reads the full document (with pattern-replaced tokens visible as placeholders). It identifies all remaining named entities:',
'pass2_li1' => 'Personal names — first name, surname, or full name; handles Norwegian, Sami, and foreign names',
'pass2_li2' => 'Organisations — companies, government agencies, NGOs, religious bodies, sports clubs',
'pass2_li3' => 'Places — streets, neighbourhoods, municipalities, counties, countries',
'pass2_li4' => 'Date-of-birth and age phrases (when Dates entity type is checked)',
'pass2_p2' => 'Each matched entity is classified by type and role (FATHER, MOTHER, JUDGE, SOCIAL WORKER, etc.) and replaced according to the selected output format. The prompt explicitly instructs the model not to infer or guess identities — only replace what is explicitly named.',
'pass3_title' => 'Post-processing & alias substitution',
'pass3_p1_html' => 'After both passes, PHP applies final transformations:',
'pass3_f1_html' => '<strong>Officials pass</strong> — if Keep official names is checked, named judges, experts, and caseworkers get labelled tags ([JUDGE: Andersen]) instead of generic ones',
'pass3_f2_html' => '<strong>Alias substitution</strong> — user-defined aliases are applied as a final regex replacement, overriding whatever the LLM assigned',
'pass3_f3_html' => '<strong>Exempt name protection</strong> — any token matching an exempt name is restored to its original value',
'pass3_f4_html' => '<strong>Pseudonym generation</strong> — if Pseudonym output is selected, all role tags are replaced with plausible Norwegian names, phone numbers, and addresses drawn from a generation pool',
'pass3_p2_html' => 'The final output is assembled and returned as plain text. The DOCX export converts this to an OOXML document via PHP ZipArchive.',
'date_eyebrow' => 'Regional pattern sets',
'date_title' => 'Four regions. Each adds patterns to the last.',
'date_sub' => 'Regional profiles are cumulative — European adds to Nordic, ECHR adds to European, Global adds to ECHR.',
'th_region' => 'Region',
'th_patterns' => 'Patterns covered',
'th_notes' => 'Notes',
'rn1' => 'Default for Norwegian documents. All local ID formats.',
'rn2' => 'Cross-border EU documents, Nordic neighbours.',
'rn3' => 'Complaints to the European Court of Human Rights.',
'rn4' => 'Documents involving non-European parties or jurisdictions.',
'class_eyebrow' => 'Entity classification',
'class_title' => 'What the LLM identifies and how it labels each type.',
'class_h1' => 'Named entity types',
'th_entity' => 'Entity',
'th_definition' => 'What qualifies',
'th_output' => 'Default output (contextual)',
'et1_def' => 'Any personal name — first, last, or full',
'et1_out' => '[ROLE] — inferred from context (FATHER, MOTHER, JUDGE, etc.)',
'et2_def' => 'Companies, agencies, authorities, institutions, clubs',
'et2_out' => '[ORG: partial name] or generic [ORG]',
'et3_def' => 'Streets, towns, counties, countries, regions',
'et3_out' => '[PLACE] or [CITY] or [ADDRESS]',
'et4_def' => 'Dates of birth, age references, personal date phrases',
'et4_out' => '[DOB] or [AGE: xx]',
'class_h2' => 'Output format comparison',
'th_format' => 'Format',
'th_person_ex' => 'Person example',
'th_org_ex' => 'Org example',
'fmt1_person' => '[FATHER] or [JUDGE: Andersen]',
'fmt1_org' => '[BARNEVERNET: Oslo] or [ORG]',
'fmt2_person' => '[PERSON]',
'fmt2_org' => '[ORG]',
'fmt3_person' => 'Ola Nordmann (generated)',
'fmt3_org' => 'Nordnes AS (generated)',
'eng_eyebrow' => 'Engines',
'eng_title' => 'Two engines, one redaction schema.',
'eng_sub' => 'Both engines produce the same redaction output schema. Engine choice affects accuracy on complex documents and credit cost only.',
'th_engine' => 'Engine',
'th_model' => 'Model',
'th_latency' => 'Latency',
'th_best' => 'Best for',
'eng1_best' => 'Default. Most documents, single subject, clear formatting.',
'eng2_best' => 'Complex documents with many named parties, overlapping roles, or degraded source text.',
'priv_eyebrow' => 'Privacy & security',
'priv_title' => 'Your documents never leave your session.',
'priv_badge' => 'Privacy by design',
'priv_1_html' => 'All uploaded files are extracted to text <strong>in memory</strong> using PHP\'s in-process file handlers. The raw binary is never written to disk on the server.',
'priv_2' => 'Session context (pasted text, uploaded content, redacted output) is scoped to your authenticated session and discarded when the session ends.',
'priv_3_html' => 'Azure OpenAI (<code>gpt-4o</code>, <code>gpt-4o-mini</code>) is configured on the <strong>West Europe</strong> region. Data processed via Azure OpenAI is not used for model training under the default enterprise agreement.',
'priv_4_html' => 'Azure OpenAI is called only for the LLM sweep pass. No document content is retained by Azure after the response is returned, per the enterprise data-handling agreement.',
'priv_5_html' => 'Telemetry logged: tool name, engine, mode, region, latency. <strong>No document text, entity names, or redacted content is logged.</strong>',
'cta_title' => 'See it work on your documents.',
'cta_sub' => 'Free for Do Better Norge members.',
'btn_open' => 'Open Redact →',
'btn_signin_cta' => 'Sign in to use Redact →',
'btn_register' => 'Register free',
'btn_guide' => 'User guide',
),
'no' =>
array (
'nav_about' => 'Om',
'nav_guide' => 'Brukerveiledning',
'nav_howit' => 'Slik fungerer det',
'nav_opentool' => '← Åpne verktøyet',
'nav_signin' => 'Logg inn',
'nav_open' => 'Åpne Sladding →',
'hero_kicker' => 'Teknisk Vist · Hvordan AI-en beskytter dokumenter',
'hero_title' => 'Hvordan Sladding vet hva som skal erstattes.',
'hero_sub' => 'En full gjennomgang av to-pass sladdingsprosessen, regional mønstergjenkjenning, enhetsklassifisering, utdataformatgenerering og personvernarkitektur.',
'stat1' => 'behandlingspass',
'stat2' => 'regionale regelsett',
'stat3' => 'utdataformater',
'stat4' => 'motoralternativer',
'arch_eyebrow' => 'Arkitektur',
'arch_title' => 'To pass. Deterministisk først, intelligent deretter.',
'arch_sub' => 'Rørledningen er bevisst lagdelt — Pass 1 fanger alt som kan fanges av regler alene; Pass 2 håndterer kontekstavhengige enheter som regler ikke kan identifisere.',
'pass1_title' => 'Oppdage & erstatte kjente mønstre',
'pass1_p1_html' => 'Et deterministisk regex-pass kjøres før noen LLM-anrop. Det skanner hele inngangen for identifikatorer som matcher den aktive regionale profilen:',
'pass1_li1_html' => 'Norsk <code>fødselsnummer</code> (11 sifre) og D-nummer',
'pass1_li2' => 'Telefonnumre i +47-format, norsk mobil (4xx/9xx) og fasttelefon',
'pass1_li3' => 'E-postadresser (RFC 5322 forenklet)',
'pass1_li4' => 'Norske postadresser: gatenavn + nummer + postnummer + poststed',
'pass1_li5' => 'Ytterligere mønstre per region (IBAN, CPR, EMD-numre, SSN, osv.)',
'pass1_p2' => 'Mønster-matchede symboler erstattes umiddelbart og merkes som allerede sladdede slik at LLM-passet ikke dobbeltbehandler dem.',
'pass2_title' => 'Søk etter navngitte enheter',
'pass2_p1_html' => 'LLM-en leser hele dokumentet (med mønster-erstattede symboler synlige som plassholdere). Den identifiserer alle gjenværende navngitte enheter:',
'pass2_li1' => 'Personnavn — fornavn, etternavn eller fullt navn; håndterer norske, samiske og utenlandske navn',
'pass2_li2' => 'Organisasjoner — selskaper, myndigheter, frivillige organisasjoner, religiøse organer, idrettslag',
'pass2_li3' => 'Steder — gater, nabolag, kommuner, fylker, land',
'pass2_li4' => 'Fødselsdato og aldersfraser (når enhetstype Datoer er avkrysset)',
'pass2_p2' => 'Hver matchet enhet klassifiseres etter type og rolle (FAR, MOR, DOMMER, SAKSBEHANDLER, osv.) og erstattes i henhold til valgt utdataformat.',
'pass3_title' => 'Etterbehandling og aliassubstitusjon',
'pass3_p1_html' => 'Etter begge passene anvender PHP endelige transformasjoner:',
'pass3_f1_html' => '<strong>Offisielt pass</strong> — hvis Behold offisielle navn er avkrysset, får navngitte dommere, eksperter og saksbehandlere merkede koder ([DOMMER: Andersen])',
'pass3_f2_html' => '<strong>Aliassubstitusjon</strong> — brukerdefinerte aliaser brukes som et siste regex-erstatning',
'pass3_f3_html' => '<strong>Unntak for navnbeskyttelse</strong> — eventuelle symboler som matcher et unntaksnavn gjenopprettes til den opprinnelige verdien',
'pass3_f4_html' => '<strong>Pseudonymgenerering</strong> — hvis Pseudonymutdata er valgt, erstattes alle rollekoder med plausible norske navn, telefonnumre og adresser',
'pass3_p2_html' => 'Sluttutdataene settes sammen og returneres som ren tekst. DOCX-eksporten konverterer dette til et OOXML-dokument via PHP ZipArchive.',
'date_eyebrow' => 'Regionale mønsterssett',
'date_title' => 'Fire regioner. Hver legger til mønstre fra den siste.',
'date_sub' => 'Regionale profiler er kumulative — Europeisk legger til Nordisk, EMD legger til Europeisk, Global legger til EMD.',
'th_region' => 'Region',
'th_patterns' => 'Dekket mønstre',
'th_notes' => 'Notater',
'rn1' => 'Standard for norske dokumenter. Alle lokale ID-formater.',
'rn2' => 'Grenseoverskridende EU-dokumenter, nordiske naboer.',
'rn3' => 'Klager til Den europeiske menneskerettighetsdomstolen.',
'rn4' => 'Dokumenter som involverer ikke-europeiske parter eller jurisdiksjoner.',
'class_eyebrow' => 'Enhetsklassifisering',
'class_title' => 'Hva LLM-en identifiserer og hvordan den merker hver type.',
'class_h1' => 'Navngitte enhetstyper',
'th_entity' => 'Enhet',
'th_definition' => 'Hva som kvalifiserer',
'th_output' => 'Standard utdata (kontekstuell)',
'et1_def' => 'Ethvert personnavn — fornavn, etternavn eller fullt navn',
'et1_out' => '[ROLLE] — utledet fra kontekst (FAR, MOR, DOMMER, osv.)',
'et2_def' => 'Selskaper, etater, myndigheter, institusjoner, klubber',
'et2_out' => '[ORG: delvis navn] eller generisk [ORG]',
'et3_def' => 'Gater, tettsteder, kommuner, fylker, land, regioner',
'et3_out' => '[STED] eller [BY] eller [ADRESSE]',
'et4_def' => 'Fødselsdatoer, aldersreferanser, personlige datofraser',
'et4_out' => '[FØDSELSDATO] eller [ALDER: xx]',
'class_h2' => 'Sammenligning av utdataformat',
'th_format' => 'Format',
'th_person_ex' => 'Person eksempel',
'th_org_ex' => 'Org eksempel',
'fmt1_person' => '[FAR] eller [DOMMER: Andersen]',
'fmt1_org' => '[BARNEVERNET: Oslo] eller [ORG]',
'fmt2_person' => '[PERSON]',
'fmt2_org' => '[ORG]',
'fmt3_person' => 'Ola Nordmann (generert)',
'fmt3_org' => 'Nordnes AS (generert)',
'eng_eyebrow' => 'Motorer',
'eng_title' => 'To motorer, ett sladdskjema.',
'eng_sub' => 'Begge motorer produserer det samme sladdutdataskjemaet. Motorvalg påvirker nøyaktigheten på komplekse dokumenter og kreditt-kostnad.',
'th_engine' => 'Motor',
'th_model' => 'Modell',
'th_latency' => 'Forsinkelse',
'th_best' => 'Best for',
'eng1_best' => 'Standard. De fleste dokumenter, enkelt emne, klar formatering.',
'eng2_best' => 'Komplekse dokumenter med mange navngitte parter, overlappende roller eller forringet kildetekst.',
'priv_eyebrow' => 'Personvern & sikkerhet',
'priv_title' => 'Dine dokumenter forlater aldri sesjonen din.',
'priv_badge' => 'Personvern ved design',
'priv_1_html' => 'Alle opplastede filer blir ekstraktert til tekst <strong>i minnet</strong> ved hjelp av PHPs in-process filbehandlere. Den rå binære data skrives aldri til disk på serveren.',
'priv_2' => 'Sesjonskonteksten (limt inn tekst, opplastet innhold, sladdet utdata) er avgrenset til din autentiserte sesjon og kastes når sesjonen avsluttes.',
'priv_3_html' => 'Azure OpenAI (<code>gpt-4o</code>, <code>gpt-4o-mini</code>) er konfigurert på <strong>Vest-Europa</strong> regionen. Data behandlet via Azure OpenAI brukes ikke til modelltrening under den standard bedriftsavtalen.',
'priv_4_html' => 'Azure OpenAI kalles kun under LLM-søkpasset. Ingen dokumentinnhold beholdes av Azure etter at svaret er returnert, i henhold til bedriftsavtalen for datahåndtering.',
'priv_5_html' => 'Telemetri logget: verktøynavn, motor, modus, region, forsinkelse. <strong>Ingen dokumenttekst, enhetsnavn eller sladdede innhold logges.</strong>',
'cta_title' => 'Se det fungere på dine dokumenter.',
'cta_sub' => 'Gratis for Do Better Norge-medlemmer.',
'btn_open' => 'Åpne Sladding →',
'btn_signin_cta' => 'Logg inn for å bruke Sladding →',
'btn_register' => 'Registrer gratis',
'btn_guide' => 'Brukerveiledning',
),
);
+37 -1
View File
@@ -32,7 +32,7 @@ return array (
'how_title' => 'Upload → extract → review. In under a minute.',
'how_sub' => 'Three steps from raw case documents to a complete, sortable timeline.',
's1_title' => 'Upload documents or paste text',
's1_body' => 'Upload up to 5 files (PDF, DOCX, TXT) or paste up to 128,000 characters of case text. Add optional context notes to help the AI interpret abbreviations, actor names, or document-specific date conventions.',
's1_body' => 'Upload one file (PDF, DOCX, or TXT) or paste up to 128,000 characters of case text. Add optional context notes to help the AI interpret abbreviations, actor names, or document-specific date conventions.',
's1_example' => 'E.g. "D refers to the defendant throughout. All dates are in 2024 unless stated otherwise."',
's2_title' => 'AI extracts & classifies',
's2_body' => 'The engine reads every sentence, recognising Norwegian date formats and classifying each event by type (absolute, relative, recurring, conditional, period) and assigning a confidence score. Focus filters scope the extraction to what matters most for your case.',
@@ -54,6 +54,15 @@ return array (
'llm_s2' => 'date formats',
'llm_s3' => 'event types',
'llm_s4' => 'local engine',
'export_eyebrow' => 'Export & live updates',
'export_title' => 'Download as Word. See progress live.',
'export_badge' => 'SSE + DOCX',
'export_h1' => 'Live status + one-click Word export',
'export_body_html' => 'Timeline streams live progress messages to your browser via Server-Sent Events — so you see <em>"Calling gpt-4o-mini…"</em> and <em>"Parsing events…"</em> instead of a blank spinner. When extraction completes, click <strong>Export to Word</strong> to download a clean .docx with every event, source excerpt, and divider line ready for use in a court submission or case file.',
'export_s1' => 'live streaming',
'export_s2' => 'Word download',
'export_s3' => 'AI engine',
'export_s4' => 'engines',
'focus_eyebrow' => 'Focus filters',
'focus_title' => 'Extract only what your case needs.',
'focus_sub' => 'Four modes scope the extraction pipeline to the events that matter most for your situation.',
@@ -123,6 +132,15 @@ return array (
'llm_s2' => 'datoformater',
'llm_s3' => 'hendelsestyper',
'llm_s4' => 'lokal motor',
'export_eyebrow' => 'Eksport og live oppdateringer',
'export_title' => 'Last ned som Word. Se fremgang live.',
'export_badge' => 'SSE + DOCX',
'export_h1' => 'Live status + nedlasting til Word med ett klikk',
'export_body_html' => 'Tidslinje strømmer live statusmeldinger til nettleseren din via Server-Sent Events — slik at du ser <em>«Kaller gpt-4o-mini…»</em> og <em>«Analyserer hendelser…»</em> i stedet for en tom spinner. Når ekstraksjonen er ferdig, klikk <strong>Eksporter til Word</strong> for å laste ned en ren .docx med hver hendelse, kildeutdrag og skillelinje klar for bruk i en rettssak eller saksmappe.',
'export_s1' => 'live strømming',
'export_s2' => 'Word-nedlasting',
'export_s3' => 'AI-motor',
'export_s4' => 'motorer',
'focus_eyebrow' => 'Fokusfiltre',
'focus_title' => 'Ekstraher kun det saken din trenger.',
'focus_sub' => 'Fire moduser avgrenser ekstraksjonsrøret til hendelsene som betyr mest for din situasjon.',
@@ -192,6 +210,15 @@ return array (
'llm_s2' => 'формати дат',
'llm_s3' => 'типи подій',
'llm_s4' => 'локальний двигун',
'export_eyebrow' => 'Експорт та живі оновлення',
'export_title' => 'Завантажуйте у Word. Слідкуйте за прогресом наживо.',
'export_badge' => 'SSE + DOCX',
'export_h1' => 'Живий статус + завантаження Word одним кліком',
'export_body_html' => 'Хронологія передає живі повідомлення про стан у ваш браузер через Server-Sent Events — тому ви бачите <em>«Виклик gpt-4o-mini…»</em> та <em>«Аналіз подій…»</em> замість порожнього індикатора. Коли витягування завершиться, натисніть <strong>Експортувати до Word</strong>, щоб завантажити чистий .docx з кожною подією, цитатами з джерел та роздільником між подіями.',
'export_s1' => 'жива передача',
'export_s2' => 'Word-завантаження',
'export_s3' => 'AI-двигун',
'export_s4' => 'двигуни',
'focus_eyebrow' => 'Фільтри фокусу',
'focus_title' => 'Витягуйте лише те, що потрібно вашій справі.',
'focus_sub' => 'Чотири режими обмежують витягування до подій, які мають найбільше значення для вашої ситуації.',
@@ -261,6 +288,15 @@ return array (
'llm_s2' => 'formaty dat',
'llm_s3' => 'typy wydarzeń',
'llm_s4' => 'lokalny silnik',
'export_eyebrow' => 'Eksport i aktualizacje na żywo',
'export_title' => 'Pobierz w Word. Śledź postęp na żywo.',
'export_badge' => 'SSE + DOCX',
'export_h1' => 'Statusy na żywo + pobieranie Word jednym kliknięciem',
'export_body_html' => 'Oś czasu przekazuje na żywo komunikaty o stanie do przeglądarki przez Server-Sent Events — więc widzisz <em>„Wywoływanie gpt-4o-mini…"</em> i <em>„Analiza wydarzeń…"</em> zamiast pustego spinnera. Po zakończeniu ekstrakcji kliknij <strong>Eksportuj do Word</strong>, aby pobrać sformatowany .docx z każdym zdarzeniem, fragmentami źródeł i linią separatora między zdarzeniami.',
'export_s1' => 'transmisja na żywo',
'export_s2' => 'Pobieranie Word',
'export_s3' => 'silnik AI',
'export_s4' => 'silniki',
'focus_eyebrow' => 'Filtry fokusowe',
'focus_title' => 'Ekstrahuj tylko to, czego potrzebuje Twoja sprawa.',
'focus_sub' => 'Cztery tryby ograniczają proces ekstrakcji do wydarzeń, które mają największe znaczenie dla Twojej sytuacji.',
+10 -10
View File
@@ -25,7 +25,7 @@ return array (
'toc_9' => 'Evidence trail, uncertainty & next step',
'toc_10' => 'Tips & gotchas',
'step1_title' => 'Choose your engine',
'step1_intro' => 'The engine controls the AI model used for extraction. Azure engines use your BNL Azure credits. The GPU engine runs the LiteLLM proxy on the local cuttlefish server with the dbn-legal-agent fine-tuned model.',
'step1_intro' => 'The engine controls the AI model used for extraction. Both engines use Azure OpenAI (West Europe). gpt-4o-mini costs 1 credit; gpt-4o costs 2 credits.',
'th_engine' => 'Engine',
'th_speed' => 'Speed',
'th_best' => 'Best for',
@@ -63,9 +63,9 @@ return array (
'step5_p2_html' => '<strong>When to uncheck:</strong> if you need only exact calendar dates — for example when exporting to a calendar app, a deadline tracker, or a court submission that requires hard dates only. Unchecking removes all events without a resolvable absolute date.',
'step6_title' => 'Upload files',
'step6_p1_html' => 'Drag files onto the upload zone or click <strong>browse</strong>. A file list appears below with a Clear button to remove files.',
'step6_p2_html' => '<strong>Supported formats:</strong> <strong>PDF</strong>, <strong>DOCX</strong>, <strong>TXT</strong>. Up to 5 files per run.',
'step6_p2_html' => '<strong>Supported formats:</strong> <strong>PDF</strong>, <strong>DOCX</strong>, <strong>TXT</strong>. One file per run.',
'step6_p3' => 'Files are extracted to text in memory. Nothing is written to disk. Nothing is retained after the session ends.',
'step6_p4' => 'Upload and pasted text can be combined — the AI reads all sources together as a single input. If a case spans multiple documents, upload them all and let the tool assemble one unified timeline.',
'step6_p4' => 'Uploaded file and pasted text can be combined — the AI reads both together as a single input. For cases spanning multiple documents, paste additional text into the text area alongside the uploaded file.',
'step7_title' => 'Pasted text & context notes',
'step7_p1_html' => 'Paste up to <strong>128,000 characters</strong> of text into the main text area — approximately 90100 pages of A4. This can include case notes, decision letters, correspondence, or any document containing dates.',
'step7_p2_html' => '<strong>Context notes</strong> (optional, up to 2,000 characters): use this field to guide the AI on ambiguities in your document. These notes are passed directly into the extraction prompt and are not stored. Good examples:',
@@ -95,7 +95,7 @@ return array (
'tip2_html' => '<strong>Combine upload and paste for best coverage.</strong> Upload the main decision letter and paste related case notes into the text area. The AI reads all sources together and produces one unified timeline.',
'tip3_html' => '<strong>Run All events first, then re-run with focus.</strong> Start with the default "All events" mode to see the full picture. Then re-run with a specific focus mode (e.g. Legal deadlines) if you need a filtered view for a submission.',
'tip4_html' => '<strong>Date types off for clean deadline lists.</strong> If you\'re exporting to a calendar or deadline tracker, uncheck "Date types" to return only resolved calendar dates — no relative or recurring entries to sort through.',
'tip5_html' => '<strong>GPU engine for maximum privacy.</strong> The cuttlefish engine processes entirely locally using dbn-legal-agent — nothing leaves your network. Use it for the most sensitive case material.',
'tip5_html' => '<strong>Use gpt-4o for complex or heavily contested cases.</strong> The higher-accuracy engine handles overlapping timelines, ambiguous phrasing, and dense source text better than gpt-4o-mini. Costs 2 credits.',
'tip6_html' => '<strong>LOW confidence isn\'t wrong — it\'s uncertain.</strong> A LOW confidence event may still be correct and important. Read the source excerpt for each LOW event before dismissing it — the AI may have found a real date that was just expressed ambiguously.',
'cta_title' => 'Ready to try it?',
'cta_sub' => 'Free for Do Better Norge members.',
@@ -127,7 +127,7 @@ return array (
'toc_9' => 'Bevissti, usikkerhet & neste steg',
'toc_10' => 'Tips & fallgruver',
'step1_title' => 'Velg motor',
'step1_intro' => 'Motoren kontrollerer AI-modellen som brukes til ekstraksjon. Azure-motorer bruker dine BNL Azure-kreditter. GPU-motoren kjører LiteLLM-proxyen på den lokale cuttlefish-serveren med den finjusterte modellen dbn-legal-agent.',
'step1_intro' => 'Motoren kontrollerer AI-modellen som brukes til ekstraksjon. Begge motorer bruker Azure OpenAI (Vest-Europa). gpt-4o-mini koster 1 kreditt; gpt-4o koster 2 kreditter.',
'th_engine' => 'Motor',
'th_speed' => 'Hastighet',
'th_best' => 'Best for',
@@ -197,7 +197,7 @@ return array (
'tip2_html' => '<strong>Kombiner opplasting og innliming for best dekning.</strong> Last opp hovedbeslutningsbrevet og lim inn relaterte saksnotater i tekstområdet. AI-en leser alle kilder sammen og produserer en samlet tidslinje.',
'tip3_html' => '<strong>Kjør Alle hendelser først, deretter kjør på nytt med fokus.</strong> Start med standard "Alle hendelser"-modus for å se det fulle bildet. Kjør deretter på nytt med en spesifikk fokusmodus (f.eks. Juridiske frister) hvis du trenger en filtrert visning for en innlevering.',
'tip4_html' => '<strong>Dato typer av for rene fristlister.</strong> Hvis du eksporterer til en kalender eller fristsporer, fjern merket for "Dato typer" for å returnere kun løste kalenderdatoer — ingen relative eller gjentakende oppføringer å sortere gjennom.',
'tip5_html' => '<strong>GPU-motor for maksimal personvern.</strong> Cuttlefish-motoren behandler helt lokalt ved hjelp av dbn-legal-agent — ingenting forlater nettverket ditt. Bruk den for det mest sensitive saksmaterialet.',
'tip5_html' => '<strong>Bruk gpt-4o for komplekse eller omstridte saker.</strong> Den mer nøyaktige motoren ndterer overlappende tidslinjer, tvetydig formulering og tett kildetekst bedre enn gpt-4o-mini. Koster 2 kreditter.',
'tip6_html' => '<strong>LOW tillit er ikke feil — det er usikkert.</strong> En LOW tillit-hendelse kan fortsatt være korrekt og viktig. Les kildeutdraget for hver LOW-hendelse før du avviser den — AI-en kan ha funnet en reell dato som bare ble uttrykt tvetydig.',
'cta_title' => 'Klar til å prøve det?',
'cta_sub' => 'Gratis for Do Better Norge-medlemmer.',
@@ -229,7 +229,7 @@ return array (
'toc_9' => 'Слід доказів, невизначеність та наступний крок',
'toc_10' => 'Поради та підводні камені',
'step1_title' => 'Виберіть свій двигун',
'step1_intro' => 'Двигун контролює модель ШІ, що використовується для витягування. Двигуни Azure використовують ваші кредити BNL Azure. Двигун GPU запускає проксі LiteLLM на локальному сервері cuttlefish з налаштованою моделлю dbn-legal-agent.',
'step1_intro' => 'Двигун контролює модель ШІ для витягування. Обидва двигуни використовують Azure OpenAI (Захід Європи). gpt-4o-mini коштує 1 кредит; gpt-4o коштує 2 кредити.',
'th_engine' => 'Двигун',
'th_speed' => 'Швидкість',
'th_best' => 'Найкраще для',
@@ -299,7 +299,7 @@ return array (
'tip2_html' => '<strong>Поєднуйте завантаження та вставку для найкращого покриття.</strong> Завантажте основний лист рішення та вставте пов\'язані нотатки справи в текстову область. ШІ читає всі джерела разом і створює одну єдину хронологію.',
'tip3_html' => '<strong>Спочатку запустіть всі події, а потім повторно запустіть з фокусом.</strong> Почніть з режиму "Усі події" за замовчуванням, щоб побачити повну картину. Потім повторно запустіть з конкретним режимом фокусу (наприклад, Юридичні терміни), якщо вам потрібен відфільтрований вигляд для подання.',
'tip4_html' => '<strong>Типи дат вимкнені для чистих списків термінів.</strong> Якщо ви експортуєте в календар або трекер термінів, зніміть позначку з "Типи дат", щоб повернути лише вирішені календарні дати — без відносних або повторюваних записів для сортування.',
'tip5_html' => '<strong>GPU-двигун для максимальної конфіденційності.</strong> Двигун cuttlefish обробляє повністю локально, використовуючи dbn-legal-agent — нічого не покидає вашу мережу. Використовуйте його для найбільш чутливих матеріалів справ.',
'tip5_html' => '<strong>Використовуйте gpt-4o для складних або спірних справ.</strong> Двигун з вищою точністю краще справляється з перекривними хронологіями, неоднозначними формулюваннями та щільним вихідним текстом. Коштує 2 кредити.',
'tip6_html' => '<strong>Низька впевненість не є помилкою — це невизначеність.</strong> Подія з низькою впевненістю може бути все ще правильною та важливою. Прочитайте витяг з джерела для кожної події з низькою впевненістю перед тим, як відхилити її — ШІ могло знайти реальну дату, яка була просто виражена неоднозначно.',
'cta_title' => 'Готові спробувати?',
'cta_sub' => 'Безкоштовно для учасників Do Better Norge.',
@@ -331,7 +331,7 @@ return array (
'toc_9' => 'Ścieżka dowodowa, niepewność i następny krok',
'toc_10' => 'Wskazówki i pułapki',
'step1_title' => 'Wybierz swój silnik',
'step1_intro' => 'Silnik kontroluje model AI używany do ekstrakcji. Silniki Azure wykorzystują Twoje kredyty BNL Azure. Silnik GPU uruchamia proxy LiteLLM na lokalnym serwerze cuttlefish z modelem dbn-legal-agent dostosowanym do potrzeb.',
'step1_intro' => 'Silnik kontroluje model AI używany do ekstrakcji. Oba silniki używają Azure OpenAI (Europa Zachodnia). gpt-4o-mini kosztuje 1 kredyt; gpt-4o kosztuje 2 kredyty.',
'th_engine' => 'Silnik',
'th_speed' => 'Szybkość',
'th_best' => 'Najlepszy dla',
@@ -401,7 +401,7 @@ return array (
'tip2_html' => '<strong>Połącz przesyłanie i wklejanie dla najlepszego pokrycia.</strong> Prześlij główny list decyzji i wklej powiązane notatki sprawy do obszaru tekstowego. AI odczytuje wszystkie źródła razem i produkuje jedną zjednoczoną oś czasu.',
'tip3_html' => '<strong>Najpierw uruchom wszystkie wydarzenia, a następnie uruchom ponownie z naciskiem.</strong> Zacznij od domyślnego trybu "Wszystkie wydarzenia", aby zobaczyć pełny obraz. Następnie uruchom ponownie z określonym trybem skupienia (np. Terminy prawne), jeśli potrzebujesz filtrowanego widoku do złożenia.',
'tip4_html' => '<strong>Typy dat wyłączone dla czystych list terminów.</strong> Jeśli eksportujesz do kalendarza lub śledzenia terminów, odznacz "Typy dat", aby zwrócić tylko rozwiązane daty kalendarzowe — bez względnych lub powtarzających się wpisów do przefiltrowania.',
'tip5_html' => '<strong>Silnik GPU dla maksymalnej prywatności.</strong> Silnik cuttlefish przetwarza całkowicie lokalnie przy użyciu dbn-legal-agent — nic nie opuszcza twojej sieci. Użyj go dla najbardziej wrażliwych materiałów sprawy.',
'tip5_html' => '<strong>Użyj gpt-4o w złożonych lub spornych sprawach.</strong> Silnik o wyższej dokładności lepiej radzi sobie z nakładającymi się harmonogramami, niejednoznacznymi sformułowaniami i gęstym tekstem źródłowym. Kosztuje 2 kredyty.',
'tip6_html' => '<strong>NISKA pewność nie jest błędna — to niepewność.</strong> Wydarzenie o NISKIEJ pewności może być nadal poprawne i ważne. Przeczytaj fragment źródła dla każdego wydarzenia o NISKIEJ pewności przed jego odrzuceniem — AI mogło znaleźć rzeczywistą datę, która była po prostu wyrażona niejednoznacznie.',
'cta_title' => 'Gotowy, aby spróbować?',
'cta_sub' => 'Darmowe dla członków Do Better Norge.',
+36 -16
View File
@@ -12,7 +12,7 @@ return array (
'nav_open' => 'Open Timeline →',
'hero_kicker' => 'Technical Showcase · How the AI reads time',
'hero_title' => 'How Timeline knows when things happened.',
'hero_sub' => 'A full walkthrough of the 3-pass extraction pipeline, Norwegian date format recognition, event classification schema, multi-engine architecture, and the fine-tuned dbn-legal-agent model.',
'hero_sub' => 'A full walkthrough of the 3-pass extraction pipeline, Norwegian date format recognition, event classification schema, live SSE streaming, and one-click Word export.',
'stat1' => 'date formats',
'stat2' => 'event types',
'stat3' => 'pipeline passes',
@@ -83,8 +83,13 @@ return array (
'act4_rule' => 'Document-level default',
'act4_example' => 'If no per-event actor, defaults to the document sender/issuing body',
'eng_eyebrow' => 'Engines',
'eng_title' => 'Three engines, one structured output.',
'eng_sub' => 'All engines return the same JSON schema — the post-processor handles all three identically. Engine choice affects speed, quality, and privacy only.',
'eng_title' => 'Two engines, one structured output.',
'eng_sub' => 'Both engines return the same JSON schema — the post-processor handles them identically. Engine choice affects speed, quality, and credit cost only.',
'stream_eyebrow' => 'Live updates & export',
'stream_title' => 'See progress as it happens. Download in Word.',
'stream_h1' => 'SSE streaming + DOCX export',
'stream_p1' => 'Timeline uses Server-Sent Events (SSE) to stream live status messages to the browser as extraction runs. Instead of staring at a spinner for 3060 seconds, you see "Preparing document…", "Calling gpt-4o-mini…", "Parsing events…" in real time.',
'stream_p2' => 'Once extraction completes, click Export to Word to download a formatted .docx with every event as a labelled paragraph, source excerpts, and a divider line between events. No third-party DOCX library is used — the file is assembled directly from OOXML via PHP ZipArchive.',
'th_model' => 'Model',
'th_latency' => 'Latency',
'th_best' => 'Best for',
@@ -102,7 +107,7 @@ return array (
'priv_1_html' => 'All uploaded files are extracted to text <strong>in memory</strong> using PHP\'s in-process file handlers. The raw binary is never written to disk on the server.',
'priv_2' => 'Session context (pasted text, uploaded content, extracted timeline events) is scoped to your authenticated session and discarded when the session ends.',
'priv_3_html' => 'Azure OpenAI (<code>gpt-4o</code>, <code>gpt-4o-mini</code>) is configured on the <strong>West Europe</strong> region. Data processed via Azure OpenAI is not used for model training under the default enterprise agreement.',
'priv_4_html' => 'The GPU/cuttlefish engine processes entirely locally — no data leaves your network. The LiteLLM proxy on cuttlefish receives your document text and returns structured JSON; nothing is forwarded to an external API.',
'priv_4_html' => 'Azure OpenAI is called only for the extraction pass. No document content is retained by Azure after the response is returned, per the enterprise data-handling agreement.',
'priv_5_html' => 'Telemetry logged: tool name, engine, focus mode, event count, latency. <strong>No document text, case references, actor names, or extracted events are logged.</strong>',
'cta_title' => 'See it work on your case.',
'cta_sub' => 'Free for Do Better Norge members. All engines available to every member.',
@@ -121,7 +126,7 @@ return array (
'nav_open' => 'Åpne Tidslinje →',
'hero_kicker' => 'Teknisk Vist · Hvordan AI-en leser tid',
'hero_title' => 'Hvordan Tidslinje vet når ting skjedde.',
'hero_sub' => 'En full gjennomgang av 3-pass ekstraksjonsrørledningen, gjenkjenning av norsk datoformat, hendelsesklassifiseringsskjema, multi-motor arkitektur, og den finjusterte dbn-legal-agent modellen.',
'hero_sub' => 'En full gjennomgang av 3-pass ekstraksjonsrørledningen, gjenkjenning av norsk datoformat, hendelsesklassifiseringsskjema, live SSE-strømming og nedlasting som Word-dokument.',
'stat1' => 'datoformater',
'stat2' => 'hendelsestyper',
'stat3' => 'rørledningspass',
@@ -192,8 +197,13 @@ return array (
'act4_rule' => 'Standard på dokumentnivå',
'act4_example' => 'Hvis ingen aktør per hendelse, standardiseres til dokumentets avsender/utstedende organ',
'eng_eyebrow' => 'Motorer',
'eng_title' => 'Tre motorer, ett strukturert utdata.',
'eng_sub' => 'Alle motorer returnerer det samme JSON-skjemaet — etterbehandleren håndterer alle tre identisk. Valg av motor påvirker hastighet, kvalitet og personvern kun.',
'eng_title' => 'To motorer, ett strukturert utdata.',
'eng_sub' => 'Begge motorer returnerer det samme JSON-skjemaet — etterbehandleren håndterer dem identisk. Valg av motor påvirker hastighet, kvalitet og kreditt-kostnad.',
'stream_eyebrow' => 'Live oppdateringer og eksport',
'stream_title' => 'Se fremgangen i sanntid. Last ned i Word.',
'stream_h1' => 'SSE-strømming + DOCX-eksport',
'stream_p1' => 'Tidslinje bruker Server-Sent Events (SSE) for å strømme live statusmeldinger til nettleseren mens ekstraksjon kjører. I stedet for å stirre på en spinner i 3060 sekunder, ser du «Forbereder dokument…», «Kaller gpt-4o-mini…», «Analyserer hendelser…» i sanntid.',
'stream_p2' => 'Når ekstraksjon er fullført, klikk Eksporter til Word for å laste ned en formatert .docx med hver hendelse som et merket avsnitt, kildesitater og en skillelinje mellom hendelsene.',
'th_model' => 'Modell',
'th_latency' => 'Forsinkelse',
'th_best' => 'Best for',
@@ -211,7 +221,7 @@ return array (
'priv_1_html' => 'Alle opplastede filer blir ekstraktert til tekst <strong>i minnet</strong> ved hjelp av PHPs in-process filbehandlere. Den rå binære data skrives aldri til disk på serveren.',
'priv_2' => 'Sesjonskonteksten (innlimt tekst, opplastet innhold, ekstrakterte tidslinjehendelser) er avgrenset til din autentiserte sesjon og kastes når sesjonen avsluttes.',
'priv_3_html' => 'Azure OpenAI (<code>gpt-4o</code>, <code>gpt-4o-mini</code>) er konfigurert på <strong>Vest-Europa</strong> regionen. Data behandlet via Azure OpenAI brukes ikke til modelltrening under den standard bedriftsavtalen.',
'priv_4_html' => 'GPU/cuttlefish-motoren prosesserer helt lokalt — ingen data forlater nettverket ditt. LiteLLM-proxyen på cuttlefish mottar dokumentteksten din og returnerer strukturert JSON; ingenting videresendes til en ekstern API.',
'priv_4_html' => 'Azure OpenAI kalles kun under ekstraksjonspasset. Ingen dokumentinnhold beholdes av Azure etter at svaret er returnert, i henhold til bedriftsavtalen for datahåndtering.',
'priv_5_html' => 'Telemetri logget: verktøynavn, motor, fokusmodus, hendelsestall, forsinkelse. <strong>Ingen dokumenttekst, saksreferanser, aktørnavn eller ekstrakterte hendelser blir logget.</strong>',
'cta_title' => 'Se det fungere i din sak.',
'cta_sub' => 'Gratis for Do Better Norge medlemmer. Alle motorer tilgjengelig for hvert medlem.',
@@ -230,7 +240,7 @@ return array (
'nav_open' => 'Відкрити Хронологію →',
'hero_kicker' => 'Технічна демонстрація · Як ШІ читає час',
'hero_title' => 'Як Хронологія знає, коли відбулися події.',
'hero_sub' => 'Повний огляд трьохетапного процесу витягування, розпізнавання дат у норвезькому форматі, схеми класифікації подій, архітектури з кількома двигунами та тонко налаштованої моделі dbn-legal-agent.',
'hero_sub' => 'Повний огляд трьохетапного процесу витягування, розпізнавання норвезьких форматів дат, схеми класифікації подій, потокового оновлення SSE та завантаження у форматі Word.',
'stat1' => 'формати дат',
'stat2' => 'типи подій',
'stat3' => 'етапи процесу',
@@ -301,8 +311,13 @@ return array (
'act4_rule' => 'За замовчуванням на рівні документа',
'act4_example' => 'Якщо немає актора для кожної події, за замовчуванням використовується відправник/видавець документа',
'eng_eyebrow' => 'Двигуни',
'eng_title' => 'Три двигуни, один структурований вихід.',
'eng_sub' => 'Усі двигуни повертають однакову JSON-схему — пост-обробник обробляє всі три однаково. Вибір двигуна впливає на швидкість, якість та конфіденційність лише.',
'eng_title' => 'Два двигуни, один структурований вихід.',
'eng_sub' => 'Обидва двигуни повертають однакову JSON-схему — пост-обробник обробляє їх однаково. Вибір двигуна впливає лише на швидкість, якість і вартість кредитів.',
'stream_eyebrow' => 'Живі оновлення та експорт',
'stream_title' => 'Дивіться прогрес у режимі реального часу. Завантажуйте у Word.',
'stream_h1' => 'SSE-потік + експорт DOCX',
'stream_p1' => 'Хронологія використовує Server-Sent Events (SSE) для потокової передачі живих повідомлень про стан у браузер під час виконання вилучення. Замість того, щоб дивитися на індикатор завантаження 30–60 секунд, ви бачите «Підготовка документа…», «Виклик gpt-4o-mini…», «Аналіз подій…» у режимі реального часу.',
'stream_p2' => 'Після завершення вилучення натисніть «Експортувати до Word», щоб завантажити відформатований .docx з кожною подією як позначеним абзацом, цитатами з джерел і роздільником між подіями.',
'th_model' => 'Модель',
'th_latency' => 'Затримка',
'th_best' => 'Найкраще для',
@@ -320,7 +335,7 @@ return array (
'priv_1_html' => 'Усі завантажені файли витягуються в текст <strong>в пам\'яті</strong> за допомогою обробників файлів PHP в процесі. Сирий бінарний файл ніколи не записується на диск на сервері.',
'priv_2' => 'Контекст сесії (вставлений текст, завантажений вміст, витягнуті події хронології) обмежується вашою автентифікованою сесією і знищується, коли сесія закінчується.',
'priv_3_html' => 'Azure OpenAI (<code>gpt-4o</code>, <code>gpt-4o-mini</code>) налаштовано на регіоні <strong>Західна Європа</strong>. Дані, оброблені через Azure OpenAI, не використовуються для навчання моделі за умовами стандартної корпоративної угоди.',
'priv_4_html' => 'Двигун GPU/cuttlefish обробляє повністю локально — жодні дані не залишають вашу мережу. Проксі LiteLLM на cuttlefish отримує текст вашого документа і повертає структурований JSON; нічого не пересилається на зовнішній API.',
'priv_4_html' => 'Azure OpenAI викликається лише під час проходу вилучення. Жодний вміст документа не зберігається Azure після повернення відповіді згідно з корпоративною угодою про обробку даних.',
'priv_5_html' => 'Логування телеметрії: назва інструменту, двигун, режим фокусу, кількість подій, затримка. <strong>Жоден текст документа, посилання на справи, імена учасників або витягнуті події не реєструються.</strong>',
'cta_title' => 'Перегляньте, як це працює у вашій справі.',
'cta_sub' => 'Безкоштовно для членів Do Better Norge. Усі механізми доступні для кожного члена.',
@@ -339,7 +354,7 @@ return array (
'nav_open' => 'Otwórz oś czasu →',
'hero_kicker' => 'Pokaz techniczny · Jak AI odczytuje czas',
'hero_title' => 'Jak oś czasu wie, kiedy miały miejsce wydarzenia.',
'hero_sub' => 'Pełne przejście przez proces ekstrakcji w 3 etapach, rozpoznawanie formatu daty w Norwegii, schemat klasyfikacji wydarzeń, architektura wielosilnikowa oraz dostosowany model dbn-legal-agent.',
'hero_sub' => 'Pełne przejście przez proces ekstrakcji w 3 etapach, rozpoznawanie norweskich formatów dat, schemat klasyfikacji wydarzeń, transmisja SSE na żywo oraz eksport do formatu Word.',
'stat1' => 'formaty dat',
'stat2' => 'typy wydarzeń',
'stat3' => 'przejścia w pipeline',
@@ -410,8 +425,13 @@ return array (
'act4_rule' => 'Domyślne na poziomie dokumentu',
'act4_example' => 'Jeśli brak aktora dla konkretnego zdarzenia, domyślnie przypisuje się nadawcę dokumentu/ciała wydającego',
'eng_eyebrow' => 'Silniki',
'eng_title' => 'Trzy silniki, jeden zorganizowany wynik.',
'eng_sub' => 'Wszystkie silniki zwracają ten sam schemat JSON — post-processer obsługuje wszystkie trzy identycznie. Wybór silnika wpływa tylko na prędkość, jakość i prywatność.',
'eng_title' => 'Dwa silniki, jeden zorganizowany wynik.',
'eng_sub' => 'Oba silniki zwracają ten sam schemat JSON — post-processer obsługuje je identycznie. Wybór silnika wpływa tylko na prędkość, jakość i koszt kredytów.',
'stream_eyebrow' => 'Aktualizacje na żywo i eksport',
'stream_title' => 'Obserwuj postęp na bieżąco. Pobierz w Word.',
'stream_h1' => 'Transmisja SSE + eksport DOCX',
'stream_p1' => 'Oś czasu używa Server-Sent Events (SSE) do strumieniowania komunikatów o stanie na żywo do przeglądarki podczas ekstrakcji. Zamiast patrzeć na spinner przez 3060 sekund, widzisz „Przygotowywanie dokumentu…", „Wywołanie gpt-4o-mini…", „Analiza wydarzeń…" w czasie rzeczywistym.',
'stream_p2' => 'Po zakończeniu ekstrakcji kliknij Eksportuj do Word, aby pobrać sformatowany .docx z każdym wydarzeniem jako oznaczony akapit, cytaty ze źródeł i linię separatora między wydarzeniami.',
'th_model' => 'Model',
'th_latency' => 'Opóźnienie',
'th_best' => 'Najlepszy dla',
@@ -429,7 +449,7 @@ return array (
'priv_1_html' => 'Wszystkie przesłane pliki są ekstraktowane do tekstu <strong>w pamięci</strong> przy użyciu obsługi plików w procesie PHP. Surowy binarny nie jest nigdy zapisywany na dysku serwera.',
'priv_2' => 'Kontekst sesji (wklejony tekst, przesłana zawartość, wyodrębnione zdarzenia czasowe) jest ograniczony do twojej uwierzytelnionej sesji i jest usuwany po zakończeniu sesji.',
'priv_3_html' => 'Azure OpenAI (<code>gpt-4o</code>, <code>gpt-4o-mini</code>) jest skonfigurowany w regionie <strong>Europa Zachodnia</strong>. Dane przetwarzane za pośrednictwem Azure OpenAI nie są wykorzystywane do szkolenia modelu w ramach domyślnej umowy przedsiębiorstwa.',
'priv_4_html' => 'Silnik GPU/cuttlefish przetwarza całkowicie lokalnie — żadne dane nie opuszczają twojej sieci. Proxy LiteLLM na cuttlefish otrzymuje tekst twojego dokumentu i zwraca strukturalny JSON; nic nie jest przesyłane do zewnętrznego API.',
'priv_4_html' => 'Azure OpenAI jest wywoływane tylko podczas kroku ekstrakcji. Żadna treść dokumentu nie jest przechowywana przez Azure po zwróceniu odpowiedzi, zgodnie z umową korporacyjną dotyczącą przetwarzania danych.',
'priv_5_html' => 'Zarejestrowana telemetria: nazwa narzędzia, silnik, tryb skupienia, liczba zdarzeń, opóźnienie. <strong>Żaden tekst dokumentu, odniesienia do spraw, nazwy aktorów ani wyodrębnione zdarzenia nie są rejestrowane.</strong>',
'cta_title' => 'Zobacz, jak to działa w Twojej sprawie.',
'cta_sub' => 'Darmowe dla członków Do Better Norge. Wszystkie silniki dostępne dla każdego członka.',