add common languages

This commit is contained in:
Eduard Gert
2026-06-09 18:04:59 +02:00
parent 9049974f26
commit 4e1e7f9518
11 changed files with 7903 additions and 190 deletions

View File

@@ -138,7 +138,9 @@ Outside React (module-scope event handlers, error titles) import the instance di
**Bundle files.** Keys live in `client/ui/i18n/locales/<code>/common.json` in Chrome-extension JSON shape: each key maps to `{ "message": "...", "description": "..." }`. `description` is translator context for Crowdin (read from the source file, ignored at runtime) — only `en/common.json` carries descriptions; target bundles carry just `message`. `lib/i18n.ts` strips each entry to its `message` when building the i18next `resources`, so `t()` lookups are unchanged. Placeholders use single braces: `"Install version {version}"`. Add a key to `en/common.json` first (the fallback), then to every other locale. Missing keys fall back to English, then to the key itself (so the gap is visible in the UI).
**Adding a language.** Drop `client/ui/i18n/locales/<code>/common.json`, append the row to `_index.json`, and drop the matching `<code>.svg` into `src/assets/flags/1x1/` (source from the dashboard repo's same-name folder). `LanguagePicker.tsx` eager-globs that flags directory at build time, so **only check in flags for languages we actually ship**. `lib/i18n.ts` discovers bundles via `import.meta.glob('../../../i18n/locales/*/common.json', { eager: true })` (the tree lives outside `frontend/`, so `vite.config.ts` whitelists the parent dir under `server.fs.allow`) — no code change needed to wire a new locale.
**Translating bundles.** `client/ui/i18n/TRANSLATING.md` is the authoritative brief for actually producing or reviewing a translation — written for any translator (human or AI agent). It carries the product context, the file-format rules, the placeholder/`\n`/plural constraints (the app has only a one/other plural split — no ICU rules), the per-language do-vs-don't-translate glossary (e.g. "Exit Node" stays English in de/hu but is translated in ru/es/fr/it/pt/zh), and the new-language + review procedures. Read it before adding or editing any locale; keep its glossary/procedures current when conventions change.
**Adding a language.** Drop `client/ui/i18n/locales/<code>/common.json` (follow `TRANSLATING.md`) and append the row to `_index.json`. No flag asset is needed — `LanguagePicker.tsx` deliberately ships no flags ("flags represent countries, not languages"). `lib/i18n.ts` discovers bundles via `import.meta.glob('../../../i18n/locales/*/common.json', { eager: true })` (the tree lives outside `frontend/`, so `vite.config.ts` whitelists the parent dir under `server.fs.allow`) — no code change needed to wire a new locale.
**What gets translated.** Every user-facing string. Don't add hard-coded English — add the key, then `t()`. Internal log strings and the `Update failed` fallback fed into `classifyError()` are not translated.

View File

@@ -0,0 +1,133 @@
# Translating the NetBird UI
A short brief for translating the desktop UI — for any translator, human or AI agent (*"you"* = whoever's translating).
**Drive an agent with:** *"Read `i18n/TRANSLATING.md` and translate the UI to Russian"* — or *"…and review the existing German translation."*
> 💡 **The one habit that matters most:** read each key's `description` before translating it. Labels are terse and ambiguous on their own; the `description` tells you what the string is, where it shows up, what to keep verbatim, and what it actually means.
---
## What NetBird is
A **business zero-trust VPN** — an encrypted **overlay mesh** between a company's devices, built on **WireGuard®**, connecting peers directly with a **relay** fallback. This is the **desktop client** (tray app + windows) someone runs to connect, switch profiles, browse peers, and pick an exit node — *not* the admin dashboard.
**Audience:** IT-literate professionals. **Tone:** clear and professional, never consumer-cute.
**The vocabulary you'll meet:**
| Term | What it means here |
|---|---|
| **Peer** | A device on the network (laptop, server, phone) |
| **Resource / Network** | A routed network or service reachable through NetBird (UI calls these "Resources") |
| **Exit Node** | A peer that routes *all* internet traffic, like a full-tunnel gateway |
| **Profile** | A saved connection identity you can switch between |
| **Daemon** | The background service the UI talks to |
| **Management server** | The control plane — *Cloud* (hosted) or *self-hosted* (customer-run) |
| **Relay** | Forwards traffic when two peers can't connect directly |
| **Rosenpass** | Post-quantum security layered over WireGuard® |
| **Handshake** | The periodic WireGuard® key sync between peers |
---
## The files
```
i18n/locales/_index.json shipped-language list
i18n/locales/en/common.json source of truth — message + description
i18n/locales/<code>/common.json a target — message only
```
Chrome-extension JSON, each key → `{ "message", "description" }`. You translate the **`message`**.
| ✅ Do | ❌ Don't |
|---|---|
| Keep **every key** from `en`, in the same order | Translate, rename, reorder, drop, or add keys (they're identifiers; the set grows over time) |
| Put **only `message`** in target bundles | Copy `description` into a target bundle |
| Give every key a non-empty `message` | Leave keys missing or empty |
| Save valid UTF-8 JSON, no BOM | Add trailing commas or break the JSON |
---
## Hard rules — get these exactly right
These are the usual ways a translation *breaks the app*, not just reads oddly.
| ✅ Do | ❌ Don't |
|---|---|
| Copy `{placeholders}` verbatim — `{version}`, `{count}`, `{name}`… | Translate the word inside the braces (`{verbleibend}` breaks it) |
| Reposition a placeholder so the sentence flows | Drop or duplicate a placeholder |
| Preserve every `\n`, leading/trailing space, and trailing `...` | Trim "invisible" spaces or the `...` (they're load-bearing) |
| Keep `®` in WireGuard® and quotes around `{name}` | Strip punctuation the description flags |
**Plurals:** the app has only a *one / other* split — the singular key fires only when `count == 1`; the `{count}` key covers everything else (0, 2, 5, 100…). Languages with more than two forms (ru, pl, uk) can't be fully correct here — use the form that fits the widest range (Russian genitive plural: `минут` / `часов` / `дней`). Don't invent extra keys or cram multiple forms into one string. When no single form fits every value — a unit label after a number field, say — reach for a number-agnostic form (an abbreviation, or wording that reads the same for 1 and 100) instead of forcing a plural the *one / other* split can't supply.
**Agreement:** a `{placeholder}` drops a value into a fixed frame, so the words around it must fit *every* value the app can supply. In inflected languages, write the frame in the case the surrounding preposition demands — German's duration fragments are **dative** because they land inside "…in {remaining}" (`in {count} Tagen`, `weniger als einer Minute`), not nominative `Tage`. Check the key that *consumes* the fragment (here `tray.session.expiresIn`) before choosing the form.
---
## Glossary
**Tier A — never translate (brands):** `NetBird` · `WireGuard®` · `Rosenpass` · `GitHub` · `ICE` · company/product names · sample URLs · version numbers.
When a brand sits beside a common noun, keep its exact spelling but join them the way your language builds such phrases — a hyphen, a connector word, an inflected noun — rather than copying English's bare noun-stack.
**Tier B — keep as-is (acronyms):** `SSO` · `MFA` · `DNS` · `IP`/`IPv6` · `ACL` · `SSH` · `GUI` · `P2P` · `URL` · `TCP`/`UDP`.
**Tier C — judgment.** One rule decides every term:
> **Use the word that language's IT users actually say.** Translate when a natural, common term exists; keep the English term *only* when the literal translation would be awkward or no one in that field really uses it.
Apply each term **consistently** — same English term → same translation everywhere — and keep a term once you've settled it. Whether a term stays English or takes a native word is **language-dependent**: a technical loanword (e.g. *Daemon*, *Handshake*) often stays, an everyday word (e.g. *Latency*, *Public key*) usually localizes, and some (*Exit Node*, *Peer*) go either way depending on the language. Decide per term with the rule above — a foreign origin alone is no reason to keep English. **Your main reference is the existing bundles:** match how a term was already rendered for your language rather than re-deciding it.
Two checks before you commit a term:
- **Prefer established localized wording.** If a widely used tool in this space (for example WireGuard) ships your language, its wording for a shared term such as *handshake* is what users already expect — look at the translated app, not just English docs. For generic UI verbs and formal address, follow your OS vendor's style guide (Microsoft / Apple / Google).
- **Watch for false friends.** A literal translation can collide with a *different* established term in your field — confirm your word doesn't already mean something else in this domain before using it.
---
## Style
| ✅ Do | ❌ Don't |
|---|---|
| Use the **formal "you"** (de *Sie*, fr *vous*, ru *вы*, it *Lei*, zh 您) | Use casual/informal address |
| Keep **buttons, menu, and tray** items short, in your language's action form (de "Speichern", fr "Enregistrer") | Let a label run much longer than the English — space is tight |
| Follow **locale punctuation** (fr NBSP + « », de „…", zh full-width), including around a quoted UI label | Carry over English Title Case (use sentence case; German nouns excepted) |
| Translate a term the **same way everywhere** | Vary wording for the same concept across screens |
Where it reads naturally, aim to keep each string **roughly the same length** as the English — the UI is tight and over-long strings can wrap or truncate. It's a soft preference, not a rule: if your language simply needs more words, use them.
A few habits that keep a bundle reading like one product rather than a word-for-word port:
- **Translate meaning, not words.** Render what a string *does*. An idiom or an awkward source phrase should become natural in your language, not a literal calque.
- **Keep one voice within a family.** Sibling strings — the connection states, every settings *help* caption, every "… Failed" title — should share a grammatical form. If one member sounds wrong in that form, re-voice the whole family rather than leave one odd sibling.
- **Mirror opposites.** A status should read as the natural counterpart of its pair: translate *Disconnected* as the opposite of however you rendered *Connected*, not as an unrelated word. Same for Active/Inactive, Selected/Not selected.
- **Give a standalone label its subject.** A bare button or title can lose the context the surrounding English UI implied — add the noun back if it would otherwise read ambiguously.
---
## Procedure
**New language** — read `en/common.json` *with* descriptions → settle your Tier C terms → write `i18n/locales/<code>/common.json` (same keys and order as `en`, `message` only, placeholders & brands preserved) → add a row to `_index.json` (`{"code","displayName"` = native name`,"englishName"}`) → run the QA list. Use the locale-code style the existing entries use (e.g. `fr`, `pt`, `zh-CN`).
**Review (de / hu / …)** — read source and target side by side; for each key check glossary conformance (e.g. de `Exit-Node``Exit Node`, hu `Kilépő csomópont``Exit Node`), placeholder/`\n` integrity, consistency, tone, and that the meaning matches the English `description`. Fix in place, then report what you changed (especially term standardizations) so a native speaker can sanity-check.
---
## QA before you finish
- [ ] Valid JSON · **every `en` key** present, same order · **no `description`** fields
- [ ] Every `{placeholder}`, `\n`, and intentional space preserved · `...` / `… Failed` / `{name}` quotes kept
- [ ] Tier A/B left intact · Tier C applied consistently (and matching the existing bundle for your language)
- [ ] Buttons & tray short · locale punctuation and capitalization applied
- [ ] New language added to `_index.json`
- [ ] **Tested in the running app**
---
## Test it in the app
A bundle can pass every check above and still read wrong on screen. **Run the app, switch to your language, and click through the real surfaces** — tray menu, main window, every Settings tab, the dialogs. Watch for text overflow or truncation, labels that are technically right but wrong *for what the control does*, leaked placeholders, and terms that drift between screens.
How to run the app and switch language: see `../CLAUDE.md` and `../frontend/CLAUDE.md`. Can't run it (e.g. a headless agent)? Say so in your summary — don't silently skip this step.

View File

@@ -2,6 +2,12 @@
"languages": [
{"code": "en", "displayName": "English (US)", "englishName": "English (US)"},
{"code": "de", "displayName": "Deutsch", "englishName": "German"},
{"code": "hu", "displayName": "Magyar", "englishName": "Hungarian"}
{"code": "hu", "displayName": "Magyar", "englishName": "Hungarian"},
{"code": "ru", "displayName": "Русский", "englishName": "Russian"},
{"code": "es", "displayName": "Español", "englishName": "Spanish"},
{"code": "fr", "displayName": "Français", "englishName": "French"},
{"code": "it", "displayName": "Italiano", "englishName": "Italian"},
{"code": "pt", "displayName": "Português", "englishName": "Portuguese"},
{"code": "zh-CN", "displayName": "简体中文", "englishName": "Simplified Chinese"}
]
}

View File

@@ -3,7 +3,7 @@
"message": "NetBird"
},
"tray.status.disconnected": {
"message": "Getrennt"
"message": "Nicht verbunden"
},
"tray.status.daemonUnavailable": {
"message": "Nicht aktiv"
@@ -15,7 +15,7 @@
"message": "Verbunden"
},
"tray.status.connecting": {
"message": "Verbinde"
"message": "Wird verbunden"
},
"tray.status.needsLogin": {
"message": "Anmeldung erforderlich"
@@ -60,7 +60,7 @@
"message": "Trennen"
},
"tray.menu.exitNode": {
"message": "Exit-Node"
"message": "Exit Node"
},
"tray.menu.networks": {
"message": "Ressourcen"
@@ -72,7 +72,7 @@
"message": "Profile verwalten"
},
"tray.menu.settings": {
"message": "Einstellungen..."
"message": "Einstellungen"
},
"tray.menu.debugBundle": {
"message": "Debug-Paket erstellen"
@@ -96,7 +96,7 @@
"message": "Version {version} installieren"
},
"tray.menu.guiVersion": {
"message": "Oberfläche: {version}"
"message": "GUI: {version}"
},
"tray.menu.daemonVersion": {
"message": "Daemon: {version}"
@@ -129,7 +129,7 @@
"message": "Wechsel zu {profile} fehlgeschlagen"
},
"notify.error.exitNode": {
"message": "Exit-Node {name} konnte nicht aktualisiert werden"
"message": "Exit Node {name} konnte nicht aktualisiert werden"
},
"notify.sessionExpired.title": {
"message": "NetBird-Sitzung abgelaufen"
@@ -162,10 +162,10 @@
"message": "Ihre Sitzung wurde erneuert."
},
"notify.sessionDeadlineRejected.title": {
"message": "Sitzungsfrist abgelehnt"
"message": "Ungültige Sitzungsablaufzeit"
},
"notify.sessionDeadlineRejected.body": {
"message": "Der Server hat eine ungültige Sitzungsfrist übermittelt. Bitte melden Sie sich erneut an."
"message": "Der Server hat eine ungültige Sitzungsablaufzeit übermittelt. Bitte melden Sie sich erneut an."
},
"common.cancel": {
"message": "Abbrechen"
@@ -222,22 +222,22 @@
"message": "Es konnten keine Ergebnisse gefunden werden. Bitte versuchen Sie es mit einem anderen Suchbegriff oder ändern Sie Ihre Filter."
},
"notConnected.title": {
"message": "Getrennt"
"message": "Nicht verbunden"
},
"notConnected.description": {
"message": "Verbinden Sie sich zuerst mit NetBird, um detaillierte Informationen zu Ihren Peers, Netzwerkressourcen und Exit Nodes einzusehen."
},
"connect.status.disconnected": {
"message": "Getrennt"
"message": "Nicht verbunden"
},
"connect.status.connecting": {
"message": "Verbindet…"
"message": "Wird verbunden…"
},
"connect.status.connected": {
"message": "Verbunden"
},
"connect.status.disconnecting": {
"message": "Trennt…"
"message": "Wird getrennt…"
},
"connect.status.daemonUnavailable": {
"message": "Daemon nicht verfügbar"
@@ -267,7 +267,7 @@
"message": "{active} von {total} aktiv"
},
"nav.exitNode.title": {
"message": "Exit-Nodes"
"message": "Exit Nodes"
},
"nav.exitNode.none": {
"message": "Nicht aktiv"
@@ -281,18 +281,6 @@
"header.togglePanel": {
"message": "Seitenleiste umschalten"
},
"header.menu.settings": {
"message": "Einstellungen …"
},
"header.menu.defaultView": {
"message": "Standardansicht"
},
"header.menu.advancedView": {
"message": "Erweiterte Ansicht"
},
"header.menu.updateAvailable": {
"message": "Update verfügbar"
},
"profile.selector.loading": {
"message": "Lädt…"
},
@@ -323,24 +311,6 @@
"profile.selector.switchTo": {
"message": "Zu diesem Profil wechseln"
},
"profile.dropdown.activeProfile": {
"message": "Aktives Profil"
},
"profile.dropdown.switchProfile": {
"message": "Profil wechseln"
},
"profile.dropdown.noEmail": {
"message": "Andere"
},
"profile.dropdown.addProfile": {
"message": "Profil hinzufügen"
},
"profile.dropdown.manageProfiles": {
"message": "Profile verwalten"
},
"profile.dropdown.settings": {
"message": "Einstellungen"
},
"profile.dialog.title": {
"message": "Neues Profil"
},
@@ -353,18 +323,30 @@
"profile.dialog.placeholder": {
"message": "z. B. Arbeit"
},
"profile.dialog.required": {
"message": "Bitte geben Sie einen Profilnamen ein, z. B. Arbeit, Privat"
},
"profile.dialog.submit": {
"message": "Profil hinzufügen"
},
"profile.dialog.required": {
"message": "Bitte geben Sie einen Profilnamen ein, z. B. Arbeit, Privat"
},
"profile.dialog.managementHelp": {
"message": "NetBird Cloud oder Ihr eigener Server."
},
"profile.dialog.urlUnreachable": {
"message": "Server nicht erreichbar. Überprüfen Sie die URL, oder fügen Sie das Profil trotzdem hinzu, wenn Sie sicher sind, dass sie korrekt ist."
},
"header.menu.settings": {
"message": "Einstellungen …"
},
"header.menu.defaultView": {
"message": "Standardansicht"
},
"header.menu.advancedView": {
"message": "Erweiterte Ansicht"
},
"header.menu.updateAvailable": {
"message": "Update verfügbar"
},
"profile.switch.title": {
"message": "Zu Profil \"{name}\" wechseln?"
},
@@ -410,6 +392,42 @@
"profile.error.loadTitle": {
"message": "Laden der Profile fehlgeschlagen"
},
"profile.dropdown.activeProfile": {
"message": "Aktives Profil"
},
"profile.dropdown.switchProfile": {
"message": "Profil wechseln"
},
"profile.dropdown.noEmail": {
"message": "Andere"
},
"profile.dropdown.addProfile": {
"message": "Profil hinzufügen"
},
"profile.dropdown.manageProfiles": {
"message": "Profile verwalten"
},
"profile.dropdown.settings": {
"message": "Einstellungen"
},
"settings.profiles.section.profiles": {
"message": "Profile"
},
"settings.profiles.intro": {
"message": "Verwalten Sie mehrere NetBird-Profile parallel, zum Beispiel berufliche und private Konten oder verschiedene Management-Server. Fügen Sie unten Profile hinzu, melden Sie sie ab oder löschen Sie sie."
},
"settings.profiles.addProfile": {
"message": "Profil hinzufügen"
},
"settings.profiles.active": {
"message": "Aktiv"
},
"settings.profiles.emptyTitle": {
"message": "Keine Profile"
},
"settings.profiles.emptyDescription": {
"message": "Erstellen Sie ein Profil, um sich mit einem NetBird-Management-Server zu verbinden."
},
"settings.error.loadTitle": {
"message": "Laden der Einstellungen fehlgeschlagen"
},
@@ -428,12 +446,12 @@
"settings.tabs.security": {
"message": "Sicherheit"
},
"settings.tabs.ssh": {
"message": "SSH"
},
"settings.tabs.profiles": {
"message": "Profile"
},
"settings.tabs.ssh": {
"message": "SSH"
},
"settings.tabs.advanced": {
"message": "Erweitert"
},
@@ -446,24 +464,6 @@
"settings.tabs.updateAvailable": {
"message": "Update verfügbar"
},
"settings.profiles.section.profiles": {
"message": "Profile"
},
"settings.profiles.intro": {
"message": "Halten Sie separate NetBird-Identitäten nebeneinander, zum Beispiel berufliche und private Konten oder verschiedene Management-Server. Fügen Sie unten Profile hinzu, melden Sie sie ab oder löschen Sie sie."
},
"settings.profiles.addProfile": {
"message": "Profil hinzufügen"
},
"settings.profiles.active": {
"message": "Aktiv"
},
"settings.profiles.emptyTitle": {
"message": "Keine Profile"
},
"settings.profiles.emptyDescription": {
"message": "Erstellen Sie ein Profil, um sich mit einem NetBird-Management-Server zu verbinden."
},
"settings.general.section.general": {
"message": "Allgemein"
},
@@ -540,7 +540,7 @@
"message": "Routing & DNS"
},
"settings.network.lazy.label": {
"message": "Verzögerte Verbindungen"
"message": "Lazy-Verbindungen"
},
"settings.network.lazy.help": {
"message": "Statt durchgehend aktive Verbindungen zu halten, aktiviert NetBird sie bei Bedarf anhand von Aktivität oder Signalisierung."
@@ -597,7 +597,7 @@
"message": "Quantenresistenz aktivieren"
},
"settings.security.rosenpass.help": {
"message": "Einen post-quanten Schlüsselaustausch via Rosenpass zusätzlich zu WireGuard® hinzufügen."
"message": "Einen Post-Quanten-Schlüsselaustausch über Rosenpass zusätzlich zu WireGuard® hinzufügen."
},
"settings.security.rosenpassPermissive.label": {
"message": "Permissiven Modus aktivieren"
@@ -669,7 +669,7 @@
"message": "Name"
},
"settings.advanced.interfaceName.error": {
"message": "Verwende 115 Buchstaben, Ziffern, Punkt, Bindestrich oder Unterstrich."
"message": "Verwenden Sie 115 Buchstaben, Ziffern, Punkte, Bindestriche oder Unterstriche."
},
"settings.advanced.interfaceName.errorMac": {
"message": "Muss mit „utun“ und einer Zahl beginnen (z. B. utun100)."
@@ -678,7 +678,7 @@
"message": "Port"
},
"settings.advanced.port.error": {
"message": "Gib einen Port zwischen {min} und {max} ein."
"message": "Geben Sie einen Port zwischen {min} und {max} ein."
},
"settings.advanced.port.help": {
"message": "Wenn auf 0 gesetzt, wird ein zufälliger freier Port verwendet."
@@ -687,13 +687,13 @@
"message": "MTU"
},
"settings.advanced.mtu.error": {
"message": "Gib eine MTU zwischen {min} und {max} ein."
"message": "Geben Sie einen MTU-Wert zwischen {min} und {max} ein."
},
"settings.advanced.psk.label": {
"message": "Pre-shared Key"
},
"settings.advanced.psk.help": {
"message": "Optionaler WireGuard-PSK für zusätzliche symmetrische Verschlüsselung. Nicht identisch mit einem NetBird Setup Key. Sie kommunizieren nur mit Peers, die denselben Pre-shared Key verwenden."
"message": "Optionaler WireGuard-PSK für zusätzliche symmetrische Verschlüsselung. Nicht identisch mit einem NetBird Setup-Key. Sie kommunizieren nur mit Peers, die denselben Pre-shared Key verwenden."
},
"settings.troubleshooting.section.title": {
"message": "Debug-Paket"
@@ -735,7 +735,7 @@
"message": "Minute(n)"
},
"settings.troubleshooting.create": {
"message": "Paket erstellen"
"message": "Debug-Paket erstellen"
},
"settings.troubleshooting.progress.description": {
"message": "Logs, Systemdetails und Verbindungszustand werden gesammelt. Dies dauert in der Regel einen Moment — lassen Sie dieses Fenster geöffnet, bis es abgeschlossen ist."
@@ -801,10 +801,10 @@
"message": "[Entwicklung]"
},
"settings.about.gui": {
"message": "Oberfläche v{version}"
"message": "GUI v{version}"
},
"settings.about.guiName": {
"message": "Oberfläche"
"message": "GUI"
},
"settings.about.copyright": {
"message": "© {year} NetBird. Alle Rechte vorbehalten."
@@ -864,10 +864,10 @@
"message": "NetBird sucht im Hintergrund nach Updates."
},
"update.card.changelog": {
"message": "Änderungsprotokoll"
"message": "Changelog"
},
"update.card.onLatestVersion": {
"message": "Du verwendest die neueste Version"
"message": "Sie verwenden die neueste Version"
},
"update.header.tooltip": {
"message": "Update verfügbar"
@@ -924,7 +924,7 @@
"message": "Ihre Client-Version ist älter als die im Management eingestellte Auto-Update-Version."
},
"update.page.status.running": {
"message": "Aktualisiert"
"message": "Wird aktualisiert"
},
"update.page.status.timeout": {
"message": "Zeitüberschreitung beim Update. Bitte erneut versuchen."
@@ -948,7 +948,7 @@
"message": "Bitte schließen Sie dieses Fenster nicht."
},
"update.page.updating": {
"message": "Aktualisiert…"
"message": "Wird aktualisiert…"
},
"update.page.complete": {
"message": "Update abgeschlossen"
@@ -990,7 +990,7 @@
"message": "NetBird einrichten"
},
"welcome.management.description": {
"message": "Klicken Sie auf „Weiter“, um loszulegen, oder wählen Sie Self-hosted, wenn Sie einen eigenen NetBird-Server haben."
"message": "Klicken Sie auf „Weiter“, um loszulegen, oder wählen Sie Self-hosted, wenn Sie einen eigenen NetBird-Server haben."
},
"welcome.management.cloud.title": {
"message": "NetBird Cloud"
@@ -999,7 +999,7 @@
"message": "Nutzen Sie unseren gehosteten Dienst. Keine Einrichtung nötig."
},
"welcome.management.selfHosted.title": {
"message": "Selbst gehostet"
"message": "Self-hosted"
},
"welcome.management.selfHosted.description": {
"message": "Verbindung zu Ihrem eigenen Management-Server."
@@ -1137,10 +1137,10 @@
"message": "Verbunden"
},
"peers.status.connecting": {
"message": "Verbinde"
"message": "Wird verbunden"
},
"peers.status.disconnected": {
"message": "Getrennt"
"message": "Nicht verbunden"
},
"peers.details.relayAddress": {
"message": "Relay"
@@ -1248,7 +1248,7 @@
"message": "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an."
},
"error.invalid_setup_key": {
"message": "Der Setup-Schlüssel fehlt oder ist ungültig."
"message": "Der Setup-Key fehlt oder ist ungültig."
},
"error.permission_denied": {
"message": "Die Anmeldung wurde vom Server abgelehnt."

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"message": "NetBird"
},
"tray.status.disconnected": {
"message": "Lekapcsolva"
"message": "Lecsatlakozva"
},
"tray.status.daemonUnavailable": {
"message": "Nem fut"
@@ -12,10 +12,10 @@
"message": "Hiba"
},
"tray.status.connected": {
"message": "Kapcsolódva"
"message": "Csatlakozva"
},
"tray.status.connecting": {
"message": "Kapcsolódás"
"message": "Csatlakozás"
},
"tray.status.needsLogin": {
"message": "Bejelentkezés szükséges"
@@ -60,7 +60,7 @@
"message": "Bontás"
},
"tray.menu.exitNode": {
"message": "Kilépő csomópont"
"message": "Exit Node"
},
"tray.menu.networks": {
"message": "Erőforrások"
@@ -72,7 +72,7 @@
"message": "Profilok kezelése"
},
"tray.menu.settings": {
"message": "Beállítások..."
"message": "Beállítások"
},
"tray.menu.debugBundle": {
"message": "Hibakeresési csomag készítése"
@@ -96,7 +96,7 @@
"message": "{version} verzió telepítése"
},
"tray.menu.guiVersion": {
"message": "Felület: {version}"
"message": "GUI: {version}"
},
"tray.menu.daemonVersion": {
"message": "Daemon: {version}"
@@ -129,7 +129,7 @@
"message": "Átváltás sikertelen erre: {profile}"
},
"notify.error.exitNode": {
"message": "A kilépő csomópont frissítése sikertelen: {name}"
"message": "Az Exit Node frissítése sikertelen: {name}"
},
"notify.sessionExpired.title": {
"message": "NetBird munkamenet lejárt"
@@ -141,10 +141,10 @@
"message": "Munkamenet hamarosan lejár"
},
"notify.sessionWarning.body": {
"message": "A NetBird munkamenet {remaining} múlva lejár. Kattints a Meghosszabbítás gombra a megújításhoz."
"message": "A NetBird munkamenet {remaining} múlva lejár. Kattintson a Meghosszabbítás gombra a megújításhoz."
},
"notify.sessionWarning.bodyGeneric": {
"message": "A NetBird munkamenet hamarosan lejár. Kattints a Meghosszabbítás gombra a megújításhoz."
"message": "A NetBird munkamenet hamarosan lejár. Kattintson a Meghosszabbítás gombra a megújításhoz."
},
"notify.sessionWarning.extend": {
"message": "Meghosszabbítás"
@@ -225,19 +225,19 @@
"message": "Lecsatlakozva"
},
"notConnected.description": {
"message": "Csatlakozz először a NetBirdhöz, hogy részletes információkat láthass a társakról, hálózati erőforrásokról és kilépő csomópontokról."
"message": "Csatlakozzon először a NetBirdhöz, hogy részletes információkat láthasson a Peerekről, a hálózati erőforrásokról és az Exit Node-okról."
},
"connect.status.disconnected": {
"message": "Lekapcsolva"
"message": "Lecsatlakozva"
},
"connect.status.connecting": {
"message": "Csatlakozás…"
},
"connect.status.connected": {
"message": "Csatlakoztatva"
"message": "Csatlakozva"
},
"connect.status.disconnecting": {
"message": "Bontás…"
"message": "Lecsatlakozás…"
},
"connect.status.daemonUnavailable": {
"message": "Daemon nem elérhető"
@@ -255,7 +255,7 @@
"message": "Bontás sikertelen"
},
"nav.peers.title": {
"message": "Társak"
"message": "Peerek"
},
"nav.peers.description": {
"message": "{connected} / {total} csatlakoztatva"
@@ -267,7 +267,7 @@
"message": "{active} / {total} aktív"
},
"nav.exitNode.title": {
"message": "Kilépő csomópontok"
"message": "Exit Node-ok"
},
"nav.exitNode.none": {
"message": "Nem aktív"
@@ -281,18 +281,6 @@
"header.togglePanel": {
"message": "Oldalsó panel váltása"
},
"header.menu.settings": {
"message": "Beállítások…"
},
"header.menu.defaultView": {
"message": "Alapnézet"
},
"header.menu.advancedView": {
"message": "Speciális nézet"
},
"header.menu.updateAvailable": {
"message": "Frissítés elérhető"
},
"profile.selector.loading": {
"message": "Betöltés…"
},
@@ -323,24 +311,6 @@
"profile.selector.switchTo": {
"message": "Váltás erre a profilra"
},
"profile.dropdown.activeProfile": {
"message": "Aktív profil"
},
"profile.dropdown.switchProfile": {
"message": "Profilváltás"
},
"profile.dropdown.noEmail": {
"message": "Egyéb"
},
"profile.dropdown.addProfile": {
"message": "Profil hozzáadása"
},
"profile.dropdown.manageProfiles": {
"message": "Profilok kezelése"
},
"profile.dropdown.settings": {
"message": "Beállítások"
},
"profile.dialog.title": {
"message": "Új profil"
},
@@ -353,18 +323,30 @@
"profile.dialog.placeholder": {
"message": "pl. Munka"
},
"profile.dialog.required": {
"message": "Adjon meg egy profilnevet, pl. Munka, Otthon"
},
"profile.dialog.submit": {
"message": "Profil hozzáadása"
},
"profile.dialog.required": {
"message": "Adjon meg egy profilnevet, pl. Munka, Otthon"
},
"profile.dialog.managementHelp": {
"message": "NetBird Cloud vagy saját kiszolgáló."
},
"profile.dialog.urlUnreachable": {
"message": "A szerver nem érhető el. Ellenőrizze az URL-t, vagy adja hozzá a profilt, ha biztos benne, hogy helyes."
},
"header.menu.settings": {
"message": "Beállítások…"
},
"header.menu.defaultView": {
"message": "Alapnézet"
},
"header.menu.advancedView": {
"message": "Speciális nézet"
},
"header.menu.updateAvailable": {
"message": "Frissítés elérhető"
},
"profile.switch.title": {
"message": "Váltás a(z) \"{name}\" profilra?"
},
@@ -410,6 +392,42 @@
"profile.error.loadTitle": {
"message": "Profilok betöltése sikertelen"
},
"profile.dropdown.activeProfile": {
"message": "Aktív profil"
},
"profile.dropdown.switchProfile": {
"message": "Profilváltás"
},
"profile.dropdown.noEmail": {
"message": "Egyéb"
},
"profile.dropdown.addProfile": {
"message": "Profil hozzáadása"
},
"profile.dropdown.manageProfiles": {
"message": "Profilok kezelése"
},
"profile.dropdown.settings": {
"message": "Beállítások"
},
"settings.profiles.section.profiles": {
"message": "Profilok"
},
"settings.profiles.intro": {
"message": "Kezeljen több NetBird-profilt párhuzamosan, például munkahelyi és személyes fiókokat, vagy különböző felügyeleti szervereket. Lent hozzáadhat, leválaszthat vagy törölhet profilokat."
},
"settings.profiles.addProfile": {
"message": "Profil hozzáadása"
},
"settings.profiles.active": {
"message": "Aktív"
},
"settings.profiles.emptyTitle": {
"message": "Nincsenek profilok"
},
"settings.profiles.emptyDescription": {
"message": "Hozzon létre egy profilt a NetBird felügyeleti szerverhez való csatlakozáshoz."
},
"settings.error.loadTitle": {
"message": "Beállítások betöltése sikertelen"
},
@@ -428,12 +446,12 @@
"settings.tabs.security": {
"message": "Biztonság"
},
"settings.tabs.ssh": {
"message": "SSH"
},
"settings.tabs.profiles": {
"message": "Profilok"
},
"settings.tabs.ssh": {
"message": "SSH"
},
"settings.tabs.advanced": {
"message": "Speciális"
},
@@ -446,24 +464,6 @@
"settings.tabs.updateAvailable": {
"message": "Frissítés elérhető"
},
"settings.profiles.section.profiles": {
"message": "Profilok"
},
"settings.profiles.intro": {
"message": "Tartson külön NetBird-identitásokat egymás mellett, például munkahelyi és személyes fiókokat, vagy különböző kezelőszervereket. Lent hozzáadhat, leválaszthat vagy törölhet profilokat."
},
"settings.profiles.addProfile": {
"message": "Profil hozzáadása"
},
"settings.profiles.active": {
"message": "Aktív"
},
"settings.profiles.emptyTitle": {
"message": "Nincsenek profilok"
},
"settings.profiles.emptyDescription": {
"message": "Hozzon létre egy profilt a NetBird kezelőszerverhez való csatlakozáshoz."
},
"settings.general.section.general": {
"message": "Általános"
},
@@ -504,10 +504,10 @@
"message": "Nincs találat."
},
"settings.general.management.label": {
"message": "Kezelőszerver"
"message": "Felügyeleti szerver"
},
"settings.general.management.help": {
"message": "Csatlakozás a NetBird Cloudhoz vagy saját self-hosted kezelőszerverhez. A módosítások újracsatlakozást váltanak ki."
"message": "Csatlakozás a NetBird Cloudhoz vagy saját üzemeltetésű felügyeleti szerverhez. A módosítások újracsatlakozást váltanak ki."
},
"settings.general.management.cloud": {
"message": "Felhő"
@@ -540,7 +540,7 @@
"message": "Útválasztás és DNS"
},
"settings.network.lazy.label": {
"message": "Késleltetett kapcsolatok"
"message": "Igény szerinti kapcsolatok"
},
"settings.network.lazy.help": {
"message": "Állandó kapcsolatok fenntartása helyett a NetBird igény szerint, aktivitás vagy jelzés alapján aktiválja azokat."
@@ -561,13 +561,13 @@
"message": "Kliens útvonalak engedélyezése"
},
"settings.network.clientRoutes.help": {
"message": "Más társak útvonalainak elfogadása az ő hálózataik eléréséhez."
"message": "Más Peerek útvonalainak elfogadása a hálózataik eléréséhez."
},
"settings.network.serverRoutes.label": {
"message": "Szerver útvonalak engedélyezése"
},
"settings.network.serverRoutes.help": {
"message": "Ennek a gazdának a helyi útvonalainak meghirdetése más társak számára."
"message": "Ennek a gazdának a helyi útvonalainak meghirdetése más Peerek számára."
},
"settings.network.ipv6.label": {
"message": "IPv6 engedélyezése"
@@ -585,13 +585,13 @@
"message": "Bejövő forgalom blokkolása"
},
"settings.security.blockInbound.help": {
"message": "Visszautasítja a társaktól érkező nem kért kapcsolatokat ezen eszközhöz és az általa irányított hálózatokhoz. A kimenő forgalmat nem érinti."
"message": "Visszautasítja a Peerektől érkező nem kért kapcsolatokat ezen eszközhöz és az általa irányított hálózatokhoz. A kimenő forgalmat nem érinti."
},
"settings.security.blockLan.label": {
"message": "LAN-hozzáférés blokkolása"
},
"settings.security.blockLan.help": {
"message": "Megakadályozza, hogy a társak elérjék a helyi hálózatot vagy annak eszközeit, amikor ez az eszköz irányítja a forgalmukat."
"message": "Megakadályozza, hogy a Peerek elérjék a helyi hálózatot vagy annak eszközeit, amikor ez az eszköz irányítja a forgalmukat."
},
"settings.security.rosenpass.label": {
"message": "Kvantumellenálló titkosítás engedélyezése"
@@ -603,7 +603,7 @@
"message": "Engedékeny mód engedélyezése"
},
"settings.security.rosenpassPermissive.help": {
"message": "Kapcsolatok engedélyezése kvantumellenálló titkosítás nélküli társakkal."
"message": "Kapcsolatok engedélyezése kvantumellenálló titkosítás nélküli Peerekkel."
},
"settings.ssh.section.server": {
"message": "Szerver"
@@ -618,13 +618,13 @@
"message": "SSH szerver engedélyezése"
},
"settings.ssh.server.help": {
"message": "Futtassa a NetBird SSH szervert ezen a gazdán, hogy más társak csatlakozhassanak."
"message": "Futtassa a NetBird SSH szervert ezen a gazdán, hogy más Peerek csatlakozhassanak."
},
"settings.ssh.root.label": {
"message": "Root bejelentkezés engedélyezése"
},
"settings.ssh.root.help": {
"message": "Társak bejelentkezhetnek root felhasználóként. Tiltsa le, ha nem privilegizált fiók szükséges."
"message": "A Peerek bejelentkezhetnek root felhasználóként. Tiltsa le, ha nem privilegizált fiók szükséges."
},
"settings.ssh.sftp.label": {
"message": "SFTP engedélyezése"
@@ -636,13 +636,13 @@
"message": "Helyi porttovábbítás"
},
"settings.ssh.localForward.help": {
"message": "A csatlakozó társak helyi portokat alagútba helyezhetnek erről a gazdáról elérhető szolgáltatásokhoz."
"message": "A csatlakozó Peerek helyi portokat alagútba helyezhetnek erről a gazdáról elérhető szolgáltatásokhoz."
},
"settings.ssh.remoteForward.label": {
"message": "Távoli porttovábbítás"
},
"settings.ssh.remoteForward.help": {
"message": "A csatlakozó társak ezen a gazdán lévő portokat tehetnek elérhetővé a saját gépük számára."
"message": "A csatlakozó Peerek ezen a gazdán lévő portokat tehetnek elérhetővé a saját gépük számára."
},
"settings.ssh.jwt.label": {
"message": "JWT-hitelesítés engedélyezése"
@@ -669,7 +669,7 @@
"message": "Név"
},
"settings.advanced.interfaceName.error": {
"message": "Használj 115 betűt, számot, pontot, kötőjelet vagy aláhúzást."
"message": "Használjon 115 betűt, számot, pontot, kötőjelet vagy aláhúzást."
},
"settings.advanced.interfaceName.errorMac": {
"message": "„utun” után számmal kezdődjön (pl. utun100)."
@@ -678,22 +678,22 @@
"message": "Port"
},
"settings.advanced.port.error": {
"message": "Adj meg egy portot {min} és {max} között."
"message": "Adjon meg egy portot {min} és {max} között."
},
"settings.advanced.port.help": {
"message": "Ha 0-ra állítod, egy véletlenszerű szabad portot használ."
"message": "Ha 0-ra állítja, egy véletlenszerű szabad portot használ."
},
"settings.advanced.mtu.label": {
"message": "MTU"
},
"settings.advanced.mtu.error": {
"message": "Adj meg egy MTU értéket {min} és {max} között."
"message": "Adjon meg egy MTU értéket {min} és {max} között."
},
"settings.advanced.psk.label": {
"message": "Pre-shared kulcs"
},
"settings.advanced.psk.help": {
"message": "Opcionális WireGuard PSK további szimmetrikus titkosításhoz. Nem azonos a NetBird telepítőkulccsal. Csak olyan társakkal kommunikál, akik ugyanazt a pre-shared kulcsot használják."
"message": "Opcionális WireGuard PSK további szimmetrikus titkosításhoz. Nem azonos a NetBird telepítőkulccsal. Csak olyan Peerekkel kommunikál, akik ugyanazt a pre-shared kulcsot használják."
},
"settings.troubleshooting.section.title": {
"message": "Hibakeresési csomag"
@@ -735,7 +735,7 @@
"message": "perc"
},
"settings.troubleshooting.create": {
"message": "Csomag létrehozása"
"message": "Hibakeresési csomag létrehozása"
},
"settings.troubleshooting.progress.description": {
"message": "Naplók, rendszerinformációk és kapcsolati állapot gyűjtése folyamatban. Általában néhány pillanatot vesz igénybe — tartsa nyitva ezt az ablakot a befejezésig."
@@ -801,10 +801,10 @@
"message": "[Fejlesztés]"
},
"settings.about.gui": {
"message": "Felület v{version}"
"message": "GUI v{version}"
},
"settings.about.guiName": {
"message": "Felület"
"message": "GUI"
},
"settings.about.copyright": {
"message": "© {year} NetBird. Minden jog fenntartva."
@@ -867,7 +867,7 @@
"message": "Változásnapló"
},
"update.card.onLatestVersion": {
"message": "A legfrissebb verziót használod"
"message": "A legfrissebb verziót használja"
},
"update.header.tooltip": {
"message": "Frissítés elérhető"
@@ -990,7 +990,7 @@
"message": "NetBird beállítása"
},
"welcome.management.description": {
"message": "Kattintson a Folytatás gombra a kezdéshez, vagy válassza a Self-hosted lehetőséget, ha saját NetBird-szervere van."
"message": "Kattintson a Folytatás gombra a kezdéshez, vagy válassza a „Saját üzemeltetésű” lehetőséget, ha saját NetBird-szervere van."
},
"welcome.management.cloud.title": {
"message": "NetBird Cloud"
@@ -1002,10 +1002,10 @@
"message": "Saját üzemeltetésű"
},
"welcome.management.selfHosted.description": {
"message": "Csatlakozás a saját menedzsmentszerveréhez."
"message": "Csatlakozás a saját felügyeleti szerveréhez."
},
"welcome.management.urlLabel": {
"message": "Menedzsmentszerver URL"
"message": "Felügyeleti szerver URL"
},
"welcome.management.urlPlaceholder": {
"message": "https://netbird.selfhosted.com:443"
@@ -1080,10 +1080,10 @@
"message": "Offline"
},
"peers.empty.title": {
"message": "Nincs elérhető társ"
"message": "Nincs elérhető Peer"
},
"peers.empty.description": {
"message": "Önnek vagy nincsenek elérhető társai vagy nincs hozzáférése egyikhez sem."
"message": "Önnek vagy nincsenek elérhető Peerei, vagy nincs hozzáférése egyikhez sem."
},
"peers.details.domain": {
"message": "Domain"
@@ -1095,7 +1095,7 @@
"message": "NetBird IPv6"
},
"peers.details.publicKey": {
"message": "Publikus kulcs"
"message": "Nyilvános kulcs"
},
"peers.details.connection": {
"message": "Kapcsolat"
@@ -1104,7 +1104,7 @@
"message": "Késleltetés"
},
"peers.details.lastHandshake": {
"message": "Utolsó kézfogás"
"message": "Utolsó Handshake"
},
"peers.details.statusSince": {
"message": "Utolsó kapcsolati frissítés"
@@ -1194,19 +1194,19 @@
"message": "Összes letiltása"
},
"exitNodes.search.placeholder": {
"message": "Keresés a kilépő csomópontok között"
"message": "Keresés az Exit Node-ok között"
},
"exitNodes.none": {
"message": "Egyik sem"
},
"exitNodes.empty.title": {
"message": "Nincs elérhető kilépő csomópont"
"message": "Nincs elérhető Exit Node"
},
"exitNodes.empty.description": {
"message": "Ehhez a társhoz nem osztottak meg kilépő csomópontokat."
"message": "Ehhez a Peerhez nem osztottak meg Exit Node-okat."
},
"exitNodes.card.title": {
"message": "Kilépő csomópont"
"message": "Exit Node"
},
"exitNodes.card.statusActive": {
"message": "Aktív"
@@ -1218,7 +1218,7 @@
"message": "Egyik sem"
},
"exitNodes.dropdown.noneDescription": {
"message": "Közvetlen kapcsolat kilépő csomópont nélkül"
"message": "Közvetlen kapcsolat Exit Node nélkül"
},
"quickActions.connect": {
"message": "Csatlakozás"
@@ -1248,7 +1248,7 @@
"message": "A munkamenet lejárt. Kérjük, jelentkezzen be újra."
},
"error.invalid_setup_key": {
"message": "A telepítési kulcs hiányzik vagy érvénytelen."
"message": "A telepítőkulcs hiányzik vagy érvénytelen."
},
"error.permission_denied": {
"message": "A szerver elutasította a bejelentkezést."

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff