diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index d5fac75..f6fec9c 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -60,3 +60,4 @@ Generated-in-code assets are original and have no file to list: | `crates/ui-egui/src/i18n/de.tsv` | the CADCraft contributors | Original German translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied | | `crates/ui-egui/src/i18n/es.tsv` | @PedroGuille | Original Spanish translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied | | `crates/ui-egui/src/i18n/pt_br.tsv` | @WladmirJunior | Original Brazilian Portuguese translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied | +| `crates/ui-egui/src/i18n/cs.tsv` | @Losminek (AI-assisted) | Original Czech translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied | diff --git a/README.md b/README.md index f1bfa8c..68252f3 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ numbers): | Layouts & plotting | Paper-space layouts, viewports (scale, lock, per-viewport layer freeze), MSPACE/PSPACE through viewports, page setups, PLOT and EXPORTPDF | | Parametric | Geometric and dimensional constraints, AUTOCONSTRAIN, PARAMETERS with expressions, conflict detection; constraints re-solve after every edit | | Grips | Hot grips with Space to cycle Stretch, Move, Rotate, Scale and Mirror | -| Interface languages | English, Ukrainian (Українська) and German (Deutsch), live switching and a remembered Auto/system-language choice; [details](docs/localization.md) | +| Interface languages | English, Ukrainian (Українська), Brazilian Portuguese (Português (Brasil)), German (Deutsch), Spanish (Español) and Czech (Čeština), live switching and a remembered Auto/system-language choice; [details](docs/localization.md) | | Automation | MCP server, JSON control channel, `cadcraft-cli` (info, convert, run, commands, mcp) | ## Quick start diff --git a/apps/cadcraft/src/native_menu.rs b/apps/cadcraft/src/native_menu.rs index 118abfc..8d41f83 100644 --- a/apps/cadcraft/src/native_menu.rs +++ b/apps/cadcraft/src/native_menu.rs @@ -57,7 +57,7 @@ impl NativeMenu { items.insert("cc-settings".into(), ("options".into(), "Settings...".into(), settings)); let _ = menu.append(&app_menu); for (title, entries) in menus::tree(app) { - let sub = Submenu::new(i18n::tr(language, &title), true); + let sub = Submenu::new(i18n::tr_menu(language, &title), true); build(&sub, &entries, &mut items, &mut submenus, &mut counter, language); let _ = menu.append(&sub); submenus.push((title, sub)); @@ -87,7 +87,7 @@ impl NativeMenu { item.set_text(i18n::tr(language, label)); } for (label, submenu) in &self.submenus { - submenu.set_text(i18n::tr(language, label)); + submenu.set_text(i18n::tr_menu(language, label)); } } let now = cadcraft_ui_egui::now_ms(); @@ -113,7 +113,7 @@ fn build( for e in entries { match e { Entry::Sub { label, children } => { - let sub = Submenu::new(i18n::tr(language, label), true); + let sub = Submenu::new(i18n::tr_menu(language, label), true); build(&sub, children, items, submenus, counter, language); let _ = parent.append(&sub); submenus.push((label.clone(), sub)); diff --git a/contributors/people.toml b/contributors/people.toml index e627c0f..aefa0ff 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -45,3 +45,6 @@ sync_github_name = true [people.WladmirJunior] real_name = "Wladmir Júnior" sync_github_name = true + +[people.Losminek] +sync_github_name = true diff --git a/crates/ui-egui/src/chrome.rs b/crates/ui-egui/src/chrome.rs index a11f37d..062f8ef 100644 --- a/crates/ui-egui/src/chrome.rs +++ b/crates/ui-egui/src/chrome.rs @@ -165,7 +165,7 @@ pub fn title_and_toolbar(app: &mut CadApp, ui: &mut egui::Ui) { } } }); - response.on_hover_text("More toolbar commands"); + response.on_hover_text(crate::tl!("More toolbar commands")); } if let Some(c) = clicked { app.start(c); diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv new file mode 100644 index 0000000..d896a9d --- /dev/null +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -0,0 +1,1207 @@ +# CADCraft Czech interface catalog — original translations by @Losminek (AI-assisted). +# SPDX-License-Identifier: MIT OR Apache-2.0 +# Written from the meaning of CADCraft English strings; no proprietary translations copied. +# UTF-8: contextEnglish sourceCzech translation. +# @plural = one|few|other forms for integer counts. + Apply Použít + Attach DWG... Připojit DWG... + Bind Svázat + Detach Odpojit + Loaded Načteno + Make it a block of this drawing, keeping its layer names Převést na blok tohoto výkresu a zachovat názvy hladin + Make it a block of this drawing; its layers become NAME$0$LAYER Převést na blok tohoto výkresu; názvy hladin budou NAME$0$LAYER + No external references are attached. Nejsou připojeny žádné externí reference. + Not Found Nenalezeno + Not loaded Nenačteno + Open Otevřít + Overlay Překrytí + Reference Manager Správce referencí + Reference Name Název reference + References: {n} Reference: {n} + Reload Znovu načíst + Reload All Znovu načíst vše + Saved Path Uložená cesta + Unload Uvolnit + Unloaded Uvolněno + Unreferenced Bez odkazu + Unresolved Nevyřešeno + Cancel Zrušit + OK OK + or [ nebo [ + % of all commits % všech commitů + * Wildcard Match * Shoda se zástupnými znaky + *VARIES* *RŮZNÉ* + + | Top | 2D Wireframe + | Shora | 2D drátový model + +Bin +Bin + +LOC +LOC + 1 Viewport 1 výřez + 2 Points 2 body + 2 Viewports 2 výřezy + 2D Solid 2D plocha + 3 Points 3 body + 3 Viewports 3 výřezy + 3D Face 3D plocha + 3D Operations 3D operace + 3D Polyline 3D křivka + 4 Viewports 4 výřezy + < Less than < Menší než + <> Not Equal <> Nerovná se + = Equals = Rovná se + > Greater than > Větší než + A variable name starts with a letter and has only letters, digits and _ Název proměnné začíná písmenem a obsahuje pouze písmena, číslice a _ + About O aplikaci + About CADCraft O aplikaci CADCraft + Absolute Absolutní + Add Leader Přidat odkaz + Additional angles Další úhly + Align Srovnat + Align Text Zarovnat text + Aligned Zarovnaná + All Vše + All Annotation Objects Všechny objekty popisů + All Used Layers Všechny použité hladiny + All files Všechny soubory + Angle Úhel + Angular Úhlová + Annotation Visibility Viditelnost popisů + Annotation scale Měřítko popisů + Apparent Intersection Zdánlivý průsečík + Append to current selection set Přidat k aktuální výběrové množině + Apply to: Použít na: + Apply true color Použít skutečnou barvu + Arc Oblouk + Arc Length Délka oblouku + Area Plocha + Arrange Panel Uspořádat panel + Array Pole + Attach Připojit + Attribute Atribut + Attribute Definition Definice atributu + Attribute Display Zobrazení atributů + Audit Prověřit + Auto (system language) Automaticky (jazyk systému) + Auto Constrain Automaticky vytvořit vazby + AutoConstrain Automatické vazby + Axis, End Osa, konec + Base Základní bod + Baseline Od základny + Batch Publish Dávkově publikovat + Binary assets added Přidané binární soubory + Binary assets removed Odebrané binární soubory + Bind... Svázat... + Blend Spojit křivky + Block Blok + Block Attribute Manager... Správce atributů bloků... + Block Editor Editor bloků + Block Reference Reference bloku + Block... Blok... + Blocks Bloky + Blue Modrá + Bold Tučné + Boolean Booleovská + Boundary Hranice + Boundary... Hranice... + Box Kvádr + Break Přerušit + Break At Point Přerušit v bodě + Bring Above Objects Přenést nad objekty + Bring Annotations to Front Přenést popisy dopředu + Bring to Front Přenést dopředu + Bulleted list Seznam s odrážkami + ByBlock Dle bloku + ByColor Dle barvy + ByLayer Dle hladiny + CADCraft Help Nápověda CADCraft + Cancel Zrušit + Cartesian (x, y) Kartézské (x, y) + Center Střed + Center Line Osa + Center Mark Středová značka + Center X Střed X + Center Y Střed Y + Center Z Střed Z + Center, Diameter Střed, průměr + Center, Radius Střed, poloměr + Center, Start, Angle Střed, počátek, úhel + Center, Start, End Střed, počátek, konec + Center, Start, Length Střed, počátek, délka + Chamfer Zkosit + Change Space Změnit prostor + Change to Current Layer Převést do aktuální hladiny + Changed: {n} Změněno: {n} + Circle Kružnice + Circumference Obvod + Clear History Vymazat historii + Clear Vymazat + Clip Oříznout hranicí + Clip Viewport Oříznout výřez + Clipboard Schránka + Close Zavřít + Close All Zavřít vše + Close All Other Drawings Zavřít všechny ostatní výkresy + Closed Uzavřeno + Close Comparison Zavřít porovnání + Coincident Totožnost + Collapse Tool Sets Sbalit sady nástrojů + Collinear Kolinearita + Color Barva + Color 8 Barva 8 + Color 9 Barva 9 + Color Index Index barvy + Color... Barva... + Command Aliases Aliasy příkazů + Command History Historie příkazů + Clear Command History Vymazat historii příkazů + Command Line Příkazový řádek + Command Line History Lines Počet řádků historie příkazového řádku + Command Reference Přehled příkazů + Commits Commity + Company Společnost + Compare Drawings... Porovnat výkresy... + Computer-aided design and drafting: an open-source, clean-room CAD application written in pure Rust. Počítačem podporované navrhování a kreslení: CAD aplikace s otevřeným zdrojovým kódem, napsaná nezávisle v čistém Rustu. + Concentric Soustřednost + Cone Kužel + Constraint Bars Lišty vazeb + Constraint Settings Nastavení vazeb + Construction Line Přímka + Contents Obsah + Continue Pokračovat + Contributors Přispěvatelé + Control Vertices Řídicí vrcholy + Convert Převést + Copy Kopírovat + Copy Full File Path Kopírovat úplnou cestu k souboru + Copy History Kopírovat historii + Copy Layout Kopírovat rozvržení + Copy Nested Objects Kopírovat vnořené objekty + Copy Selection Kopírovat výběr + Copy with Base Point Kopírovat se základním bodem + Count Počet + Count List Seznam počtů + Count Table Tabulka počtů + Create Block Vytvořit blok + Creates a user parameter Vytvoří uživatelský parametr + Ctrl+Enter to finish Ctrl+Enter pro dokončení + Current layer Aktuální hladina + Current selection Aktuální výběr + Current: {color} Aktuální: {color} + Cut Vyjmout + Cyan Azurová + Cylinder Válec + DWG DWG + DWG Reference... Reference DWG... + DXF DXF + Dark Tmavé + Data Extraction... Extrahovat data... + Default Výchozí + Data Link... Datové propojení... + Default Save Format Výchozí formát ukládání + Default Save Version Výchozí verze ukládání + Define Attributes Definovat atributy + Define Attributes... Definovat atributy... + Defined width Definovaná šířka + Degree Stupeň + Degrees of Freedom Stupně volnosti + Degrees of freedom: {n} Stupně volnosti: {n} + Delete Odstranit + Delete Column Odstranit sloupec + Delete Constraints Odstranit vazby + Delete Dimension Style Odstranit kótovací styl + Delete Duplicate Objects Odstranit duplicitní objekty + Delete Layer Odstranit hladinu + Delete Layer State Odstranit stav hladin + Delete Layout Odstranit rozvržení + Delete Row Odstranit řádek + Delete Text Style Odstranit styl textu + Delta X Rozdíl X + Delta Y Rozdíl Y + Description Popis + Deselect All Zrušit celý výběr + Diameter Průměr + Dim style Kótovací styl + Dimension Break Přerušení kóty + Dimension Edit Upravit kótu + Dimension Kóta + Dimension Objects Only Pouze objekty kót + Dimension Space Rozestup kót + Dimension Style Override Přepsat kótovací styl + Dimension Style... Kótovací styl... + Dimension Text Edit Upravit text kóty + Dimension style Styl kótování + Dimensional Constraint Rozměrová vazba + Dimensional Constraint Parameters Parametry rozměrových vazeb + Dimensional Constraints Rozměrové vazby + Disassociate Dimensions Zrušit asociativitu kót + Display name Zobrazované jméno + Distance Vzdálenost + Divide Dělit + Do not plot (click: plot) Netisknout (kliknutím: tisknout) + Donut Prstenec + Double-click to edit the description Dvojitým kliknutím upravíte popis + Down Dolů + Drafting Kreslení + Drafting Settings Nastavení kreslení + Drafting Settings... Nastavení kreslení... + Draw Kreslit + Draw Order Pořadí kreslení + Drawing (DWG) Výkres (DWG) + Drawing (DXF) Výkres (DXF) + Drawing Limits Meze výkresu + Drawing Template (DWT) Šablona výkresu (DWT) + Drawing Utilities Nástroje výkresu + Drawings (DWG, DXF) Výkresy (DWG, DXF) + Dynamic Dynamická + Dynamic Dimensions Dynamické kóty + Dynamic Input Dynamické zadávání + Dynamic Input (F12) Dynamické zadávání (F12) + E V + Edit Úpravy + Edit Attributes... Upravit atributy... + Edit Text... Upravit text... + Edit Table Cell Upravit buňku tabulky + Elevation Výška zdvihu + Ellipse Elipsa + Elliptical Arc Eliptický oblouk + Enable Dynamic Input (F12) Zapnout dynamické zadávání (F12) + End Object Isolation Ukončit izolaci objektů + End Width Koncová šířka + End X Konec X + End Y Konec Y + End angle Koncový úhel + Endpoint Koncový bod + Enter Enter + Enter Top, Zero or Bottom. Zadejte Top, Zero nebo Bottom. + Enter a fit data option Zadejte možnost pro prokládací body + Enter a pattern name Zadejte název vzoru + Enter a vertex editing option Zadejte možnost úpravy vrcholů + Enter an option Zadejte možnost + Enter angle of xline Zadejte úhel přímky + Enter angle of xline (0) or Zadejte úhel přímky (0) nebo + Enter area of rectangle in current units Zadejte plochu obdélníku v aktuálních jednotkách + Enter attribute prompt Zadejte výzvu atributu + Enter attribute tag name Zadejte označení atributu + Enter attribute value Zadejte hodnotu atributu + Enter block name Zadejte název bloku + Enter constraint type Zadejte typ vazby + Enter continuity Zadejte spojitost + Enter default attribute value Zadejte výchozí hodnotu atributu + Enter degree of spline Zadejte stupeň spline + Enter delta angle Zadejte změnu úhlu + Enter delta length or Zadejte změnu délky nebo + Enter dimension text Zadejte text kóty + Enter dimension text (<> = measurement) Zadejte text kóty (<> = naměřená hodnota) + Enter dimension value or [name=expression] Zadejte hodnotu kóty nebo [name=expression] + Enter dimension variable name to override Zadejte název kótovací proměnné k přepsání + Enter justification type Zadejte typ zarovnání + Enter leader text Zadejte text odkazu + Enter mline scale Zadejte měřítko multičáry + Enter mode Zadejte režim + Enter name of block to insert Zadejte název bloku k vložení + Enter new text Zadejte nový text + Enter next point Zadejte další bod + Enter number of columns Zadejte počet sloupců + Enter number of data rows Zadejte počet datových řádků + Enter number of items Zadejte počet prvků + Enter number of items along path Zadejte počet prvků podél trajektorie + Enter number of sides Zadejte počet stran + Enter number of turns Zadejte počet závitů + Enter percentage length Zadejte délku v procentech + Enter rectangle length Zadejte délku obdélníku + Enter rectangle width Zadejte šířku obdélníku + Enter scale factor Zadejte faktor měřítka + Enter text Zadejte text + Enter text (use \P for new paragraphs) Zadejte text (\P vytvoří nový odstavec) + Enter the number of segments Zadejte počet segmentů + Enter twist direction of helix Zadejte směr vinutí šroubovice + Entire drawing Celý výkres + Equal Shodnost + Erase Vymazat objekty + Evaluate Vyhodnotit + Exclude from new selection set Vyloučit z nové výběrové množiny + Explode Rozložit + Export Exportovat + Export Table Exportovat tabulku + Export to PDF... Exportovat do PDF... + Expression Výraz + Extend Prodloužit + Extension Prodloužení + Extents Rozsah + External Reference Externí reference + External References Externí reference výkresu + Extrude Vysunout + File Soubor + File Tab Karta souboru + Fillet Zaoblit + Filter Filtr + Filters Filtry + Find and Replace Najít a nahradit + Find... Najít... + First První + First commit První commit + Fit Points Prokládací body + Fix Pevná vazba + Flatten Objects Převést objekty do roviny + Format Formát + Freehand Od ruky + Freeze Zmrazit + Freeze Layer Zmrazit hladinu + Freeze in new viewports Zmrazit v nových výřezech + Freeze/Thaw Zmrazit/Rozmrazit + Freeze/Thaw in all viewports Zmrazit/Rozmrazit ve všech výřezech + Freeze/Thaw in the current viewport Zmrazit/Rozmrazit v aktuálním výřezu + From Od + From Template... Ze šablony... + General Obecné + Geometric Center Geometrický střed + Geometric Constraint Geometrická vazba + Geometric Constraints Geometrické vazby + Geometry Geometrie + Get from the Drawing Převzít z výkresu + Get Variable Získat proměnnou + Get View Získat pohled + Global Globální + Global width Celková šířka + Grab bag Přehled přispěvatelů + Gradient Přechod + Gradient... Přechod... + Green Zelená + Grid (F7) Rastr (F7) + Grid Display Zobrazení rastru + Grid On (F7) Zapnout rastr (F7) + Grid snap Uchopení k rastru + Grid spacing Rozteč rastru + Grip Edit Upravit pomocí uzlů + Grip Mirror Zrcadlit pomocí uzlů + Grip Option Možnost uzlu + Grip Rotate Otočit pomocí uzlů + Grip Scale Měřítko pomocí uzlů + Grip Stretch Protáhnout pomocí uzlů + Group Skupina + Group Edit Upravit skupinu + Group Options Možnosti skupiny + Group Selection Výběr skupin + Hatch Šrafy + Hatch Edit Upravit šrafy + Hatch Patterns Vzory šraf + Hatch... Šrafy... + Height Výška + Height: {height} Výška: {height} + Helix Šroubovice + Help Nápověda + Hide All Skrýt vše + Hide All Constraint Bars Skrýt všechny lišty vazeb + Hide All Dynamic Dimensions Skrýt všechny dynamické kóty + Hide Layer List Skrýt seznam hladin + Hide Objects Skrýt objekty + Hide Palettes Skrýt palety + History Historie + Home Domů + Horizontal Vodorovná + HorizontalDistance Vodorovná vzdálenost + How to apply: Způsob použití: + ID Point Souřadnice bodu + Import Importovat + In Přiblížit pohled + In-window Menu Bar Nabídka v okně + Include in new selection set Zahrnout do nové výběrové množiny + Increment angle Přírůstek úhlu + Index Color Indexovaná barva + Index color: {index} Indexovaná barva: {index} + Infer Constraints Odvozovat vazby + Inquiry Dotazy + Insert Vložit + Insert Block Vložit blok + Insert Column Vložit sloupec + Insert Row Vložit řádek + Insert tab Vložit tabulátor + Insert this block Vložit tento blok + Insert Table Formula Vložit vzorec tabulky + Insertion Bod vložení + Insertion X Vložení X + Insertion Y Vložení Y + Insertion Z Vložení Z + Inspect Constraints Prohlédnout vazby + Inspect Drawing Prohlédnout výkres + Inspection Kontrolní kóta + Interface Language Jazyk rozhraní + Interface Theme Motiv rozhraní + Intersect Průnik + Intersection Průsečík + Isolate Izolovat + Isolate Layer Izolovat hladinu + Isolate Objects Izolovat objekty + Isometric Drafting Izometrické kreslení + Jogged Zalomená + Jogged Linear Zalomená lineární + Join Spojit + Join the ArtCraft Discord… Připojit se na Discord ArtCraft… + Join us on Discord Připojte se k nám na Discordu + Isometric Plane Izometrická rovina + Isometric snap Izometrické uchopení + Language Jazyk + Last Poslední + Last commit Poslední commit + Layer Hladina + Layer Delete Odstranění hladiny + Layer Match Převzetí hladiny + Layer Merge Sloučení hladin + Layer Off Vypnutí hladiny + Layer Properties Vlastnosti hladiny + Layer Properties Manager Správce vlastností hladin + Layer Properties Manager — current viewport Správce vlastností hladin — aktuální výřez + Layer State Stav hladin + Layer States Manager... Správce stavů hladin... + Layer Tools Nástroje hladin + Layer contains objects (double-click to make current) Hladina obsahuje objekty (dvojitým kliknutím ji nastavíte jako aktuální) + Layer is empty (double-click to make current) Hladina je prázdná (dvojitým kliknutím ji nastavíte jako aktuální) + Layers Hladiny + Layers Palette Paleta hladin + Hide Palette Skrýt paletu + Layers displayed: {shown} of {total}. Current layer: {layer} Zobrazené hladiny: {shown} z {total}. Aktuální hladina: {layer} + Layout Rozvržení + Layout list Seznam rozvržení + Leader Odkaz + Leaders Only Pouze odkazy + Left Vlevo + Length Délka + Length X Délka X + Length Y Délka Y + Lengthen Změnit délku + Light Světlé + Line Úsečka + Line delta Rozdíl počtu řádků + Linear Lineární + Lines +/− Řádky +/− + Lines added Přidané řádky + Lines deleted Odstraněné řádky + Lines of Command History Řádky historie příkazů + Linetype Typ čáry + Linetype Scale Měřítko typu čáry + Linetype scale Měřítko čar + Ltscale Faktor typu čáry + Linetype... Typ čáry... + Lineweight Tloušťka čáry + Lineweight... Tloušťka čáry... + List Výpis + List Blocks Vypsat bloky + List Dimension Styles Vypsat kótovací styly + List Groups Vypsat skupiny + List Layer States Vypsat stavy hladin + List Layouts Vypsat rozvržení + List System Variables Vypsat systémové proměnné + List Text Styles Vypsat styly textu + Load all Načíst vše + Load... Načíst... + Loaded linetypes Načtené typy čar + Lock Zamknout + Lock Layer Zamknout hladinu + Lock viewport Zamknout výřez + Lock/Unlock Zamknout/Odemknout + Loft Šablonovat + MIT OR Apache-2.0. Not affiliated with Autodesk, Inc. MIT OR Apache-2.0. Bez spojení se společností Autodesk, Inc. + MODEL MODEL + MText Víceřádkový text + Magenta Purpurová + Major line every Hlavní čára po každých + Make Current Nastavit jako aktuální + Make Object's Layer Current Nastavit hladinu objektu jako aktuální + Make... Vytvořit... + Match Layer Převzít hladinu + Match Properties Převzít vlastnosti + Measure Rozdělit podle délky + Measure Distance Změřit vzdálenost + Measure Geometry Změřit geometrii + Merge Cells Sloučit buňky + Merged PRs Sloučené PR + Mid Between 2 Points Střed mezi 2 body + Midpoint Polovina + Mirror Zrcadlit + Model Model + Model Space (in viewport) Modelový prostor (ve výřezu) + Modeling Modelování + Models Modely + Modify Upravit + Move Posunout + Multileader Multiodkaz + Multileader Style... Styl multiodkazu... + Multileader style Styl multiodkazů + Multiline Multičára + Multiline Text Víceřádkový textový objekt + Multiline Text... Víceřádkový text... + Multiple Více + Multiple Point Více bodů + My Moje + My properties: not available yet Moje vlastnosti: zatím nejsou k dispozici + N S + Name Název + Name (A–Z) Název (A–Z) + Named Views... Pojmenované pohledy... + Nearest Nejbližší + New Nový + New (metric) Nový (metrický) + New Drawing Nový výkres + New Drawing (⌘N) Nový výkres (⌘N) + New Drawing... Nový výkres... + New Layer Nová hladina + New Layout Nové rozvržení + New VP Freeze Zmrazení v nových výřezech + New Viewports... Nové výřezy... + New from Template... Nový ze šablony... + New layout Nové rozvržení výkresu + New state name Název nového stavu + Next Change Další změna + No Ne + No blocks defined in this drawing. V tomto výkresu nejsou definovány žádné bloky. + No contributor data was built into this copy. Tato kopie neobsahuje údaje o přispěvatelích. + No model credits were built into this copy. Tato kopie neobsahuje kredity modelů. + No saved layer states Žádné uložené stavy hladin + No selection Žádný výběr + Node Bod + None Žádné + Not available Není k dispozici + Not available yet Zatím není k dispozici + Numbered list Číslovaný seznam + OK OK + Object Objekt + Object Snap Uchopení objektu + Object Snap (F3) Uchopení objektu (F3) + Object Snap On (F3) Zapnout uchopení objektu (F3) + Object Snap Tracking Trasování uchopení objektu + Object Snap Tracking (F11) Trasování uchopení objektu (F11) + Object Snap Tracking Settings Nastavení trasování uchopení objektu + Object type: Typ objektu: + Oblique Šikmá + Off Vypnuto + Offset Ekvidistanta + On Zapnuto + On/Off Zapnout/Vypnout + One of the Crafting Apps by the ArtCraft team and community. Jedna z aplikací Crafting Apps od týmu ArtCraft a komunity. + Only in this drawing: {n} Pouze v tomto výkresu: {n} + Only in {name}: {n} Pouze v {name}: {n} + Open (⌘O) Otevřít (⌘O) + Open Sample Drawing Otevřít ukázkový výkres + Open sample drawing Otevřít ukázku výkresu + Open Xref Otevřít externí referenci + Open... Otevřít... + Operator: Operátor: + Orbit Orbit + Ordinate Souřadnicová + Ortho (F8) Ortho (F8) + Ortho Mode Režim Ortho + Ortho Mode (F8) Režim Ortho (F8) + Osnap Settings... Nastavení uchopení objektu... + Out Oddálit pohled + Over-constrained Přeurčeno + Override Přepsat + PAPER PAPÍR + Percent Procenta + Polar (distance < angle) Polární (vzdálenost < úhel) + PRs PR + Page Setup Manager Správce nastavení stránky + Page Setup Manager... Správce nastavení stránky... + Pan Posun pohledu + Pan Down Posunout pohled dolů + Pan Left Posunout pohled vlevo + Pan Right Posunout pohled vpravo + Pan Up Posunout pohled nahoru + Paper Space Výkresový prostor + Parallel Rovnoběžná + Parameters Manager Správce parametrů + Parametric Parametrické + Paste Vložit ze schránky + Paste as Block Vložit jako blok + Paste to Command Line Vložit do příkazového řádku + Paste to Original Coordinates Vložit na původní souřadnice + Path Array Pole podél trajektorie + Pattern Vzor + Perpendicular Kolmá + Plot Tisk + Plot (click: do not plot) Tisknout (kliknutím: netisknout) + Plot Preview Náhled tisku + Plot style Tiskový styl + Plot style attached to Tiskový styl přiřazený k + Plot style table Tabulka tiskových stylů + Plot Style... Tiskový styl... + Plot Style Manager Správce tiskových stylů + Plot Style Manager... Správce tiskových stylů... + Plot Styles... Tiskové styly... + Plotter Manager Správce plotrů + Plotter Manager... Správce plotrů... + New CTB Nová CTB + New STB Nová STB + New style Nový styl + Reset Panel Layout Obnovit rozložení panelů + Send Hatches to Back Přenést šrafy dozadu + Send Under Objects Přenést pod objekty + Text Objects Only Pouze textové objekty + Use for this layout Použít pro toto rozvržení + Display plot styles Zobrazit tiskové styly + No plot style tables. Žádné tabulky tiskových stylů. + A built-in table: editing it keeps an edited copy in the drawing. Vestavěná tabulka: při úpravě se do výkresu uloží upravená kopie. + Keep an editable copy of this table in the drawing Uchovat upravitelnou kopii této tabulky ve výkresu + Layout {name}: {table} Rozvržení {name}: {table} + Grayscale Odstíny šedi + Screening Intenzita tisku + Use object linetype Použít typ čáry objektu + Use object lineweight Použít tloušťku čáry objektu + Remove Odebrat + Add Přidat + Open a drawing first. Nejprve otevřete výkres. + Plot table type Typ tabulky tiskových stylů + Color-dependent Závislé na barvě + Named Pojmenované + Plus/minus Plus/mínus + Point Bod + Point Filters Filtry souřadnic + Point Style... Styl bodu... + Polar Array Kruhové pole + Polar Tracking Polární trasování + Polar Tracking (F10) Polární trasování (F10) + Polar Tracking On (F10) Zapnout polární trasování (F10) + Polar angle measurement Měření polárního úhlu + Polar distance Polární vzdálenost + Polar: {distance} < {angle}° Polární: {distance} < {angle}° + PolarSnap Polární uchopení + Polygon Mnohoúhelník + Polygonal Mnohoúhelníkové + Polygonal Viewport Mnohoúhelníkový výřez + Polyline Křivka + Polyline Edit Upravit křivku + Position X Poloha X + Position Y Poloha Y + Position Z Poloha Z + Previous Předchozí + Previous Change Předchozí změna + Previous Layer Předchozí hladina + Primitives Základní tělesa + Print Tisknout + Print... Tisknout... + Properties Vlastnosti + Properties Inspector Inspektor vlastností + Properties: Vlastnosti: + Proxy Proxy objekt + Purge Čistit + Pyramid Jehlan + Quadrant Kvadrant + Query Entities Dotaz na entity + Quick Rychlé + Quick Dimension Rychlá kóta + Quick Properties Rychlé vlastnosti + Quick Select Rychlý výběr + Quick Select Properties Vlastnosti rychlého výběru + Quick Select... Rychlý výběr... + QuickCalc Rychlá kalkulačka + QuickCalc Pick Výběr pro rychlou kalkulačku + Quit CADCraft Ukončit CADCraft + Radius Poloměr + Raster Image Rastrový obrázek + Ray Polopřímka + Read-only Pouze pro čtení + Real name Skutečné jméno + Realtime V reálném čase + Reassociate Dimensions Obnovit asociativitu kót + Recent Nedávné + Recent Commands Nedávné příkazy + Recent Input Nedávné vstupy + Recover... Obnovit výkres... + Rectangle Obdélník + Recalculate Table Formulas Přepočítat vzorce tabulky + Rectangular Obdélníkové + Rectangular snap Pravoúhlé uchopení + Rectangular Array Obdélníkové pole + Red Červená + Redo Znovu + Redo (⇧⌘Z) Znovu (⇧⌘Z) + Redraw Překreslit + Regen Regenerovat + Regen All Regenerovat vše + Region Oblast + Region/Mass Properties Vlastnosti oblasti/hmoty + Reinitialize Znovu inicializovat + Relative Relativní + Relative to last segment Vzhledem k poslednímu segmentu + Remove Leader Odebrat odkaz + Remove the viewport override Odebrat přepsání výřezu + Rename Dimension Style Přejmenovat kótovací styl + Rename Layer Přejmenovat hladinu + Rename Layer State Přejmenovat stav hladin + Rename Layout Přejmenovat rozvržení + Rename Text Style Přejmenovat styl textu + Rename... Přejmenovat... + Repeat {command} Opakovat {command} + Requires a point (x,y, @dx,dy or @d Určete druhý bod nebo + Specify second source point Určete druhý zdrojový bod + Specify side to offset Určete stranu pro ekvidistantu + Specify start angle Určete počáteční úhel + Specify start point Určete počáteční bod + Specify start point of arc Určete počáteční bod oblouku + Specify start point of polyline Určete počáteční bod křivky + Specify start point of text Určete počáteční bod textu + Specify starting width Určete počáteční šířku + Specify starting width for next segment Určete počáteční šířku dalšího segmentu + Specify tangent direction for the start point of arc Určete směr tečny v počátečním bodě oblouku + Specify the elevation for rectangles Určete výšku zdvihu obdélníků + Specify thickness for rectangles Určete tloušťku obdélníků + Specify third point on circle Určete třetí bod na kružnici + Specify third point on circle: _tan to Určete třetí bod na kružnici: _tan k + Specify third source point or Určete třetí zdrojový bod nebo + Specify through point Určete bod, kterým má procházet + Specify top diameter Určete horní průměr + Specify top radius or Určete horní poloměr nebo + Specify total angle Určete celkový úhel + Specify total length or Určete celkovou délku nebo + Specify width for rectangles Určete šířku obdélníků + Sphere Koule + Spline Spline + Spline Edit Upravit spline + Stack (type 1/2 then select) Zlomek (napište 1/2 a poté vyberte) + Standard Standardní + Start Úvod + Start Width Počáteční šířka + Start X Počátek X + Start Y Počátek Y + Start angle Počáteční úhel + Start, Center, Angle Počátek, střed, úhel + Start, Center, End Počátek, střed, konec + Start, Center, Length Počátek, střed, délka + Start, End, Angle Počátek, konec, úhel + Start, End, Direction Počátek, konec, směr + Start, End, Radius Počátek, konec, poloměr + Status Stav + Status Bar Stavový řádek + Stretch Protáhnout + Style: Standard Styl: Standard + Subtract Rozdíl + Sweep Tažení + Switch Drawing Přepnout výkres + Switch Layout Přepnout rozvržení + Switch between model space in a viewport and paper space Přepnout mezi modelovým prostorem ve výřezu a výkresovým prostorem + Symmetric Symetrie + Synchronize Attributes Synchronizovat atributy + To Do + Toggle PICKADD (off: each pick replaces the selection) Přepnout PICKADD (vypnuto: každý výběr nahradí předchozí) + Toggle PICKADD (on: picks add to the selection) Přepnout PICKADD (zapnuto: výběry se přidávají) + TOP SHORA + Table Tabulka + Table Breaks Přerušení tabulky + Table Cell Style Styl buňky tabulky + Table Style... Styl tabulky... + Table style Styl tabulky + Table... Tabulka... + Tan, Tan, Radius Tečna, tečna, poloměr + Tan, Tan, Tan Tečna, tečna, tečna + Tangent Tečna + Temporary track point Dočasný bod trasování + Text Text + Text Editor Editor textu + Text Height Výška textu + Text Style... Styl textu... + Text height Výška písma + Text override Přepsání textu + Text style Styl textu + Thaw All Layers Rozmrazit všechny hladiny + Thaw Layer Rozmrazit hladinu + There is nothing here yet. Zatím zde nic není. + Thickness Tloušťka + Time Čas + To get started, create or open a drawing. Začněte vytvořením nebo otevřením výkresu. + Tool Bar Panel nástrojů + Tool Sets Sady nástrojů + Tools Nástroje + Torus Anuloid + Trace Stopa + Track orthogonally only Trasovat pouze kolmo + Track using all polar angle settings Trasovat podle všech nastavení polárních úhlů + Transparency Průhlednost + Trim Oříznout + True Color Skutečná barva + Turn All Layers On Zapnout všechny hladiny + Turn Off Layer Vypnout hladinu + Turn On Layer Zapnout hladinu + Turn Quick Properties off (QPMODE) Vypnout rychlé vlastnosti (QPMODE) + Type Typ + Type a command Zadejte příkaz + Type text; Enter starts a new paragraph Pište text; Enter začne nový odstavec + UCS Icon Ikona USS + Undo Zpět + Undo (⌘Z) Zpět (⌘Z) + Ungroup Zrušit skupinu + Union Sjednocení + Unisolate Layer Zrušit izolaci hladiny + Units Conversion Převod jednotek + Units... Jednotky... + Unlock Layer Odemknout hladinu + Unlock viewport Odemknout výřez + Unmerge Cells Zrušit sloučení buněk + Unsaved Layer State Neuložený stav hladin + Up Nahoru + Update Data Links Aktualizovat datová propojení + Update Aktualizovat + Use System Setting Použít nastavení systému + User Uživatel + User Parameters Uživatelské parametry + Username Uživatelské jméno + Volume Objem + VP Color Barva ve výřezu + VP Freeze Zmrazení ve výřezu + Value Hodnota + Value: Hodnota: + Variables Proměnné + Version Verze + Version 2000 Verze 2000 + Version 2004 Verze 2004 + Version 2007 Verze 2007 + Version 2010 Verze 2010 + Version 2013 Verze 2013 + Version 2018 Verze 2018 + Version {version} Verze {version} + Vertical Svislá + VerticalDistance Svislá vzdálenost + View Pohled + ViewCube ViewCube + Viewport Výřez + Viewport Layer Freeze Zmrazení hladiny ve výřezu + Viewport Properties Vlastnosti výřezu + Viewport is locked Výřez je zamčený + Viewport scale Měřítko výřezu + Viewport {id} Výřez {id} + Viewports Výřezy + W Z + WCS ⌄ GSS ⌄ + White Bílá + Width factor Faktor šířky + Window Okno + Wipeout Zakrytí + Workspace Switching Přepínání pracovních prostorů + Write Block Zapsat blok + Xline Konstrukční přímka + Yellow Žlutá + Yes Ano + Zoom Změna přiblížení + Zoom All Přiblížit vše + Zoom Dynamic Dynamické přiblížení + Zoom Extents Přiblížit na rozsah + Zoom In Přiblížit + Zoom Object Přiblížit objekt + Zoom Out Oddálit + Zoom Previous Předchozí přiblížení + Zoom Realtime Přiblížení v reálném čase + Zoom Window Přiblížit oknem + error chyba + {contributors} · {commits} {contributors} · {commits} + {kind} (constraint {id}) {kind} (vazba {id}) + {kind} constraint {name} = {expression} (double-click to edit) Vazba {kind} {name} = {expression} (dvojitým kliknutím upravíte) + {name}: {distance} < {angle}° {name}: {distance} < {angle}° + ƒx New User Parameter ƒx Nový uživatelský parametr + ΔLOC ΔLOC + −Bin −Bin + −LOC −LOC + ⌘↩ to finish ⌘↩ pro dokončení +@plural {n} commit {n} commit|{n} commity|{n} commitů +@plural {n} contributor {n} přispěvatel|{n} přispěvatelé|{n} přispěvatelů + Drawing as bytes Výkres jako bajty + Services Služby + Hide CADCraft Skrýt CADCraft + Hide Others Skrýt ostatní + Accessibility Zpřístupnění + Show System Cursor Zobrazit systémový kurzor + Import... Importovat... + Export... Exportovat... + Batch Publish... Dávkově publikovat... + Scale List... Seznam měřítek... + Annotative Object Scale Měřítko objektu popisu + Add Current Scale Přidat aktuální měřítko + Delete Current Scale Odstranit aktuální měřítko + Add/Delete Scales... Přidat/Odebrat měřítka... + Synchronize Multiple-scale Positions Synchronizovat polohy pro více měřítek + Annotative Update Aktualizovat popisy + Show Annotative Objects Zobrazit objekty popisů + Current Scale Only Pouze aktuální měřítko + All Scales Všechna měřítka + Drawing Recovery Manager... Správce obnovení výkresů... + Tolerance... Tolerance... + Add Vertex Přidat vrchol + Remove Vertex Odebrat vrchol + Convert to Arc Převést na oblouk + Convert to Line Převést na úsečku + Stretch Vertex Protáhnout vrchol + Edit Array Upravit pole + Close Array Editing Ukončit úpravy pole + Multiline... Multičára... + Multiline Style... Styl multičáry... + Solid Editing Úpravy těles + X X + Y Y + B B + CADCraft CADCraft + More toolbar commands Další příkazy panelu nástrojů +menu View Zobrazení +menu Draw Kreslení +menu Dimension Kótování +menu Modify Modifikace diff --git a/crates/ui-egui/src/i18n/mod.rs b/crates/ui-egui/src/i18n/mod.rs index c9dca56..9253deb 100644 --- a/crates/ui-egui/src/i18n/mod.rs +++ b/crates/ui-egui/src/i18n/mod.rs @@ -23,10 +23,12 @@ pub enum Preference { German, #[serde(rename = "es")] Spanish, + #[serde(rename = "cs")] + Czech, } impl Preference { - pub const ALL: [Self; 6] = [Self::Auto, Self::English, Self::Ukrainian, Self::BrazilianPortuguese, Self::German, Self::Spanish]; + pub const ALL: [Self; 7] = [Self::Auto, Self::English, Self::Ukrainian, Self::BrazilianPortuguese, Self::German, Self::Spanish, Self::Czech]; /// The codes a preference can be given as, for messages ("auto, en or uk"). pub fn codes() -> String { @@ -45,6 +47,7 @@ impl Preference { Self::BrazilianPortuguese => "pt-BR", Self::German => "de", Self::Spanish => "es", + Self::Czech => "cs", } } @@ -56,6 +59,7 @@ impl Preference { Self::BrazilianPortuguese => "Português (Brasil)", Self::German => "Deutsch", Self::Spanish => "Español", + Self::Czech => "Čeština", } } @@ -75,6 +79,7 @@ impl Preference { Self::BrazilianPortuguese => "pt-BR", Self::German => "de", Self::Spanish => "es", + Self::Czech => "cs", Self::Auto => locales.iter().find_map(|s| locale_language(s)).unwrap_or("en"), } } @@ -91,7 +96,7 @@ pub struct Language { catalog: OnceLock>, } -pub static LANGUAGES: [Language; 5] = [ +pub static LANGUAGES: [Language; 6] = [ Language { code: "en", name: "English", source: "", plural: plural_en, plural_forms: 2, catalog: OnceLock::new() }, Language { code: "uk", name: "Українська", source: include_str!("uk.tsv"), plural: plural_uk, plural_forms: 3, catalog: OnceLock::new() @@ -108,6 +113,7 @@ pub static LANGUAGES: [Language; 5] = [ Language { code: "de", name: "Deutsch", source: include_str!("de.tsv"), plural: plural_en, plural_forms: 2, catalog: OnceLock::new() }, // Spanish integer plurals follow the English rule too. Language { code: "es", name: "Español", source: include_str!("es.tsv"), plural: plural_en, plural_forms: 2, catalog: OnceLock::new() }, + Language { code: "cs", name: "Čeština", source: include_str!("cs.tsv"), plural: plural_cs, plural_forms: 3, catalog: OnceLock::new() }, ]; /// BCP 47 and POSIX locale tags, including `uk-UA`, `uk_UA.UTF-8` and `pt_BR.UTF-8`. @@ -168,6 +174,16 @@ pub fn t(source: &str) -> &str { CURRENT.with(|l| tr(l.get(), source)) } +/// Menu headings can differ from command or object labels (e.g. Czech Kótování / Kóta). +/// Catalogs without a `menu` entry retain their ordinary translation. +pub fn tr_menu<'a>(language: &str, source: &'a str) -> &'a str { + catalog(language).and_then(|c| c.get(&("menu", source))).copied().unwrap_or_else(|| tr(language, source)) +} + +pub fn menu(source: &str) -> &str { + CURRENT.with(|l| tr_menu(l.get(), source)) +} + /// Named placeholders allow translations to reorder values. Inserted values are never looked up /// or substituted again, so a user's name containing `{n}` is preserved verbatim. pub fn format(source: &str, values: &[(&str, String)]) -> String { @@ -213,6 +229,15 @@ fn plural_en(n: u64) -> usize { usize::from(n != 1) } +/// Czech integer plurals: one (1), few (2–4), other (0 and 5 or more). +pub fn plural_cs(n: u64) -> usize { + match n { + 1 => 0, + 2..=4 => 1, + _ => 2, + } +} + pub fn count(n: u64, one: &str, other: &str) -> String { let language = CURRENT.get(); let source = catalog(language).and_then(|c| c.get(&("@plural", one))).copied(); diff --git a/crates/ui-egui/src/i18n/tests.rs b/crates/ui-egui/src/i18n/tests.rs index e34836d..6adf51d 100644 --- a/crates/ui-egui/src/i18n/tests.rs +++ b/crates/ui-egui/src/i18n/tests.rs @@ -15,7 +15,7 @@ fn catalog_is_valid_and_preserves_placeholders_and_ellipses() { let (catalog, errors) = parse(language.source); assert!(errors.is_empty(), "{}: {errors:?}", language.code); for ((context, key), value) in catalog { - assert!(["", "@plural"].contains(&context), "unknown context: {context}"); + assert!(["", "menu", "@plural"].contains(&context), "unknown context: {context}"); let forms: Vec<_> = if context == "@plural" { value.split('|').collect() } else { vec![value] }; if context == "@plural" { assert_eq!(forms.len(), language.plural_forms, "{}: {key}", language.code); @@ -39,7 +39,7 @@ fn catalog_is_valid_and_preserves_placeholders_and_ellipses() { /// to English for what they don't cover yet; their gaps are reported, not enforced, so adding a /// command doesn't require a row in every language. const REQUIRED: &[&str] = &["uk"]; -const REPORTED: &[&str] = &["pt-BR", "de", "es"]; +const REPORTED: &[&str] = &["pt-BR", "de", "es", "cs"]; fn check(language: &str, what: &str, missing: Vec) { if REQUIRED.contains(&language) { @@ -101,6 +101,7 @@ fn missing_marked_ui_literals(language: &str) -> BTreeSet { include_str!("../parametric.rs"), include_str!("../quick.rs"), include_str!("../vpscale.rs"), + include_str!("../options/dialog.rs"), ]; let mut missing = BTreeSet::new(); for source in sources { @@ -388,3 +389,118 @@ fn default_fonts_cover_every_ukrainian_letter_in_the_catalog() { } }); } + +#[test] +fn czech_locales_preferences_and_plural_forms() { + for tag in ["cs", "cs-CZ", "cs_CZ.UTF-8", "CS-cz", " cs-CZ ", "cs_CZ@euro"] { + assert_eq!(locale_language(tag), Some("cs"), "{tag}"); + } + for tag in ["cz", "csharp", "csomething"] { + assert_eq!(locale_language(tag), None, "{tag}"); + } + assert_eq!(Preference::parse("cs"), Some(Preference::Czech)); + assert_eq!(Preference::Czech.name(), "Čeština"); + assert_eq!(Preference::Czech.resolve(&["en-US".into()]), "cs"); + assert_eq!(Preference::Auto.resolve(&["pl-PL".into(), "cs-CZ".into(), "en-US".into()]), "cs"); + let mut app = CadApp::new(Session::new(), Services::default()); + app.ui.interface_language = Preference::Czech; + let mut restored = CadApp::new(Session::new(), Services::default()); + restored.load_prefs(&app.prefs_json()); + assert_eq!(restored.ui.interface_language, Preference::Czech); + with_language("cs", || { + for (n, form) in [(0, 2), (1, 0), (2, 1), (4, 1), (5, 2), (11, 2), (21, 2), (22, 2), (25, 2), (u64::MAX, 2)] { + assert_eq!(plural_cs(n), form, "{n}"); + let contributor = ["přispěvatel", "přispěvatelé", "přispěvatelů"][form]; + let commit = ["commit", "commity", "commitů"][form]; + assert_eq!(count(n, "{n} contributor", "{n} contributors"), format!("{n} {contributor}")); + assert_eq!(count(n, "{n} commit", "{n} commits"), format!("{n} {commit}")); + } + assert_eq!(format("Current: {color}", &[("color", "{n} Open".into())]), "Aktuální: {n} Open"); + }); +} + +#[test] +fn czech_menu_headings_keep_object_labels_and_other_catalogs() { + with_language("cs", || { + assert_eq!(menu("View"), "Zobrazení"); + assert_eq!(t("View"), "Pohled"); + assert_eq!(menu("Dimension"), "Kótování"); + assert_eq!(t("Dimension"), "Kóta"); + assert_eq!(menu("Draw"), "Kreslení"); + assert_eq!(menu("Modify"), "Modifikace"); + assert_eq!(menu("Edit"), "Úpravy"); + assert_eq!(menu("File"), "Soubor"); + }); + for language in ["en", "uk", "de", "es", "pt-BR", "unknown"] { + for source in crate::menus::MENUS { + assert_eq!(tr_menu(language, source), tr(language, source)); + } + } +} + +#[test] +fn live_czech_switch_preserves_drawing_command_and_saved_choice() { + let mut app = CadApp::new(Session::new(), Services::default()); + app.ui.in_window_menu = true; + app.session.state_mut().unwrap().title = "Open".into(); + let ctx = egui::Context::default(); + app.logic(&ctx); + assert!(render(&mut app, &ctx).contains("Properties")); + app.start("line"); + let prompt = crate::control::cmdline_state(&app); + let commands = crate::control::all_commands(&app); + app.run("ui.language", json!({"lang":"cs"})).unwrap(); + let text = render(&mut app, &ctx); + for label in ["Vlastnosti", "Soubor", "Zobrazení", "Kreslení", "Kótování", "Určete první bod"] { + assert!(text.contains(label), "missing {label}: {text}"); + } + assert_eq!(app.language(), "cs"); + assert_eq!(app.session.state().unwrap().title, "Open"); + assert_eq!(crate::control::cmdline_state(&app), prompt); + assert_eq!(crate::control::all_commands(&app), commands); + assert_eq!(t("Properties"), "Properties"); + app.run("ui.resetpalettes", json!({})).unwrap(); + assert_eq!(app.language(), "cs"); + app.run("ui.language", json!({"lang":"en"})).unwrap(); + assert!(render(&mut app, &ctx).contains("Properties")); +} + +#[test] +fn czech_dialogs_render_with_stable_ids() { + for (dialog, heading) in [ + ("dsettings", "Nastavení kreslení"), + ("about", "O aplikaci CADCraft"), + ("commands", "Přehled příkazů"), + ("blocks", "Bloky"), + ("layers", "Správce vlastností hladin"), + ("qselect", "Rychlý výběr"), + ("parameters", "Správce parametrů"), + ("language", "Čeština"), + ("options:preferences", "Uživatelské předvolby"), + ] { + let mut app = CadApp::new(Session::new(), Services::default()); + app.ui.interface_language = Preference::Czech; + app.ui.dialog = Some(dialog.into()); + let ctx = egui::Context::default(); + app.logic(&ctx); + let text = render(&mut app, &ctx); + assert!(text.contains(heading), "{dialog}: {text}"); + assert_eq!(app.ui.dialog.as_deref(), Some(dialog)); + } +} + +#[test] +fn default_fonts_cover_czech_letters_and_typographic_quotes() { + let ctx = egui::Context::default(); + let mut output = ctx.run_ui(Default::default(), |_| {}); + output.textures_delta.clear(); + let letters: BTreeSet<_> = "ÁČĎÉĚÍŇÓŘŠŤÚŮÝŽáčďéěíňóřšťúůýž„“".chars().collect(); + ctx.fonts_mut(|view| { + for family in [egui::FontFamily::Proportional, egui::FontFamily::Monospace] { + let mut font = view.fonts.font(&family); + for c in &letters { + assert!(font.characters().contains_key(c), "missing {c} in {family:?}"); + } + } + }); +} diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 9484eaa..155e646 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -1203,6 +1203,7 @@ Multiline... Мультилінія... Multiline Style... Стиль мультилінії... Solid Editing Редагування тіл + More toolbar commands Інші команди панелі інструментів Default save version Типова версія збереження Automatic save every Автозбереження кожні min хв diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 7fd0d1c..55ceb39 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -456,7 +456,7 @@ pub(crate) fn entry_ui(ui: &mut egui::Ui, e: &Entry, clicked: &mut Option { - ui.menu_button(crate::i18n::t(label), |ui| { + ui.menu_button(crate::i18n::menu(label), |ui| { for c in children { entry_ui(ui, c, clicked); } @@ -474,7 +474,7 @@ pub fn menu_bar(app: &mut CadApp, ui: &mut egui::Ui) { |ui| { egui::MenuBar::new().ui(ui, |ui| { for (name, entries) in &tree { - ui.menu_button(crate::i18n::t(name), |ui| { + ui.menu_button(crate::i18n::menu(name), |ui| { for e in entries { entry_ui(ui, e, &mut clicked); } diff --git a/crates/ui-egui/src/options/mod.rs b/crates/ui-egui/src/options/mod.rs index cb9a7b8..49cc0c9 100644 --- a/crates/ui-egui/src/options/mod.rs +++ b/crates/ui-egui/src/options/mod.rs @@ -9,7 +9,7 @@ //! | name | value | //! |---|---| //! | `theme` | `"system"`, `"light"` or `"dark"` | -//! | `interfaceLanguage` | `"auto"`, `"en"` or `"uk"` | +//! | `interfaceLanguage` | `"auto"`, `"en"`, `"uk"`, `"pt-BR"`, `"de"`, `"es"` or `"cs"` | //! | `saveFormat` | `"dxf"` or `"dwg"`: the format Save As suggests for new drawings | //! | `saveVersion` | `"2000"` … `"2018"`: the version drawings with no file yet are saved in | //! | `SAVETIME` | minutes between automatic saves, 0–600 (0: off) | diff --git a/docs/control-protocol.md b/docs/control-protocol.md index 9c359c3..94db087 100644 --- a/docs/control-protocol.md +++ b/docs/control-protocol.md @@ -115,7 +115,7 @@ Select a language with `engine.execute` and the UI command `ui.language`: {"id":1,"method":"engine.execute","params":{"command":"ui.language","params":{"lang":"uk"}}} ``` -Supported values are `auto`, `en`, `uk` and `de`. `ui.set` also accepts +Supported values are `auto`, `en`, `uk`, `pt-BR`, `de`, `es` and `cs`. `ui.set` also accepts `{"interfaceLanguage":"uk"}`; `ui.inspect` reports the saved choice in its UI state. Invalid choices leave the current language unchanged. Menus, command labels and prompt text returned by the control channel retain their English source text. See [localization.md](localization.md). diff --git a/docs/localization-parity.md b/docs/localization-parity.md index 923f833..a56c3e8 100644 --- a/docs/localization-parity.md +++ b/docs/localization-parity.md @@ -1,6 +1,6 @@ # Localization parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (German catalog landed: second non-English language, per-language plural rules) · **Target:** Autodesk AutoCAD 2027 for Mac (26.0) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (Czech catalog added: reference/literal coverage, Czech plurals and menu headings) · **Target:** Autodesk AutoCAD 2027 for Mac (26.0) How far CADCraft's interface and drawing text are from AutoCAD's languages. Summarised in [ROADMAP.md](../ROADMAP.md#languages); work items in [gaps.md](gaps.md#localization). @@ -64,8 +64,10 @@ plus native review by a human; extending the catalog to the remaining English-on | Korean | ko | 0 (0%) | 0% | Hangul renders; macOS Korean IME fixes pending (#118, #119) | no | none | 4–6 h | | Vietnamese | vi | 0 (0%) | 0% | Latin with stacked diacritics: renders per code point, untested | no | none | 3–5 h | | Ukrainian | uk | 989 catalog rows (≈ 100% of the catalog; ≈ 80% of all UI strings, estimated: engine diagnostics and uncatalogued text stay English) | dialogs and tooltips yes; command reference searchable in Ukrainian | Cyrillic: yes (bundled egui fonts) | translated by a contributor; no second review | partial | 2–4 h | +| Czech | cs | 1,202 catalog rows; reference catalog and marked UI literals covered | dialogs and tooltips yes; contextual menu headings; command reference searchable in Czech | Latin: yes (bundled egui proportional and monospace fonts; Czech letters and quotes tested) | AI-assisted by @Losminek; independent review pass; not yet proofread by a native speaker | complete current catalog; English-only interface gaps remain | native review + shared English-only UI work | -Other languages shipped: Ukrainian, Brazilian Portuguese and German (all partial). AutoCAD for Mac ships 7 +Other languages shipped: Ukrainian, Brazilian Portuguese, German and Czech. Czech covers the +reference catalog and marked UI literals; engine diagnostics and uncatalogued text remain English. AutoCAD for Mac ships 7 non-English languages (zh-Hans, es, fr, ja, de, ko, it); of those, CADCraft now ships German, and additionally Ukrainian, which AutoCAD for Mac doesn't ship. @@ -77,6 +79,7 @@ each language, which needs humans. Translations parallelise fully once the catal | Date | Change | Summary | |---|---|---| +| 2026-10-11 | minor | Czech added: 1,202 rows, one/few/other plurals, locale/preferences/menu/font/render tests; independent review pass; native proofreading pending | | 2026-10-11 | minor | German catalog landed: `de` preference and catalog, per-language plural rules; non-English languages 1 → 2; total hours 60–100 → 55–95 | | 2026-10-10 | minor | Right-to-left drawing text: bidi and Arabic-script shaping in TEXT and MTEXT (#287) | | 2026-10-10 | minor | Ukrainian catalog landed on main (#36): catalog infrastructure exists, Ukrainian partial; total hours 70–110 → 60–100 | diff --git a/docs/localization.md b/docs/localization.md index bd376fc..32bbd46 100644 --- a/docs/localization.md +++ b/docs/localization.md @@ -1,46 +1,42 @@ # Interface languages Choose **Edit → Interface Language** and select **Auto (system language)**, **English**, -**Українська**, or **Deutsch**. The interface updates without restarting, including the native -macOS menus. -**Українська**, or **Português (Brasil)**. The interface updates without restarting, including the native macOS menus. +**Українська**, **Português (Brasil)**, **Deutsch**, **Español**, or **Čeština** (Czech). +The interface updates without restarting, including the native macOS menus. The choice is saved with the other interface preferences (`cadcraft.prefs`, beside the theme): eframe storage on the desktop, browser local storage on the web. Installations without a saved choice use Auto. Auto uses the first supported language in the operating system's preferred locales, or the -browser's `navigator.languages` on the web. Ukrainian tags such as `uk-UA` and `uk_UA.UTF-8` -resolve to `uk`, German tags such as `de-DE` and `de_AT.UTF-8` resolve to `de`; unsupported -languages fall back to English. Set `CADCRAFT_LOCALE=uk-UA` to -override the desktop's locale for a launch. An explicit saved English, Ukrainian or German -choice takes precedence over that override. -resolve to `uk`, and Portuguese tags such as `pt-BR` and `pt_BR.UTF-8` resolve to `pt-BR`; -unsupported languages fall back to English. Set `CADCRAFT_LOCALE=uk-UA` to -override the desktop's locale for a launch. An explicit saved English, Ukrainian or Brazilian Portuguese choice -takes precedence over that override. +browser's `navigator.languages` on the web. BCP 47 and POSIX tags select their primary language: +`uk-UA` → `uk`, `de_AT.UTF-8` → `de`, `es-MX` → `es`, `pt_BR.UTF-8` → `pt-BR`, +`cs-CZ` and `cs_CZ.UTF-8` → `cs`. Unsupported languages fall back to English. +Set `CADCRAFT_LOCALE=cs-CZ` to override the desktop's locale for a launch. +An explicit saved language choice takes precedence over that override. Automation can select the language through the existing control channel: ```json -{"id":1,"method":"engine.execute","params":{"command":"ui.language","params":{"lang":"uk"}}} +{"id":1,"method":"engine.execute","params":{"command":"ui.language","params":{"lang":"cs"}}} ``` -The `ui.set` method also accepts `{"interfaceLanguage":"uk"}`. Supported values are `auto`, -`en`, `uk`, and `de`; invalid values are rejected without changing the current selection. -Resetting palettes keeps the language choice. -`en`, `uk`, and `pt-BR`; invalid values are rejected without changing the current selection. Resetting -palettes keeps the language choice. +The `ui.set` method also accepts `{"interfaceLanguage":"cs"}`. Supported values are `auto`, +`en`, `uk`, `pt-BR`, `de`, `es`, and `cs`; invalid values are rejected without changing the current +selection. Resetting palettes keeps the language choice. ## Translation coverage -Ukrainian and German cover command and menu labels, tool groups and tooltips, the Start page, +The catalogs cover command and menu labels, tool groups and tooltips, the Start page, file and model-space tabs, status controls, object snaps, drafting prompts, property labels, dialogs, and the About window's controls. The command reference can be searched by English -command ID, English label, or translated label. -The Ukrainian and Brazilian Portuguese catalogs cover command and menu labels, tool groups and tooltips, the Start page, file and -model-space tabs, status controls, object snaps, drafting prompts, property labels, dialogs, -and the About window's controls. The command reference can be searched by English command -ID, English label, or translated label. +command ID, English label, or translated label. Ukrainian has enforced coverage; +missing entries in the other catalogs are reported by tests and fall back to English. + +Czech has 1,202 catalog rows, covering the reference catalog and every marked UI +literal, including Options. Four `menu` entries distinguish menu headings from object/command +labels: **Zobrazení / Pohled**, **Kreslení / Kreslit**, **Kótování / Kóta**, and **Modifikace / Upravit**. +The translation is AI-assisted work by @Losminek, reviewed against Czech desktop and CAD UI +conventions and an independent review pass; it has not yet been proofread by a native speaker. Drawing titles, layer/layout/block/style names, parameter names and expressions, text in a drawing, and command-line input are user data and retain their original spelling. Clickable @@ -49,9 +45,9 @@ by the engine. CLI/MCP/control responses, engine diagnostics and command history English. Uncatalogued text also falls back to English. Number formatting and the operating system's own file-picker controls follow the existing behavior. -The bundled egui fonts cover Ukrainian, including `Ґґ Єє Іі Її`, and German, including -`ÄÖÜ äöü ß`; the translations add no font -assets and work on the web without system fonts. +The bundled egui fonts cover Ukrainian (`Ґґ Єє Іі Її`), German (`ÄÖÜ äöü ß`), and Czech +(`ÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ áčďéěíňóřšťúůýž`, including typographic quotes `„…“`). +The translations add no font assets and work on the web without system fonts. ## Adding translations @@ -60,14 +56,14 @@ The implementation follows the display-time catalog pattern used by [PdfCraft #106](https://github.com/storytold/pdfcraft/pull/106), and [FilmCraft #238](https://github.com/storytold/filmcraft/pull/238). Its code is local to CADCraft. -- `crates/ui-egui/src/i18n/uk.tsv` and `crates/ui-egui/src/i18n/de.tsv` are UTF-8 with three - tab-separated columns: -- `crates/ui-egui/src/i18n/uk.tsv` and `pt_br.tsv` are UTF-8 with three tab-separated columns: +- `crates/ui-egui/src/i18n/*.tsv` are UTF-8 with three tab-separated columns: `context`, `English source`, and `translation`. Ordinary labels have an empty context. - `@plural` entries hold Ukrainian `one|few|many` forms for integer counts; German uses - `one|other|other` (singular/plural only, so the third form repeats the plural). - `@plural` entries hold the language's plural forms for integer counts: Ukrainian - `one|few|many`, Brazilian Portuguese `one|other` (0 and 1 are `one`). + Optional `menu` entries translate menu headings via `i18n::menu` / `i18n::tr_menu`; + without one, the ordinary translation is used. +- `@plural` entries hold the language's forms for integer counts: Ukrainian `one|few|many`, + German and Spanish `one|other`, Brazilian Portuguese `one|other` (0 and 1 are `one`), + Czech `one|few|other` (1; 2–4; everything else, including 0, 11, 21 and 22). + The API takes `u64`, so fractional counts are not accepted. - Register a new catalog in `i18n::LANGUAGES`, add its preference variant and code/name, and set its integer plural rule and form count on the `Language` row. - Use `crate::tl!("English label")` for a literal, `i18n::t(label)` for a known dynamic UI @@ -75,11 +71,16 @@ The implementation follows the display-time catalog pattern used by Translate only at the display boundary; never look up arbitrary user names or identifiers. - Windows retain explicit IDs based on their English source, and tool groups retain their source names as keys, so switching languages preserves their state. +- Add a translation attribution row in `ATTRIBUTION.md`, update the language lists, and add + locale, plural, font-glyph and live-switch tests. Add the catalog to `REPORTED` in + `i18n/tests.rs`: only Ukrainian, the reference translation, is in `REQUIRED`, so adding a + command needs a row in one language, not in all of them. - Catalogs are embedded and parsed once. Missing or malformed rows cannot crash the app; tests reject invalid rows, duplicate keys, changed placeholders, and mismatched ellipses. - `cargo test -p cadcraft-ui-egui i18n` checks menu/command/tool/snap coverage, every marked - UI literal, locale resolution, preferences, integer plurals, bundled glyphs and an actual - English/Ukrainian/English egui render. `cargo xtask ci` runs the workspace quality gates. + UI literal, locale resolution, preferences, integer plurals, bundled glyphs and actual + egui renders with language switching. `cargo xtask assets` checks asset attribution; + `cargo xtask ci` runs the workspace quality gates. Translations are original work under `MIT OR Apache-2.0`, written from the meaning of CADCraft's English strings. Do not copy proprietary localization resources.