diff --git a/Cargo.lock b/Cargo.lock index c89a20002..34b5455fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1306,7 +1306,7 @@ dependencies = [ [[package]] name = "designcraft" -version = "0.15.2" +version = "0.16.0" dependencies = [ "arboard", "craft-update", @@ -1330,7 +1330,7 @@ dependencies = [ [[package]] name = "designcraft-cli" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-color", "designcraft-compose", @@ -1346,7 +1346,7 @@ dependencies = [ [[package]] name = "designcraft-color" -version = "0.15.2" +version = "0.16.0" dependencies = [ "craft-cms", "kurbo", @@ -1358,7 +1358,7 @@ dependencies = [ [[package]] name = "designcraft-compose" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-color", "designcraft-doc", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "designcraft-doc" -version = "0.15.2" +version = "0.16.0" dependencies = [ "chrono", "designcraft-color", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "designcraft-engine" -version = "0.15.2" +version = "0.16.0" dependencies = [ "caseless", "craft-atomic", @@ -1431,7 +1431,7 @@ dependencies = [ [[package]] name = "designcraft-epub" -version = "0.15.2" +version = "0.16.0" dependencies = [ "chrono", "designcraft-color", @@ -1441,7 +1441,7 @@ dependencies = [ [[package]] name = "designcraft-fonts" -version = "0.15.2" +version = "0.16.0" dependencies = [ "core-text", "harfrust 0.13.3", @@ -1454,7 +1454,7 @@ dependencies = [ [[package]] name = "designcraft-format" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-doc", "designcraft-images", @@ -1466,7 +1466,7 @@ dependencies = [ [[package]] name = "designcraft-geom" -version = "0.15.2" +version = "0.16.0" dependencies = [ "flo_curves", "kurbo", @@ -1479,7 +1479,7 @@ dependencies = [ [[package]] name = "designcraft-idml" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-color", "designcraft-compose", @@ -1494,7 +1494,7 @@ dependencies = [ [[package]] name = "designcraft-images" -version = "0.15.2" +version = "0.16.0" dependencies = [ "craft-cms", "designcraft-color", @@ -1504,6 +1504,7 @@ dependencies = [ "log", "quick-xml 0.41.0", "resvg", + "skrifa 0.47.0", "tiff", "zune-core", "zune-jpeg", @@ -1511,7 +1512,7 @@ dependencies = [ [[package]] name = "designcraft-mcp" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-engine", "designcraft-geom", @@ -1524,7 +1525,7 @@ dependencies = [ [[package]] name = "designcraft-pdf" -version = "0.15.2" +version = "0.16.0" dependencies = [ "chrono", "craft-cms", @@ -1550,7 +1551,7 @@ dependencies = [ [[package]] name = "designcraft-pptx" -version = "0.15.2" +version = "0.16.0" dependencies = [ "chrono", "designcraft-color", @@ -1568,7 +1569,7 @@ dependencies = [ [[package]] name = "designcraft-render" -version = "0.15.2" +version = "0.16.0" dependencies = [ "craft-pdf", "designcraft-color", @@ -1587,7 +1588,7 @@ dependencies = [ [[package]] name = "designcraft-textimport" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-doc", "quick-xml 0.41.0", @@ -1596,7 +1597,7 @@ dependencies = [ [[package]] name = "designcraft-tools" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-color", "designcraft-compose", @@ -1608,7 +1609,7 @@ dependencies = [ [[package]] name = "designcraft-ui-egui" -version = "0.15.2" +version = "0.16.0" dependencies = [ "craft-dialogs", "craft-keymap", @@ -1640,7 +1641,7 @@ dependencies = [ [[package]] name = "designcraft-web" -version = "0.15.2" +version = "0.16.0" dependencies = [ "designcraft-engine", "designcraft-format", @@ -7604,7 +7605,7 @@ checksum = "9440ea3e5aeabb0ac63af70daf835274065238cdd0cec83418f417eae38bacee" [[package]] name = "xtask" -version = "0.15.2" +version = "0.16.0" dependencies = [ "serde_json", ] diff --git a/Cargo.toml b/Cargo.toml index 726874c06..138a07985 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = ["crates/*", "apps/*", "xtask"] default-members = ["crates/*", "apps/designcraft", "apps/designcraft-cli", "xtask"] [workspace.package] -version = "0.15.2" +version = "0.16.0" edition = "2024" license = "MIT OR Apache-2.0" rust-version = "1.95" diff --git a/NOTICE b/NOTICE index 188a3dc76..b96185401 100644 --- a/NOTICE +++ b/NOTICE @@ -32,6 +32,20 @@ list (author, source, license) is in ASSETS.md. AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- Dutch hyphenation patterns, embedded through the hypher crate (feature "dutch"): + hyph-nl.tex 1.1 from hyph-utf8, https://github.com/hyphenation/tex-hyphen. + Copyright (C) 1996 Piet Tutelaers. MIT License: + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: The above copyright notice + and this permission notice shall be included in all copies or substantial portions of the + Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Portuguese hyphenation patterns, embedded through the hypher crate (feature "portuguese"): hyph-pt.tex 1.4 from hyph-utf8, https://github.com/hyphenation/tex-hyphen. Copyright (C) 1987, 1994, 1996, 2015 Pedro J. de Rezende, 1996, 2015 J. Joao Dias Almeida, diff --git a/README.md b/README.md index b2f065153..37e67cfa4 100644 --- a/README.md +++ b/README.md @@ -336,7 +336,16 @@ stand on its own. | | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) | [Website](https://getartcraft.com/apps/lightcraft) | | | **PdfCraft** | Reading, organizing and protecting PDFs | [GitHub](https://github.com/storytold/pdfcraft) | [Website](https://getartcraft.com/apps/pdfcraft) | | | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) | [Website](https://getartcraft.com/apps/effectcraft) | -| | **DesignCraft** | **Page layout and publishing · you are here** | [GitHub](https://github.com/storytold/designcraft) | [Website](https://getartcraft.com/apps/designcraft) | +| | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) | [Website](https://getartcraft.com/apps/designcraft) | +| | **FigCraft** | Interface design and prototyping | [GitHub](https://github.com/storytold/figcraft) | [Website](https://getartcraft.com/apps/figcraft) | +| | **WordCraft** | Word processing and documents | [GitHub](https://github.com/storytold/wordcraft) | [Website](https://getartcraft.com/apps/wordcraft) | +| | **SoundCraft** | Audio recording and editing | [GitHub](https://github.com/storytold/soundcraft) | [Website](https://getartcraft.com/apps/soundcraft) | +| | **DeckCraft** | Presentations and slide decks | [GitHub](https://github.com/storytold/deckcraft) | [Website](https://getartcraft.com/apps/deckcraft) | +| | **CADCraft** | Computer-aided design | [GitHub](https://github.com/storytold/cadcraft) | [Website](https://getartcraft.com/apps/cadcraft) | +| | **GridCraft** | Spreadsheets and data | [GitHub](https://github.com/storytold/gridcraft) | [Website](https://getartcraft.com/apps/gridcraft) | +| | **TextureCraft** | 3D texture painting | [GitHub](https://github.com/storytold/texturecraft) | [Website](https://getartcraft.com/apps/texturecraft) | +| | **Craft Anything** | See how any software works, then build your own | [GitHub](https://github.com/storytold/craft-anything) | [Website](https://getartcraft.com/apps/craft-anything) | +| | **SolidCraft** | Parametric 3D CAD by Tangency Labs (community app) | [GitHub](https://github.com/tangency-labs/solidcraft) | | And [**ArtCraft**](https://getartcraft.com/) itself, our AI image and video studio for artists who want real control. diff --git a/ROADMAP.md b/ROADMAP.md index 3523a83be..d88e8fc36 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -354,7 +354,7 @@ A string without a translation shows in English and fails no check; `cargo xtask | Vietnamese | vi | none | 0% | Also shipped: Czech (99%), Italian (85%), Ukrainian (83%), Polish (99%). -Also shipped: Italian (85%), Ukrainian (83%), Georgian (100%). +Also shipped: Italian (85%), Ukrainian (83%), Georgian (100%), Swedish (99%). ## Upcoming @@ -382,6 +382,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m ## Progress log +- **2026-11-02** · Windows: the custom title bar window stays borderless, so the content is no longer drawn offset by the caption and border (black bars at the top and left, clicks landing off target). The workaround goes when winit carries the fix (storytold/winit#17). No readiness percentage change. - **2026-10-30** · The Color Picker takes an eyedropper: dragged from the picker onto the page, it takes the colour the canvas shows (proofed under Proof Colors). No readiness percentage change. - **2026-10-30** · The Color Picker is laid out as the reference app's: a field and slider for the component chosen, HSB, Lab, RGB and CMYK values, the old colour, and Add CMYK Swatch; Enter and Esc close it once. No readiness percentage change. - **2026-10-18** · Table of Contents gains Create PDF Bookmarks: included headings become nested page destinations, regenerated in their existing outline position on update without replacing or moving surrounding manual bookmarks. The setting survives native and IDML files. No readiness percentage change. @@ -389,7 +390,8 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m Newest first. - **2026-11-01** · Parent page resizing (#1620): Properties, the Page Tool Control panel and on-page handles resize the selected parent page independently of document pages. Stable parent IDs, repeated resizing, anchors and liquid rules are preserved on the current command modules. Inline parent margin editing targets only the selected parent page and preserves opposite-page margins and document overrides; document commands retain their first-page default before the canvas is initialized. No readiness percentage change. - +- **2026-10-31** · `font.list` reports the embedding licence of the face that sets each font's text: its OS/2 `fsType` and what the bits mean (`restrictedLicence`, `bitmapOnly`, `noSubsetting`, `editable`, `previewPrint`; null when the font is missing or has no OS/2 table). A script or host that makes PDFs can check every face, bundled and installed ones included, without reading font files. Export behaviour is unchanged. No readiness percentage change. +- **2026-10-31** · A `.designcraft` file opened from bytes (`file.openBytes` with its file name, as a browser or host passes it) is titled without the extension, as an IDML file opened that way is. Saving it in the browser downloaded `Brochure.designcraft.designcraft`, and the File Name variable showed the doubled name. Browser Open and Drop pass the full file name, so only the engine removes the extension and a repeated suffix is kept in the title. No readiness percentage change. - **2026-10-30** · Import warnings about a story have a Show button: it closes the warnings (the status line keeps them) and selects the story's first frame, fitted in the window. `file.open` returns `warningItems`, the frame each IDML or InDesign warning is about (or null), matching the converter's INDD story numbers (`story 30892`, written to IDML as `u78ac`) and IDML `Self` names to the imported stories. No readiness percentage change. - **2026-10-30** · Parent pages: a running-header variable shows its name in angle brackets on the parent itself (it was blank), as InDesign shows it; on the document pages, and in text with no page, it shows its text as before. No readiness percentage change. - **2026-10-30** · Without facing pages, a page of a multi-page spread shows the parent page in its place, as in InDesign: the second page of a two-page spread shows the parent's second page. Every single-sided page showed the parent's first page, so an InDesign book set up without facing pages but laid out in two-page spreads repeated the left parent page's items (a black heading bar) on its right pages and lost the right parent page's. No readiness percentage change. @@ -406,6 +408,7 @@ Newest first. - **2026-10-20** · Edit › Keyboard Shortcuts is craft-keymap's shared dialog: commands grouped by menu with Show and Filter, recording that asks before taking a key from another command, undo and redo, named shortcut sets (edits of Default become Custom; an imported set becomes a set of its own), an on-screen US keyboard, InDesign Show Set files reviewed before they apply, JSON export and an HTML summary. ui.json keeps the `shortcuts` map earlier versions read, for the active set. No readiness percentage change. - **2026-10-19** · Import InDesign Set… runs on craft-keymap's importer: a set's Window menu panel items (Layers F7, Pages F12, Swatches F5) and Tools items set the panel and tool shortcuts, all of an item's Default keys apply, and the report adds numeric keypad keys read as main keys and likely commands for unmatched items (`window.importShortcuts`). On InDesign's Windows defaults it matches 366 of 1,629 items (was 233) and changes 23 commands. No readiness percentage change. - **2026-10-19** · Keyboard shortcuts run on the shared craft-keymap crate. Panels take shortcuts, with InDesign's defaults where the key is free (Swatches F5, Color F6, Layers F7, Info F8, Stroke F10, Paragraph Styles F11, Character Styles Shift+F11, Pages F12, Align Shift+F7); tool keys are editable in Edit › Keyboard Shortcuts and `window.setShortcut`, and tools sharing a key take turns (B). Saved shortcuts load unchanged. No readiness percentage change. +- **2026-10-17** · HU1: initial Hungarian (`hu` / Magyar) interface localization (updated 2026-11-01): 1,906 catalog entries, four context captions and all 37 tool labels. AI-assisted; the initial catalog was personally reviewed in the app by Veress Róbert, a native Hungarian speaker with over 30 years of DTP experience. Uncatalogued strings keep their English fallback. Hungarian spelling and hyphenation are separate work in #1484. No readiness percentage change. - **2026-10-16** · Edit › Keyboard Shortcuts imports a set saved by InDesign's Show Set (.txt, Windows or Mac key names, UTF-8 or UTF-16): matched commands take its Default shortcuts or lose theirs, other commands give up keys it takes, and a report lists what it changed and the items it could not match (`window.importShortcuts`, #1180). Tool keys stay fixed. No readiness percentage change. - **2026-10-20** · PDF/X-1a:2003 export (craft-libs#194): `file.exportPdf {standard: "x1a"}`, the Export PDF dialog's PDF/X-1a:2003 preset and standard. The PDF/X-4 print file is flattened in its inks by craft-prepress (no transparency; spot, process, overprint and live text kept; complex regions as DeviceN images at the Transparency Flattener preset's resolution), then written as PDF 1.4 with the X-1a identification and checked; `validate-pdf --standard x1a`. Soft drop shadows reach the flattener in their swatch's inks; other soft effects are still RGB images. No readiness percentage change. - **2026-10-20** · Print color (craft-libs#190): CMYK print PDFs blend in DeviceCMYK through craft-pdf's print settings instead of byte rewrites, with the CMYK working space as the output intent in PDF/X-4 only; overprint (Overprint Fill, Stroke and Gap, overprinting text, 100% [Black]) is written as `/op` `/OP` `/OPM 1`; Knockout Group writes `/K true` instead of becoming an image; File › Print prints the PDF Export PDF writes. No readiness percentage change. @@ -539,6 +542,10 @@ Newest first. - **2026-10-16** · Layout: autoflow, inserted pages and new parents follow dragged column guides (#1096). Autoflow sets one frame per dragged column and counts the pages it adds from them; Insert Pages and New Parent keep the custom positions with the column count and gutter; `document.inspect` reports each page's gutter, column rects and whether its columns are custom. No readiness percentage change. - **2026-10-16** · Lock Guides and Lock Column Guides are commands in View ▸ Grids & Guides (`view.lockGuides`, ⌥⌘;, and `view.lockColumnGuides`), so the control channel and MCP reach them. Lock Column Guides is saved with the document, on in new ones, and read from and written to IDML's `ColumnGuideLocked`, which export always wrote as locked (#1096). No readiness percentage change. +- **2026-10-15** · Swedish interface (`sv`, Preferences ▸ General ▸ Interface Language ▸ Svenska): menus, panels, + dialogs and messages, 2,857 of the 2,891 interface strings (99%) in the missing-translations report; the other 34 + show in English. AI-drafted with Claude Code from the English source; spot-checked by a native speaker, not every + string reviewed. No readiness percentage change. - **2026-10-16** · Threading: the loaded text cursor threads into a text frame inside a group (it hit the group and showed it could not thread); a plain click still selects the group (#1075). Gap 27 closed. No readiness percentage change. - **2026-10-16** · Greek text hyphenates. The patterns were never compiled in, so Greek set unhyphenated however narrow the column; `"Greek"`, `"Greek: Greece"`, `el` and `el-GR` all resolve now and ανθρωπος breaks αν-θρω-πος. They are the monotonic patterns (hyph-el-monoton, Dimitrios Filippou, under MIT), which is what polytonic text hyphenates by too. Five of InDesign's ~40 hyphenation languages. No readiness percentage change. - **2026-10-16** · A swatch applied to a placed greyscale or bitmap image colours it, as in InDesign: IDML's `` is read and written, greyscale pixels become a tint of the swatch on opaque white and a bitmap's white lets the frame show through, on screen and in PDF (spot swatches print on their plate). Colour images keep their colours. Applying the swatch from the Swatches panel comes next. No readiness percentage change. diff --git a/apps/designcraft-cli/src/main.rs b/apps/designcraft-cli/src/main.rs index 9ce15674c..a9839fcd3 100644 --- a/apps/designcraft-cli/src/main.rs +++ b/apps/designcraft-cli/src/main.rs @@ -156,7 +156,6 @@ fn report(r: Result<(), String>) -> ExitCode { fn validate_pdf(args: &[String]) -> Result<(), String> { const USAGE: &str = "usage: designcraft-cli validate-pdf FILE.pdf [--standard x4|x1a]"; - const X1A: &[u8] = b"/GTS_PDFXVersion(PDF/X-1:"; let mut path = None; let mut standard = None; let mut it = args.iter(); @@ -172,7 +171,7 @@ fn validate_pdf(args: &[String]) -> Result<(), String> { let standard = match standard.map(designcraft_pdf::Standard::parse) { Some(Some(s)) => s, Some(None) => return Err(USAGE.into()), - None if bytes.windows(X1A.len()).any(|w| w == X1A) => designcraft_pdf::Standard::PdfX1a, + None if designcraft_pdf::pdfx_version(&bytes).is_some_and(|v| v.starts_with("PDF/X-1:")) => designcraft_pdf::Standard::PdfX1a, None => designcraft_pdf::Standard::PdfX4, }; let (name, issues) = match standard { diff --git a/apps/designcraft/Cargo.toml b/apps/designcraft/Cargo.toml index d706374c7..47eafee71 100644 --- a/apps/designcraft/Cargo.toml +++ b/apps/designcraft/Cargo.toml @@ -37,7 +37,8 @@ winit = { version = "0.30", default-features = false, features = ["x11"] } craft-update = { workspace = true } # EnumDisplayDevices (src/gpu.rs): which GPU drives the display, so the window draws on the GPU # that shows it; drawing on a GPU without a monitor reset the display driver. Safe wrappers over -# Win32 (MIT); the `user` feature is User32.dll only. +# Win32 (MIT); the `user` feature is User32.dll only. Also the window frame for the custom title +# bar (src/window_frame.rs, window styles). winsafe = { version = "0.0.29", default-features = false, features = ["user"] } [target.'cfg(target_os = "macos")'.dependencies] diff --git a/apps/designcraft/src/main.rs b/apps/designcraft/src/main.rs index 4b4a1ab7f..ea0747a46 100644 --- a/apps/designcraft/src/main.rs +++ b/apps/designcraft/src/main.rs @@ -22,6 +22,7 @@ mod logging; #[cfg(target_os = "macos")] mod native_menu; mod profile; +mod window_frame; use designcraft_engine::Session; use designcraft_ui_egui::{DesignApp, Services}; @@ -428,6 +429,9 @@ fn main() -> std::process::ExitCode { } app.integrated_titlebar = cfg!(target_os = "macos"); app.custom_titlebar = cfg!(target_os = "windows"); + // The custom title bar's undecorated window must stay borderless, or its caption + // and border offset the content and the pointer on some Windows systems (#1295). + app.services.window_frame = window_frame::service(cc, app.custom_titlebar); if let Some(port) = control_port { let rx = control_server::start(port, cc.egui_ctx.clone()); app = app.with_control(rx); diff --git a/apps/designcraft/src/window_frame.rs b/apps/designcraft/src/window_frame.rs new file mode 100644 index 000000000..c50e1870c --- /dev/null +++ b/apps/designcraft/src/window_frame.rs @@ -0,0 +1,352 @@ +//! Keeps the custom (undecorated) title bar window truly borderless (#1295). +//! +//! winit 0.30 gives an undecorated window the `WS_CAPTION | WS_BORDER` styles and hides the +//! non-client area by spreading the client rect over it (`WM_NCCALCSIZE`). On some systems +//! (reported: Windows 10 LTSB, Intel HD Graphics 4600, 1366 × 768) the desktop compositor still +//! reserves that frame for the window surface: the content is drawn offset by the caption and +//! border, leaving black bars at the window's top-left, while the pointer keeps the un-offset +//! client coordinates, so it no longer points at what is drawn under it. +//! +//! winit 0.27 — before rust-windowing/winit#2419 — simply omitted those styles for undecorated +//! windows, and there was no offset. [`service`] restores that: it strips `WS_CAPTION` and +//! `WS_BORDER` and forces Windows to recalculate the frame. winit puts them back whenever it +//! changes the window flags (maximize, restore, …), so the returned guard checks every frame. +//! +//! Windows sizes a maximize by the frame its styles describe, so a window maximized while its +//! caption is gone is sized without one: its rect covers the whole monitor, taskbar included. +//! The shell reads a caption-less window covering its monitor as a full-screen app and drops the +//! taskbar's backdrop behind it — a black band on stock Windows 11, a glitched unresponsive one +//! under ExplorerPatcher (photocraft#3144). The guard therefore also trims a parked maximize's rect back to +//! the work area plus its own frame, clear of the taskbar. winit pins the client area to the work +//! area either way (`WM_NCCALCSIZE`), so the app's pixels do not move. +//! +//! An auto-hidden taskbar reserves no work area, so that trim leaves the maximize covering the +//! whole monitor, and the shell, taking it for a full-screen app, no longer reveals the taskbar +//! when the pointer reaches its edge (photocraft#4845). On each edge with an auto-hidden taskbar the guard +//! instead stops the window one pixel short of the monitor, as other custom-frame apps do. +//! +//! The long-term fix is in winit itself (storytold/winit#17); this module goes when that lands. +//! +//! The Windows calls go through safe `winsafe` wrappers; the workspace forbids `unsafe`, and +//! winsafe can't wrap a raw handle without it, so the window is found by its handle instead. + +pub use platform::service; + +#[cfg(target_os = "windows")] +mod platform { + use designcraft_ui_egui::WindowFrameFn; + use eframe::wgpu::rwh::{HasWindowHandle, RawWindowHandle}; + use winsafe::prelude::Handle; + use winsafe::{AtomStr, HWND, HwndPlace, POINT, SIZE, co}; + + /// A rect in desktop coordinates: `(left, top, right, bottom)`, right and bottom exclusive. + type Rect = (i32, i32, i32, i32); + + /// A monitor edge. + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + enum Edge { + Left, + Top, + Right, + Bottom, + } + + /// A guard that keeps the window borderless each frame, or `None` when the app uses the + /// system title bar (the window is decorated) or its handle can't be found. + pub fn service(cc: &eframe::CreationContext<'_>, custom_titlebar: bool) -> Option { + if !custom_titlebar { + return None; + } + let target = match cc.window_handle().ok()?.as_raw() { + RawWindowHandle::Win32(h) => h.hwnd.get(), + _ => return None, + }; + let hwnd = find_window(target)?; + reapply(&hwnd); + Some(Box::new(move || reapply(&hwnd))) + } + + /// The top-level window with the given raw handle. `EnumWindows` hands out real `HWND`s, so + /// this matches winit's own window without wrapping a raw handle (which needs `unsafe`). + fn find_window(target: isize) -> Option { + let mut found = None; + let _ = winsafe::EnumWindows(|hwnd| { + if hwnd.ptr() as isize == target { + found = Some(hwnd); + false + } else { + true + } + }); + found + } + + /// One pass of the per-frame guard: the styles winit put back come off again, and a parked + /// maximize stays clear of the taskbar. + fn reapply(hwnd: &HWND) { + strip(hwnd); + keep_clear_of_the_taskbar(hwnd); + } + + /// Removes `WS_CAPTION`/`WS_BORDER` and has Windows recalculate the frame. A no-op once they + /// are gone, so it is cheap to call every frame. + fn strip(hwnd: &HWND) { + let style = hwnd.style(); + let without = borderless(style); + if without.raw() == style.raw() { + return; + } + hwnd.set_style(without); + let _ = hwnd.SetWindowPos( + HwndPlace::None, + POINT::new(), + SIZE::new(), + co::SWP::FRAMECHANGED | co::SWP::NOCOPYBITS | co::SWP::NOMOVE | co::SWP::NOSIZE | co::SWP::NOZORDER | co::SWP::NOACTIVATE, + ); + } + + /// How far a parked maximize reaches past a monitor/work-area edge: the resize + /// border (about 8 pt at 100 %, more with DPI). Past that, a maximized window's rect is not + /// parked but being dragged or snapped, and is left alone. + const FRAME: i32 = 32; + + /// Keep a parked maximize inside all four work-area edges, including a top taskbar. + fn keep_clear_of_the_taskbar(hwnd: &HWND) { + if !hwnd.IsZoomed() { + return; + } + let (Ok(r), Ok(mi)) = (hwnd.GetWindowRect(), hwnd.MonitorFromWindow(co::MONITOR::DEFAULTTONEAREST).GetMonitorInfo()) else { + return; + }; + let (m, w) = (mi.rcMonitor, mi.rcWork); + let (rect, monitor, work) = ((r.left, r.top, r.right, r.bottom), (m.left, m.top, m.right, m.bottom), (w.left, w.top, w.right, w.bottom)); + // The taskbars (a couple of `FindWindowEx` calls) are only looked up while the window + // covers the whole monitor, which a trimmed maximize no longer does. + let Some((left, top, right, bottom)) = clamped_rect(rect, monitor, work) + .or_else(|| covers(rect, monitor).then(|| short_of_autohide_taskbars(rect, monitor, work, &taskbar_edges(monitor))).flatten()) + else { + return; + }; + let (Some(width), Some(height)) = (right.checked_sub(left), bottom.checked_sub(top)) else { + return; + }; + // Moving the outer frame while winit pins the client rect to the work area must + // not copy the old frame's pixels into the custom title bar. + let _ = hwnd.SetWindowPos( + HwndPlace::None, + POINT { x: left, y: top }, + SIZE { cx: width, cy: height }, + co::SWP::FRAMECHANGED | co::SWP::NOCOPYBITS | co::SWP::NOZORDER | co::SWP::NOACTIVATE, + ); + let _ = hwnd.InvalidateRect(None, false); + } + + /// Return the corrected outer rect in desktop coordinates, preserving the resize border. + /// Each edge must be parked just outside either the monitor or work-area edge. Accepting + /// both makes the guard idempotent and handles Windows already correcting some edges. + /// Dragged/snapped windows are left alone; no monitor-origin or DPI assumptions are needed. + fn clamped_rect(rect: (i32, i32, i32, i32), monitor: (i32, i32, i32, i32), work: (i32, i32, i32, i32)) -> Option<(i32, i32, i32, i32)> { + let (l, t, r, b) = rect; + let (ml, mt, mr, mb) = monitor; + let (wl, wt, wr, wb) = work; + if ml >= mr || mt >= mb || wl < ml || wt < mt || wr > mr || wb > mb || wl >= wr || wt >= wb { + return None; + } + // Infer the frame from an edge without a taskbar. On an obstructed edge, the + // monitor and work-area offsets can both look like valid borders (e.g. auto-hide). + let border = [ + (ml == wl).then(|| ml.checked_sub(l)).flatten(), + (mt == wt).then(|| mt.checked_sub(t)).flatten(), + (mr == wr).then(|| r.checked_sub(mr)).flatten(), + (mb == wb).then(|| b.checked_sub(mb)).flatten(), + ] + .into_iter() + .flatten() + .filter(|n| (0..=FRAME).contains(n)) + .min()?; + let parked = |monitor: Option, work: Option| monitor == Some(border) || work == Some(border); + if !parked(ml.checked_sub(l), wl.checked_sub(l)) + || !parked(mt.checked_sub(t), wt.checked_sub(t)) + || !parked(r.checked_sub(mr), r.checked_sub(wr)) + || !parked(b.checked_sub(mb), b.checked_sub(wb)) + { + return None; + } + let corrected = (wl.checked_sub(border)?, wt.checked_sub(border)?, wr.checked_add(border)?, wb.checked_add(border)?); + (corrected != rect).then_some(corrected) + } + + /// Whether `rect` reaches every edge of `monitor`: what the shell takes for a full-screen app. + fn covers(rect: Rect, monitor: Rect) -> bool { + rect.0 <= monitor.0 && rect.1 <= monitor.1 && rect.2 >= monitor.2 && rect.3 >= monitor.3 + } + + /// The edges of `monitor` that have a taskbar (the primary `Shell_TrayWnd` or a secondary + /// monitor's `Shell_SecondaryTrayWnd`), shown or hidden. + fn taskbar_edges(monitor: Rect) -> Vec { + let mut edges = Vec::new(); + for class in ["Shell_TrayWnd", "Shell_SecondaryTrayWnd"] { + let mut after: Option = None; + // One taskbar per monitor; the bound only guards against a misbehaving shell. + for _ in 0..64 { + let Ok(Some(tray)) = HWND::NULL.FindWindowEx(after.as_ref(), AtomStr::from_str(class), None) else { + break; + }; + if let Ok(r) = tray.GetWindowRect() { + edges.extend(taskbar_edge((r.left, r.top, r.right, r.bottom), monitor)); + } + after = Some(tray); + } + } + edges + } + + /// The edge of `monitor` a taskbar with rect `taskbar` sits on: the one nearest its centre, + /// or `None` when it is on another monitor. An auto-hidden taskbar is parked mostly past its + /// edge with a sliver left on screen, so its centre may lie outside the monitor. + fn taskbar_edge(taskbar: Rect, monitor: Rect) -> Option { + let (tl, tt, tr, tb) = (i64::from(taskbar.0), i64::from(taskbar.1), i64::from(taskbar.2), i64::from(taskbar.3)); + let (ml, mt, mr, mb) = (i64::from(monitor.0), i64::from(monitor.1), i64::from(monitor.2), i64::from(monitor.3)); + if tl >= tr || tt >= tb || ml >= mr || mt >= mb || tr <= ml || tl >= mr || tb <= mt || tt >= mb { + return None; + } + // Doubled centre and distances, so nothing rounds. + let (cx, cy) = (tl + tr, tt + tb); + [(Edge::Left, cx - 2 * ml), (Edge::Top, cy - 2 * mt), (Edge::Right, 2 * mr - cx), (Edge::Bottom, 2 * mb - cy)] + .into_iter() + .min_by_key(|&(_, distance)| distance) + .map(|(edge, _)| edge) + } + + /// A maximize covering its monitor, trimmed to stop one pixel short of each edge where a + /// taskbar reserves no work area (it auto-hides), so the shell still reveals it there. + /// `None` when there is nothing to trim. + fn short_of_autohide_taskbars(rect: Rect, monitor: Rect, work: Rect, taskbars: &[Edge]) -> Option { + if !covers(rect, monitor) { + return None; + } + let (mut l, mut t, mut r, mut b) = rect; + for edge in taskbars { + match edge { + Edge::Left if work.0 == monitor.0 => l = monitor.0.checked_add(1)?, + Edge::Top if work.1 == monitor.1 => t = monitor.1.checked_add(1)?, + Edge::Right if work.2 == monitor.2 => r = monitor.2.checked_sub(1)?, + Edge::Bottom if work.3 == monitor.3 => b = monitor.3.checked_sub(1)?, + _ => {} + } + } + let trimmed = (l, t, r, b); + (l < r && t < b && trimmed != rect).then_some(trimmed) + } + + /// `style` without the OS title bar and frame (`WS_CAPTION`, which already includes + /// `WS_BORDER`). The sizing border (`WS_THICKFRAME`) stays, so edge resizing and Aero snap + /// keep working, as they did with winit 0.27's undecorated windows. + fn borderless(style: co::WS) -> co::WS { + style & !(co::WS::CAPTION | co::WS::BORDER) + } + + #[cfg(test)] + mod tests { + use super::{Edge, borderless, clamped_rect, short_of_autohide_taskbars, taskbar_edge}; + use winsafe::co; + + #[test] + fn the_borderless_style_drops_the_caption_and_border_only() { + // `WS_CAPTION` is 0x00c0_0000 and already contains `WS_BORDER` (0x0080_0000). + let decorated = co::WS::CAPTION | co::WS::BORDER | co::WS::SYSMENU | co::WS::THICKFRAME | co::WS::MAXIMIZEBOX | co::WS::MINIMIZEBOX; + let bare = borderless(decorated); + assert!(!bare.has(co::WS::CAPTION), "caption gone"); + assert!(!bare.has(co::WS::BORDER), "border gone"); + assert!(bare.has(co::WS::THICKFRAME), "edge resizing kept"); + assert!(bare.has(co::WS::MAXIMIZEBOX) && bare.has(co::WS::SYSMENU), "window buttons kept"); + // Already borderless: unchanged, so the per-frame call does nothing. + assert_eq!(bare.raw(), borderless(bare).raw()); + } + + #[test] + fn a_maximize_respects_taskbars_on_every_edge() { + let monitor = (0, 0, 1920, 1080); + let rect = (-8, -8, 1928, 1088); + for (work, expected) in [ + ((0, 0, 1920, 1046), (-8, -8, 1928, 1054)), + ((0, 48, 1920, 1080), (-8, 40, 1928, 1088)), + ((0, 2, 1920, 1080), (-8, -6, 1928, 1088)), + ((0, 0, 1920, 1078), (-8, -8, 1928, 1086)), + ((48, 0, 1920, 1080), (40, -8, 1928, 1088)), + ((0, 0, 1872, 1080), (-8, -8, 1880, 1088)), + ] { + assert_eq!(clamped_rect(rect, monitor, work), Some(expected)); + assert_eq!(clamped_rect(expected, monitor, work), None, "already corrected"); + } + } + + #[test] + fn a_top_taskbar_keeps_its_offset_at_other_origins_and_frame_sizes() { + let monitor = (-1920, -1080, 0, 0); + let work = (-1920, -1032, 0, 0); + for border in [0, 8, 16, 32] { + let rect = (-1920 - border, -1080 - border, border, border); + let expected = (-1920 - border, -1032 - border, border, border); + assert_eq!(clamped_rect(rect, monitor, work), Some(expected)); + assert_eq!(clamped_rect(expected, monitor, work), None); + } + } + + #[test] + fn a_maximize_without_a_reserved_taskbar_is_left_alone() { + let monitor = (0, 0, 1920, 1080); + assert_eq!(clamped_rect((-8, -8, 1928, 1088), monitor, monitor), None); + } + + #[test] + fn a_maximize_being_dragged_or_snapped_is_left_alone() { + let monitor = (0, 0, 1920, 1080); + let work = (0, 48, 1920, 1080); + assert_eq!(clamped_rect((100, 200, 1100, 900), monitor, work), None, "moved"); + assert_eq!(clamped_rect((-500, -8, 1428, 1088), monitor, work), None, "dragged"); + assert_eq!(clamped_rect((0, 48, 960, 1080), monitor, work), None, "half-screen"); + } + + #[test] + fn a_maximize_leaves_a_pixel_strip_on_an_auto_hidden_taskbar_edge() { + // photocraft#4845: an auto-hidden taskbar reserves no work area. + let monitor = (0, 0, 1920, 1080); + let rect = (-8, -8, 1928, 1088); + for (edge, expected) in [ + (Edge::Bottom, (-8, -8, 1928, 1079)), + (Edge::Top, (-8, 1, 1928, 1088)), + (Edge::Left, (1, -8, 1928, 1088)), + (Edge::Right, (-8, -8, 1919, 1088)), + ] { + assert_eq!(short_of_autohide_taskbars(rect, monitor, monitor, &[edge]), Some(expected)); + assert_eq!(short_of_autohide_taskbars(expected, monitor, monitor, &[edge]), None, "already trimmed"); + } + assert_eq!(short_of_autohide_taskbars(rect, monitor, monitor, &[]), None, "no taskbar"); + // A taskbar that reserves its work area is the clamp's job. + assert_eq!(short_of_autohide_taskbars(rect, monitor, (0, 0, 1920, 1032), &[Edge::Bottom]), None); + assert_eq!(short_of_autohide_taskbars((0, 0, 960, 1080), monitor, monitor, &[Edge::Bottom]), None, "half-screen"); + } + + #[test] + fn a_taskbar_sits_on_the_monitor_edge_nearest_its_centre() { + let monitor = (0, 0, 1920, 1080); + assert_eq!(taskbar_edge((0, 1032, 1920, 1080), monitor), Some(Edge::Bottom), "shown"); + assert_eq!(taskbar_edge((0, 1078, 1920, 1126), monitor), Some(Edge::Bottom), "auto-hidden"); + assert_eq!(taskbar_edge((0, -46, 1920, 2), monitor), Some(Edge::Top)); + assert_eq!(taskbar_edge((-60, 0, 2, 1080), monitor), Some(Edge::Left)); + assert_eq!(taskbar_edge((1918, 0, 1980, 1080), monitor), Some(Edge::Right)); + assert_eq!(taskbar_edge((1920, 1032, 3840, 1080), monitor), None, "other monitor"); + assert!(taskbar_edge((i32::MIN, i32::MIN, i32::MAX, i32::MAX), monitor).is_some(), "no overflow"); + } + } +} + +#[cfg(not(target_os = "windows"))] +mod platform { + use designcraft_ui_egui::WindowFrameFn; + + pub fn service(_cc: &eframe::CreationContext<'_>, _custom_titlebar: bool) -> Option { + None + } +} diff --git a/contributors/people.toml b/contributors/people.toml index cd1cb022a..3e1b92d94 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -63,11 +63,23 @@ real_name = "Marco Arnulfo" display_name = "Marco Arnulfo" sync_github_name = false +[people.macrobi] +real_name = "Veress Róbert" +display_name = "Veress Róbert" +sync_github_name = false + [people.4waymedia] real_name = "Paul Gemignani" [people.skylartaylor] display_name = "skylartaylor" +[people.y-az] +real_name = "Youssef Azriouil" +display_name = "youssef" + [people.dylanmtaylor] sync_github_name = true + +[people.Tom-R-Main] +sync_github_name = true diff --git a/crates/color/src/lib.rs b/crates/color/src/lib.rs index d085c5c48..c83d93f0c 100644 --- a/crates/color/src/lib.rs +++ b/crates/color/src/lib.rs @@ -118,6 +118,8 @@ impl Color { } else { 60.0 * ((r - g) / d + 4.0) }; + // A tiny negative `rem_euclid` input can round up to exactly 6.0 (hue 360). + let h = if h >= 360.0 { 0.0 } else { h }; let s = if max <= 0.0 { 0.0 } else { d / max }; [h, s, max] } @@ -251,6 +253,12 @@ impl Paint { mod tests { use super::*; + #[test] + fn hsb_hue_stays_below_360() { + let h = Color::rgb(1.0, 0.0, 1e-8).to_hsb()[0]; + assert!((0.0..360.0).contains(&h), "hue {h}"); + } + #[test] fn hex_roundtrip() { let c = Color::from_hex("#ff8000").unwrap(); diff --git a/crates/compose/Cargo.toml b/crates/compose/Cargo.toml index ea6a0bf42..37092adb8 100644 --- a/crates/compose/Cargo.toml +++ b/crates/compose/Cargo.toml @@ -21,7 +21,7 @@ log = { workspace = true } regex = { workspace = true } fancy-regex = { workspace = true } miniz_oxide = "0.8" -hypher = { version = "0.1.8", default-features = false, features = ["alloc", "french", "german", "greek", "italian", "portuguese", "spanish", "norwegian"] } +hypher = { version = "0.1.8", default-features = false, features = ["alloc", "dutch", "french", "german", "greek", "italian", "portuguese", "spanish", "norwegian"] } [dev-dependencies] designcraft-fonts = { workspace = true, features = ["testing"] } diff --git a/crates/compose/src/hyphen.rs b/crates/compose/src/hyphen.rs index be9e7b7e6..b63c1b110 100644 --- a/crates/compose/src/hyphen.rs +++ b/crates/compose/src/hyphen.rs @@ -3,7 +3,7 @@ //! `hyph-es.tex` 5.0 from hyph-utf8, MIT; Portuguese is `hyph-pt.tex` 1.4 from hyph-utf8 (Pedro J. //! de Rezende, J. Joao Dias Almeida, Leonardo Araujo, Aline Benevides), BSD-3-Clause; Norwegian is //! `hyph-no.tex` from hyph-utf8 (Rune Kleveland, Ole Michael Selberg), permissive (see NOTICE); -//! Greek is `hyph-el-monoton.tex` 5.0 from hyph-utf8 (Dimitrios Filippou), LPPL or MIT, taken +//! Dutch is Piet Tutelaers's `hyph-nl.tex` 1.1 from hyph-utf8, MIT; Greek is `hyph-el-monoton.tex` 5.0 from hyph-utf8 (Dimitrios Filippou), LPPL or MIT, taken //! under MIT. Those are the **monotonic** patterns, which is what `hypher` maps `el` to, so //! polytonic text hyphenates by them as well. French is `hyph-fr.tex` 2.13 from hyph-utf8 (Daniel //! Flipo, Bernard Gaulle, Arthur Reutenauer), MIT; Italian is `hyph-it.tex` 4.9 from hyph-utf8 @@ -588,6 +588,28 @@ mod tests { assert_eq!(marked("dell'impaginazione", it), "dell'im-pa-gi-na-zio-ne", "after an elision"); } + #[test] + fn dutch_uses_the_hyph_nl_patterns() { + let nl = Lang::for_language("Dutch").unwrap(); + // InDesign writes the 2005 spelling as `nl_NL_2005`. + assert_eq!(nl, Lang::for_language("nl_NL_2005").unwrap()); + assert_ne!(nl, Lang::for_language("Spanish").unwrap()); + let h = |w: &str| { + let pts = hyphen_points_in(w, &Limits::default(), nl); + w.chars().enumerate().map(|(i, c)| if pts.contains(&i) { format!("-{c}") } else { c.to_string() }).collect::() + }; + assert_eq!(h("uitspraak"), "uit-spraak"); + assert_eq!(h("kinderen"), "kin-de-ren"); + assert_eq!(h("leesvaardigheid"), "lees-vaar-dig-heid"); + assert_eq!(h("zelfvertrouwen"), "zelf-ver-trou-wen"); + assert_eq!(h("Ontwikkelen"), "Ont-wik-ke-len"); + // Long compounds break at their parts and at the syllables inside them. + assert_eq!(h("arbeidsongeschiktheidsverzekering"), "ar-beids-on-ge-schikt-heids-ver-ze-ke-ring"); + assert_eq!(h("ziekenhuisopname"), "zie-ken-huis-op-na-me"); + assert_eq!(h("gemeenteraadsverkiezingen"), "ge-meen-te-raads-ver-kie-zin-gen"); + assert_eq!(h("kinderdagverblijf"), "kin-der-dag-ver-blijf"); + } + #[test] fn heuristic_fallback() { let c: Vec = "happen".chars().collect(); diff --git a/crates/engine/src/cmd/file/bytes.rs b/crates/engine/src/cmd/file/bytes.rs index 0946205a8..f42925034 100644 --- a/crates/engine/src/cmd/file/bytes.rs +++ b/crates/engine/src/cmd/file/bytes.rs @@ -27,6 +27,16 @@ pub fn with_document_extension(path: &str) -> String { format!("{path}.{}", designcraft_format::EXTENSION) } +/// `name` without a trailing `.designcraft` (any case): the title of a document opened from bytes +/// under its file name. Save, Save As and the File Name variable add the extension back, so a title +/// that kept it would name the file `Brochure.designcraft.designcraft`. A bare `.designcraft` stays. +pub(super) fn without_native_extension(name: &str) -> &str { + match name.rsplit_once('.') { + Some((stem, ext)) if !stem.is_empty() && ext.eq_ignore_ascii_case(designcraft_format::EXTENSION) => stem, + _ => name, + } +} + /// Whether `bytes` are a document `file.open` reads: a DesignCraft package or an IDML package. /// The first [`DOCUMENT_SNIFF_BYTES`] of a file are enough for packages that start with their /// `mimetype` entry, as both formats write them. diff --git a/crates/engine/src/cmd/file/open.rs b/crates/engine/src/cmd/file/open.rs index 75a7ce627..4e90f30fb 100644 --- a/crates/engine/src/cmd/file/open.rs +++ b/crates/engine/src/cmd/file/open.rs @@ -1,6 +1,6 @@ #[cfg(test)] use super::bytes::{PREVIEW_PX, to_bytes}; -use super::bytes::{base64_decode, load_bytes}; +use super::bytes::{base64_decode, load_bytes, without_native_extension}; use super::{Arc, DocState, Document, EngineError, Result, Session, Value, bad, json, str_param}; pub(super) fn has_recent(s: &Session) -> std::result::Result<(), String> { @@ -150,7 +150,8 @@ pub(super) fn file_open_bytes(s: &mut Session, p: &Value) -> Result { let (mut d, warnings) = load_bytes(&b)?; crate::cmd::datamerge::resolve_sources_on_open(&mut d, None); if let Some(n) = str_param(p, "name") { - d.title = n.to_string(); + // Titled as an IDML file opened from bytes is: without its extension. + d.title = without_native_extension(n).to_string(); } let i = s.add_document(DocState::new(d, None)); Ok(json!({"index": i, "warnings": warnings})) @@ -413,6 +414,41 @@ mod document_fonts_tests { } } +#[cfg(test)] +mod open_bytes_tests { + use serde_json::json; + + use crate::Session; + + /// A `.designcraft` file opened from bytes under its file name (a browser or host passes the + /// name it has) is titled without the extension, as an IDML file is, so saving it gives + /// `Brochure.designcraft` and not `Brochure.designcraft.designcraft`. + #[test] + fn open_bytes_titles_a_native_document_without_its_extension() { + let mut s = Session::new(); + s.execute("file.new", &json!({})).unwrap(); + let native = s.execute("file.serialize", &json!({})).unwrap(); + for (name, title) in [ + ("Brochure.designcraft", "Brochure"), + ("Brochure.DesignCraft", "Brochure"), + ("Brochure", "Brochure"), + ("Brochure.v2", "Brochure.v2"), + ("Brochure.designcraft.designcraft", "Brochure.designcraft"), + (".designcraft", ".designcraft"), + // Names that aren't ASCII: cutting the extension's length off the end of the last one + // would land inside its `é`. + ("Präsentation.designcraft", "Präsentation"), + ("日本.DESIGNCRAFT", "日本"), + ("é", "é"), + ("édesigncraft", "édesigncraft"), + ] { + let r = s.execute("file.openBytes", &json!({"name": name, "base64": native["base64"]})).unwrap(); + let st = &s.documents()[r["index"].as_u64().unwrap() as usize]; + assert_eq!((st.doc.title.as_str(), st.title()), (title, title.to_string()), "{name}"); + } + } +} + #[cfg(test)] mod recent_tests { use serde_json::json; diff --git a/crates/engine/src/cmd/fonts.rs b/crates/engine/src/cmd/fonts.rs index ee80eb914..77cebe369 100644 --- a/crates/engine/src/cmd/fonts.rs +++ b/crates/engine/src/cmd/fonts.rs @@ -14,7 +14,7 @@ use crate::{Result, Session}; pub fn specs() -> Vec { vec![ - cmd!(query "font.list", "Fonts in Document", [], None, "{} → [{family, style, characters, missing, styleMissing, source: bundled|installed|document|added (null when missing), matchStatus: exact|styleSubstitute|missing, resolvedFamily, resolvedStyle, replacementFamily, replacementStyle}] (missing first)", has_doc, |s, _| { + cmd!(query "font.list", "Fonts in Document", [], None, "{} → [{family, style, characters, missing, styleMissing, source: bundled|installed|document|added (null when missing), matchStatus: exact|styleSubstitute|missing, resolvedFamily, resolvedStyle, replacementFamily, replacementStyle, fsType, restrictedLicence, bitmapOnly, noSubsetting, editable, previewPrint (the OS/2 fsType embedding bits of the face that sets the text and what they mean; null when missing or the face has no OS/2 table)}] (missing first)", has_doc, |s, _| { Ok(Value::Array(list(&s.doc()?.doc))) }), cmd!( @@ -75,6 +75,19 @@ pub(super) struct UsedFont { pub resolved_style: String, pub replacement_family: String, pub replacement_style: String, + /// The OS/2 `fsType` of the face that sets the text (`resolved_*`); None when missing or the + /// face has no OS/2 table (as are the bits below). + pub fs_type: Option, + /// Restricted License embedding (bit 1 without bits 2–3). + pub restricted_licence: Option, + /// Bitmap embedding only (bit 9). + pub bitmap_only: Option, + /// No subsetting (bit 8): the font may only be embedded whole. + pub no_subsetting: Option, + /// Editable embedding (bit 3). + pub editable: Option, + /// Preview & Print embedding (bit 2). + pub preview_print: Option, } fn list(d: &Document) -> Vec { @@ -124,6 +137,8 @@ pub(super) fn used_fonts(d: &Document) -> Vec { let resolved = db.face(&family, &style); let characters: Vec = characters.into_iter().filter(|c| !('\u{E000}'..='\u{E1FF}').contains(c)).collect(); let replacement = db.replacement_face(&family, &style, &characters); + let fs_type = (!missing).then(|| resolved.fs_type()).flatten(); + let bit = |mask: u16| fs_type.map(|t| t & mask != 0); let source = (!missing).then(|| match db.face(&family, &style).source { FontSource::Bundled => "bundled", FontSource::Installed(_) => "installed", @@ -148,6 +163,12 @@ pub(super) fn used_fonts(d: &Document) -> Vec { resolved_style: resolved.style.clone(), replacement_family: replacement.family.clone(), replacement_style: replacement.style.clone(), + fs_type, + restricted_licence: fs_type.map(|_| resolved.restricted_licence()), + bitmap_only: bit(0x0200), + no_subsetting: bit(0x0100), + editable: bit(0x0008), + preview_print: bit(0x0004), } }) .collect(); @@ -297,6 +318,55 @@ mod tests { assert_eq!(before, s.execute("font.list", &json!({})).unwrap()); } + /// `font.list` reports each face's OS/2 fsType and what its bits allow, so a caller can + /// refuse a face whose licence doesn't allow the export it is about to make. + #[test] + fn font_list_reports_the_embedding_licence_bits() { + use designcraft_fonts::testing::{font_with, with_fs_type, with_table_len}; + const FAMILY: &str = "DocFont List FsType"; + const FS_TYPES: [u16; 3] = [0x0002, 0x0108, 0x0204]; + for fs_type in FS_TYPES { + designcraft_fonts::FontDb::global() + .add_font(with_fs_type(font_with(&format!("{FAMILY} {fs_type:04x}"), &['W']).unwrap(), fs_type).unwrap()); + } + // An OS/2 table cut to nothing can't be read: as if the font had none. + designcraft_fonts::FontDb::global().add_font(with_table_len(font_with(&format!("{FAMILY} no OS/2"), &['W']).unwrap(), b"OS/2", 0).unwrap()); + let mut s = Session::new(); + s.execute("file.new", &json!({})).unwrap(); + // "W W W W Plain Gone": each W in one of the fonts above, Plain in the default (bundled) + // font, Gone in a family that isn't available. + let r = s.execute("frame.create", &json!({"rect": [72, 72, 400, 300], "content": "text", "text": "W W W W Plain Gone"})).unwrap(); + let sid = s.doc().unwrap().doc.item(designcraft_doc::ItemId(r["id"].as_u64().unwrap())).unwrap().text_frame().unwrap().story; + let set = |s: &mut Session, at: usize, end: usize, family: &str| { + s.execute("text.select", &json!({"story": sid.0, "anchor": at, "focus": end})).unwrap(); + s.execute("type.char", &json!({"fontFamily": family, "fontStyle": "Regular"})).unwrap(); + }; + for (i, fs_type) in FS_TYPES.into_iter().enumerate() { + set(&mut s, i * 2, i * 2 + 1, &format!("{FAMILY} {fs_type:04x}")); + } + set(&mut s, 6, 7, &format!("{FAMILY} no OS/2")); + set(&mut s, 14, 18, "Nonexistent Sans"); + let l = s.execute("font.list", &json!({})).unwrap(); + let rows = l.as_array().unwrap(); + let entry = |family: &str| rows.iter().find(|f| f["family"] == family).unwrap_or_else(|| panic!("{family}: {l}")); + let bits = |e: &Value| ["fsType", "restrictedLicence", "bitmapOnly", "noSubsetting", "editable", "previewPrint"].map(|k| e[k].clone()); + let (t, f) = (json!(true), json!(false)); + assert_eq!(entry(&format!("{FAMILY} 0002"))["source"], "added", "{l}"); + assert_eq!(bits(entry(&format!("{FAMILY} 0002"))), [json!(0x0002), t.clone(), f.clone(), f.clone(), f.clone(), f.clone()], "{l}"); + assert_eq!(bits(entry(&format!("{FAMILY} 0108"))), [json!(0x0108), f.clone(), f.clone(), t.clone(), t.clone(), f.clone()], "{l}"); + assert_eq!(bits(entry(&format!("{FAMILY} 0204"))), [json!(0x0204), f.clone(), t.clone(), f.clone(), f.clone(), t.clone()], "{l}"); + // The bundled fonts are OFL: installable embedding, every bit clear. + let bundled = rows.iter().find(|r| r["source"] == "bundled").unwrap_or_else(|| panic!("no bundled face: {l}")); + assert_eq!(bits(bundled), [json!(0), f.clone(), f.clone(), f.clone(), f.clone(), f], "{l}"); + // A face without an OS/2 table doesn't say what its licence allows. + assert_eq!(entry(&format!("{FAMILY} no OS/2"))["missing"], false, "{l}"); + assert_eq!(bits(entry(&format!("{FAMILY} no OS/2"))), [(); 6].map(|()| Value::Null), "{l}"); + // A missing face has no file to read. + let missing = entry("Nonexistent Sans"); + assert_eq!(missing["missing"], true, "{l}"); + assert_eq!(bits(missing), [(); 6].map(|()| Value::Null), "{l}"); + } + #[test] fn find_and_replace_font() { let mut s = Session::new(); diff --git a/crates/engine/src/cmd/mathexpr.rs b/crates/engine/src/cmd/mathexpr.rs index e5342f79c..d6b4a9e95 100644 --- a/crates/engine/src/cmd/mathexpr.rs +++ b/crates/engine/src/cmd/mathexpr.rs @@ -35,6 +35,11 @@ fn math_item(d: &mut designcraft_doc::Document, latex: &str, size: f64, lid: des it } +/// The `size` parameter in points: 12 by default (also for non-finite values), clamped to 2..=400. +fn size_param(p: &Value) -> f64 { + p.get("size").and_then(Value::as_f64).filter(|v| v.is_finite()).unwrap_or(12.0).clamp(2.0, 400.0) +} + pub fn specs() -> Vec { vec![ cmd!( @@ -48,7 +53,7 @@ pub fn specs() -> Vec { ), cmd!(query "math.svg", "Math Expression SVG", [], None, "{latex, size?} → {svg, width, height} — typeset without placing", has_doc, |_s, p| { let latex = str_param(p, "latex").ok_or_else(|| bad("math.svg", "`latex` required"))?; - let (svg, (w, h)) = crate::math::to_svg(latex, p.get("size").and_then(Value::as_f64).unwrap_or(12.0)); + let (svg, (w, h)) = crate::math::to_svg(latex, size_param(p)); Ok(json!({"svg": String::from_utf8_lossy(&svg), "width": w, "height": h})) }), ] @@ -56,7 +61,7 @@ pub fn specs() -> Vec { fn insert(s: &mut Session, p: &Value) -> Result { let latex = str_param(p, "latex").ok_or_else(|| bad("math.insert", "`latex` required"))?.to_string(); - let size = p.get("size").and_then(Value::as_f64).unwrap_or(12.0).clamp(2.0, 400.0); + let size = size_param(p); let lid = s.doc()?.active_layer; // Edit an existing expression in place. if let Some(id) = super::id_param(p, "id") { @@ -102,6 +107,24 @@ mod tests { use crate::Session; + #[test] + fn math_svg_clamps_size_like_insert() { + let mut s = Session::new(); + s.execute("file.new", &json!({})).unwrap(); + let dims = |s: &mut Session, size: f64| { + let r = s.execute("math.svg", &json!({"latex": "x", "size": size})).unwrap(); + (r["width"].as_f64().unwrap(), r["height"].as_f64().unwrap()) + }; + let (w2, h2) = dims(&mut s, 2.0); + let (w400, h400) = dims(&mut s, 400.0); + for size in [0.0, -5.0, 1e-300] { + assert_eq!(dims(&mut s, size), (w2, h2), "size {size}"); + } + for size in [1e9, 1e300] { + assert_eq!(dims(&mut s, size), (w400, h400), "size {size}"); + } + } + #[test] fn math_places_inline_and_as_frames() { let mut s = Session::new(); diff --git a/crates/engine/src/math.rs b/crates/engine/src/math.rs index 468ce1c5a..e0d520648 100644 --- a/crates/engine/src/math.rs +++ b/crates/engine/src/math.rs @@ -900,7 +900,13 @@ fn layout(f: &Fonts, n: &Node, size: f64) -> MBox { pub fn to_svg(latex: &str, size: f64) -> (Vec, (f64, f64)) { let db = FontDb::global(); let f = Fonts { upright: db.face(FAMILY, "Regular"), italic: db.face(FAMILY, "Italic"), fallback: db.face(FALLBACK, "Regular") }; - let b = layout(&f, &parse(latex), size); + // XML 1.0 forbids most control characters and U+FFFE/U+FFFF; drop them before layout so + // they take no width either. + let latex: String = latex + .chars() + .filter(|c| matches!(c, '\t' | '\n' | '\r' | '\u{20}'..='\u{D7FF}' | '\u{E000}'..='\u{FFFD}' | '\u{10000}'..='\u{10FFFF}')) + .collect(); + let b = layout(&f, &parse(&latex), size); let pad = size * 0.1; let (w, h) = (b.w + 2.0 * pad, b.asc + b.desc + 2.0 * pad); let base = pad + b.asc; diff --git a/crates/engine/src/math/tests.rs b/crates/engine/src/math/tests.rs index 9d1e75884..ddc006be6 100644 --- a/crates/engine/src/math/tests.rs +++ b/crates/engine/src/math/tests.rs @@ -474,3 +474,12 @@ fn deep_nodes_drop_when_replaced_or_owned_by_unwinding_continuations() { }); assert!(result.is_err(), "the intentional panic must actually unwind the owned frames"); } + +#[test] +fn svg_drops_control_characters_forbidden_by_xml() { + let (svg, _) = to_svg("a\u{1}b\u{c}", 12.0); + let svg = String::from_utf8(svg).unwrap(); + assert!(!svg.chars().any(|c| c < ' ' && !matches!(c, '\t' | '\n' | '\r')), "control character in SVG: {svg:?}"); + // The dropped characters take no width either. + assert_eq!(to_svg("a\u{1}b\u{c}", 12.0).1, to_svg("ab", 12.0).1); +} diff --git a/crates/engine/src/script.rs b/crates/engine/src/script.rs index 4a66ff87f..bcc4f8fe9 100644 --- a/crates/engine/src/script.rs +++ b/crates/engine/src/script.rs @@ -26,7 +26,8 @@ pub struct Step { pub fn parse(text: &str) -> Result, String> { // Windows tools save "UTF-8 with BOM"; `trim` keeps U+FEFF, which then became part of the // first command id. - let t = text.trim_start_matches('\u{feff}').trim(); + let body = text.trim_start_matches('\u{feff}'); + let t = body.trim(); if t.starts_with('[') { let v: Value = serde_json::from_str(t).map_err(|e| format!("script: {e}"))?; return v @@ -38,7 +39,8 @@ pub fn parse(text: &str) -> Result, String> { .collect(); } let mut out = Vec::new(); - for (n, line) in t.lines().enumerate() { + // Number lines from the untrimmed text so leading blank lines still count. + for (n, line) in body.lines().enumerate() { let l = line.trim(); if l.is_empty() || l.starts_with('#') || l.starts_with("//") { continue; @@ -185,6 +187,12 @@ impl crate::Session { mod tests { use super::*; + #[test] + fn leading_blank_lines_keep_line_numbers() { + let e = parse("\n\n# c\nfile.new\nframe.create {bad").unwrap_err(); + assert!(e.contains("line 5"), "{e}"); + } + #[test] fn parses_all_forms() { let a = parse(r#"[{"command": "file.new"}, {"command": "frame.create", "params": {"rect": [0, 0, 10, 10]}}]"#).unwrap(); diff --git a/crates/epub/src/html.rs b/crates/epub/src/html.rs index ce9d7176c..7f7fbe26f 100644 --- a/crates/epub/src/html.rs +++ b/crates/epub/src/html.rs @@ -45,13 +45,13 @@ pub fn reading_order(doc: &Document) -> Vec { continue; }; let xf = *parent * it.xf; + if it.hidden { + continue; + } let children = it.children(); if !children.is_empty() { stack.push((children.iter(), xf)); } - if it.hidden { - continue; - } let block = match &it.content { Content::Text(tf) => { let Some(story) = doc.story(tf.story) else { continue }; diff --git a/crates/epub/src/tests.rs b/crates/epub/src/tests.rs index 4b0531967..b3865dfc1 100644 --- a/crates/epub/src/tests.rs +++ b/crates/epub/src/tests.rs @@ -977,3 +977,21 @@ fn override_keeps_style_decorations_and_resets_tracking_and_caps() { assert_eq!(css::override_css(&d, "Base", &small), "text-transform: none; font-variant: normal; font-variant: small-caps;"); assert_eq!(css::override_css(&d, "Small", &all), "text-transform: none; font-variant: normal; text-transform: uppercase;"); } + +fn grouped_text(hidden: bool) -> Document { + let mut d = Document::new(&NewDocument::default()); + let lid = d.default_layer(); + d.add_text_frame(SpreadRef::Doc(0), Rect::new(36.0, 36.0, 300.0, 100.0), lid, "Grouped text", ParaFormat::default()).unwrap(); + let child = Arc::make_mut(&mut d.spreads[0]).items.pop().unwrap(); + let mut g = Item::new(ItemId(d.alloc()), lid, Shape::Group, Default::default()); + g.content = Content::Group { items: vec![child] }; + g.hidden = hidden; + Arc::make_mut(&mut d.spreads[0]).items.push(Arc::new(g)); + d +} + +#[test] +fn hidden_group_children_are_not_exported() { + assert!(html::reading_order(&grouped_text(true)).is_empty()); + assert_eq!(html::reading_order(&grouped_text(false)).len(), 1); +} diff --git a/crates/fonts/src/fontdb/face.rs b/crates/fonts/src/fontdb/face.rs index 058be0c0e..014220a16 100644 --- a/crates/fonts/src/fontdb/face.rs +++ b/crates/fonts/src/fontdb/face.rs @@ -297,16 +297,21 @@ impl FontFace { /// (bit 1) without a less restrictive bit (Preview & Print, Editable). Fonts without an OS/2 /// table aren't restricted. pub fn restricted_licence(&self) -> bool { - use skrifa::raw::TableProvider; - let fs_type = self.skrifa().and_then(|f| f.os2().ok()).map_or(0, |t| t.fs_type()); + let fs_type = self.fs_type().unwrap_or(0); fs_type & 0x0002 != 0 && fs_type & 0x000C == 0 } /// Does the font's licence allow embedding bitmaps only? OS/2 `fsType` bit 9: the outlines /// may not be passed on, so the font file can't be packaged whole. pub fn bitmap_only(&self) -> bool { + self.fs_type().is_some_and(|t| t & 0x0200 != 0) + } + + /// The font's OS/2 `fsType` (embedding licence bits), None when the font has no OS/2 table it + /// can read: the font doesn't say, which isn't the same as 0 (installable). + pub fn fs_type(&self) -> Option { use skrifa::raw::TableProvider; - self.skrifa().and_then(|f| f.os2().ok()).is_some_and(|t| t.fs_type() & 0x0200 != 0) + self.skrifa().and_then(|f| f.os2().ok()).map(|t| t.fs_type()) } } diff --git a/crates/geom/src/hit.rs b/crates/geom/src/hit.rs index 944ded3e9..096e0e1e3 100644 --- a/crates/geom/src/hit.rs +++ b/crates/geom/src/hit.rs @@ -27,7 +27,8 @@ pub fn stroke_contains(path: &BezPath, width: f64, tol: f64, p: Point) -> bool { /// Does the path intersect (or lie inside) the rect? Used for marquee selection. pub fn intersects_rect(path: &PathData, r: Rect) -> bool { let Some(b) = path.bounds() else { return false }; - if b.intersect(r).area() <= 0.0 && !(b.width() == 0.0 || b.height() == 0.0) { + let flat = |q: Rect| q.width() == 0.0 || q.height() == 0.0; + if b.intersect(r).area() <= 0.0 && !flat(b) && !flat(r) { return false; } // Any anchor inside? @@ -90,4 +91,12 @@ mod tests { let l = shapes::line(Point::new(0.0, 0.0), Point::new(10.0, 10.0)); assert!(intersects_rect(&l, Rect::new(4.0, 0.0, 6.0, 10.0))); } + + #[test] + fn flat_marquee() { + let p = shapes::rectangle(Rect::new(0.0, 0.0, 10.0, 10.0)); + assert!(intersects_rect(&p, Rect::new(-5.0, 5.0, 15.0, 5.0))); + assert!(intersects_rect(&p, Rect::new(5.0, -5.0, 5.0, 15.0))); + assert!(!intersects_rect(&p, Rect::new(-5.0, 20.0, 15.0, 20.0))); + } } diff --git a/crates/geom/src/warp.rs b/crates/geom/src/warp.rs index dacdedd06..6dd0cda9b 100644 --- a/crates/geom/src/warp.rs +++ b/crates/geom/src/warp.rs @@ -2,6 +2,20 @@ use kurbo::{Affine, BezPath, ParamCurve, ParamCurveArclen, ParamCurveDeriv, PathSeg, Point}; +/// Direction at a curve end whose derivative vanishes: from the end anchor towards the nearest +/// control point that differs from it (`at_end` selects the last anchor). +fn first_distinct(pts: &[Point], at_end: bool) -> kurbo::Vec2 { + let n = pts.len(); + for k in 1..n { + let (a, b) = if at_end { (pts[n - 1 - k], pts[n - 1]) } else { (pts[0], pts[k]) }; + let v = b - a; + if v.hypot2() > 1e-18 { + return v; + } + } + kurbo::Vec2::ZERO +} + /// A path measured for placing glyphs along it. #[derive(Clone, Debug)] pub struct PathWarp { @@ -29,12 +43,24 @@ impl PathWarp { let n = self.segs.len(); for (i, (seg, len)) in self.segs.iter().enumerate() { if s <= *len || i + 1 == n { - let t = if *len > 1e-9 { seg.inv_arclen(s.min(*len), 1e-4) } else { 0.0 }; + let t = if *len <= 1e-9 || s <= 0.0 { + 0.0 + } else if s >= *len { + 1.0 + } else { + seg.inv_arclen(s, 1e-4) + }; let p = seg.eval(t); let d = match seg { PathSeg::Line(l) => l.p1 - l.p0, - PathSeg::Quad(q) => q.deriv().eval(t).to_vec2(), - PathSeg::Cubic(c) => c.deriv().eval(t).to_vec2(), + PathSeg::Quad(q) => { + let d = q.deriv().eval(t).to_vec2(); + if d.hypot2() > 1e-18 { d } else { first_distinct(&[q.p0, q.p1, q.p2], t > 0.5) } + } + PathSeg::Cubic(c) => { + let d = c.deriv().eval(t).to_vec2(); + if d.hypot2() > 1e-18 { d } else { first_distinct(&[c.p0, c.p1, c.p2, c.p3], t > 0.5) } + } }; let mut a = d.y.atan2(d.x); if self.flip { @@ -98,4 +124,19 @@ mod tests { assert!((w.nearest(Point::new(30.0, -8.0)) - 30.0).abs() < 1e-6); assert!((flipped.nearest(Point::new(30.0, -8.0)) - 170.0).abs() < 1e-6); } + + #[test] + fn collapsed_handles_fall_back_to_the_next_control_point() { + let half_pi = std::f64::consts::FRAC_PI_2; + let mut bp = BezPath::new(); + bp.move_to((0.0, 0.0)); + bp.curve_to((0.0, 0.0), (0.0, 10.0), (10.0, 10.0)); + let w = PathWarp::new(&bp, false); + assert!((w.at(0.0).unwrap().1 - half_pi).abs() < 1e-9, "start handle on the anchor"); + let mut bp = BezPath::new(); + bp.move_to((0.0, 0.0)); + bp.curve_to((10.0, 0.0), (10.0, 10.0), (10.0, 10.0)); + let w = PathWarp::new(&bp, false); + assert!((w.at(w.length()).unwrap().1 - half_pi).abs() < 1e-9, "end handle on the anchor"); + } } diff --git a/crates/images/Cargo.toml b/crates/images/Cargo.toml index 48dc5955d..685c7d947 100644 --- a/crates/images/Cargo.toml +++ b/crates/images/Cargo.toml @@ -14,6 +14,7 @@ designcraft-fonts = { workspace = true } image = { workspace = true } tiff = { workspace = true } resvg = { workspace = true } +skrifa = { workspace = true } quick-xml = { workspace = true } flate2 = "1" log = { workspace = true } diff --git a/crates/images/src/lib.rs b/crates/images/src/lib.rs index 97067ac41..3f9a23d63 100644 --- a/crates/images/src/lib.rs +++ b/crates/images/src/lib.rs @@ -104,7 +104,10 @@ fn svg_options() -> &'static usvg::Options<'static> { /// family's but a face's PostScript name (as Illustrator's SVG export writes them: /// `font-family="'MyriadPro-Regular'"`) sets the text in that face, whatever font-weight and /// font-style say: the name already picks the weight and style, and a family's other faces would -/// contradict it. Families listed before it come first. +/// contradict it. A name that is a face's legacy family name (name ID 1) or full name (ID 4), as +/// Windows names faces outside the regular/bold/italic quartet (`'Segoe UI Semibold'`, whose +/// typographic family is `Segoe UI`), sets the text in that face (the closest to font-weight and +/// font-style when the legacy family has several). Families listed before it come first. fn select_font() -> usvg::FontSelectionFn<'static> { use usvg::fontdb::{Family, Query, Stretch, Style, Weight}; Box::new(move |font, db| { @@ -112,27 +115,67 @@ fn select_font() -> usvg::FontSelectionFn<'static> { let spelled = |db: &usvg::fontdb::Database, name: &str| { db.faces().flat_map(|f| &f.families).find(|(n, _)| n.eq_ignore_ascii_case(name)).map(|(n, _)| n.clone()) }; - for family in font.families() { + // (index in the font-family list, face) of the faces a name names by its legacy names. + let mut legacy: Vec<(usize, usvg::fontdb::ID)> = Vec::new(); + for (i, family) in font.families().iter().enumerate() { if let usvg::FontFamily::Named(name) = family && spelled(db, name).is_none() { if fonts.has_family(name) { for style in fonts.styles(name) { - add_face(db, fonts.face(name, &style)); + let face = fonts.face(name, &style); + let named = has_legacy_name(&face, name); + if let Some(id) = add_face(db, face) + && named + { + legacy.push((i, id)); + } + } + } else if postscript_face(db, name).is_none() { + if let Some((family, style)) = fonts.postscript_face(name) { + add_face(db, fonts.face(&family, &style)); + } else { + // A full name: the family is the name without its last words ("Bold"). + let mut base = name.as_str(); + for _ in 0..3 { + let Some((head, _)) = base.trim_end().rsplit_once(' ') else { break }; + base = head; + if fonts.has_family(base) { + for style in fonts.styles(base) { + let face = fonts.face(base, &style); + if has_legacy_name(&face, name) + && let Some(id) = add_face(db, face) + { + legacy.push((i, id)); + } + } + break; + } + } } - } else if postscript_face(db, name).is_none() - && let Some((family, style)) = fonts.postscript_face(name) - { - add_face(db, fonts.face(&family, &style)); } } } - for family in font.families() { + let want_style = match font.style() { + usvg::FontStyle::Normal => Style::Normal, + usvg::FontStyle::Italic => Style::Italic, + usvg::FontStyle::Oblique => Style::Oblique, + }; + for (i, family) in font.families().iter().enumerate() { match family { usvg::FontFamily::Named(name) if spelled(db, name).is_none() => { if let Some(id) = postscript_face(db, name) { return Some(id); } + let closest = legacy + .iter() + .filter(|(at, _)| *at == i) + .filter_map(|(_, id)| db.face(*id)) + .min_by_key(|f| (f.style != want_style, f.weight.0.abs_diff(font.weight()))) + .map(|f| f.id); + if closest.is_some() { + return closest; + } } // A family (or generic family) that matches: the query below. _ => break, @@ -173,15 +216,22 @@ fn select_font() -> usvg::FontSelectionFn<'static> { usvg::FontStretch::ExtraExpanded => Stretch::ExtraExpanded, usvg::FontStretch::UltraExpanded => Stretch::UltraExpanded, }; - let style = match font.style() { - usvg::FontStyle::Normal => Style::Normal, - usvg::FontStyle::Italic => Style::Italic, - usvg::FontStyle::Oblique => Style::Oblique, - }; - db.query(&Query { families: &families, weight: Weight(font.weight()), stretch, style }) + db.query(&Query { families: &families, weight: Weight(font.weight()), stretch, style: want_style }) }) } +/// Is `name` (ignoring case) a legacy family name (name ID 1) or full name (ID 4) of `face`? +fn has_legacy_name(face: &designcraft_fonts::FontFace, name: &str) -> bool { + use skrifa::MetadataProvider; + use skrifa::string::StringId; + let Some(f) = face.skrifa() else { return false }; + [StringId::FAMILY_NAME, StringId::FULL_NAME] + .into_iter() + .flat_map(|id| f.localized_strings(id)) + .take(256) + .any(|s| s.chars().map(|c| c.to_ascii_lowercase()).eq(name.chars().map(|c| c.to_ascii_lowercase()))) +} + /// The face in the SVG's font database with PostScript name `name` (ignoring case). fn postscript_face(db: &usvg::fontdb::Database, name: &str) -> Option { db.faces().find(|f| f.post_script_name.eq_ignore_ascii_case(name)).map(|f| f.id) diff --git a/crates/images/src/tests.rs b/crates/images/src/tests.rs index dd09f2577..d69a6f504 100644 --- a/crates/images/src/tests.rs +++ b/crates/images/src/tests.rs @@ -248,6 +248,34 @@ fn svg_text_finds_fonts_by_postscript_name() { assert_eq!(text_face(r#" font-family="NoSuch-Font""#), "SourceSerif4-Regular"); } +#[test] +fn svg_text_matches_legacy_family_names() { + use designcraft_fonts::testing::{font_with_names, with_table_u16}; + // Laid out as Windows names faces outside the regular/bold/italic quartet (seguisb.ttf): the + // weight is in the legacy family (ID 1) and full name (ID 4), the typographic family (ID 16) + // is the base name. + let face = |names: &[(u16, &str)], weight: u16| with_table_u16(font_with_names(names, &['a', 'b']).unwrap(), b"OS/2", 4, weight).unwrap(); + let fonts = designcraft_fonts::FontDb::global(); + fonts.add_font(face(&[(1, "DC Test Legacy"), (2, "Regular"), (4, "DC Test Legacy Regular"), (6, "DCTestLegacy-Regular")], 400)); + fonts.add_font(face(&[(1, "DC Test Legacy"), (2, "Bold"), (4, "DC Test Legacy Bold"), (6, "DCTestLegacy-Bold")], 700)); + for (name, weight) in [("Semibold", 600), ("Light", 300)] { + let legacy = format!("DC Test Legacy {name}"); + let ps = format!("DCTestLegacy-{name}"); + fonts.add_font(face(&[(1, &legacy), (2, "Regular"), (4, &legacy), (6, &ps), (16, "DC Test Legacy"), (17, name)], weight)); + } + assert_eq!(text_face(r#" font-family="DC Test Legacy Semibold""#), "DCTestLegacy-Semibold"); + assert_eq!(text_face(r#" font-family="dc test legacy light""#), "DCTestLegacy-Light"); + assert_eq!(text_face(r#" font-family="'DC Test Legacy Semibold', sans-serif""#), "DCTestLegacy-Semibold"); + assert_eq!(text_face(r#" font-family="NoSuch Font, 'DC Test Legacy Light', serif""#), "DCTestLegacy-Light"); + // The full name (ID 4) of a face of the quartet. + assert_eq!(text_face(r#" font-family="DC Test Legacy Bold""#), "DCTestLegacy-Bold"); + // The typographic family still picks by weight. + assert_eq!(text_face(r#" font-family="DC Test Legacy" font-weight="600""#), "DCTestLegacy-Semibold"); + assert_eq!(text_face(r#" font-family="DC Test Legacy""#), "DCTestLegacy-Regular"); + // A name nobody has still falls to the serif. + assert_eq!(text_face(r#" font-family="DC Test Legacy Nothing""#), "SourceSerif4-Regular"); +} + /// A minimal Photoshop file: 2×1 RGB, no layers, raw merged image. fn tiny_psd() -> Vec { let mut b = Vec::new(); diff --git a/crates/pdf/src/lib.rs b/crates/pdf/src/lib.rs index 987e7ea97..37909a1f5 100644 --- a/crates/pdf/src/lib.rs +++ b/crates/pdf/src/lib.rs @@ -51,7 +51,7 @@ mod transitions; pub use export::{ BookletKind, BookletOptions, booklet_pairs, export_booklet, export_pdf, export_pdf_with_report, merge_pdfs, print_color, sheet_spreads, }; -pub use pdfx::{check_pdfx4, has_rgb_groups, make_pdfx4}; +pub use pdfx::{check_pdfx4, has_rgb_groups, make_pdfx4, pdfx_version}; pub use pdfx1a::check_pdfx1a; pub use transitions::{add_blend_space, add_catalog_entries, add_page_entries, add_transitions}; diff --git a/crates/pdf/src/optional_content.rs b/crates/pdf/src/optional_content.rs index 7857d36d7..374c0d1f1 100644 --- a/crates/pdf/src/optional_content.rs +++ b/crates/pdf/src/optional_content.rs @@ -58,7 +58,7 @@ fn edited(dict: &Dict<'_>, replacements: &[(&[u8], &[u8])]) -> Result> { /// The trailer of the cross-reference section at `offset`: a table's `trailer` dictionary or an /// xref stream's own. A table is read entry by entry rather than searched for the keyword, so a /// `trailer` in a comment can't stand in for the real one; reading is bounded either way. -fn trailer_at(bytes: &[u8], offset: usize) -> Option> { +pub(crate) fn trailer_at(bytes: &[u8], offset: usize) -> Option> { const MAX_SECTION_BYTES: usize = 4 * 1024 * 1024; let data = bytes.get(offset..)?; let mut reader = Reader::new(data.get(..data.len().min(MAX_SECTION_BYTES))?); diff --git a/crates/pdf/src/pdfx.rs b/crates/pdf/src/pdfx.rs index e20247813..6d7a3714f 100644 --- a/crates/pdf/src/pdfx.rs +++ b/crates/pdf/src/pdfx.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; use hayro_syntax::content::UntypedIter; use hayro_syntax::object::{Array, Dict, Name, Object, ObjectIdentifier, Stream}; use hayro_syntax::page::Resources; +use hayro_syntax::reader::ReaderExt; use craft_pdf::write::WriteError; use craft_pdf::write::backend as krilla; @@ -115,16 +116,18 @@ pub fn has_rgb_groups(pdf: &[u8]) -> bool { pub fn check_pdfx4(pdf: &[u8]) -> Vec { let mut issues = Vec::new(); let text = String::from_utf8_lossy(pdf); + let file = hayro_syntax::Pdf::new(pdf.to_vec()).ok(); if !pdf.starts_with(b"%PDF-1.") || pdf.get(7).is_none_or(|v| *v > b'6') { issues.push("the PDF version must be 1.6 or lower".into()); } - if !text.contains("/S/GTS_PDFX") { + let intents = file.as_ref().map(pdfx_intents).unwrap_or_default(); + if intents.is_empty() { issues.push("no PDF/X output intent".into()); } - if !text.contains("/DestOutputProfile") { + if !intents.iter().any(|oi| oi.contains_key(b"DestOutputProfile")) { issues.push("the output intent has no destination profile".into()); } - if !text.contains("/GTS_PDFXVersion(PDF/X-4)") { + if file.as_ref().and_then(|f| info_text(pdf, f, b"GTS_PDFXVersion")).as_deref() != Some("PDF/X-4") { issues.push("the document information doesn't name PDF/X-4".into()); } if !text.contains("pdfxid:GTS_PDFXVersion>PDF/X-4<") { @@ -150,22 +153,67 @@ pub fn check_pdfx4(pdf: &[u8]) -> Vec { if text.contains("/Subtype/Type3") { issues.push("Type 3 fonts aren't allowed".into()); } - issues.extend(device_rgb(pdf)); + issues.extend(device_rgb(file.as_ref())); issues.extend(fonts::unembedded_fonts(pdf)); issues } +/// The document information's `GTS_PDFXVersion` (`PDF/X-4`, `PDF/X-1:2003`, …), read as an +/// object; `None` when the file can't be read or doesn't name one. +pub fn pdfx_version(pdf: &[u8]) -> Option { + info_text(pdf, &hayro_syntax::Pdf::new(pdf.to_vec()).ok()?, b"GTS_PDFXVersion") +} + +/// The catalog's `GTS_PDFX` output intents, read as objects (whitespace and object streams +/// don't matter). +pub(crate) fn pdfx_intents<'a>(file: &'a hayro_syntax::Pdf) -> Vec> { + let xref = file.xref(); + let Some(catalog) = xref.get::>(xref.root_id()) else { return Vec::new() }; + let Some(intents) = catalog.get::>(b"OutputIntents") else { return Vec::new() }; + intents.iter::>().filter(|oi| oi.get::>(b"S").is_some_and(|s| s.as_ref() == b"GTS_PDFX")).collect() +} + +/// The text entry `key` of the document information dictionary, trimmed: the `/Info` of the +/// newest trailer that has one (classic or cross-reference stream, following `/Prev` a bounded +/// number of times), else of the last `trailer` keyword in the file. +pub(crate) fn info_text(pdf: &[u8], file: &hayro_syntax::Pdf, key: &[u8]) -> Option { + let lookup = |trailer: &Dict<'_>| -> Option { + let info = match trailer.get_ref(b"Info") { + Some(r) => file.xref().get::>(r.into())?, + None => trailer.get::>(b"Info")?, + }; + let value = info.get::>(key)?; + Some(String::from_utf8_lossy(value.as_bytes()).trim().to_string()) + }; + let tail = pdf.get(rfind(pdf, b"startxref")?..).unwrap_or_default(); + let mut offset = int_after(&String::from_utf8_lossy(tail), "startxref"); + let mut seen = HashSet::new(); + for _ in 0..32 { + let Some(at) = offset.filter(|at| seen.insert(*at)) else { break }; + let Some(trailer) = crate::optional_content::trailer_at(pdf, at) else { break }; + if trailer.contains_key(b"Info") { + return lookup(&trailer); + } + offset = trailer.get::(b"Prev"); + } + // A damaged cross-reference offset: the dictionary after the last `trailer` keyword. + let at = rfind(pdf, b"trailer")? + b"trailer".len(); + let mut reader = hayro_syntax::reader::Reader::new(pdf.get(at..)?); + reader.skip_white_spaces_and_comments(); + lookup(&reader.read_without_context::>()?) +} + /// Device-dependent RGB under a CMYK output intent. PDF/X-4 (ISO 15930-7) lets RGB in only when /// it is colour-managed: ICCBased RGB, or DeviceRGB remapped by a `DefaultRGB` colour space in the /// resources. DeviceCMYK and DeviceGray are the output intent's own device values, so they stay. /// This walks every page's content, the images, forms, patterns, shadings and soft masks it uses, /// and the transparency groups, and reports each kind of device RGB it finds with the pages it is /// on. Nothing is reported when the file has no CMYK PDF/X output intent. -fn device_rgb(pdf: &[u8]) -> Vec { - let Ok(file) = hayro_syntax::Pdf::new(pdf.to_vec()) else { +fn device_rgb(file: Option<&hayro_syntax::Pdf>) -> Vec { + let Some(file) = file else { return vec!["the file couldn't be read to check its colour spaces".into()]; }; - if !cmyk_output_intent(&file) { + if !cmyk_output_intent(file) { return Vec::new(); } let mut found: Vec<(String, Vec)> = Vec::new(); @@ -198,13 +246,7 @@ fn device_rgb(pdf: &[u8]) -> Vec { /// Whether the file's PDF/X output intent has a four-channel (CMYK) destination profile. pub(crate) fn cmyk_output_intent(file: &hayro_syntax::Pdf) -> bool { - let xref = file.xref(); - let Some(catalog) = xref.get::>(xref.root_id()) else { return false }; - let Some(intents) = catalog.get::>(b"OutputIntents") else { return false }; - intents.iter::>().any(|oi| { - oi.get::>(b"S").is_some_and(|s| s.as_ref() == b"GTS_PDFX") - && oi.get::>(b"DestOutputProfile").and_then(|p| p.dict().get::(b"N")) == Some(4) - }) + pdfx_intents(file).iter().any(|oi| oi.get::>(b"DestOutputProfile").and_then(|p| p.dict().get::(b"N")) == Some(4)) } /// Whether a colour space is device RGB: `/DeviceRGB` (`/RGB` in inline images), or an diff --git a/crates/pdf/src/pdfx/tests.rs b/crates/pdf/src/pdfx/tests.rs index edb6aec8f..b35e897c2 100644 --- a/crates/pdf/src/pdfx/tests.rs +++ b/crates/pdf/src/pdfx/tests.rs @@ -462,3 +462,106 @@ fn xmp_states_trapped() { assert!(String::from_utf8_lossy(&r.bytes).contains("/Trapped/False")); assert!(r.warnings.is_empty(), "{:?}", r.warnings); } + +/// `objects` (from 1) as a PDF 1.6 file with a classic cross-reference table and `trailer`. +fn assemble_x4(objects: &[&str], trailer: &str) -> Vec { + let mut out = b"%PDF-1.6\n".to_vec(); + let mut offsets = Vec::new(); + for (i, o) in objects.iter().enumerate() { + offsets.push(out.len()); + out.extend_from_slice(format!("{} 0 obj\n{o}\nendobj\n", i + 1).as_bytes()); + } + let xref = out.len(); + out.extend_from_slice(format!("xref\n0 {}\n0000000000 65535 f\r\n", objects.len() + 1).as_bytes()); + for off in offsets { + out.extend_from_slice(format!("{off:010} 00000 n\r\n").as_bytes()); + } + out.extend_from_slice(format!("trailer\n{trailer}\nstartxref\n{xref}\n%%EOF\n").as_bytes()); + out +} + +const NO_INTENT: &str = "no PDF/X output intent"; +const NO_INFO: &str = "the document information doesn't name PDF/X-4"; + +/// The output intent and the document information are read as objects: whitespace between +/// tokens (as qpdf and Ghostscript write them) doesn't hide them. +#[test] +fn x4_checks_ignore_whitespace_between_tokens() { + let pdf = assemble_x4( + &[ + "<< /Type /Catalog /Pages 2 0 R /OutputIntents [ << /Type /OutputIntent /S /GTS_PDFX /DestOutputProfile 4 0 R >> ] >>", + "<< /Type /Pages /Kids [ 3 0 R ] /Count 1 >>", + "<< /Type /Page /Parent 2 0 R /MediaBox [ 0 0 100 100 ] /TrimBox [ 0 0 100 100 ] >>", + "<< /N 4 /Length 0 >>\nstream\n\nendstream", + "<< /GTS_PDFXVersion (PDF/X-4) /Trapped /False >>", + ], + "<< /Size 6 /Root 1 0 R /Info 5 0 R >>", + ); + let issues = check_pdfx4(&pdf); + assert!(!issues.iter().any(|i| i == NO_INTENT || i == NO_INFO), "{issues:?}"); + // Without them, both are still reported. + let bare = assemble_x4( + &[ + "<< /Type /Catalog /Pages 2 0 R /OutputIntents [ << /Type /OutputIntent /S /GTS_PDFA1 >> ] >>", + "<< /Type /Pages /Kids [ 3 0 R ] /Count 1 >>", + "<< /Type /Page /Parent 2 0 R /MediaBox [ 0 0 100 100 ] /TrimBox [ 0 0 100 100 ] >>", + "<< /N 4 /Length 0 >>\nstream\n\nendstream", + "<< /Title (/S/GTS_PDFX /GTS_PDFXVersion(PDF/X-4)) /GTS_PDFXVersion (PDF/X-3:2002) >>", + ], + "<< /Size 6 /Root 1 0 R /Info 5 0 R >>", + ); + let issues = check_pdfx4(&bare); + assert!(issues.iter().any(|i| i == NO_INTENT) && issues.iter().any(|i| i == NO_INFO), "{issues:?}"); +} + +/// The output intent and the document information are found inside a compressed object stream, +/// through a cross-reference stream. +#[test] +fn x4_checks_read_object_streams() { + let plain = [ + "<>", + "<>", + "<>", + "<>\nstream\n\nendstream", + ]; + let (info, intent) = ("<>", "<>"); + let mut out = b"%PDF-1.6\n".to_vec(); + let mut offsets = Vec::new(); + for (i, o) in plain.iter().enumerate() { + offsets.push(out.len()); + out.extend_from_slice(format!("{} 0 obj\n{o}\nendobj\n", i + 1).as_bytes()); + } + // Object 5 is free; 6 and 7 live in object stream 8. + let header = format!("6 0 7 {} ", info.len() + 1); + let body = format!("{header}{info} {intent}"); + let objstm = out.len(); + let mut z = flate2::write::ZlibEncoder::new(Vec::new(), flate2::Compression::fast()); + std::io::Write::write_all(&mut z, body.as_bytes()).unwrap(); + let packed = z.finish().unwrap(); + out.extend_from_slice( + format!("8 0 obj\n<>\nstream\n", header.len(), packed.len()).as_bytes(), + ); + out.extend_from_slice(&packed); + out.extend_from_slice(b"\nendstream\nendobj\n"); + let xref = out.len(); + let mut rows = Vec::new(); + let mut row = |kind: u8, field: usize, idx: u16| { + rows.push(kind); + rows.extend_from_slice(&u32::try_from(field).unwrap().to_be_bytes()); + rows.extend_from_slice(&idx.to_be_bytes()); + }; + row(0, 0, 65535); + for off in &offsets { + row(1, *off, 0); + } + row(0, 0, 0); + row(2, 8, 0); + row(2, 8, 1); + row(1, objstm, 0); + row(1, xref, 0); + out.extend_from_slice(format!("9 0 obj\n<>\nstream\n", rows.len()).as_bytes()); + out.extend_from_slice(&rows); + out.extend_from_slice(format!("\nendstream\nendobj\nstartxref\n{xref}\n%%EOF\n").as_bytes()); + let issues = check_pdfx4(&out); + assert!(!issues.iter().any(|i| i == NO_INTENT || i == NO_INFO), "{issues:?}"); +} diff --git a/crates/pdf/src/pdfx1a.rs b/crates/pdf/src/pdfx1a.rs index 88759b071..495a389d8 100644 --- a/crates/pdf/src/pdfx1a.rs +++ b/crates/pdf/src/pdfx1a.rs @@ -116,16 +116,18 @@ pub fn check_pdfx1a(pdf: &[u8]) -> Vec { fn checks(pdf: &[u8]) -> (Vec, Vec) { let mut issues = Vec::new(); let text = String::from_utf8_lossy(pdf); + let file = hayro_syntax::Pdf::new(pdf.to_vec()).ok(); if !pdf.starts_with(b"%PDF-1.") || pdf.get(7).is_none_or(|v| *v > b'4') { issues.push("the PDF version must be 1.4 or lower".into()); } - if !text.contains("/S/GTS_PDFX") { + if file.as_ref().is_none_or(|f| crate::pdfx::pdfx_intents(f).is_empty()) { issues.push("no PDF/X output intent".into()); } - if !text.contains(&format!("/GTS_PDFXVersion({VERSION})")) { + let info = |key: &[u8]| file.as_ref().and_then(|f| crate::pdfx::info_text(pdf, f, key)); + if info(b"GTS_PDFXVersion").as_deref() != Some(VERSION) { issues.push(format!("the document information doesn't name {VERSION}")); } - if !text.contains(&format!("/GTS_PDFXConformance({CONFORMANCE})")) { + if info(b"GTS_PDFXConformance").as_deref() != Some(CONFORMANCE) { issues.push(format!("the document information doesn't name the conformance level {CONFORMANCE}")); } if !text.contains("/Trapped/False") && !text.contains("/Trapped/True") && !text.contains("/Trapped /False") && !text.contains("/Trapped /True") { @@ -142,18 +144,18 @@ fn checks(pdf: &[u8]) -> (Vec, Vec) { if pages > 0 && trims < pages { issues.push("every page needs a trim box".into()); } - let (content, fonts) = content(pdf); + let (content, fonts) = content(file.as_ref()); issues.extend(fonts); (content, issues) } /// Transparency and color spaces, then the output intent and fonts, walked through every page's /// content and what it uses. -fn content(pdf: &[u8]) -> (Vec, Vec) { - let Ok(file) = hayro_syntax::Pdf::new(pdf.to_vec()) else { +fn content(file: Option<&hayro_syntax::Pdf>) -> (Vec, Vec) { + let Some(file) = file else { return (vec!["the file couldn't be read to check its transparency and color spaces".into()], Vec::new()); }; - let mut fonts = intent_issues(&file); + let mut fonts = intent_issues(file); let mut found: Vec<(String, Vec)> = Vec::new(); let mut font_found: Vec<(String, Vec)> = Vec::new(); for (i, page) in file.pages().iter().enumerate() { @@ -214,13 +216,9 @@ impl Intent { /// The catalog's `GTS_PDFX` output intents. fn pdfx_intents(file: &hayro_syntax::Pdf) -> Vec { - let xref = file.xref(); - let Some(catalog) = xref.get::>(xref.root_id()) else { return Vec::new() }; - let Some(intents) = catalog.get::>(b"OutputIntents") else { return Vec::new() }; let number = |n: i32| usize::try_from(n).ok(); - intents - .iter::>() - .filter(|oi| oi.get::>(b"S").is_some_and(|s| s.as_ref() == b"GTS_PDFX")) + crate::pdfx::pdfx_intents(file) + .into_iter() .map(|oi| { let text = |key: &[u8]| { oi.get::>(key) diff --git a/crates/pdf/src/x1a_tests.rs b/crates/pdf/src/x1a_tests.rs index 777d1e2a6..c79aaa172 100644 --- a/crates/pdf/src/x1a_tests.rs +++ b/crates/pdf/src/x1a_tests.rs @@ -318,3 +318,13 @@ fn x1a_dropped_inks_warning_says_they_wont_print() { assert!(warnings.iter().any(|w| w.contains("3 tint(s)") && w.contains("dropped and won't print")), "{warnings:?}"); assert!(warnings.iter().all(|w| !w.contains("converted to process")), "{warnings:?}"); } + +/// The output intent and the identification are read as objects: whitespace between tokens (as +/// qpdf and Ghostscript write them) doesn't hide them. +#[test] +fn x1a_checks_ignore_whitespace_between_tokens() { + let mut objects = tiny_objects("/Resources<<>>", "0 0 0 1 k", "/OutputConditionIdentifier(Custom)/DestOutputProfile 4 0 R", &icc_header(2)); + objects[5] = b"<< /GTS_PDFXVersion (PDF/X-1:2003) /GTS_PDFXConformance (PDF/X-1a:2003) /Trapped /False >>".to_vec(); + objects[6] = b"<< /Type /OutputIntent /S /GTS_PDFX /OutputConditionIdentifier (Custom) /DestOutputProfile 4 0 R >>".to_vec(); + assert_eq!(check_pdfx1a(&assemble(&objects)), Vec::::new()); +} diff --git a/crates/textimport/src/export.rs b/crates/textimport/src/export.rs index 8262e4691..7d614f640 100644 --- a/crates/textimport/src/export.rs +++ b/crates/textimport/src/export.rs @@ -15,7 +15,7 @@ fn plain_char(c: char) -> Option<&'static str> { match c { PAGE_NUMBER | NEXT_PAGE_NUMBER | PREV_PAGE_NUMBER => Some("#"), FORCED_LINE_BREAK => Some("\u{2028}"), - '\u{E000}'..='\u{E0FF}' => None, + '\u{E000}'..='\u{E1FF}' => None, _ => Some(""), } } @@ -174,7 +174,7 @@ pub fn rtf(doc: &Document, story: &Story) -> String { } } PAGE_NUMBER | NEXT_PAGE_NUMBER | PREV_PAGE_NUMBER => out.push('#'), - '\u{E000}'..='\u{E0FF}' => {} + '\u{E000}'..='\u{E1FF}' => {} c => rtf_escape(&mut out, c), } } @@ -201,6 +201,14 @@ mod tests { st } + #[test] + fn text_variable_markers_are_dropped() { + let st = Story::with_text(StoryId(1), "Page \u{E100} of", Default::default()); + assert_eq!(plain_text(&st), "Page of"); + let r = rtf(&Document::new(&NewDocument::default()), &st); + assert!(!r.contains("\\u-7936") && r.contains("Page of"), "{r}"); + } + #[test] fn text_only() { assert_eq!(plain_text(&story()), "Plain bold {x}\r\nCafé\ntwo"); diff --git a/crates/ui-egui/src/app/files.rs b/crates/ui-egui/src/app/files.rs index b5de53ab1..68155d884 100644 --- a/crates/ui-egui/src/app/files.rs +++ b/crates/ui-egui/src/app/files.rs @@ -161,8 +161,7 @@ impl DesignApp { } else if place { self.open_file("file.place", json!({"name": file.name, "base64": b64})) } else { - let title = file.name.rsplit_once('.').map_or(file.name.as_str(), |(stem, _)| stem); - self.open_file("file.openBytes", json!({"name": title, "base64": b64})) + self.open_file("file.openBytes", json!({"name": file.name, "base64": b64})) } } @@ -377,7 +376,7 @@ mod import_warning_tests { let request = app.import_request("open"); app.services.inbox.as_ref().unwrap().lock().unwrap().push(ImportedFile { request, name: "partial.idml".into(), bytes: idml(true) }); app.drain_inbox(); - assert_partial_import_warning(&mut app, "partial"); + assert_partial_import_warning(&mut app, "partial.idml"); } #[test] @@ -424,6 +423,34 @@ pub(crate) mod browser_import_tests { app.services.inbox.as_ref().unwrap().lock().unwrap().push(ImportedFile { request, name: name.into(), bytes }); app.drain_inbox(); } + + /// A document chosen or dropped in the browser is titled by its file name less one extension, + /// as on the desktop: the extension comes off once, in the engine. + #[test] + fn browser_opens_title_a_document_by_its_name_without_one_extension() { + let mut app = app(); + let native = designcraft_engine::cmd::base64_decode(app.run("file.serialize", json!({})).unwrap()["base64"].as_str().unwrap()); + for purpose in ["open", "drop"] { + for (name, title) in [ + ("Brochure.designcraft", "Brochure"), + ("Brochure.designcraft.designcraft", "Brochure.designcraft"), + ("Brochure.v2.designcraft", "Brochure.v2"), + ("日本.DESIGNCRAFT", "日本"), + (".designcraft", ".designcraft"), + ("Brochure", "Brochure"), + ] { + let request = app.import_request(purpose); + deliver(&mut app, request, name, native.clone()); + assert_eq!(app.session.doc().unwrap().doc.title, title, "{purpose}: {name}"); + } + } + let idml = designcraft_idml::export_idml(&app.session.doc().unwrap().doc); + for purpose in ["open", "drop"] { + let request = app.import_request(purpose); + deliver(&mut app, request, "Brochure.idml", idml.clone()); + assert_eq!(app.session.doc().unwrap().doc.title, "Brochure", "{purpose}: IDML"); + } + } fn image() -> Vec { br##""##.to_vec() } diff --git a/crates/ui-egui/src/app/input.rs b/crates/ui-egui/src/app/input.rs index 8d248561c..e889c3287 100644 --- a/crates/ui-egui/src/app/input.rs +++ b/crates/ui-egui/src/app/input.rs @@ -23,6 +23,11 @@ impl DesignApp { /// Inject synthetic events (one pointer event per host iteration), retaining control /// provenance until a settled UI pass has actually taken the batch. pub fn raw_input_hook(&mut self, ctx: &egui::Context, raw: &mut egui::RawInput) { + // An undecorated window gets its caption back when the toolkit changes its flags + // (maximize, restore, …): take it off again before the frame is laid out (#1295). + if let Some(window_frame) = self.services.window_frame.as_mut() { + window_frame(); + } if !self.injected_settle_hook { let pending = self.injected_pending.clone(); let settled = self.injected_settled.clone(); diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index 3c2565052..73e6e83db 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -12,12 +12,14 @@ mod ar; mod cs; mod de; mod fr; +mod hu; mod it; mod ja; mod ka; mod pl; mod pt_br; mod ru; +mod sv; mod uk; /// Supported interface languages: (code, name in that language). @@ -36,6 +38,8 @@ pub const LANGUAGES: &[(&str, &str)] = &[ ("cs", "Čeština"), ("pl", "Polski"), ("ka", "ქართული"), + ("hu", "Magyar"), + ("sv", "Svenska"), ]; /// The interface languages in the order the Preferences picker lists them: English first (the @@ -77,6 +81,8 @@ pub fn tr<'a>(lang: &str, s: &'a str) -> &'a str { if text.trim().is_empty() { s } else { text } } +/// Looks up a label in lazily cached language tables, using the shared table where supported. +/// Unknown languages and missing keys keep the source text; `tr` also handles blank entries. fn lookup<'a>(lang: &str, s: &'a str) -> &'a str { static GERMAN: OnceLock> = OnceLock::new(); static JAPANESE: OnceLock> = OnceLock::new(); @@ -90,6 +96,11 @@ fn lookup<'a>(lang: &str, s: &'a str) -> &'a str { static CZECH: OnceLock> = OnceLock::new(); static FRENCH: OnceLock> = OnceLock::new(); static GEORGIAN: OnceLock> = OnceLock::new(); + static HUNGARIAN: OnceLock> = OnceLock::new(); + if lang == "hu" { + return HUNGARIAN.get_or_init(|| hu::TABLE.iter().copied().collect()).get(s).copied().unwrap_or(s); + } + static SWEDISH: OnceLock> = OnceLock::new(); if lang == "ar" { return ARABIC.get_or_init(|| ar::TABLE.iter().copied().collect()).get(s).copied().unwrap_or(s); } @@ -123,6 +134,9 @@ fn lookup<'a>(lang: &str, s: &'a str) -> &'a str { if lang == "ka" { return GEORGIAN.get_or_init(|| ka::TABLE.iter().copied().collect()).get(s).copied().unwrap_or(s); } + if lang == "sv" { + return SWEDISH.get_or_init(|| sv::TABLE.iter().copied().collect()).get(s).copied().unwrap_or(s); + } if lang == "uk" { return UKRAINIAN.get_or_init(|| uk::TABLE.iter().copied().collect()).get(s).copied().unwrap_or(s); } @@ -145,12 +159,14 @@ const CONTEXT: &[(&str, &str, [&str; 5])] = &[ /// Context-sensitive UI captions; unsupported contexts keep the shared translation. pub fn tr_context<'a>(lang: &str, s: &'a str, context: &str) -> &'a str { let contexts = match lang { + "hu" => hu::CONTEXT, "uk" => uk::CONTEXT, "ru" => ru::CONTEXT, "cs" => cs::CONTEXT, "pl" => pl::CONTEXT, "ja" => ja::CONTEXT, "ar" => ar::CONTEXT, + "sv" => sv::CONTEXT, _ => &[], }; let written = |text: &&str| !text.trim().is_empty(); @@ -176,6 +192,12 @@ pub(crate) fn russian_catalog() -> Vec<&'static str> { ru::TABLE.iter().map(|(_, text)| *text).chain(ru::CONTEXT.iter().map(|(_, _, text)| *text)).collect() } +/// Whether the Swedish catalog has an entry for `s` (many Swedish labels read like the English ones). +#[cfg(test)] +pub(crate) fn swedish_has(s: &str) -> bool { + sv::TABLE.iter().any(|(key, _)| *key == s) +} + /// Ukrainian, Russian, Polish and Georgian put the category before the value in count captions /// ("сторінок: 5", "страниц: 5", "Strony: 5", "გვერდი: 5"): every number stays grammatical in the /// languages with several plural forms, and Georgian nouns stay singular after numerals. Other @@ -184,12 +206,29 @@ pub fn category_first(lang: &str) -> bool { matches!(lang, "uk" | "ru" | "pl" | "ka") } +/// Swedish singular for a count of one, where it differs from the catalog's plural ("1 sida", +/// "5 sidor"); "fel", "objekt" and "lager" read the same either way. +fn swedish_singular(noun: &str) -> Option<&'static str> { + match noun { + "pages" => Some("sida"), + "stories" => Some("artikel"), + "warnings" => Some("varning"), + _ => None, + } +} + /// Caption for a counted category, e.g. `count_label("ru", "pages", 5)` is "страниц: 5". Czech -/// picks the plural form for the count (1, 2–4, other). +/// picks the plural form for the count (1, 2–4, other); Swedish the singular for one. pub fn count_label(lang: &str, noun: &str, count: usize) -> String { if category_first(lang) { return format!("{}: {count}", tr(lang, noun)); } + if lang == "sv" + && count == 1 + && let Some(one) = swedish_singular(noun) + { + return format!("{count} {one}"); + } if lang == "cs" && let Some((_, [one, few, other])) = cs::PLURALS.iter().find(|(key, _)| *key == noun) { @@ -231,6 +270,40 @@ pub fn workspace_name<'a>(lang: &str, name: &'a str) -> &'a str { #[cfg(test)] mod tests; +#[cfg(test)] +mod swedish_tests { + use super::*; + + #[test] + fn swedish_catalog_preserves_placeholders_and_ellipses() { + let catalog: HashMap<_, _> = sv::TABLE.iter().copied().collect(); + assert_eq!(catalog.len(), sv::TABLE.len(), "duplicate Swedish keys"); + let placeholders = |s: &str| { + s.split('{').skip(1).filter_map(|part| part.split_once('}').map(|(name, _)| name.to_owned())).collect::>() + }; + for (key, translation) in sv::TABLE { + assert!(!translation.trim().is_empty(), "empty {key}"); + assert_eq!(placeholders(key), placeholders(translation), "placeholders: {key}"); + assert_eq!(key.ends_with('…'), translation.ends_with('…'), "ellipsis: {key}"); + assert_eq!(tr("sv", key), *translation, "sv: {key}"); + } + let contexts: std::collections::HashSet<_> = sv::CONTEXT.iter().map(|(key, scope, _)| (*key, *scope)).collect(); + assert_eq!(contexts.len(), sv::CONTEXT.len(), "duplicate Swedish context keys"); + for (key, context, expected) in sv::CONTEXT { + assert_eq!(placeholders(key), placeholders(expected), "placeholders: {key} ({context})"); + assert_eq!(tr_context("sv", key, context), *expected, "sv {context}: {key}"); + } + assert_eq!(tr("sv", "File"), "Arkiv"); + assert_eq!(tr("sv", "Save As…"), "Spara som…"); + assert_eq!(tr("sv", "Unknown label"), "Unknown label"); + assert!(!is_rtl("sv")); + assert_eq!(count_label("sv", "pages", 5), "5 sidor"); + assert_eq!(count_label("sv", "pages", 1), "1 sida"); + assert_eq!(count_label("sv", "warnings", 1), "1 varning"); + assert_eq!(count_label("sv", "errors", 1), "1 fel"); + } +} + /// `name` lowercased with the Latin accents that occur in language names folded away, so a /// byte-wise sort reads alphabetically. Other scripts are left as they are. fn name_sort_key(name: &str) -> String { diff --git a/crates/ui-egui/src/i18n/hu.rs b/crates/ui-egui/src/i18n/hu.rs new file mode 100644 index 000000000..890959761 --- /dev/null +++ b/crates/ui-egui/src/i18n/hu.rs @@ -0,0 +1,1963 @@ +//! Hungarian interface translation, prepared with AI assistance and initially reviewed +//! by a native Hungarian contributor with 30+ years of DTP experience. +//! Further terminology and in-context UI review is welcome. +//! Uncatalogued keys fall back to English. +pub(super) const TABLE: &[(&str, &str)] = &[ + ("Redefine Style", "Stílus újradefiniálása"), + ("Alt-click clears overrides", "Alt-kattintás: felülírások törlése"), + ("Apply \"{name}\", Clear Overrides", "„{name}” alkalmazása, felülírások törlése"), + (" Close ", " Bezárás "), + (" New file ", " Új fájl "), + (" OK ", " OK "), + (" Open ", " Megnyitás "), + (" Open sample magazine ", " Mintaújság megnyitása "), + (" (auto)", " (automatikus)"), + ("(Text Color)", "(Szövegszín)"), + ("(Top Level)", "(Legfelső szint)"), + ("(import)", "(importálás)"), + ("180°", "180°"), + ("90° CCW", "90° balra"), + ("90° CW", "90° jobbra"), + ("A, B, C, D...", "A, B, C, D..."), + ("About DesignCraft", "A DesignCraft névjegye"), + ("Absolute Colorimetric", "Abszolút kolorimetrikus"), + ("Absolute Numbering (instead of Section Numbering)", "Abszolút oldalszámozás (szakasz szerinti helyett)"), + ("Accept", "Elfogadás"), + ("Accept All", "Összes elfogadása"), + ("Accept All Changes", "Összes módosítás elfogadása"), + ("Accept Change", "Módosítás elfogadása"), + ("Activate Document", "Dokumentum aktiválása"), + ("Activate Panel", "Panel aktiválása"), + ("Actual Size", "Tényleges méret"), + ("Add", "Hozzáadás"), + ("Add Anchor", "Csomópont hozzáadása"), + ("Add Anchor Point", "Csomópont hozzáadása"), + ("Add Document", "Dokumentum hozzáadása"), + ("Add Document…", "Dokumentum hozzáadása…"), + ("Add Hyphenation Exception", "Elválasztási kivétel hozzáadása"), + ("Add Item", "Elem hozzáadása"), + ("Add Page to Spread", "Oldal hozzáadása az oldalpárhoz"), + ("Add Selection", "Kijelölt elemek hozzáadása"), + ("Add Selection to Article", "Kijelölt elemek hozzáadása a cikkhez"), + ("Add Unnamed Colors", "Névtelen színek hozzáadása"), + ( + "Add and remove pages as the primary text frame's story grows and shrinks", + "Oldalak hozzáadása és eltávolítása az elsődleges szövegkeret szövegfolyamának hosszához igazodva", + ), + ("Add the selection", "Kijelölt elemek hozzáadása"), + ("Add to Dictionary", "Hozzáadás a szótárhoz"), + ("Add to Flex Layout", "Hozzáadás a rugalmas elrendezéshez"), + ("Add to Previous Spread", "Hozzáadás az előző oldalpárhoz"), + ("Add to Swatches", "Hozzáadás a színtárhoz"), + ("Added", "Hozzáadva"), + ("Added Text (highlighted)", "Beszúrt szöveg (kiemelve)"), + ("Adjust Layout", "Elrendezés igazítása"), + ("Adjust Layout (objects follow the new page size)", "Elrendezés igazítása (az objektumok követik az új oldalméretet)"), + ("Advanced", "Haladó"), + ("Advanced Character Formats", "Speciális karakterformázás"), + ("Advanced Type", "Speciális szövegbeállítások"), + ("After", "Utána"), + ("After First:", "Az első után:"), + ("Align", "Igazítás"), + ("Align Center", "Középre igazítás"), + ("Align From:", "Igazítás alapja:"), + ("Align Left", "Balra igazítás"), + ("Align Left Edge", "Bal szél igazítása"), + ("Align Right", "Jobbra igazítás"), + ("Align Stroke:", "Körvonal igazítása:"), + ("Align away from spine", "Igazítás a gerinctől kifelé"), + ("Align bottom edges", "Alsó szélek igazítása"), + ("Align center", "Középre igazítás"), + ("Align horizontal centers", "Vízszintes középpontok igazítása"), + ("Align left", "Balra igazítás"), + ("Align left edges", "Bal szélek igazítása"), + ("Align right", "Jobbra igazítás"), + ("Align right edges", "Jobb szélek igazítása"), + ("Align to Key Object", "Igazítás a kulcsobjektumhoz"), + ("Align to Margins", "Igazítás a margókhoz"), + ("Align to Object Centers", "Igazítás az objektumok középpontjához"), + ("Align to Object Edges", "Igazítás az objektumok széléhez"), + ("Align to Page", "Igazítás az oldalhoz"), + ("Align to Selection", "Igazítás a kijelöléshez"), + ("Align to Spread", "Igazítás az oldalpárhoz"), + ("Align to baseline grid", "Igazítás az alapvonalrácshoz"), + ("Align top edges", "Felső szélek igazítása"), + ("Align towards spine", "Igazítás a gerinc felé"), + ("Align vertical centers", "Függőleges középpontok igazítása"), + ("Alignment", "Igazítás"), + ("Alignment:", "Igazítás:"), + ("All Caps", "Nagybetűk"), + ("All Documents", "Összes dokumentum"), + ("All Spots to Process", "Összes direktszín átalakítása nyomdai alapszínekké"), + ("All records", "Összes rekord"), + ("Allow Selected Spread to Shuffle", "Kijelölt oldalpár oldalainak átrendezése engedélyezett"), + ("Allow Spread to Shuffle", "Oldalpár oldalainak átrendezése engedélyezett"), + ("Alpha Channel", "Alfa-csatorna"), + ("Alternating Row Fills", "Váltakozó sorkitöltések"), + ("Anchored Object", "Rögzített objektum"), + ("Anchored Object Options", "Rögzített objektum beállításai"), + ("Anchored Object Options…", "Rögzített objektum beállításai…"), + ("Anchored Objects", "Rögzített objektumok"), + ("Angle", "Szög"), + ("Angle:", "Szög:"), + ("Appearance", "Megjelenés"), + ("Appearance of Black", "Fekete megjelenítése"), + ("Applies to fill", "A kitöltésre vonatkozik"), + ("Applies to text", "A szövegre vonatkozik"), + ("Apply", "Alkalmazás"), + ("Apply Attributes (Eyedropper", "Tulajdonságok alkalmazása (pipetta"), + ("Apply Attributes (Eyedropper)", "Tulajdonságok alkalmazása (pipetta)"), + ("Apply Cell Style", "Cellastílus alkalmazása"), + ("Apply Character Style", "Karakterstílus alkalmazása"), + ("Apply Color", "Szín alkalmazása"), + ("Apply Color (,)", "Szín alkalmazása (,)"), + ("Apply Condition", "Feltétel alkalmazása"), + ("Apply Gradient", "Színátmenet alkalmazása"), + ("Apply Gradient (.)", "Színátmenet alkalmazása (.)"), + ("Apply None", "Szín eltávolítása"), + ("Apply None (/)", "Szín eltávolítása (/)"), + ("Apply Normal", "Normál karakterhelyzet"), + ("Apply Object Style", "Objektumstílus alkalmazása"), + ("Apply Paragraph Style", "Bekezdésstílus alkalmazása"), + ("Apply Parent", "Mesteroldal alkalmazása"), + ("Apply Parent to Pages", "Mesteroldal alkalmazása az oldalakra"), + ("Apply Parent to Pages…", "Mesteroldal alkalmazása az oldalakra…"), + ("Apply Style:", "Alkalmazandó stílus:"), + ("Apply Subscript", "Alsó index alkalmazása"), + ("Apply Superscript", "Felső index alkalmazása"), + ("Apply Table Style", "Táblázatstílus alkalmazása"), + ("Apply to All Spreads", "Alkalmazás az összes oldalpárra"), + ("Apply to Stroke", "Alkalmazás a körvonalra"), + ("Arabic", "Arab"), + ("Arrange", "Sorrend"), + ("Arrangement", "Elrendezés"), + ("Art", "Grafika"), + ("ArtCraft App Page", "ArtCraft alkalmazásoldal"), + ("ArtCraft App Page…", "ArtCraft alkalmazásoldal…"), + ("ArtCraft Website", "ArtCraft weboldala"), + ("ArtCraft Website…", "ArtCraft weboldala…"), + ("Article Options", "Cikk beállításai"), + ("Articles", "Cikkek"), + ("Ascent", "Felső betűszármagasság"), + ("At Least", "Legalább"), + ("Attributes", "Tulajdonságok"), + ("Auto", "Automatikus"), + ("Auto Size", "Automatikus méretezés"), + ("Auto-Fit", "Automatikus illesztés"), + ("Autocorrect", "Automatikus javítás"), + ("Bar", "Vonás"), + ("Barbed", "Szakállas nyíl"), + ("Based On:", "Alapstílus:"), + ("Baseline", "Alapvonal"), + ("Baseline Grid", "Alapvonalrács"), + ("Baseline Shift:", "Alapvonal-eltolás:"), + ("Basic Character Formats", "Alapvető karakterformázás"), + ("Basic Feather", "Alapvető lágyítás"), + ("Before", "Előtte"), + ("Before Last:", "Az utolsó előtt:"), + ("Between syllables (not only at spaces)", "Szótagok között (nem csak szóközöknél)"), + ("Bevel", "Levágott sarok"), + ("Bevel and Emboss", "Domborítás"), + ("Beveled Rectangle", "Levágott sarkú téglalap"), + ("Bind to frame", "Hozzárendelés a kerethez"), + ("Binding", "Kötésirány"), + ("Binding:", "Kötésirány:"), + ("Black", "Fekete"), + ("Bleed", "Kifutó"), + ("Bleed Marks", "Kifutójelek"), + ("Bleed and Slug", "Kifutó és infóterület"), + ("Bleed:", "Kifutó:"), + ("Blinds", "Redőny"), + ("Body Rows", "Törzssorok"), + ("Bold", "Félkövér"), + ("Book", "Könyv"), + ("Bookmarks", "Könyvjelzők"), + ("Border", "Szegély"), + ("Both", "Mindkettő"), + ("Bottom", "Alul"), + ("Bottom Inset", "Alsó belső margó"), + ("Bottom:", "Lent:"), + ("Box", "Doboz"), + ("Break Link to Style", "Stíluskapcsolat megszüntetése"), + ("Break Thread", "Szövegkeret-lánc megszakítása"), + ("Bring Forward", "Egy szinttel előrébb"), + ("Bring to Front", "Előtérbe hozás"), + ("Bullet Character", "Felsorolásjel"), + ("Bulleted & Numbered Lists", "Felsorolások és számozott listák"), + ("Bulleted List", "Felsorolás"), + ("Bulleted and Numbered Lists", "Felsorolások és számozott listák"), + ("Bullets and Numbering", "Felsorolás és számozás"), + ("Business Card", "Névjegykártya"), + ("Butt", "Tompa vonalvég"), + ("Buttons", "Gombok"), + ("Buttons act in interactive PDF export.", "A gombok interaktív PDF-exportban működnek."), + ("Buttons and Forms", "Gombok és űrlapok"), + ("CMYK", "CMYK"), + ("CMYK:", "CMYK:"), + ("Can't Open the File", "A fájl nem nyitható meg"), + ("Can't Place the File", "A fájl nem helyezhető el"), + ("Cancel", "Mégse"), + ("Cap Height", "Nagybetűmagasság"), + ("Cap:", "Vonalvég:"), + ("Captions", "Képaláírások"), + ("Case sensitive", "Kis- és nagybetű megkülönböztetése"), + ("Case:", "Betűváltozat:"), + ("Cell Options", "Cellabeállítások"), + ("Cell Style", "Cellastílus"), + ("Cell Style Options…", "Cellastílus beállításai…"), + ("Cell Text", "Cellaszöveg"), + ("Cell Type", "Cellatípus"), + ("Center", "Középre"), + ("Center Content", "Tartalom középre igazítása"), + ("Center in frame", "Középre igazítás a keretben"), + ("Change", "Csere"), + ("Change All", "Összes cseréje"), + ("Change All (Object", "Összes cseréje (objektum"), + ("Change All (Object)", "Összes cseréje (objektum)"), + ("Change Case", "Kis- és nagybetűk váltása"), + ("Change Panel Layout", "Panelelrendezés módosítása"), + ("Change To", "Csere erre"), + ("Change to:", "Csere erre:"), + ("Changes", "Módosítások"), + ("Character", "Karakter"), + ("Character Color", "Karakter színe"), + ("Character Formatting", "Karakterformázás"), + ("Character Settings", "Karakterbeállítások"), + ("Character Style Options", "Karakterstílus beállításai"), + ("Character Style Options…", "Karakterstílus beállításai…"), + ("Character Style:", "Karakterstílus:"), + ("Character Styles", "Karakterstílusok"), + ("Character Styles panel", "Karakterstílusok panel"), + ("Characters", "Karakterek"), + ("Characters:", "Karakterek:"), + ("Check Box", "Jelölőnégyzet"), + ("Check Spelling", "Helyesírás-ellenőrzés"), + ("Check Spelling…", "Helyesírás-ellenőrzés…"), + ("Checked by default", "Alapértelmezés szerint bejelölve"), + ("Chinese", "Kínai"), + ("Choices", "Választási lehetőségek"), + ("Choose Image…", "Kép kiválasztása…"), + ("Choose a link.", "Válasszon egy csatolást."), + ("Circle", "Kör"), + ("Circle - Solid", "Kitöltött kör"), + ("Class:", "Osztály:"), + ("Clear", "Törlés"), + ("Clear Conveyor", "Tartalomgyűjtő kiürítése"), + ("Clear Rotation", "Elforgatás törlése"), + ("Clear Transformations", "Átalakítások törlése"), + ("Clear overrides", "Helyi felülírások törlése"), + ("Click to pin the object relative to the page edge.", "Kattintson az objektum oldalszélhez rögzítéséhez."), + ("Clipping Path", "Vágógörbe"), + ("Clipping Path…", "Vágógörbe…"), + ("Close", "Bezárás"), + ("Close Book", "Könyv bezárása"), + ("Close Library", "Könyvtár bezárása"), + ("Close Panel", "Panel bezárása"), + ("Close Path", "Görbe bezárása"), + ("Closed Path", "Zárt görbe"), + ("Col ←", "Oszlop ←"), + ("Col →", "Oszlop →"), + ("Collect", "Gyűjtés"), + ( + "Collect objects with the Content Collector (B); place them with the Content Placer.", + "Gyűjtse össze az objektumokat a Tartalomgyűjtővel (B), majd helyezze el őket a Tartalomelhelyezővel.", + ), + ("Color", "Szín"), + ("Color Blindness – Deuteranopia", "Színtévesztés – deuteranópia"), + ("Color Blindness – Protanopia", "Színtévesztés – protanópia"), + ("Color Group Options", "Színcsoport beállításai"), + ("Color Picker", "Színválasztó"), + ("Color Settings", "Színbeállítások"), + ("Color Settings…", "Színbeállítások…"), + ("Color:", "Szín:"), + ("Colour", "Szín"), + ("Colour Picker", "Színválasztó"), + ("Column", "Hasáb"), + ("Column Break", "Hasábtörés"), + ("Column Rules", "Hasábelválasztó vonalak"), + ("Column Width", "Oszlopszélesség"), + ("Column spacing", "Oszlopköz"), + ("Columns", "Hasábok"), + ("Columns first", "Először az oszlopok"), + ("Columns:", "Hasábok:"), + ("Comb", "Fésű"), + ("Combo Box", "Kombinált lista"), + ("Commercial Printing", "Nyomdai előállítás"), + ("Community", "Közösség"), + ("Community & Project Links", "Közösségi és projekthivatkozások"), + ("Composer", "Tördelő"), + ("Composer:", "Tördelő:"), + ("Composition", "Tördelés"), + ("Compress images", "Képek tömörítése"), + ("Compression", "Tömörítés"), + ("Condition Options…", "Feltétel beállításai…"), + ("Conditional Text", "Feltételes szöveg"), + ("Conditions", "Feltételek"), + ("Constrain proportions", "Arányok megtartása"), + ("Constrain proportions for width and height", "Szélesség és magasság arányának megtartása"), + ("Container", "Tároló"), + ("Content", "Tartalom"), + ("Content Fitting", "Tartalom illesztése"), + ("Content:", "Tartalom:"), + ("Contextual Alternates", "Környezetfüggő változatok"), + ("Contextual Task Bar", "Környezetfüggő feladatsáv"), + ("Control", "Vezérlő"), + ("Controlled by Parent", "A mesteroldal határozza meg"), + ("Convert Cell Type", "Cellatípus átalakítása"), + ("Convert Cell to Graphic Cell", "Cella átalakítása grafikus cellává"), + ("Convert Cell to Graphic Cell…", "Cella átalakítása grafikus cellává…"), + ("Convert Cell to Text Cell", "Cella átalakítása szöveges cellává"), + ("Convert Color", "Szín átalakítása"), + ("Convert Direction Point", "Irányítópont átalakítása"), + ("Convert Note to Text", "Jegyzet átalakítása szöveggé"), + ("Convert Point", "Pont átalakítása"), + ("Convert Point:", "Pont átalakítása:"), + ("Convert Selection to Multi-State Object", "Kijelölés átalakítása többállapotú objektummá"), + ("Convert Shape", "Alakzat átalakítása"), + ("Convert Shape:", "Alakzat átalakítása:"), + ("Convert Table to Text", "Táblázat átalakítása szöveggé"), + ("Convert Text to Table", "Szöveg átalakítása táblázattá"), + ("Convert to Button", "Átalakítás gombbá"), + ("Convert to Flex Layout", "Átalakítás rugalmas elrendezéssé"), + ("Convert to Form Field", "Átalakítás űrlapmezővé"), + ("Convert to Liquid Guide", "Átalakítás alkalmazkodó segédvonallá"), + ("Convert to Object", "Átalakítás objektummá"), + ("Convert to Text", "Átalakítás szöveggé"), + ("Conveyor", "Tartalomgyűjtő tálca"), + ("Copies:", "Példányszám:"), + ("Copy", "Másolás"), + ("Copy Link(s", "Csatolások másolása"), + ("Copy Link(s) To…", "Csatolások másolása ide…"), + ("Copyright Symbol", "Szerzői jog jele"), + ("Corner", "Sarok"), + ("Corner Options", "Sarokbeállítások"), + ("Corner Options…", "Sarokbeállítások…"), + ("Count", "Darabszám"), + ("Count:", "Darabszám:"), + ("Cover", "Borítás"), + ("Create", "Létrehozás"), + ("Create Alternate Layout", "Alternatív elrendezés létrehozása"), + ("Create Alternate Layout…", "Alternatív elrendezés létrehozása…"), + ("Create Flex Layout", "Rugalmas elrendezés létrehozása"), + ("Create Frame", "Keret létrehozása"), + ("Create Guides", "Segédvonalak létrehozása"), + ("Create Guides…", "Segédvonalak létrehozása…"), + ("Create Line", "Vonal létrehozása"), + ("Create Links When Placing Text Files", "Csatolások létrehozása szövegfájlok elhelyezésekor"), + ("Create Merged Document…", "Egyesített dokumentum létrehozása…"), + ("Create New Layer", "Új réteg létrehozása"), + ("Create New Style from Selection", "Új stílus létrehozása a kijelölésből"), + ("Create Outlines", "Görbévé alakítás"), + ("Create Path", "Görbe létrehozása"), + ("Create Table", "Táblázat létrehozása"), + ("Create Table…", "Táblázat létrehozása…"), + ("Create as a grid", "Létrehozás rácsként"), + ("Create new page", "Új oldal létrehozása"), + ("Create new style", "Új stílus létrehozása"), + ("Crop", "Vágás"), + ("Crop Amount", "Vágás mértéke"), + ("Crop Marks", "Vágójelek"), + ("Crop to:", "Vágás határa:"), + ("Cross-Reference Format", "Kereszthivatkozás formátuma"), + ("Cross-Reference Formats", "Kereszthivatkozás-formátumok"), + ("Cross-References", "Kereszthivatkozások"), + ("Current Page Number", "Aktuális oldalszám"), + ("Cursor Key:", "Kurzorgomb lépésköze:"), + ("Curved", "Ívelt"), + ("Custom", "Egyéni"), + ("Custom Page Size…", "Egyéni oldalméret…"), + ("Custom Tracking/Kerning", "Egyéni betűköz/alávágás"), + ("Cut", "Kivágás"), + ("Cyan", "Cián"), + ("Czech", "Cseh"), + ("Danish", "Dán"), + ("Dark", "Sötét"), + ("Dashed", "Szaggatott"), + ("Data Fields", "Adatmezők"), + ("Data Merge", "Adategyesítés"), + ("Data Merge Fields", "Adategyesítési mezők"), + ("Data Merge Options", "Adategyesítés beállításai"), + ("Decrease Point Size", "Betűméret csökkentése"), + ("Default", "Alapértelmezett"), + ("Default Figure Style", "Alapértelmezett számjegystílus"), + ("Default Fill and Stroke", "Alapértelmezett kitöltés és körvonal"), + ("Default Fill and Stroke (D)", "Alapértelmezett kitöltés és körvonal (D)"), + ("Default View:", "Alapértelmezett nézet:"), + ("Define Cross-Reference Format", "Kereszthivatkozás-formátum meghatározása"), + ("Define Cross-Reference Format…", "Kereszthivatkozás-formátum meghatározása…"), + ("Define Lists", "Listák meghatározása"), + ("Define Lists…", "Listák meghatározása…"), + ("Define Text Variable", "Szövegváltozó meghatározása"), + ("Define Text Variable…", "Szövegváltozó meghatározása…"), + ("Delete", "Törlés"), + ("Delete All Guides on Spread", "Oldalpár összes segédvonalának törlése"), + ("Delete Anchor Point", "Csomópont törlése"), + ("Delete Article", "Cikk törlése"), + ("Delete Bookmark", "Könyvjelző törlése"), + ("Delete Character Style", "Karakterstílus törlése"), + ("Delete Character Style…", "Karakterstílus törlése…"), + ("Delete Column", "Oszlop törlése"), + ("Delete Condition", "Feltétel törlése"), + ("Delete DTD", "DTD törlése"), + ("Delete Endnote", "Végjegyzet törlése"), + ("Delete Footnote", "Lábjegyzet törlése"), + ("Delete Guide", "Segédvonal törlése"), + ("Delete Hyperlink", "Hiperhivatkozás törlése"), + ("Delete Item", "Elem törlése"), + ("Delete Layer", "Réteg törlése"), + ("Delete List", "Lista törlése"), + ("Delete Note", "Jegyzet törlése"), + ("Delete Page", "Oldal törlése"), + ("Delete Pages", "Oldalak törlése"), + ("Delete Paragraph Style", "Bekezdésstílus törlése"), + ("Delete Paragraph Style…", "Bekezdésstílus törlése…"), + ("Delete Row", "Sor törlése"), + ("Delete Spread", "Oldalpár törlése"), + ("Delete Stroke Style", "Körvonalstílus törlése"), + ("Delete Swatch", "Színminta törlése"), + ("Delete Table", "Táblázat törlése"), + ("Delete Tag", "Címke törlése"), + ("Delete Text", "Szöveg törlése"), + ("Delete Text Variable", "Szövegváltozó törlése"), + ("Delete Type from Path", "Görbére írt szöveg törlése"), + ("Delete Unused Layers", "Nem használt rétegek törlése"), + ("Delete Workspace", "Munkaterület törlése"), + ("Delete Workspace…", "Munkaterület törlése…"), + ("Delete selected pages", "Kijelölt oldalak törlése"), + ("Delete the character style \"{name}\"?", "Törli a(z) „{name}” karakterstílust?"), + ("Delete the paragraph style \"{name}\"?", "Törli a(z) „{name}” bekezdésstílust?"), + ("Deleted", "Törölve"), + ("Deselect All", "Kijelölés megszüntetése"), + ("DesignCraft", "DesignCraft"), + ("DesignCraft Website", "DesignCraft weboldala"), + ("DesignCraft Website…", "DesignCraft weboldala…"), + ("DesignCraft on GitHub", "DesignCraft a GitHubon"), + ("DesignCraft on GitHub…", "DesignCraft a GitHubon…"), + ("Desired", "Kívánt"), + ("Desktop Printing", "Asztali nyomtatás"), + ("Detach All Objects from Parent", "Összes objektum leválasztása a mesteroldalról"), + ("Detect Edges", "Szélek felismerése"), + ("Dialog", "Párbeszédablak"), + ("Dictionary", "Szótár"), + ("Digital Publishing", "Digitális kiadványkészítés"), + ("Digits", "Számjegyek"), + ("Dimensions Include Stroke Weight", "A méretek tartalmazzák a körvonal vastagságát"), + ("Direction", "Irány"), + ("Directional Feather", "Irányított lágyítás"), + ("Discretionary Hyphen", "Feltételes elválasztójel"), + ("Discretionary Ligatures", "Tetszőleges ligatúrák"), + ("Display All Blacks Accurately", "Minden fekete pontos megjelenítése"), + ("Display All Blacks as Rich Black", "Minden fekete megjelenítése dús feketeként"), + ("Display Performance", "Megjelenítési teljesítmény"), + ("Dissolve", "Áttűnés"), + ("Distance", "Távolság"), + ("Distribute", "Elosztás"), + ("Distribute Columns Evenly", "Oszlopok egyenletes elosztása"), + ("Distribute Rows Evenly", "Sorok egyenletes elosztása"), + ("Distribute ↔", "Elosztás ↔"), + ("Distribute ↕", "Elosztás ↕"), + ("Dock Panel", "Panel dokkolása"), + ("Dock panel", "Panel dokkolása"), + ("Document", "Dokumentum"), + ("Document CMYK", "Dokumentum CMYK-színtere"), + ("Document Endnote Options", "Dokumentum végjegyzet-beállításai"), + ("Document Endnote Options…", "Dokumentum végjegyzet-beállításai…"), + ("Document Footnote Options", "Dokumentum lábjegyzet-beállításai"), + ("Document Footnote Options...", "Dokumentum lábjegyzet-beállításai..."), + ("Document Footnote Options…", "Dokumentum lábjegyzet-beállításai…"), + ("Document Grid", "Dokumentumrács"), + ("Document Preferences", "Dokumentumbeállítások"), + ("Document Presets", "Dokumentumkészletek"), + ("Document RGB", "Dokumentum RGB-színtere"), + ("Document Recovery Data", "Dokumentum helyreállítási adatai"), + ("Document Setup", "Dokumentum beállításai"), + ("Document Setup…", "Dokumentum beállításai…"), + ("Document…", "Dokumentum…"), + ("Don't Save", "Ne mentse"), + ("Done", "Kész"), + ("Dotted", "Pontozott"), + ("Double Left Quotation Marks", "Bal oldali dupla idézőjel"), + ("Double Right Quotation Marks", "Jobb oldali dupla idézőjel"), + ("Drag Rows or Columns", "Sorok vagy oszlopok húzása"), + ("Draw Missing Glyphs from Fallback Fonts", "Hiányzó karakterjelek megjelenítése helyettesítő betűtípusból"), + ("Drop Caps", "Iniciálék"), + ("Drop Caps and Nested Styles", "Iniciálék és beágyazott stílusok"), + ("Drop Chars", "Iniciálé karaktereinek száma"), + ("Drop Lines", "Iniciálé sorainak száma"), + ("Drop Shadow", "Vetett árnyék"), + ("Duplicate", "Másolat készítése"), + ("Duplicate Spread", "Oldalpár másolása"), + ("Duplicate Spread at End of Document", "Oldalpár másolása a dokumentum végére"), + ("Dutch: 2005 Reform", "Holland: 2005-ös reform"), + ("Dynamic Spelling", "Folyamatos helyesírás-ellenőrzés"), + ("EPUB and HTML", "EPUB és HTML"), + ("Edit", "Szerkesztés"), + ("Edit \"{name}\"…", "„{name}” szerkesztése…"), + ("Edit Endnote", "Végjegyzet szerkesztése"), + ("Edit Note", "Jegyzet szerkesztése"), + ("Edit Page", "Oldal szerkesztése"), + ("Edit Parents", "Mesteroldalak szerkesztése"), + ("Edit Story", "Szövegfolyam szerkesztése"), + ("Edit in Story Editor", "Szerkesztés a szövegszerkesztőben"), + ("Edit page size", "Oldalméret szerkesztése"), + ("Edit/Interface Language", "Szerkesztés/Felület nyelve"), + ("Edit/Spelling", "Szerkesztés/Helyesírás"), + ("Edit/Transparency Blend Space", "Szerkesztés/Átlátszóság keverési színtere"), + ("Edit/Transparency Flattener Presets", "Szerkesztés/Átlátszóság-összeolvasztási készletek"), + ("Editorial", "Szerkesztőség"), + ("Effects", "Hatások"), + ("Effects: Drop Shadow", "Hatások: vetett árnyék"), + ("Ellipse", "Ellipszis"), + ("Ellipsis", "Három pont"), + ("Em Box Height", "Négyzet magassága"), + ("Em Dash", "Hosszú gondolatjel"), + ("Em Space", "Négyzetnyi szóköz"), + ("Email", "E-mail"), + ("Embed", "Beágyazás"), + ("Embed Link", "Csatolás beágyazása"), + ("Embedded", "Beágyazva"), + ("En Dash", "Félkvirtmínusz"), + ("En Space", "Félnégyzetnyi szóköz"), + ("Enable Autocorrect", "Automatikus javítás engedélyezése"), + ("Enable Dynamic Spelling (underline misspelled words)", "Folyamatos helyesírás-ellenőrzés (hibás szavak aláhúzása)"), + ("Endnotes", "Végjegyzetek"), + ("English: Canadian", "Angol: kanadai"), + ("English: UK", "Angol: brit"), + ("English: USA", "Angol: amerikai"), + ("Entire Pasteboard", "Teljes munkaterület"), + ("Erase", "Radírozás"), + ("Essentials", "Alapok"), + ("Essentials Classic", "Klasszikus alapok"), + ("Even Page Break", "Páros oldaltörés"), + ("Exactly", "Pontosan"), + ("Exclude Overlap", "Átfedés kizárása"), + ("Export", "Exportálás"), + ("Export Book to PDF…", "Könyv exportálása PDF-be…"), + ("Export EPUB", "EPUB exportálása"), + ("Export EPUB (Fixed Layout", "Rögzített elrendezésű EPUB exportálása"), + ("Export EPUB (Fixed Layout)", "Rögzített elrendezésű EPUB exportálása"), + ("Export EPUB (Fixed Layout)…", "Rögzített elrendezésű EPUB exportálása…"), + ("Export EPUB (Reflowable", "Újratördelhető EPUB exportálása"), + ("Export EPUB (Reflowable)", "Újratördelhető EPUB exportálása"), + ("Export EPUB (Reflowable)…", "Újratördelhető EPUB exportálása…"), + ("Export EPUB…", "EPUB exportálása…"), + ("Export HTML", "HTML exportálása"), + ("Export HTML…", "HTML exportálása…"), + ("Export IDML", "IDML exportálása"), + ("Export IDML…", "IDML exportálása…"), + ("Export PDF", "PDF exportálása"), + ("Export PDF (Interactive)", "Interaktív PDF exportálása"), + ("Export PDF (Interactive)…", "Interaktív PDF exportálása…"), + ("Export PDF…", "PDF exportálása…"), + ("Export Page as PNG", "Oldal exportálása PNG-ként"), + ("Export Page as PNG…", "Oldal exportálása PNG-ként…"), + ("Export PowerPoint…", "PowerPoint exportálása…"), + ("Export Selection as Snippet", "Kijelölés exportálása részletként"), + ("Export Tagging", "Exportcímkézés"), + ("Export Text", "Szöveg exportálása"), + ("Export Text…", "Szöveg exportálása…"), + ("Export XML", "XML exportálása"), + ("Export XML…", "XML exportálása…"), + ("Extend Text Selection", "Szövegkijelölés kiterjesztése"), + ("Extras", "Kiegészítők"), + ("Facing Pages", "Szemközti oldalak"), + ("Fade", "Elhalványulás"), + ("Farsi", "Perzsa"), + ("Fast", "Gyors"), + ("Fast Display", "Gyors megjelenítés"), + ("Favorites", "Kedvencek"), + ("Figure Space", "Számjegynyi szóköz"), + ("Figure Style:", "Számjegystílus:"), + ("File", "Fájl"), + ("File Handling", "Fájlkezelés"), + ("File/Export", "Fájl/Exportálás"), + ("Fill", "Kitöltés"), + ("Fill (X)", "Kitöltés (X)"), + ("Fill Frame Proportionally", "Keret arányos kitöltése"), + ("Fill proportionally", "Arányos kitöltés"), + ("Fill with Placeholder Text", "Kitöltés helykitöltő szöveggel"), + ("Find", "Keresés"), + ("Find All", "Összes keresése"), + ("Find Next", "Következő keresése"), + ("Find Object", "Objektum keresése"), + ("Find What", "Keresett szöveg"), + ("Find by Script Label", "Keresés parancsfájlcímke alapján"), + ("Find what:", "Keresett szöveg:"), + ("Find/Change", "Keresés és csere"), + ("Find/Change…", "Keresés és csere…"), + ("Find/Replace Font", "Betűtípus keresése és cseréje"), + ("Find/Replace Font…", "Betűtípus keresése és cseréje…"), + ("Finnish", "Finn"), + ("First", "Első"), + ("First Baseline", "Első alapvonal"), + ("First Line Indent:", "Első sor behúzása:"), + ("First Object Above", "Legfelső objektum"), + ("First Page", "Első oldal"), + ("First Spread", "Első oldalpár"), + ("Fit Content Proportionally", "Tartalom arányos illesztése"), + ("Fit Content to Frame", "Tartalom igazítása a kerethez"), + ("Fit Frame to Content", "Keret igazítása a tartalomhoz"), + ("Fit Guides to:", "Segédvonalak igazítása ehhez:"), + ("Fit Page in Window", "Oldal igazítása az ablakhoz"), + ("Fit Selection in Window", "Kijelölés igazítása az ablakhoz"), + ("Fit Spread in Window", "Oldalpár igazítása az ablakhoz"), + ("Fit Text", "Szöveg illesztése"), + ("Fit content to frame", "Tartalom igazítása a kerethez"), + ("Fit frame height to text", "Keretmagasság igazítása a szöveghez"), + ("Fit proportionally", "Arányos illesztés"), + ("Fitting", "Illesztés"), + ("Fitting:", "Illesztés:"), + ("Fixed", "Rögzített"), + ("Flattener Preview", "Lapítási előnézet"), + ("Flattener preset", "Lapítási készlet"), + ("Flex End", "Rugalmas elrendezés vége"), + ("Flex Layout", "Rugalmas elrendezés"), + ("Flex Layout Options", "Rugalmas elrendezés beállításai"), + ("Flex Start", "Rugalmas elrendezés eleje"), + ("Flip", "Tükrözés"), + ("Flip Horizontal", "Vízszintes tükrözés"), + ("Flip Vertical", "Függőleges tükrözés"), + ("Float Panel", "Panel lebegtetése"), + ("Float panel", "Panel lebegtetése"), + ("Flush Space", "Kitöltő szóköz"), + ("Font", "Betűtípus"), + ("Font Family:", "Betűcsalád:"), + ("Font Size:", "Betűméret:"), + ("Font Style:", "Betűváltozat:"), + ("Fonts in Document", "Betűtípusok a dokumentumban"), + ("Fonts in Document: {count} Missing: {missing}", "Betűtípusok a dokumentumban: {count} Hiányzik: {missing}"), + ("Footer Rows", "Láblécsorok"), + ("Footnote Formatting", "Lábjegyzet formázása"), + ("Footnote Options", "Lábjegyzet beállításai"), + ("Footnote Reference", "Lábjegyzethivatkozás"), + ("Footnote Reference Number in Text", "Lábjegyzethivatkozás száma a szövegben"), + ("Footnote Text", "Lábjegyzet szövege"), + ("Footnotes", "Lábjegyzetek"), + ("Forced Line Break", "Kényszerített sortörés"), + ("Form Field", "Űrlapmező"), + ("Form Fields", "Űrlapmezők"), + ("Format:", "Formátum:"), + ("Formatting Affects Text", "A formázás a szövegre vonatkozik"), + ("Formatting affects container (J)", "A formázás a tárolóra vonatkozik (J)"), + ("Formatting affects text (J)", "A formázás a szövegre vonatkozik (J)"), + ("Fractions", "Törtek"), + ("Frame Break", "Kerettörés"), + ("Frame Edges", "Keretek szélei"), + ("Frame Fitting", "Keretillesztés"), + ("Frame Fitting Options", "Keretillesztés beállításai"), + ("Frame Fitting Options…", "Keretillesztés beállításai…"), + ("French", "Francia"), + ("French: Canadian", "Francia: kanadai"), + ("GREP", "GREP"), + ("GREP Style", "GREP-stílus"), + ("GREP Styles", "GREP-stílusok"), + ("Gap Color:", "Hézag színe:"), + ("General", "Általános"), + ("Generate Index", "Tárgymutató létrehozása"), + ("Generate Index…", "Tárgymutató létrehozása…"), + ("Generate Live Caption", "Élő képaláírás létrehozása"), + ("Generate QR Code", "QR-kód létrehozása"), + ("Generate QR Code…", "QR-kód létrehozása…"), + ("Generate Static Caption", "Statikus képaláírás létrehozása"), + ("Georgian", "Grúz"), + ("German: 2006 Reform", "Német: 2006-os reform"), + ("German: Swiss 2006 Reform", "Német: svájci, 2006-os reform"), + ("Get Story", "Szövegfolyam lekérése"), + ("Get Table", "Táblázat lekérése"), + ( + "Get help, share your layouts and shape what we build next.", + "Kérjen segítséget, mutassa meg kiadványait, és alakítsa velünk a következő fejlesztéseket.", + ), + ("Global Light", "Globális megvilágítás"), + ("Global Light…", "Globális megvilágítás…"), + ("Glyph Scaling:", "Karakterjel méretezése:"), + ("Glyphs", "Karakterjelek"), + ("Go To", "Ugrás"), + ("Go To First Page", "Ugrás az első oldalra"), + ("Go To Last Page", "Ugrás az utolsó oldalra"), + ("Go To Link", "Ugrás a csatoláshoz"), + ("Go To Next Page", "Ugrás a következő oldalra"), + ("Go To Page", "Ugrás oldalra"), + ("Go To Previous Page", "Ugrás az előző oldalra"), + ("Go To Source", "Ugrás a forráshoz"), + ("Go To URL", "Ugrás az URL-re"), + ("Go to Footnote Reference", "Ugrás a lábjegyzethivatkozáshoz"), + ("Go to Page", "Ugrás oldalra"), + ("Go to Page…", "Ugrás oldalra…"), + ("Gradient", "Színátmenet"), + ("Gradient Feather", "Színátmenetes lágyítás"), + ("Graphic", "Grafika"), + ("Graphic…", "Grafika…"), + ("Gray", "Szürke"), + ("Greek", "Görög"), + ("Gridify", "Rácsba rendezés"), + ("Grids", "Rácsok"), + ("Grids & Guides", "Rácsok és segédvonalak"), + ("Grids in Back", "Rácsok a háttérben"), + ("Group", "Csoportosítás"), + ("Group Transparency", "Csoport átlátszósága"), + ("Group with", "Csoportosítás ezzel"), + ("Group:", "Csoport:"), + ("Guide-Based", "Segédvonal-alapú"), + ("Guide-based", "Segédvonal-alapú"), + ("Guides", "Segédvonalak"), + ("Guides & Pasteboard", "Segédvonalak és munkaterület"), + ("Gutter", "Hasábköz"), + ("Gutter:", "Hasábköz:"), + ("H&J Violations", "Elválasztási és sorkizárási eltérések"), + ("H:", "M.:"), + ("Hair Space", "Hajszálköz"), + ("Header Rows", "Fejlécsorok"), + ("Hebrew", "Héber"), + ("Height", "Magasság"), + ("Height Only", "Csak magasság"), + ("Height and Width", "Magasság és szélesség"), + ("Height and width", "Magasság és szélesség"), + ("Height only", "Csak magasság"), + ("Height:", "Magasság:"), + ("Help", "Súgó"), + ("Hidden Characters", "Rejtett karakterek"), + ("Hide", "Elrejtés"), + ("Hide Bar", "Sáv elrejtése"), + ("Hide Guides", "Segédvonalak elrejtése"), + ("Hide Menu Item", "Menüpont elrejtése"), + ("Hide Others", "Többi elrejtése"), + ("Hide Rulers", "Vonalzók elrejtése"), + ("Hide/Lock Others", "Többi elrejtése/zárolása"), + ("High Contrast", "Erős kontraszt"), + ("High Quality", "Kiváló minőség"), + ("High Quality Display", "Kiváló minőségű megjelenítés"), + ("High Resolution", "Nagy felbontás"), + ("Highlight", "Kiemelés"), + ("Hindi", "Hindi"), + ("History", "Előzmények"), + ("Home", "Kezdőlap"), + ("Horizontal", "Vízszintes"), + ("Horizontal Gridline Every:", "Vízszintes rácsvonalak távolsága:"), + ("Horizontal Margins:", "Vízszintes margók:"), + ("Horizontal Offset", "Vízszintes eltolás"), + ("Horizontal Scale:", "Vízszintes méretezés:"), + ("Horizontal Spacing", "Vízszintes térköz"), + ("Horizontal:", "Vízszintes:"), + ("Hungarian", "Magyar"), + ("Hyperlink Options…", "Hiperhivatkozás beállításai…"), + ("Hyperlink from the selected text or frames", "Hiperhivatkozás a kijelölt szövegből vagy keretekből"), + ("Hyperlinks", "Hiperhivatkozások"), + ("Hyperlinks & Cross-References", "Hiperhivatkozások és kereszthivatkozások"), + ("Hyperlinks Cross-References", "Hiperhivatkozások és kereszthivatkozások"), + ("Hyphen Limit:", "Egymást követő elválasztások korlátja:"), + ("Hyphenate", "Elválasztás engedélyezése"), + ("Hyphenation", "Elválasztás"), + ("Hyphenation Exceptions", "Elválasztási kivételek"), + ("Hyphens and Dashes", "Kötőjelek és gondolatjelek"), + ("I, II, III, IV...", "I, II, III, IV..."), + ("IT", "IT"), + ("Image", "Kép"), + ("Import File", "Fájl importálása"), + ("Import Options", "Importálási beállítások"), + ("Import Options: Styles", "Importálási beállítások: stílusok"), + ("Import Warnings", "Importálási figyelmeztetések"), + ("Import XML", "XML importálása"), + ("Import XML…", "XML importálása…"), + ("In justified Arabic text", "Sorkizárt arab szövegben"), + ("Include Bleed", "Kifutóval együtt"), + ("Include Stroke Weight", "Körvonalvastagsággal együtt"), + ("Include document bleed", "Dokumentum kifutójának felvétele"), + ("Include when exporting", "Felvétel exportáláskor"), + ("Increase Point Size", "Betűméret növelése"), + ("Increment Every:", "Lépésköz:"), + ("Indent", "Behúzás"), + ("Indent to Here", "Behúzás eddig"), + ("Indents and Spacing", "Behúzások és térközök"), + ("Index", "Tárgymutató"), + ("Index Page References", "Tárgymutató-oldalhivatkozások"), + ("Info", "Információ"), + ("Ink Limit 300%", "300%-os festékterhelési korlát"), + ("Ink Manager", "Festékkezelő"), + ("Inner Glow", "Belső ragyogás"), + ("Inner Shadow", "Belső árnyék"), + ("Insert", "Beszúrás"), + ("Insert Anchored Object", "Rögzített objektum beszúrása"), + ("Insert Anchored Object…", "Rögzített objektum beszúrása…"), + ("Insert Break Character", "Töréskarakter beszúrása"), + ("Insert Column", "Oszlop beszúrása"), + ("Insert Column Left", "Oszlop beszúrása balra"), + ("Insert Column Right", "Oszlop beszúrása jobbra"), + ("Insert Column Rule", "Hasábelválasztó vonal beszúrása"), + ("Insert Cross-Reference", "Kereszthivatkozás beszúrása"), + ("Insert Cross-Reference…", "Kereszthivatkozás beszúrása…"), + ("Insert Endnote", "Végjegyzet beszúrása"), + ("Insert Field", "Mező beszúrása"), + ("Insert Footnote", "Lábjegyzet beszúrása"), + ("Insert Kashidas:", "Kasídák beszúrása:"), + ("Insert Math Expression", "Matematikai kifejezés beszúrása"), + ("Insert Math Expression…", "Matematikai kifejezés beszúrása…"), + ("Insert Page", "Oldal beszúrása"), + ("Insert Page After", "Oldal beszúrása utána"), + ("Insert Pages", "Oldalak beszúrása"), + ("Insert Pages…", "Oldalak beszúrása…"), + ("Insert Row", "Sor beszúrása"), + ("Insert Row Above", "Sor beszúrása fölé"), + ("Insert Row Below", "Sor beszúrása alá"), + ("Insert Special Character", "Speciális karakter beszúrása"), + ("Insert Table…", "Táblázat beszúrása…"), + ("Insert Variable", "Változó beszúrása"), + ("Insert White Space", "Szóközkarakter beszúrása"), + ("Insert field", "Mező beszúrása"), + ("Inset spacing", "Belső margók"), + ("Inside", "Belül"), + ("Inside:", "Belül:"), + ("Inspect Document", "Dokumentum vizsgálata"), + ("Intent:", "Leképezési mód:"), + ("Interactive", "Interaktív"), + ("Interactive for PDF", "Interaktív PDF"), + ("Interface", "Felület"), + ("Interface Color Theme", "Felület színtémája"), + ("Interface Language", "Felület nyelve"), + ("Internet Standard RGB (sRGB)", "Internetes szabványos RGB (sRGB)"), + ("Intersect", "Metszet"), + ("Invalid value", "Érvénytelen érték"), + ("Inverse Rounded Rectangle", "Befelé lekerekített téglalap"), + ("Invert", "Megfordítás"), + ("Inward", "Befelé"), + ("Isolate Blending", "Keverés elkülönítése"), + ("Italian", "Olasz"), + ("Italic", "Dőlt"), + ("Japanese", "Japán"), + ("Join", "Összekapcsolás"), + ("Join Path", "Görbék összekapcsolása"), + ("Join our Discord", "Csatlakozás a Discordhoz"), + ("Join the ArtCraft Discord", "Csatlakozás az ArtCraft Discordhoz"), + ("Join the ArtCraft Discord…", "Csatlakozás az ArtCraft Discordhoz…"), + ("Join the ArtCraft community", "Csatlakozás az ArtCraft közösségéhez"), + ("Join the community", "Csatlakozás a közösséghez"), + ("Join:", "Vonalcsatlakozás:"), + ("Jump Object", "Objektum átugrása"), + ("Jump to Next Column", "Ugrás a következő hasábba"), + ("Justification", "Sorkizárás"), + ("Justify", "Sorkizárt"), + ("Justify Left", "Sorkizárt, utolsó sor balra"), + ("Justify all lines", "Minden sor sorkizárt"), + ("Justify with last line aligned center", "Sorkizárt, utolsó sor középre"), + ("Justify with last line aligned left", "Sorkizárt, utolsó sor balra"), + ("Justify with last line aligned right", "Sorkizárt, utolsó sor jobbra"), + ("Keep Violations", "Együtt tartási eltérések"), + ("Kenten", "Kenten"), + ("Kerning", "Alávágás"), + ("Kerning:", "Alávágás:"), + ("Keyboard Increments", "Billentyűzeti lépésközök"), + ("Keyboard Shortcuts", "Billentyűparancsok"), + ("Keyboard Shortcuts…", "Billentyűparancsok…"), + ("Kind:", "Fajta:"), + ("Knockout Group", "Kiütési csoport"), + ("Korean", "Koreai"), + ("Korean Line Breaks:", "Koreai sortörések:"), + ("Lab", "Lab"), + ("Landscape", "Fekvő"), + ("Language", "Nyelv"), + ("Language:", "Nyelv:"), + ("Last", "Utolsó"), + ("Last Object Below", "Legalsó objektum"), + ("Last Page", "Utolsó oldal"), + ("Last Spread", "Utolsó oldalpár"), + ("Layer Options…", "Réteg beállításai…"), + ("Layers", "Rétegek"), + ("Layout", "Elrendezés"), + ("Layout/Index", "Elrendezés/Tárgymutató"), + ("Layout/Pages", "Elrendezés/Oldalak"), + ("Leading", "Sortávolság"), + ("Leading:", "Sortávolság:"), + ("Left", "Balra"), + ("Left Indent:", "Bal oldali behúzás:"), + ("Left to Right", "Balról jobbra"), + ("Left:", "Balra:"), + ("Legacy Macintosh RGB", "Régi Macintosh RGB"), + ("Letter Spacing:", "Betűköz:"), + ("Library", "Könyvtár"), + ("Library Contents", "Könyvtár tartalma"), + ("Library Items", "Könyvtári elemek"), + ("Ligatures", "Ligatúrák"), + ("Light", "Világos"), + ("Limit", "Korlát"), + ("Line", "Vonal"), + ("Linear", "Lineáris"), + ("Lines:", "Sorok:"), + ("Link To:", "Hivatkozás célja:"), + ("Link images", "Képek csatolása"), + ("Linked Stories", "Csatolt szövegfolyamok"), + ("Links", "Csatolások"), + ("Liquid Layout", "Alkalmazkodó elrendezés"), + ("Liquid Page Rule", "Alkalmazkodó oldalszabály"), + ("Liquid Page Rule:", "Alkalmazkodó oldalszabály:"), + ("Liquid guides", "Alkalmazkodó segédvonalak"), + ("List Box", "Listamező"), + ("List Composite Fonts", "Összetett betűtípusok listázása"), + ("List Documents", "Dokumentumok listázása"), + ("List Styles", "Stílusok listázása"), + ("List Tools", "Eszközök listázása"), + ("Load DTD", "DTD betöltése"), + ("Load DTD…", "DTD betöltése…"), + ("Load Place Cursor", "Elhelyezőkurzor feltöltése"), + ("Load Profile…", "Profil betöltése…"), + ("Load Swatches", "Színtár betöltése"), + ("Load Swatches…", "Színtár betöltése…"), + ("Load…", "Betöltés…"), + ("Location:", "Hely:"), + ("Lock", "Zárolás"), + ("Lock Guides", "Segédvonalak zárolása"), + ("Lock Others", "Többi zárolása"), + ("Loop", "Ismétlés"), + ("Low Resolution", "Kis felbontás"), + ("Magenta", "Bíbor"), + ("Make Compound", "Összetett alakzat készítése"), + ("Make Compound Path", "Összetett görbe készítése"), + ("Make all settings the same", "Összes beállítás azonossá tétele"), + ("Map Styles to Tags", "Stílusok hozzárendelése címkékhez"), + ("Margins", "Margók"), + ("Margins and Columns", "Margók és hasábok"), + ("Margins and Columns…", "Margók és hasábok…"), + ("Margins:", "Margók:"), + ("Markers", "Jelölők"), + ("Marks and Bleeds", "Nyomdai jelek és kifutó"), + ("Math Expression SVG", "Matematikai kifejezés SVG-je"), + ("Maximum", "Maximum"), + ("Media", "Média"), + ("Media Options", "Médiabeállítások"), + ("Medium Dark", "Középsötét"), + ("Medium Light", "Középvilágos"), + ("Medium Resolution", "Közepes felbontás"), + ("Menu Customization", "Menük testreszabása"), + ("Menus", "Menük"), + ("Menus…", "Menük…"), + ("Merge Cells", "Cellák egyesítése"), + ("Merge Layers", "Rétegek egyesítése"), + ("Merge into Active Layer", "Egyesítés az aktív réteggel"), + ("Merge options", "Egyesítési beállítások"), + ("Metrics", "Metrikus"), + ("Min:", "Min.:"), + ("Minimum", "Minimum"), + ("Minimum Space Before First Footnote:", "Legkisebb térköz az első lábjegyzet előtt:"), + ("Minus Back", "Hátsó alakzat kivonása"), + ("Missing Glyphs", "Hiányzó karakterjelek"), + ("Misspelled word → Correction (one per line):", "Hibás szó → Javítás (soronként egy):"), + ("Miter", "Hegyes vonalcsatlakozás"), + ("Miter Limit:", "Saroknyúlás korlátja:"), + ("Mobile", "Mobil"), + ("Monitor RGB", "Monitor RGB-színtere"), + ("More ArtCraft apps", "További ArtCraft-alkalmazások"), + ("More Options", "További beállítások"), + ("Move", "Áthelyezés"), + ("Move Anchors", "Csomópontok áthelyezése"), + ("Move Caret", "Szövegkurzor áthelyezése"), + ("Move Column", "Oszlop áthelyezése"), + ("Move Gap", "Hézag áthelyezése"), + ("Move Guide", "Segédvonal áthelyezése"), + ("Move Layer", "Réteg áthelyezése"), + ("Move Pages", "Oldalak áthelyezése"), + ("Move Pages…", "Oldalak áthelyezése…"), + ("Move Panel", "Panel áthelyezése"), + ("Move Row", "Sor áthelyezése"), + ("Move Selection Here", "Kijelölés áthelyezése ide"), + ("Move to Color Group", "Áthelyezés színcsoportba"), + ("Move to Group", "Áthelyezés csoportba"), + ("Move to Layer", "Áthelyezés rétegre"), + ("Multiline", "Többsoros"), + ("Multiple Objects", "Több objektum"), + ("Multiple records", "Több rekord"), + ("Name", "Név"), + ("Name:", "Név:"), + ("Native", "Natív"), + ("Nested Line Styles", "Beágyazott sorstílusok"), + ("Nested Styles", "Beágyazott stílusok"), + ("Never (continuous)", "Soha (folyamatos)"), + ("New", "Új"), + ("New Article", "Új cikk"), + ("New Article from Selection", "Új cikk a kijelölésből"), + ("New Book", "Új könyv"), + ("New Bookmark", "Új könyvjelző"), + ("New Bookmark for This Page", "Új könyvjelző ehhez az oldalhoz"), + ("New Book…", "Új könyv…"), + ("New Cell Style…", "Új cellastílus…"), + ("New Character Style…", "Új karakterstílus…"), + ("New Color Group", "Új színcsoport"), + ("New Color Group with Swatch", "Új színcsoport színmintával"), + ("New Color Swatch…", "Új színminta…"), + ("New Condition", "Új feltétel"), + ("New Condition…", "Új feltétel…"), + ("New Cross-Reference", "Új kereszthivatkozás"), + ("New Document", "Új dokumentum"), + ("New Document…", "Új dokumentum…"), + ("New GREP Style", "Új GREP-stílus"), + ("New Guide", "Új segédvonal"), + ("New Hyperlink", "Új hiperhivatkozás"), + ("New Hyperlink Destination", "Új hivatkozási cél"), + ("New Hyperlink Destination…", "Új hivatkozási cél…"), + ("New Hyperlink…", "Új hiperhivatkozás…"), + ("New Layer", "Új réteg"), + ("New Layer…", "Új réteg…"), + ("New Library", "Új könyvtár"), + ("New Library…", "Új könyvtár…"), + ("New Line Style", "Új sorstílus"), + ("New Nested Style", "Új beágyazott stílus"), + ("New Note", "Új jegyzet"), + ("New Note at Cursor", "Új jegyzet a kurzornál"), + ("New Object Style…", "Új objektumstílus…"), + ("New Page Reference", "Új oldalhivatkozás"), + ("New Page Reference…", "Új oldalhivatkozás…"), + ("New Paragraph Style…", "Új bekezdésstílus…"), + ("New Parent", "Új mesteroldal"), + ("New Parent…", "Új mesteroldal…"), + ("New Stroke Style", "Új körvonalstílus"), + ("New Stroke Style…", "Új körvonalstílus…"), + ("New Swatch", "Új színminta"), + ("New Table Style…", "Új táblázatstílus…"), + ("New Tag", "Új címke"), + ("New Window", "Új ablak"), + ("New Workspace", "Új munkaterület"), + ("New Workspace…", "Új munkaterület…"), + ("New condition name", "Új feltétel neve"), + ("New group…", "Új csoport…"), + ("New tag", "Új címke"), + ("Next", "Következő"), + ("Next Cell", "Következő cella"), + ("Next Document", "Következő dokumentum"), + ("Next Object Above", "Következő felső objektum"), + ("Next Object Below", "Következő alsó objektum"), + ("Next Object in Group", "Következő objektum a csoportban"), + ("Next Page", "Következő oldal"), + ("Next Page Number", "Következő oldalszám"), + ("Next Spread", "Következő oldalpár"), + ("No Break", "Nem törhető"), + ("No Selection", "Nincs kijelölés"), + ("No Text Wrap", "Nincs körbefuttatás"), + ("No articles: exports follow page order.", "Nincs cikk: az exportálás az oldalak sorrendjét követi."), + ("No book open.", "Nincs megnyitott könyv."), + ("No bookmarks. They become the PDF outline.", "Nincsenek könyvjelzők. Ezekből készül a PDF navigációs vázlata."), + ("No changes.", "Nincs módosítás."), + ( + "No conditions. Create one, then select text and click it to apply.", + "Nincs feltétel. Hozzon létre egyet, majd jelöljön ki szöveget, és kattintással alkalmazza rá.", + ), + ("No conflicts", "Nincs ütközés"), + ("No data source", "Nincs adatforrás"), + ("No document open", "Nincs megnyitott dokumentum"), + ("No document.", "Nincs dokumentum."), + ("No errors", "Nincs hiba"), + ( + "No hyperlinks. Select text or a frame, type a URL and click New.", + "Nincs hiperhivatkozás. Jelöljön ki szöveget vagy keretet, írjon be egy URL-t, és kattintson az Új gombra.", + ), + ("No library open.", "Nincs megnyitott könyvtár."), + ("No notes in this document.", "Nincs jegyzet ebben a dokumentumban."), + ("No placed graphics.", "Nincs elhelyezett grafika."), + ("No scripts. Add one below.", "Nincs parancsfájl. Alább hozzáadhat egyet."), + ("No spot inks", "Nincs direktszín"), + ("No text anchors in this document.", "Nincs szöveghorgony ebben a dokumentumban."), + ("No text selected", "Nincs kijelölt szöveg"), + ("Nonbreaking Hyphen", "Nem törhető kötőjel"), + ("Nonbreaking Space", "Nem törhető szóköz"), + ("None", "Nincs"), + ("None (keep transparency)", "Nincs (átlátszóság megőrzése)"), + ("Nonprinting", "Nem nyomtatandó"), + ("Normal", "Normál"), + ("Normal (W)", "Normál (W)"), + ("Norwegian: Bokmål", "Norvég: bokmål"), + ("Not a button", "Nem gomb"), + ("Not a form field", "Nem űrlapmező"), + ("Note text", "Jegyzet szövege"), + ("Notes", "Jegyzetek"), + ("Number of Pages", "Oldalak száma"), + ("Number of Pages:", "Oldalak száma:"), + ("Number of Sides:", "Sokszög oldalszáma:"), + ("Number of columns", "Oszlopok száma"), + ("Number:", "Szám:"), + ("Numbered List", "Számozott lista"), + ("Numbering", "Számozás"), + ("Numbering & Section Options", "Számozás és szakaszbeállítások"), + ("Numbering & Section Options…", "Számozás és szakaszbeállítások…"), + ("Numbering and Formatting", "Számozás és formázás"), + ("OK", "OK"), + ("OK changes all: text and paragraph/character styles.", "Az OK mindenhol cserél: a szövegben, valamint a bekezdés- és karakterstílusokban is."), + ("OVERSET", "TÚLCSORDULT SZÖVEG"), + ("Object", "Objektum"), + ("Object & Layout", "Objektum és elrendezés"), + ("Object Constraints:", "Objektum méret- és helyzetkötései:"), + ("Object Export Options", "Objektum exportálási beállításai"), + ("Object Export Options…", "Objektum exportálási beállításai…"), + ("Object Layer Options", "Objektum rétegbeállításai"), + ("Object Layer Options…", "Objektum rétegbeállításai…"), + ("Object Layers", "Objektumrétegek"), + ("Object Liquid Settings", "Objektum alkalmazkodási beállításai"), + ("Object States", "Objektumállapotok"), + ("Object Styles", "Objektumstílusok"), + ("Object is pinned relative to the page edge. Click to release.", "Az objektum az oldalszélhez van rögzítve. Kattintson a feloldáshoz."), + ("Object-Based", "Objektumalapú"), + ("Object-based", "Objektumalapú"), + ("Object/Anchored Object", "Objektum/Rögzített objektum"), + ("Object/Arrange", "Objektum/Sorrend"), + ("Object/Captions", "Objektum/Képaláírások"), + ("Object/Clipping Path", "Objektum/Vágógörbe"), + ("Object/Content", "Objektum/Tartalom"), + ("Object/Convert Shape", "Objektum/Alakzat átalakítása"), + ("Object/Effects", "Objektum/Hatások"), + ("Object/Fitting", "Objektum/Illesztés"), + ("Object/Pathfinder", "Objektum/Görbeműveletek"), + ("Object/Paths", "Objektum/Görbék"), + ("Object/Select", "Objektum/Kijelölés"), + ("Object/Transform", "Objektum/Átalakítás"), + ("Object/Transform Again", "Objektum/Átalakítás ismétlése"), + ("Object:", "Objektum:"), + ("Odd Page Break", "Páratlan oldaltörés"), + ("Off", "Ki"), + ("Offset", "Eltolás"), + ("Offset:", "Eltolás:"), + ("Offsets", "Eltolások"), + ("On", "Be"), + ("On Release", "Felengedéskor"), + ("On Screen:", "Képernyőn:"), + ("One record", "Egy rekord"), + ("Opacity", "Fedettség"), + ("Open", "Megnyitás"), + ("Open Book", "Könyv megnyitása"), + ("Open Bytes", "Megnyitás bájtokból"), + ("Open IDML", "IDML megnyitása"), + ("Open Library", "Könyvtár megnyitása"), + ("Open Path", "Görbe megnyitása"), + ("Open source. No telemetry.", "Nyílt forráskód. Nincs telemetria."), + ("OpenType", "OpenType"), + ("OpenType All Small Caps", "OpenType kiskapitális minden betűre"), + ("OpenType Denominator", "OpenType nevező"), + ("OpenType Features", "OpenType-funkciók"), + ("OpenType Numerator", "OpenType számláló"), + ("OpenType Subscript", "OpenType alsó index"), + ("OpenType Superscript", "OpenType felső index"), + ("Open…", "Megnyitás…"), + ("Optical", "Optikai"), + ("Optical Margin Alignment", "Optikai margóigazítás"), + ("Options", "Beállítások"), + ("Options for Black on RGB and Grayscale Devices", "Fekete beállításai RGB- és szürkeárnyalatos eszközökön"), + ("Ordinal", "Sorszámjel"), + ("Orientation", "Tájolás"), + ("Orientation:", "Tájolás:"), + ("Orthogonal Line", "Merőleges vonal"), + ("Other", "Egyéb"), + ("Outer Glow", "Külső ragyogás"), + ("Output", "Kimenet"), + ("Output All Blacks Accurately", "Minden fekete pontos kimenete"), + ("Output All Blacks as Rich Black", "Minden fekete kimenete dús feketeként"), + ("Outside", "Kívül"), + ("Outside:", "Kívül:"), + ("Overprint Fill", "Kitöltés felülnyomása"), + ("Overprint Gap", "Hézag felülnyomása"), + ("Overprint Preview", "Felülnyomási előnézet"), + ("Overprint Stroke", "Körvonal felülnyomása"), + ("Overprint [Black] Swatch at 100%", "A [Fekete] színminta felülnyomása 100%-nál"), + ("Override All Parent Page Items", "Mesteroldal összes elemének helyi felülírása"), + ("PDF/A-2b", "PDF/A-2b"), + ("PDF/X-4", "PDF/X-4"), + ("Package", "Csomagolás"), + ("Package…", "Csomagolás…"), + ("Page", "Oldal"), + ("Page (1–{count}):", "Oldal (1–{count}):"), + ("Page Break", "Oldaltörés"), + ("Page Information", "Oldalinformációk"), + ("Page Numbering", "Oldalszámozás"), + ("Page Options", "Oldalbeállítások"), + ("Page Range", "Oldaltartomány"), + ("Page Range:", "Oldaltartomány:"), + ("Page Size", "Oldalméret"), + ("Page Transition", "Oldaláttűnés"), + ("Page Transitions", "Oldaláttűnések"), + ( + "Page layout for print and screen — fast, open and scriptable.", + "Kiadványszerkesztés nyomtatáshoz és képernyőre – gyors, nyílt és parancsfájlokkal vezérelhető.", + ), + ("Page · PPI", "Oldal · PPI"), + ("Page:", "Oldal:"), + ("Pages", "Oldalak"), + ("Pages:", "Oldalak:"), + ("Panels", "Panelek"), + ("Paragraph", "Bekezdés"), + ("Paragraph Composer", "Bekezdéstördelő"), + ("Paragraph Formatting", "Bekezdésformázás"), + ("Paragraph Return", "Bekezdésjel"), + ("Paragraph Rules", "Bekezdésvonalak"), + ("Paragraph Rules…", "Bekezdésvonalak…"), + ("Paragraph Style Options", "Bekezdésstílus beállításai"), + ("Paragraph Style Options…", "Bekezdésstílus beállításai…"), + ("Paragraph Style:", "Bekezdésstílus:"), + ("Paragraph Styles", "Bekezdésstílusok"), + ("Paragraph Styles panel", "Bekezdésstílusok panel"), + ("Paragraph Symbol", "Bekezdés szimbóluma"), + ("Paragraph alignment", "Bekezdés igazítása"), + ("Parent Pages", "Mesteroldalak"), + ("Part of the ArtCraft suite of open creative tools.", "Az ArtCraft nyílt kreatív eszközcsalád része."), + ("Pass csv, rows, or bytes from the control channel.", "Adjon át csv, rows vagy bytes adatot a vezérlőcsatornán."), + ("Paste", "Beillesztés"), + ("Paste Into", "Beillesztés belülre"), + ("Paste in Place", "Beillesztés az eredeti helyre"), + ("Paste without Formatting", "Beillesztés formázás nélkül"), + ("Pasteboard Options", "Munkaterület beállításai"), + ("Path", "Görbe"), + ("Pathfinder", "Görbeműveletek"), + ("Pathfinder:", "Görbeműveletek:"), + ("Paths", "Görbék"), + ("Paths:", "Görbék:"), + ("Perceptual", "Érzékelési"), + ("Picas", "Pica"), + ("Pick a file in the folder holding the moved graphics", "Válasszon egy fájlt az áthelyezett grafikákat tartalmazó mappában"), + ("Pin Bar Position", "Sáv helyzetének rögzítése"), + ("Pin bottom", "Rögzítés alul"), + ("Pin left", "Rögzítés balra"), + ("Pin right", "Rögzítés jobbra"), + ("Pin top", "Rögzítés felül"), + ("Pin:", "Rögzítés:"), + ("Place", "Elhelyezés"), + ("Place Caret", "Szövegkurzor elhelyezése"), + ("Place Item", "Elem elhelyezése"), + ("Place Loaded Graphic", "Betöltött grafika elhelyezése"), + ("Place PDF", "PDF elhelyezése"), + ("Place Snippet", "Részlet elhelyezése"), + ("Place and Link", "Elhelyezés és csatolás"), + ("Place the insertion point in a table, or create one.", "Helyezze a szövegkurzort egy táblázatba, vagy hozzon létre táblázatot."), + ("Place with Import Options", "Elhelyezés importálási beállításokkal"), + ("Place with Import Options…", "Elhelyezés importálási beállításokkal…"), + ("Place…", "Elhelyezés…"), + ("Plain", "Egyszerű"), + ("Plain Text", "Egyszerű szöveg"), + ("Play on Page Load", "Lejátszás az oldal betöltésekor"), + ("Plays in EPUB export; print and PDF show the poster.", "EPUB-exportban lejátszható; nyomtatásban és PDF-ben a poszterkép látható."), + ("Polish", "Lengyel"), + ("Polygon", "Sokszög"), + ("Polygon Settings", "Sokszög beállításai"), + ("Polygon Settings…", "Sokszög beállításai…"), + ("Portrait", "Álló"), + ("Portuguese", "Portugál"), + ("Portuguese: Brazilian", "Portugál: brazíliai"), + ("Position", "Pozíció"), + ("Position:", "Pozíció:"), + ("Poster", "Poszter"), + ("Preferences", "Beállítások"), + ("Preferences…", "Beállítások…"), + ("Prefix:", "Előtag:"), + ("Preflight", "Nyomdai előellenőrzés"), + ("Preflight Document", "Dokumentum nyomdai előellenőrzése"), + ("Presentation", "Bemutató"), + ("Preset", "Készlet"), + ("Preset:", "Készlet:"), + ("Preview", "Előnézet"), + ("Preview (W)", "Előnézet (W)"), + ("Preview Record", "Rekord előnézete"), + ("Previous", "Előző"), + ("Previous Cell", "Előző cella"), + ("Previous Document", "Előző dokumentum"), + ("Previous Object in Group", "Előző objektum a csoportban"), + ("Previous Page", "Előző oldal"), + ("Previous Page Number", "Előző oldalszám"), + ("Previous Spread", "Előző oldalpár"), + ("Primary Text Frame", "Elsődleges szövegkeret"), + ("Print", "Nyomtatás"), + ("Print Booklet", "Füzet nyomtatása"), + ("Print Booklet…", "Füzet nyomtatása…"), + ("Printer's Marks", "Nyomdai jelek"), + ("Printer:", "Nyomtató:"), + ("Printers", "Nyomtatók"), + ("Printing / Exporting:", "Nyomtatás / exportálás:"), + ("Printing and Proofing", "Nyomtatás és próbanyomat"), + ("Print…", "Nyomtatás…"), + ("Projecting", "Túlnyúló"), + ("Proof Colors", "Próbaszínek"), + ("Proof Setup", "Próbanyomat beállításai"), + ("Properties", "Tulajdonságok"), + ("Properties Panel", "Tulajdonságok panel"), + ("Proportional Lining", "Arányos verzálszámok"), + ("Proportional Oldstyle", "Arányos ugráló számok"), + ("Punctuation Space", "Írásjelköz"), + ("Push", "Eltolás"), + ("Quarter Space", "Negyedkvirt szóköz"), + ("Quick Actions", "Gyorsműveletek"), + ("Quick Apply", "Gyors alkalmazás"), + ("Quick Apply…", "Gyors alkalmazás…"), + ("Quit DesignCraft", "Kilépés a DesignCraftból"), + ("Quotation Marks", "Idézőjelek"), + ("RGB", "RGB"), + ("RGB:", "RGB:"), + ("Radial", "Sugárirányú"), + ("Radio Button", "Választógomb"), + ("Range", "Tartomány"), + ("Re-center", "Újra középre"), + ("Recently Used", "Legutóbb használt"), + ("Record", "Rekord"), + ("Records per page", "Rekordok oldalanként"), + ("Recover Documents", "Dokumentumok helyreállítása"), + ("Recovery Data", "Helyreállítási adatok"), + ("Rectangle", "Téglalap"), + ("Redo", "Újra"), + ("Registered Trademark Symbol", "Bejegyzett védjegy jele"), + ("Reject", "Elutasítás"), + ("Reject All", "Összes elutasítása"), + ("Reject All Changes", "Összes módosítás elutasítása"), + ("Reject Change", "Módosítás elutasítása"), + ("Relative Colorimetric", "Relatív kolorimetrikus"), + ("Relative To:", "Viszonyítási alap:"), + ("Release", "Feloldás"), + ("Release Compound Path", "Összetett görbe feloldása"), + ("Release State to Objects", "Állapot feloldása objektumokra"), + ("Release to Objects", "Feloldás objektumokra"), + ("Relink", "Újracsatolás"), + ("Relink to Folder", "Újracsatolás mappához"), + ("Relink to Folder…", "Újracsatolás mappához…"), + ("Relink…", "Újracsatolás…"), + ("Remove", "Eltávolítás"), + ("Remove All Local Overrides", "Összes helyi felülírás törlése"), + ("Remove Conditions from Selection", "Feltételek eltávolítása a kijelölésből"), + ("Remove Data Source", "Adatforrás eltávolítása"), + ("Remove Document", "Dokumentum eltávolítása"), + ("Remove Field", "Mező eltávolítása"), + ("Remove Flex Layout", "Rugalmas elrendezés eltávolítása"), + ("Remove Frame from Thread", "Keret kivétele a láncból"), + ("Remove Hyphenation Exception", "Elválasztási kivétel eltávolítása"), + ("Remove Styles and Formatting from Text and Tables", "Stílusok és formázás eltávolítása a szövegből és a táblázatokból"), + ("Remove from Article", "Eltávolítás a cikkből"), + ("Rename", "Átnevezés"), + ("Rename Bookmark", "Könyvjelző átnevezése"), + ("Render", "Renderelés"), + ("Reorder in Flex Layout", "Átrendezés a rugalmas elrendezésben"), + ("Repeat", "Ismétlés"), + ("Repeat Header Rows", "Fejlécsorok ismétlése"), + ("Replace With", "Csere erre"), + ("Replace with:", "Csere erre:"), + ("Report an Issue", "Hiba bejelentése"), + ("Report an Issue…", "Hiba bejelentése…"), + ("Required", "Kötelező"), + ("Reset", "Visszaállítás"), + ("Reset All to Defaults", "Összes alapérték visszaállítása"), + ("Reset Bar Position", "Sáv pozíciójának visszaállítása"), + ("Reset Shortcuts", "Gyorsbillentyűk visszaállítása"), + ("Reset Workspace", "Munkaterület visszaállítása"), + ("Resize", "Átméretezés"), + ("Resize Page", "Oldal átméretezése"), + ("Resize height", "Magasság módosítása"), + ("Resize panel window", "Panelablak átméretezése"), + ("Resize panels", "Panelek átméretezése"), + ("Resize width", "Szélesség módosítása"), + ("Resize with Page:", "Átméretezés az oldallal:"), + ("Restart Numbering Every:", "Számozás újrakezdése:"), + ("Reverse", "Megfordítás"), + ("Reverse Column", "Fordított oszlopsorrend"), + ("Reverse Path", "Görbeirány megfordítása"), + ("Reverse Row", "Fordított sorsorrend"), + ("Reverse the gradient", "Színátmenet megfordítása"), + ("Revert", "Visszaállítás a mentett változatra"), + ("Right", "Jobbra"), + ("Right Indent Tab", "Jobbra behúzó tabulátor"), + ("Right Indent:", "Jobb behúzás:"), + ("Right to Left", "Jobbról balra"), + ("Right-click: stroke, groups", "Jobb kattintás: körvonal, csoportok"), + ("Right:", "Jobbra:"), + ("Rotate", "Forgatás"), + ("Rotate 90° Clockwise", "Forgatás 90°-kal jobbra"), + ("Rotate 90° Counterclockwise", "Forgatás 90°-kal balra"), + ("Rotate Spread", "Oldalpár elforgatása"), + ("Rotation", "Elforgatás"), + ("Rotation Angle", "Elforgatás szöge"), + ("Round", "Kerek"), + ("Rounded Rectangle", "Lekerekített téglalap"), + ("Row", "Sor"), + ("Row Height", "Sormagasság"), + ("Row spacing", "Sorköz"), + ("Row ↑", "Sor ↑"), + ("Row ↓", "Sor ↓"), + ("Rows", "Sorok"), + ("Rows first", "Először a sorok"), + ("Rows:", "Sorok:"), + ("Ruby", "Ruby"), + ("Ruby:", "Ruby:"), + ("Ruby…", "Ruby…"), + ("Rule Above", "Bekezdés feletti vonal"), + ("Rule Below", "Vonal alatta"), + ("Rule On", "Vonal bekapcsolása"), + ("Ruler Units", "Vonalzó mértékegységei"), + ("Rulers", "Vonalzók"), + ("Rulers & Grids", "Vonalzók és rácsok"), + ("Run", "Futtatás"), + ("Run Script", "Szkript futtatása"), + ("Russian", "Orosz"), + ("Sample Color (Eyedropper)", "Színmintavétel (pipetta)"), + ("Sample Document", "Mintadokumentum"), + ("Satin", "Szatén"), + ("Saturation", "Telítettség"), + ("Save", "Mentés"), + ("Save As", "Mentés másként"), + ("Save As…", "Mentés másként…"), + ("Save Recovery Data", "Helyreállítási adatok mentése"), + ("Save Swatches for Exchange", "Színminták mentése cseréhez"), + ("Save Swatches for Exchange…", "Színtár mentése cseréhez…"), + ("Save a Copy", "Másolat mentése"), + ("Save a Copy…", "Másolat mentése…"), + ("Save recovery data every:", "Helyreállítási adatok mentési időköze:"), + ("Saves which bars show and where the panels are.", "Menti a látható sávokat és a panelek helyét."), + ("Scale", "Méretezés"), + ("Scale X Percentage", "Vízszintes méretezés százalékban"), + ("Scale Y Percentage", "Függőleges méretezés százalékban"), + ("Scale for Descenders", "Méretezés a lenyúló szárakhoz"), + ("Screen Mode", "Képernyőmód"), + ("Screen and Email", "Képernyő és e-mail"), + ("Script Label", "Szkriptcímke"), + ("Scripts", "Szkriptek"), + ("Search", "Keresés"), + ("Search commands", "Parancsok keresése"), + ("Search fonts", "Betűtípusok keresése"), + ("Search styles and commands…", "Stílusok és parancsok keresése…"), + ("Search:", "Keresés:"), + ("Search: character or U+code", "Keresés: karakter vagy U+kód"), + ("Section", "Szakasz"), + ("Section Marker", "Szakaszjelölő"), + ("Section Symbol", "Paragrafusjel"), + ("Select", "Kijelölés"), + ("Select All", "Az összes kijelölése"), + ("Select All on Layer", "Összes kijelölése a rétegen"), + ("Select Cells", "Cellák kijelölése"), + ("Select Column", "Oszlop kijelölése"), + ("Select Data Source…", "Adatforrás kiválasztása…"), + ("Select Frame", "Keret kijelölése"), + ("Select Page", "Oldal kijelölése"), + ("Select Paragraph", "Bekezdés kijelölése"), + ("Select Row", "Sor kijelölése"), + ("Select Sentence", "Mondat kijelölése"), + ("Select Story", "Szövegfolyam kijelölése"), + ("Select Table", "Táblázat kijelölése"), + ("Select Text", "Szöveg kijelölése"), + ("Select Text Unit", "Szövegegység kijelölése"), + ("Select Tool", "Eszköz kiválasztása"), + ("Select Word", "Szó kijelölése"), + ( + "Select a placed video or sound (File › Place a .mp4, .mov, .mp3, .wav …).", + "Jelöljön ki egy elhelyezett videót vagy hangot (Fájl › Elhelyezés: .mp4, .mov, .mp3, .wav …).", + ), + ("Select an object or text to color its fill or stroke.", "Jelöljön ki egy objektumot vagy szöveget a kitöltés vagy a körvonal színezéséhez."), + ("Select an object to color its fill or stroke.", "Jelöljön ki egy objektumot a kitöltés vagy a körvonal színezéséhez."), + ("Select an object to give its fill a gradient.", "Jelöljön ki egy objektumot a színátmenetes kitöltéshez."), + ("Select an object to make it a button.", "Jelöljön ki egy objektumot a gombbá alakításhoz."), + ("Select an object.", "Jelöljön ki egy objektumot."), + ("Select text or a text frame.", "Jelöljön ki szöveget vagy szövegkeretet."), + ("Select text to apply a condition", "Jelöljön ki szöveget a feltétel alkalmazásához"), + ( + "Select two or more objects (or a group) to make a multi-state object.", + "Jelöljön ki legalább két objektumot (vagy egy csoportot) a többállapotú objektum létrehozásához.", + ), + ("Selection", "Kijelölés"), + ("Selection Attributes", "Kijelölés tulajdonságai"), + ("Send Backward", "Eggyel hátrébb"), + ("Send to Back", "Leghátra"), + ("Sentence case", "Mondatkezdő nagybetű"), + ("Separated by commas", "Vesszővel elválasztva"), + ("Separations Preview", "Színkivonatok előnézete"), + ("Separator:", "Elválasztó:"), + ("Serialize", "Szerializálás"), + ("Set", "Beállítás"), + ("Set Active Layer", "Aktív réteg beállítása"), + ("Set Anchor", "Csomópont beállítása"), + ("Set Composite Font", "Összetett betűtípus beállítása"), + ("Set Cross-Reference Format", "Kereszthivatkozás formátumának beállítása"), + ("Set Footnote Text", "Lábjegyzetszöveg beállítása"), + ("Set OpenType Features", "OpenType-funkciók beállítása"), + ("Set Shortcut", "Gyorsbillentyű beállítása"), + ("Set Story Text", "Szövegfolyam szövegének beállítása"), + ("Set Visibility / Lock", "Láthatóság / zárolás beállítása"), + ("Set over the selected text; empty removes it.", "A kijelölt szöveg fölé kerül; üresen hagyva eltávolítható."), + ("Shading", "Háttérszínezés"), + ("Share", "Megosztás"), + ("Shear", "Döntés"), + ("Shear X Angle", "Vízszintes döntés szöge"), + ("Show", "Megjelenítés"), + ("Show / hide text with this condition", "Az ezzel a feltétellel jelölt szöveg megjelenítése / elrejtése"), + ("Show All Layers", "Összes réteg megjelenítése"), + ("Show All Menu Items", "Összes menüpont megjelenítése"), + ("Show All on Spread", "Összes megjelenítése az oldalpáron"), + ("Show Baseline Grid", "Alapvonalrács megjelenítése"), + ("Show Controls", "Vezérlők megjelenítése"), + ("Show Document Grid", "Dokumentumrács megjelenítése"), + ("Show Favorites Only", "Csak a kedvencek megjelenítése"), + ("Show Flex Controls", "Rugalmas elrendezés vezérlőinek megjelenítése"), + ("Show Font Names in English", "Betűtípusnevek megjelenítése angolul"), + ("Show Guides", "Segédvonalak megjelenítése"), + ("Show Hidden Characters", "Rejtett karakterek megjelenítése"), + ("Show Note Anchors in Layout View", "Jegyzethorgonyok megjelenítése elrendezési nézetben"), + ("Show Panel", "Panel megjelenítése"), + ("Show Parent Page Overlay", "Mesteroldal fedvényének megjelenítése"), + ("Show Prefix/Suffix in:", "Előtag/utótag megjelenítése itt:"), + ("Show Rulers", "Vonalzók megjelenítése"), + ("Show State", "Állapot megjelenítése"), + ("Show Tag Markers", "Címkejelölők megjelenítése"), + ("Show in the text", "Megjelenítés a szövegben"), + ("Show the Typography panel", "Tipográfia panel megjelenítése"), + ("Show/Hide Baseline Grid", "Alapvonalrács megjelenítése/elrejtése"), + ("Show/Hide Depth Ruler", "Mélységmérő megjelenítése/elrejtése"), + ("Show/Hide Frame Edges", "Keretélek megjelenítése/elrejtése"), + ("Show/Hide Guides", "Segédvonalak megjelenítése/elrejtése"), + ("Show/Hide Hidden Characters", "Rejtett karakterek megjelenítése/elrejtése"), + ("Show/Hide Panels", "Panelek megjelenítése/elrejtése"), + ("Show/Hide Panels Except Tools", "Panelek megjelenítése/elrejtése az eszközök kivételével"), + ("Show/Hide Rulers", "Vonalzók megjelenítése/elrejtése"), + ("Show/Hide Tagged Frames", "Címkézett keretek megjelenítése/elrejtése"), + ("Show/Hide Text Threads", "Szövegláncok megjelenítése/elrejtése"), + ("Signature", "Aláírás"), + ("Signature Field", "Aláírásmező"), + ("Simple", "Egyszerű"), + ("Simple - Wide", "Egyszerű – széles"), + ("Simulate Paper Color", "Papírszín szimulálása"), + ("Single Left Quotation Mark", "Bal oldali szimpla idézőjel"), + ("Single Right Quotation Mark", "Jobb oldali szimpla idézőjel"), + ("Single record", "Egy rekord"), + ("Single-line", "Egysoros"), + ("Single-line Composer", "Egysoros tördelő"), + ("Sixth Space", "Hatodkvirt szóköz"), + ("Size", "Méret"), + ("Size:", "Méret:"), + ("Skew:", "Dőlés:"), + ("Slashed Zero", "Áthúzott nulla"), + ("Slug", "Infóterület"), + ("Slug:", "Infóterület:"), + ("Small Caps", "Kiskapitális"), + ("Smart Dimensions", "Intelligens méretek"), + ("Smart Guide Options", "Intelligens segédvonalak beállításai"), + ("Smart Guides", "Intelligens segédvonalak"), + ("Smart Spacing", "Intelligens térközök"), + ("Smart Text Reflow", "Intelligens szövegáttördelés"), + ("Smooth", "Simítás"), + ("Snap to Document Grid", "Igazítás a dokumentumrácshoz"), + ("Snap to Guides", "Igazítás a segédvonalakhoz"), + ("Snap to Zone", "Zónához igazítás"), + ("Solid", "Folytonos"), + ("Sort", "Rendezés"), + ("Space After", "Térköz utána"), + ("Space After:", "Térköz utána:"), + ("Space Around", "Térköz az elemek körül"), + ("Space Before", "Térköz előtte"), + ("Space Before:", "Térköz előtte:"), + ("Space Between", "Térköz az elemek között"), + ("Space Between Footnotes:", "Lábjegyzetek közötti térköz:"), + ("Space Evenly", "Egyenletes térköz"), + ("Spacing", "Térköz"), + ("Spacing Options", "Térköz beállításai"), + ("Span Footnotes Across Columns", "Lábjegyzetek több hasábon át"), + ("Spanish", "Spanyol"), + ("Speed", "Sebesség"), + ("Spelling", "Helyesírás"), + ("Split", "Felosztás"), + ("Split Cell Horizontally", "Cella vízszintes felosztása"), + ("Split Cell Vertically", "Cella függőleges felosztása"), + ("Split Path", "Görbe felosztása"), + ("Split Window", "Ablak felosztása"), + ("Spread", "Oldalpár"), + ("Spreads", "Oldalpárok"), + ("Spreads of up to 10 pages", "Legfeljebb 10 oldalas oldalcsoportok"), + ("Square", "Négyzet"), + ("Square - Solid", "Négyzet – tömör"), + ("Standard", "Szabványos"), + ("Standard:", "Szabvány:"), + ("Star Inset:", "Csillag behúzása:"), + ("Start Page #", "Kezdőoldalszám"), + ("Start Page #:", "Kezdő oldalszám:"), + ("Start a new document", "Új dokumentum létrehozása"), + ("Start at:", "Kezdőérték:"), + ("Start/End:", "Kezdet/vég:"), + ("Start:", "Kezdet:"), + ("State Options", "Állapot beállításai"), + ("Status", "Állapot"), + ("Step and Repeat", "Ismételt másolás"), + ("Step and Repeat…", "Ismételt másolás…"), + ("Stop Color:", "Színpont színe:"), + ("Stop Preview", "Előnézet leállítása"), + ("Story", "Szövegfolyam"), + ("Story Column Direction", "Szövegfolyam hasábiránya"), + ("Story Direction", "Szövegfolyam iránya"), + ("Story Editor", "Szövegfolyam-szerkesztő"), + ("Story Editor Display", "Szövegfolyam-szerkesztő megjelenítése"), + ("Straight Double Quotation Marks", "Egyenes dupla idézőjel"), + ("Straight Hash", "Egyenes rovátkázás"), + ("Straight Single Quotation Mark (Apostrophe)", "Egyenes szimpla idézőjel (aposztróf)"), + ("Strikethrough", "Áthúzás"), + ("Strikethrough On", "Áthúzás bekapcsolása"), + ("Strikethrough Options", "Áthúzás beállításai"), + ("Stripes", "Csíkok"), + ("Stroke", "Körvonal"), + ("Stroke (X)", "Körvonal (X)"), + ("Stroke Behind Fill", "Körvonal a kitöltés mögött"), + ("Stroke Styles", "Körvonalstílusok"), + ("Structure", "Struktúra"), + ("Style", "Stílus"), + ("Style Mapping", "Stílusok megfeleltetése"), + ("Style Name Conflicts", "Stílusnevek ütközései"), + ("Style Name:", "Stílus neve:"), + ("Style Settings:", "Stílus beállításai:"), + ("Style Source", "Stílusforrás"), + ("Style source", "Stílusforrás"), + ("Style:", "Stílus:"), + ("Styles", "Stílusok"), + ("Styles panel", "Stílusok panel"), + ("Stylistic Set", "Stílusváltozat-készlet"), + ("Stylistic Sets", "Stílusváltozat-készletek"), + ("Subdivisions:", "Felosztások:"), + ("Subscript", "Alsó index"), + ("Subscript:", "Alsó index:"), + ("Substituted Fonts", "Helyettesített betűtípusok"), + ("Subtract", "Kivonás"), + ("Suffix:", "Utótag:"), + ("Superscript", "Felső index"), + ("Superscript:", "Felső index:"), + ("Swap Fill and Stroke", "Kitöltés és körvonal felcserélése"), + ("Swap Fill and Stroke (Shift+X)", "Kitöltés és körvonal felcserélése (Shift+X)"), + ("Swap Text Fill and Stroke", "Szöveg kitöltésének és körvonalának felcserélése"), + ("Swash", "Díszes betűváltozat"), + ("Swatches", "Színtár"), + ("Swedish", "Svéd"), + ("Symbols", "Szimbólumok"), + ("Symmetrical", "Szimmetrikus"), + ("Synchronize", "Szinkronizálás"), + ("Synchronize Book", "Könyv szinkronizálása"), + ("System default", "Rendszer alapértelmezése"), + ("Tab", "Tabulátor"), + ("Table", "Táblázat"), + ("Table Dimensions", "Táblázat méretei"), + ("Table Options", "Táblázat beállításai"), + ("Table Panel", "Táblázat panel"), + ("Table Style", "Táblázatstílus"), + ("Table Style Options…", "Táblázatstílus beállításai…"), + ("Table of Contents", "Tartalomjegyzék"), + ("Table of Contents Entries", "Tartalomjegyzék bejegyzései"), + ("Table of Contents…", "Tartalomjegyzék…"), + ("Table/Convert Cell Type", "Táblázat/Cellatípus átalakítása"), + ("Table/Delete", "Táblázat/Törlés"), + ("Table/Insert", "Táblázat/Beszúrás"), + ("Table/Select", "Táblázat/Kijelölés"), + ("Tabs", "Tabulátorok"), + ("Tabular Lining", "Táblázatos verzálszámok"), + ("Tabular Oldstyle", "Táblázatos ugráló számok"), + ("Tag Frame", "Keret címkézése"), + ("Tag Text", "Szöveg címkézése"), + ("Tag the selection", "Kijelölés címkézése"), + ("Tag:", "Címke:"), + ("Tagged PDF", "Címkézett PDF"), + ("Tags", "Címkék"), + ("Tate-Chu-Yoko", "Tate-Chu-Yoko"), + ("Text", "Szöveg"), + ("Text Anchors", "Szöveghorgonyok"), + ("Text Display Options", "Szöveg megjelenítési beállításai"), + ("Text Field", "Szövegmező"), + ("Text Frame", "Szövegkeret"), + ("Text Frame Options", "Szövegkeret beállításai"), + ("Text Frame Options…", "Szövegkeret beállításai…"), + ("Text Message", "Szöveges üzenet"), + ("Text Style", "Szövegstílus"), + ("Text Variables", "Szövegváltozók"), + ("Text Wrap", "Szöveg körbefuttatása"), + ("The fill isn't a gradient.", "A kitöltés nem színátmenetes."), + ( + "The library is empty. Select objects and Add Selection.", + "A könyvtár üres. Jelöljön ki objektumokat, majd válassza a Kijelölt elemek hozzáadása parancsot.", + ), + ( + "The object changes height as the page changes height. Click to lock the object height.", + "Az objektum magassága az oldal magasságával együtt változik. Kattintson az objektum magasságának rögzítéséhez.", + ), + ( + "The object changes width as the page changes width. Click to lock the object width.", + "Az objektum szélessége az oldal szélességével együtt változik. Kattintson az objektum szélességének rögzítéséhez.", + ), + ( + "The object's height is locked. Click to let the object change height as the page changes height.", + "Az objektum magassága rögzített. Kattintson, hogy a magassága az oldal magasságával együtt változhasson.", + ), + ( + "The object's width is locked. Click to let the object change width as the page changes width.", + "Az objektum szélessége rögzített. Kattintson, hogy a szélessége az oldal szélességével együtt változhasson.", + ), + ("The selected fonts have no OpenType features.", "A kijelölt betűtípusoknak nincsenek OpenType-funkcióik."), + ("The stroke isn't a gradient.", "A körvonal nem színátmenetes."), + ("The structure is valid.", "A struktúra érvényes."), + ("Thick - Thick", "Vastag – vastag"), + ("Thick - Thin", "Vastag – vékony"), + ("Thick - Thin - Thick", "Vastag – vékony – vastag"), + ("Thin - Thick", "Vékony – vastag"), + ("Thin - Thick - Thin", "Vékony – vastag – vékony"), + ("Thin - Thin", "Vékony – vékony"), + ("Thin Space", "Keskeny szóköz"), + ("Third Space", "Harmadkvirt szóköz"), + ("This PDF has no layers.", "Ez a PDF nem tartalmaz rétegeket."), + ( + "This story was edited in the layout: you'll be asked before those edits are replaced", + "Ezt a szövegfolyamot az elrendezésben módosította: a módosítások felülírása előtt megerősítést kérünk", + ), + ("This style is in use. Text using it will be reassigned to:", "Ez a stílus használatban van. Az ezt használó szöveg új stílusa:"), + ("Thread Text Frames", "Szövegkeretek összeláncolása"), + ("Tint %", "Árnyalat %"), + ("Tint:", "Százalékos árnyalat:"), + ("Title Case", "Szavak kezdőbetűje nagy"), + ("Titling Alternates", "Címbetűváltozatok"), + ("To Text:", "Erre a szövegre:"), + ("Toggle Fill and Stroke", "Váltás a kitöltés és a körvonal között"), + ("Toggle Normal/Preview", "Váltás normál nézet és előnézet között"), + ("Toggle Selection", "Kijelölés átváltása"), + ("Toggle double column", "Váltás két oszlopra"), + ("Tools: Double Column", "Eszközök: két oszlop"), + ("Top", "Fent"), + ("Top Inset", "Felső belső margó"), + ("Top Margin", "Felső margó"), + ("Top of Page", "Oldal teteje"), + ("Top:", "Fent:"), + ("Track Changes", "Változások követése"), + ("Track Changes in All Stories", "Változások követése minden szövegfolyamban"), + ("Tracking", "Betűköz"), + ("Tracking:", "Betűköz:"), + ("Trademark Symbol", "Védjegy jele"), + ("Transform", "Átalakítás"), + ("Transform Again", "Átalakítás ismétlése"), + ("Transform Again Individually", "Átalakítás ismétlése egyenként"), + ("Transform Panel", "Átalakítás panel"), + ("Transform Sequence Again", "Átalakítássorozat ismétlése"), + ("Transform Sequence Again Individually", "Átalakítássorozat ismétlése egyenként"), + ("Transform Values", "Átalakítási értékek"), + ("Transformations are Totals", "Összesített átalakítások"), + ("Transitions play in interactive PDF (full-screen mode).", "Az áttűnések interaktív PDF-ben, teljes képernyős módban játszhatók le."), + ("Transparency", "Átlátszóság"), + ("Transparency Blend Space", "Átlátszóság keverési színtere"), + ("Transparency Flattener Presets", "Átlátszóság-összeolvasztási készletek"), + ("Triangle", "Háromszög"), + ("Triangle - Wide", "Háromszög – széles"), + ("Trim", "Körülvágás"), + ("Turkish", "Török"), + ("Type", "Szöveg"), + ("Type & Tables", "Szöveg és táblázatok"), + ("Type Options", "Szövegbeállítások"), + ( + "Type a word with ~ at each allowed break (ex~am~ple); without ~ the word is never hyphenated.", + "Írjon be egy szót, és jelölje ~ karakterrel az engedélyezett elválasztásokat (el~vá~lasz~tás); ~ nélkül a szó nem választható el.", + ), + ("Type on a Path", "Szöveg görbén"), + ("Type on a Path Options", "Görbére írt szöveg beállításai"), + ("Type on a Path Options…", "Görbére írt szöveg beállításai…"), + ("Type/Bulleted and Numbered Lists", "Szöveg/Felsorolások és számozott listák"), + ("Type/Change Case", "Szöveg/Kis- és nagybetűk váltása"), + ("Type/Hyperlinks & Cross-References", "Szöveg/Hiperhivatkozások és kereszthivatkozások"), + ("Type/Insert Break Character", "Szöveg/Töréskarakter beszúrása"), + ("Type/Insert Special Character/Hyphens and Dashes", "Szöveg/Speciális karakter beszúrása/Kötőjelek és gondolatjelek"), + ("Type/Insert Special Character/Markers", "Szöveg/Speciális karakter beszúrása/Jelölők"), + ("Type/Insert Special Character/Other", "Szöveg/Speciális karakter beszúrása/Egyéb"), + ("Type/Insert Special Character/Quotation Marks", "Szöveg/Speciális karakter beszúrása/Idézőjelek"), + ("Type/Insert Special Character/Symbols", "Szöveg/Speciális karakter beszúrása/Szimbólumok"), + ("Type/Insert White Space", "Szöveg/Szóközkarakter beszúrása"), + ("Type/Proof Setup", "Szöveg/Próbanyomat beállításai"), + ("Type/Rotate Spread", "Szöveg/Oldalpár elforgatása"), + ("Type/Separations Preview", "Szöveg/Színkivonatok előnézete"), + ("Type/Story Direction", "Szöveg/Szövegfolyam iránya"), + ("Type/Text Variables", "Szöveg/Szövegváltozók"), + ("Type/Track Changes", "Szöveg/Változások követése"), + ("Type/Type on a Path", "Szöveg/Szöveg görbén"), + ("Type:", "Típus:"), + ("Typical", "Szokásos"), + ("Typical Display", "Szokásos megjelenítés"), + ("Typography", "Tipográfia"), + ("UI Scaling", "Felület méretezése"), + ("UI Size:", "Felület mérete:"), + ("UPPERCASE", "NAGYBETŰK"), + ("URL:", "URL:"), + ("US Business Card", "Amerikai névjegykártya"), + ("Ukrainian", "Ukrán"), + ("Unassigned", "Nincs hozzárendelve"), + ("Uncover", "Felfedés"), + ("Underline", "Aláhúzás"), + ("Underline On", "Aláhúzás bekapcsolása"), + ("Underline Options", "Aláhúzás beállításai"), + ("Undo", "Visszavonás"), + ("Ungroup", "Csoportbontás"), + ("Ungroup Color Group", "Színcsoport felbontása"), + ("Units", "Mértékegységek"), + ("Units & Increments", "Mértékegységek és lépésközök"), + ("Unlink", "Csatolás megszüntetése"), + ("Unlock", "Zárolás feloldása"), + ("Unlock All Layers", "Összes réteg zárolásának feloldása"), + ("Unlock All on Spread", "Összes zárolás feloldása az oldalpáron"), + ("Unmerge", "Egyesítés felbontása"), + ("Unmerge Cells", "Cellák egyesítésének megszüntetése"), + ("Unsaved Changes", "Nem mentett módosítások"), + ("Untag Selection", "Címke eltávolítása a kijelölésről"), + ("Update", "Frissítés"), + ("Update Data Source", "Adatforrás frissítése"), + ("Update Index", "Tárgymutató frissítése"), + ("Update Link", "Csatolás frissítése"), + ("Update Numbering", "Számozás frissítése"), + ("Update Table of Contents", "Tartalomjegyzék frissítése"), + ("Use Black Point Compensation", "Feketepont-kompenzáció használata"), + ("Use Global Light", "Globális fény használata"), + ("Use Typographer's Quotes", "Tipográfiai idézőjelek használata"), + ("User Dictionary", "Felhasználói szótár"), + ("User Dictionary (this document)", "Felhasználói szótár (ez a dokumentum)"), + ("User Dictionary Words", "Felhasználói szótár szavai"), + ("User Dictionary…", "Felhasználói szótár…"), + ("Utilities", "Segédeszközök"), + ("VA", "VA"), + ("Validate", "Érvényesítés"), + ("Validate from Root Element", "Érvényesítés a gyökérelemtől"), + ("Variable Font", "Változtatható betűtípus"), + ("Version", "Verzió"), + ("Vertical", "Függőleges"), + ("Vertical Gridline Every:", "Függőleges rácsvonalak távolsága:"), + ("Vertical Margins:", "Függőleges margók:"), + ("Vertical Scale:", "Függőleges méretezés:"), + ("Vertical Spacing", "Függőleges térköz"), + ("Vertical justification", "Függőleges igazítás"), + ("Vertical:", "Függőleges:"), + ("View", "Nézet"), + ("View Options", "Nézetbeállítások"), + ("View Threshold:", "Megjelenítési küszöb:"), + ("View/Display Performance", "Nézet/Megjelenítési teljesítmény"), + ("View/Extras", "Nézet/Kiegészítők"), + ("View/Grids & Guides", "Nézet/Rácsok és segédvonalak"), + ("View/Proof Setup", "Nézet/Próbanyomat beállításai"), + ("View/Rotate Spread", "Nézet/Oldalpár elforgatása"), + ("View/Screen Mode", "Nézet/Képernyőmód"), + ("View/Separations Preview", "Nézet/Színkivonatok előnézete"), + ("View/Structure", "Nézet/Struktúra"), + ("W:", "Sz.:"), + ("Warichu", "Warichu"), + ("Wavy", "Hullámos"), + ("Web", "Web"), + ("Web Hyperlink", "Webes hiperhivatkozás"), + ("Weight", "Vonalvastagság"), + ("Weight:", "Vonalvastagság:"), + ("Welcome to DesignCraft", "Üdvözöl a DesignCraft"), + ("When Scaling", "Méretezéskor"), + ("Whole word", "Teljes szó"), + ("Width", "Szélesség"), + ("Width Only", "Csak szélesség"), + ("Width only", "Csak szélesség"), + ("Width:", "Szélesség:"), + ("Window", "Ablak"), + ("Window/Arrange", "Ablak/Elrendezés"), + ("Window/Interactive", "Ablak/Interaktív"), + ("Window/Interface Color Theme", "Ablak/Felület színtémája"), + ("Window/Output", "Ablak/Kimenet"), + ("Window/Panels", "Ablak/Panelek"), + ("Window/Type & Tables", "Ablak/Szöveg és táblázatok"), + ("Window/Utilities", "Ablak/Segédeszközök"), + ("Wipe", "Törléses áttűnés"), + ("Word Spacing:", "Szóköz:"), + ("Words with at Least:", "Szavak legalább ennyi betűvel:"), + ("Words, one per line:", "Szavak, soronként egy:"), + ("Working CMYK", "Munka CMYK"), + ("Workspace", "Munkaterület"), + ("Wrap Around Bounding Box", "Körbefuttatás a határolókeret körül"), + ("Wrap Around Object Shape", "Körbefuttatás az objektum alakja körül"), + ("Wrap Content", "Tartalom tördelése"), + ("X:", "X:"), + ("Y:", "Y:"), + ("Yellow", "Sárga"), + ("Zoom In", "Nagyítás"), + ("Zoom Out", "Kicsinyítés"), + ("Zoom To", "Nagyítás erre"), + ("[Automatic]", "[Automatikus]"), + ("[Basic Paragraph]", "[Alapbekezdés]"), + ("[Basic] (working) ▾", "[Alap] (munka) ▾"), + ("[Black] Overprint", "[Fekete] felülnyomás"), + ("[No Group]", "[Nincs csoport]"), + ("[No Paragraph Style]", "[Nincs bekezdésstílus]"), + ("[None]", "[Nincs]"), + ("[None] — choose a colour on the ramp.", "[Nincs] — válasszon színt a színátmeneten."), + ("a, b, c, d...", "a, b, c, d..."), + ("bottom", "lent"), + ("center", "középen"), + ("characters", "karakter"), + ("chars", "karakter"), + ("digits", "számjegy"), + ("discord.gg/artcraft — help, feedback and show-and-tell", "discord.gg/artcraft — segítség, visszajelzés és bemutatók"), + ("document", "dokumentum"), + ("dropcap", "iniciálé"), + ("emSpace", "Kvirt szóköz"), + ("enSpace", "Félkvirt szóköz"), + ("error", "hiba"), + ("errors", "hiba"), + ("for", "ehhez"), + ("forcedLineBreak", "Kényszerített sortörés"), + ("graphic", "grafika"), + ("i, ii, iii, iv...", "i, ii, iii, iv..."), + ("items", "elem"), + ("justify", "sorkizárt"), + ("letters", "betű"), + ("line", "sor"), + ("lines", "sor"), + ("lowercase", "kisbetűk"), + ("objects", "objektum"), + ("pages", "oldal"), + ("selection", "kijelölés"), + ("sentences", "mondat"), + ("stories", "szövegfolyam"), + ("story", "szövegfolyam"), + ("tab", "tabulátor"), + ("text", "szöveg"), + ("through", "beleértve"), + ("top", "fent"), + ("unassigned", "nincs hozzárendelve"), + ("unused", "nem használt"), + ("up to", "kizárva"), + ("warnings", "figyelmeztetés"), + ("words", "szó"), + ("x Height", "x-magasság"), + ("{count} characters don't fit", "{count} karakter nem fér el"), + ("{count} glyphs — click to insert at the text cursor", "{count} karakterjel — kattintással beszúrható a szövegkurzornál"), + ("{pages} Pages in {spreads} Spreads", "{pages} oldal, {spreads} oldalpáron"), + ( + "“{}” has been edited in this layout. Updating replaces those edits with the text from the file.", + "A(z) „{}” szövegét módosította ebben az elrendezésben. A frissítés a fájl szövegével felülírja ezeket a módosításokat.", + ), + ("“{}” has changes that are not saved. Save them before closing?", "A(z) „{}” nem mentett módosításokat tartalmaz. Menti őket bezárás előtt?"), + ("⇧", "⇧"), + ("⌃", "⌃"), + ("⌘", "⌘"), + ("⌥", "⌥"), + ("⌥-click clears overrides", "⌥-kattintás törli a felülírásokat"), + ("▲ Modified", "▲ Módosítva"), + ("⚠ Missing", "⚠ Hiányzik"), + ("⚠ out of date", "⚠ elavult"), + ("Selection Tool", "Kijelölő eszköz"), + ("Direct Selection Tool", "Közvetlen kijelölő eszköz"), + ("Page Tool", "Oldaleszköz"), + ("Gap Tool", "Térközeszköz"), + ("Content Collector Tool", "Tartalomgyűjtő eszköz"), + ("Content Placer Tool", "Tartalomelhelyező eszköz"), + ("Type Tool", "Szövegeszköz"), + ("Type on a Path Tool", "Görbére író szövegeszköz"), + ("Vertical Type Tool", "Függőleges szövegeszköz"), + ("Vertical Type on a Path Tool", "Görbére író függőleges szövegeszköz"), + ("Line Tool", "Vonaleszköz"), + ("Pen Tool", "Toll eszköz"), + ("Add Anchor Point Tool", "Csomópont-hozzáadó eszköz"), + ("Delete Anchor Point Tool", "Csomóponttörlő eszköz"), + ("Convert Direction Point Tool", "Csomópont-átalakító eszköz"), + ("Pencil Tool", "Ceruza eszköz"), + ("Smooth Tool", "Simító eszköz"), + ("Erase Tool", "Radír eszköz"), + ("Rectangle Frame Tool", "Téglalapkeret eszköz"), + ("Ellipse Frame Tool", "Ellipsziskeret eszköz"), + ("Polygon Frame Tool", "Sokszögkeret eszköz"), + ("Rectangle Tool", "Téglalap eszköz"), + ("Ellipse Tool", "Ellipszis eszköz"), + ("Polygon Tool", "Sokszög eszköz"), + ("Scissors Tool", "Olló eszköz"), + ("Free Transform Tool", "Szabad átalakítás eszköz"), + ("Rotate Tool", "Forgató eszköz"), + ("Scale Tool", "Méretező eszköz"), + ("Shear Tool", "Döntő eszköz"), + ("Gradient Swatch Tool", "Színátmenet eszköz"), + ("Gradient Feather Tool", "Színátmenetes lágyítás eszköz"), + ("Note Tool", "Jegyzeteszköz"), + ("Color Theme Tool", "Színtéma eszköz"), + ("Eyedropper Tool", "Pipetta eszköz"), + ("Measure Tool", "Mérőeszköz"), + ("Hand Tool", "Kéz eszköz"), + ("Zoom Tool", "Nagyító eszköz"), +]; + +pub(super) const CONTEXT: &[(&str, &str, &str)] = + &[("Columns", "table", "Oszlopok"), ("Columns:", "grid", "Oszlopok:"), ("Group", "selection", "Csoport"), ("Number:", "count", "Darabszám:")]; diff --git a/crates/ui-egui/src/i18n/sv.rs b/crates/ui-egui/src/i18n/sv.rs new file mode 100644 index 000000000..1a7550a35 --- /dev/null +++ b/crates/ui-egui/src/i18n/sv.rs @@ -0,0 +1,2957 @@ +//! Swedish (sv) interface translations for DesignCraft, written from the English source with ordinary +//! Swedish software vocabulary; no other catalog and no proprietary localisation was used. +//! AI-drafted with Claude Code; spot-checked by a native Swedish speaker, not every string reviewed. +pub(super) const TABLE: &[(&str, &str)] = &[ + ("File", "Arkiv"), + ("Edit", "Redigera"), + ("Layout", "Layout"), + ("Type", "Text"), + ("Object", "Objekt"), + ("Table", "Tabell"), + ("View", "Visa"), + ("Window", "Fönster"), + ("Help", "Hjälp"), + ("New", "Nytt"), + ("New Document…", "Nytt dokument…"), + ("New Document", "Nytt dokument"), + ("Open…", "Öppna…"), + ("Close", "Stäng"), + ("Save", "Spara"), + ("Save As…", "Spara som…"), + ("Save a Copy…", "Spara en kopia…"), + ("Revert", "Återgå"), + ("Place…", "Placera…"), + ("Export PDF…", "Exportera PDF…"), + ("Print…", "Skriv ut…"), + ("Print", "Skriv ut"), + ("Document Setup…", "Dokumentinställningar…"), + ("Document Setup", "Dokumentinställningar"), + ("Package…", "Paketera…"), + ("Undo", "Ångra"), + ("Redo", "Gör om"), + ("Cut", "Klipp ut"), + ("Copy", "Kopiera"), + ("Paste", "Klistra in"), + ("Bulleted & Numbered Lists", "Punktlistor och numrerade listor"), + ("Current Page Number", "Aktuellt sidnummer"), + ("Apply Color (,)", "Använd färg (,)"), + ("Apply Gradient (.)", "Använd gradient (.)"), + ("View Options", "Visningsalternativ"), + ("Frame Edges", "Ramkanter"), + ("Hidden Characters", "Dolda tecken"), + ("Create Flex Layout", "Skapa flexlayout"), + ("Add to Flex Layout", "Lägg till i flexlayout"), + ("Convert to Flex Layout", "Konvertera till flexlayout"), + ("Remove Flex Layout", "Ta bort flexlayout"), + ("Show Flex Controls", "Visa flexkontroller"), + ("Flex Layout Options", "Alternativ för flex-layout"), + ("Reorder in Flex Layout", "Ändra ordning i flexlayout"), + ("Flex Start", "Flex-start"), + ("Flex End", "Flex-slut"), + ("Space Between", "Avstånd mellan"), + ("Space Around", "Avstånd runt"), + ("Space Evenly", "Jämnt avstånd"), + ("Reverse Row", "Omvänd rad"), + ("Reverse Column", "Omvänd kolumn"), + ("Wrap Content", "Ombryt innehåll"), + ("Spacing", "Avstånd"), + ("Horizontal Spacing", "Horisontellt avstånd"), + ("Vertical Spacing", "Vertikalt avstånd"), + ("Constrain proportions", "Behåll proportioner"), + ("Auto", "Auto"), + ("W:", "B:"), + ("H:", "H:"), + ("Number:", "Antal:"), + ("Gutter:", "Spaltmellanrum:"), + ("Fit Guides to:", "Anpassa stödlinjer till:"), + ("Top:", "Överkant:"), + ("Bottom:", "Nederkant:"), + ("Inside:", "Inre:"), + ("Outside:", "Yttre:"), + ("Left:", "Vänster:"), + ("Right:", "Höger:"), + ("Paths:", "Banor:"), + ("Pathfinder:", "Banfinnare:"), + ("Convert Shape:", "Konvertera form:"), + ("Convert Point:", "Konvertera punkt:"), + ("Join Path", "Foga samman bana"), + ("Open Path", "Öppen bana"), + ("Plain", "Normal"), + ("Symmetrical", "Symmetrisk"), + ("The stroke isn't a gradient.", "Konturen är inte en gradient."), + ("Reverse Path", "Vänd banans riktning"), + ("Set Anchor", "Ange ankare"), + ("Clear", "Rensa"), + ("Delete", "Radera"), + ("Duplicate", "Duplicera"), + ("Select All", "Markera allt"), + ("Deselect All", "Avmarkera alla"), + ("Find/Change…", "Sök/ändra…"), + ("Find/Change", "Sök/ändra"), + ("Check Spelling…", "Kontrollera stavning…"), + ("Preferences…", "Inställningar…"), + ("Preferences", "Inställningar"), + ("Keyboard Shortcuts…", "Kortkommandon…"), + ("Keyboard Shortcuts", "Kortkommandon"), + ("Interface Language", "Gränssnittsspråk"), + ("Pages", "Sidor"), + ("Panels", "Paneler"), + ("Page", "Sida"), + ("Margins and Columns…", "Marginaler och spalter…"), + ("Create Guides…", "Skapa stödlinjer…"), + ("Numbering & Section Options…", "Numrerings- och avsnittsalternativ…"), + ("Go to Page…", "Gå till sida…"), + ("Go to Page", "Gå till sida"), + ("Next Page", "Nästa sida"), + ("Previous Page", "Föregående sida"), + ("First Page", "Första sidan"), + ("Last Page", "Sista sidan"), + ("Font", "Typsnitt"), + ("Size", "Storlek"), + ("Character", "Tecken"), + ("Paragraph", "Stycke"), + ("Paragraph Styles", "Styckestilar"), + ("Character Styles", "Teckenstilar"), + ("Paragraph Style Options", "Alternativ för styckestil"), + ("Object Styles", "Objektstilar"), + ("Glyphs", "Glyfer"), + ("Find/Replace Font…", "Sök/ersätt typsnitt…"), + ("Find/Replace Font", "Sök/ersätt typsnitt"), + ("Story Editor", "Artikelredigerare"), + ("Edit in Story Editor", "Redigera i textredigeraren"), + ("Insert Special Character", "Infoga specialtecken"), + ("Insert White Space", "Infoga blanktecken"), + ("Insert Break Character", "Infoga brytningstecken"), + ("Change Case", "Ändra skiftläge"), + ("Text Frame Options…", "Alternativ för textram…"), + ("Text Frame Options", "Alternativ för textram"), + ("Footnote Options", "Fotnotsalternativ"), + ("New Cross-Reference", "Ny korsreferens"), + ("Arrange", "Ordna"), + ("Transform", "Transformera"), + ("Group", "Gruppera"), + ("Ungroup", "Dela upp grupp"), + ("Lock", "Lås"), + ("Unlock All on Spread", "Lås upp alla på uppslaget"), + ("Bring to Front", "Flytta längst fram"), + ("Send to Back", "Flytta längst bak"), + ("Bring Forward", "Flytta framåt"), + ("Send Backward", "Flytta bakåt"), + ("Fitting", "Anpassning"), + ("Fit Frame to Content", "Anpassa ram till innehåll"), + ("Fit Content to Frame", "Anpassa innehåll till ram"), + ("Fill Frame Proportionally", "Fyll ram proportionerligt"), + ("Fit Content Proportionally", "Anpassa innehåll proportionerligt"), + ("Center Content", "Centrera innehåll"), + ("Frame Fitting Options", "Alternativ för ramanpassning"), + ("Generate QR Code", "Generera QR-kod"), + ("Create Table", "Skapa tabell"), + ("Insert Table…", "Infoga tabell…"), + ("Insert", "Infoga"), + ("Rows", "Rader"), + ("Columns", "Kolumner"), + ("Row", "Rad"), + ("Column", "Kolumn"), + ("Merge Cells", "Sammanfoga celler"), + ("Split Cell Horizontally", "Dela cell horisontellt"), + ("Split Cell Vertically", "Dela cell vertikalt"), + ("Table Options", "Tabellalternativ"), + ("Cell Options", "Cellalternativ"), + ("Header Rows", "Rubrikrader"), + ("Footer Rows", "Fotrader"), + ("Zoom In", "Zooma in"), + ("Zoom Out", "Zooma ut"), + ("Fit Page in Window", "Anpassa sidan till fönstret"), + ("Fit Spread in Window", "Anpassa uppslaget till fönstret"), + ("Actual Size", "Verklig storlek"), + ("Screen Mode", "Skärmläge"), + ("Normal", "Normal"), + ("Preview", "Förhandsgranskning"), + ("Rulers", "Linjaler"), + ("Grids & Guides", "Rutnät och stödlinjer"), + ("Show Guides", "Visa stödlinjer"), + ("Hide Guides", "Dölj stödlinjer"), + ("Show Rulers", "Visa linjaler"), + ("Hide Rulers", "Dölj linjaler"), + ("Extras", "Extrafunktioner"), + ("Workspace", "Arbetslayout"), + ("Editorial", "Redaktionell"), + ("Object & Layout", "Objekt och layout"), + ("Styles", "Stilar"), + ("Essentials Classic", "Grundläggande klassisk"), + ("New Workspace", "Ny arbetslayout"), + ("Properties", "Egenskaper"), + ("Layers", "Lager"), + ("Swatches", "Färgrutor"), + ("Colour", "Färg"), + ("Color", "Färg"), + ("Stroke", "Kontur"), + ("Fill", "Fyllning"), + ("Gradient", "Gradient"), + ("Transparency", "Transparens"), + ("Effects", "Effekter"), + ("Links", "Länkar"), + ("Notes", "Anteckningar"), + ("Conditions", "Villkor"), + ("Library", "Bibliotek"), + ("Text Wrap", "Textombrytning"), + ("Align", "Justera"), + ("Pathfinder", "Banfinnare"), + ("Transform Again", "Transformera igen"), + ("Interactive", "Interaktiv"), + ("Buttons and Forms", "Knappar och formulär"), + ("Hyperlinks", "Hyperlänkar"), + ("Bookmarks", "Bokmärken"), + ("Show All Menu Items", "Visa alla menyalternativ"), + ("About DesignCraft", "Om DesignCraft"), + ("Quit DesignCraft", "Avsluta DesignCraft"), + ("Welcome to DesignCraft", "Välkommen till DesignCraft"), + ("Page layout for print and screen — fast, open and scriptable.", "Sidlayout för tryck och skärm – snabb, öppen och skriptbar."), + (" New file ", " Ny fil "), + (" Open ", " Öppna "), + (" Open sample magazine ", " Öppna exempeltidning "), + ("Start a new document", "Skapa ett nytt dokument"), + ("No document open", "Inget dokument är öppet"), + ("Join the ArtCraft community", "Gå med i ArtCraft-gemenskapen"), + ("Get help, share your layouts and shape what we build next.", "Få hjälp, dela dina layouter och påverka vad vi bygger härnäst."), + ("Join our Discord", "Gå med i vår Discord"), + ("Community", "Gemenskap"), + ("Join the community", "Gå med i gemenskapen"), + ("discord.gg/artcraft — help, feedback and show-and-tell", "discord.gg/artcraft – hjälp, återkoppling och visa upp vad du gjort"), + (" OK ", " OK "), + ("Float panel", "Gör panelen flytande"), + ("Dock panel", "Docka panel"), + ("OK", "OK"), + ("Cancel", "Avbryt"), + ("Can't Open the File", "Det går inte att öppna filen"), + ("Can't Place the File", "Det går inte att placera filen"), + ("Apply", "Använd"), + ("Done", "Klart"), + ("Reset", "Återställ"), + ("Add", "Lägg till"), + ("Remove", "Ta bort"), + ("Name", "Namn"), + ("Width", "Bredd"), + ("Height", "Höjd"), + ("Portrait", "Stående"), + ("Landscape", "Liggande"), + ("Orientation", "Orientering"), + ("Units", "Enheter"), + ("Preset", "Förinställning"), + ("Facing Pages", "Motstående sidor"), + ("Primary Text Frame", "Primär textram"), + ("Number of Pages", "Antal sidor"), + ("Start Page #", "Startsida nr"), + ("Page Size", "Sidstorlek"), + ("Margins", "Marginaler"), + ("Bleed", "Utfall"), + ("Slug", "Informationsområde"), + ("Top", "Överkant"), + ("Bottom", "Nederkant"), + ("Left", "Vänster"), + ("Right", "Höger"), + ("Inside", "Inuti"), + ("Outside", "Utanför"), + ("Gutter", "Spaltmellanrum"), + ("Binding", "Bindning"), + ("Left to Right", "Vänster till höger"), + ("Right to Left", "Höger till vänster"), + ("No Selection", "Ingen markering"), + ("Rectangle", "Rektangel"), + ("Ellipse", "Ellips"), + ("Polygon", "Polygon"), + ("Polygon Settings", "Polygoninställningar"), + ("Text", "Text"), + ("Image", "Bild"), + ("Line", "Linje"), + ("Position", "Position"), + ("Appearance", "Utseende"), + ("Opacity", "Opacitet"), + ("Corner", "Hörn"), + ("Rotation", "Rotation"), + ("Rulers & Grids", "Linjaler och rutnät"), + ("Guides", "Stödlinjer"), + ("Flex Layout", "Flex-layout"), + ("Auto Size", "Automatisk storlek"), + ("Tracking", "Spärrning"), + ("Leading", "Radavstånd"), + ("Kerning", "Kerning"), + ("Language", "Språk"), + ("Hyphenation", "Avstavning"), + ("Alignment", "Justering"), + ("Indent", "Indrag"), + ("Space Before", "Avstånd före"), + ("Space After", "Avstånd efter"), + ("New Layer", "Nytt lager"), + ("New Swatch", "Ny färgruta"), + ("Object Layer Options", "Lageralternativ för objekt"), + ("Colour Picker", "Färgväljare"), + ("Color Picker", "Färgväljare"), + ("Color Settings", "Färginställningar"), + ("User Dictionary", "Användarordlista"), + ("Menu Customization", "Anpassning av menyer"), + ("Import Options", "Importalternativ"), + ("Place PDF", "Placera PDF"), + ("Find", "Sök"), + ("Change", "Ändra"), + ("Find What", "Sök efter"), + ("Change To", "Ändra till"), + ("Find Next", "Sök nästa"), + ("Change All", "Ändra alla"), + ("Search", "Sök"), + ("Document", "Dokument"), + ("Selection", "Markering"), + ("All Documents", "Alla dokument"), + ("Direction", "Riktning"), + ("Horizontal", "Horisontell"), + ("Vertical", "Vertikal"), + ("On", "På"), + ("Off", "Av"), + ("None", "Ingen"), + ("[None]", "[Ingen]"), + ("Place with Import Options…", "Placera med importalternativ…"), + ("Print Booklet…", "Skriv ut häfte…"), + ("Export", "Exportera"), + ("Export Page as PNG…", "Exportera sidan som PNG…"), + ("Export IDML…", "Exportera IDML…"), + ("Export EPUB…", "Exportera EPUB…"), + ("Export EPUB (Fixed Layout)…", "Exportera EPUB (fast layout)…"), + ("Export PDF (Interactive)…", "Exportera PDF (interaktiv)…"), + ("Export HTML…", "Exportera HTML…"), + ("Export XML…", "Exportera XML…"), + ("Export Text…", "Exportera text…"), + ("Quick Actions", "Snabbåtgärder"), + ("Import File", "Importera fil"), + ("Insert Page", "Infoga sida"), + ("Delete selected pages", "Radera markerade sidor"), + ("Create new page", "Skapa ny sida"), + ("Edit page size", "Redigera sidstorlek"), + ("Custom Page Size…", "Anpassad sidstorlek…"), + ("Edit Page", "Redigera sida"), + ("Adjust Layout", "Anpassa layout"), + ("Smart Guides", "Smarta stödlinjer"), + ("Lock Guides", "Lås stödlinjer"), + ("Show Document Grid", "Visa dokumentrutnät"), + ("Show Baseline Grid", "Visa baslinjerutnät"), + ("Options", "Alternativ"), + ("More Options", "Fler alternativ"), + ("Dialog", "Dialogruta"), + ("General", "Allmänt"), + ("Basic Character Formats", "Grundläggande teckenformat"), + ("Indents and Spacing", "Indrag och avstånd"), + ("Justification", "Justering"), + ("Drop Caps and Nested Styles", "Anfanger och kapslade stilar"), + ("GREP Style", "GREP-format"), + ("Character Color", "Teckenfärg"), + ("Export Tagging", "Exporttaggning"), + ("Numbering and Formatting", "Numrering och formatering"), + ("Spacing Options", "Avståndsalternativ"), + ("First Baseline", "Första baslinje"), + ("Rule Above", "Linje ovanför"), + ("Numbering", "Numrering"), + ("Footnote Reference Number in Text", "Fotnotsreferensnummer i texten"), + ("Footnote Formatting", "Fotnotsformatering"), + ("Span Footnotes Across Columns", "Låt fotnoter sträcka sig över spalter"), + ("Rule On", "Linje på"), + ("Ascent", "Uppstapelhöjd"), + ("Cap Height", "Versalhöjd"), + ("x Height", "x-höjd"), + ("Em Box Height", "Fyrkantshöjd"), + ("Fixed", "Fast"), + ("Never (continuous)", "Aldrig (kontinuerlig)"), + ("Spread", "Uppslag"), + ("Section", "Avsnitt"), + ("Footnote Reference", "Fotnotsreferens"), + ("Footnote Text", "Fotnotstext"), + ("Both", "Båda"), + ("Apply Superscript", "Använd upphöjd"), + ("Apply Subscript", "Använd nedsänkt"), + ("Apply Normal", "Använd normal"), + ("OpenType Superscript", "OpenType upphöjd"), + ("through", "till"), + ("up to", "upp till"), + ("line", "rad"), + ("lines", "rader"), + ("sentences", "meningar"), + ("words", "ord"), + ("characters", "tecken"), + ("letters", "bokstäver"), + ("digits", "siffror"), + ("tab", "tabb"), + ("forcedLineBreak", "forcedLineBreak"), + ("emSpace", "helfyrkant"), + ("enSpace", "halvfyrkant"), + ("dropcap", "anfang"), + ("Drop Caps", "Anfanger"), + ("Lines:", "Rader:"), + ("Characters:", "Tecken:"), + ("Drop Lines", "Anfangsrader"), + ("Drop Chars", "Anfangtecken"), + ("Align Left Edge", "Justera vänsterkant"), + ("Scale for Descenders", "Skala för nedstaplar"), + ("chars", "tkn"), + ("[Automatic]", "[Automatisk]"), + ("Size:", "Storlek:"), + ("Tracking:", "Spärrning:"), + ("Left Indent:", "Vänsterindrag:"), + ("Right Indent:", "Högerindrag:"), + ("First Line Indent:", "Indrag första raden:"), + ("Space Before:", "Avstånd före:"), + ("Space After:", "Avstånd efter:"), + ("Words with at Least:", "Ord med minst:"), + ("After First:", "Efter första:"), + ("Before Last:", "Före sista:"), + ("Hyphen Limit:", "Gräns för avstavningar:"), + ("Word Spacing:", "Ordavstånd:"), + ("Letter Spacing:", "Teckenavstånd:"), + ("Glyph Scaling:", "Glyfskalning:"), + ("Insert Kashidas:", "Infoga kashidor:"), + ("In justified Arabic text", "I marginaljusterad arabisk text"), + ("Korean Line Breaks:", "Koreanska radbrytningar:"), + ("Between syllables (not only at spaces)", "Mellan stavelser (inte bara vid blanksteg)"), + ("Minimum Space Before First Footnote:", "Minsta avstånd före första fotnoten:"), + ("Space Between Footnotes:", "Avstånd mellan fotnoter:"), + ("Offset:", "Förskjutning:"), + ("Min:", "Min:"), + ("Weight:", "Tjocklek:"), + ("Color:", "Färg:"), + ("Width:", "Bredd:"), + ("Style:", "Stil:"), + ("Start at:", "Börja på:"), + ("Restart Numbering Every:", "Börja om numreringen varje:"), + ("Show Prefix/Suffix in:", "Visa prefix/suffix i:"), + ("Prefix:", "Prefix:"), + ("Suffix:", "Suffix:"), + ("Position:", "Position:"), + ("Character Style:", "Teckenstil:"), + ("Paragraph Style:", "Styckestil:"), + ("Separator:", "Avgränsare:"), + ("EPUB and HTML", "EPUB och HTML"), + ("Tag:", "Tagg:"), + ("Class:", "Klass:"), + ("Nested Styles", "Kapslade stilar"), + ("Nested Line Styles", "Kapslade radstilar"), + ("New Nested Style", "Ny kapslad stil"), + ("New Line Style", "Ny radstil"), + ("GREP Styles", "GREP-format"), + ("Apply Style:", "Använd stil:"), + ("To Text:", "Till text:"), + ("New GREP Style", "Ny GREP-stil"), + ("Font Family:", "Typsnittsfamilj:"), + ("Font Style:", "Teckenstil:"), + ("Leading:", "Radavstånd:"), + ("Alignment:", "Justering:"), + ("Hyphenate", "Avstava"), + ("Minimum", "Minimum"), + ("Desired", "Önskad"), + ("Maximum", "Maximum"), + ("Composer:", "Sättningsmotor:"), + ("Paragraph Composer", "Styckesättare"), + ("Single-line Composer", "Enradssättare"), + ("Style Name:", "Stilnamn:"), + ("Based On:", "Baserat på:"), + ("for", "för"), + ("Hyphenation Exceptions", "Avstavningsundantag"), + ("Binding:", "Bindning:"), + ("Dynamic Spelling", "Dynamisk stavning"), + ("UI Scaling", "Gränssnittsskalning"), + ("Ruby:", "Ruby:"), + ("Set over the selected text; empty removes it.", "Sätts över den markerade texten; tomt tar bort den."), + ("Document Footnote Options…", "Alternativ för dokumentets fotnoter…"), + ("Insert Footnote", "Infoga fotnot"), + ("Go to Footnote Reference", "Gå till fotnotsreferens"), + ("Footnotes", "Fotnoter"), + ("Paragraph Style Options…", "Alternativ för styckestil…"), + ("New Paragraph Style…", "Ny styckestil…"), + ("New Character Style…", "Ny teckenstil…"), + ("[Basic Paragraph]", "[Grundläggande stycke]"), + ("[No Paragraph Style]", "[Ingen styckestil]"), + ("Align left", "Justera vänster"), + ("Align center", "Centrera"), + ("Align right", "Justera höger"), + ("Justify with last line aligned left", "Marginaljustera med sista raden vänsterjusterad"), + ("Justify with last line aligned center", "Marginaljustera med sista raden centrerad"), + ("Justify with last line aligned right", "Marginaljustera med sista raden högerjusterad"), + ("Justify all lines", "Marginaljustera alla rader"), + ("Align towards spine", "Justera mot bokryggen"), + ("Align away from spine", "Justera bort från bokryggen"), + ("Create New Style from Selection", "Skapa ny stil från markering"), + ("No text selected", "Ingen text är markerad"), + ("Essentials", "Grundläggande"), + ("Advanced", "Avancerat"), + ("Book", "Bok"), + ("Digital Publishing", "Digital publicering"), + ("Interactive for PDF", "Interaktiv för PDF"), + ("Printing and Proofing", "Utskrift och korrektur"), + ("Typography", "Typografi"), + ("No errors", "Inga fel"), + ("error", "fel"), + ("errors", "fel"), + ("Display All Blacks as Rich Black", "Visa alla svarta som djupsvart"), + ("Display All Blacks Accurately", "Visa alla svarta korrekt"), + ("Output All Blacks as Rich Black", "Återge all svart som djupsvart"), + ("Output All Blacks Accurately", "Återge all svart korrekt"), + ("Top Margin", "Övre marginal"), + ("Top of Page", "Överst på sidan"), + ("Paragraph Styles panel", "Panelen Styckestilar"), + ("Character Styles panel", "Panel för teckenstilar"), + ("Create new style", "Skapa ny stil"), + ("Clear overrides", "Rensa lokala ändringar"), + ("Accept", "Acceptera"), + ("Reject", "Avvisa"), + ("Add Selection", "Lägg till markering"), + ("Add the selection", "Lägg till markeringen"), + ("Add to Swatches", "Lägg till i färgrutor"), + ("Align Stroke:", "Justera kontur:"), + ("All Caps", "Versaler"), + ("Angle", "Vinkel"), + ("Angle:", "Vinkel:"), + ("Baseline", "Baslinje"), + ("Cap:", "Ände:"), + ("Cell Text", "Celltext"), + ("Cell Type", "Celltyp"), + ("Column Width", "Kolumnbredd"), + ("Column Rules", "Spaltlinjer"), + ("Insert Column Rule", "Infoga spaltlinje"), + ("Tint %", "Färgton %"), + ("Top Inset", "Övre infällning"), + ("Bottom Inset", "Infällning nederkant"), + ("Horizontal Offset", "Horisontell förskjutning"), + ("Composer", "Sättningsmotor"), + ("Convert Selection to Multi-State Object", "Konvertera markering till objekt med flera lägen"), + ("Convert to Text", "Konvertera till text"), + ("Create New Layer", "Skapa nytt lager"), + ("Default", "Standard"), + ("Delete DTD", "Radera DTD"), + ("Delete Layer", "Radera lager"), + ("Delete Page", "Radera sida"), + ("Digits", "Siffror"), + ("Distance", "Avstånd"), + ("Distribute ↔", "Fördela ↔"), + ("Distribute ↕", "Fördela ↕"), + ("Drop Shadow", "Slagskugga"), + ("Effects: Drop Shadow", "Effekter: Slagskugga"), + ("Favorites", "Favoriter"), + ("First Spread", "Första uppslaget"), + ("Frame Fitting", "Ramanpassning"), + ("Gap Color:", "Mellanrumsfärg:"), + ("Go To", "Gå till"), + ("Graphic…", "Grafik…"), + ("Home", "Start"), + ("Hyperlink from the selected text or frames", "Hyperlänk från markerad text eller markerade ramar"), + ("Include when exporting", "Inkludera vid export"), + ("Join:", "Hörn:"), + ("Last Spread", "Sista uppslaget"), + ("Linked Stories", "Länkade artiklar"), + ("Load DTD…", "Läs in DTD…"), + ("Location:", "Plats:"), + ("Miter Limit:", "Spetsgräns:"), + ("Move", "Flytta"), + ("New Article from Selection", "Ny artikel från markering"), + ("New Note at Cursor", "Ny anteckning vid textmarkören"), + ("New condition name", "Namn på nytt villkor"), + ("New group…", "Ny grupp…"), + ("New tag", "Ny tagg"), + ("Next Spread", "Nästa uppslag"), + ("Note text", "Anteckningstext"), + ("Offset", "Förskjutning"), + ("Offsets", "Förskjutningar"), + ("Open", "Öppna"), + ("Paragraph alignment", "Styckejustering"), + ("Pick a file in the folder holding the moved graphics", "Välj en fil i mappen som innehåller den flyttade grafiken"), + ("Place", "Placera"), + ("Previous Spread", "Föregående uppslag"), + ("Release to Objects", "Släpp till objekt"), + ("Reverse the gradient", "Vänd gradienten"), + ("Rotate 90° Counterclockwise", "Rotera 90° moturs"), + ("Rotation Angle", "Rotationsvinkel"), + ("Row Height", "Radhöjd"), + ("Run", "Kör"), + ("Scale X Percentage", "Skala X i procent"), + ("Scale Y Percentage", "Skala Y i procent"), + ("Search commands", "Sök kommandon"), + ("Search fonts", "Sök typsnitt"), + ("Search styles and commands…", "Sök format och kommandon…"), + ("Search: character or U+code", "Sök: tecken eller U+kod"), + ("Separated by commas", "Avgränsade med kommatecken"), + ("Share", "Dela"), + ("Shear X Angle", "Skjuvningsvinkel X"), + ("Show / hide text with this condition", "Visa/dölj text med det här villkoret"), + ("Show Favorites Only", "Visa endast favoriter"), + ("Show in the text", "Visa i texten"), + ("Spreads of up to 10 pages", "Uppslag på upp till 10 sidor"), + ("Stop Color:", "Stoppfärg:"), + ("Strikethrough", "Genomstruken"), + ("Structure", "Struktur"), + ("Style", "Stil"), + ("Style source", "Stilkälla"), + ("Styles panel", "Panelen Stilar"), + ("Superscript", "Upphöjd"), + ("Tag the selection", "Tagga markeringen"), + ("The structure is valid.", "Strukturen är giltig."), + ("Toggle Fill and Stroke", "Växla fyllning och kontur"), + ("Toggle double column", "Växla dubbel kolumn"), + ("Type:", "Typ:"), + ("Underline", "Understrykning"), + ("Untag Selection", "Ta bort tagg från markering"), + ("Update", "Uppdatera"), + ("Validate", "Validera"), + ("Weight", "Tjocklek"), + ("Subtract", "Subtrahera"), + ("Intersect", "Skärning"), + ("Exclude Overlap", "Uteslut överlappning"), + ("Minus Back", "Minus bakom"), + ("Make Compound", "Skapa sammansatt"), + ("Release", "Släpp"), + ("Paths", "Banor"), + ("Align left edges", "Justera vänsterkanter"), + ("Align horizontal centers", "Justera horisontella mittpunkter"), + ("Align right edges", "Justera högerkanter"), + ("Align top edges", "Justera överkanter"), + ("Align vertical centers", "Justera vertikala mittpunkter"), + ("Align bottom edges", "Justera nederkanter"), + ("Align to Selection", "Justera mot markering"), + ("Align to Key Object", "Justera mot nyckelobjekt"), + ("Align to Margins", "Justera mot marginaler"), + ("Align to Page", "Justera mot sida"), + ("Align to Spread", "Justera mot uppslag"), + ("No Text Wrap", "Ingen textombrytning"), + ("Wrap Around Bounding Box", "Ombryt runt avgränsningsramen"), + ("Wrap Around Object Shape", "Ombryt runt objektets form"), + ("Jump Object", "Hoppa över objekt"), + ("Jump to Next Column", "Hoppa till nästa spalt"), + ("Bulleted List", "Punktlista"), + ("Numbered List", "Numrerad lista"), + ("UPPERCASE", "VERSALER"), + ("Small Caps", "Kapitäler"), + ("Butt", "Rak"), + ("Round", "Rund"), + ("Projecting", "Utskjutande"), + ("Miter", "Spets"), + ("Bevel", "Fasning"), + ("Center", "Center"), + ("Start/End:", "Start/slut:"), + ("First", "Första"), + ("Last", "Senaste"), + ("Before", "Före"), + ("After", "Efter"), + ("Shading", "Skuggning"), + ("Border", "Kant"), + ("Overprint Fill", "Övertryck fyllning"), + ("Overprint Stroke", "Övertryck kontur"), + ("Overprint Gap", "Övertryck mellanrum"), + ("Nonprinting", "Skrivs inte ut"), + ("At Least", "Minst"), + ("Exactly", "Exakt"), + ("Justify", "Marginaljustera"), + ("Underline Options", "Alternativ för understrykning"), + ("Strikethrough Options", "Alternativ för genomstrykning"), + ("Character Style Options", "Alternativ för teckenstil"), + ("Advanced Character Formats", "Avancerade teckenformat"), + ("OpenType Features", "OpenType-funktioner"), + ("Style Settings:", "Stilinställningar:"), + ("Kerning:", "Kerning:"), + ("Case:", "Skiftläge:"), + ("OpenType All Small Caps", "OpenType alla kapitäler"), + ("Subscript", "Nedsänkt"), + ("OpenType Subscript", "OpenType nedsänkt"), + ("OpenType Numerator", "OpenType täljare"), + ("OpenType Denominator", "OpenType nämnare"), + ("Ligatures", "Ligaturer"), + ("No Break", "Ingen radbrytning"), + ("Horizontal Scale:", "Horisontell skala:"), + ("Vertical Scale:", "Vertikal skala:"), + ("Baseline Shift:", "Baslinjeförskjutning:"), + ("Skew:", "Skevning:"), + ("Language:", "Språk:"), + ("Tint:", "Färgton:"), + ("Figure Style:", "Formatmall för figur:"), + ("Underline On", "Understrykning på"), + ("Strikethrough On", "Genomstrykning på"), + ("Edit \"{name}\"…", "Redigera \"{name}\"…"), + ("Discretionary Ligatures", "Valfria ligaturer"), + ("Fractions", "Bråk"), + ("Ordinal", "Ordningstal"), + ("Swash", "Swash"), + ("Titling Alternates", "Rubrikalternativ"), + ("Contextual Alternates", "Kontextuella alternativ"), + ("Slashed Zero", "Nolla med snedstreck"), + ("Tabular Lining", "Tabellsiffror, versala"), + ("Proportional Oldstyle", "Proportionella medievalsiffror"), + ("Proportional Lining", "Proportionella versalsiffror"), + ("Tabular Oldstyle", "Medievalsiffror i tabellbredd"), + ("Default Figure Style", "Standardfigurstil"), + ("Not a button", "Inte en knapp"), + ("Go To Next Page", "Gå till nästa sida"), + ("Go To Previous Page", "Gå till föregående sida"), + ("Go To First Page", "Gå till första sidan"), + ("Go To Last Page", "Gå till sista sidan"), + ("Go To Page", "Gå till sida"), + ("Go To URL", "Gå till URL"), + ("Not a form field", "Inte ett formulärfält"), + ("Text Field", "Textfält"), + ("Check Box", "Kryssruta"), + ("Radio Button", "Alternativknapp"), + ("Combo Box", "Kombinationsruta"), + ("List Box", "Listruta"), + ("Signature", "Signatur"), + ("Resize width", "Ändra bredd"), + ("Resize height", "Ändra höjd"), + ("Pin top", "Fäst överkant"), + ("Pin bottom", "Fäst nederkant"), + ("Pin left", "Fäst vänster"), + ("Pin right", "Fäst höger"), + ("Inward", "Inåt"), + ("Metrics", "Mått"), + ("Optical", "Optisk"), + ("Applies to fill", "Gäller för fyllning"), + ("Applies to text", "Gäller för text"), + ("Gray", "Grå"), + ("Linear", "Linjär"), + ("Radial", "Radiell"), + ("Arabic", "Arabiska"), + ("Beveled Rectangle", "Avfasad rektangel"), + ("Chinese", "Kinesiska"), + ("Constrain proportions for width and height", "Behåll proportioner för bredd och höjd"), + ("Custom", "Anpassad"), + ("Czech", "Tjeckiska"), + ("Danish", "Danska"), + ("Dashed", "Streckad"), + ("Dotted", "Prickad"), + ("Dutch: 2005 Reform", "Nederländska: 2005 års reform"), + ("Embedded", "Inbäddad"), + ("English: Canadian", "Engelska: Kanada"), + ("English: UK", "Engelska: Storbritannien"), + ("English: USA", "Engelska: USA"), + ("Farsi", "Farsi"), + ("Finnish", "Finska"), + ("French", "Franska"), + ("French: Canadian", "Franska: kanadensisk"), + ("German: 2006 Reform", "Tyska: reformen 2006"), + ("German: Swiss 2006 Reform", "Tyska: schweizisk, reformen 2006"), + ("Greek", "Grekiska"), + ("Hebrew", "Hebreiska"), + ("Hindi", "Hindi"), + ("Hungarian", "Ungerska"), + ("Inverse Rounded Rectangle", "Omvänd rundad rektangel"), + ("Italian", "Italienska"), + ("Japanese", "Japanska"), + ("Korean", "Koreanska"), + ("Make all settings the same", "Gör alla inställningar lika"), + ("Native", "Ursprunglig"), + ("Norwegian: Bokmål", "Norska: bokmål"), + ("Orthogonal Line", "Ortogonal linje"), + ("Polish", "Polska"), + ("Portuguese", "Portugisiska"), + ("Portuguese: Brazilian", "Portugisiska: brasiliansk"), + ("Rounded Rectangle", "Rundad rektangel"), + ("Russian", "Ryska"), + ("Solid", "Enfärgad"), + ("Spanish", "Spanska"), + ("Swedish", "Svenska"), + ("Thick - Thick", "Tjock - tjock"), + ("Thick - Thin", "Tjock - tunn"), + ("Thin - Thick", "Tunn - tjock"), + ("Thin - Thin", "Tunn - tunn"), + ("Thin - Thick - Thin", "Tunn - tjock - tunn"), + ("Thick - Thin - Thick", "Tjock - tunn - tjock"), + ("Wavy", "Vågig"), + ("Straight Hash", "Rakt nummertecken"), + ("Stripes", "Ränder"), + ("Triangle", "Triangel"), + ("Turkish", "Turkiska"), + ("Ukrainian", "Ukrainska"), + ("Cell Style", "Cellstil"), + ("Table Style", "Tabellstil"), + ("Col ←", "Kol ←"), + ("Col →", "Kol →"), + ("Row ↑", "Rad ↑"), + ("Row ↓", "Rad ↓"), + ("Hide Others", "Göm övriga"), + ("Lock Others", "Lås övriga"), + ("Show All Layers", "Visa alla lager"), + ("Unlock", "Lås upp"), + ("Unlock All Layers", "Lås upp alla lager"), + ("Added", "Tillagd"), + ("Deleted", "Borttaget"), + ("Guide-based", "Stödlinjebaserad"), + ("Page:", "Sida:"), + ("Content:", "Innehåll:"), + ("Object Constraints:", "Objektbegränsningar:"), + ("Resize with Page:", "Ändra storlek med sidan:"), + ("Pin:", "Fäst:"), + ("Object-Based", "Objektbaserad"), + ("Guide-Based", "Stödlinjebaserad"), + ("Resize Page", "Ändra sidstorlek"), + ("Liquid Page Rule:", "Regel för flytande sida:"), + ("Show Parent Page Overlay", "Visa mallsidesöverlägg"), + ("Controlled by Parent", "Styrs av mallsida"), + ("US Business Card", "Amerikanskt visitkort"), + ("Object is pinned relative to the page edge. Click to release.", "Objektet är fäst relativt sidkanten. Klicka för att släppa."), + ("Click to pin the object relative to the page edge.", "Klicka för att fästa objektet relativt sidkanten."), + ( + "The object changes width as the page changes width. Click to lock the object width.", + "Objektets bredd ändras när sidans bredd ändras. Klicka för att låsa objektets bredd.", + ), + ( + "The object's width is locked. Click to let the object change width as the page changes width.", + "Objektets bredd är låst. Klicka för att låta objektets bredd ändras när sidans bredd ändras.", + ), + ( + "The object changes height as the page changes height. Click to lock the object height.", + "Objektets höjd ändras när sidans höjd ändras. Klicka för att låsa objektets höjd.", + ), + ( + "The object's height is locked. Click to let the object change height as the page changes height.", + "Objektets höjd är låst. Klicka för att låta objektets höjd ändras när sidans höjd ändras.", + ), + ("Loop", "Loopa"), + ("Object-based", "Objektbaserad"), + ("Play on Page Load", "Spela upp när sidan läses in"), + ("Re-center", "Centrera igen"), + ("Show Controls", "Visa kontroller"), + ("Signature Field", "Signaturfält"), + ("Select text to apply a condition", "Markera text för att tillämpa ett villkor"), + ("Blinds", "Persienner"), + ("Box", "Ruta"), + ("Comb", "Kam"), + ("Cover", "Täck"), + ("Dissolve", "Övertoning"), + ("Fade", "Toning"), + ("Push", "Skjut"), + ("Split", "Dela"), + ("Uncover", "Avtäck"), + ("Wipe", "Ridå"), + ("Simple", "Enkel"), + ("Simple - Wide", "Enkel – bred"), + ("Triangle - Wide", "Triangel – bred"), + ("Barbed", "Hullingförsedd"), + ("Curved", "Krökt"), + ("Circle", "Cirkel"), + ("Circle - Solid", "Cirkel – enfärgad"), + ("Square", "Kvadrat"), + ("Square - Solid", "Kvadrat – enfärgad"), + ("Bar", "Lodstreck"), + ("Hide", "Dölj"), + ("Show", "Visa"), + ("Select", "Markera"), + ("Fit Text", "Anpassa text"), + ("Preview (W)", "Förhandsgranskning (W)"), + ("Normal (W)", "Normal (W)"), + ("Conveyor", "Transportband"), + ("objects", "objekt"), + ("pages", "sidor"), + ("stories", "artiklar"), + ("items", "objekt"), + ("warnings", "varningar"), + ("Render", "Rendera"), + ("Set", "Ange"), + ("unused", "oanvänd"), + ("⚠ Missing", "⚠ Saknas"), + ("▲ Modified", "▲ Ändrad"), + ("(Text Color)", "(Textfärg)"), + ("{count} glyphs — click to insert at the text cursor", "{count} glyfer – klicka för att infoga vid textmarkören"), + ("{pages} Pages in {spreads} Spreads", "{pages} sidor i {spreads} uppslag"), + ("Text Frame", "Textram"), + ("Text Style", "Textstil"), + (" (auto)", " (auto)"), + ("Absolute Numbering (instead of Section Numbering)", "Absolut numrering (i stället för avsnittsnumrering)"), + ( + "Add and remove pages as the primary text frame's story grows and shrinks", + "Lägg till och ta bort sidor när texten i den primära textramen växer och krymper", + ), + ("Added Text (highlighted)", "Tillagd text (färgmarkerad)"), + ("Adjust Layout (objects follow the new page size)", "Anpassa layout (objekt följer den nya sidstorleken)"), + ("Auto-Fit", "Autoanpassa"), + ("Case sensitive", "Skiftlägeskänslig"), + ("Custom Tracking/Kerning", "Anpassad spärrning/kerning"), + ("Dimensions Include Stroke Weight", "Dimensioner inkluderar konturtjocklek"), + ("Enable Autocorrect", "Aktivera autokorrigering"), + ("Enable Dynamic Spelling (underline misspelled words)", "Aktivera dynamisk stavning (stryk under felstavade ord)"), + ("Grids in Back", "Rutnät bakom"), + ("H&J Violations", "Avstavnings- och justeringsfel"), + ("Include Bleed", "Inkludera utfall"), + ("Include Stroke Weight", "Inkludera konturtjocklek"), + ("Keep Violations", "Behåll regelbrott"), + ("Overprint [Black] Swatch at 100%", "Övertryck färgrutan [Black] vid 100 %"), + ("Printer's Marks", "Tryckmärken"), + ("Remove Styles and Formatting from Text and Tables", "Ta bort format och formatering från text och tabeller"), + ("Ruby", "Ruby"), + ("Show Note Anchors in Layout View", "Visa anteckningsankare i layoutvyn"), + ("Spreads", "Uppslag"), + ("Export PDF", "Exportera PDF"), + ("Standard", "Standard"), + ("Standard:", "Standard:"), + ("Compress images", "Komprimera bilder"), + ("Flattener preset", "Förinställning för tillplattning"), + ("Include document bleed", "Inkludera dokumentets utfall"), + ("Crop Marks", "Skärmärken"), + ("Bleed Marks", "Utfallsmärken"), + ("Page Information", "Sidinformation"), + ("Page Range", "Sidomfång"), + ("Page Range:", "Sidomfång:"), + ("Tagged PDF", "Taggad PDF"), + ("Desktop Printing", "Skrivbordsutskrift"), + ("Commercial Printing", "Kommersiellt tryck"), + ("Screen and Email", "Skärm och e-post"), + ("PDF/X-4", "PDF/X-4"), + ("PDF/A-2b", "PDF/A-2b"), + ("Compression", "Komprimering"), + ("Marks and Bleeds", "Märken och utfall"), + ("Preset:", "Förinställning:"), + ("Substituted Fonts", "Ersatta typsnitt"), + ("Transformations are Totals", "Transformeringar anges som totalvärden"), + ("Use Black Point Compensation", "Använd svartpunktskompensering"), + ("Use Typographer's Quotes", "Använd typografiska citattecken"), + ("Whole word", "Hela ord"), + (" Close ", " Stäng "), + ("(Top Level)", "(Översta nivån)"), + ("(import)", "(import)"), + ("Accept All", "Acceptera alla"), + ("Add Document…", "Lägg till dokument…"), + ("Add to Previous Spread", "Lägg till i föregående uppslag"), + ("Align From:", "Justera från:"), + ("Align to baseline grid", "Justera mot baslinjerutnät"), + ("All Spots to Process", "Alla dekorfärger till processfärger"), + ("Allow Spread to Shuffle", "Tillåt omflyttning av uppslag"), + ("Alternating Row Fills", "Alternerande radfyllningar"), + ("Apply Gradient", "Använd gradient"), + ("Apply None (/)", "Använd ingen (/)"), + ("Apply Parent", "Använd mallsida"), + ("Apply to All Spreads", "Använd på alla uppslag"), + ("Apply to Stroke", "Använd på kontur"), + ("Art", "Konst"), + ("Baseline Grid", "Baslinjerutnät"), + ("Bleed and Slug", "Utfall och informationsområde"), + ("Body Rows", "Brödtextrader"), + ("Break Link to Style", "Bryt länk till stil"), + ("Bullets and Numbering", "Punkter och numrering"), + ("Business Card", "Visitkort"), + ("Buttons act in interactive PDF export.", "Knappar fungerar vid export till interaktiv PDF."), + ("Change to:", "Ändra till:"), + ("Character Settings", "Teckeninställningar"), + ("Characters", "Tecken"), + ("Checked by default", "Ikryssad som standard"), + ("Choices", "Val"), + ("Choose Image…", "Välj bild…"), + ("Choose a link.", "Välj en länk."), + ("Content Fitting", "Innehållsanpassning"), + ("Convert Shape", "Konvertera form"), + ("Copies:", "Kopior:"), + ("Count", "Antal"), + ("Create", "Skapa"), + ("Create Alternate Layout", "Skapa alternativ layout"), + ("Create Table…", "Skapa tabell…"), + ("Crop", "Beskär"), + ("Crop Amount", "Beskärningsmängd"), + ("Crop to:", "Beskär till:"), + ("Cross-Reference Format", "Korsreferensformat"), + ("Cursor Key:", "Piltangent:"), + ("Default Fill and Stroke", "Standardfyllning och -kontur"), + ("Default Fill and Stroke (D)", "Standardfyllning och -kontur (D)"), + ("Default View:", "Standardvy:"), + ("Delete Column", "Ta bort kolumn"), + ("Delete Condition", "Radera villkor"), + ("Delete Row", "Ta bort rad"), + ("Delete Swatch", "Radera färgruta"), + ("Delete Unused Layers", "Radera oanvända lager"), + ("Delete Workspace", "Radera arbetslayout"), + ("Document Grid", "Dokumentrutnät"), + ("Document Recovery Data", "Återställningsdata för dokument"), + ("Duplicate Spread", "Duplicera uppslag"), + ("Duplicate Spread at End of Document", "Duplicera uppslag i slutet av dokumentet"), + ("Delete Spread", "Radera uppslag"), + ("Parent Pages", "Mallsidor"), + ("Apply Parent to Pages", "Använd mallsida på sidor"), + ("Email", "E-post"), + ("Embed", "Bädda in"), + ("Fast", "Snabb"), + ("Fill (X)", "Fyllning (X)"), + ("Fill with Placeholder Text", "Fyll med platshållartext"), + ("Find All", "Sök alla"), + ("Find what:", "Sök efter:"), + ("Fit frame height to text", "Anpassa ramhöjden till texten"), + ("Fitting:", "Anpassning:"), + ("Flip Horizontal", "Vänd vågrätt"), + ("Flip Vertical", "Vänd lodrätt"), + ("Font Size:", "Teckenstorlek:"), + ("Form Field", "Formulärfält"), + ("Format:", "Format:"), + ("Height:", "Höjd:"), + ("Hide Bar", "Dölj fältet"), + ("High Quality", "Hög kvalitet"), + ("Highlight", "Högdager"), + ("Horizontal Gridline Every:", "Horisontell stödlinje var:"), + ("Horizontal Margins:", "Horisontella marginaler:"), + ("Import XML…", "Importera XML…"), + ("Increment Every:", "Öka var:"), + ("Ink Manager", "Tryckfärgshanterare"), + ("Insert Column", "Infoga kolumn"), + ("Insert Page After", "Infoga sida efter"), + ("Insert Row", "Infoga rad"), + ("Inset spacing", "Infällningsavstånd"), + ("Intent:", "Återgivningsmetod:"), + ("Invert", "Invertera"), + ("Keyboard Increments", "Tangentbordssteg"), + ("Kind:", "Typ:"), + ("Link To:", "Länka till:"), + ("Liquid guides", "Flytande stödlinjer"), + ("Load Profile…", "Läs in profil…"), + ("Load Swatches…", "Läs in färgrutor…"), + ("Load…", "Läs in…"), + ("Media", "Media"), + ("Merge into Active Layer", "Sammanfoga med aktivt lager"), + ("Misspelled word → Correction (one per line):", "Felstavat ord → Korrigering (ett per rad):"), + ("Mobile", "Mobil"), + ("More ArtCraft apps", "Fler ArtCraft-appar"), + ("Move Selection Here", "Flytta markeringen hit"), + ("Move to Color Group", "Flytta till färggrupp"), + ("Move to Group", "Flytta till grupp"), + ("Multiline", "Multilinje"), + ("Multiple Objects", "Flera objekt"), + ("Name:", "Namn:"), + ("New Bookmark for This Page", "Nytt bokmärke för den här sidan"), + ("New Book…", "Ny bok…"), + ("New Color Group", "Ny färggrupp"), + ("New Color Group with Swatch", "Ny färggrupp med färgruta"), + ("New Library…", "Nytt bibliotek…"), + ("New Workspace…", "Ny arbetslayout…"), + ("No articles: exports follow page order.", "Inga artiklar: exporten följer sidordningen."), + ("No book open.", "Ingen bok är öppen."), + ("No bookmarks. They become the PDF outline.", "Inga bokmärken. De blir PDF-filens disposition."), + ("No changes.", "Inga ändringar."), + ( + "No conditions. Create one, then select text and click it to apply.", + "Inga villkor. Skapa ett, markera sedan text och klicka på villkoret för att använda det.", + ), + ("No document.", "Inget dokument."), + ( + "No hyperlinks. Select text or a frame, type a URL and click New.", + "Inga hyperlänkar. Markera text eller en ram, skriv en URL och klicka på Nytt.", + ), + ("No library open.", "Inget bibliotek är öppet."), + ("No notes in this document.", "Det finns inga anteckningar i det här dokumentet."), + ("No placed graphics.", "Ingen placerad grafik."), + ("No scripts. Add one below.", "Inga skript. Lägg till ett nedan."), + ("No spot inks", "Inga dekorfärger"), + ("No text anchors in this document.", "Det finns inga textankare i det här dokumentet."), + ("Number of Pages:", "Antal sidor:"), + ("Number of Sides:", "Antal sidor:"), + ("Number of columns", "Antal spalter"), + ("OK changes all: text and paragraph/character styles.", "OK ändrar allt: text samt stycke- och teckenstilar."), + ("OVERSET", "ÖVERSKJUTANDE"), + ("On Release", "Vid släpp"), + ("On Screen:", "På skärmen:"), + ("Open source. No telemetry.", "Öppen källkod. Ingen telemetri."), + ("Options for Black on RGB and Grayscale Devices", "Alternativ för svart på RGB- och gråskaleenheter"), + ("Orientation:", "Orientering:"), + ("Page Numbering", "Sidnumrering"), + ("Page · PPI", "Sida · PPI"), + ("Pages:", "Sidor:"), + ("Part of the ArtCraft suite of open creative tools.", "Del av ArtCraft-sviten av öppna kreativa verktyg."), + ("Pasteboard Options", "Alternativ för montageyta"), + ("Path", "Bana"), + ("Place the insertion point in a table, or create one.", "Placera insättningspunkten i en tabell eller skapa en."), + ("Plain Text", "Oformaterad text"), + ("Plays in EPUB export; print and PDF show the poster.", "Spelas upp vid EPUB-export; utskrift och PDF visar affischen."), + ("Poster", "Affisch"), + ("Printer:", "Skrivare:"), + ("Printing / Exporting:", "Utskrift/export:"), + ("Properties Panel", "Egenskapspanel"), + ("Recently Used", "Senast använda"), + ("Reject All", "Avvisa alla"), + ("Relative To:", "Relativt till:"), + ("Relink to Folder…", "Länka om till mapp…"), + ("Relink…", "Länka om…"), + ("Remove Conditions from Selection", "Ta bort villkor från markeringen"), + ("Repeat Header Rows", "Upprepa rubrikrader"), + ("Replace With", "Ersätt med"), + ("Required", "Obligatoriskt"), + ("Reset All to Defaults", "Återställ alla till standardvärden"), + ("Reverse", "Omvänd"), + ("Right-click: stroke, groups", "Högerklicka: kontur, grupper"), + ("Rotate 90° Clockwise", "Rotera 90° medurs"), + ("Ruler Units", "Linjalenheter"), + ("Save Swatches for Exchange…", "Spara färgrutor för utbyte…"), + ("Save recovery data every:", "Spara återställningsdata var:"), + ("Saves which bars show and where the panels are.", "Sparar vilka fält som visas och var panelerna finns."), + ("Search:", "Sök:"), + ( + "Select a placed video or sound (File › Place a .mp4, .mov, .mp3, .wav …).", + "Markera en placerad video eller ett placerat ljud (Arkiv › Placera en .mp4, .mov, .mp3, .wav …).", + ), + ("Select an object or text to color its fill or stroke.", "Markera ett objekt eller text för att färglägga fyllning eller kontur."), + ("Select an object to give its fill a gradient.", "Markera ett objekt för att ge dess fyllning en gradient."), + ("Select an object to make it a button.", "Markera ett objekt för att göra det till en knapp."), + ("Select an object.", "Markera ett objekt."), + ("Select text or a text frame.", "Markera text eller en textram."), + ( + "Select two or more objects (or a group) to make a multi-state object.", + "Markera två eller fler objekt (eller en grupp) för att skapa ett objekt med flera lägen.", + ), + ("Show Tag Markers", "Visa taggmarkörer"), + ("Single-line", "Enradig"), + ("Smart Text Reflow", "Smart textomflödning"), + ("Speed", "Hastighet"), + ("Star Inset:", "Stjärninfällning:"), + ("Start Page #:", "Startsida nr:"), + ("Start:", "Start:"), + ("Status", "Status"), + ("Stroke (X)", "Kontur (X)"), + ("Style Mapping", "Stilmappning"), + ("Style Name Conflicts", "Stilnamnskonflikter"), + ("Stylistic Sets", "Stilistiska uppsättningar"), + ("Subdivisions:", "Underindelningar:"), + ("Swap Fill and Stroke", "Byt plats på fyllning och kontur"), + ("Swap Fill and Stroke (Shift+X)", "Byt plats på fyllning och kontur (Shift+X)"), + ("Synchronize", "Synkronisera"), + ("System default", "Systemstandard"), + ("Table Dimensions", "Tabelldimensioner"), + ("Text Display Options", "Alternativ för textvisning"), + ("Text Message", "Textmeddelande"), + ("The fill isn't a gradient.", "Fyllningen är inte en gradient."), + ("The library is empty. Select objects and Add Selection.", "Biblioteket är tomt. Markera objekt och välj Lägg till markering."), + ("This PDF has no layers.", "Den här PDF-filen har inga lager."), + ("Track Changes in All Stories", "Spåra ändringar i alla artiklar"), + ("Transitions play in interactive PDF (full-screen mode).", "Övergångar spelas upp i interaktiv PDF (helskärmsläge)."), + ("Trim", "Trimma"), + ("Type Options", "Textalternativ"), + ("Typical", "Normal"), + ("UI Size:", "Gränssnittsstorlek:"), + ("Ungroup Color Group", "Dela upp färggrupp"), + ("Unmerge", "Dela"), + ("Update Numbering", "Uppdatera numrering"), + ("Use Global Light", "Använd globalt ljus"), + ("User Dictionary (this document)", "Användarordlista (det här dokumentet)"), + ("Variable Font", "Variabelt typsnitt"), + ("Vertical Gridline Every:", "Vertikal stödlinje var:"), + ("Vertical Margins:", "Vertikala marginaler:"), + ("Vertical justification", "Vertikal justering"), + ("View Threshold:", "Visningströskel:"), + ("Web", "Webb"), + ("Web Hyperlink", "Webbhyperlänk"), + ("When Scaling", "Vid skalning"), + ("Words, one per line:", "Ord, ett per rad:"), + ("[Basic] (working) ▾", "[Grundläggande] (arbetar) ▾"), + ("[Black] Overprint", "[Svart] övertryck"), + ("[No Group]", "[Ingen grupp]"), + ("[None] — choose a colour on the ramp.", "[Ingen] — välj en färg på färgrampen."), + ("⌥-click clears overrides", "⌥-klicka för att rensa lokala ändringar"), + ("⚠ out of date", "⚠ inaktuell"), + ("Interface", "Gränssnitt"), + ("Advanced Type", "Avancerad typografi"), + ("Composition", "Komposition"), + ("Show Font Names in English", "Visa typsnittsnamn på engelska"), + ("Missing Glyphs", "Saknade glyfer"), + ("Draw Missing Glyphs from Fallback Fonts", "Rita saknade glyfer från reservtypsnitt"), + ("Units & Increments", "Enheter och steg"), + ("Grids", "Rutnät"), + ("Guides & Pasteboard", "Stödlinjer och montageyta"), + ("Dictionary", "Ordlista"), + ("Spelling", "Stavning"), + ("Autocorrect", "Autokorrigering"), + ("Track Changes", "Spåra ändringar"), + ("Story Editor Display", "Visning i artikelredigeraren"), + ("Display Performance", "Visningsprestanda"), + ("Appearance of Black", "Utseende för svart"), + ("File Handling", "Filhantering"), + ("Formatting affects container (J)", "Formateringen påverkar behållaren (J)"), + ("Formatting affects text (J)", "Formateringen påverkar texten (J)"), + ("Apply Color", "Använd färg"), + ("Repeat", "Upprepa"), + ("Count:", "Antal:"), + ("Create as a grid", "Skapa som rutnät"), + ("Rows:", "Rader:"), + ("Columns:", "Kolumner:"), + ("Vertical:", "Vertikalt:"), + ("Horizontal:", "Horisontellt:"), + ("Invalid value", "Ogiltigt värde"), + ("Isolate Blending", "Isolera blandning"), + ("Knockout Group", "Utsparningsgrupp"), + ("Object:", "Objekt:"), + ("Group:", "Grupp:"), + ("Sample Color (Eyedropper)", "Ta färgprov (pipett)"), + ("Apply None", "Använd ingen"), + ("Height Only", "Endast höjd"), + ("Width Only", "Endast bredd"), + ("Height and Width", "Höjd och bredd"), + ("Height only", "Endast höjd"), + ("Width only", "Endast bredd"), + ("Height and width", "Höjd och bredd"), + ("Version", "Version"), + ("{count} characters don't fit", "{count} tecken får inte plats"), + ("document", "dokument"), + ("story", "artikel"), + ("selection", "markering"), + ("top", "överkant"), + ("center", "center"), + ("bottom", "nederkant"), + ("justify", "marginaljustera"), + ("text", "text"), + ("graphic", "grafik"), + ("unassigned", "ej tilldelad"), + ("Perceptual", "Perceptuell"), + ("Relative Colorimetric", "Relativ kolorimetrisk"), + ("Saturation", "Mättnad"), + ("Absolute Colorimetric", "Absolut kolorimetrisk"), + ("No conflicts", "Inga konflikter"), + ("Page (1–{count}):", "Sida (1–{count}):"), + ("Fonts in Document: {count} Missing: {missing}", "Typsnitt i dokumentet: {count} Saknas: {missing}"), + ("Story Direction", "Artikelriktning"), + ("Tate-Chu-Yoko", "Tate-chu-yoko"), + ("Ruby…", "Ruby…"), + ("Kenten", "Kenten"), + ("Warichu", "Warichu"), + ("Tabs", "Tabbstopp"), + ("Story", "Artikel"), + ("Create Outlines", "Skapa konturbanor"), + ("Show Hidden Characters", "Visa dolda tecken"), + ("Unmerge Cells", "Dela celler"), + ("Snap to Guides", "Fäst mot stödlinjer"), + ("Snap to Document Grid", "Fäst mot dokumentrutnät"), + ("Align to Object Edges", "Justera mot objektens kanter"), + ("Align to Object Centers", "Justera mot objektens mittpunkter"), + ("Smart Dimensions", "Smarta mått"), + ("Smart Spacing", "Smarta avstånd"), + ("Snap to Zone", "Fäst mot zon"), + ("Info", "Info"), + ("Index", "Register"), + ("Articles", "Artiklar"), + ("Tags", "Taggar"), + ("Object States", "Objekttillstånd"), + ("Liquid Layout", "Flytande layout"), + ("Split Window", "Dela fönster"), + ("New Window", "Nytt fönster"), + ("CMYK", "CMYK"), + ("Lab", "Lab"), + ("OpenType", "OpenType"), + ("RGB", "RGB"), + ("Accept All Changes", "Acceptera alla ändringar"), + ("Activate Document", "Aktivera dokument"), + ("Add Anchor Point", "Lägg till ankarpunkt"), + ("Add Document", "Lägg till dokument"), + ("Add Hyphenation Exception", "Lägg till avstavningsundantag"), + ("Add Item", "Lägg till objekt"), + ("Add Page to Spread", "Lägg till sida i uppslag"), + ("Allow Selected Spread to Shuffle", "Tillåt omflyttning av markerat uppslag"), + ("Anchored Object Options…", "Alternativ för förankrat objekt…"), + ("Anchored Objects", "Förankrade objekt"), + ("Apply Attributes (Eyedropper)", "Använd attribut (pipett)"), + ("Apply Cell Style", "Använd cellstil"), + ("Apply Condition", "Använd villkor"), + ("Apply Parent to Pages…", "Använd mallsida på sidor…"), + ("ArtCraft App Page…", "ArtCrafts appsida…"), + ("ArtCraft Website…", "ArtCrafts webbplats…"), + ("Attributes", "Attribut"), + ("Bevel and Emboss", "Fasning och relief"), + ("Buttons", "Knappar"), + ("Cell Style Options…", "Alternativ för cellstil…"), + ("Change All (Object)", "Ändra alla (objekt)"), + ("Changes", "Ändringar"), + ("Character Formatting", "Teckenformatering"), + ("Clear Conveyor", "Rensa transportband"), + ("Clear Transformations", "Rensa transformeringar"), + ("Clipping Path…", "Klippbana…"), + ("Close Book", "Stäng bok"), + ("Close Library", "Stäng bibliotek"), + ("Collect", "Samla"), + ("Color Settings…", "Färginställningar…"), + ("Community & Project Links", "Länkar till gemenskap och projekt"), + ("Container", "Behållare"), + ("Content", "Innehåll"), + ("Contextual Task Bar", "Kontextuellt aktivitetsfält"), + ("Control", "Kontroll"), + ("Convert Cell to Graphic Cell", "Konvertera cell till grafikcell"), + ("Convert Cell to Graphic Cell…", "Konvertera cell till grafikcell…"), + ("Convert Cell to Text Cell", "Konvertera cell till textcell"), + ("Convert Color", "Konvertera färg"), + ("Convert Direction Point", "Konvertera riktningspunkt"), + ("Convert Note to Text", "Konvertera anteckning till text"), + ("Convert Table to Text", "Konvertera tabell till text"), + ("Convert Text to Table", "Konvertera text till tabell"), + ("Convert to Button", "Konvertera till knapp"), + ("Convert to Form Field", "Konvertera till formulärfält"), + ("Copy Link(s) To…", "Kopiera länk(ar) till…"), + ("Corner Options…", "Hörnalternativ…"), + ("Create Alternate Layout…", "Skapa alternativ layout…"), + ("Create Frame", "Skapa ram"), + ("Create Merged Document…", "Skapa sammanfogat dokument…"), + ("Cross-Reference Formats", "Korsreferensformat"), + ("Cross-References", "Korsreferenser"), + ("Data Merge Fields", "Fält för datasammanfogning"), + ("Define Cross-Reference Format…", "Definiera korsreferensformat…"), + ("Define Lists…", "Definiera listor…"), + ("Define Text Variable…", "Definiera textvariabel…"), + ("Delete All Guides on Spread", "Radera alla stödlinjer på uppslaget"), + ("Delete Anchor Point", "Radera ankarpunkt"), + ("Delete Item", "Radera objekt"), + ("Delete Text Variable", "Radera textvariabel"), + ("Delete Workspace…", "Radera arbetslayout…"), + ("DesignCraft Website…", "DesignCrafts webbplats…"), + ("DesignCraft on GitHub…", "DesignCraft på GitHub…"), + ("Detach All Objects from Parent", "Koppla bort alla objekt från mallsidan"), + ("Directional Feather", "Riktad fjädring"), + ("Distribute", "Fördela"), + ("Dock Panel", "Docka panel"), + ("Document Endnote Options…", "Alternativ för dokumentets slutnoter…"), + ("Document Preferences", "Inställningar för dokument"), + ("Document Presets", "Dokumentförinställningar"), + ("Document…", "Dokument…"), + ("Edit Parents", "Redigera mallsidor"), + ("Edit Story", "Redigera text"), + ("Endnotes", "Slutnoter"), + ("Entire Pasteboard", "Hela montageytan"), + ("Erase", "Radera"), + ("Export Book to PDF…", "Exportera bok till PDF…"), + ("Export EPUB (Reflowable)…", "Exportera EPUB (flytande)…"), + ("Export Selection as Snippet", "Exportera markering som fragment"), + ("Extend Text Selection", "Utöka textmarkering"), + ("Fast Display", "Snabb visning"), + ("Find Object", "Sök objekt"), + ("Find by Script Label", "Sök efter skriptetikett"), + ("First Object Above", "Första objektet ovanför"), + ("Fit Selection in Window", "Anpassa markeringen till fönstret"), + ("Flattener Preview", "Förhandsgranskning av tillplattning"), + ("Float Panel", "Gör panelen flytande"), + ("Fonts in Document", "Typsnitt i dokumentet"), + ("Form Fields", "Formulärfält"), + ("Frame Fitting Options…", "Alternativ för ramanpassning…"), + ("Generate Index…", "Generera register…"), + ("Generate QR Code…", "Generera QR-kod…"), + ("Generate Static Caption", "Generera statisk bildtext"), + ("Get Story", "Hämta artikel"), + ("Get Table", "Hämta tabell"), + ("Global Light…", "Globalt ljus…"), + ("Go To Link", "Gå till länk"), + ("Go To Source", "Gå till källa"), + ("Gradient Feather", "Gradientfjädring"), + ("Gridify", "Placera i rutnät"), + ("Group Transparency", "Grupptransparens"), + ("Hide Menu Item", "Dölj menyalternativ"), + ("Hide/Lock Others", "Dölj/lås övriga"), + ("High Quality Display", "Visning med hög kvalitet"), + ("History", "Historik"), + ("Import Options: Styles", "Importalternativ: Stilar"), + ("Index Page References", "Sidreferenser i registret"), + ("Inner Glow", "Inre glöd"), + ("Inner Shadow", "Inre skugga"), + ("Insert Anchored Object…", "Infoga förankrat objekt…"), + ("Insert Cross-Reference…", "Infoga korsreferens…"), + ("Insert Endnote", "Infoga slutnot"), + ("Insert Math Expression…", "Infoga matematiskt uttryck…"), + ("Insert Pages…", "Infoga sidor…"), + ("Insert Variable", "Infoga variabel"), + ("Inspect Document", "Inspektera dokumentet"), + ("Interface Color Theme", "Färgtema för gränssnittet"), + ("Join the ArtCraft Discord…", "Gå med i ArtCraft på Discord…"), + ("Last Object Below", "Sista objektet nedanför"), + ("Library Contents", "Biblioteksinnehåll"), + ("Library Items", "Biblioteksobjekt"), + ("Liquid Page Rule", "Regel för flytande sida"), + ("List Documents", "Lista dokument"), + ("List Styles", "Lista stilar"), + ("List Tools", "Lista verktyg"), + ("Load Place Cursor", "Läs in placeringsmarkör"), + ("Make Compound Path", "Skapa sammansatt bana"), + ("Map Styles to Tags", "Mappa stilar till taggar"), + ("Math Expression SVG", "SVG för matematiska uttryck"), + ("Media Options", "Mediealternativ"), + ("Menus…", "Menyer…"), + ("Merge Layers", "Sammanfoga lager"), + ("Move Caret", "Flytta textmarkören"), + ("Move Gap", "Flytta mellanrum"), + ("Move Row", "Flytta rad"), + ("New Book", "Ny bok"), + ("New Cell Style…", "Ny cellstil…"), + ("New Color Swatch…", "Ny färgruta…"), + ("New Condition…", "Nytt villkor…"), + ("New Guide", "Ny stödlinje"), + ("New Hyperlink Destination…", "Nytt hyperlänkmål…"), + ("New Hyperlink…", "Ny hyperlänk…"), + ("New Library", "Nytt bibliotek"), + ("New Page Reference…", "Ny sidreferens…"), + ("New Stroke Style…", "Ny konturstil…"), + ("New Table Style…", "Ny tabellstil…"), + ("Next Cell", "Nästa cell"), + ("Next Document", "Nästa dokument"), + ("Next Object Above", "Nästa objekt ovanför"), + ("Next Object Below", "Nästa objekt nedanför"), + ("Next Object in Group", "Nästa objekt i gruppen"), + ("Object Export Options", "Exportalternativ för objekt"), + ("Object Export Options…", "Exportalternativ för objekt…"), + ("Object Layer Options…", "Lageralternativ för objekt…"), + ("Object Layers", "Objektlager"), + ("Object Liquid Settings", "Inställningar för flexibel layout"), + ("Open Book", "Öppna bok"), + ("Open Bytes", "Öppna byte"), + ("Open IDML", "Öppna IDML"), + ("Open Library", "Öppna bibliotek"), + ("Outer Glow", "Yttre glöd"), + ("Overprint Preview", "Förhandsgranskning av övertryck"), + ("Override All Parent Page Items", "Ändra alla objekt från mallsidan lokalt"), + ("Page Transition", "Sidövergång"), + ("Page Transitions", "Sidövergångar"), + ("Paragraph Formatting", "Styckeformatering"), + ("Paste Into", "Klistra in i"), + ("Paste without Formatting", "Klistra in utan formatering"), + ("Place Caret", "Placera insättningspunkt"), + ("Place Item", "Placera objekt"), + ("Place Snippet", "Placera fragment"), + ("Place and Link", "Placera och länka"), + ("Polygon Settings…", "Polygoninställningar…"), + ("Preflight Document", "Förhandskontrollera dokument"), + ("Previous Cell", "Föregående cell"), + ("Previous Document", "Föregående dokument"), + ("Previous Object in Group", "Föregående objekt i gruppen"), + ("Printers", "Skrivare"), + ("Proof Colors", "Provtrycksfärger"), + ("Proof Setup", "Provtrycksinställningar"), + ("Quick Apply…", "Snabbanvänd…"), + ("Recover Documents", "Återställ dokument"), + ("Recovery Data", "Återställningsdata"), + ("Reject All Changes", "Avvisa alla ändringar"), + ("Release Compound Path", "Släpp sammansatt bana"), + ("Remove All Local Overrides", "Ta bort alla lokala ändringar"), + ("Remove Document", "Ta bort dokument"), + ("Report an Issue…", "Rapportera ett problem…"), + ("Reset Shortcuts", "Återställ kortkommandon"), + ("Reset Workspace", "Återställ arbetslayout"), + ("Resize", "Ändra storlek"), + ("Rotate Spread", "Rotera uppslag"), + ("Run Script", "Kör skript"), + ("Sample Document", "Exempeldokument"), + ("Satin", "Satin"), + ("Save Recovery Data", "Spara återställningsdata"), + ("Script Label", "Skriptetikett"), + ("Select All on Layer", "Markera allt på lagret"), + ("Select Cells", "Markera celler"), + ("Select Column", "Markera kolumn"), + ("Select Frame", "Markera ram"), + ("Select Row", "Markera rad"), + ("Select Table", "Markera tabell"), + ("Select Text", "Markera text"), + ("Select Tool", "Markeringsverktyg"), + ("Select Word", "Markera ord"), + ("Selection Attributes", "Markeringsattribut"), + ("Separations Preview", "Förhandsgranskning av separationer"), + ("Serialize", "Serialisera"), + ("Set Active Layer", "Ange aktivt lager"), + ("Set Shortcut", "Ange kortkommando"), + ("Set Visibility / Lock", "Ange synlighet/lås"), + ("Show Panel", "Visa panel"), + ("Show/Hide Baseline Grid", "Visa/dölj baslinjerutnät"), + ("Show/Hide Frame Edges", "Visa/dölj ramkanter"), + ("Show/Hide Guides", "Visa/dölj stödlinjer"), + ("Show/Hide Hidden Characters", "Visa/dölj dolda tecken"), + ("Show/Hide Panels", "Visa/dölj paneler"), + ("Show/Hide Panels Except Tools", "Visa/dölj paneler utom verktyg"), + ("Show/Hide Rulers", "Visa/dölj linjaler"), + ("Show/Hide Tagged Frames", "Visa/dölj taggade ramar"), + ("Show/Hide Text Threads", "Visa/dölj textflöden"), + ("Smooth", "Mjuk"), + ("Sort", "Sortera"), + ("Split Path", "Dela bana"), + ("Step and Repeat…", "Steg och upprepa…"), + ("Stroke Styles", "Konturstilar"), + ("Style Source", "Stilkälla"), + ("Synchronize Book", "Synkronisera bok"), + ("Table Panel", "Tabellpanel"), + ("Table Style Options…", "Alternativ för tabellstil…"), + ("Table of Contents Entries", "Poster i innehållsförteckningen"), + ("Table of Contents…", "Innehållsförteckning…"), + ("Text Anchors", "Textankare"), + ("Text Variables", "Textvariabler"), + ("Toggle Normal/Preview", "Växla normal/förhandsgranskning"), + ("Toggle Selection", "Växla markering"), + ("Tools: Double Column", "Verktyg: dubbel kolumn"), + ("Transform Panel", "Transformeringspanel"), + ("Transform Values", "Transformeringsvärden"), + ("Transparency Blend Space", "Blandningsrymd för transparens"), + ("Transparency Flattener Presets", "Förinställningar för transparensutjämning"), + ("Type on a Path", "Text på bana"), + ("Type on a Path Options…", "Alternativ för text på bana…"), + ("Typical Display", "Normal visning"), + ("Update Link", "Uppdatera länk"), + ("User Dictionary Words", "Ord i användarordlista"), + ("User Dictionary…", "Användarordlista…"), + ("Zoom To", "Zooma till"), + ("⇧", "⇧"), + ("⌃", "⌃"), + ("⌘", "⌘"), + ("⌥", "⌥"), + ("Accept Change", "Acceptera ändring"), + ("Add Anchor", "Lägg till ankare"), + ("Add Selection to Article", "Lägg till markering i artikel"), + ("Add Unnamed Colors", "Lägg till namnlösa färger"), + ("Add to Dictionary", "Lägg till i ordlistan"), + ("Align Center", "Centrera"), + ("Align Left", "Justera vänster"), + ("Align Right", "Justera höger"), + ("Apply Character Style", "Använd teckenstil"), + ("Apply Object Style", "Använd objektstil"), + ("Apply Paragraph Style", "Använd styckestil"), + ("Apply Table Style", "Använd tabellstil"), + ("Article Options", "Artikelalternativ"), + ("Basic Feather", "Grundläggande fjädring"), + ("Bold", "Fet"), + ("Character Style Options…", "Alternativ för teckenstil…"), + ("Close Path", "Stäng bana"), + ("Color Group Options", "Alternativ för färggrupp"), + ("Condition Options…", "Villkorsalternativ…"), + ("Convert to Liquid Guide", "Konvertera till flytande stödlinje"), + ("Convert to Object", "Konvertera till objekt"), + ("Create Line", "Skapa linje"), + ("Create Path", "Skapa bana"), + ("Decrease Point Size", "Minska punktstorlek"), + ("Delete Article", "Radera artikel"), + ("Delete Bookmark", "Ta bort bokmärke"), + ("Delete Endnote", "Radera slutnot"), + ("Delete Footnote", "Radera fotnot"), + ("Delete Guide", "Radera stödlinje"), + ("Delete Hyperlink", "Radera hyperlänk"), + ("Delete List", "Radera lista"), + ("Delete Note", "Radera anteckning"), + ("Delete Pages", "Radera sidor"), + ("Delete Paragraph Style", "Radera styckestil"), + ("Delete Stroke Style", "Radera konturstil"), + ("Delete Table", "Ta bort tabell"), + ("Delete Tag", "Radera tagg"), + ("Delete Text", "Radera text"), + ("Distribute Columns Evenly", "Fördela kolumner jämnt"), + ("Edit Endnote", "Redigera slutnot"), + ("Edit Note", "Redigera anteckning"), + ("Embed Link", "Bädda in länk"), + ("Flip", "Vänd"), + ("Hyperlink Options…", "Hyperlänkalternativ…"), + ("Increase Point Size", "Öka punktstorlek"), + ("Insert Column Left", "Infoga kolumn till vänster"), + ("Insert Column Right", "Infoga kolumn till höger"), + ("Insert Row Above", "Infoga rad ovanför"), + ("Insert Row Below", "Infoga rad nedanför"), + ("Italic", "Kursiv"), + ("Justify Left", "Marginaljustera vänster"), + ("Layer Options…", "Lageralternativ…"), + ("Move Anchors", "Flytta ankarpunkter"), + ("Move Column", "Flytta kolumn"), + ("Move Guide", "Flytta stödlinje"), + ("Move Layer", "Flytta lager"), + ("Move Pages…", "Flytta sidor…"), + ("Move to Layer", "Flytta till lager"), + ("New Article", "Ny artikel"), + ("New Bookmark", "Nytt bokmärke"), + ("New Layer…", "Nytt lager…"), + ("New Note", "Ny anteckning"), + ("New Object Style…", "Ny objektstil…"), + ("New Parent…", "Ny mallsida…"), + ("New Tag", "Ny tagg"), + ("Paste in Place", "Klistra in på plats"), + ("Place Loaded Graphic", "Placera inläst grafik"), + ("Reject Change", "Avvisa ändring"), + ("Release State to Objects", "Släpp tillstånd till objekt"), + ("Remove Hyphenation Exception", "Ta bort avstavningsundantag"), + ("Remove from Article", "Ta bort från artikel"), + ("Rename", "Byt namn"), + ("Rename Bookmark", "Byt namn på bokmärke"), + ("Rotate", "Rotera"), + ("Scale", "Skala"), + ("Set Cross-Reference Format", "Ange korsreferensformat"), + ("Set Footnote Text", "Ange fotnotstext"), + ("Set Story Text", "Ange artikeltext"), + ("Shear", "Skjuva"), + ("Show All on Spread", "Visa allt på uppslaget"), + ("Show State", "Visa tillstånd"), + ("State Options", "Tillståndsalternativ"), + ("Tag Frame", "Tagga ram"), + ("Tag Text", "Tagga text"), + ("Unlink", "Ta bort länk"), + ("Update Index", "Uppdatera register"), + ("Update Table of Contents", "Uppdatera innehållsförteckning"), + ("Bulleted and Numbered Lists", "Punktlistor och numrerade listor"), + ("Hyperlinks Cross-References", "Hyperlänkar, korsreferenser"), + ("Document Footnote Options...", "Alternativ för dokumentets fotnoter..."), + ("Anchored Object", "Förankrat objekt"), + ("Apply Attributes (Eyedropper", "Använd attribut (pipett"), + ("Captions", "Bildtexter"), + ("Change All (Object", "Ändra alla (objekt"), + ("Clipping Path", "Klippbana"), + ( + "Collect objects with the Content Collector (B); place them with the Content Placer.", + "Samla objekt med innehållsinsamlaren (B) och placera dem med innehållsplaceraren.", + ), + ("Convert Cell Type", "Konvertera celltyp"), + ("Copy Link(s", "Kopiera länk(ar"), + ("DesignCraft", "DesignCraft"), + ("Export EPUB (Fixed Layout", "Exportera EPUB (fast layout"), + ("Export EPUB (Reflowable", "Exportera EPUB (flytande"), + ("Hyperlinks & Cross-References", "Hyperlänkar och korsreferenser"), + ("Hyphens and Dashes", "Bindestreck och tankstreck"), + ("Markers", "Markörer"), + ("Other", "Annat"), + ("Output", "Utdata"), + ("Quotation Marks", "Citattecken"), + ("Symbols", "Symboler"), + ("Type & Tables", "Text och tabeller"), + ( + "Type a word with ~ at each allowed break (ex~am~ple); without ~ the word is never hyphenated.", + "Skriv ett ord med ~ vid varje tillåten avstavning (ex~em~pel); utan ~ avstavas ordet aldrig.", + ), + ("Utilities", "Verktyg"), + ("Paragraph Rules…", "Styckelinjer…"), + ("Paragraph Rules", "Styckelinjer"), + ("Rule Below", "Linje nedanför"), + ("90° CCW", "90° moturs"), + ("90° CW", "90° medurs"), + ("A, B, C, D...", "A, B, C, D..."), + ("All records", "Alla poster"), + ("Alpha Channel", "Alfakanal"), + ("Anchored Object Options", "Alternativ för förankrat objekt"), + ("ArtCraft App Page", "ArtCrafts appsida"), + ("ArtCraft Website", "ArtCrafts webbplats"), + ("Bind to frame", "Koppla till ramen"), + ("Black", "Svart"), + ("Bleed:", "Utfall:"), + ("Bullet Character", "Punkttecken"), + ("CMYK:", "CMYK:"), + ("Center in frame", "Centrera i ramen"), + ("Check Spelling", "Kontrollera stavning"), + ("Clear Rotation", "Rensa rotation"), + ("Closed Path", "Sluten bana"), + ("Color Blindness – Deuteranopia", "Färgblindhet – deuteranopi"), + ("Color Blindness – Protanopia", "Färgblindhet – protanopi"), + ("Column Break", "Kolumnbrytning"), + ("Column spacing", "Kolumnavstånd"), + ("Columns first", "Kolumner först"), + ("Conditional Text", "Villkorlig text"), + ("Copyright Symbol", "Upphovsrättssymbol"), + ("Corner Options", "Hörnalternativ"), + ("Create Guides", "Skapa stödlinjer"), + ("Cyan", "Cyan"), + ("Dark", "Mörk"), + ("Data Merge", "Datasammanfogning"), + ("Define Cross-Reference Format", "Definiera korsreferensformat"), + ("Define Lists", "Definiera listor"), + ("Define Text Variable", "Definiera textvariabel"), + ("Delete Type from Path", "Radera text från bana"), + ("DesignCraft Website", "DesignCrafts webbplats"), + ("DesignCraft on GitHub", "DesignCraft på GitHub"), + ("Detect Edges", "Identifiera kanter"), + ("Discretionary Hyphen", "Mjukt bindestreck"), + ("Document CMYK", "Dokument-CMYK"), + ("Document Endnote Options", "Alternativ för dokumentets slutnoter"), + ("Document Footnote Options", "Alternativ för dokumentets fotnoter"), + ("Document RGB", "Dokument-RGB"), + ("Double Left Quotation Marks", "Dubbla vänstercitattecken"), + ("Double Right Quotation Marks", "Dubbla högercitattecken"), + ("Edit/Interface Language", "Redigera/Gränssnittsspråk"), + ("Edit/Spelling", "Redigera/Stavning"), + ("Edit/Transparency Blend Space", "Redigera/Färgrymd för transparensblandning"), + ("Edit/Transparency Flattener Presets", "Redigera/Förinställningar för transparensutjämning"), + ("Ellipsis", "Ellips"), + ("Em Dash", "Långt tankstreck"), + ("Em Space", "Helfyrkant"), + ("En Dash", "Tankstreck"), + ("En Space", "Halvfyrkant"), + ("Export EPUB", "Exportera EPUB"), + ("Export EPUB (Fixed Layout)", "Exportera EPUB (fast layout)"), + ("Export EPUB (Reflowable)", "Exportera EPUB (flytande)"), + ("Export HTML", "Exportera HTML"), + ("Export IDML", "Exportera IDML"), + ("Export PDF (Interactive)", "Exportera PDF (interaktiv)"), + ("Export Page as PNG", "Exportera sidan som PNG"), + ("Export Text", "Exportera text"), + ("Export XML", "Exportera XML"), + ("Figure Space", "Siffermellanrum"), + ("File/Export", "Arkiv/Exportera"), + ("Fill proportionally", "Fyll proportionerligt"), + ("Fit content to frame", "Anpassa innehåll till ram"), + ("Fit proportionally", "Anpassa proportionellt"), + ("Flush Space", "Utfyllnadsblanksteg"), + ("Forced Line Break", "Tvingad radbrytning"), + ("Frame Break", "Rambrytning"), + ("GREP", "GREP"), + ("Generate Index", "Generera register"), + ("Generate Live Caption", "Generera dynamisk bildtext"), + ("Global Light", "Globalt ljus"), + ("Graphic", "Grafik"), + ("Hair Space", "Hårfint blanksteg"), + ("High Contrast", "Hög kontrast"), + ("High Resolution", "Hög upplösning"), + ("I, II, III, IV...", "I, II, III, IV..."), + ("Import XML", "Importera XML"), + ("Indent to Here", "Indrag hit"), + ("Ink Limit 300%", "Total färgmängd 300 %"), + ("Insert Anchored Object", "Infoga förankrat objekt"), + ("Insert Cross-Reference", "Infoga korsreferens"), + ("Insert Math Expression", "Infoga matematiskt uttryck"), + ("Insert Pages", "Infoga sidor"), + ("Insert field", "Infoga fält"), + ("Internet Standard RGB (sRGB)", "Internetstandard-RGB (sRGB)"), + ("Join the ArtCraft Discord", "Gå med i ArtCraft på Discord"), + ("Layout/Index", "Layout/Register"), + ("Layout/Pages", "Layout/Sidor"), + ("Legacy Macintosh RGB", "Äldre Macintosh RGB"), + ("Light", "Ljus"), + ("Limit", "Gränsvärde"), + ("Link images", "Länka bilder"), + ("Load DTD", "Läs in DTD"), + ("Load Swatches", "Läs in färgrutor"), + ("Low Resolution", "Låg upplösning"), + ("Magenta", "Magenta"), + ("Margins and Columns", "Marginaler och spalter"), + ("Margins:", "Marginaler:"), + ("Medium Dark", "Mellanmörk"), + ("Medium Light", "Mellanljus"), + ("Medium Resolution", "Medelhög upplösning"), + ("Menus", "Menyer"), + ("Merge options", "Sammanfogningsalternativ"), + ("Monitor RGB", "Bildskärms-RGB"), + ("Move Pages", "Flytta sidor"), + ("Multiple records", "Flera poster"), + ("New Condition", "Nytt villkor"), + ("New Hyperlink", "Ny hyperlänk"), + ("New Hyperlink Destination", "Nytt hyperlänkmål"), + ("New Page Reference", "Ny sidreferens"), + ("New Parent", "Ny mallsida"), + ("New Stroke Style", "Ny konturstil"), + ("Next", "Nästa"), + ("Next Page Number", "Nästa sidnummer"), + ("No data source", "Ingen datakälla"), + ("Nonbreaking Hyphen", "Hårt bindestreck"), + ("Nonbreaking Space", "Hårt blanksteg"), + ("None (keep transparency)", "Ingen (behåll transparens)"), + ("Numbering & Section Options", "Numrerings- och avsnittsalternativ"), + ("Object/Anchored Object", "Objekt/Förankrat objekt"), + ("Object/Arrange", "Objekt/Ordna"), + ("Object/Captions", "Objekt/Bildtexter"), + ("Object/Clipping Path", "Objekt/Klippbana"), + ("Object/Content", "Objekt/Innehåll"), + ("Object/Convert Shape", "Objekt/Konvertera form"), + ("Object/Effects", "Objekt/Effekter"), + ("Object/Fitting", "Objekt/Anpassning"), + ("Object/Pathfinder", "Objekt/Banfinnare"), + ("Object/Paths", "Objekt/Banor"), + ("Object/Select", "Objekt/Markera"), + ("Object/Transform", "Objekt/Transformera"), + ("Object/Transform Again", "Objekt/Transformera igen"), + ("One record", "En post"), + ("Package", "Paketera"), + ("Page Break", "Sidbrytning"), + ("Paragraph Return", "Styckeretur"), + ("Paragraph Symbol", "Styckesymbol"), + ("Pass csv, rows, or bytes from the control channel.", "Skicka csv, rader eller byte från kontrollkanalen."), + ("Picas", "Pica"), + ("Place with Import Options", "Placera med importalternativ"), + ("Preflight", "Förhandskontroll"), + ("Previous", "Föregående"), + ("Previous Page Number", "Föregående sidnummer"), + ("Print Booklet", "Skriv ut häfte"), + ("Punctuation Space", "Blanksteg för skiljetecken"), + ("Quarter Space", "Fjärdedels blanksteg"), + ("Quick Apply", "Snabbanvänd"), + ("RGB:", "RGB:"), + ("Range", "Omfång"), + ("Record", "Post"), + ("Records per page", "Poster per sida"), + ("Registered Trademark Symbol", "Symbol för registrerat varumärke"), + ("Relink", "Länka om"), + ("Relink to Folder", "Länka om till mapp"), + ("Report an Issue", "Rapportera ett problem"), + ("Right Indent Tab", "Högerindragstabb"), + ("Row spacing", "Radavstånd"), + ("Rows first", "Rader först"), + ("Save As", "Spara som"), + ("Save Swatches for Exchange", "Spara färgrutor för utbyte"), + ("Save a Copy", "Spara en kopia"), + ("Scripts", "Skript"), + ("Section Marker", "Avsnittsmarkör"), + ("Section Symbol", "Paragraftecken"), + ("Select Data Source…", "Välj datakälla…"), + ("Sentence case", "Inledande versal"), + ("Simulate Paper Color", "Simulera pappersfärg"), + ("Single Left Quotation Mark", "Enkelt vänster citattecken"), + ("Single Right Quotation Mark", "Enkelt höger citattecken"), + ("Single record", "En post"), + ("Sixth Space", "Sjättedelsblanksteg"), + ("Slug:", "Informationsområde:"), + ("Smart Guide Options", "Alternativ för smarta stödlinjer"), + ("Step and Repeat", "Steg och upprepa"), + ("Story Column Direction", "Artikelns spaltriktning"), + ("Straight Double Quotation Marks", "Raka dubbla citattecken"), + ("Straight Single Quotation Mark (Apostrophe)", "Rakt enkelt citattecken (apostrof)"), + ("Subscript:", "Nedsänkt:"), + ("Superscript:", "Upphöjd:"), + ("Tab", "Tabb"), + ("Table of Contents", "Innehållsförteckning"), + ("Table/Convert Cell Type", "Tabell/Konvertera celltyp"), + ("Table/Delete", "Tabell/Radera"), + ("Table/Insert", "Tabell/Infoga"), + ("Table/Select", "Tabell/Markera"), + ("Thin Space", "Smalt mellanrum"), + ("Third Space", "Tredjedelsmellanrum"), + ("Title Case", "Inledande versaler"), + ("Trademark Symbol", "Varumärkessymbol"), + ("Transform Again Individually", "Transformera igen individuellt"), + ("Transform Sequence Again", "Transformera sekvens igen"), + ("Transform Sequence Again Individually", "Transformera sekvens igen individuellt"), + ("Type on a Path Options", "Alternativ för text på bana"), + ("Type/Bulleted and Numbered Lists", "Text/Punktlistor och numrerade listor"), + ("Type/Change Case", "Text/Ändra skiftläge"), + ("Type/Hyperlinks & Cross-References", "Text/Hyperlänkar och korsreferenser"), + ("Type/Insert Break Character", "Text/Infoga brytningstecken"), + ("Type/Insert Special Character/Hyphens and Dashes", "Text/Infoga specialtecken/Bindestreck och tankstreck"), + ("Type/Insert Special Character/Markers", "Text/Infoga specialtecken/Markörer"), + ("Type/Insert Special Character/Other", "Text/Infoga specialtecken/Annat"), + ("Type/Insert Special Character/Quotation Marks", "Text/Infoga specialtecken/Citattecken"), + ("Type/Insert Special Character/Symbols", "Text/Infoga specialtecken/Symboler"), + ("Type/Insert White Space", "Text/Infoga blanktecken"), + ("Type/Proof Setup", "Text/Provtrycksinställningar"), + ("Type/Rotate Spread", "Text/Rotera uppslag"), + ("Type/Separations Preview", "Text/Förhandsgranskning av separationer"), + ("Type/Story Direction", "Text/Artikelriktning"), + ("Type/Text Variables", "Text/Textvariabler"), + ("Type/Track Changes", "Text/Spåra ändringar"), + ("Type/Type on a Path", "Text/Text på bana"), + ("URL:", "URL:"), + ("Unassigned", "Ej tilldelad"), + ("View/Display Performance", "Visa/Visningsprestanda"), + ("View/Grids & Guides", "Visa/Rutnät och stödlinjer"), + ("Window/Arrange", "Fönster/Ordna"), + ("Window/Interactive", "Fönster/Interaktivt"), + ("Window/Interface Color Theme", "Fönster/Färgtema för gränssnittet"), + ("Window/Output", "Fönster/Utdata"), + ("Window/Panels", "Fönster/Paneler"), + ("Window/Type & Tables", "Fönster/Text och tabeller"), + ("Window/Utilities", "Fönster/Tillbehör"), + ("Working CMYK", "Arbets-CMYK"), + ("Yellow", "Gul"), + ("a, b, c, d...", "a, b, c, d..."), + ("i, ii, iii, iv...", "i, ii, iii, iv..."), + ("lowercase", "gemener"), + ("All pages", "Alla sidor"), + ("Between Entry and Number:", "Mellan post och nummer:"), + ("Both pages of the parent spread", "Båda sidorna i mallsidans uppslag"), + ("Both pages of the spread", "Båda sidorna i uppslaget"), + ("Close Panel", "Stäng panel"), + ("Data Fields", "Datafält"), + ("Data Merge Options", "Alternativ för datasammanfogning"), + ("Distribute Rows Evenly", "Fördela rader jämnt"), + ("Don't Save", "Spara inte"), + ("Drag Rows or Columns", "Dra rader eller kolumner"), + ("Entry Style:", "Formatmall för post:"), + ("Even Page Break", "Brytning till jämn sida"), + ("Export PowerPoint…", "Exportera PowerPoint…"), + ("Formatting Affects Text", "Formateringen påverkar texten"), + ("Georgian", "Georgiska"), + ("Group with", "Gruppera med"), + ("Import Warnings", "Importvarningar"), + ("Include Paragraph Styles:", "Inkludera styckestilar:"), + ("Insert Field", "Infoga fält"), + ("Level:", "Nivå:"), + ("List Composite Fonts", "Lista sammansatta typsnitt"), + ("Odd Page Break", "Brytning till udda sida"), + ("Optical Margin Alignment", "Optisk marginaljustering"), + ("Other Styles:", "Andra stilar:"), + ("Page Number:", "Sidnummer:"), + ("Pin Bar Position", "Fäst fältets position"), + ("Presentation", "Presentation"), + ("Preview Record", "Förhandsgranska post"), + ("Remove Data Source", "Ta bort datakälla"), + ("Remove Existing Ruler Guides", "Ta bort befintliga stödlinjer"), + ("Remove Field", "Ta bort fält"), + ("Remove »", "Ta bort »"), + ("Replace Existing Table of Contents", "Ersätt befintlig innehållsförteckning"), + ("Reset Bar Position", "Återställ fältets position"), + ("Resize panel window", "Ändra storlek på panelfönster"), + ("Resize panels", "Ändra storlek på paneler"), + ("Select an object to color its fill or stroke.", "Markera ett objekt för att färglägga dess fyllning eller kontur."), + ("Set Composite Font", "Ange komposittypsnitt"), + ("Stop Preview", "Stoppa förhandsgranskning"), + ("Styles in Table of Contents", "Stilar i innehållsförteckningen"), + ("This page", "Den här sidan"), + ("This page is", "Den här sidan är"), + ("Title:", "Titel:"), + ("Unsaved Changes", "Osparade ändringar"), + ("Update Data Source", "Uppdatera datakälla"), + ("Validate from Root Element", "Validera från rotelement"), + ("View/Extras", "Visa/Extrafunktioner"), + ("View/Proof Setup", "Visa/Provtrycksinställningar"), + ("View/Rotate Spread", "Visa/Rotera uppslag"), + ("View/Screen Mode", "Visa/Skärmläge"), + ("View/Separations Preview", "Visa/Förhandsgranskning av separationer"), + ("View/Structure", "Visa/Struktur"), + ("« Add", "« Lägg till"), + ( + "“{}” has changes that are not saved. Save them before closing?", + "”{}” har ändringar som inte har sparats. Vill du spara dem innan du stänger?", + ), + ("Inches Decimal", "Tum decimal"), + ("Back", "Tillbaka"), + ("Warning", "Varning"), + ("Don't show again", "Visa inte igen"), + ("The affected page contains objects. Delete the page anyway?", "Sidan innehåller objekt. Vill du radera sidan ändå?"), + ("The affected pages contain objects. Delete the pages anyway?", "Sidorna innehåller objekt. Vill du radera sidorna ändå?"), + ("Capture", "Inspelning"), + ("Panel Locations", "Panelplaceringar"), + ("Close Tab Group", "Stäng flikgrupp"), + ("Minimize", "Minimera"), + ("Collapse to Icons", "Komprimera till ikoner"), + ("Panel Options", "Panelalternativ"), + ("Panel Options…", "Panelalternativ…"), + ("Show Thumbnails", "Visa miniatyrer"), + ("Show Vertically", "Visa vertikalt"), + ("Panel Layout", "Panellayout"), + ("Pages on Top", "Sidor överst"), + ("Parents on Top", "Mallsidor överst"), + ("Resize:", "Ändra storlek:"), + ("Extra Small", "Extra liten"), + ("Small", "Liten"), + ("Medium", "Medel"), + ("Large", "Stor"), + ("Extra Large", "Extra stor"), + ("Jumbo", "Jumbo"), + ("Proportional", "Proportionell"), + ("Pages Fixed", "Fasta sidor"), + ("Parents Fixed", "Fasta mallsidor"), + ("Parents", "Mallsidor"), + ("Settings…", "Inställningar…"), + ("Left-aligned tab", "Vänsterjusterad tabb"), + ("Centered tab", "Centrerad tabb"), + ("Right-aligned tab", "Högerjusterad tabb"), + ("Tab aligned on a character", "Tabb justerad mot ett tecken"), + ("X:", "X:"), + ("Leader:", "Utfyllnadstecken:"), + ("Align On:", "Justera mot:"), + ("Position panel above text frame", "Placera panelen ovanför textramen"), + ("Clear All", "Rensa alla"), + ("Delete Tab", "Radera tabb"), + ("Repeat Tab", "Upprepa tabb"), + ("Reset Indents", "Återställ indrag"), + ("Redefine Style", "Omdefiniera stil"), + ("Select; drag to move the selection to another layer", "Markera; dra för att flytta markeringen till ett annat lager"), + ("Alt-click clears overrides", "Alt-klick rensar lokala ändringar"), + ("Apply \"{name}\", Clear Overrides", "Använd \"{name}\", rensa lokala ändringar"), + ("Rotate 180°", "Rotera 180°"), + ("No matching commands", "Inga matchande kommandon"), + ("Kanji", "Kanji"), + ("Show CJK Features", "Visa CJK-funktioner"), + ("Page Size:", "Sidstorlek:"), + ("Adjust page elements to document changes", "Anpassa sidelement efter dokumentändringar"), + ("Apply the changes; objects follow the new page size and margins", "Använd ändringarna; objekten följer den nya sidstorleken och marginalerna"), + ("Preflight Panel…", "Panelen Förhandskontroll…"), + ("Recent", "Senaste"), + ("Saved", "Sparat"), + ("[Default]", "[Standard]"), + ("Your Recent Items", "Dina senaste objekt"), + ("Saved Presets", "Sparade förinställningar"), + ("Blank Document Presets", "Förinställningar för tomma dokument"), + ("Delete Preset", "Radera förinställning"), + ("Preset Details", "Detaljer för förinställning"), + ("Document Name", "Dokumentnamn"), + ("Save Document Preset", "Spara dokumentförinställning"), + ("Save Document Preset As:", "Spara dokumentförinställning som:"), + ("Save Preset", "Spara förinställning"), + ("Start #", "Startnr"), + ("Column Gutter", "Spaltmellanrum"), + ("Start Section", "Börja avsnitt"), + ("Automatic Page Numbering", "Automatisk sidnumrering"), + ("Start Page Numbering at:", "Börja sidnumrering vid:"), + ("Section Prefix:", "Avsnittsprefix:"), + ("Section Marker:", "Avsnittsmarkör:"), + ("Include Prefix when Numbering Pages", "Inkludera prefix vid sidnumrering"), + ("Document Chapter Numbering", "Kapitelnumrering för dokument"), + ("Automatic Chapter Numbering", "Automatisk kapitelnumrering"), + ("Start Chapter Numbering at:", "Börja kapitelnumrering vid:"), + ("Same as Previous Document in the Book", "Samma som föregående dokument i boken"), + ("Book Name:", "Boknamn:"), + ("N/A", "Saknas"), + ("Preset Name", "Namn på förinställning"), + ("Bounding Box (Visible Layers Only)", "Avgränsningsram (endast synliga lager)"), + ("Bounding Box (All Layers)", "Avgränsningsram (alla lager)"), + ("Origin:", "Origo:"), + ("Spine", "Rygg"), + ("Lock Zero Point", "Lås nollpunkt"), + ("Unlock Zero Point", "Lås upp nollpunkt"), + ("All", "Alla"), + ("All Lines in Paragraph", "Alla rader i stycket"), + ("Anywhere", "Var som helst"), + ("At Start/End of Paragraph", "Vid styckets början/slut"), + ("Bullet Character:", "Punkttecken:"), + ("Bullets", "Punktlista"), + ("Continue from Previous Number", "Fortsätt från föregående nummer"), + ("End:", "Slut:"), + ("In Next Column", "I nästa spalt"), + ("In Next Frame", "I nästa ram"), + ("Inside Gutter:", "Inre spaltmellanrum:"), + ("Keep Lines Together", "Håll ihop raderna"), + ("Keep Options", "Alternativ för att hålla ihop"), + ("Keep with Next:", "Håll ihop med nästa:"), + ("List Type:", "Listtyp:"), + ("List:", "Lista:"), + ("Mode:", "Läge:"), + ("Numbers", "Siffror"), + ("On Next Even Page", "På nästa jämna sida"), + ("On Next Odd Page", "På nästa udda sida"), + ("On Next Page", "På nästa sida"), + ("Outside Gutter:", "Yttre spaltmellanrum:"), + ("Paragraph Border", "Styckekantlinje"), + ("Paragraph Layout:", "Styckelayout:"), + ("Paragraph Shading", "Styckeskuggning"), + ("Single Column", "Enkel spalt"), + ("Span Columns", "Sträck över spalter"), + ("Split Column", "Dela spalt"), + ("Start At", "Börja vid"), + ("Start Paragraph:", "Första stycke:"), + ("Text After:", "Text efter:"), + ("(Paragraph Font)", "(Styckets typsnitt)"), + ("Any Previous Level", "Valfri föregående nivå"), + ("Bottom Edge:", "Nederkant:"), + ("Bottom Left:", "Nere till vänster:"), + ("Bottom Right:", "Nere till höger:"), + ("Bullets and Numbering…", "Punkter och numrering…"), + ("Clip to Frame", "Beskär till ram"), + ("Corner Size and Shape", "Hörnstorlek och form"), + ("Descent", "Underlängd"), + ("Display Border if Paragraph Splits Across Frames/Columns", "Visa kant om stycket delas mellan ramar/spalter"), + ("Do not Print or Export", "Skriv inte ut eller exportera"), + ("Em Box Bottom", "Em-ruta nederkant"), + ("Em Box Top", "Em-ruta överkant"), + ("Fancy", "Dekorativ"), + ("Gap Tint:", "Färgton för mellanrum:"), + ("Strokes and Fills…", "Konturer och fyllningar…"), + ("Cell Stroke", "Cellkontur"), + ("Cell Fill", "Cellfyllning"), + ("Cell edges", "Cellkanter"), + ( + "Click a line to include or exclude it. Double-click selects all outer or all inner lines; triple-click selects or clears all.", + "Klicka på en linje för att ta med eller utesluta den. Dubbelklicka för att markera alla yttre eller alla inre linjer; trippelklicka för att markera eller rensa alla.", + ), + ("Glyphs…", "Glyfer…"), + ("Inset", "Infällning"), + ("Inverse Rounded", "Omvänt rundad"), + ("Merge Consecutive Borders and Shading", "Sammanfoga intilliggande kantlinjer och skuggning"), + ("Paragraph Borders and Shading", "Kantlinjer och skuggning för stycke"), + ("Paragraph Borders and Shading…", "Kantlinjer och skuggning för stycke…"), + ("Restart Numbers at This Level After:", "Börja om numreringen på den här nivån efter:"), + ("Rounded", "Rundad"), + ("Space After Span:", "Avstånd efter sträckning:"), + ("Space After Split:", "Avstånd efter delning:"), + ("Space Before Span:", "Avstånd före sträckning:"), + ("Space Before Split:", "Avstånd före delning:"), + ("Span Columns…", "Sträck över spalter…"), + ("Tab Position:", "Tabbposition:"), + ("Top Edge:", "Överkant:"), + ("Top Left:", "Uppe till vänster:"), + ("Top Right:", "Uppe till höger:"), + ("Absorb Ideographic Space at Line End", "Absorbera ideografiskt blanksteg vid radslut"), + ("Align Only First Line to Grid", "Justera endast första raden mot rutnätet"), + ("Black Circle", "Svart cirkel"), + ("Black Triangle", "Svart triangel"), + ("Bullseye", "Måltavla"), + ("Bunri-Kinshi", "Bunri-kinshi"), + ("Character:", "Tecken:"), + ("Characters After Break:", "Tecken efter brytning:"), + ("Characters Before Break:", "Tecken före brytning:"), + ("Default Rules", "Standardregler"), + ("Double Circle", "Dubbel cirkel"), + ("Em Box Bottom/Left", "Em-ruta nederkant/vänster"), + ("Em Box Center", "Em-ruta mitt"), + ("Em Box Center (Down)", "Em-ruta mitt (ned)"), + ("Em Box Top/Right", "Em-ruta överkant/höger"), + ("Force", "Tvinga"), + ("Grid Alignment:", "Rutnätsjustering:"), + ("Grid Settings", "Rutnätsinställningar"), + ("Hanging Type:", "Hängningstyp:"), + ("Hard Kinsoku", "Hård kinsoku"), + ("Japanese Composition Settings", "Inställningar för japansk komposition"), + ("Kenten Settings", "Kenten-inställningar"), + ("Kenten Type:", "Kenten-typ:"), + ("Kinsoku Set:", "Kinsoku-uppsättning:"), + ("Kinsoku Type:", "Kinsoku-typ:"), + ("Korean Kinsoku", "Koreansk kinsoku"), + ("Leading Model:", "Radavståndsmodell:"), + ("Left/Right Position:", "Vänster/höger-position:"), + ("Line Break Options", "Alternativ för radbrytning"), + ("Line Spacing:", "Radavstånd:"), + ("Mojikumi Set:", "Mojikumi-uppsättning:"), + ("Prioritize Adjustment Amount", "Prioritera justeringsmängd"), + ("Push In First", "Skjut in först"), + ("Push Out First", "Skjut ut först"), + ("Push Out Only", "Skjut endast ut"), + ("Rensuuji", "Rensuuji"), + ("Roman Baseline", "Baslinje (roman)"), + ("Sesame Dot", "Sesampunkt"), + ("Simplified Chinese Kinsoku", "Kinsoku för förenklad kinesiska"), + ("Small Black Circle", "Liten svart cirkel"), + ("Small White Circle", "Liten vit cirkel"), + ("Soft Kinsoku", "Mjuk kinsoku"), + ("Tate-chu-yoko Settings", "Inställningar för tate-chu-yoko"), + ("Traditional Chinese Kinsoku", "Kinsoku för traditionell kinesiska"), + ("Up/Down Position:", "Position upp/ned:"), + ("Warichu Settings", "Warichu-inställningar"), + ("Warichu Size:", "Warichu-storlek:"), + ("White Circle", "Vit cirkel"), + ("White Sesame Dot", "Vit sesampunkt"), + ("White Triangle", "Vit triangel"), + ("1 Parent Character", "1 bastecken"), + ("1 Ruby Character", "1 ruby-tecken"), + ("1 Ruby Character Aki", "1 ruby-tecken aki"), + ("1-2-1 (JIS) Rule", "1-2-1-regel (JIS)"), + ("1-2-1 Aki", "1-2-1 aki"), + ("1/2 Parent Character", "1/2 bastecken"), + ("1/2 Ruby Character", "1/2 ruby-tecken"), + ("Above/Right", "Ovanför/höger"), + ("Across the Line:", "Tvärs över raden:"), + ("Adjust Rotation", "Justera rotation"), + ("Adjust Tsume", "Justera tsume"), + ("Adjustment When Ruby Is Longer Than Parent", "Justering när ruby är längre än bastexten"), + ("Along the Line:", "Längs raden:"), + ("Auto Align at Line Start/End", "Automatisk justering vid radbörjan/radslut"), + ("Auto Tate-chu-yoko Settings", "Inställningar för automatisk tate-chu-yoko"), + ("Below/Left", "Nedanför/vänster"), + ("Both Sides", "Båda sidor"), + ("Centered", "Centrerad"), + ("Distance from Parent:", "Avstånd från överordnad:"), + ("Equal Aki", "Lika aki"), + ("Fisheye", "Fisköga"), + ("Fit to Width", "Anpassa till bredd"), + ("Full Justify", "Full marginaljustering"), + ("Group Ruby", "Grupp-ruby"), + ("Gyoudori:", "Gyoudori:"), + ("ICF Bottom", "ICF nederkant"), + ("ICF Top", "ICF överkant"), + ("Include Roman Characters", "Inkludera romerska tecken"), + ("Kenten Color", "Kenten-färg"), + ("Left/Top", "Vänster/överkant"), + ("Magnification:", "Förstoring:"), + ("Minimum Scale:", "Minsta skala:"), + ("No Adjustment", "Ingen justering"), + ("Offset from Parent", "Förskjutning från bastext"), + ("Parent Character Spacing:", "Teckenavstånd för bastext:"), + ("Parent's Font", "Bastextens typsnitt"), + ("Per-Character Ruby", "Ruby per tecken"), + ("Right/Bottom", "Höger/nederkant"), + ("Roman Word Break", "Ordbrytning (roman)"), + ("Rotate Roman Characters in Vertical Text", "Rotera romerska tecken i lodrät text"), + ("Ruby Color", "Rubyfärg"), + ("Ruby Font and Size", "Rubytypsnitt och storlek"), + ("Ruby Overhang:", "Ruby-överhäng:"), + ("Ruby Placement and Spacing", "Rubyplacering och avstånd"), + ("Ruby Type:", "Rubytyp:"), + ("Shatai", "Shatai"), + ("Shrink Ruby Width Automatically", "Krymp rubybredd automatiskt"), + ("Tate-chu-yoko Digits:", "Tate-chu-yoko-siffror:"), + ("Text Color", "Textfärg"), + ("Unlimited", "Obegränsat"), + ("Use OpenType Pro Ruby Glyphs", "Använd OpenType Pro-rubyglyfer"), + ("Use Paragraph Gyoudori", "Använd styckets gyoudori"), + ("Swatch Options…", "Färgrutealternativ…"), + ("Swatch Options", "Färgrutealternativ"), + ("Color Group Options…", "Alternativ för färggrupp…"), + ("Layer Options", "Lageralternativ"), + ("Layer Options for \"{name}\"…", "Lageralternativ för \"{name}\"…"), + ("Swatch Name:", "Färgrutenamn:"), + ("Name with Color Value", "Namn med färgvärde"), + ("Color Type:", "Färgtyp:"), + ("Process", "Process"), + ("Spot", "Dekor"), + ("Color Mode:", "Färgläge:"), + ("Base Color:", "Basfärg:"), + ("Edit the gradient's stops in the Gradient panel.", "Redigera gradientens stopp i panelen Gradient."), + ("This swatch can't be edited.", "Den här färgrutan kan inte redigeras."), + ("Light Blue", "Ljusblå"), + ("Red", "Röd"), + ("Green", "Grön"), + ("Blue", "Blå"), + ("Orange", "Orange"), + ("Dark Green", "Mörkgrön"), + ("Teal", "Blågrön"), + ("Tan", "Sandbrun"), + ("Brown", "Brun"), + ("Violet", "Violett"), + ("Gold", "Guld"), + ("Show Layer", "Visa lager"), + ("Lock Layer", "Lås lager"), + ("Print Layer", "Skriv ut lager"), + ("Suppress Text Wrap When Layer is Hidden", "Undertryck textombrytning när lagret är dolt"), + ("Text Anchor", "Textankare"), + ("Open Recent", "Öppna senaste"), + ("Open Recent File", "Öppna senaste fil"), + ("Clear Recent Files", "Rensa senaste filer"), + ("Recent files", "Senaste filer"), + ("Number of Recent Items to Display:", "Antal senaste objekt att visa:"), + ("Paste Vector Art", "Klistra in vektorgrafik"), + ("Baseline Options", "Baslinjealternativ"), + ("Fixed Number", "Fast antal"), + ("Fixed Width", "Fast bredd"), + ("Inset Spacing", "Infällningsavstånd"), + ("Vertical Justification", "Vertikal justering"), + ("Align:", "Justera:"), + ("Ignore Text Wrap", "Ignorera textombrytning"), + ("Technique:", "Teknik:"), + ("Softer", "Mjukare"), + ("Precise", "Exakt"), + ("Corners:", "Hörn:"), + ("Sharp", "Skarp"), + ("Diffused", "Diffus"), + ("Effects…", "Effekter…"), + ("Settings for:", "Inställningar för:"), + ("Transparency…", "Transparens…"), + ("Basic Blending", "Grundläggande blandning"), + ("Opacity:", "Opacitet:"), + ("Blending", "Blandning"), + ("Distance:", "Avstånd:"), + ("X Offset:", "X-förskjutning:"), + ("Y Offset:", "Y-förskjutning:"), + ("Spread:", "Spridning:"), + ("Choke:", "Krympning:"), + ("Source:", "Källa:"), + ("Edge", "Kant"), + ("Depth:", "Djup:"), + ("Highlight:", "Högdager:"), + ("Shadow:", "Skugga:"), + ("Feather Width:", "Fjädringsbredd:"), + ("Feather Widths", "Fjädringsbredder"), + ("Gradient Stops", "Gradientstopp"), + ("Start Opacity:", "Startopacitet:"), + ("End Opacity:", "Slutopacitet:"), + ("(no effects)", "(inga effekter)"), + ("OBJECT", "OBJEKT"), + ("Add an object effect to the selected target", "Lägg till en objekteffekt på det markerade målet"), + ("Load Paragraph Styles…", "Läs in styckestilar…"), + ("Load Character Styles…", "Läs in teckenstilar…"), + ("Load All Text Styles…", "Läs in alla textstilar…"), + ("Load Styles", "Läs in stilar"), + ("Differs from this document", "Skiljer sig från det här dokumentet"), + ("Redefine Document Style", "Omdefiniera dokumentstil"), + ("Use Document Style Definition", "Använd dokumentets formatdefinition"), + ("Auto Rename", "Byt namn automatiskt"), + ("Toggle Presentation", "Visa/dölj presentation"), + ("Balance Columns", "Balansera spalter"), + ("Digits:", "Siffror:"), + ("Justification…", "Justering…"), + ("Apply To:", "Använd på:"), + ("Frame", "Ram"), + ("Filters:", "Filter:"), + ("All Classes", "Alla klasser"), + ("Serif", "Serif"), + ("Slab Serif", "Slab serif"), + ("Sans Serif", "Sans serif"), + ("Script", "Skrivstil"), + ("Monospaced", "Fast teckenbredd"), + ("Decorative", "Dekorativ"), + ("Show Recently Added", "Visa nyligen tillagda"), + ("Small Sample Text Size", "Liten exempeltextstorlek"), + ("Medium Sample Text Size", "Medelstor exempeltext"), + ("Large Sample Text Size", "Stor storlek på exempeltext"), + ("Selected Text", "Markerad text"), + ("Sample", "Exempel"), + ("Similar to {family}", "Likartade {family}"), + ("No fonts match", "Inga typsnitt matchar"), + ("Show Similar Fonts", "Visa likartade typsnitt"), + ("Loading fonts…", "Läser in typsnitt…"), + ("Show Styles", "Visa stilar"), + ("Hide Styles", "Dölj stilar"), + ("TrueType font", "TrueType-typsnitt"), + ("OpenType font", "OpenType-typsnitt"), + ("Variable font", "Variabelt typsnitt"), + ("Color font", "Färgtypsnitt"), + ("Sort Entries in Alphabetical Order", "Sortera poster i bokstavsordning"), + ("% of all commits", "% av alla commits"), + ("(any)", "(valfri)"), + ("(unchanged)", "(oförändrad)"), + ("[No Language]", "[Inget språk]"), + ("About", "Om"), + ("Activate Panel", "Aktivera panel"), + ("Add Anchor Point Tool", "Verktyget Lägg till ankarpunkt"), + ("Align To", "Justera mot"), + ("Alternate layout", "Alternativ layout"), + ("Binary assets added", "Binära resurser tillagda"), + ("Binary assets removed", "Binära resurser borttagna"), + ("Cell Number:", "Cellnummer:"), + ("Change fill to:", "Ändra fyllning till:"), + ("Change Panel Layout", "Ändra panellayout"), + ("Chinese: Simplified", "Kinesiska: förenklad"), + ("Chinese: Traditional", "Kinesiska: traditionell"), + ("Color Theme Tool", "Färgtemaverktyg"), + ("Commits", "Commits"), + ("Company", "Företag"), + ("Content Collector Tool", "Innehållsinsamlingsverktyg"), + ("Content Placer Tool", "Innehållsplaceringsverktyg"), + ("Contributors", "Bidragsgivare"), + ("Convert Rows", "Konvertera rader"), + ("Corner Size", "Hörnstorlek"), + ("Couldn't write recovery data: {error}", "Kunde inte skriva återställningsdata: {error}"), + ("Delete Anchor Point Tool", "Verktyg för att radera ankarpunkt"), + ("DesignCraft page", "DesignCraft-sida"), + ("Direct Selection Tool", "Direktmarkeringsverktyg"), + ("Display name", "Visningsnamn"), + ("Ellipse Frame Tool", "Ellipsramverktyg"), + ("Ellipse Tool", "Ellipsverktyg"), + ("Email Address:", "E-postadress:"), + ( + "Equal fixed heights for the selected rows; cell text may become overset.", + "Lika fasta höjder för de markerade raderna; celltexten kan bli överskjutande.", + ), + ("Erase Tool", "Raderingsverktyg"), + ( + "Export a PDF, IDML or package to share — no cloud account needed.", + "Exportera en PDF, IDML eller ett paket för att dela – inget molnkonto behövs.", + ), + ("Eyedropper Tool", "Pipettverktyg"), + ("Find fill:", "Sök fyllning:"), + ("First commit", "Första commit"), + ("Found", "Hittade"), + ("Free Transform Tool", "Verktyg för fri transformering"), + ("Gap Tool", "Mellanrumsverktyg"), + ("Grab bag", "Blandat"), + ("Gradient Feather Tool", "Verktyg för gradientfjädring"), + ("Gradient Swatch Tool", "Verktyg för gradientfärgruta"), + ("Hand Tool", "Handverktyg"), + ("image editing", "bildredigering"), + ("Import cancelled: the originating document has closed", "Importen avbröts: ursprungsdokumentet har stängts"), + ("Invalid panel layout; restored the default dock", "Ogiltig panellayout; standarddockningen har återställts"), + ("Key Object", "Nyckelobjekt"), + ("Last commit", "Senaste commit"), + ("layer", "lager"), + ("layers", "lager"), + ("Line delta", "Raddifferens"), + ("Line Tool", "Linjeverktyg"), + ("Lines +/−", "Rader +/−"), + ("Lines added", "Tillagda rader"), + ("Lines deleted", "Borttagna rader"), + ("Measure Tool", "Verktyget Mät"), + ("Merged PRs", "Sammanslagna PR:er"), + ("Message:", "Meddelande:"), + ("Models", "Modeller"), + ("motion graphics and visual effects", "rörlig grafik och visuella effekter"), + ("Move Panel", "Flytta panel"), + ("Name (A–Z)", "Namn (A–Ö)"), + ("No contributor data was built into this copy.", "Inga uppgifter om bidragsgivare finns inbyggda i den här kopian."), + ("No matches", "Inga träffar"), + ("No model credits were built into this copy.", "Inga modellkrediteringar finns inbyggda i den här kopian."), + ("Note Tool", "Anteckningsverktyg"), + ("Organization:", "Organisation:"), + ("Packaged {count} files into {dir}", "Paketerade {count} filer i {dir}"), + ("Page Tool", "Sidverktyg"), + ("PDF import cancelled: the originating document has closed", "PDF-importen avbröts: ursprungsdokumentet har stängts"), + ("Pen Tool", "Pennverktyg"), + ("Pencil Tool", "Blyertsverktyg"), + ("Phone:", "Telefon:"), + ("photo library and raw development", "fotobibliotek och raw-framkallning"), + ("Polygon Frame Tool", "Polygonramverktyg"), + ("Polygon Tool", "Polygonverktyg"), + ("Press keys…", "Tryck på tangenter…"), + ("Range:", "Omfång:"), + ("reading, organizing and protecting PDFs", "läsa, ordna och skydda PDF:er"), + ("Real name", "Riktigt namn"), + ("Rectangle Frame Tool", "Rektangelramverktyg"), + ("Rectangle Tool", "Rektangelverktyg"), + ("Relinked {count}", "Omlänkade {count}"), + ("Reverse the order", "Vänd på ordningen"), + ("Rotate Tool", "Rotationsverktyg"), + ("Scale Tool", "Skalningsverktyg"), + ("Scissors Tool", "Saxverktyg"), + ("Selection Tool", "Markeringsverktyg"), + ("Sent {count} page(s) to {printer}", "Skickade {count} sida/sidor till {printer}"), + ("Shear Tool", "Skjuvningsverktyg"), + ("Show/Hide Document Grid", "Visa/dölj dokumentrutnät"), + ("Smooth Tool", "Utjämningsverktyg"), + ("Story Editor — {count} words", "Artikelredigerare – {count} ord"), + ("Story {story} ← story {parent}", "Artikel {story} ← artikel {parent}"), + ("Stroke Weight", "Konturtjocklek"), + ("Subject:", "Ämne:"), + ("Symbol", "Symbol"), + ("Text:", "Text:"), + ("the default printer", "standardskrivaren"), + ("To Body", "Till brödtext"), + ("To Footer", "Till sidfot"), + ("To Header", "Till sidhuvud"), + ("Type on a Path Tool", "Verktyg för text på bana"), + ("Type Tool", "Textverktyg"), + ("Username", "Användarnamn"), + ("vector illustration", "vektorillustration"), + ("Vertical Type on a Path Tool", "Verktyg för vertikal text på bana"), + ("Vertical Type Tool", "Vertikalt textverktyg"), + ("video editing, color and sound", "videoredigering, färg och ljud"), + ("Zoom Tool", "Zoomverktyg"), + ("{contributors} contributors · {commits} commits", "Bidragsgivare: {contributors} · Commits: {commits}"), + ("{count} conflict(s): {names}", "Konflikter ({count}): {names}"), + ("{count} match(es)", "Träffar: {count}"), + ("{count} replacement(s) made", "Antal ersättningar: {count}"), + ("{label}: {name} (double-click: Color Picker)", "{label}: {name} (dubbelklicka för färgväljare)"), + ( + "{name}: import cancelled while a dialog is open; choose the file again", + "{name}: importen avbröts eftersom en dialogruta är öppen; välj filen igen", + ), + ("{name}: {count} step(s) done", "{name}: klart med {count} steg"), + ("Add Tab", "Lägg till tabbstopp"), + ("Auto Tate-Chu-Yoko", "Automatisk tate-chu-yoko"), + ("Break Thread", "Bryt textlänk"), + ("Cancel Preview", "Avbryt förhandsgranskning"), + ("Change Tab", "Ändra tabbstopp"), + ("Character Style", "Teckenstil"), + ("Clear All Tabs", "Rensa alla tabbstopp"), + ("Clear Object Style Overrides", "Rensa lokala ändringar av objektstil"), + ("Clipping Path Options…", "Alternativ för klippbana…"), + ("Close Window", "Stäng fönster"), + ("Color Theme…", "Färgtema…"), + ("Commit Preview", "Godkänn förhandsgranskning"), + ("Convert Direction Point Tool", "Verktyget Konvertera riktningspunkt"), + ("Delete Character Style", "Radera teckenstil"), + ("Delete Document Preset", "Radera dokumentförinställning"), + ("Delete Parent", "Radera mallsida"), + ("Deselect Guides", "Avmarkera stödlinjer"), + ("Email:", "E-post:"), + ("Extract Color Theme", "Extrahera färgtema"), + ("Get Cell Stroke", "Hämta cellkontur"), + ("Get Tabs", "Hämta tabbstopp"), + ("Import InDesign Shortcut Set", "Importera kortkommandon från InDesign"), + ("Join", "Foga samman"), + ("Kerning/Tracking Step", "Steg för kerning/spärrning"), + ("List Styles in File", "Lista stilar i filen"), + ("Maximize/Restore Window", "Maximera/återställ fönster"), + ("Minimize Window", "Minimera fönster"), + ("Move Column Guide", "Flytta spaltstödlinje"), + ("Move Tab", "Flytta tabbstopp"), + ("Move Window", "Flytta fönster"), + ("New Cell Style", "Ny cellstil"), + ("New Table Style", "Ny tabellstil"), + ("Object Style", "Objektstil"), + ("Object Style Options…", "Alternativ för objektstil…"), + ("PRs", "PR:er"), + ("Page Options", "Sidalternativ"), + ("Paragraph Style", "Styckestil"), + ("Parent Options…", "Alternativ för mallsida…"), + ("Preview Change", "Förhandsgranska ändring"), + ("Redefine Character Style", "Definiera om teckenstil"), + ("Redefine Paragraph Style", "Definiera om styckestil"), + ("Reload Fonts", "Läs in typsnitt igen"), + ("Remove Frame from Thread", "Ta bort ram från länkningen"), + ("Reorder Objects", "Ändra ordning på objekt"), + ("Report an issue", "Rapportera ett problem"), + ("Resize Row or Column", "Ändra storlek på rad eller kolumn"), + ("Resize Window", "Ändra storlek på fönster"), + ("Ruler Zero Point", "Linjalens nollpunkt"), + ("Select Guide", "Markera stödlinje"), + ("Select Page", "Markera sida"), + ("Select Paragraph", "Markera stycke"), + ("Select Sentence", "Markera mening"), + ("Select Story", "Markera artikel"), + ("Select Text Unit", "Markera textenhet"), + ("Set OpenType Features", "Ange OpenType-funktioner"), + ("Swap Text Fill and Stroke", "Byt plats på textfyllning och kontur"), + ("Thread Text Frames", "Länka textramar"), + ("Select All Guides", "Markera alla stödlinjer"), + ("Ruler Guide", "Linjalstödlinje"), + ("Lock Column Guides", "Lås spaltstödlinjer"), + ("Character Formatting Controls", "Kontroller för teckenformatering"), + ("Paragraph Formatting Controls", "Kontroller för styckeformatering"), + ("Font Size", "Teckenstorlek"), + ("Vertical Scale", "Vertikal skala"), + ("Horizontal Scale", "Horisontell skala"), + ("Baseline Shift", "Baslinjeförskjutning"), + ("Skew (False Italic)", "Skevning (falsk kursiv)"), + ("Left Indent", "Vänsterindrag"), + ("Right Indent", "Högerindrag"), + ("First Line Left Indent", "Vänsterindrag för första raden"), + ("Last Line Right Indent", "Högerindrag för sista raden"), + ("Drop Cap Number of Lines", "Antal rader för anfang"), + ("Drop Cap One or More Characters", "Antal tecken för anfang"), + ("Align to Baseline Grid", "Justera mot baslinjerutnät"), + ("Go Back", "Gå bakåt"), + ("Go Forward", "Gå framåt"), + ("Restart Numbering", "Starta om numrering"), + ("Continue Numbering", "Fortsätt numrering"), + ("Keep Options…", "Alternativ för att hålla ihop…"), + ("Space Between Paragraphs Using Same Style", "Avstånd mellan stycken med samma format"), + ("Ignore", "Ignorera"), + ("Do Not Align to Baseline Grid", "Justera inte mot baslinjerutnät"), + ("Only Align First Line to Grid", "Justera endast första raden mot rutnätet"), + ("Balance Ragged Lines", "Balansera ojämna rader"), + ("Drop Caps and Nested Styles…", "Anfanger och kapslade stilar…"), + ("GREP Styles…", "GREP-format…"), + ("Restart/Continue Numbering", "Starta om/fortsätt numrering"), + ("Convert Bullets and Numbering to Text", "Konvertera punkter och numrering till text"), + ("Hyphenation…", "Avstavning…"), + ("Hyphenation Settings", "Avstavningsinställningar"), + ("hyphens", "bindestreck"), + ("Hyphenation Zone:", "Avstavningszon:"), + ("Better Spacing", "Bättre avstånd"), + ("Fewer Hyphens", "Färre bindestreck"), + ("Hyphenate Capitalized Words", "Avstava ord med inledande versal"), + ("Hyphenate Last Word", "Avstava sista ordet"), + ("Hyphenate Across Column", "Avstava mellan spalter"), + ("Convert to Note", "Konvertera till anteckning"), + ("Apply Bullets", "Använd punktlista"), + ("Apply Numbers", "Använd numrering"), + ("Convert Variable to Text", "Konvertera variabel till text"), + ("Next Note", "Nästa anteckning"), + ("Previous Note", "Föregående anteckning"), + ("Optical Margin Size", "Storlek för optisk marginal"), + ("Dismiss", "Stäng"), + ("Show/Hide Depth Ruler", "Visa/dölj djuplinjal"), + ("Split Note", "Dela anteckning"), + ("Arrangement", "Arrangemang"), + ("All Inks", "Alla tryckfärger"), + ("Apply Numbering & Section Options", "Använd numrerings- och avsnittsalternativ"), + ("Apply Text Attributes (Eyedropper)", "Använd textattribut (pipett)"), + ("Convert Point", "Konvertera punkt"), + ("Load Styles…", "Läs in stilar…"), + ("Recent Files", "Senaste filer"), + ("Apply to:", "Använd på:"), + ("Auto-Size", "Automatisk storlek"), + ("Create Links When Placing Text Files", "Skapa länkar när textfiler placeras"), + ("Kerning/Tracking:", "Kerning/spärrning:"), + ("Replace All", "Ersätt alla"), + ( + "Replace All updates this font throughout text and styles. Done keeps remaining fallback fonts.", + "Ersätt alla uppdaterar det här typsnittet i all text och alla stilar. Klart behåller återstående reservtypsnitt.", + ), + ("Replace with:", "Ersätt med:"), + ("Stroke Behind Fill", "Kontur bakom fyllning"), + ("Delete the character style \"{name}\"?", "Radera teckenstilen ”{name}”?"), + ("Delete the paragraph style \"{name}\"?", "Radera styckestilen ”{name}”?"), + ("Currently Rendered With", "Återges för närvarande med"), + ( + "“{}” has been edited in this layout. Updating replaces those edits with the text from the file.", + "”{}” har ändrats i den här layouten. Om du uppdaterar ersätts ändringarna med texten från filen.", + ), + ("Proportional Metrics", "Proportionella mått"), + ("Horizontal Kana", "Horisontell kana"), + ("Localized Forms", "Lokaliserade former"), + ("Mark Positioning", "Placering av diakritiska tecken"), + ("Historical Forms", "Historiska former"), + ("Stylistic Alternates", "Stilistiska alternativ"), + ("Justification Alternates", "Alternativa justeringstecken"), + ("Roman Italics", "Roman kursiv"), + ("Letter", "Letter"), + ("Legal", "Legal"), + ("Tabloid", "Tabloid"), + ("Letter - Half", "Letter - halv"), + ("Postcard", "Vykort"), + ("Web 1920 × 1080", "Webb 1920 × 1080"), + ("Web 1366 × 768", "Webb 1366 × 768"), + ("Web 1024 × 768", "Webb 1024 × 768"), + ("Mobile 1080 × 1920", "Mobil 1080 × 1920"), + ("Mobile 390 × 844", "Mobil 390 × 844"), + ("Tablet 1024 × 1366", "Surfplatta 1024 × 1366"), + ("Action", "Åtgärd"), + ("Advance seconds", "Sekunder till nästa"), + ("Affix in", "Fäst i"), + ("Allow", "Tillåt"), + ("Anchor", "Ankare"), + ("Artifact", "Artefakt"), + ("Asset", "Resurs"), + ("Assets", "Resurser"), + ("At end", "I slutet"), + ("Attrs", "Attribut"), + ("Author", "Författare"), + ("Auto fit", "Anpassa automatiskt"), + ("Auto size", "Automatisk storlek"), + ("Auto size reference", "Referenspunkt för automatisk storlek"), + ("Axis", "Axel"), + ("Bands", "Band"), + ("Bookmarks panel", "Panelen Bokmärken"), + ("Case", "Skiftläge"), + ("Columns kind", "Spalttyp"), + ("Continue across stories", "Fortsätt över artiklar"), + ("Cover image", "Omslagsbild"), + ("Definition", "Definition"), + ("Dir", "Riktning"), + ("Dry run", "Testkörning"), + ("Embed fonts", "Bädda in typsnitt"), + ("End", "End"), + ("Extension", "Förlängning"), + ("Family", "Familj"), + ("First baseline min", "Min. första baslinje"), + ("Fit to", "Anpassa till"), + ("Fixed layout", "Fast layout"), + ("Flatten", "Platta till"), + ("Font size", "Teckenstorlek"), + ("From", "Från"), + ("Full screen", "Helskärm"), + ("Grep", "GREP"), + ("Heading", "Rubrik"), + ("Heading style", "Rubrikstil"), + ("Hidden", "Dold"), + ("Identifier", "Identifierare"), + ("Idml", "IDML"), + ("Ids", "Id:n"), + ("Include inside edges", "Ta med inre kanter"), + ("Include prefix", "Ta med prefix"), + ("Instructions", "Instruktioner"), + ("Keep within column", "Håll inom spalten"), + ("Kind", "Typ"), + ("Label", "Etikett"), + ("Latex", "Latex"), + ("Layout page", "Layoutsida"), + ("Line breaks", "Radbrytningar"), + ("Load cursor", "Laddad markör"), + ("Marks", "Märken"), + ("Minimum height", "Minsta höjd"), + ("Minimum width", "Minsta bredd"), + ("Missing only", "Endast saknade"), + ("Mode", "Läge"), + ("Object point", "Objektpunkt"), + ("Org", "Origo"), + ("Page break before", "Sidbrytning före"), + ("Page layout", "Sidlayout"), + ("Para style", "Styckeformat"), + ("Pattern", "Mönster"), + ("Pdf", "PDF"), + ("Pdf crop", "PDF-beskärning"), + ("Pdf page", "PDF-sida"), + ("Pos", "Pos"), + ("Primary text frame", "Primär textram"), + ("Rasterize", "Rastrera"), + ("Rect", "Rekt"), + ("Redefine styles", "Omdefiniera stilar"), + ("Ref", "Ref"), + ("Ref char style", "Ref. teckenformat"), + ("Ref position", "Ref. position"), + ("Remove existing", "Ta bort befintliga"), + ("Restart", "Starta om"), + ("Row gutter", "Radmellanrum"), + ("Rule", "Linje"), + ("Run in", "Inlagd"), + ("Scope", "Omfång"), + ("Section headings", "Avsnittsrubriker"), + ("Shape", "Form"), + ("Space", "Blanksteg"), + ("Start number", "Startnummer"), + ("Start page", "Startsida"), + ("Subpath", "Delbana"), + ("Suggestions", "Förslag"), + ("Tagged", "Taggad"), + ("Target", "Mål"), + ("Threshold", "Tröskel"), + ("To family", "Till familj"), + ("To spread", "Till uppslag"), + ("To style", "Till stil"), + ("Toc title", "Rubrik för innehållsförteckning"), + ("Tolerance", "Tolerans"), + ("Topics", "Ämnen"), + ("Url", "URL"), + ("Use", "Använd"), + ("Use minimum height", "Använd minsta höjd"), + ("Use minimum width", "Använd minsta bredd"), + ("Value", "Värde"), + ("Visible", "Synlig"), + ("Word", "Ord"), + ("X offset", "X-förskjutning"), + ("X relative", "X relativt"), + ("Y offset", "Y-förskjutning"), + (" Save ", " Spara "), + (" Update ", " Uppdatera "), + ("(cycles)", "(växlar)"), + ("(modified)", "(ändrad)"), + ("+Bin", "+Bin"), + ("+LOC", "+LOC"), + ("A command can have at most {n} shortcuts", "Ett kommando kan ha högst {n} kortkommandon"), + ("A set with this name exists", "Det finns redan en uppsättning med det här namnet"), + ("Add a shortcut to {label}", "Lägg till ett kortkommando för {label}"), + ("All Commands", "Alla kommandon"), + ("Also used by {label}", "Används även av {label}"), + ("Alt", "Alt"), + ("Application", "Program"), + ("Approximated", "Approximerad"), + ("Assign", "Tilldela"), + ("Assign to Selected", "Tilldela markerade"), + ("Assign {chord} to {label}", "Tilldela {chord} till {label}"), + ("Auto-Collapse Iconic Panels", "Fäll ihop ikonpaneler automatiskt"), + ("Based on:", "Baserat på:"), + ("Built-in sets cannot be changed", "Inbyggda uppsättningar kan inte ändras"), + ("Cancel Import", "Avbryt import"), + ("Cancel the new shortcut", "Avbryt det nya kortkommandot"), + ("Caps Lock", "Caps Lock"), + ("Check for Updates…", "Sök efter uppdateringar…"), + ("Choose a command…", "Välj ett kommando…"), + ("Click a key to see its shortcuts", "Klicka på en tangent för att se dess kortkommandon"), + ("Close Other Panels in Group", "Stäng andra paneler i gruppen"), + ("Close panel window", "Stäng panelfönstret"), + ("Command", "Kommando"), + ("Command for {item}", "Kommando för {item}"), + ("Commands", "Kommandon"), + ("Conflicts", "Konflikter"), + ("Context:", "Sammanhang:"), + ("Copy Report", "Kopiera rapport"), + ("Ctrl", "Ctrl"), + ("Current shortcuts", "Aktuella kortkommandon"), + ("Current shortcuts:", "Aktuella kortkommandon:"), + ("Currently assigned to:", "Tilldelat för närvarande:"), + ("Default: {chord}", "Standard: {chord}"), + ("Delete Surrounding Text", "Radera omgivande text"), + ("Delete the set “{set}”?", "Radera uppsättningen ”{set}”?"), + ("Detail pane size", "Storlek på detaljrutan"), + ("EPUB Split Document", "EPUB – dela dokument"), + ("Expand", "Expandera"), + ("Expand Panels", "Expandera paneler"), + ("File Info", "Filinformation"), + ("File Info…", "Filinformation…"), + ("Fixed Keys", "Fasta tangenter"), + ("Float Tab Group", "Gör flikgruppen flytande"), + ("Go to Conflict", "Gå till konflikt"), + ("Group Tab Group with", "Gruppera flikgruppen med"), + ("Import", "Importera"), + ("Import as New Set", "Importera som ny uppsättning"), + ("Import “{set}”", "Importera ”{set}”"), + ("Imported", "Importerad"), + ("Imported as “{set}”", "Importerad som ”{set}”"), + ("Import…", "Importera…"), + ("Keep Both", "Behåll båda"), + ("Key: {key}", "Tangent: {key}"), + ("Keyboard", "Tangentbord"), + ("Keyboard Shortcuts (JSON)", "Kortkommandon (JSON)"), + ("Keyboard: US", "Tangentbord: amerikanskt"), + ("Keyboard: US (macOS)", "Tangentbord: amerikanskt (macOS)"), + ("Lock Workspace", "Lås arbetslayout"), + ("Matched without change", "Matchad utan ändring"), + ("Maximize Frame", "Maximera ram"), + ("Modifier on", "Modifierartangent på"), + ("More", "Mer"), + ("Move Guides", "Flytta stödlinjer"), + ("Move Panel to New Window", "Flytta panelen till ett nytt fönster"), + ("Move panel column", "Flytta panelkolumn"), + ("Move panel window", "Flytta panelfönster"), + ("Move tab group", "Flytta flikgrupp"), + ("New Set…", "Ny uppsättning…"), + ("New shortcut:", "Nytt kortkommando:"), + ("New shortcut: {chord}", "Nytt kortkommando: {chord}"), + ("Not assigned", "Inte tilldelad"), + ("Not changed", "Inte ändrad"), + ("Not matched", "Inte matchad"), + ("Nothing uses this key", "Ingenting använder den här tangenten"), + ("Now used by {label}", "Används nu av {label}"), + ("PDF/X-1a:2003", "PDF/X-1a:2003"), + ("Panel or context", "Panel eller sammanhang"), + ("Remove {chord} from {label}", "Ta bort {chord} från {label}"), + ("Reset All", "Återställ alla"), + ("Reset All…", "Återställ alla…"), + ("Restore Frame Size", "Återställ ramstorlek"), + ("Restore every default shortcut in this set?", "Vill du återställa alla standardkortkommandon i den här uppsättningen?"), + ("Restore the default for {label}", "Återställ standardvärdet för {label}"), + ("Revert Set", "Återgå till sparad uppsättning"), + ("Save changes to “{set}”?", "Vill du spara ändringarna i ”{set}”?"), + ("Search by key", "Sök efter tangent"), + ("Select a command first", "Markera ett kommando först"), + ("Select a command to see and change its shortcuts", "Markera ett kommando för att se och ändra dess kortkommandon"), + ("Set name:", "Namn på uppsättning:"), + ("Set:", "Uppsättning:"), + ("Shift", "Shift"), + ("Shortcut", "Kortkommando"), + ("Shortcut Sets", "Uppsättningar av kortkommandon"), + ("Show:", "Visa:"), + ("Skipped", "Överhoppade"), + ("Story Options", "Artikelalternativ"), + ("Suggestions ({n})", "Förslag ({n})"), + ("Summarize…", "Sammanfatta…"), + ("Super", "Super"), + ("Take It", "Ta över"), + ("Take It and Go to Conflict", "Ta över och gå till konflikt"), + ("Taken from other commands", "Övertagna från andra kommandon"), + ("The file is too large", "Filen är för stor"), + ("The name is empty, too long or has control characters", "Namnet är tomt, för långt eller innehåller kontrolltecken"), + ("The scope {scope} is unknown", "Omfånget {scope} är okänt"), + ("The set was not found", "Uppsättningen hittades inte"), + ("There are too many sets", "Det finns för många uppsättningar"), + ("This command is unknown", "Det här kommandot är okänt"), + ("This file is from a newer version (format {n})", "Den här filen kommer från en nyare version (format {n})"), + ("This is not a craft-keymap file", "Det här är inte en craft-keymap-fil"), + ("This is not a shortcut set file", "Det här är inte en fil med en kortkommandouppsättning"), + ("Too many shortcuts are assigned", "För många kortkommandon är tilldelade"), + ("Tools", "Verktyg"), + ("Transparency Flattener", "Utplattning av transparens"), + ("Type…", "Text…"), + ("Unreadable", "Oläsbar"), + ("Use Default", "Använd standard"), + ("Will change", "Ändras"), + ("Win", "Win"), + ("With Shortcut", "Med kortkommando"), + ("empty shortcut", "tomt kortkommando"), + ("in a context that is not imported", "i ett sammanhang som inte importeras"), + ("key sequences are not supported", "tangentsekvenser stöds inte"), + ("line {n}", "rad {n}"), + ("modifier {key} given twice", "modifierartangenten {key} anges två gånger"), + ("more than one command fits", "fler än ett kommando passar"), + ("no command has this name", "inget kommando har det här namnet"), + ("numeric keypad key read as main key", "tangent på det numeriska tangentbordet tolkas som huvudtangent"), + ("only a command of the other kind fits (tool or menu command)", "endast ett kommando av den andra typen passar (verktyg eller menykommando)"), + ("press keys", "tryck på tangenter"), + ("reserved by the system", "reserverad av systemet"), + ("taken by a later entry", "upptaget av en senare post"), + ("taken by {label}", "upptaget av {label}"), + ("the scope is unknown", "omfånget är okänt"), + ("the scope name is not valid", "omfångets namn är inte giltigt"), + ("the set's shortcuts could not be added", "uppsättningens kortkommandon kunde inte läggas till"), + ("the shortcut has no key", "kortkommandot har ingen tangent"), + ("the shortcut is too long", "kortkommandot är för långt"), + ("the shortcuts could not be removed", "kortkommandona kunde inte tas bort"), + ("unknown key {key}", "okänd tangent {key}"), + ("unknown modifier {key}", "okänd modifierartangent {key}"), + ("unsupported modifier {key}", "modifierartangenten {key} stöds inte"), + ("{chord} (Default)", "{chord} (Standard)"), + ("{chord} (press again for a double press)", "{chord} (tryck igen för dubbeltryck)"), + ("{chord} ({scope})", "{chord} ({scope})"), + ("{chord} is reserved by the system", "{chord} är reserverat av systemet"), + ("{chord} was removed from {label}", "{chord} togs bort från {label}"), + ("{chord}: {label}", "{chord}: {label}"), + ("{key}: listed more than once", "{key}: finns med mer än en gång"), + ("{key}: no command has this name", "{key}: inget kommando har det här namnet"), + ("{key}: part of the entry was dropped", "{key}: en del av posten ignorerades"), + ("{key}: the scope in “{text}” is unknown", "{key}: omfånget i ”{text}” är okänt"), + ("{key}: {text} is reserved by the system", "{key}: {text} är reserverat av systemet"), + ("{key}: “{text}” is not a shortcut ({error})", "{key}: ”{text}” är inte ett kortkommando ({error})"), + ("{label} (Changed)", "{label} (Ändrad)"), + ("{label} (cycles)", "{label} (växlar)"), + ("{label} ({scope})", "{label} ({scope})"), + ("{label} ({scope}, both work)", "{label} ({scope}, båda fungerar)"), + ("{label} keeps its shortcuts (matched by a panel menu name)", "{label} behåller sina kortkommandon (matchat via ett namn i en panelmeny)"), + ("{label}: press keys", "{label}: tryck på tangenter"), + ("{label}: {chord}", "{label}: {chord}"), + ("{label}: {chord} (Now used by {holder})", "{label}: {chord} (används nu av {holder})"), + ("{menu} Menu", "Menyn {menu}"), + ("{n} command changed", "{n} kommando ändrades"), + ("{n} command will change", "{n} kommando kommer att ändras"), + ("{n} commands changed", "{n} kommandon ändrades"), + ("{n} commands will change", "{n} kommandon kommer att ändras"), + ("{n} entries cut at a limit", "{n} poster kapades vid en gräns"), + ("{n} entries were ignored: too many commands", "{n} poster ignorerades: för många kommandon"), + ("{n} entry cut at a limit", "{n} post kapades vid en gräns"), + ("{n} entry was ignored: too many commands", "{n} post ignorerades: för många kommandon"), + ("{n} item could not be read", "{n} objekt kunde inte läsas"), + ("{n} item not matched", "{n} objekt matchades inte"), + ("{n} item without a shortcut", "{n} objekt utan kortkommando"), + ("{n} items could not be read", "{n} objekt kunde inte läsas"), + ("{n} items not matched", "{n} objekt matchades inte"), + ("{n} items without a shortcut", "{n} objekt utan kortkommando"), + ("{n} key read approximately", "{n} tangent lästes ungefärligt"), + ("{n} keys read approximately", "{n} tangenter lästes ungefärligt"), + ("{n} saved shortcut could not be used", "{n} sparat kortkommando kunde inte användas"), + ("{n} saved shortcuts could not be used", "{n} sparade kortkommandon kunde inte användas"), + ("{n} shortcut also works in another scope", "{n} kortkommando fungerar även i ett annat omfång"), + ("{n} shortcut is assigned more than once", "{n} kortkommando är tilldelat mer än en gång"), + ("{n} shortcuts also work in another scope", "{n} kortkommandon fungerar även i ett annat omfång"), + ("{n} shortcuts are assigned more than once", "{n} kortkommandon är tilldelade mer än en gång"), + ("{panel} Panel", "Panelen {panel}"), + ("{title} ({n})", "{title} ({n})"), + ("{title}: {set}", "{title}: {set}"), + ("ΔLOC", "ΔLOC"), + ("−Bin", "−Bin"), + ("−LOC", "−LOC"), + ("⚠ {chord} is used by {label}", "⚠ {chord} används av {label}"), + ("Y:", "Y:"), + ("Show the Typography panel", "Visa panelen Typografi"), + ( + "This story was edited in the layout: you'll be asked before those edits are replaced", + "Den här artikeln har ändrats i layouten: du får en fråga innan de ändringarna ersätts", + ), + ("Fewer Options", "Färre alternativ"), + ("Tab Character", "Tabbtecken"), + ("Keep In Frame", "Behåll i ramen"), + ("New Paragraph Style", "Ny styckestil"), + ("New Character Style", "Ny teckenstil"), + ("Next Style:", "Nästa stil:"), + ("[Same style]", "[Samma stil]"), + ("Reset To Base", "Återställ till bas"), + ("Apply Style to Selection", "Använd stil på markeringen"), + ("Change/Find", "Ändra/Sök"), + ("Find Format:", "Sök format:"), + ("Find Format Settings", "Formatinställningar för sökning"), + ("Specify attributes to find", "Ange attribut att söka efter"), + ( + "With a Find Format, only text that has it is found; with nothing in Find what, all text that has it", + "Med Sök format hittas bara text som har formatet; om Sök efter är tomt hittas all text som har det", + ), + ("Change Format:", "Ändra format:"), + ("Change Format Settings", "Formatinställningar för ändring"), + ("Style Options", "Stilalternativ"), + ("[Any Style]", "[Valfri stil]"), + ("Specify attributes to change", "Ange attribut att ändra"), + ("Clear specified attributes", "Rensa angivna attribut"), + ( + "With a Change Format and nothing in Change to, the found text stays and is only formatted", + "Om Ändra format är angivet och Ändra till är tomt behålls den hittade texten och formateras bara", + ), + ("Double Column", "Dubbel kolumn"), + ("Tools Panel:", "Verktygspanel:"), + ("Color Theme:", "Färgtema:"), + ("At End of Document", "I slutet av dokumentet"), + ("At Start of Document", "I början av dokumentet"), + ("Before Page", "Före sidan"), + ("After Page", "Efter sidan"), + ("Parent:", "Mallsida:"), + ("Insert:", "Infoga:"), + ("Stroke Type", "Konturtyp"), + ("Corner Shape", "Hörnform"), + ("Corner Size and Shape:", "Hörnstorlek och form:"), + ("New Section", "Nytt avsnitt"), + ("Clear Frame Fitting Options", "Rensa alternativ för ramanpassning"), + ("Cannot be edited", "Kan inte redigeras"), + ("Maximum:", "Maximum:"), + ("Paragraph Spacing Limit:", "Gränsvärde för styckeavstånd:"), + ("Overprint", "Övertryck"), + ("Top Left Corner", "Övre vänstra hörnet"), + ("Top Right Corner", "Övre högra hörnet"), + ("Bottom Left Corner", "Nedre vänstra hörnet"), + ("Bottom Right Corner", "Nedre högra hörnet"), + ("Anchor Point(s)", "Ankarpunkt(er)"), + ("Convert Points", "Konvertera punkter"), + ("Delete Point(s)", "Radera punkt(er)"), + ("Convert Text to Table…", "Konvertera text till tabell…"), + ("Convert Table to Text…", "Konvertera tabell till text…"), + ("Column Separator", "Kolumnavgränsare"), + ("Row Separator", "Radavgränsare"), + ("Number of Columns", "Antal spalter"), + ("Comma", "Komma"), + ("RGB Color Space View", "Vy för RGB-färgrymd"), + ("Lab Color Space View", "Vy för Lab-färgrymd"), + ("Add CMYK Swatch", "Lägg till CMYK-färgruta"), + ("Added swatch", "Tillagd färgruta"), + ("Eyedropper: drag it onto the page", "Pipett: dra den till sidan"), + ("PDF Preset:", "PDF-förinställning:"), + ("Continue", "Fortsätt"), + ("Printing Instructions", "Utskriftsinstruktioner"), + ("Show Problems Only", "Visa endast problem"), + ("Include PDF (Print)", "Inkludera PDF (utskrift)"), + ("Include IDML", "Inkludera IDML"), + ("Create Printing Instructions", "Skapa utskriftsinstruktioner"), + ("Entire Publication", "Hela publikationen"), + ("Scope:", "Omfång:"), + ("Source", "Källa"), + ("Installed", "Installerade"), + ("Bundled", "Medföljande"), + ("Substituted", "Ersatt"), + ("Modified", "Ändrad"), + ("Missing", "Saknas"), + ("Colors and Inks: {process} process, {spot} spot", "Färger och tryckfärger: {process} processfärger, {spot} dekorfärger"), + ("Embedded images: {embedded}", "Inbäddade bilder: {embedded}"), + ("Instructions:", "Instruktioner:"), + ("Fax:", "Fax:"), + ("Address:", "Adress:"), + ("Company:", "Företag:"), + ("Contact:", "Kontakt:"), + ("Process Black", "Processvart"), + ("Process Yellow", "Processgul"), + ("Process Magenta", "Processmagenta"), + ("Process Cyan", "Processcyan"), + ("Colors and Inks", "Färger och tryckfärger"), + ("Links and Images", "Länkar och bilder"), + ("Fonts", "Typsnitt"), + ("Summary", "Sammanfattning"), + ("Color spectrum", "Färgspektrum"), + ("Object/Convert Point", "Objekt/Konvertera punkt"), + ("Fonts: {used} in use, {missing} unavailable", "Typsnitt: {used} används, {missing} inte tillgängliga"), + ( + "Links and Images: {found} linked, {modified} changed, {missing} not found", + "Länkar och bilder: {found} länkade, {modified} ändrade, {missing} hittades inte", + ), +]; + +pub(super) const CONTEXT: &[(&str, &str, &str)] = &[ + ("Group", "selection", "Gruppera"), + ("Columns", "table", "Kolumner"), + ("Name", "contributors", "Namn"), + ("Number:", "count", "Antal:"), + ("Columns:", "grid", "Kolumner:"), + ("Span Columns", "paragraphLayout", "Sträck över spalter"), +]; diff --git a/crates/ui-egui/src/i18n/tests.rs b/crates/ui-egui/src/i18n/tests.rs index db13138cf..b676a0c5f 100644 --- a/crates/ui-egui/src/i18n/tests.rs +++ b/crates/ui-egui/src/i18n/tests.rs @@ -7,18 +7,28 @@ const LANGUAGE_TABLES: &[(&str, &[(&str, &str)])] = &[ ("cs", cs::TABLE), ("de", de::TABLE), ("fr", fr::TABLE), + ("hu", hu::TABLE), ("it", it::TABLE), ("ja", ja::TABLE), ("ka", ka::TABLE), ("pl", pl::TABLE), ("pt-br", pt_br::TABLE), ("ru", ru::TABLE), + ("sv", sv::TABLE), ("uk", uk::TABLE), ]; /// Every per-language table `tr_context` looks up. -const CONTEXT_TABLES: &[(&str, &[(&str, &str, &str)])] = - &[("ar", ar::CONTEXT), ("cs", cs::CONTEXT), ("ja", ja::CONTEXT), ("pl", pl::CONTEXT), ("ru", ru::CONTEXT), ("uk", uk::CONTEXT)]; +const CONTEXT_TABLES: &[(&str, &[(&str, &str, &str)])] = &[ + ("ar", ar::CONTEXT), + ("cs", cs::CONTEXT), + ("hu", hu::CONTEXT), + ("ja", ja::CONTEXT), + ("pl", pl::CONTEXT), + ("ru", ru::CONTEXT), + ("sv", sv::CONTEXT), + ("uk", uk::CONTEXT), +]; /// The languages of the shared tables' columns, in column order. const SHARED_COLUMNS: [&str; 5] = ["de", "fr", "es", "ja", "zh"]; @@ -31,6 +41,7 @@ fn or_english<'a>(text: &'a str, english: &'a str) -> &'a str { if text.trim().is_empty() { english } else { text } } +/// Checks cached catalog lookup across language switches, including source-text fallback. #[test] fn cached_lookup_preserves_every_translation_across_language_switches() { let own = |lang: &str, key: &str| { @@ -61,6 +72,167 @@ fn cached_lookup_preserves_every_translation_across_language_switches() { } } +/// Checks Hungarian catalog integrity, context captions and count substitutions, including +/// English fallback and preservation of user-defined style and workspace names. +#[test] +fn hungarian_catalog_preserves_placeholders_context_and_counts() { + let catalog: HashMap<_, _> = hu::TABLE.iter().copied().collect(); + assert_eq!(catalog.len(), hu::TABLE.len(), "duplicate Hungarian keys"); + let placeholders = |s: &str| { + let mut names: Vec<_> = s.split('{').skip(1).filter_map(|part| part.split_once('}').map(|(name, _)| name.to_owned())).collect(); + names.sort(); + names + }; + for (key, translation) in hu::TABLE { + assert!(!translation.trim().is_empty(), "empty {key}"); + assert_eq!(placeholders(key), placeholders(translation), "placeholders: {key}"); + assert_eq!(key.ends_with('…'), translation.ends_with('…'), "ellipsis: {key}"); + } + assert!(!is_rtl("hu")); + assert_eq!(tr("hu", "File"), "Fájl"); + assert_eq!(tr("hu", "Bleed"), "Kifutó"); + assert_eq!(tr("hu", "Arrangement"), "Elrendezés"); + assert_eq!(tr("hu", "Unknown label"), "Unknown label"); + assert_eq!(tr("hu", "Columns"), "Hasábok"); + assert_eq!(tr_context("hu", "Columns", "table"), "Oszlopok"); + assert_eq!(tr("hu", "Columns:"), "Hasábok:"); + assert_eq!(tr_context("hu", "Columns:", "grid"), "Oszlopok:"); + assert_eq!(tr_context("hu", "Columns:", "unknown"), "Hasábok:"); + assert_eq!(tr("hu", "Group"), "Csoportosítás"); + assert_eq!(tr_context("hu", "Group", "selection"), "Csoport"); + assert_eq!(tr_context("hu", "Columns", "unknown"), "Hasábok"); + assert_eq!(tr_context("", "Columns", "table"), "Columns"); + for n in [0, 1, 2, 5, 21] { + assert_eq!(count_label("hu", "pages", n), format!("{n} oldal")); + assert_eq!(count_label("hu", "objects", n), format!("{n} objektum")); + assert_eq!(count_label("hu", "errors", n), format!("{n} hiba")); + assert_eq!( + tr("hu", "{pages} Pages in {spreads} Spreads").replace("{pages}", &n.to_string()).replace("{spreads}", &n.to_string()), + format!("{n} oldal, {n} oldalpáron") + ); + } + assert_eq!(style_name("hu", "[Basic Paragraph]"), "[Alapbekezdés]"); + assert_eq!(style_name("hu", "Saját stílus"), "Saját stílus"); + assert_eq!(workspace_name("hu", "Essentials"), "Alapok"); + assert_eq!(workspace_name("hu", "Saját munkaterület"), "Saját munkaterület"); +} + +/// Checks every Latin catalog letter and all Hungarian accented vowels against the +/// configured bundled UI faces, with system and optional craft-fonts fallbacks disabled. +#[test] +fn hungarian_catalog_glyphs_exist_in_the_bundled_ui_fonts() { + let definitions = crate::theme::font_definitions(&[], "hu"); + let db = designcraft_fonts::FontDb::with_font_dirs(Vec::new()); + db.set_system_fallback(false); + let letters: std::collections::BTreeSet<_> = hu::TABLE + .iter() + .flat_map(|(_, text)| text.chars()) + .chain(hu::CONTEXT.iter().flat_map(|(_, _, text)| text.chars())) + .chain("ÁáÉéÍíÓóÖöŐőÚúÜüŰű".chars()) + .filter(|c| c.is_alphabetic() && *c <= '\u{024f}') + .collect(); + for (name, family, style, ui_family) in [ + ("ui", "Source Sans 3", "Regular", egui::FontFamily::Proportional), + ("ui-semibold", "Source Sans 3", "Semibold", egui::FontFamily::Name("semibold".into())), + ("mono", "JetBrains Mono", "Regular", egui::FontFamily::Monospace), + ] { + assert_eq!(definitions.families[&ui_family].first().map(String::as_str), Some(name)); + let face = db.face(family, style); + assert_eq!(face.data(), definitions.font_data[name].bytes(), "configured UI face {name}"); + for letter in &letters { + assert_ne!(face.glyph_for(*letter), 0, "missing {letter} in {family} {style}"); + } + } + eprintln!( + "Hungarian glyph coverage: {} Latin catalog letters, including ŐőŰű, in Source Sans 3 Regular/Semibold and JetBrains Mono Regular; no system/craft fallback", + letters.len() + ); + if let Some(dir) = std::env::var_os("DESIGNCRAFT_HU_REVIEW_SHOTS") { + let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(820.0, 260.0)).build_ui_state( + |ui, ready: &mut bool| { + if !*ready { + ui.ctx().set_fonts(crate::theme::font_definitions(&[], "hu")); + *ready = true; + return; + } + ui.style_mut().visuals = egui::Visuals::light(); + ui.painter().rect_filled(ui.ctx().content_rect(), 0.0, egui::Color32::WHITE); + ui.heading("Magyar ékezetek · ő, ű / Ő, Ű"); + for (name, family) in [ + ("Source Sans 3 Regular", egui::FontFamily::Proportional), + ("Source Sans 3 Semibold", egui::FontFamily::Name("semibold".into())), + ("JetBrains Mono Regular", egui::FontFamily::Monospace), + ] { + ui.label(egui::RichText::new(name).color(egui::Color32::DARK_GRAY)); + ui.label( + egui::RichText::new("Árvíztűrő tükörfúrógép · Őő Űű · ÁÉÍÓÖŐÚÜŰ") + .font(egui::FontId::new(22.0, family)) + .color(egui::Color32::BLACK), + ); + } + }, + false, + ); + h.run_steps(3); + h.render().unwrap().save(std::path::Path::new(&dir).join("hungarian-bundled-ui-fonts.png")).unwrap(); + let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + app.ui.language = "hu".into(); + app.run("file.new", serde_json::json!({"pages": 1})).unwrap(); + app.run( + "frame.create", + serde_json::json!({"rect": [60, 60, 420, 180], "content": "text", "text": "Magyar kiadvány +Árvíztűrő tükörfúrógép +Őő Űű · ÁÉÍÓÖŐÚÜŰ"}), + ) + .unwrap(); + app.run("type.char", serde_json::json!({"attrs": {"fontFamily": "Source Sans 3", "size": 28}})).unwrap(); + app.run("window.panel.activate", serde_json::json!({"panel": "character"})).unwrap(); + let mut interface = crate::test_window::open(app, egui::vec2(1400.0, 900.0)); + interface.render().unwrap().save(std::path::Path::new(&dir).join("designcraft-hungarian-interface.png")).unwrap(); + } +} + +/// Checks translated labels and source-text fallback, plus key uniqueness and nonempty rows +/// in the shared, Arabic, Brazilian Portuguese and Italian catalogs. +#[test] +fn translates_known_strings_and_keeps_the_rest() { + assert_eq!(tr("de", "File"), "Datei"); + assert_eq!(tr("ja", "Swatches"), "スウォッチ"); + assert_eq!(tr("fr", "Something new"), "Something new"); + assert_eq!(tr("", "File"), "File"); + assert_eq!(tr("ar", "File"), "ملف"); + assert_eq!(tr("ar", "Unknown label"), "Unknown label"); + assert_eq!(tr("pt-br", "File"), "Arquivo"); + assert_eq!(tr("pt-br", "New Document…"), "Novo documento…"); + assert_eq!(tr("pt-br", "Unknown label"), "Unknown label"); + assert_eq!(tr("it", "Edit"), "Modifica"); + assert_eq!(tr("it", "New Document…"), "Nuovo documento…"); + assert_eq!(tr("it", "Unknown label"), "Unknown label"); + assert!(is_rtl("ar")); + for (i, (en, translation)) in ar::TABLE.iter().enumerate() { + assert!(ar::TABLE[..i].iter().all(|(key, _)| key != en), "duplicate {en}"); + assert!(!translation.is_empty(), "{en}"); + } + for (i, (en, translation)) in pt_br::TABLE.iter().enumerate() { + assert!(pt_br::TABLE[..i].iter().all(|(key, _)| key != en), "duplicate {en}"); + assert!(!translation.is_empty(), "{en}"); + } + for (i, (en, translation)) in it::TABLE.iter().enumerate() { + assert!(it::TABLE[..i].iter().all(|(key, _)| key != en), "duplicate {en}"); + assert!(!translation.is_empty(), "{en}"); + } + // Italian entries are for keys the shared or Arabic table knows. A new English string + // falls back to English until it is translated, so it doesn't fail here. + for (en, _) in it::TABLE { + assert!(TABLE.iter().any(|(key, _)| key == en) || ar::TABLE.iter().any(|(key, _)| key == en), "it: unknown key {en}"); + } + // Every row is unique and complete. + for (i, (en, t)) in TABLE.iter().enumerate() { + assert!(TABLE[..i].iter().all(|(e, _)| e != en), "duplicate {en}"); + assert!(t.iter().all(|x| !x.is_empty()), "{en}"); + } +} + /// The Data Merge arrangement combo takes its accessible name from `tr(lang, "Arrangement")`. /// A row in only the shared table leaves the languages whose lookup returns directly with the /// English name. @@ -77,6 +249,7 @@ fn arrangement_accessible_name_is_localized_in_every_interface_language() { } } +/// Checks language-specific context precedence and fallback to the plain translation. #[test] fn context_captions_come_from_their_context_or_the_plain_translation() { for (lang, table) in CONTEXT_TABLES { @@ -110,6 +283,38 @@ fn context_captions_come_from_their_context_or_the_plain_translation() { } } +/// Keeps quantity labels distinct from numeric values and checks translated Pages-panel captions. +#[test] +fn a_column_count_and_a_list_number_read_differently() { + for (lang, count, numeral) in [ + ("hu", "Darabszám:", "Szám:"), + ("de", "Anzahl:", "Zahl:"), + ("ja", "数:", "番号:"), + ("uk", "Кількість:", "Номер:"), + ("ar", "العدد:", "الرقم:"), + ("fr", "Nombre :", "Numéro:"), + ("zh", "数量:", "编号:"), + ] { + assert_eq!((tr_context(lang, "Number:", "count"), tr(lang, "Number:")), (count, numeral), "{lang}"); + } + assert_eq!(tr_context("en", "Number:", "count"), "Number:"); + assert_eq!(tr("de", "Gutter:"), "Spaltenabstand:"); + // The Pages panel menu. + for key in [ + "Insert Pages…", + "Move Pages…", + "New Parent…", + "Override All Parent Page Items", + "Remove All Local Overrides", + "Detach All Objects from Parent", + "Create Alternate Layout…", + "Allow Selected Spread to Shuffle", + ] { + assert_ne!(tr("pt-br", key), key); + } + assert_ne!(tr("ar", "Apply Parent to Pages"), "Apply Parent to Pages"); +} + /// The tables `tr` reads, as (language, key, translation), context captions included. fn entries() -> Vec<(&'static str, &'static str, &'static str)> { let mut entries: Vec<_> = LANGUAGE_TABLES.iter().flat_map(|(lang, table)| table.iter().map(|(key, text)| (*lang, *key, *text))).collect(); @@ -263,6 +468,23 @@ fn interface_strings() -> HashSet<&'static str> { keys.extend(crate::panel_docking::DOCK_LABELS.iter().map(|(_, english)| *english)); // UI labels passed to `tr` that no other catalog has yet. keys.extend([ + "180°", + "Create Links When Placing Text Files", + "Delete Character Style…", + "Delete Paragraph Style…", + "Delete the character style \"{name}\"?", + "Delete the paragraph style \"{name}\"?", + "IT", + "Replace with:", + "Show the Typography panel", + "Stroke Behind Fill", + "Stylistic Set", + "The selected fonts have no OpenType features.", + "This story was edited in the layout: you'll be asked before those edits are replaced", + "This style is in use. Text using it will be reassigned to:", + "VA", + "Y:", + "“{}” has been edited in this layout. Updating replaces those edits with the text from the file.", "(any)", "(unchanged)", "[No Language]", diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index de364b91f..ef8629896 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -71,7 +71,7 @@ use app::browser_import_tests; pub use app::opens_as_document; pub use clock::now_ms; pub use key_names::{drop_key_name_text, is_key_name}; -pub use services::{ClipboardFn, DownloadFn, Inbox, OpenAsyncFn, ReadFn, Services, WriteFn}; +pub use services::{ClipboardFn, DownloadFn, Inbox, OpenAsyncFn, ReadFn, Services, WindowFrameFn, WriteFn}; pub(crate) use state::second_window_viewport; pub use state::{CanvasCache, HiddenPanels, ImportRequest, ImportedFile, PdfExportSettings, Perf, SavedWorkspace, ScreenMode, Shown, UiState, View}; @@ -314,6 +314,9 @@ pub fn cjk_features(app: &DesignApp) -> bool { #[cfg(test)] mod tests; +#[cfg(test)] +mod window_frame_tests; + /// The whole window in a headless test harness, at a chosen window size. #[cfg(test)] pub(crate) mod test_window { diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index d1e41d549..a31c7a8f0 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -65,3 +65,37 @@ fn cmd_item(id: &str, params: Value) -> Item { #[cfg(test)] mod tests; + +#[cfg(test)] +mod swedish_tests { + use super::*; + + #[test] + fn swedish_interface_is_selectable_and_translates_every_menu_label() { + let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + run_ui(&mut app, "app.language", &json!({"lang": "sv"})).unwrap().unwrap(); + assert_eq!(app.ui.language, "sv"); + assert_eq!(checked(&app, "app.language", &json!({"lang": "sv"})), Some(true)); + assert_eq!(crate::i18n::tr("sv", "File"), "Arkiv"); + // Every menu title, item and submenu has a Swedish entry. + let mut untranslated = Vec::new(); + for (title, entries) in menu_tree() { + let mut labels = vec![title.to_string()]; + let mut stack: Vec<&Item> = entries.iter().collect(); + while let Some(entry) = stack.pop() { + match entry { + Item::Sub(label, children) => { + labels.push(label.clone()); + stack.extend(children.iter()); + } + Item::Cmd { label, id, .. } if id != "app.language" => labels.push(label.clone()), + _ => {} + } + } + // Swedish shares many words with English ("Layout", "Cyan"), so look for a catalog entry. + let size = |l: &str| l.strip_suffix(" pt").is_some_and(|n| !n.is_empty() && n.chars().all(|c| c.is_ascii_digit())); + untranslated.extend(labels.into_iter().filter(|l| l.chars().any(char::is_alphabetic) && !size(l) && !crate::i18n::swedish_has(l))); + } + assert!(untranslated.is_empty(), "untranslated Swedish menu labels: {untranslated:?}"); + } +} diff --git a/crates/ui-egui/src/menus/invoke.rs b/crates/ui-egui/src/menus/invoke.rs index 16c7bc191..b9d35539d 100644 --- a/crates/ui-egui/src/menus/invoke.rs +++ b/crates/ui-egui/src/menus/invoke.rs @@ -151,9 +151,24 @@ pub fn activate_native(app: &mut DesignApp, ctx: &egui::Context, id: &str, param if params.is_null() && app.session.wants_text() && matches!(id, "edit.copy" | "edit.cut" | "edit.paste") && forward_to_text_edit(app, ctx, id) { return; } + // Zoom In/Out by key equivalent: the pointer is still in the window. A click in the menu bar + // takes it out, so that zooms around the centre. + if params.is_null() + && let Some(p) = pointer_zoom_params(ctx, id) + { + activate(app, id, &p); + return; + } activate(app, id, params); } +/// Zoom In/Out from a key: the pointer's position (`at`), so the zoom keeps the point under it +/// when it is over the canvas. `None` for other commands or with no pointer in the window. +pub(super) fn pointer_zoom_params(ctx: &egui::Context, id: &str) -> Option { + let at = ctx.pointer_hover_pos()?; + matches!(id, "view.zoomIn" | "view.zoomOut").then(|| json!({"at": [at.x, at.y]})) +} + /// The editing commands a focused text field takes from the native menu bar. pub(super) const TEXT_FIELD_COMMANDS: [&str; 6] = ["edit.selectAll", "edit.copy", "edit.cut", "edit.paste", "edit.undo", "edit.redo"]; diff --git a/crates/ui-egui/src/menus/keys.rs b/crates/ui-egui/src/menus/keys.rs index b7e1fa539..8b2179469 100644 --- a/crates/ui-egui/src/menus/keys.rs +++ b/crates/ui-egui/src/menus/keys.rs @@ -1,4 +1,4 @@ -use super::invoke::activate; +use super::invoke::{activate, pointer_zoom_params}; use super::{DesignApp, ScreenMode, Value, json}; /// The command a paste event stands for besides plain Paste. egui-winit turns every ⌘+V chord into @@ -39,7 +39,7 @@ pub fn shortcuts(app: &mut DesignApp, ctx: &egui::Context) { } let typing = app.session.wants_text(); let keys = ctx.input_mut(|i| take_keys(app, i, typing)); - run_keys(app, keys, typing); + run_keys(app, ctx, keys, typing); } /// Keys that a floating panel in its own OS window left over (craft-ui's @@ -59,7 +59,7 @@ pub fn forwarded_shortcuts(app: &mut DesignApp, ctx: &egui::Context, events: Vec input.events = events; input.modifiers = modifiers; let keys = take_keys(app, &mut input, typing); - run_keys(app, keys, typing); + run_keys(app, ctx, keys, typing); crate::canvas::forwarded_keys(app, input.events, modifiers); } @@ -112,7 +112,7 @@ fn take_keys(app: &mut DesignApp, input: &mut egui::InputState, typing: bool) -> } /// Runs what [`take_keys`] took, then Esc's return to the Selection tool. -fn run_keys(app: &mut DesignApp, keys: Keys, typing: bool) { +fn run_keys(app: &mut DesignApp, ctx: &egui::Context, keys: Keys, typing: bool) { for step in keys.presentation { match step { None => { @@ -138,7 +138,11 @@ fn run_keys(app: &mut DesignApp, keys: Keys, typing: bool) { app.select_tool(&tool); } else { // Like choosing the menu item: "…" commands open their dialog. - activate(app, &hit.command.id, &hit.command.params); + // Zoom In/Out by key zoom around the pointer while it is over the canvas. + match pointer_zoom_params(ctx, &hit.command.id) { + Some(p) => activate(app, &hit.command.id, &p), + None => activate(app, &hit.command.id, &hit.command.params), + } } } // Esc with no shortcut of its own goes back to the Selection tool. diff --git a/crates/ui-egui/src/menus/run.rs b/crates/ui-egui/src/menus/run.rs index f26532ebf..717e1332e 100644 --- a/crates/ui-egui/src/menus/run.rs +++ b/crates/ui-egui/src/menus/run.rs @@ -579,7 +579,14 @@ fn run_ui_part3(app: &mut DesignApp, id: &str, p: &Value) -> Option { if let Some(r) = rect { - crate::canvas::zoom_at(app, r.center(), if id == "view.zoomIn" { 1.5 } else { 1.0 / 1.5 }); + // A keyboard zoom names the pointer ("at"); it counts only over the canvas. + let at = p + .get("at") + .and_then(Value::as_array) + .filter(|a| a.len() == 2) + .and_then(|a| Some(egui::pos2(a.first()?.as_f64()? as f32, a.get(1)?.as_f64()? as f32))); + let at = at.filter(|at| r.contains(*at)).unwrap_or_else(|| r.center()); + crate::canvas::zoom_at(app, at, if id == "view.zoomIn" { 1.5 } else { 1.0 / 1.5 }); } Ok(Value::Null) } diff --git a/crates/ui-egui/src/menus/tests.rs b/crates/ui-egui/src/menus/tests.rs index efe978dc5..3fbd56424 100644 --- a/crates/ui-egui/src/menus/tests.rs +++ b/crates/ui-egui/src/menus/tests.rs @@ -154,6 +154,7 @@ fn define_lists_command_path_matches_the_type_menu() { assert!(menu_ids("Type").contains(&"list.define")); } +/// Checks that screen-mode menu checkmarks follow the current Normal or Preview mode. #[test] fn screen_mode_shows_the_current_mode() { let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); @@ -163,6 +164,24 @@ fn screen_mode_shows_the_current_mode() { assert_eq!((mode(&app, "normal"), mode(&app, "preview")), (Some(false), Some(true))); } +/// Checks that translated customization paths match the visible submenu captions, while +/// allowing uncatalogued paths to keep their English fallback. +#[test] +fn hungarian_menu_paths_match_the_visible_submenu_labels() { + // These paths are displayed by menu customization; they must use the same + // captions as the actual menu tree, including nested special characters. + for title in ["Edit", "Type", "View"] { + for path in submenu_paths(title) { + let translated = crate::i18n::tr("hu", &path); + if translated == path { + continue; // New, uncatalogued paths still fall back to English. + } + let visible = path.split('/').map(|part| crate::i18n::tr("hu", part)).collect::>().join("/"); + assert_eq!(translated, visible, "{path}"); + } + } +} + fn walk(items: &[Item], out: &mut Vec<(String, String, Value)>) { for it in items { match it { @@ -648,6 +667,7 @@ fn split_window_contextual_bars_have_independent_widget_ids() { assert!(!bars[0].intersects(bars[1]), "each pane keeps its own bar: {bars:?}"); } +/// Checks the document-grid menu label, shortcut, checkmark and repeated toggle behavior. #[test] fn show_document_grid_toggles_from_the_grids_and_guides_menu() { let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); @@ -666,6 +686,8 @@ fn show_document_grid_toggles_from_the_grids_and_guides_menu() { assert!(!app.ui.document_grid); } +/// Checks language selection and rejection of unknown language codes, Preferences dispatch, +/// translated menu labels and preservation of document data when switching to Arabic. #[test] fn interface_language_switches_and_validates() { let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); @@ -683,6 +705,113 @@ fn interface_language_switches_and_validates() { run_ui(&mut app, "app.language", &json!({})).unwrap().unwrap(); assert_eq!(app.ui.dialog.as_ref().map(|d| d.id.as_str()), Some("preferences")); assert_eq!(app.ui.language, "de"); + app.ui.dialog = None; + + run_ui(&mut app, "app.language", &json!({"lang": "zh"})).unwrap().unwrap(); + assert_eq!(app.ui.language, "zh"); + assert_eq!(crate::i18n::tr(&app.ui.language, "File"), "文件"); + + app.run("file.new", json!({"pages": 4, "facingPages": true})).unwrap(); + let before = serde_json::to_value(&app.session.doc().unwrap().doc).unwrap(); + run_ui(&mut app, "app.language", &json!({"lang": "ar"})).unwrap().unwrap(); + assert_eq!(app.ui.language, "ar"); + assert_eq!(checked(&app, "app.language", &json!({"lang": "ar"})), Some(true)); + assert_eq!(before, serde_json::to_value(&app.session.doc().unwrap().doc).unwrap()); + for (title, _) in menu_tree() { + assert_ne!(crate::i18n::tr("ar", title), title, "{title}"); + } + // Every menu title has a translation (Japanese never matches the English). + for (title, _) in menu_tree() { + assert_ne!(crate::i18n::tr("ja", title), title, "{title}"); + } + + run_ui(&mut app, "app.language", &json!({"lang": "pt-br"})).unwrap().unwrap(); + assert_eq!(app.ui.language, "pt-br"); + assert_eq!(checked(&app, "app.language", &json!({"lang": "pt-br"})), Some(true)); + for (title, _) in menu_tree() { + // "Layout" is the natural Brazilian Portuguese word, so it stays identical + // to English; every other title must be translated. + if title != "Layout" { + assert_ne!(crate::i18n::tr("pt-br", title), title, "{title}"); + } + } + + run_ui(&mut app, "app.language", &json!({"lang": "it"})).unwrap().unwrap(); + assert_eq!(app.ui.language, "it"); + assert_eq!(checked(&app, "app.language", &json!({"lang": "it"})), Some(true)); + for (title, _) in menu_tree() { + // "File" and "Layout" are the usual Italian menu names, so they stay identical + // to English; every other title must be translated. + if title != "File" && title != "Layout" { + assert_ne!(crate::i18n::tr("it", title), title, "{title}"); + } + } +} + +/// Checks Hungarian selection, menu captions and saved UI preferences without changing +/// document data or translating user-defined names. +#[test] +fn hungarian_language_is_selectable_persisted_and_keeps_document_data() { + let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", json!({"pages": 4, "facingPages": true})).unwrap(); + app.run("frame.create", json!({"rect": [36, 36, 200, 200], "content": "text", "text": "My words · Árvíztűrő tükörfúrógép"})).unwrap(); + let before = serde_json::to_value(&app.session.doc().unwrap().doc).unwrap(); + run_ui(&mut app, "app.language", &json!({"lang": "hu"})).unwrap().unwrap(); + assert_eq!(checked(&app, "app.language", &json!({"lang": "hu"})), Some(true)); + assert_eq!(before, serde_json::to_value(&app.session.doc().unwrap().doc).unwrap()); + for (title, _) in menu_tree() { + assert_ne!(crate::i18n::tr("hu", title), title, "{title}"); + } + let bytes = serde_json::to_vec(&app.ui).unwrap(); + let restored: crate::UiState = serde_json::from_slice(&bytes).unwrap(); + assert_eq!(restored.language, "hu"); + assert_eq!(crate::i18n::tr(&restored.language, "File"), "Fájl"); + assert_eq!(crate::i18n::tr(&restored.language, "A custom name"), "A custom name"); + assert!(crate::i18n::LANGUAGES.contains(&("hu", "Magyar")), "Preferences lists Hungarian by its own name"); +} + +/// Checks Ukrainian selection, menu captions and saved UI preferences without changing +/// document data or translating user-defined names. +#[test] +fn ukrainian_language_is_selectable_persisted_and_keeps_document_data() { + let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", json!({"pages": 4, "facingPages": true})).unwrap(); + app.run("frame.create", json!({"rect": [36, 36, 200, 200], "content": "text", "text": "My words · Мої слова"})).unwrap(); + let before = serde_json::to_value(&app.session.doc().unwrap().doc).unwrap(); + run_ui(&mut app, "app.language", &json!({"lang": "uk"})).unwrap().unwrap(); + assert_eq!(checked(&app, "app.language", &json!({"lang": "uk"})), Some(true)); + assert_eq!(before, serde_json::to_value(&app.session.doc().unwrap().doc).unwrap()); + for (title, _) in menu_tree() { + assert_ne!(crate::i18n::tr("uk", title), title, "{title}"); + } + let bytes = serde_json::to_vec(&app.ui).unwrap(); + let restored: crate::UiState = serde_json::from_slice(&bytes).unwrap(); + assert_eq!(restored.language, "uk"); + assert_eq!(crate::i18n::tr(&restored.language, "File"), "Файл"); + assert_eq!(crate::i18n::tr(&restored.language, "A custom name"), "A custom name"); + assert!(crate::i18n::LANGUAGES.contains(&("uk", "Українська")), "Preferences lists Ukrainian by its own name"); +} + +/// Checks Russian selection, menu captions and saved UI preferences without changing +/// document data or translating user-defined names. +#[test] +fn russian_language_is_selectable_persisted_and_keeps_document_data() { + let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", json!({"pages": 4, "facingPages": true})).unwrap(); + app.run("frame.create", json!({"rect": [36, 36, 200, 200], "content": "text", "text": "My words · Мои слова"})).unwrap(); + let before = serde_json::to_value(&app.session.doc().unwrap().doc).unwrap(); + run_ui(&mut app, "app.language", &json!({"lang": "ru"})).unwrap().unwrap(); + assert_eq!(checked(&app, "app.language", &json!({"lang": "ru"})), Some(true)); + assert_eq!(before, serde_json::to_value(&app.session.doc().unwrap().doc).unwrap()); + for (title, _) in menu_tree() { + assert_ne!(crate::i18n::tr("ru", title), title, "{title}"); + } + let bytes = serde_json::to_vec(&app.ui).unwrap(); + let restored: crate::UiState = serde_json::from_slice(&bytes).unwrap(); + assert_eq!(restored.language, "ru"); + assert_eq!(crate::i18n::tr(&restored.language, "File"), "Файл"); + assert_eq!(crate::i18n::tr(&restored.language, "A custom name"), "A custom name"); + assert!(crate::i18n::LANGUAGES.contains(&("ru", "Русский")), "Preferences lists Russian by its own name"); } #[test] @@ -3152,3 +3281,70 @@ fn file_menu_ends_with_quit_but_the_macos_menu_bar_leaves_it_to_the_app_menu() { let file_items = native.iter().find(|(t, _)| *t == "File").map(|(_, e)| e); assert!(!matches!(file_items.and_then(|e| e.last()), Some(Item::Sep)), "no separator left at the end of File"); } + +#[test] +fn zoom_commands_zoom_around_the_pointer_when_it_is_over_the_canvas() { + let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + app.session.execute("file.new", &json!({})).unwrap(); + let ctx = egui::Context::default(); + let frame = |app: &mut crate::DesignApp, events: Vec| { + let input = egui::RawInput { + screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1400.0, 900.0))), + events, + ..Default::default() + }; + let mut out = ctx.run_ui(input, |ui| { + app.logic(&ui.ctx().clone()); + app.ui(ui); + }); + out.textures_delta.clear(); + }; + frame(&mut app, vec![]); + frame(&mut app, vec![]); + let rect = app.canvas_rect.unwrap(); + let pointer = rect.center() + egui::vec2(200.0, 120.0); + let under = |app: &crate::DesignApp, at: egui::Pos2| crate::canvas::Xf::new(app.canvas_rect.unwrap(), app.view().unwrap()).to_canvas(at); + let before = under(&app, pointer); + let zoom = app.view().unwrap().zoom; + + // The command with a pointer position keeps the point under it fixed. + app.run("view.zoomIn", json!({"at": [pointer.x, pointer.y]})).unwrap(); + assert!(app.view().unwrap().zoom > zoom); + let after = under(&app, pointer); + assert!((after.x - before.x).abs() < 1e-3 && (after.y - before.y).abs() < 1e-3); + app.run("view.zoomOut", json!({"at": [pointer.x, pointer.y]})).unwrap(); + let after = under(&app, pointer); + assert!((after.x - before.x).abs() < 1e-3 && (after.y - before.y).abs() < 1e-3); + + // A position outside the canvas (or none: the menu) zooms around the centre. + let centre = under(&app, rect.center()); + app.run("view.zoomIn", json!({"at": [-50.0, -50.0]})).unwrap(); + let kept = under(&app, rect.center()); + assert!((kept.x - centre.x).abs() < 1e-3 && (kept.y - centre.y).abs() < 1e-3); + app.run("view.zoomIn", json!({})).unwrap(); + let kept = under(&app, rect.center()); + assert!((kept.x - centre.x).abs() < 1e-3 && (kept.y - centre.y).abs() < 1e-3); + + // The keyboard shortcut uses the pointer. + app.run("view.zoom", json!({"zoom": 1.0})).unwrap(); + let before = under(&app, pointer); + frame(&mut app, vec![egui::Event::PointerMoved(pointer)]); + let key = egui::Event::Key { key: egui::Key::Equals, physical_key: None, pressed: true, repeat: false, modifiers: egui::Modifiers::COMMAND }; + frame(&mut app, vec![key]); + assert!(app.view().unwrap().zoom > 1.0); + let after = under(&app, pointer); + assert!((after.x - before.x).abs() < 1e-3 && (after.y - before.y).abs() < 1e-3); + + // The native menu bar's key equivalent (macOS) leaves the pointer in the window and uses it. + app.run("view.zoom", json!({"zoom": 1.0})).unwrap(); + let before = under(&app, pointer); + native_frame(&mut app, &ctx, vec![egui::Event::PointerMoved(pointer)], Some("view.zoomIn")); + assert!(app.view().unwrap().zoom > 1.0); + let after = under(&app, pointer); + assert!((after.x - before.x).abs() < 1e-3 && (after.y - before.y).abs() < 1e-3); + // A click in the menu bar takes the pointer out of the window: the centre stays. + let centre = under(&app, rect.center()); + native_frame(&mut app, &ctx, vec![egui::Event::PointerGone], Some("view.zoomOut")); + let kept = under(&app, rect.center()); + assert!((kept.x - centre.x).abs() < 1e-3 && (kept.y - centre.y).abs() < 1e-3); +} diff --git a/crates/ui-egui/src/menus/ui_commands.rs b/crates/ui-egui/src/menus/ui_commands.rs index 4a75a994e..f24d1d548 100644 --- a/crates/ui-egui/src/menus/ui_commands.rs +++ b/crates/ui-egui/src/menus/ui_commands.rs @@ -71,7 +71,7 @@ pub const UI_COMMANDS: &[(&str, &str, Option<&str>, &str)] = &[ "app.language", "Interface Language", None, - "{lang?: \"\"|de|fr|es|ja|zh|ar|pt-br|it|uk|ru|cs|pl|ka} — menus and panel names (the macOS menu bar follows at once); without lang, opens Preferences, where it is the first setting", + "{lang?: \"\"|de|fr|es|ja|zh|ar|pt-br|it|uk|ru|cs|pl|ka|hu|sv} — menus and panel names (the macOS menu bar follows at once); without lang, opens Preferences, where it is the first setting", ), ( "app.flattener", @@ -178,8 +178,8 @@ pub const UI_COMMANDS: &[(&str, &str, Option<&str>, &str)] = &[ ("app.paragraphStylesPanel", "Paragraph Styles", Some("Cmd+F11"), "{} — the Paragraph Styles panel"), ("app.insertCurrentPageNumber", "Current Page Number", Some("Cmd+Alt+Shift+N"), "{} — the Current Page Number marker at the insertion point"), ("app.storyEditor", "Edit in Story Editor", Some("Cmd+Y"), "{story?}"), - ("view.zoomIn", "Zoom In", Some("Cmd+="), "{}"), - ("view.zoomOut", "Zoom Out", Some("Cmd+-"), "{}"), + ("view.zoomIn", "Zoom In", Some("Cmd+="), "{at?: [x, y] window pixels, kept in place when over the canvas}"), + ("view.zoomOut", "Zoom Out", Some("Cmd+-"), "{at?: [x, y] window pixels, kept in place when over the canvas}"), ("view.fitPage", "Fit Page in Window", Some("Cmd+0"), "{}"), ("view.fitSelection", "Fit Selection in Window", Some("Cmd+Alt+="), "{}"), ("view.fitSpread", "Fit Spread in Window", Some("Cmd+Alt+0"), "{}"), diff --git a/crates/ui-egui/src/services.rs b/crates/ui-egui/src/services.rs index b413e90c4..47459cddb 100644 --- a/crates/ui-egui/src/services.rs +++ b/crates/ui-egui/src/services.rs @@ -11,6 +11,9 @@ pub type DownloadFn = Box Result<(), String>>; pub type ClipboardFn = Box Option>; +/// Keeps the window's frame as the app needs it; called once per frame, before it is laid out. +pub type WindowFrameFn = Box; + /// Files delivered asynchronously with their original operation and document identity. pub type Inbox = std::sync::Arc>>; @@ -32,4 +35,8 @@ pub struct Services { /// The system clipboard's text, for Paste chosen from a menu (egui only delivers it with the /// paste keys, which a native menu bar takes first). pub clipboard_text: Option, + /// Keeps the undecorated window borderless, so the content and the pointer stay aligned + /// (Windows custom title bar, #1295). `None` when the window is decorated or the platform + /// needs no fixing. + pub window_frame: Option, } diff --git a/crates/ui-egui/src/toolbar.rs b/crates/ui-egui/src/toolbar.rs index ec5b6f67b..d909d6a04 100644 --- a/crates/ui-egui/src/toolbar.rs +++ b/crates/ui-egui/src/toolbar.rs @@ -10,6 +10,8 @@ use crate::{DesignApp, icons}; const BTN: f32 = 24.0; +/// Draws the adaptive Tools panel with localized tool flyouts, fill/stroke controls and +/// screen-mode buttons; flyout rows accommodate translated labels and their shortcuts. pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) { let t = Tokens::get(ui.ctx()); let frame = egui::Frame::NONE.fill(t.panel).stroke(Stroke::new(1.0, t.divider)); @@ -173,43 +175,77 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) { ui.ctx(), |ui| { egui::Frame::popup(ui.style()).show(ui, |ui| { - for tl in g { - ui.horizontal(|ui| { - let (r, row) = ui.allocate_exact_size(vec2(210.0, 24.0), Sense::click()); - if row.hovered() { - ui.painter().rect_filled(r, 2.0, t.hover); - } - icons::paint( - ui.painter(), - egui::Rect::from_min_size(r.min + vec2(4.0, 3.0), vec2(18.0, 18.0)), - tl.icon, - t.icon, - ); - if tl.id == current { - ui.painter().circle_filled(r.min + vec2(-2.0, 12.0), 2.0, t.accent); - } - ui.painter().text( - r.min + vec2(28.0, 12.0), - egui::Align2::LEFT_CENTER, - crate::i18n::tr(&app.ui.language, tl.label), - egui::FontId::proportional(12.5), - t.text, - ); - if let Some(sc) = crate::menus::tool_shortcut_label(app, tl.id) { - ui.painter().text( - r.right_center() - vec2(6.0, 0.0), - egui::Align2::RIGHT_CENTER, - sc, - egui::FontId::proportional(11.5), - t.text_dim, - ); - } - row.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Button, true, tl.label)); - if row.clicked() { - chosen = Some(tl.id); - } - }); + let row_width = g.iter().fold(210.0_f32, |width, tl| { + let label = crate::i18n::tr(&app.ui.language, tl.label); + let label_width = ui + .painter() + .layout_no_wrap(label.to_owned(), egui::FontId::proportional(12.5), t.text) + .size() + .x; + let shortcut_width = ui + .painter() + .layout_no_wrap( + crate::menus::tool_shortcut_label(app, tl.id).unwrap_or_default(), + egui::FontId::proportional(11.5), + t.text_dim, + ) + .size() + .x; + width.max(label_width + shortcut_width + 46.0) + }); + let max_width = (ui.ctx().content_rect().width() + - egui::Frame::popup(ui.style()).total_margin().sum().x) + .max(0.0); + let mut scroll = + egui::ScrollArea::horizontal().id_salt(("tool-flyout-scroll", gi)).max_width(max_width); + if opened_now { + scroll = scroll.horizontal_scroll_offset(0.0); } + scroll.show(ui, |ui| { + for tl in g { + ui.horizontal(|ui| { + let (r, row) = ui.allocate_exact_size(vec2(row_width, 24.0), Sense::click()); + if row.hovered() { + ui.painter().rect_filled(r, 2.0, t.hover); + } + icons::paint( + ui.painter(), + egui::Rect::from_min_size(r.min + vec2(4.0, 3.0), vec2(18.0, 18.0)), + tl.icon, + t.icon, + ); + if tl.id == current { + ui.painter().circle_filled(r.min + vec2(-2.0, 12.0), 2.0, t.accent); + } + ui.painter().text( + r.min + vec2(28.0, 12.0), + egui::Align2::LEFT_CENTER, + crate::i18n::tr(&app.ui.language, tl.label), + egui::FontId::proportional(12.5), + t.text, + ); + if let Some(sc) = crate::menus::tool_shortcut_label(app, tl.id) { + ui.painter().text( + r.right_center() - vec2(6.0, 0.0), + egui::Align2::RIGHT_CENTER, + sc, + egui::FontId::proportional(11.5), + t.text_dim, + ); + } + row.widget_info(|| { + egui::WidgetInfo::labeled( + egui::Role::Button, + true, + crate::i18n::tr(&app.ui.language, tl.label), + ) + }); + if row.clicked() { + chosen = Some(tl.id); + } + }); + } + }); }); }, ); diff --git a/crates/ui-egui/src/toolbar/tests.rs b/crates/ui-egui/src/toolbar/tests.rs index 7a0948817..df06bd020 100644 --- a/crates/ui-egui/src/toolbar/tests.rs +++ b/crates/ui-egui/src/toolbar/tests.rs @@ -19,10 +19,203 @@ fn column_width(cols: f32) -> f32 { 8.0 + super::BTN * cols + 4.0 * (cols - 1.0) + 8.0 } +/// Returns the bounds of the labeled test widget, failing if the label cannot be found. fn rect(h: &egui_kittest::Harness<'static, test_window::Window>, label: &str) -> egui::Rect { h.get_by_label(label).rect() } +/// Collects painted text bounds and their clip rectangles, including nested shapes. +fn collect_text(shape: &egui::Shape, clip: egui::Rect, texts: &mut Vec<(String, egui::Rect, egui::Rect)>) { + match shape { + egui::Shape::Text(text) => texts.push((text.galley.text().to_owned(), text.visual_bounding_rect(), clip)), + egui::Shape::Vec(shapes) => shapes.iter().for_each(|shape| collect_text(shape, clip, texts)), + _ => {} + } +} + +/// Checks translated tooltips and right-click flyout rows in both Tools-panel layouts, +/// including painted labels, unchanged shortcuts and unclipped, nonoverlapping text. +#[test] +fn hungarian_tool_buttons_translate_every_tool_and_keep_shortcuts() { + use egui::{Event, Modifiers, PointerButton}; + + for double in [false, true] { + let mut app = app(double); + app.ui.language = "hu".into(); + let mut h = test_window::open(app, vec2(1400.0, 1000.0)); + for tool in designcraft_tools::TOOL_GROUPS.iter().flat_map(|group| group.iter()) { + h.state_mut().app.run("tool.select", serde_json::json!({"tool": tool.id})).unwrap(); + h.run_steps(3); + let label = crate::i18n::tr("hu", tool.label); + assert_ne!(label, tool.label, "untranslated tool: {}", tool.id); + let shortcut = tool.shortcut.map(crate::menus::shortcut_text); + assert_eq!(crate::menus::tool_shortcut_label(&h.state().app, tool.id), shortcut, "default binding for {}", tool.id); + let tip = shortcut.map_or_else(|| label.to_owned(), |shortcut| format!("{label} ({shortcut})")); + assert!(rect(&h, &tip).is_finite(), "{tip}"); + } + // A user-assigned chord also has to fit beside a translated flyout label. + let custom_shortcut = "Ctrl+Alt+Shift+F12"; + h.state_mut() + .app + .run( + "window.setShortcut", + serde_json::json!({"id": "tool.select", "params": {"tool": "ellipseFrame"}, "shortcut": custom_shortcut, "steal": true}), + ) + .unwrap(); + for (gi, group) in designcraft_tools::TOOL_GROUPS.iter().enumerate() { + // Single tools have no flyout; the collector group is split into separate + // buttons in two-column mode and is covered by the tooltip checks above. + if group.len() < 2 || (double && designcraft_tools::SPLIT_IN_TWO_COLUMNS.contains(&group[0].id)) { + continue; + } + let first = group[0]; + h.state_mut().app.run("tool.select", serde_json::json!({"tool": first.id})).unwrap(); + h.run_steps(3); + let label = crate::i18n::tr("hu", first.label); + let tip = first.shortcut.map(crate::menus::shortcut_text).map_or_else(|| label.to_owned(), |shortcut| format!("{label} ({shortcut})")); + let at = rect(&h, &tip).center(); + h.input_mut().events.push(Event::PointerMoved(at)); + for pressed in [true, false] { + h.input_mut().events.push(Event::PointerButton { pos: at, button: PointerButton::Secondary, pressed, modifiers: Modifiers::NONE }); + } + h.run_steps(3); + assert_eq!(h.state().app.ui.flyout, Some(gi), "right-click opens {} (double={double})", first.id); + let mut texts = Vec::new(); + for shape in &h.output().shapes { + collect_text(&shape.shape, shape.clip_rect, &mut texts); + } + for tool in *group { + let label = crate::i18n::tr("hu", tool.label); + // Flyout accessibility labels omit the shortcut; inspect the painted + // text inside this row so another button cannot satisfy the assertion. + let row = rect(&h, label); + assert!(row.is_finite() && row.is_positive(), "{label}"); + let painted = |expected: &str| { + let (_, bounds, clip) = texts + .iter() + .find(|(text, bounds, _)| text == expected && row.contains(bounds.center())) + .unwrap_or_else(|| panic!("missing flyout text {expected:?} for {} (double={double})", tool.id)); + assert!(row.contains_rect(*bounds) && clip.contains_rect(*bounds), "clipped flyout text {expected:?}: {bounds:?}"); + *bounds + }; + let label_bounds = painted(label); + let binding = if tool.id == "ellipseFrame" { Some(custom_shortcut) } else { tool.shortcut }; + if let Some(shortcut) = binding.map(crate::menus::shortcut_text) { + let shortcut_bounds = painted(&shortcut); + assert!(label_bounds.right() < shortcut_bounds.left(), "label overlaps shortcut for {} (double={double})", tool.id); + } + } + h.key_press(egui::Key::Escape); + h.run_steps(2); + assert!(h.state().app.ui.flyout.is_none()); + } + assert_eq!(crate::i18n::tr("hu", "Direct Selection Tool"), "Közvetlen kijelölő eszköz"); + } +} + +/// Keeps long translated flyout rows reachable by scrolling in a narrow viewport, +/// resetting on reopening while preserving the open scroll position, shortcut and selection. +#[test] +fn hungarian_flyout_scrolls_horizontally_in_narrow_windows() { + use egui::{Event, Modifiers, PointerButton}; + + for double in [false, true] { + for width in [180.0, 240.0] { + let mut app = app(double); + app.ui.language = "hu".into(); + let chord = "Ctrl+Alt+Shift+F12"; + app.run( + "window.setShortcut", + serde_json::json!({"id": "tool.select", "params": {"tool": "ellipseFrame"}, "shortcut": chord, "steal": true}), + ) + .unwrap(); + app.select_tool("rectangleFrame"); + let mut h = test_window::open(app, vec2(width, 1000.0)); + let at = rect(&h, "Téglalapkeret eszköz (F)").center(); + h.input_mut().events.push(Event::PointerMoved(at)); + for pressed in [true, false] { + h.input_mut().events.push(Event::PointerButton { pos: at, button: PointerButton::Secondary, pressed, modifiers: Modifiers::NONE }); + } + h.run_steps(3); + let gi = h.state().app.ui.flyout.unwrap(); + let area = h.ctx.memory(|m| m.area_rect(egui::Id::unique(("flyout", gi)))).unwrap(); + let viewport = h.ctx.content_rect(); + assert!(viewport.expand(0.5).contains_rect(area), "flyout {area:?} exceeds viewport {viewport:?}"); + let label = "Ellipsziskeret eszköz"; + let shortcut = crate::menus::shortcut_text(chord); + let painted = |h: &egui_kittest::Harness<'static, test_window::Window>, text: &str| { + let row = rect(h, label); + let mut texts = Vec::new(); + for shape in &h.output().shapes { + collect_text(&shape.shape, shape.clip_rect, &mut texts); + } + let (_, bounds, clip) = texts.into_iter().find(|(t, b, _)| t == text && row.contains(b.center())).unwrap(); + (bounds, clip) + }; + let (label_bounds, label_clip) = painted(&h, label); + assert!(label_clip.contains_rect(label_bounds), "label must be readable at the start"); + let (before, clip) = painted(&h, &shortcut); + let oversized = rect(&h, label).width() > clip.width(); + if width == 180.0 { + assert!(oversized, "the tighter case must exercise horizontal overflow on every platform"); + } + review_shot(&mut h, &format!("flyout-{width}-double-{double}-left.png")); + if oversized { + assert!(!clip.contains_rect(before), "the shortcut starts beyond the narrow viewport"); + wheel(&mut h, area.center(), vec2(-1000.0, 0.0)); + let (after, clip) = painted(&h, &shortcut); + assert!(clip.contains_rect(after), "scrolling must make the complete shortcut readable"); + assert!(after.left() < before.left(), "horizontal input must move the row"); + h.run_steps(3); + let (settled, clip) = painted(&h, &shortcut); + assert!(clip.contains_rect(settled), "an open flyout must retain its horizontal scroll position"); + h.key_press(egui::Key::Escape); + h.run_steps(2); + assert!(h.state().app.ui.flyout.is_none()); + // Reopen through the toolbar input path, without changing the stored scroll state. + let at = rect(&h, "Téglalapkeret eszköz (F)").center(); + h.input_mut().events.push(Event::PointerMoved(at)); + for pressed in [true, false] { + h.input_mut().events.push(Event::PointerButton { + pos: at, + button: PointerButton::Secondary, + pressed, + modifiers: Modifiers::NONE, + }); + } + h.run_steps(3); + assert_eq!(h.state().app.ui.flyout, Some(gi)); + let (reopened, clip) = painted(&h, label); + assert!(clip.contains_rect(reopened), "a reopened flyout must show the complete translated label"); + assert!((reopened.left() - label_bounds.left()).abs() < 0.5, "reopening must return to the initial left edge"); + review_shot(&mut h, &format!("flyout-{width}-double-{double}-reopened.png")); + wheel(&mut h, area.center(), vec2(-1000.0, 0.0)); + let (rescrolled, clip) = painted(&h, &shortcut); + assert!(clip.contains_rect(rescrolled), "a reopened flyout must still allow scrolling to the shortcut"); + } else { + assert!(clip.contains_rect(before)); + } + review_shot(&mut h, &format!("flyout-{width}-double-{double}-right.png")); + assert_eq!(crate::menus::tool_shortcut_label(&h.state().app, "ellipseFrame"), Some(shortcut)); + let at = rect(&h, label).intersect(area).center(); + h.input_mut().events.push(Event::PointerMoved(at)); + for pressed in [true, false] { + h.input_mut().events.push(Event::PointerButton { pos: at, button: PointerButton::Primary, pressed, modifiers: Modifiers::NONE }); + } + h.run_steps(3); + assert_eq!(h.state().app.session.tool_id(), "ellipseFrame"); + assert!(h.state().app.ui.flyout.is_none()); + } + } +} + +/// Saves synthetic UI evidence only when the local review explicitly requests it. +fn review_shot(h: &mut egui_kittest::Harness<'static, test_window::Window>, name: &str) { + if let Some(dir) = std::env::var_os("DESIGNCRAFT_HU_REVIEW_SHOTS") { + h.render().unwrap().save(std::path::Path::new(&dir).join(name)).unwrap(); + } +} + /// As InDesign's: a tool group's flyout closes on Esc and on a click outside it (the fill /// swatch, a panel), not only on the canvas. #[test] @@ -197,7 +390,8 @@ fn the_tools_panel_lays_out_like_indesigns() { for double in [false, true] { let h = test_window::open(app(double), vec2(1400.0, 900.0)); let _ = rect(&h, "Gradient Swatch Tool (G)"); - let _ = rect(&h, "Gradient Feather Tool (Shift+G)"); + let feather = format!("Gradient Feather Tool ({})", crate::menus::shortcut_text("Shift+G")); + let _ = rect(&h, &feather); let _ = rect(&h, "View Options"); let split = ["Content Placer Tool (B)", "Apply Color (,)", "Apply Gradient (.)", "Normal"]; for label in split { diff --git a/crates/ui-egui/src/window_frame_tests.rs b/crates/ui-egui/src/window_frame_tests.rs new file mode 100644 index 000000000..18be1ae5b --- /dev/null +++ b/crates/ui-egui/src/window_frame_tests.rs @@ -0,0 +1,39 @@ +//! The window-frame service keeps the custom title bar's undecorated window borderless (#1295). +//! +//! winit 0.30 gives an undecorated window a caption and border (`WS_CAPTION | WS_BORDER`), which +//! on some Windows systems offset the drawn content and the pointer. The app shell strips them +//! and re-strips them after every toolkit flag change (maximize, restore, …), driven from +//! `raw_input_hook`. These tests pin the shell side: the hook must run the service once per frame, +//! before the frame is laid out. + +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use super::*; + +#[test] +fn the_window_frame_service_runs_every_raw_input_hook() { + let calls = Arc::new(AtomicUsize::new(0)); + let n = calls.clone(); + let services = Services { + window_frame: Some(Box::new(move || { + n.fetch_add(1, Ordering::SeqCst); + })), + ..Default::default() + }; + let mut app = DesignApp::new(designcraft_engine::Session::new(), services); + let ctx = egui::Context::default(); + for _ in 0..3 { + app.raw_input_hook(&ctx, &mut egui::RawInput::default()); + } + assert_eq!(calls.load(Ordering::SeqCst), 3); +} + +#[test] +fn no_window_frame_service_is_fine() { + // Decorated windows and non-Windows platforms leave the service unset; the hook must simply + // do nothing. + let mut app = DesignApp::new(designcraft_engine::Session::new(), Services::default()); + let ctx = egui::Context::default(); + app.raw_input_hook(&ctx, &mut egui::RawInput::default()); +} diff --git a/docs/gaps.md b/docs/gaps.md index 7e78c0eda..c2ca44ad2 100644 --- a/docs/gaps.md +++ b/docs/gaps.md @@ -156,7 +156,7 @@ Kind: **F** feature · **U** UI/UX · **T** typography · **FF** file format · - **Estimate:** 25–40 h. ### 13. Hyphenation and spelling languages (T, L) -- **Missing:** hyphenation patterns for every language but English, Spanish, Portuguese, Norwegian, Greek, German (2006 reform), French and Italian; spelling for +- **Missing:** hyphenation patterns for every language but English, Spanish, Portuguese, Norwegian, Greek, German (2006 reform), French, Italian and Dutch; spelling for every language but English. InDesign ships dictionaries for ~40 languages. - **Estimate:** 30–60 h (permissively licensed patterns exist for most; spelling word lists need licence review). **Doc:** [typography-parity.md](typography-parity.md) diff --git a/docs/localization-parity.md b/docs/localization-parity.md index df015a34b..677c4291a 100644 --- a/docs/localization-parity.md +++ b/docs/localization-parity.md @@ -1,6 +1,6 @@ # Localization parity -> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-23 · **Change:** minor (missing translations are reported, never a failure; catalog counts remain the 2026-10-10 measurement) · **Target:** Adobe InDesign 2026 (21.6) +> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-11-01 · **Change:** minor (Hungarian interface catalog, bundled-font coverage and flyout regression checks; Swedish interface) · **Target:** Adobe InDesign 2026 (21.6) Per-language status of the DesignCraft interface and of document typesetting in each script. Script-specific typesetting detail: [cjk.md](cjk.md), [cjk-typography.md](cjk-typography.md), @@ -11,7 +11,7 @@ Script-specific typesetting detail: [cjk.md](cjk.md), [cjk-typography.md](cjk-ty ## How it was measured Interface strings live in `crates/ui-egui/src/i18n/table.rs` (a shared table with German, French, -Spanish, Japanese and Simplified Chinese columns) and `crates/ui-egui/src/i18n/{ar,cs,it,ja,ka,pt_br,uk}.rs`. +Spanish, Japanese and Simplified Chinese columns) and `crates/ui-egui/src/i18n/{ar,cs,de,fr,hu,it,ja,ka,pl,pt_br,ru,sv,uk}.rs`. Untranslated strings fall back to English. A script (2026-10-10) built the set of English interface strings as the union of every catalog's keys, every engine command label and every literal passed to `tr`/`t` in the UI crate: **1,724 strings**. A further ~145 capitalized literals @@ -19,9 +19,11 @@ in the UI crate appear in no catalog (some are test data or proper names), so th somewhat higher and every percentage below is a slight overestimate. Help: DesignCraft has no help content in any language (Help ▸ opens the project's pages). -A missing translation never fails a test, a build or a release. `cargo xtask i18n-report` (also -a step of `cargo xtask ci`, so the list is in every gate log) prints how many interface strings -each language lacks, then the strings. +Missing translations normally fall back to English and are reported without blocking a build. +Targeted regression tests can require specific captions, such as the Data Merge arrangement +label, in every registered interface language. `cargo xtask i18n-report` (also a step of +`cargo xtask ci`, so the list is in every gate log) prints how many interface strings each +language lacks, then the strings. InDesign 2026 ships 25 interface localizations (`.lproj` folders: cs, da, de, el, en, en_GB, es, fi, fr, hu, it, ja, ko, nb, nl, pl, pt, ro, ru, sq, sv, tr, uk, zh_CN, zh_TW); Arabic and Hebrew @@ -52,23 +54,46 @@ caption, table row/column movement and row-height distribution now use the exist catalog. Print, import options and an active table were rendered in Japanese and English with craft-fonts. The language totals above retain their dated measurement; this is a targeted fix. +Hungarian interface (2026-11-01): `hu.rs` contains **1,906 entries and four context-specific +captions**, including all 37 tool names. The initial catalog was prepared with AI assistance +and personally reviewed in the app by **Veress Róbert**, a native Hungarian speaker with over +30 years of DTP experience. Further terminology and in-context feedback is welcome. This is a +partial catalog, not a new coverage measurement against current main: uncatalogued strings +fall back to English. Preferences lists `Magyar`; interface selection does not enable the +separate spelling and hyphenation work in #1484. + +The interface uses bundled **Source Sans 3 Regular** and **Source Sans 3 Semibold**; monospace +labels use **JetBrains Mono Regular** (`assets/fonts/`, registered by `theme::font_definitions`). +`hungarian_catalog_glyphs_exist_in_the_bundled_ui_fonts` checks the actual configured font +bytes, every Latin letter used by the catalog and all Hungarian accented vowels in both cases, +including **ŐőŰű**, with system and optional craft-fonts fallbacks disabled. No new font asset +or font dependency is needed. + +Hungarian regressions cover placeholder/context integrity, formal address and count/column +terminology, language persistence, matching menu paths, translated tool labels and real +right-click flyouts in both Tools-panel layouts. Narrow-window coverage exercises horizontal +scrolling, complete label/shortcut accessibility and selecting a scrolled row at 180 and +240 points; the existing wide-window checks keep their assertions. + ## Other shipped languages | Language | Code | UI strings translated | Status | |---|---|---|---| +| Hungarian | hu | 1,906 entries + 4 context captions (2026-11-01); initial catalog native-reviewed | partial | | Czech | cs | 1,722 (99%), plural categories handled | partial | | Italian | it | 1,464 (85%) | partial | | Ukrainian | uk | 1,432 (83%), plural categories handled | partial | | Polish | pl | 1,717 (99%), count captions category-first; AI-drafted, awaiting native review | partial | | Georgian | ka | 1,724 (~100%: every catalog key plus the command labels the others lack), count captions as `noun: n` | partial (reviewed by a native speaker) | +| Swedish | sv | 2,857 of 2,891 (99%, 2026-11-01 missing-translations report): menus, panels, dialogs and messages; singular for a count of one; AI-drafted with Claude Code from the English source, spot-checked by a native speaker (not every string) | partial | -DesignCraft ships **5** interface languages beyond the twelve; InDesign ships 17 beyond its +DesignCraft ships **6** interface languages beyond the twelve; InDesign ships 17 beyond its eight of the twelve (cs, da, el, en_GB, fi, hu, it, nb, nl, pl, ro, ru, sq, sv, tr, uk, zh_TW). ## Document languages InDesign 2026 hyphenates and spell-checks ~40 languages (Hunspell and Duden dictionaries). -DesignCraft hyphenates **English, French, German (2006 reform), Greek, Italian, Norwegian, Portuguese and Spanish** and spell-checks **English** only. Text language +DesignCraft hyphenates **English, Dutch, French, German (2006 reform), Greek, Italian, Norwegian, Portuguese and Spanish** and spell-checks **English** only. Text language can be set per paragraph and character (Properties, Character panel) and drives quotes and locale shaping. See [typography-parity.md](typography-parity.md). German hyphenation accepts `German: 2006 Reform`, `German: Swiss 2006 Reform` and `de` locale @@ -92,7 +117,9 @@ German variants have no automatic hyphenation; their German shaping and quotes a | Date | Change | Summary | |---|---|---| +| 2026-11-01 | minor | Initial Hungarian interface: 1,906 entries, four context captions, native review, bundled-font glyph coverage and wide/narrow flyout regressions | | 2026-10-11 | minor | Localized Japanese print, import and table controls; checked Japanese and English renders | +| 2026-10-15 | minor | Swedish (`sv`) interface added | | 2026-10-14 | minor | Georgian (`ka`) interface added | | 2026-10-10 | major | Created: catalogs measured (1,724 strings), the twelve key languages plus Italian and Ukrainian | | 2026-10-11 | minor | Czech (cs) added: 1,722 strings, plural categories handled | diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 9c3bff483..4f2dc5ec2 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -59,7 +59,7 @@ they receive, setting type exactly, and basic editing that never fails. | Dimension | Weight | Ready | Remaining (Opus 5.5 h) | Evidence | Doc | |---|---|---|---|---|---| | Features (depth of each area) | 25% | 55% | 250–400 | 275 catalogue rows exist; many lack options (e.g. Books is 258 lines of engine code, Liquid Layout 329); see the area table | this file | -| Typography and composition fidelity | 15% | 45% | 120–200 | Knuth–Plass composer, keeps, grids, CJK, Arabic all exist; no comparison with InDesign's line breaks; optical kerning falls back to metrics (#181); overset rule differs (#180); hyphenation patterns for English, Spanish, Portuguese, Norwegian, Greek and German 2006 only | [typography-parity.md](typography-parity.md) | +| Typography and composition fidelity | 15% | 45% | 120–200 | Knuth–Plass composer, keeps, grids, CJK, Arabic all exist; no comparison with InDesign's line breaks; optical kerning falls back to metrics (#181); overset rule differs (#180); hyphenation patterns for English, Spanish, Portuguese, Norwegian, Greek, German 2006, French, Italian and Dutch only | [typography-parity.md](typography-parity.md) | | File formats | 20% | 40% | 150–250 (+10–30 for an INDD corpus) | INDD and INDT open through indd-utils, measured on synthetic bytes only (#21); IDML both ways and verified in InDesign 2026, but real-file bugs open (#193, #338, #339, #340); PDF export strong; PDF/X-4 only | [file-format-parity.md](file-format-parity.md) | | UI/UX fidelity | 15% | 45% | 120–180 | Measured InDesign 2026 look; but users report object copy/paste (#351, #348, #185, #164), right-click menus (#238, #187, #160), out-port threading (#352, #194, #165) failing | [ui-parity.md](ui-parity.md) | | Stability | 10% | 45% | 60–100 | Never-crash rules and last-resort guards; startup failures on some GPUs and machines (#334, #273, #220, #192, #167, #166); no CI runs the tests on pull requests | [gaps.md](gaps.md) | @@ -293,7 +293,7 @@ It is evidence of breadth: each item exists. It is not a claim of InDesign-level - Column guides: with the Selection tool, drag an interior column guide to move its gutter (both guides together, keeping its width, stopped by the neighbouring guides and the margins), snapping to the document grid, guides and objects, or with Shift to the ruler's tick marks; Escape cancels; one undo step. Refused while Lock Column Guides is on (the default). A document page takes the result as its own columns; on a parent page it reaches the pages that follow it. Objects stay where they are (there is no persistent Layout Adjustment setting yet). `layout.moveColumnGuide`. - Links panel: every placed graphic with status (OK / Modified / Missing / Embedded, checked against the file on disk), page and effective PPI (low resolution flagged); Relink…, Go To, Update, Embed; `links.*` commands. - Linked text files: `file.place {link: true}` or Preferences › File Handling › Create Links When Placing Text Files keeps a placed .docx/.rtf/.txt story linked to its file (path, size and hash, and the style map and conflict option used). The Links panel shows it OK / Modified / Missing; Update imports the file again into the same frames and thread with the saved style map, replacing edits made in the layout (the Links panel and menu ask first; the `links.update` command updates and returns a warning; undoable); Relink, Go To and Unlink. Saved in the native format; IDML exports the text unlinked. -- Missing fonts: highlighted pink on screen (never in output), listed by Preflight; Type › Find/Replace Font (fonts in the document, missing first; replace in text, cells, footnotes and styles); `font.list` / `font.replace`. Type › Reload Fonts (`font.reload`) scans the font folders again and reads again the installed font files edited or removed since they were read, then recomposes the open documents: a font installed or edited while DesignCraft runs needs no restart (#328, #547). InDesign notices such changes by itself. +- Missing fonts: highlighted pink on screen (never in output), listed by Preflight; Type › Find/Replace Font (fonts in the document, missing first; replace in text, cells, footnotes and styles); `font.list` (with each face's OS/2 `fsType` embedding bits) / `font.replace`. Type › Reload Fonts (`font.reload`) scans the font folders again and reads again the installed font files edited or removed since they were read, then recomposes the open documents: a font installed or edited while DesignCraft runs needs no restart (#328, #547). InDesign notices such changes by itself. - Missing glyphs, as in InDesign: a character the applied font lacks is drawn as that font's missing-glyph box (its .notdef; a drawn box when the font's is empty), on screen and in PDF (as a path, so PDF/A and PDF/UA exports take it), and Preflight lists the characters by font. Preferences › Composition › Draw Missing Glyphs from Fallback Fonts (`document.preferences {glyphFallback}`, stored with the document) draws them from other fonts instead; it is off in new documents and IDML imports, on in documents saved before it existed. A missing font's substitute always uses fallback fonts. - Damage-region repaint: after an edit the canvas re-renders only the frames whose composed text (or the items that) changed and patches its texture — pixel-identical to a full render; typing in a frame repaints in under a millisecond instead of a full-viewport render (22 ms measured on the sample). - Native engine saves, Save a Copy, snippets, books, libraries, swatches and engine/MCP exports use same-folder atomic replacement through craft-libs/craft-atomic, as do desktop Services writes and CLI raster exports. Failed writes before replacement retain the original, and already-open readers retain the old bytes. On Unix a new file gets the permissions ordinary file creation gives it (the umask applies) and a replaced file keeps its permissions. Parent-folder flushing is best effort, so this is not a power-loss durability guarantee. @@ -362,7 +362,7 @@ It is evidence of breadth: each item exists. It is not a claim of InDesign-level - Linked stories (Edit ▸ Place and Link, `story.placeAndLink/links/updateLink/unlink`): child stories copy a parent, show out of date in the Links panel and update. - Edit ▸ Menus (`window.hideMenuItem`): hide menu items; menus with hidden items end in Show All Menu Items. - View ▸ Separations Preview (`view.separations`, Window ▸ Output ▸ Separations Preview, `ink.separations`): the plates the print PDF puts on film, spot plates included. Each visible spread is exported as Export PDF writes it and separated with craft-prepress, so the Ink Manager's aliases and spots to process, overprint and the flattener show as printed. All inks as printed, one plate as film, or an ink limit in red over gray; the panel lists the plates with each ink's percentage under the pointer. -- Language (Character panel ▸ Language, Properties ▸ Character, `type.char {language}`): text in other languages isn't hyphenated or spell-checked with the English dictionaries, typographer's quotes follow the language (German „…“, French and Russian «…», Swiss, Spanish, Dutch, Nordic, Japanese and Traditional Chinese 「…」, Simplified Chinese “…”), the font's localized forms (OpenType `locl`: Turkish i, Bulgarian Cyrillic, Japanese / Chinese / Korean glyph variants) follow it too, and so does the fallback for CJK characters the font lacks (with Draw Missing Glyphs from Fallback Fonts on): Japanese, Simplified Chinese, Traditional Chinese and Korean each try their own installed system fonts (Japanese starts with the craft-fonts Japanese faces, Mincho first, when built with them; Hangul, kana and Bopomofo pick their language's fonts whatever the language). Language names from IDML keep their spelling; locale codes as InDesign writes them for some languages (`de_DE_2006`, `nl_NL_2005`; any `ll`, `ll_CC`, `ll-CC`) are their language and region for all of the above, and Chinese is also recognised in its common spellings ("Simplified Chinese", "Chinese (Traditional)", `zh_CN`, `zh-Hant`). Spanish is hyphenated with Javier Bezos's Liang patterns (`hyph-es.tex` 5.0, MIT), Portuguese with hyph-utf8's `hyph-pt.tex` 1.4 (BSD-3-Clause) and Norwegian with hyph-utf8's `hyph-no.tex` (permissive), all through the `hypher` crate; Greek uses `hyph-el-monoton.tex` (MIT). German uses hyph-utf8's `hyph-de-1996.tex` 2024-02-28 (MIT), which contains the reformed 2006 patterns despite its filename. Only the explicit 2006 reform names and plain or 2006 German locale codes use this set; `German: Traditional`, `de_DE_1901` and unknown German variants have no automatic hyphenation. No separate old-spelling or Swiss set is bundled. Hyphenation for other languages isn't bundled yet. +- Language (Character panel ▸ Language, Properties ▸ Character, `type.char {language}`): text in other languages isn't hyphenated or spell-checked with the English dictionaries, typographer's quotes follow the language (German „…“, French and Russian «…», Swiss, Spanish, Dutch, Nordic, Japanese and Traditional Chinese 「…」, Simplified Chinese “…”), the font's localized forms (OpenType `locl`: Turkish i, Bulgarian Cyrillic, Japanese / Chinese / Korean glyph variants) follow it too, and so does the fallback for CJK characters the font lacks (with Draw Missing Glyphs from Fallback Fonts on): Japanese, Simplified Chinese, Traditional Chinese and Korean each try their own installed system fonts (Japanese starts with the craft-fonts Japanese faces, Mincho first, when built with them; Hangul, kana and Bopomofo pick their language's fonts whatever the language). Language names from IDML keep their spelling; locale codes as InDesign writes them for some languages (`de_DE_2006`, `nl_NL_2005`; any `ll`, `ll_CC`, `ll-CC`) are their language and region for all of the above, and Chinese is also recognised in its common spellings ("Simplified Chinese", "Chinese (Traditional)", `zh_CN`, `zh-Hant`). Spanish is hyphenated with Javier Bezos's Liang patterns (`hyph-es.tex` 5.0, MIT), Portuguese with hyph-utf8's `hyph-pt.tex` 1.4 (BSD-3-Clause) and Norwegian with hyph-utf8's `hyph-no.tex` (permissive) and Dutch with Piet Tutelaers's `hyph-nl.tex` 1.1 (MIT), all through the `hypher` crate; Greek uses `hyph-el-monoton.tex` (MIT). German uses hyph-utf8's `hyph-de-1996.tex` 2024-02-28 (MIT), which contains the reformed 2006 patterns despite its filename. Only the explicit 2006 reform names and plain or 2006 German locale codes use this set; `German: Traditional`, `de_DE_1901` and unknown German variants have no automatic hyphenation. No separate old-spelling or Swiss set is bundled. Hyphenation for other languages isn't bundled yet. - Books (`book.new/open/add/remove/list/styleSource/paginate/syncStyles/exportPdf`, Book panel): `.dcbook` files, continuous page numbering, chapter numbers resolved in book order (Automatic, Start Chapter Numbering at, Same as Previous Document; `layout.chapterNumbering`, with a style for Chapter Number variables and cross-references), style sync from a style source, one merged PDF. Section prefixes follow InDesign's rule (up to 8 characters, no + or comma). - Numbering & Section Options window as in InDesign (Start Section, automatic or explicit page numbering up to 99999, prefix, style, marker, Include Prefix; the document's chapter numbering and its book); OK applies both in one undo step (`layout.numberingOptions`). - Book numbering/style updates validate and serialize all targets before changing the first chapter. They write only closed native chapters, checking canonical paths for open aliases; IDML remains a read-only style source and PDF input. Snapshots are staged on disk with at most 4,096 chapter records in memory. Each replacement is atomic; a later write failure explicitly lists completed chapters rather than claiming whole-book rollback. Import/serialization memory limits and advanced book TOC/index work remain separate. diff --git a/docs/typography-parity.md b/docs/typography-parity.md index 9382443aa..3e06b2007 100644 --- a/docs/typography-parity.md +++ b/docs/typography-parity.md @@ -36,7 +36,7 @@ Fidelity: **unmeasured** unless stated. | Single-line Composer | greedy | greedy with the same ranges | ✓ | | | World-Ready composers | Paragraph / Single-line World-Ready | RTL, Arabic and bidi in the main composer | ~ | Indic scripts (Devanagari etc.) shape through harfrust but are untested | | Justification | word/letter spacing, glyph scaling min/desired/max, single-word, last line | all of these | ✓ | a justified line with a tab justifies after the tab (#284); set per paragraph in Type › Justification… and the Paragraph panel menu (#531) | -| Hyphenation | per-language dictionaries (~40), zone, limits, capitalized, last word, across columns | Liang patterns: English (trained from the public-domain Moby list), Spanish (Bezos), Portuguese (hyph-pt), Norwegian (hyph-no), Greek (hyph-el-monoton), German 2006 (hyph-de-1996), French (hyph-fr) and Italian (hyph-it); zone, limits, exceptions in the user dictionary; Hyphenate Across Column off keeps automatic hyphens off the last line of a column or frame; discretionary U+00AD breaks with both composers regardless of automatic hyphenation and replaces pattern points within its word (#1955) | ~ | other languages don't hyphenate (#87 reported "doesn't work") | +| Hyphenation | per-language dictionaries (~40), zone, limits, capitalized, last word, across columns | Liang patterns: English (trained from the public-domain Moby list), Spanish (Bezos), Portuguese (hyph-pt), Norwegian (hyph-no), Greek (hyph-el-monoton), German 2006 (hyph-de-1996), French (hyph-fr), Italian (hyph-it) and Dutch (Tutelaers); zone, limits, exceptions in the user dictionary; Hyphenate Across Column off keeps automatic hyphens off the last line of a column or frame; discretionary U+00AD breaks with both composers regardless of automatic hyphenation and replaces pattern points within its word (#1955) | ~ | other languages don't hyphenate (#87 reported "doesn't work") | | Spelling | per-language dictionaries | English (Moby) + document/user dictionary | ~ | | | Kerning | Metrics, Optical, manual, none | Metrics, Optical (outline-based: pairs pulled towards the font's stem gap, `crates/compose/src/optical.rs`), manual, none | ~ | Optical is an approximation of Adobe's algorithm (#181), not a match: imported display text can still break differently | | Tracking, scale, skew, baseline shift | ✓ | ✓ | ✓ | | diff --git a/packaging/macos/Info.plist.in b/packaging/macos/Info.plist.in index 03d7cb8e4..01e03a682 100644 --- a/packaging/macos/Info.plist.in +++ b/packaging/macos/Info.plist.in @@ -16,12 +16,14 @@ de es fr + hu it ja ka pl pt-BR ru + sv uk zh-Hans