mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-29 04:27:30 -06:00
Swedish interface translation (sv)
Adds Swedish (Svenska) as an interface language: 2707 strings, written from the English source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7af7b31af6
commit
9ce2804160
@@ -405,7 +405,7 @@ CRAFT_FONTS_DIR=../craft-fonts cargo run --release -p lightcraft
|
||||
Without it LightCraft builds and runs the same, but Chinese and Japanese text have no glyphs. Fonts are never committed to this
|
||||
repo — the standard for what goes there lives with it: see the [craft-fonts README](https://github.com/storytold/craft-fonts#readme).
|
||||
|
||||
**Interface language:** **Edit → Language** (English, 简体中文, 繁體中文(台灣), 日本語, Português (Brasil), Español, Deutsch, Русский, Français, Українська, Čeština) or **Settings → General →
|
||||
**Interface language:** **Edit → Language** (English, 简体中文, 繁體中文(台灣), 日本語, Português (Brasil), Español, Deutsch, Русский, Français, Українська, Čeština, Svenska) or **Settings → General →
|
||||
Language**; the choice applies immediately and persists. See [docs/localization.md](docs/localization.md).
|
||||
|
||||
**Logs:** the desktop app writes its log to standard error and to `logs/lightcraft.log` in its settings folder
|
||||
|
||||
@@ -29,6 +29,7 @@ covers a whole directory), or if a licence file referenced in the Licence column
|
||||
| craft-fonts: optional build input, not files in this repository | BIZ UDPGothic (Regular, Bold), BIZ UDMincho Regular, Shippori Mincho Regular, Noto Sans CJK SC Regular, Noto Sans Arabic Regular, Noto Sans Thai Regular | The Noto Project Authors (Arabic and Thai); Morisawa Inc. / The BIZ UDGothic and BIZ UDMincho Project Authors; The Shippori Mincho Project Authors; Google and Adobe (Noto Sans CJK, maintainer-approved exception; see AGENTS.md) (per craft-fonts' attribution) | https://github.com/storytold/craft-fonts/blob/main/ATTRIBUTION.md | SIL Open Font License 1.1 (each font's OFL.txt in craft-fonts; release packages ship it as OFL-<family>.txt) | 2026-10-06 | none; native builds made with `CRAFT_FONTS_DIR` embed the manifest fonts (all official releases); the web build embeds BIZ UDPGothic Regular and Noto Sans Thai Regular and ships Noto Sans CJK SC Regular as a separate font file |
|
||||
| `crates/ui-egui/locales/uk.json`, `crates/ui-egui/locales/uk-formats.json` | Ukrainian interface catalogs | @dmatviichuk with Codex; PhotoCraft, FilmCraft and VectorCraft translation contributors for reused labels | original translations from English source; 337 initial English-key matches reviewed from [PhotoCraft 69c41f3](https://github.com/storytold/photocraft/blob/69c41f3523e147eb215da8c7b4c29b18b35d1c63/crates/ui-egui/src/i18n/uk.tsv), [FilmCraft 4854c27](https://github.com/storytold/filmcraft/blob/4854c277536fe8118257362304b6a7d82d8e704b/crates/ui-egui/src/i18n/uk.tsv), [VectorCraft 4b44265](https://github.com/storytold/vectorcraft/blob/4b44265965fdd6ffedfd6182a892c1a6c360d344/crates/ui-egui/src/i18n/uk.tsv) | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`, also the source repositories' licences) | 2026-10-09 | adapted to LightCraft photo-development context, completed catalogs, reviewed spelling and placeholders |
|
||||
| `crates/ui-egui/locales/cs.json`, `crates/ui-egui/locales/cs-formats.json` | Czech interface catalogs | @Losminek with AI assistance (Codex) | original work: translations of English source phrases, reviewed against the app UI conventions; no external translation material | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | 2026-10-11 | catalog coverage, Czech dates and count-neutral wording; independent scope/terminology review; native-speaker proofreading pending |
|
||||
| `crates/ui-egui/locales/sv.json`, `crates/ui-egui/locales/sv-formats.json` | Swedish interface catalogs | LightCraft contributors | original work: clean-room Swedish translations of English source phrases | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | 2026-10-15 | none |
|
||||
|
||||
Notes
|
||||
- Fonts authored or published by Adobe (Source Sans/Serif/Code, Source Han, …) are not used, even though some are
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
{
|
||||
" ({unsure} with several look-alike files: use Locate)": " ({unsure} med flera likadana filer: använd Leta upp)",
|
||||
" ({} in Recently Deleted)": " ({} i Nyligen raderade)",
|
||||
" in {g} group{}": " i {g} grupp{}",
|
||||
" · kept, not applied: {}": " · behålls men tillämpas inte: {}",
|
||||
" · {:.0}% clipped": " · {:.0} % klippt",
|
||||
" · {failed} couldn't be rendered": " · {failed} kunde inte renderas",
|
||||
" · {n} skipped (could not be rendered)": " · {n} överhoppade (kunde inte renderas)",
|
||||
" · {queued} waiting": " · {queued} väntar",
|
||||
" · {skipped} skipped (file exists)": " · {skipped} överhoppade (filen finns)",
|
||||
" · {} duplicate{} skipped": " · {} dubblett{} överhoppade",
|
||||
" · {} failed: {}": " · {} misslyckades: {}",
|
||||
" · {} moved": " · {} flyttade",
|
||||
" · {} not readable": " · {} kunde inte läsas",
|
||||
" · {} original{} left at the source": " · {} original{} kvar i källan",
|
||||
" · {} restored from Recently Deleted": " · {} återställda från Nyligen raderade",
|
||||
" — Capture One won't import a list with ; , < or > in a keyword: {names}": " — Capture One importerar inte en lista med ; , < eller > i ett nyckelord: {names}",
|
||||
" — kept but not applied: {}": " — behålls men tillämpas inte: {}",
|
||||
" — left out, as a keyword list can't hold them: {names}": " — utelämnade, eftersom en nyckelordslista inte kan innehålla dem: {names}",
|
||||
" — not carried over: {}{}": " — fördes inte över: {}{}",
|
||||
"+{n} more": "+{n} till",
|
||||
"+{} more": "+{} till",
|
||||
", {failed} file{} not readable": ", {failed} fil{} kunde inte läsas",
|
||||
", {} label": ", {} etikett",
|
||||
", {} star{}": ", {} stjärna{}",
|
||||
"1 task is still running: {names}. Quitting stops it.": "1 uppgift körs fortfarande: {names}. Om du avslutar stoppas den.",
|
||||
"; {kept} already had a location": "; {kept} hade redan en plats",
|
||||
"; {n} gained synonyms": "; {n} fick synonymer",
|
||||
"; {outside} outside its time range": "; {outside} utanför sitt tidsintervall",
|
||||
"@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {}": "@{}: {} PR:er, {} commits, +{} / −{} rader (Δ {}), +{} / −{} binära resurser, {} – {}",
|
||||
"Add {local_n} to My Photos": "Lägg till {local_n} i Mina foton",
|
||||
"Add {} Photo{}": "Lägg till {} foto{}",
|
||||
"Add {} Photo{}, restore {}": "Lägg till {} foto{}, återställ {}",
|
||||
"Add “{}” to Favorites": "Lägg till ”{}” i Favoriter",
|
||||
"Added {n} keyword{}": "Lade till {n} nyckelord{}",
|
||||
"Added {n} photo{} to My Photos": "Lade till {n} foto{} i Mina foton",
|
||||
"Added {n} photo{} to “{}”": "Lade till {n} foto{} i ”{}”",
|
||||
"Added {what} to {name}": "Lade till {what} i {name}",
|
||||
"Added “{keyword}” to {n} photo{}": "Lade till ”{keyword}” på {n} foto{}",
|
||||
"Adding photos… {} of {}": "Lägger till foton… {} av {}",
|
||||
"All {n} selected photos move by the same amount.": "Alla {n} markerade foton flyttas lika mycket.",
|
||||
"Already in the library, in Recently Deleted: {} photo{} selected · right-click ▸ Restore, or Delete Permanently to import afresh": "Finns redan i biblioteket, i Nyligen raderade: {} foto{} markerade · högerklicka → Återställ, eller Radera permanent för att importera på nytt",
|
||||
"Already in the library: {} photo{} selected in All Photos": "Finns redan i biblioteket: {} foto{} markerade i Alla foton",
|
||||
"Applied {name}": "Tillämpade {name}",
|
||||
"Apply to “{mask}” on Selected Photos": "Använd på ”{mask}” i markerade foton",
|
||||
"Auto ({})": "Auto ({})",
|
||||
"Auto Import: added {} photo{}": "Automatisk import: lade till {} foto{}",
|
||||
"Auto Sync: edits apply to {n} photos": "Automatisk synkning: ändringar gäller {n} foton",
|
||||
"Automatic ({} MB)": "Automatisk ({} MB)",
|
||||
"Build 1:1 Previews ({scope})": "Bygg 1:1-förhandsgranskningar ({scope})",
|
||||
"Build Smart Previews ({scope})": "Bygg smarta förhandsgranskningar ({scope})",
|
||||
"Build Standard-Sized Previews ({scope})": "Bygg förhandsgranskningar i standardstorlek ({scope})",
|
||||
"Building previews for {} photos…": "Bygger förhandsgranskningar för {} foton…",
|
||||
"Click {}:1": "Klick {}:1",
|
||||
"Couldn't open the editor: {e}": "Kunde inte öppna redigeraren: {e}",
|
||||
"Create Keyword Tag Inside “{name}”…": "Skapa nyckelordstagg i ”{name}”…",
|
||||
"Create the keyword “{name}”": "Skapa nyckelordet ”{name}”",
|
||||
"Create {n} Virtual Copies": "Skapa {n} virtuella kopior",
|
||||
"Creates {} stacks from {} of {scope}": "Skapar {} staplar av {} i {scope}",
|
||||
"Decoder: {reason}": "Avkodare: {reason}",
|
||||
"Delete \"{label}\"": "Radera ”{label}”",
|
||||
"Delete \"{label}\" (and the mask)": "Radera ”{label}” (och masken)",
|
||||
"Delete the effect preset “{name}”?": "Radera effektförinställningen ”{name}”?",
|
||||
"Delete the keyword “{name}”?": "Radera nyckelordet ”{name}”?",
|
||||
"Delete these {n} effect presets?": "Radera dessa {n} effektförinställningar?",
|
||||
"Delete {n} effect preset{}? This can't be undone.": "Radera {n} effektförinställning{}? Det går inte att ångra.",
|
||||
"Delete {n} Photos": "Radera {n} foton",
|
||||
"Delete “{current}”": "Radera ”{current}”",
|
||||
"Delete “{name}”?": "Radera ”{name}”?",
|
||||
"Denoising {name}: {done} of {total} tiles{}": "Brusreducerar {name}: {done} av {total} rutor{}",
|
||||
"Discard Smart Previews ({scope})": "Släng smarta förhandsgranskningar ({scope})",
|
||||
"Done ({what}): {done} photo{plural}": "Klart ({what}): {done} foto{plural}",
|
||||
"Downloads from {host}. Once it has arrived and checked out, LightCraft installs it, {after}.": "Laddas ned från {host}. När den har kommit fram och kontrollerats installerar LightCraft den, {after}.",
|
||||
"Duplicate \"{label}\"": "Duplicera ”{label}”",
|
||||
"Effect: {name}": "Effekt: {name}",
|
||||
"Example: {example}": "Exempel: {example}",
|
||||
"Exported to {path}": "Exporterade till {path}",
|
||||
"Exported {n} keyword{}": "Exporterade {n} nyckelord{}",
|
||||
"Exported {n} photo{}": "Exporterade {n} foto{}",
|
||||
"Exported {ok} of {total} photo{}": "Exporterade {ok} av {total} foto{}",
|
||||
"Exported {} effect preset{}": "Exporterade {} effektförinställning{}",
|
||||
"Exported {} point curve preset{}": "Exporterade {} punktkurvförinställning{}",
|
||||
"Exported {} preset{}": "Exporterade {} förinställning{}",
|
||||
"Exporting {} of {total}": "Exporterar {} av {total}",
|
||||
"Filter bar — {active} active filter{}": "Filterfält — {active} aktiva filter{}",
|
||||
"Filtered: {label}": "Filtrerat: {label}",
|
||||
"Focus {:.0}": "Fokus {:.0}",
|
||||
"Folder “{}” (and its subfolders)": "Mappen ”{}” (och dess undermappar)",
|
||||
"Found {n} missing photo{}; {left} still missing{unsure}": "Hittade {n} saknade foto{}; {left} saknas fortfarande{unsure}",
|
||||
"Healed {n} dust spot{}": "Retuscherade {n} dammfläck{}",
|
||||
"Import cancelled · {} photo{} added": "Importen avbröts · {} foto{} tillagda",
|
||||
"Import failed: {e}": "Importen misslyckades: {e}",
|
||||
"Import warnings ({n}):\n{warnings}": "Importvarningar ({n}):\n{warnings}",
|
||||
"Imported {e} mask effect{} (Masking ▸ Effect)": "Importerade {e} maskeffekt{} (Maskering → Effekt)",
|
||||
"Imported {name}": "Importerade {name}",
|
||||
"Imported {n} point curve preset{}": "Importerade {n} punktkurvförinställning{}",
|
||||
"Imported {n} preset{}": "Importerade {n} förinställning{}",
|
||||
"Imported {n} preset{}, {f} file{} not readable": "Importerade {n} förinställning{}, {f} fil{} kunde inte läsas",
|
||||
"Imported {profiles} profile{} (Profile browser ▸ their groups)": "Importerade {profiles} profil{} (Profilbläddrare → deras grupper)",
|
||||
"Imported {} photo{}": "Importerade {} foto{}",
|
||||
"In line for AI Denoise ({ahead} ahead)…": "I kö för AI-brusreducering ({ahead} före)…",
|
||||
"Insert at the cursor (also written {})": "Infoga vid textmarkören (skrivs även {})",
|
||||
"It is taken off {count} photo{}, with the keywords below it. Undo brings it back.": "Det tas bort från {count} foto{}, tillsammans med nyckelorden under det. Ångra återställer det.",
|
||||
"Keywords of {n} selected photos": "Nyckelord för {n} markerade foton",
|
||||
"Label Set: {name}": "Etikettuppsättning: {name}",
|
||||
"LightCraft can't decode this raw variant yet ({}). You're editing the camera's embedded JPEG preview, which already includes the camera's picture style (e.g. Monochrome) and white balance.": "LightCraft kan inte avkoda den här raw-varianten än ({}). Du redigerar kamerans inbäddade JPEG-förhandsgranskning, som redan innehåller kamerans bildstil (t.ex. Monokrom) och vitbalans.",
|
||||
"LightCraft could not open its window: {e}": "LightCraft kunde inte öppna sitt fönster: {e}",
|
||||
"LightCraft could not open its window: {e}\n\nThe log file has the details: {path}": "LightCraft kunde inte öppna sitt fönster: {e}\n\nDetaljer finns i loggfilen: {path}",
|
||||
"LightCraft stopped unexpectedly: {e}": "LightCraft avslutades oväntat: {e}",
|
||||
"LightCraft stopped unexpectedly: {e}\n\nThe log file has the details: {path}": "LightCraft avslutades oväntat: {e}\n\nDetaljer finns i loggfilen: {path}",
|
||||
"Lightroom catalog inspected: {photos} photos, {collections} collections, {missing} missing": "Lightroom-katalogen har granskats: {photos} foton, {collections} samlingar, {missing} saknas",
|
||||
"Lightroom geometry for {path} was not preserved; Guided Upright saved transform is unsupported.": "Lightroom-geometrin för {path} bevarades inte; sparad transformering med guidad Upright stöds inte.",
|
||||
"Lightroom geometry for {path} was not preserved; saved transform is ignored because Upright is Off.": "Lightroom-geometrin för {path} bevarades inte; den sparade transformeringen ignoreras eftersom Upright är av.",
|
||||
"Lightroom geometry for {path} was not preserved; saved Upright transform is unsupported.": "Lightroom-geometrin för {path} bevarades inte; sparad Upright-transformering stöds inte.",
|
||||
"Lightroom geometry was not preserved for {path}; {mode} will be recalculated.": "Lightroom-geometrin bevarades inte för {path}; {mode} beräknas om.",
|
||||
"Lightroom import complete: {imported} photos added": "Lightroom-importen är klar: {imported} foton har lagts till",
|
||||
"Lightroom import complete: {imported} photos added, {failed} failed": "Lightroom-importen är klar: {imported} foton har lagts till, {failed} misslyckades",
|
||||
"Lightroom import complete: {imported} photos added; index warning: {warning}": "Lightroom-importen är klar: {imported} foton har lagts till; indexvarning: {warning}",
|
||||
"Lightroom import failed: {e}{warning}": "Lightroom-importen misslyckades: {e}{warning}",
|
||||
"Lightroom inspection failed: {e}{warning}": "Granskningen av Lightroom misslyckades: {e}{warning}",
|
||||
"Making the denoised picture… {}%": "Skapar den brusreducerade bilden… {}%",
|
||||
"Matches: {}": "Matchar: {}",
|
||||
"Merging… {stage} {:.0}%": "Sammanfogar… {stage} {:.0}%",
|
||||
"MIT OR Apache-2.0. Fonts: {} (OFL). Icons: original.": "MIT OR Apache-2.0. Typsnitt: {} (OFL). Ikoner: original.",
|
||||
"Move {what} to Recently Deleted?": "Vill du flytta {what} till Nyligen raderade?",
|
||||
"Moved {} photo(s)": "Flyttade {} foto(n)",
|
||||
"Moved; {} photo(s) relinked": "Flyttat; {} foto(n) har länkats om",
|
||||
"Named ({named_n})": "Namngivna ({named_n})",
|
||||
"New Folder in “{name}”": "Ny mapp i ”{name}”",
|
||||
"new, inside {parent}": "ny, inuti {parent}",
|
||||
"none (CPU rendering): {why}": "ingen (CPU-rendering): {why}",
|
||||
"not added to Apple Photos: {e}": "inte tillagt i Apple Photos: {e}",
|
||||
"On {have} of {of} selected photos": "På {have} av {of} markerade foton",
|
||||
"Painting “{k}”: click photos to add or remove it · Esc stops": "Målar ”{k}”: klicka på foton för att lägga till eller ta bort det · Esc avslutar",
|
||||
"Paste into {n} photo{} — only settings that were copied are pasted": "Klistra in i {n} foto{} – endast inställningar som kopierades klistras in",
|
||||
"Preset: {name}": "Förinställning: {name}",
|
||||
"Preview only — editing the camera's embedded JPEG ({})": "Endast förhandsgranskning – du redigerar kamerans inbäddade JPEG ({})",
|
||||
"Preview only — {}": "Endast förhandsgranskning – {}",
|
||||
"Previews ready for {done} photo{plural}": "Förhandsgranskningar klara för {done} foto{plural}",
|
||||
"Profile: {}": "Profil: {}",
|
||||
"Proof Copy ({})": "Korrekturkopia ({})",
|
||||
"Proof Preview · {}": "Korrekturförhandsgranskning · {}",
|
||||
"Put inside “{parent}”": "Placera i ”{parent}”",
|
||||
"Quick Develop · {n} photos": "Snabbframkalla · {n} foton",
|
||||
"Quick Develop: {name}": "Snabbframkalla: {name}",
|
||||
"Rated {}": "Betygsatt {}",
|
||||
"Reading Lightroom catalog… {done} of {total}": "Läser Lightroom-katalogen… {done} av {total}",
|
||||
"Reading photos… {done} of {total}": "Läser foton… {done} av {total}",
|
||||
"Reading photos… {} of {}": "Läser foton… {} av {}",
|
||||
"Redo {}": "Gör om {}",
|
||||
"Remove “{name}”": "Ta bort ”{name}”",
|
||||
"Remove “{name}” and its {count} photo{} from the library?": "Vill du ta bort ”{name}” och dess {count} foto{} från biblioteket?",
|
||||
"Remove “{}” from Favorites": "Ta bort ”{}” från Favoriter",
|
||||
"Removed from {}": "Borttaget från {}",
|
||||
"Removed {what} from {name}": "Tog bort {what} från {name}",
|
||||
"Removed “{name}” from {n} photos. Edit ▸ Undo puts it back.": "Tog bort ”{name}” från {n} foton. Redigera → Ångra lägger tillbaka det.",
|
||||
"Rename {n} Photos…": "Byt namn på {n} foton…",
|
||||
"Rename “{name}”": "Byt namn på ”{name}”",
|
||||
"Renames {n} face{} across the library. The files are not changed.": "Byter namn på {n} ansikte{} i hela biblioteket. Filerna ändras inte.",
|
||||
"Renames “{from}” on {n} photo{} (keywords below it too). Use | for levels, e.g. Travel|Italy. An existing name merges the two.": "Byter namn på ”{from}” på {n} foto{} (även nyckelord under det). Använd | för nivåer, t.ex. Resor|Italien. Ett befintligt namn sammanfogar de två.",
|
||||
"Rendering on the CPU: {why}": "Renderar på processorn: {why}",
|
||||
"Replace {} with:": "Ersätt {} med:",
|
||||
"Reset {name}": "Återställ {name}",
|
||||
"Reset {} Channel": "Återställ kanalen {}",
|
||||
"Restore {}": "Återställ {}",
|
||||
"Restore {} Photo{}": "Återställ {} foto{}",
|
||||
"Restored {} photo{} from Recently Deleted": "Återställde {} foto{} från Nyligen raderade",
|
||||
"Running on the processor: {}.": "Körs på processorn: {}.",
|
||||
"Running on {}.": "Körs på {}.",
|
||||
"Saved export preset “{}”": "Exportförinställningen ”{}” har sparats",
|
||||
"Saved template {name}": "Mallen {name} har sparats",
|
||||
"Scores {scope} for focus and exposure and finds similar shots taken within seconds of each other (bursts).": "Bedömer {scope} efter fokus och exponering och hittar likartade bilder tagna inom några sekunder från varandra (serier).",
|
||||
"Show {hidden} hidden location{}": "Visa {hidden} dold plats{}",
|
||||
"Showing {n} of {}": "Visar {n} av {}",
|
||||
"Shows the model's terms, then downloads {} from {host}, installs it and starts using it. Nothing else is sent.": "Visar modellens villkor, hämtar sedan {} från {host}, installerar den och börjar använda den. Inget annat skickas.",
|
||||
"Skipped {problem}": "Hoppade över {problem}",
|
||||
"Slideshow exported: {what}": "Bildspelet har exporterats: {what}",
|
||||
"Smart album: {}": "Smart album: {}",
|
||||
"Tagged {n} photo{} from the tracklog": "Taggade {n} foto{} från spårloggen",
|
||||
"Template preview: {name}": "Förhandsgranskning av mall: {name}",
|
||||
"The SAM 3 download failed: {e}": "Hämtningen av SAM 3 misslyckades: {e}",
|
||||
"The XMP sidecars of {n} photos couldn't be written (is their folder offline?). LightCraft keeps trying.": "XMP-sidofilerna för {n} foton kunde inte skrivas (är mappen offline?). LightCraft fortsätter att försöka.",
|
||||
"the {n} selected photos": "de {n} markerade fotona",
|
||||
"the {} photos in view": "de {} fotona i vyn",
|
||||
"There is a keyword set “{name}” already": "Det finns redan en nyckelordsuppsättning ”{name}”",
|
||||
"There is a “{name}” at the top level already. Merge the two?": "Det finns redan ett ”{name}” på översta nivån. Vill du sammanfoga dem?",
|
||||
"these {count} photos": "dessa {count} foton",
|
||||
"Trained on: {provenance}": "Tränad på: {provenance}",
|
||||
"Undo {}": "Ångra {}",
|
||||
"Unknown tag{s} {} stay{} as typed (see Tags)": "Okända taggar ({}) behåll{s}{} som de skrevs (se Taggar)",
|
||||
"Update “{name}” with Current Settings": "Uppdatera ”{name}” med aktuella inställningar",
|
||||
"Updated {name}": "{name} har uppdaterats",
|
||||
"Updated “{name}”": "”{name}” har uppdaterats",
|
||||
"Version {} — a clean-room, pure-Rust photo library and raw developer.": "Version {} – ett fotobibliotek och raw-framkallare i ren Rust, utvecklat enligt clean room-metoden.",
|
||||
"Version: {}": "Version: {}",
|
||||
"Virtual copy “{name}” of {of}": "Virtuell kopia ”{name}” av {of}",
|
||||
"Working on {what} for {} photos…": "Arbetar med {what} för {} foton…",
|
||||
"XMP adjustments were not imported for {path}: {fields}.": "XMP-justeringar importerades inte för {path}: {fields}.",
|
||||
"XMP profile \"{profile}\" was not applied for {path}; colors may differ from Lightroom.": "XMP-profilen \"{profile}\" tillämpades inte för {path}; färgerna kan skilja sig från Lightroom.",
|
||||
"{:.1} MB": "{:.1} MB",
|
||||
"{count} more warnings.": "{count} varningar till.",
|
||||
"{count} smart preview{} · {:.1} MB": "{count} smarta förhandsgranskning{} · {:.1} MB",
|
||||
"{done} of {total}": "{done} av {total}",
|
||||
"{done} of {total} MB": "{done} av {total} MB",
|
||||
"{file} · {size}": "{file} · {size}",
|
||||
"{f} folders (and their subfolders)": "{f} mappar (och deras undermappar)",
|
||||
"{label} Grading": "Gradering: {label}",
|
||||
"{label} {d:+} on every selected photo": "{label} {d:+} på varje markerat foto",
|
||||
"{label} {index} of {n}": "{label} {index} av {n}",
|
||||
"{label}, {n} photos": "{label}, {n} foton",
|
||||
"{matching} of {t} photos": "{matching} av {t} foton",
|
||||
"{matching} photos": "{matching} foton",
|
||||
"{missing} originals are missing. Their catalog records are available; use Find Missing Photos to relink them.": "{missing} original saknas. Deras katalogposter finns kvar; använd Sök efter saknade foton för att länka om dem.",
|
||||
"{mode} spot {} of {}": "{mode} – punkt {} av {}",
|
||||
"{month}": "{month}",
|
||||
"{month} {year}": "{month} {year}",
|
||||
"{msg} ({failed} failed)": "{msg} ({failed} misslyckades)",
|
||||
"{name} Label": "Etiketten {name}",
|
||||
"{name} Off": "{name} av",
|
||||
"{name} On": "{name} på",
|
||||
"{name} opened for editing; it is stacked with the original": "{name} öppnades för redigering; den är staplad med originalet",
|
||||
"{name} opened in the other editor": "{name} öppnades i den andra redigeraren",
|
||||
"{name} · {terms}": "{name} · {terms}",
|
||||
"{name} — double-click to reset it": "{name} – dubbelklicka för att återställa",
|
||||
"{n} added to Apple Photos": "{n} tillagda i Apple Photos",
|
||||
"{n} added to Apple Photos album “{album}”": "{n} har lagts till i Apple Photos-albumet ”{album}”",
|
||||
"{n} change{} couldn't be written to disk: {e}\nIf you quit now, {} lost.": "{n} ändring{} kunde inte skrivas till disken: {e}\nOm du avslutar nu går {} förlorade.",
|
||||
"{n} change{} saved in memory but not written to disk: {e}\nLightCraft retries automatically; quitting now would lose {}.": "{n} ändring{} har sparats i minnet men inte skrivits till disken: {e}\nLightCraft försöker igen automatiskt. Om du avslutar nu går {} förlorade.",
|
||||
"{n} change{} saved in memory but not written to disk: {e} — LightCraft will retry": "{n} ändring{} har sparats i minnet men inte skrivits till disken: {e} – LightCraft försöker igen",
|
||||
"{n} found · {sel} selected": "{n} hittade · {sel} markerade",
|
||||
"{n} JPEG files": "{n} JPEG-filer",
|
||||
"{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "{n} lokala foto{} hoppades över: album innehåller foton från biblioteket (lägg först till i Mina foton)",
|
||||
"{n} originals opened in the other editor": "{n} original har öppnats i den andra redigeraren",
|
||||
"{n} pages": "{n} sidor",
|
||||
"{n} photos": "{n} foton",
|
||||
"{n} photos in view · {slides} slides · {time}": "{n} foton i vyn · {slides} bilder · {time}",
|
||||
"{n} photos in {} are hidden by the filters above": "{n} foton i {} döljs av filtren ovan",
|
||||
"{n} photos opened for editing; each is stacked with its original": "{n} foton har öppnats för redigering; vart och ett staplas med sitt original",
|
||||
"{n} photo{}": "{n} foto{}",
|
||||
"{n} photo{} match · updates automatically as photos change": "{n} foto{} matchar · uppdateras automatiskt när fotona ändras",
|
||||
"{n} photo{} now · updates automatically as photos change": "{n} foto{} just nu · uppdateras automatiskt när fotona ändras",
|
||||
"{n} preset{}": "{n} förinställning{}",
|
||||
"{n} raws can now be developed from their raw data": "{n} raw-filer kan nu framkallas från sina rådata",
|
||||
"{n} similar photo{} · View ▸ Clear Filters to see all": "{n} likartade foto{} · Visa → Rensa filter för att se alla",
|
||||
"{n} tasks are still running: {names}. Quitting stops them.": "{n} uppgifter körs fortfarande: {names}. Om du avslutar stoppas de.",
|
||||
"{n} {noun}": "{n} {noun}",
|
||||
"{pct} %": "{pct} %",
|
||||
"{photos} catalog records processed; {collections} collections.": "{photos} katalogposter bearbetade; {collections} samlingar.",
|
||||
"{pid} (missing)": "{pid} (saknas)",
|
||||
"{sel_n} selected · {counted}": "{sel_n} markerade · {counted}",
|
||||
"{size} GB": "{size} GB",
|
||||
"{stage}… {:.0}%": "{stage}… {:.0} %",
|
||||
"{s} s of AV1 video": "{s} s AV1-video",
|
||||
"{verb} {n} Photo{}": "{verb} {n} foto{}",
|
||||
"{weekday}, {day}": "{weekday} {day}",
|
||||
"{weekday}, {day} {month} {year}": "{weekday} {day} {month} {year}",
|
||||
"{what} merge added": "{what}-sammanfogning tillagd",
|
||||
"{what} merge added at {mp}, the largest a panorama can be (its full size is {full})": "{what}-sammanfogning tillagd med {mp}, den största storlek ett panorama kan ha (full storlek är {full})",
|
||||
"{what} merge added at {mp}: its full size, {full}, needs more memory than this computer has": "{what}-sammanfogning tillagd med {mp}: full storlek, {full}, kräver mer minne än den här datorn har",
|
||||
"{what} merge cancelled": "{what}-sammanfogning avbruten",
|
||||
"{what} merge failed: {e}": "{what}-sammanfogning misslyckades: {e}",
|
||||
"{year}": "{year}",
|
||||
"{{date:…}} directives: {}": "{{date:…}}-direktiv: {}",
|
||||
"{} and higher": "{} och högre",
|
||||
"{} contributors · {} commits": "{} bidragsgivare · {} commits",
|
||||
"{} failed": "{} misslyckades",
|
||||
"{} files": "{} filer",
|
||||
"{} files and {f} folder{}": "{} filer och {f} mapp{}",
|
||||
"{} item{}": "{} objekt{}",
|
||||
"{} KB": "{} kB",
|
||||
"{} label (click more labels to show any of them)": "Etiketten {} (klicka på fler etiketter för att visa foton med någon av dem)",
|
||||
"{} MB": "{} MB",
|
||||
"{} of 4 guides — drag along lines that should be vertical or horizontal.": "{} av 4 stödlinjer – dra längs linjer som ska vara vertikala eller horisontella.",
|
||||
"{} of {} from {host}": "{} av {} från {host}",
|
||||
"{} photos": "{} foton",
|
||||
"{} photos · exposures {} EV": "{} foton · exponeringar {} EV",
|
||||
"{} photos · {} · {:.0}° × {:.0}°": "{} foton · {} · {:.0}° × {:.0}°",
|
||||
"{} photo{} not readable": "{} foto{} kunde inte läsas",
|
||||
"{} sample{}": "{} sample{}",
|
||||
"{} sec": "{} s",
|
||||
"{} spot(s) on this photo": "{} fläck(ar) på det här fotot",
|
||||
"{} · {}. Kept in the library's “denoise” folder; the oldest ones that no photo uses go first when the limit is reached.": "{} · {}. Sparas i bibliotekets mapp ”denoise”; de äldsta som inget foto använder tas bort först när gränsen nås.",
|
||||
"{} — show their photos": "{} – visa deras foton",
|
||||
"· {dups} already in the library": "· {dups} finns redan i biblioteket",
|
||||
"· {in_source} identical copies": "· {in_source} identiska kopior",
|
||||
"· {n} photo{}": "· {n} foto{}",
|
||||
"· {trashed} in Recently Deleted": "· {trashed} i Nyligen raderade",
|
||||
"“{parent}” has a “{name}” already. Merge the two?": "”{parent}” har redan en ”{name}”. Vill du sammanfoga dem?",
|
||||
"“{to}” is already a person. Combining them makes one person; Undo separates them again.": "”{to}” är redan en person. Om du kombinerar dem blir de en person; Ångra skiljer dem åt igen.",
|
||||
"• {assumption}": "• {assumption}",
|
||||
"… and {more} more": "… och {more} till",
|
||||
"…and {more} more": "…och {more} till"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -128,6 +128,7 @@ language_table! {
|
||||
Uk, "uk", "Українська", "Cyrl", include_str!("../locales/uk.json");
|
||||
Pl, "pl", "Polski", "Latn", include_str!("../locales/pl.json");
|
||||
Cs, "cs", "Čeština", "Latn", include_str!("../locales/cs.json");
|
||||
Sv, "sv", "Svenska", "Latn", include_str!("../locales/sv.json");
|
||||
}
|
||||
|
||||
// The settings file stores the BCP-47 code (`"zh-hans"`), never the Rust variant name, so a
|
||||
@@ -516,6 +517,46 @@ mod tests {
|
||||
set_language(Locale::En);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swedish_switches_persists_and_formats_without_changing_user_values() {
|
||||
use crate::control::{ControlRequest, Outcome};
|
||||
let mut app = crate::LightcraftApp::new(lightcraft_engine::Session::with_demo(), Default::default());
|
||||
app.run("app.language.swedish", serde_json::json!({})).unwrap();
|
||||
assert_eq!(app.ui.language, Locale::Sv);
|
||||
assert_eq!(Locale::Sv.name(), "Svenska");
|
||||
assert_eq!(Locale::Sv.script(), "Latn");
|
||||
assert_eq!(crate::menubar::checked(&app, "app.language.swedish"), Some(true));
|
||||
assert_eq!(tr("File"), "Fil");
|
||||
assert_eq!(tr("Develop"), "Framkalla");
|
||||
assert_eq!(tr("Exposure"), "Exponering");
|
||||
assert_eq!(date_group_label("2026", false), "2026");
|
||||
assert!(date_group_label("2026-09-20", false).starts_with("Söndag 20 "), "{}", date_group_label("2026-09-20", false));
|
||||
assert_eq!(builtin_label("Warm Glow", false), "Warm Glow");
|
||||
assert_eq!(tr("photo-{title}.jpg"), "photo-{title}.jpg");
|
||||
let saved = serde_json::to_string(&app.ui).unwrap();
|
||||
assert!(saved.contains("\"sv\""), "{saved}");
|
||||
assert_eq!(serde_json::from_str::<crate::state::UiState>(&saved).unwrap().language, Locale::Sv);
|
||||
let ctx = egui::Context::default();
|
||||
for tag in ["sv", "sv-SE", "sv_SE.UTF-8", "sv-FI"] {
|
||||
assert_eq!(Locale::parse_tag(tag), Some(Locale::Sv), "{tag}");
|
||||
let (request, _) = ControlRequest::new("ui.set", serde_json::json!({"language": tag}));
|
||||
let Outcome::Done(reply) = crate::control::handle(&mut app, &ctx, &request) else { panic!("expected reply") };
|
||||
assert_eq!(reply["ok"], true);
|
||||
assert_eq!(language(), Locale::Sv);
|
||||
}
|
||||
let text = painted_text(&ctx, &mut app, Locale::Sv);
|
||||
assert!(text.contains("Fil") && text.contains("Exponering"), "{text}");
|
||||
ctx.fonts_mut(|fonts| {
|
||||
for family in [egui::FontFamily::Proportional, egui::FontFamily::Name(crate::theme::FONT_SEMIBOLD.into())] {
|
||||
let font = egui::FontId::new(13.0, family);
|
||||
for ch in "åäöÅÄÖé”’".chars() {
|
||||
assert!(fonts.has_glyph(&font, ch), "missing Swedish glyph {ch}");
|
||||
}
|
||||
}
|
||||
});
|
||||
set_language(Locale::En);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_language_has_a_catalog_covering_the_source() {
|
||||
assert!(crate::i18n::Locale::En.catalog().is_empty(), "the source language needs no catalog");
|
||||
@@ -753,6 +794,7 @@ mod tests {
|
||||
("app.language.ukrainian", Locale::Uk),
|
||||
("app.language.polish", Locale::Pl),
|
||||
("app.language.czech", Locale::Cs),
|
||||
("app.language.swedish", Locale::Sv),
|
||||
];
|
||||
// One command per language, and every command reachable from the menu table.
|
||||
assert_eq!(commands.len(), Locale::ALL.len());
|
||||
|
||||
@@ -26,6 +26,7 @@ pub const LANGUAGE_COMMANDS: &[UiCommand] = &[
|
||||
("app.language.ukrainian", crate::i18n::Locale::Uk.name(), None, "Edit>Language"),
|
||||
("app.language.polish", crate::i18n::Locale::Pl.name(), None, "Edit>Language"),
|
||||
("app.language.czech", crate::i18n::Locale::Cs.name(), None, "Edit>Language"),
|
||||
("app.language.swedish", crate::i18n::Locale::Sv.name(), None, "Edit>Language"),
|
||||
];
|
||||
|
||||
/// Every UI command: the languages, then everything else. `xtask parity` reads both tables from
|
||||
@@ -50,6 +51,7 @@ pub fn language_from_command(id: &str) -> Option<crate::i18n::Locale> {
|
||||
"app.language.ukrainian" => Some(crate::i18n::Locale::Uk),
|
||||
"app.language.polish" => Some(crate::i18n::Locale::Pl),
|
||||
"app.language.czech" => Some(crate::i18n::Locale::Cs),
|
||||
"app.language.swedish" => Some(crate::i18n::Locale::Sv),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,13 +621,13 @@ mod tests {
|
||||
"Export Keywords…",
|
||||
];
|
||||
let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("locales");
|
||||
for code in ["de", "es", "fr", "pt-br", "ru", "uk", "ja", "zh-hans", "zh-hant", "cs", "pl"] {
|
||||
for code in ["de", "es", "fr", "pt-br", "ru", "uk", "ja", "zh-hans", "zh-hant", "cs", "pl", "sv"] {
|
||||
let text = std::fs::read_to_string(dir.join(format!("{code}.json"))).unwrap();
|
||||
let catalog: std::collections::HashMap<String, String> = serde_json::from_str(&text).unwrap();
|
||||
for label in labels {
|
||||
assert!(catalog.contains_key(label), "{code}: “{label}”");
|
||||
}
|
||||
}
|
||||
assert_eq!(Locale::ALL.len(), 12, "a language added: list its file above");
|
||||
assert_eq!(Locale::ALL.len(), 13, "a language added: list its file above");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The interface ships in the language it is written in (English) plus every language in the table in
|
||||
`crates/ui-egui/src/i18n.rs`. Today that is English, Simplified Chinese (`zh-hans`), Traditional
|
||||
Chinese (`zh-hant`, Taiwan), Japanese (`ja`), Brazilian Portuguese (`pt-br`), Spanish (`es`), German (`de`), Russian (`ru`), French (`fr`), Ukrainian (`uk`) and Czech (`cs`). This file is the reference for **adding or maintaining a language**; the per-language notes
|
||||
Chinese (`zh-hant`, Taiwan), Japanese (`ja`), Brazilian Portuguese (`pt-br`), Spanish (`es`), German (`de`), Russian (`ru`), French (`fr`), Ukrainian (`uk`), Czech (`cs`) and Swedish (`sv`). This file is the reference for **adding or maintaining a language**; the per-language notes
|
||||
are in [`localization-zh-hans.md`](localization-zh-hans.md), [`localization-zh-hant.md`](localization-zh-hant.md),
|
||||
[`localization-ja.md`](localization-ja.md), [`localization-pt-br.md`](localization-pt-br.md), [`localization-es.md`](localization-es.md),
|
||||
[`localization-de.md`](localization-de.md), [`localization-ru.md`](localization-ru.md) and
|
||||
|
||||
Reference in New Issue
Block a user