diff --git a/ROADMAP.md b/ROADMAP.md index 47a8dfc..36db7b7 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,7 +2,7 @@ **Stage: alpha** · next: beta, ~26 points and ~162–292 h away (one Opus 5.5 agent; ~33–67 h wall-clock with 5 agents) -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; headline percentages recomputed from the area table: feature breadth ~84%, core ~94%, mainstream ~50%; text lists, hanging punctuation and decoration styles; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; export and inspect behaviour suite and fixes; .fig import: editable vector networks and more layer kinds; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; styles and variables behaviour suite and fixes; prototyping behaviour suite and fixes; components behaviour suite and fixes; embedded image colour profiles; layers panel keyboard: F2 rename, Shift+F10 context menu, keyboard box selection, 10k-layer QA; per-side stroke weight variables; text behaviour suite: CJK line breaking, metrics, vertical trim; selection and transform behaviour suite and fixes; `.fig` import, best effort; Windows QA pass with eight fixes; auto layout behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~80%; ready ~49%) · **Target:** Figma Design (desktop app 126.10.7) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Japanese and Korean draft catalogs and CJK UI fonts; plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; headline percentages recomputed from the area table: feature breadth ~84%, core ~94%, mainstream ~50%; text lists, hanging punctuation and decoration styles; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; export and inspect behaviour suite and fixes; .fig import: editable vector networks and more layer kinds; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; styles and variables behaviour suite and fixes; prototyping behaviour suite and fixes; components behaviour suite and fixes; embedded image colour profiles; layers panel keyboard: F2 rename, Shift+F10 context menu, keyboard box selection, 10k-layer QA; per-side stroke weight variables; text behaviour suite: CJK line breaking, metrics, vertical trim; selection and transform behaviour suite and fixes; `.fig` import, best effort; Windows QA pass with eight fixes; auto layout behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~80%; ready ~49%) · **Target:** Figma Design (desktop app 126.10.7) FigCraft is a clean-room, open-source, pure-Rust reimplementation of the Figma design workflow, native on macOS, Windows, Linux and FreeBSD and in the browser, fully drivable by agents through @@ -15,17 +15,17 @@ start with [`docs/gaps.md`](docs/gaps.md). |---|---|---| | Menu/command breadth | **100%** (204 / 204) | measured, [`docs/parity-checklist.md`](docs/parity-checklist.md) (`cargo xtask parity`) | | Feature breadth | **~84%** (core editor ~94%) | estimated, [`docs/target-app-parity.md`](docs/target-app-parity.md) | -| Ready for real work | **~52%** | estimated, same doc (written dimension weights and scores) | +| Ready for real work | **~53%** | estimated, same doc (written dimension weights and scores) | | Essentials user | **~57%** | estimated: core features 77.8% × 0.92 launch/stability × 0.92 discoverability × 0.88 opening files people send ([method](docs/target-app-parity.md#essentials-user)) | | Mainstream practitioner | **~49%** | estimated: weekly areas 72.6% × 0.9 interaction × 0.9 stability × 0.85 file exchange with Figma users ([method](docs/target-app-parity.md#mainstream-practitioner)) | -| Remaining to beta | **~162–292 h** one agent | estimated | -| Remaining to full parity | **~276–538 h** one agent (~85–148 h wall-clock with 5 agents) | estimated | +| Remaining to beta | **~155–280 h** one agent | estimated | +| Remaining to full parity | **~268–528 h** one agent (~83–145 h wall-clock with 5 agents) | estimated | ### Readiness by audience | Audience | Ready % | Opus 5.5 agent wall-clock hours to ~95% | Work that dominates | |---|---|---|---| -| Full target (ready for real work) | ~52% | ~281–540 h | multiplayer (42–84), localization (40–65), plugins (10–30), the interaction pass (40–60), GPU canvas (30–60), AI (30–60), the `.fig` import's tail (5–10) | +| Full target (ready for real work) | ~53% | ~273–530 h | multiplayer (42–84), localization (32–55), plugins (10–30), the interaction pass (40–60), GPU canvas (30–60), AI (30–60), the `.fig` import's tail (5–10) | | Mainstream practitioner | ~49% | ~130–244 h | core editor depth incl. the `.fig` import's tail (49–98), the interaction pass (40–60), real-file corpus and platform QA (25–50), `.fig` export for handing work back (15–30) | | Essentials user | ~57% | ~60–110 h | the `.fig` import's tail so the files people send open well (5–10), core tool polish (25–45), interaction pass on the core tools (15–25), stability QA (10–20), onboarding and starter templates (5–10) | @@ -46,11 +46,11 @@ lines, a typical feature PR 1–2.5 h). Details and what needs a human: **Alpha.** Core workflows exist end to end (frames, shapes, vectors, text, auto layout, components with variants and overrides, styles, variables, prototyping, Dev Mode, SVG/PNG/JPG/PDF), but FigCraft opens `.fig` files only best effort, has only a preview of multiplayer, and nothing has been checked -against real Figma documents. Ready-for-real-work is ~52%, inside alpha's ~40–75% band, and the alpha gate passes: every daily core workflow (design screens, build a design system, prototype, hand off to developers) works end to end on FigCraft's own files, which save and reopen; review works only asynchronously and `.fig` import is unproven on real files, both beta gaps ([alpha gate](docs/roadmap.md#alpha-gate)). Beta needs +against real Figma documents. Ready-for-real-work is ~53%, inside alpha's ~40–75% band, and the alpha gate passes: every daily core workflow (design screens, build a design system, prototype, hand off to developers) works end to end on FigCraft's own files, which save and reopen; review works only asynchronously and `.fig` import is unproven on real files, both beta gaps ([alpha gate](docs/roadmap.md#alpha-gate)). Beta needs ~75% **and** reliable `.fig` import: the `.fig` import's tail (5–10 h), a real-file corpus with measured fidelity (15–30 h), the interaction pass (25–40 h of the 40–60), core depth to ~80% (40–75 h), -basic multiplayer on the landed core (30–55 h), stability and platform QA (20–40 h), a partial GPU path (15–30 h) and -Figma's last two languages, Japanese and Korean, on the landed localization layer (7–12 h). +basic multiplayer on the landed core (30–55 h), stability and platform QA (20–40 h), a partial GPU path (15–30 h); +native speakers' reviews of the six language drafts need people. ## By dimension @@ -63,7 +63,7 @@ Figma's last two languages, Japanese and Korean, on the landed localization laye | Stability | 55% | 20–40 | [gaps](docs/gaps.md) | | Performance | 60% | 30–60 | [hardware-parity](docs/hardware-parity.md) | | Hardware | 60% | 10–21 | [hardware-parity](docs/hardware-parity.md) | -| Localization | 30% (layer; English; Spanish, French, German, Brazilian Portuguese drafts) | 40–65 | [localization-parity](docs/localization-parity.md) | +| Localization | 35% (layer; English; Spanish, French, German, Brazilian Portuguese, Japanese, Korean drafts; CJK UI fonts) | 32–55 | [localization-parity](docs/localization-parity.md) | | Platforms | 75% | 10–20 | [hardware-parity](docs/hardware-parity.md) | | Ecosystem / plugins | 34% (own WASM plugins with panels, settings and widgets) | 10–30 | [gaps](docs/gaps.md) | | AI features | 0% | 30–60 | [gaps](docs/gaps.md) | @@ -106,14 +106,15 @@ Figma's last two languages, Japanese and Korean, on the landed localization laye | French | fr | 100% | draft (needs native review) | | Portuguese (Brazil) | pt-BR | 100% | draft (needs native review) | | Indonesian | id | 0% | none | -| Japanese | ja | 0% | none | +| Japanese | ja | 100% | draft (needs native review) | | German | de | 100% | draft (needs native review) | -| Korean | ko | 0% | none | +| Korean | ko | 100% | draft (needs native review) | | Vietnamese | vi | 0% | none | No other languages. Figma ships English, Japanese, Korean, French, German, Spanish and Portuguese -(Brazil); FigCraft has the localization layer, English and Spanish, French, German and Brazilian -Portuguese drafts (Preferences ▸ Language; adding a language: +(Brazil); FigCraft has the localization layer, English and Spanish, French, German, Brazilian +Portuguese, Japanese and Korean drafts (Preferences ▸ Language; CJK UI text uses an installed CJK +font, loaded only when needed; adding a language: [`docs/translating.md`](docs/translating.md)). Document text in any script (bidi, Arabic shaping, IME) already works. Detail: [`docs/localization-parity.md`](docs/localization-parity.md). @@ -124,7 +125,7 @@ Ranked; detail and milestones in [`docs/roadmap.md`](docs/roadmap.md). 1. `.fig` import's tail: fixes from real files, connector labels, table cells, filled areas with their own fills (the best-effort import, editable vector networks, the other layer kinds and variable prototype actions landed 2026-10-11): 5–10 h. 2. Real-file corpus and measured fidelity: 15–30 h. 3. Tool-by-tool interaction pass against Figma: 40–60 h. -4. Languages on the landed localization layer: ja and ko (7–12 h), and native reviews of the es, fr, de and pt-BR drafts (people). +4. Languages: native reviews of the es, fr, de, pt-BR, ja and ko drafts (people), Latin American Spanish (1–2 h), then Simplified Chinese (3–5 h). 5. Multiplayer (M9): accounts and teams on top of the live sessions and the standalone server (transport, hosting, invite links that open the app, document sync, presence with remote text carets, cursor chat and spotlight, per-user undo, reconnect with offline edits, collision-free ids for styles, variables and comments, the browser client, `figcraft-server` with persistence and share links to edit or view, team libraries on the server landed): 42–84 h. ## Progress log @@ -229,6 +230,7 @@ Ranked; detail and milestones in [`docs/roadmap.md`](docs/roadmap.md). | Date | Change | Summary | |---|---|---| +| 2026-10-12 | minor | Japanese and Korean draft catalogs and CJK UI fonts (gap 5): `ja.toml` and `ko.toml` translate every UI string (1,351 keys; plurals give only `other`, and `plural_one` never picks "one" in either), command label (519) and menu wording (29), machine-drafted and marked as drafts awaiting native review; Preferences ▸ Language lists 日本語 and 한국어, System picks ja* and ko*. CJK UI text renders: once the UI language, the open file's names or comments, typed text or the language picker needs Japanese kana, Hangul or Han, the desktop app appends one installed face per script to egui's fallbacks (Windows Yu Gothic UI / Meiryo / Malgun Gothic / Microsoft YaHei, macOS Hiragino Sans / Apple SD Gothic Neo / PingFang SC, Linux Noto Sans CJK; the craft-fonts build's BIZ UDPGothic first), reading only that face's file and sharing its bytes with egui (English users load none: startup and memory unchanged); the web shows Japanese and Korean only when built with craft-fonts' Noto Sans CJK (`FIGCRAFT_EMBED_CJK`), else it keeps them out of the picker and System. Localization 30% → 35%, 40–65 h → 32–55 h; ready for real work ~52% → ~53% (52.9 → 53.1); full parity ~284–554 h → ~276–544 h; beta ~162–292 h → ~155–280 h | | 2026-10-12 | minor | Plugin widgets and the panel tail (gap 6, plugin API 3; v1 and v2 plugins unchanged): a plugin marked as a widget puts a layer of its own on the canvas from Plugins ▸ Widgets or `widget.insert`: it describes the layer (frames with auto layout, text, rectangles, ellipses, images it carries) and FigCraft validates the description (size, layer count, depth, numbers, colours, text and image sizes) and builds it as a frame with locked layers inside; a click on a part the plugin named (on the canvas with the Move tool, a pointing hand over it, or `widget.click`) calls the plugin back in a fresh, metered sandbox with the widget's state, as one undo step, and the widget is redrawn; the state lives in the widget's own layer data, so widgets survive save and reload, copying, undo, export and live sessions; no plugin can write that data or call `widget.*`. `widget.list` lists them. A Counter example widget. Plugin panels of different plugins open side by side, and a colour field's swatch opens the colour picker (the plugin hears of the colour when a drag ends). Plugins & widgets 45%/28% → 55%/32%, 15–40 h → 10–30 h; Ecosystem dimension 28% → 34%; weighted totals unchanged at this rounding; full parity ~286–558 h → ~281–548 h | | 2026-10-12 | minor | French, German and Brazilian Portuguese draft catalogs (gap 5): every UI string, command label and menu wording (1,899 entries) machine-drafted in each and marked as drafts awaiting native review, falling back to English per key (new strings need only English and Spanish); 0 counts as singular in French and Brazilian Portuguese; System picks the first OS language with a catalog (pt-PT and pt read pt-BR); long translations elide with a tooltip in dropdowns, two-column labels and the home cards. Localization 20% → 30%, 45–75 h → 40–65 h; ready for real work unchanged (~52%); full parity ~289–564 h → ~284–554 h; beta ~170–305 h → ~162–292 h | | 2026-10-12 | minor | Cursor chat and spotlight in live sessions: `/` opens a chat bubble at your pointer that everyone sees as you type and that fades a few seconds after the last change; a spotlight (your avatar's menu, `collab.spotlight`) makes everyone follow your view and page until they move their own. Ephemeral presence the host validates and rate-limits, passed only to clients that read it (older clients keep working). Multiplayer & sharing breadth 15% → 17%, ready unchanged (5%), 45–90 h → 42–84 h; collaboration 13% unchanged, 49–98 h → 46–92 h; feature breadth (~84%) and ready for real work (~51%) unchanged at this rounding; full parity ~301–587 h → ~298–581 h | diff --git a/crates/engine/src/cmd/view.rs b/crates/engine/src/cmd/view.rs index eea8291..21f0cb1 100644 --- a/crates/engine/src/cmd/view.rs +++ b/crates/engine/src/cmd/view.rs @@ -272,7 +272,7 @@ pub fn specs() -> Vec { s.prefs.user_name = if name.is_empty() { super::comment::DEFAULT_AUTHOR.into() } else { name }; Ok(json!({"name": s.prefs.user_name})) }), - spec!("pref.language", "Interface language", "{language: system|en|es|fr|de|pt-BR|… (no catalog: English)}", false, |s, p| { + spec!("pref.language", "Interface language", "{language: system|en|es|fr|de|pt-BR|ja|ko|… (no catalog: English)}", false, |s, p| { let lang = req_string("pref.language", p, "language")?; let lang = lang.trim(); // A BCP 47-style tag ("es", "pt-BR", "zh_Hans") or "system". diff --git a/crates/text/build.rs b/crates/text/build.rs index 5375599..e11de00 100644 --- a/crates/text/build.rs +++ b/crates/text/build.rs @@ -1,12 +1,14 @@ //! Embeds the optional craft-fonts build input (`CRAFT_FONTS_DIR`): both `fonts/manifest.txt` and the //! opt-in Latin presentation fonts in `fonts/latin-manifest.txt` (Inter, Roboto, …). Unset or missing, //! `CRAFT_FONTS` is empty and the app uses system fonts. Recipe: craft-fonts `docs/integration.md`. +//! Noto Sans CJK only with `FIGCRAFT_EMBED_CJK` set (the web build's only way to show CJK UI text). use std::fmt::Write as _; use std::path::PathBuf; fn main() { println!("cargo::rerun-if-env-changed=CRAFT_FONTS_DIR"); println!("cargo::rerun-if-env-changed=CRAFT_FONTS_REQUIRED"); + println!("cargo::rerun-if-env-changed=FIGCRAFT_EMBED_CJK"); let mut src = String::from("pub static CRAFT_FONTS: &[CraftFont] = &[\n"); if let Some(dir) = std::env::var_os("CRAFT_FONTS_DIR").map(PathBuf::from) { let mut ok = false; @@ -37,7 +39,6 @@ fn craft_fonts(dir: &std::path::Path, manifest_rel: &str) -> Result Result String { s.to_lowercase().replace([' ', '-', '_'], "") } +/// A style name's weight before its file is read: the usual names, and Hiragino's "W3" (300). +fn pending_weight(style: &str) -> i32 { + let w = norm_style(style).strip_prefix('w').and_then(|n| n.parse::().ok()).filter(|n| (0..=9).contains(n)); + w.map_or(i32::from(figcraft_doc::style_weight(style)), |n| n * 100) +} + /// The axes (user-space ranges) and named instances of a variable font. fn variation_info(f: &skrifa::FontRef) -> (Vec, Vec) { let all = f.axes(); @@ -455,7 +461,7 @@ impl FontDb { /// Style names of a family, by weight then italic. pub fn styles(&mut self, family: &str) -> Vec { - self.load_family(family); + self.load_family(family, None); let Some((_, idx)) = self.families.get(&family.to_lowercase()) else { return vec![] }; // (weight, italic, order in the font, name): named instances keep the font's order. let mut v: Vec<(u16, bool, usize, String)> = Vec::new(); @@ -482,9 +488,30 @@ impl FontDb { self.families.contains_key(&k) || self.pending.contains_key(&k) } - fn load_family(&mut self, family: &str) { + /// Read a system family's faces from disk; with `only`, just the face nearest that style (the + /// rest stay pending). + fn load_family(&mut self, family: &str, only: Option<&str>) { let key = family.to_lowercase(); - let Some((_, entries)) = self.pending.remove(&key) else { return }; + let entries = match only { + None => match self.pending.remove(&key) { + Some((_, entries)) => entries, + None => return, + }, + Some(style) => { + let Some((_, pending)) = self.pending.get_mut(&key) else { return }; + let (want, want_w) = (norm_style(style), pending_weight(style)); + let cost = |e: &Pending| { + let italic = if e.style.to_lowercase().contains("italic") { 1000 } else { 0 }; + if norm_style(&e.style) == want { 0 } else { 1 + (pending_weight(&e.style) - want_w).abs() + italic } + }; + let Some(i) = pending.iter().enumerate().min_by_key(|(_, e)| cost(e)).map(|(i, _)| i) else { return }; + let one = pending.remove(i); + if pending.is_empty() { + self.pending.remove(&key); + } + vec![one] + } + }; let mut by_path: BTreeMap>> = BTreeMap::new(); for e in entries { let bytes = match by_path.get(&e.path) { @@ -506,7 +533,22 @@ impl FontDb { /// The best face for `family` + `style` (exact style name, else nearest weight/italic). pub fn find(&mut self, family: &str, style: &str) -> Option> { - self.load_family(family); + self.load_family(family, None); + self.best(family, style) + } + + /// [`find`](Self::find), but a system family not loaded yet reads only its face nearest + /// `style`: a fallback for missing characters needs one face, not every file of a CJK family + /// (10–20 MB each). The family's other faces load when it is used by name. + pub fn find_one(&mut self, family: &str, style: &str) -> Option> { + if !self.families.contains_key(&family.to_lowercase()) { + self.load_family(family, Some(style)); + } + self.best(family, style) + } + + /// The loaded face of `family` nearest `style`. + fn best(&self, family: &str, style: &str) -> Option> { let (_, idx) = self.families.get(&family.to_lowercase())?; let faces: Vec<&Arc> = idx.iter().filter_map(|i| self.faces.get(*i)).collect(); let want = norm_style(style); @@ -714,5 +756,9 @@ pub fn system_fonts_scanned() -> bool { /// that needs a font for a script its own fonts lack. pub fn face_with_char(c: char, families: &[&str]) -> Option> { let mut db = db().write().unwrap_or_else(std::sync::PoisonError::into_inner); - families.iter().filter_map(|f| db.find(f, "Regular")).find(|f| f.has_char(c)) + families.iter().filter_map(|f| db.find_one(f, "Regular")).find(|f| f.has_char(c)) } + +#[cfg(test)] +#[path = "fontdb_tests.rs"] +mod tests; diff --git a/crates/text/src/fontdb_tests.rs b/crates/text/src/fontdb_tests.rs new file mode 100644 index 0000000..293ee81 --- /dev/null +++ b/crates/text/src/fontdb_tests.rs @@ -0,0 +1,31 @@ +use super::*; + +fn pending(styles: &[&str]) -> FontDb { + let mut db = FontDb::default(); + let entries = styles.iter().map(|s| Pending { path: format!("no-such-dir/{s}.ttf").into(), index: 0, style: (*s).into() }).collect(); + db.pending.insert("cjk ui".into(), ("CJK UI".into(), entries)); + db +} + +fn left(db: &FontDb) -> Vec { + db.pending.get("cjk ui").map(|(_, v)| v.iter().map(|e| e.style.clone()).collect()).unwrap_or_default() +} + +#[test] +fn find_one_reads_only_the_nearest_style() { + // The files don't exist: what matters is which entry is tried, and that the rest stay pending. + let mut db = pending(&["Bold", "Light", "Regular", "Italic"]); + assert!(db.find_one("CJK UI", "Regular").is_none()); + assert_eq!(left(&db), ["Bold", "Light", "Italic"]); + assert!(db.has_family("cjk ui"), "the family is still offered"); + // No exact name: the nearest weight, upright before italic. + let mut db = pending(&["W6", "Italic", "W3", "Bold"]); + db.find_one("CJK UI", "Regular"); + assert_eq!(left(&db), ["W6", "Italic", "Bold"]); + // `find` reads the whole family. + db.find("CJK UI", "Regular"); + assert!(left(&db).is_empty() && !db.has_family("cjk ui")); + assert_eq!(pending_weight("W3"), 300); + assert_eq!(pending_weight("SemiBold"), 600); + assert_eq!(pending_weight("W12"), 400); +} diff --git a/crates/ui-egui/locales/ja.toml b/crates/ui-egui/locales/ja.toml new file mode 100644 index 0000000..a50dc57 --- /dev/null +++ b/crates/ui-egui/locales/ja.toml @@ -0,0 +1,1916 @@ +# FigCraft interface strings: Japanese. +# +# Draft — needs native review: machine-drafted from the English catalog. Brand names, keyboard +# glyphs and {placeholders} stay as they are. Concise UI style without です/ます endings, +# full-width punctuation ()「」:、。 where Japanese UI text uses it. No plural forms: plural +# entries give only `other`. +# See docs/translating.md. + +[meta] +name = "日本語" +status = "draft — needs native review" + +[ui] +"% of all commits" = "全コミット中の %" +"(no longer published)" = "(公開終了)" +"({n} warnings: some entries were skipped)" = { other = "(警告 {n} 件:一部の項目をスキップ)" } +"+ Create variable" = "+ 変数を作成" +"1…9, 0" = "1…9, 0" +"@{login}: {prs} PRs, {commits} commits, +{added} / −{deleted} lines (Δ {delta}), +{bin_added} / −{bin_deleted} binary assets, {first} – {last}" = "@{login}:PR {prs} 件、コミット {commits} 件、+{added} / −{deleted} 行(Δ {delta})、バイナリアセット +{bin_added} / −{bin_deleted}、{first} – {last}" +"A collection of this file with these modes and variables: override their values per mode and add variables of its own" = "このファイルのコレクションとそのモード・変数:モードごとに値を上書きし、独自の変数を追加できる" +"A spring plays until it settles: its mass, stiffness and damping set how long" = "スプリングは静止するまで再生。長さは質量・剛性・減衰で決まる" +"About" = "情報" +"About FigCraft" = "FigCraft について" +"Action" = "アクション" +"Actions" = "アクション" +"Actions…" = "アクション…" +"Active" = "アクティブ" +"Actual size (100%)" = "実際のサイズ(100%)" +"Add a category" = "カテゴリを追加" +"Add a comment" = "コメントを追加" +"Add a description" = "説明を追加" +"Add a frame (F) or a shape (R) to get started" = "フレーム(F)またはシェイプ(R)を追加して開始" +"Add a layer or component to tile first" = "先に並べるレイヤーまたはコンポーネントを追加" +"Add a note for developers" = "開発者向けのメモを追加" +"Add action" = "アクションを追加" +"Add actions for when no condition holds" = "どの条件にも当てはまらないときのアクションを追加" +"Add an annotation for developers" = "開発者向けの注釈を追加" +"Add another condition" = "条件を追加" +"Add auto layout" = "オートレイアウトを追加" +"Add background behind overlay" = "オーバーレイの背後に背景を追加" +"Add content to this slot" = "このスロットにコンテンツを追加" +"Add dev resource" = "開発リソースを追加" +"Add effect" = "エフェクトを追加" +"Add export setting" = "書き出し設定を追加" +"Add fill" = "塗りを追加" +"Add interaction" = "インタラクションを追加" +"Add layout grid" = "レイアウトグリッドを追加" +"Add library" = "ライブラリを追加" +"Add library file…" = "ライブラリファイルを追加…" +"Add max height" = "最大の高さを追加" +"Add max width" = "最大の幅を追加" +"Add min height" = "最小の高さを追加" +"Add min width" = "最小の幅を追加" +"Add mode" = "モードを追加" +"Add new page" = "新しいページを追加" +"Add or update collections from a variables JSON" = "変数 JSON からコレクションを追加・更新" +"Add properties to make instances configurable" = "プロパティを追加してインスタンスを設定可能にする" +"Add reaction" = "リアクションを追加" +"Add starting point" = "開始点を追加" +"Add stroke" = "線を追加" +"Add variant" = "バリアントを追加" +"Add variant with a new value" = "新しい値でバリアントを追加" +"Added" = "追加" +"Added the library \"{name}\"" = "ライブラリ「{name}」を追加済み" +"Adjust" = "調整" +"Adjustment presets" = "調整プリセット" +"Advanced stroke" = "詳細な線" +"After delay" = "遅延後" +"After delay {ms}ms" = "{ms}ms 遅延後" +"Align" = "整列" +"Align bottom" = "下揃え" +"Align center" = "中央揃え" +"Align horizontal centers" = "水平方向の中央揃え" +"Align left" = "左揃え" +"Align middle" = "上下中央揃え" +"Align right" = "右揃え" +"Align text baselines" = "テキストのベースラインを揃える" +"Align top" = "上揃え" +"Align vertical centers" = "垂直方向の中央揃え" +"Alignment" = "配置" +"All" = "すべて" +"All categories" = "すべてのカテゴリ" +"All comments" = "すべてのコメント" +"All components" = "すべてのコンポーネント" +"All fonts" = "すべてのフォント" +"All supported properties" = "サポートされているすべてのプロパティ" +"All variables" = "すべての変数" +"Alpha" = "アルファ" +"Alt+drag" = "Alt+ドラッグ" +"Anchor" = "アンカー" +"Android" = "Android" +"Angular" = "角度" +"Animation" = "アニメーション" +"Annotations" = "注釈" +"Annotations shown on the canvas" = "キャンバスに表示される注釈" +"Any status" = "すべてのステータス" +"Anyone on your network who has the invite link can join." = "招待リンクを持つネットワーク内の誰でも参加できる。" +"Anyone with the edit link can change the file; the view link only lets people look. The links carry their secrets: share them like passwords. `figcraft-server links` makes more and revokes them." = "編集リンクを持つ人はファイルを変更でき、閲覧リンクでは表示のみ可能。リンクには秘密情報が含まれるため、パスワードと同様に扱うこと。リンクの追加と取り消しは `figcraft-server links` で行う。" +"Appearance" = "外観" +"Apply a component property" = "コンポーネントプロパティを適用" +"Apply variable" = "変数を適用" +"Apply variable to text" = "テキストに変数を適用" +"Apply variable to visibility" = "表示に変数を適用" +"Arc" = "円弧" +"Arc ratio" = "円弧の比率" +"Arc start" = "円弧の開始" +"Arc sweep" = "円弧の範囲" +"Archive" = "アーカイブ" +"Archived" = "アーカイブ済み" +"Arrange" = "配置" +"Arrow" = "矢印" +"As typed" = "入力どおり" +"Assets" = "アセット" +"Auto" = "自動" +"Auto (space around)" = "自動(周囲に間隔)" +"Auto (space between)" = "自動(間に間隔)" +"Auto (space evenly)" = "自動(均等な間隔)" +"Auto ({mode})" = "自動({mode})" +"Auto columns" = "自動列" +"Auto gap" = "自動間隔" +"Auto height" = "高さを自動調整" +"Auto layout" = "オートレイアウト" +"Auto rows" = "自動行" +"Auto width" = "幅を自動調整" +"Back to the font's value" = "フォントの値に戻す" +"Back" = "戻る" +"Back to Ready for dev" = "開発準備完了に戻す" +"Back to Ready for dev: the next change compares with how it is now" = "開発準備完了に戻す:次の変更は現在の状態と比較" +"Back to assets" = "アセットに戻る" +"Back to current" = "現在に戻る" +"Back to styles" = "スタイルに戻る" +"Back to the canvas from a focused region" = "フォーカスした領域からキャンバスに戻る" +"Back to the current version" = "現在のバージョンに戻る" +"Back to the values the font style implies" = "フォントスタイルが示す値に戻す" +"Background" = "背景" +"Background blur" = "背景のぼかし" +"Basics" = "基本" +"Before" = "変更前" +"Bend" = "曲げ" +"Bevel" = "ベベル" +"Binary assets added" = "追加されたバイナリアセット" +"Binary assets removed" = "削除されたバイナリアセット" +"Black & white" = "白黒" +"Bleed" = "裁ち落とし" +"Bleed marks" = "裁ち落としトンボ" +"Bleed marks need a bleed" = "裁ち落としトンボには裁ち落としが必要" +"Blend" = "ブレンド" +"Blend mode" = "ブレンドモード" +"Blue" = "青" +"Blur" = "ぼかし" +"Boolean" = "ブーリアン" +"Boolean groups" = "ブーリアングループ" +"Both directions" = "両方向" +"Bottom" = "下" +"Bottom left radius" = "左下の半径" +"Bottom right radius" = "右下の半径" +"Branch" = "ブランチ" +"Branch archived" = "ブランチをアーカイブ済み" +"Branch merged" = "ブランチをマージ済み" +"Branch name" = "ブランチ名" +"Branch of {file}" = "{file} のブランチ" +"Branch of {file} · merged or archived" = "{file} のブランチ · マージ済みまたはアーカイブ済み" +"Branch updated from main" = "メインからブランチを更新済み" +"Branch {name}" = "ブランチ {name}" +"Branches" = "ブランチ" +"Bring forward" = "前面へ" +"Bring the main file's changes into the branch" = "メインファイルの変更をブランチに取り込む" +"Bring to front" = "最前面へ" +"Bristle" = "剛毛" +"Brush" = "ブラシ" +"Brush rotation jitter" = "ブラシの回転のばらつき" +"Brush scatter" = "ブラシの散布" +"Brush size jitter" = "ブラシのサイズのばらつき" +"Brush spacing" = "ブラシの間隔" +"Bulleted list" = "箇条書き" +"CMYK colour" = "CMYK カラー" +"Color profile: {name}" = "カラープロファイル:{name}" +"CSS custom properties…" = "CSS カスタムプロパティ…" +"Can edit" = "編集可" +"Can't read this library: {e}" = "このライブラリを読み込めない:{e}" +"Cancel" = "キャンセル" +"Canvas" = "キャンバス" +"Canvas stacking" = "キャンバスの重なり順" +"Cap height to baseline" = "キャップハイトからベースライン" +"Case" = "大文字・小文字" +"Case-sensitive forms" = "大文字用の字形" +"Categories" = "カテゴリ" +"Center" = "中央" +"Change alias" = "エイリアスを変更" +"Change resolved" = "変更を解決済み" +"Change style" = "スタイルを変更" +"Change to" = "変更先" +"Change to needs a layer inside a variant" = "「変更先」にはバリアント内のレイヤーが必要" +"Changed" = "変更済み" +"Changed on both sides: keep one" = "両方で変更あり:どちらかを残す" +"Changes on main" = "メインの変更" +"Changes on the branch" = "ブランチの変更" +"Changes unknown" = "変更内容は不明" +"Choose React, SwiftUI or Compose above to connect this component to its code." = "上で React、SwiftUI、Compose のいずれかを選び、このコンポーネントをコードに接続。" +"Choose another profile to change it." = "変更するには別のプロファイルを選択。" +"Choose collection" = "コレクションを選択" +"Choose image" = "画像を選択" +"Choose mode" = "モードを選択" +"Choose variable" = "変数を選択" +"Circle" = "円" +"Clear recent" = "最近の項目をクリア" +"Click + to replace mixed content" = "+ をクリックして混在した内容を置き換え" +"Click anywhere on the canvas to leave one." = "キャンバスの任意の場所をクリックしてコメントを残せる。" +"Click or drag to merge · {alt} removes" = "クリックまたはドラッグで結合 · {alt} で削除" +"Click or drag to remove · {alt} merges" = "クリックまたはドラッグで削除 · {alt} で結合" +"Click to record a key" = "クリックしてキーを記録" +"Clip content" = "コンテンツを切り抜く" +"Clip to shape" = "シェイプでクリップ" +"Close" = "閉じる" +"Close overlay" = "オーバーレイを閉じる" +"Close preview" = "プレビューを閉じる" +"Close tab" = "タブを閉じる" +"Close version history" = "バージョン履歴を閉じる" +"Close when clicking outside" = "外側をクリックしたら閉じる" +"Close without saving" = "保存せずに閉じる" +"Code" = "コード" +"Code syntax" = "コード構文" +"Collapse" = "折りたたむ" +"Collapse panel" = "パネルを折りたたむ" +"Collection" = "コレクション" +"Collections" = "コレクション" +"Color" = "カラー" +"Color burn" = "焼き込みカラー" +"Color dodge" = "覆い焼きカラー" +"Color format" = "カラー形式" +"Color profile" = "カラープロファイル" +"Color styles" = "カラースタイル" +"Color values in this file are in this color space." = "このファイルのカラー値はこのカラースペースで表される。" +"Color variables" = "カラー変数" +"Colour" = "カラー" +"Column" = "列" +"Column gap" = "列の間隔" +"Column sizes" = "列のサイズ" +"Column span" = "列の範囲" +"Columns" = "列" +"Columns {count}" = "列 {count}" +"Comment" = "コメント" +"Comments" = "コメント" +"Commits" = "コミット" +"Community" = "コミュニティ" +"Company" = "会社" +"Compare changes" = "変更を比較" +"Completed" = "完了" +"Component" = "コンポーネント" +"Component name" = "コンポーネント名" +"Component property" = "コンポーネントプロパティ" +"Component set" = "コンポーネントセット" +"Component sets" = "コンポーネントセット" +"Components" = "コンポーネント" +"Conditional" = "条件分岐" +"Confetti" = "紙吹雪" +"Conflicts" = "競合" +"Connect to code" = "コードに接続" +"Connected" = "接続済み" +"Connected to code: {from}" = "コードに接続済み:{from}" +"Connection lost, reconnecting (attempt {attempt})…" = "接続が切断。再接続中({attempt} 回目)…" +"Constrain proportions" = "縦横比を固定" +"Constraints" = "制約" +"Content" = "コンテンツ" +"Contents hidden" = "コンテンツ非表示" +"Contents only" = "コンテンツのみ" +"Contextual alternates" = "前後関係に依存する字形" +"Contrast" = "コントラスト" +"Contributors" = "貢献者" +"Contributors: {people} · Commits: {commits}" = "貢献者:{people} · コミット:{commits}" +"Cool" = "クール" +"Copied as CSS" = "CSS としてコピー済み" +"Copied as PNG" = "PNG としてコピー済み" +"Copied as SVG" = "SVG としてコピー済み" +"Copied as text" = "テキストとしてコピー済み" +"Copied {value}" = "{value} をコピー済み" +"Copy" = "コピー" +"Copy as" = "形式を指定してコピー" +"Copy as CSS" = "CSS としてコピー" +"Copy as PNG" = "PNG としてコピー" +"Copy as SVG" = "SVG としてコピー" +"Copy link" = "リンクをコピー" +"Copy the {label}" = "{label}をコピー" +"Copy {value}" = "{value} をコピー" +"Corner radius" = "角の半径" +"Corner smoothing" = "角のスムージング" +"Count" = "数" +"Create" = "作成" +"Create a variable collection first" = "先に変数コレクションを作成" +"Create a variable first" = "先に変数を作成" +"Create alias" = "エイリアスを作成" +"Create branch" = "ブランチを作成" +"Create collection" = "コレクションを作成" +"Create component" = "コンポーネントを作成" +"Create component property" = "コンポーネントプロパティを作成" +"Create components, styles or variables to publish them as a library." = "コンポーネント、スタイル、変数を作成すると、ライブラリとして公開できる。" +"Create property…" = "プロパティを作成…" +"Create style" = "スタイルを作成" +"Create style from the selected text" = "選択したテキストからスタイルを作成" +"Crop" = "切り抜き" +"Crop marks" = "トンボ" +"Ctrl+arrows" = "Ctrl+矢印キー" +"Ctrl+click" = "Ctrl+クリック" +"Ctrl+scroll" = "Ctrl+スクロール" +"Current version" = "現在のバージョン" +"Custom" = "カスタム" +"Cut" = "カット" +"Dark" = "ダーク" +"Darken" = "比較(暗)" +"Dash" = "破線" +"Decoration style" = "装飾のスタイル" +"Decoration" = "装飾" +"Deep select" = "深い階層を選択" +"Default" = "デフォルト" +"Default content" = "デフォルトのコンテンツ" +"Default value (the top-left variant)" = "デフォルト値(左上のバリアント)" +"Delay" = "遅延" +"Delete" = "削除" +"Delete category (its annotations stay)" = "カテゴリを削除(注釈は残る)" +"Delete collection" = "コレクションを削除" +"Delete group" = "グループを削除" +"Delete mode" = "モードを削除" +"Delete page" = "ページを削除" +"Delete preset" = "プリセットを削除" +"Delete property" = "プロパティを削除" +"Delete the style (layers keep their values)" = "スタイルを削除(レイヤーの値は保持)" +"Delete thread" = "スレッドを削除" +"Delete variable" = "変数を削除" +"Delete “{name}”? This can't be undone." = "「{name}」を削除する? この操作は元に戻せない。" +"Density" = "密度" +"Depth" = "深さ" +"Describe how and when to use this component" = "このコンポーネントの使い方と使う場面を説明" +"Describe what changed" = "変更内容を説明" +"Description" = "説明" +"Description (optional)" = "説明(任意)" +"Design" = "デザイン" +"Desktop" = "デスクトップ" +"Destination" = "遷移先" +"Detach alias" = "エイリアスを解除" +"Detach instance" = "インスタンスを切り離す" +"Detach property" = "プロパティを切り離す" +"Detach style" = "スタイルを切り離す" +"Detach styles" = "スタイルを切り離す" +"Detach variable" = "変数を切り離す" +"Details" = "詳細" +"Dev Mode" = "開発モード" +"Dev resources" = "開発リソース" +"Development" = "開発" +"Device" = "デバイス" +"Device at 100%" = "デバイス(100%)" +"Diamond" = "ひし形" +"Difference" = "差の絶対値" +"Dimensions" = "寸法" +"Direction" = "方向" +"Disconnect from code" = "コードとの接続を解除" +"Dispersion" = "分散" +"Display name" = "表示名" +"Dissolve" = "ディザ合成" +"Distribute and tidy" = "分布と整列" +"Distribute horizontal spacing" = "水平方向に等間隔に分布" +"Distribute vertical spacing" = "垂直方向に等間隔に分布" +"Don't truncate" = "切り詰めない" +"Done" = "完了" +"Done editing" = "編集を完了" +"Dots" = "ドット" +"Dotted" = "点線" +"Down" = "下" +"Drafts" = "下書き" +"Drag the stroke to add a width point" = "線をドラッグして幅のポイントを追加" +"Draw" = "描画" +"Drawing tools" = "描画ツール" +"Drop shadow" = "ドロップシャドウ" +"Dual-licensed MIT OR Apache-2.0. Made by the ArtCraft team and community." = "MIT または Apache-2.0 のデュアルライセンス。ArtCraft チームとコミュニティが制作。" +"Duo" = "デュオ" +"Duplicate" = "複製" +"Duplicate by dragging" = "ドラッグで複製" +"Duplicate mode" = "モードを複製" +"Duplicate page" = "ページを複製" +"Edit" = "編集" +"Edit as an expression" = "式として編集" +"Edit colour" = "カラーを編集" +"Edit comment" = "コメントを編集" +"Edit dev resource" = "開発リソースを編集" +"Edit link" = "編集リンク" +"Edit link copied" = "編集リンクをコピー済み" +"Edit style" = "スタイルを編集" +"Edit variable" = "変数を編集" +"Edit with the builder" = "ビルダーで編集" +"Effect settings" = "エフェクトの設定" +"Effect styles" = "エフェクトスタイル" +"Effects" = "エフェクト" +"Ellipse" = "楕円" +"Ellipses" = "楕円" +"Else" = "それ以外" +"Else if" = "それ以外で条件" +"Embedded profile" = "埋め込みプロファイル" +"Empty" = "空" +"End" = "終了" +"End point" = "終点" +"Enter to save · Esc to cancel" = "Enter で保存 · Esc でキャンセル" +"Eraser" = "消しゴム" +"Esc" = "Esc" +"Essential" = "基本" +"Every conflict has a choice." = "すべての競合で選択済み。" +"Every top-level frame already starts a flow" = "すべてのトップレベルフレームがすでにフローを開始済み" +"Exact opacity (4 then 5: 45%)" = "正確な不透明度(4 の次に 5:45%)" +"Exclude" = "除外" +"Excluded" = "除外" +"Excluded from layout" = "レイアウトから除外" +"Excludes" = "除外" +"Exclusion" = "除外" +"Exit focus view (Esc)" = "フォーカスビューを終了(Esc)" +"Expand" = "展開" +"Export" = "書き出し" +"Export all" = "すべて書き出し" +"Export page as PNG" = "ページを PNG で書き出し" +"Export settings" = "書き出し設定" +"Export variables" = "変数を書き出し" +"Export {name}" = "{name} を書き出し" +"Export {n} layers" = { other = "{n} 個のレイヤーを書き出し" } +"Exported {file}" = "{file} を書き出し済み" +"Exported {name}" = "{name} を書き出し済み" +"Exported {n} files" = { other = "{n} 個のファイルを書き出し済み" } +"Export…" = "書き出し…" +"Expose properties to instances" = "プロパティをインスタンスに公開" +"Exposure" = "露光量" +"Expression" = "式" +"Extend collection" = "コレクションを拡張" +"Extends \"{name}\": overridden values are marked" = "「{name}」を拡張:上書きした値に印が付く" +"Eye" = "目" +"Fade" = "フェード" +"False" = "false" +"Fetching from the server…" = "サーバーから取得中…" +"File" = "ファイル" +"File name" = "ファイル名" +"Fill" = "塗り" +"Fill (fr)" = "フィル(fr)" +"Fill container" = "コンテナに合わせる" +"Fill window" = "ウィンドウに合わせる" +"Fills" = "塗り" +"Fill|sizing" = "フィル" +"Filter and sort" = "フィルターと並べ替え" +"Find" = "検索" +"Find and replace" = "検索と置換" +"Find layers" = "レイヤーを検索" +"First" = "最初" +"First commit" = "最初のコミット" +"First on top" = "最初を上に" +"Fit" = "フィット" +"Fit device to window" = "デバイスをウィンドウに合わせる" +"Fit to contents" = "コンテンツに合わせる" +"Fit to window" = "ウィンドウに合わせる" +"Fit width" = "幅に合わせる" +"Fixed" = "固定" +"Fixed gap" = "固定間隔" +"Fixed size" = "固定サイズ" +"Flatten" = "平坦化" +"Flip" = "反転" +"Flip horizontal" = "左右反転" +"Flip text to the other side" = "テキストを反対側に反転" +"Flip vertical" = "上下反転" +"Flip width profile" = "幅プロファイルを反転" +"Flow starting point" = "フローの開始点" +"Flow starting points" = "フローの開始点" +"Flows" = "フロー" +"Focus view" = "フォーカスビュー" +"Fold autosaves" = "自動保存をまとめる" +"Follow {name}" = "{name} をフォロー" +"Following" = "フォロー中" +"Following {name} · {key} to stop" = "{name} をフォロー中 · {key} で停止" +"Font" = "フォント" +"Font not installed" = "フォントが未インストール" +"Font size" = "フォントサイズ" +"Font style" = "フォントスタイル" +"Fractions" = "分数" +"Frame" = "フレーム" +"Frame selection" = "選択範囲をフレームで囲む" +"Frame tools" = "フレームツール" +"Frames" = "フレーム" +"From the library \"{name}\": read-only" = "ライブラリ「{name}」から:読み取り専用" +"From {name}" = "{name} から" +"Frost" = "すりガラス" +"Gap" = "間隔" +"Gap between columns" = "列の間隔" +"Gap between items" = "アイテムの間隔" +"Gap between rows" = "行の間隔" +"Glass" = "ガラス" +"Go to main component" = "メインコンポーネントへ移動" +"Go to {name}" = "{name} へ移動" +"Grab bag" = "ピックアップ" +"Gradient" = "グラデーション" +"Gray" = "グレー" +"Green" = "緑" +"Grid" = "グリッド" +"Grid ({size})" = "グリッド({size})" +"Grid styles" = "グリッドスタイル" +"Grid {size}" = "グリッド {size}" +"Group" = "グループ" +"Group selection" = "選択範囲をグループ化" +"Groups" = "グループ" +"Gutter" = "ガター" +"Hand tool" = "手のひらツール" +"Hanging list" = "ぶら下げリスト" +"Hanging punctuation" = "ぶら下げ句読点" +"Hard light" = "ハードライト" +"Height" = "高さ" +"Help" = "ヘルプ" +"Help and resources" = "ヘルプとリソース" +"Help page" = "ヘルプページ" +"Hidden" = "非表示" +"Hide contents" = "コンテンツを非表示" +"Hide from publishing" = "公開対象から除外" +"Hide section contents" = "セクションのコンテンツを非表示" +"Highlight layers on hover" = "ホバー時にレイヤーをハイライト" +"Highlights" = "ハイライト" +"Hold Alt" = "Alt を押したまま" +"Hold Alt+Z" = "Alt+Z を押したまま" +"Hold Z" = "Z を押したまま" +"Hold ⌥" = "⌥ を押したまま" +"Hold ⌥Z" = "⌥Z を押したまま" +"Home" = "ホーム" +"Horizontal" = "水平" +"Horizontal align" = "水平方向の配置" +"Horizontal hex" = "横向き六角形" +"Horizontal padding" = "左右のパディング" +"Horizontal spacing" = "水平方向の間隔" +"Hosting a session needs the desktop app; here you can join one." = "セッションのホストにはデスクトップアプリが必要。ここでは参加のみ可能。" +"Hover a layer to see its properties" = "レイヤーにポインターを合わせるとプロパティを表示" +"Hover other layers to measure the distance" = "他のレイヤーにポインターを合わせると距離を測定" +"Hue" = "色相" +"Hug" = "ハグ" +"Hug contents" = "内容に合わせる" +"If" = "条件" +"If {condition}" = "条件:{condition}" +"Ignore auto layout (absolute position)" = "オートレイアウトを無視(絶対位置)" +"Image" = "画像" +"Import" = "インポート" +"Import path" = "インポートパス" +"Import plugin from manifest" = "マニフェストからプラグインをインポート" +"Import plugin from manifest…" = "マニフェストからプラグインをインポート…" +"Import variables" = "変数をインポート" +"Imported {name}" = "{name} をインポート済み" +"Imported {n} new variables, updated {updated}" = { other = "新しい変数を {n} 個インポートし、{updated} 個を更新" } +"Import…" = "インポート…" +"In an instance, this comes from the main component" = "インスタンスでは、この値はメインコンポーネントから取得" +"In the browser you can join sessions the desktop app hosts and files on a FigCraft server. A page opened over https reaches other computers only through wss:// links (a server behind TLS)." = "ブラウザーでは、デスクトップアプリがホストするセッションや FigCraft サーバー上のファイルに参加できる。https で開いたページが他のコンピューターに接続できるのは wss:// リンク(TLS の背後にあるサーバー)のみ。" +"Include bounding box" = "バウンディングボックスを含める" +"Include id attribute" = "id 属性を含める" +"Included" = "含む" +"Included in layout" = "レイアウトに含む" +"Individual corners" = "個別の角" +"Individual strokes" = "個別の線" +"Ink" = "インク" +"Inner shadow" = "インナーシャドウ" +"Inside" = "内側" +"Inspect" = "検査" +"Inspect the layer under the pointer: size, colours, typography" = "ポインター下のレイヤーを検査:サイズ、カラー、タイポグラフィ" +"Instance" = "インスタンス" +"Instance properties" = "インスタンスのプロパティ" +"Instance swap" = "インスタンスの入れ替え" +"Instance swap (no other component)" = "インスタンスの入れ替え(他のコンポーネントなし)" +"Instances" = "インスタンス" +"Instant" = "即時" +"Interaction" = "インタラクション" +"Interactions" = "インタラクション" +"Interface design and prototyping. A free, open-source, clean-room design tool written from scratch in Rust, part of the ArtCraft Crafting Apps." = "インターフェースデザインとプロトタイピング。Rust でゼロから書かれた、無料でオープンソースのクリーンルーム設計のデザインツール。ArtCraft Crafting Apps の一つ。" +"Intersect" = "交差" +"Intersects" = "交差" +"Invite link" = "招待リンク" +"Invite link copied" = "招待リンクをコピー済み" +"Join" = "参加" +"Join a session…" = "セッションに参加…" +"Join live session" = "ライブセッションに参加" +"Join us on Discord" = "Discord に参加する" +"Joined" = "参加済み" +"Joined {file}" = "{file} に参加済み" +"Joining…" = "参加中…" +"Join|stroke" = "角の形状" +"Just now" = "たった今" +"Justify" = "両端揃え" +"Keep appearance" = "見た目を保持" +"Keep appearance converts every color value to {profile} so colors look the same. Keep values leaves the numbers as they are, so colors shift." = "「見た目を保持」はすべてのカラー値を {profile} に変換し、色の見た目を保つ。「値を保持」は数値をそのまま残すため、色が変わる。" +"Keep tool selected after use" = "使用後もツールを選択したままにする" +"Keep values" = "値を保持" +"Key/Gamepad" = "キー/ゲームパッド" +"Key/Gamepad {key}" = "キー/ゲームパッド {key}" +"Keyboard shortcuts" = "キーボードショートカット" +"Language" = "言語" +"Lasso" = "なげなわ" +"Last" = "最後" +"Last change: {note}" = "最後の変更:{note}" +"Last commit" = "最後のコミット" +"Last on top" = "最後を上に" +"Layer blur" = "レイヤーのぼかし" +"Layer name" = "レイヤー名" +"Layers" = "レイヤー" +"Layers in an instance take their position from the main component" = "インスタンス内のレイヤーの位置はメインコンポーネントから取得" +"Layout" = "レイアウト" +"Layout grid" = "レイアウトグリッド" +"Layout grid settings" = "レイアウトグリッドの設定" +"Layout grids" = "レイアウトグリッド" +"Leave session" = "セッションから退出" +"Leaves" = "葉" +"Left" = "左" +"Left & right" = "左右" +"Left side" = "左側" +"Left side width" = "左側の幅" +"Letter case" = "大文字と小文字" +"Letter spacing" = "文字間隔" +"Libraries" = "ライブラリ" +"Libraries in this file" = "このファイルのライブラリ" +"Library updates available" = "ライブラリの更新あり" +"Library: click to collapse" = "ライブラリ:クリックして折りたたむ" +"Library: click to expand" = "ライブラリ:クリックして展開" +"Library: its variables are read-only here; edit them in the library file and publish it" = "ライブラリ:ここでは変数は読み取り専用。ライブラリファイルで編集して公開" +"Light" = "ライト" +"Lighten" = "比較(明)" +"Light|glass" = "光" +"Line" = "線" +"Line arrow" = "線の矢印" +"Line delta" = "行の増減" +"Line height" = "行の高さ" +"Linear" = "線形" +"Lines" = "線" +"Lines +/−" = "行 +/−" +"Lines added" = "追加行数" +"Lines deleted" = "削除行数" +"Link" = "リンク" +"Link copied" = "リンクをコピー済み" +"Link docs, code or tickets for developers." = "開発者向けにドキュメント、コード、チケットをリンク。" +"Link this component to its code component: instances then show your real snippet with their values." = "このコンポーネントをコードコンポーネントにリンクすると、インスタンスに実際のスニペットがその値とともに表示される。" +"List spacing" = "リストの間隔" +"List style" = "リストのスタイル" +"Live session" = "ライブセッション" +"Live · {people}" = "ライブ · {people}" +"Local components" = "ローカルコンポーネント" +"Local styles" = "ローカルスタイル" +"Local variables" = "ローカル変数" +"Lock/Unlock" = "ロック/ロック解除" +"Locked" = "ロック中" +"Lowercase" = "小文字" +"Luminance" = "輝度" +"Luminosity" = "輝度" +"Main" = "メイン" +"Main component deleted" = "メインコンポーネントは削除済み" +"Main menu" = "メインメニュー" +"Make slot" = "スロットにする" +"Margin" = "マージン" +"Mark all as read" = "すべて既読にする" +"Mark as resolved" = "解決済みにする" +"Mark as unread" = "未読にする" +"Mark as unresolved" = "未解決にする" +"Mask" = "マスク" +"Mass · Stiffness · Damping" = "質量 · 剛性 · 減衰" +"Max H" = "最大 H" +"Max W" = "最大 W" +"Max lines" = "最大行数" +"Maximize" = "最大化" +"Measure to the selection" = "選択範囲までの距離を測定" +"Merge into main" = "メインにマージ" +"Merge regions" = "領域を結合" +"Merge the branch into the main file (one undo step) and archive it" = "ブランチをメインファイルにマージし(1 回の取り消し単位)、アーカイブする" +"Merged" = "マージ済み" +"Merged PRs" = "マージされた PR" +"Min H" = "最小 H" +"Min W" = "最小 W" +"Minimize" = "最小化" +"Mirror angle" = "角度を対称にする" +"Mirror angle and length" = "角度と長さを対称にする" +"Mirroring" = "対称" +"Missing" = "見つからない" +"Missing layer" = "レイヤーが見つからない" +"Missing style" = "スタイルが見つからない" +"Missing variable" = "変数が見つからない" +"Miter" = "マイター" +"Miter angle" = "マイター角度" +"Mixed" = "混在" +"Mixed fonts" = "混在フォント" +"Mixed interactions: click + to replace them" = "混在したインタラクション:+ をクリックして置き換え" +"Mode" = "モード" +"Model" = "モデル" +"Models" = "モデル" +"Mono" = "モノ" +"More" = "その他" +"More instance actions" = "その他のインスタンス操作" +"Mouse down" = "マウスダウン" +"Mouse enter" = "マウスエンター" +"Mouse leave" = "マウスリーブ" +"Mouse up" = "マウスアップ" +"Move" = "移動" +"Move column left" = "列を左へ移動" +"Move column right" = "列を右へ移動" +"Move down" = "下へ移動" +"Move in" = "ムーブイン" +"Move out" = "ムーブアウト" +"Move tools" = "移動ツール" +"Move up" = "上へ移動" +"Moved to {name}" = "{name} に移動済み" +"Multi" = "マルチ" +"Multiply" = "乗算" +"Muted" = "ミュート" +"Name" = "名前" +"Name (A–Z)" = "名前(A–Z)" +"Named instance" = "名前付きインスタンス" +"Navigate to" = "移動先" +"Nested instance" = "ネストされたインスタンス" +"New design file" = "新規デザインファイル" +"Next or previous control in the focused region" = "フォーカス中の領域で次または前のコントロール" +"Next ready for dev" = "次の開発準備完了" +"Next size option" = "次のサイズオプション" +"No assets: no export settings, icons or images. Add export settings in the Design tab." = "アセットなし:書き出し設定、アイコン、画像がない。書き出し設定は[デザイン]タブで追加。" +"No boolean variables fit here." = "ここに使えるブーリアン変数はない。" +"No boolean variables yet. Create them in Local variables." = "ブーリアン変数はまだない。ローカル変数で作成。" +"No branches. A branch is a copy of the file to try changes in, then review and merge." = "ブランチはない。ブランチはファイルのコピーで、変更を試してからレビューしてマージできる。" +"No category" = "カテゴリなし" +"No changes" = "変更なし" +"No colour variables fit here." = "ここに使えるカラー変数はない。" +"No colour variables yet. Create them in Local variables." = "カラー変数はまだない。ローカル変数で作成。" +"No comments yet" = "コメントはまだない" +"No components yet. Select layers and press {keys}." = "コンポーネントはまだない。レイヤーを選択して {keys} を押す。" +"No conflicts." = "競合なし。" +"No contributor data was built into this copy." = "このコピーには貢献者データが含まれていない。" +"No fonts match" = "一致するフォントなし" +"No layer changes to show." = "表示するレイヤーの変更なし。" +"No libraries yet. Add a .figcraft file that was published as a library, or paste a team library's link." = "ライブラリはまだない。ライブラリとして公開された .figcraft ファイルを追加するか、チームライブラリのリンクを貼り付ける。" +"No list" = "リストなし" +"No matching comments" = "一致するコメントなし" +"No matching components" = "一致するコンポーネントなし" +"No matching layers" = "一致するレイヤーなし" +"No matching styles" = "一致するスタイルなし" +"No matching variables" = "一致する変数なし" +"No mirroring" = "対称なし" +"No model credits were built into this copy." = "このコピーにはモデルのクレジットが含まれていない。" +"No number variables fit here." = "ここに使える数値変数はない。" +"No number variables yet. Create them in Local variables." = "数値変数はまだない。ローカル変数で作成。" +"No paints" = "ペイントなし" +"No plugins yet. Import a development plugin from its figcraft-plugin.json." = "プラグインはまだない。開発用プラグインを figcraft-plugin.json からインポート。" +"No preferred components" = "優先コンポーネントなし" +"No preset" = "プリセットなし" +"No saved versions yet. Save a version to mark a point in your work you can come back to." = "保存したバージョンはまだない。バージョンを保存すると、作業の途中に戻れる地点を残せる。" +"No scrolling" = "スクロールなし" +"No shortcuts match" = "一致するショートカットなし" +"No status" = "ステータスなし" +"No string variables fit here." = "ここに使える文字列変数はない。" +"No string variables yet. Create them in Local variables." = "文字列変数はまだない。ローカル変数で作成。" +"No styles yet." = "スタイルはまだない。" +"No styles yet. Click + to create one from the selection." = "スタイルはまだない。+ をクリックして選択範囲から作成。" +"No text styles yet. Click + to create one from the selected text." = "テキストスタイルはまだない。+ をクリックして選択したテキストから作成。" +"No variables fit here." = "ここに使える変数はない。" +"No variables yet. Create them in Local variables." = "変数はまだない。ローカル変数で作成。" +"Nobody else is here yet" = "まだ他に誰もいない" +"Noise" = "ノイズ" +"None" = "なし" +"None." = "なし。" +"Normal" = "通常" +"Not bound" = "未割り当て" +"Not in a live session" = "ライブセッションに未参加" +"Not in this font" = "このフォントにはない" +"Not properties, kept as written: {names}" = "プロパティではないため記述どおりに保持:{names}" +"Not read yet" = "未読" +"Note {n}" = "メモ {n}" +"Nothing changed since this was marked ready for dev." = "開発準備完了にしてから変更なし。" +"Nothing here yet. Set a frame's status to list it." = "まだ何もない。フレームのステータスを設定すると一覧に表示される。" +"Nothing to export" = "書き出すものがない" +"Now" = "現在" +"Nudge (Shift: big nudge)" = "微調整(Shift:大きく微調整)" +"Nudge amount" = "微調整の量" +"Number" = "数値" +"Numbered list" = "番号付きリスト" +"Object" = "オブジェクト" +"Off" = "オフ" +"Offered first when filling the slot (any content is allowed)" = "スロットを埋めるときに最初に提示(どのコンテンツも使用可)" +"Offered first when swapping the instance (any component is allowed)" = "インスタンスを入れ替えるときに最初に提示(どのコンポーネントも使用可)" +"Offset" = "オフセット" +"On click" = "クリック時" +"On drag" = "ドラッグ時" +"On the server's machine, `figcraft-server key` prints it." = "サーバーのマシンで `figcraft-server key` を実行すると表示される。" +"On this page" = "このページ" +"Only the first changed layers are listed." = "変更されたレイヤーは最初の分のみ表示。" +"Only the first {n} changed layers are listed." = "変更されたレイヤーは最初の {n} 個のみ表示。" +"Only this computer can join (turn on network sharing to invite others)." = "このコンピューターのみ参加可能(他の人を招待するにはネットワーク共有をオンにする)。" +"Only your threads" = "自分のスレッドのみ" +"Opacity" = "不透明度" +"Opacity & blend" = "不透明度とブレンド" +"Opacity 10%…90%, 0: 100%" = "不透明度 10%…90%、0:100%" +"Open" = "開く" +"Open .figcraft, .svg or images" = ".figcraft、.svg、画像を開く" +"Open branch" = "ブランチを開く" +"Open file" = "ファイルを開く" +"Open files" = "開いているファイル" +"Open in focus view" = "フォーカスビューで開く" +"Open in new window" = "新しいウィンドウで開く" +"Open invite links in FigCraft" = "招待リンクを FigCraft で開く" +"Open link" = "リンクを開く" +"Open link {url}" = "リンク {url} を開く" +"Open overlay" = "オーバーレイを開く" +"Open prototype preview" = "プロトタイプのプレビューを開く" +"Open variables ({count})" = "変数を開く({count})" +"Opened “{name}” in a new tab" = "「{name}」を新しいタブで開いた" +"Open|comments" = "未解決" +"Options" = "オプション" +"Or keep the file on a FigCraft server and share links to edit or to view it." = "または、ファイルを FigCraft サーバーに置いて、編集用または閲覧用のリンクを共有。" +"Orange" = "オレンジ" +"Outline stroke" = "線のアウトライン化" +"Outline text" = "テキストのアウトライン化" +"Outlines" = "アウトライン" +"Outside" = "外側" +"Overflow" = "はみ出し" +"Overlay" = "オーバーレイ" +"Overlay position" = "オーバーレイの位置" +"Overridden here (the collection it extends has another value)" = "ここで上書き(拡張元のコレクションには別の値がある)" +"Overrides" = "オーバーライド" +"PDF print options" = "PDF 印刷オプション" +"PDF print settings" = "PDF 印刷設定" +"Padding" = "パディング" +"Page" = "ページ" +"Pages" = "ページ" +"Pages: {pages}" = "ページ:{pages}" +"Paint bucket" = "塗りつぶし" +"Pan the canvas" = "キャンバスをパン" +"Panels" = "パネル" +"Paper" = "紙" +"Paragraph indent" = "段落インデント" +"Paragraph indent applies to left-aligned text" = "段落インデントは左揃えのテキストに適用" +"Paragraph spacing" = "段落間隔" +"Pass through" = "通過" +"Paste a link (https://…)" = "リンクを貼り付け(https://…)" +"Paste a team library link (a view link)" = "チームライブラリのリンク(閲覧リンク)を貼り付け" +"Paste here" = "ここに貼り付け" +"Paste the invite link the host shared with you." = "ホストから共有された招待リンクを貼り付ける。" +"Paste to replace" = "貼り付けて置換" +"Pattern" = "パターン" +"Pattern alignment" = "パターンの配置" +"Pattern scale" = "パターンの拡大縮小" +"Pattern source" = "パターンのソース" +"Pen" = "ペン" +"Pencil" = "鉛筆" +"People in this file" = "このファイルにいるユーザー" +"Phone" = "スマートフォン" +"Pick color" = "色を抽出" +"Pick color (I)" = "色を抽出(I)" +"Pick one font family first" = "先にフォントファミリーを 1 つ選択" +"Pin a property" = "プロパティを固定" +"Pinch" = "すぼめる" +"Pixel grid" = "ピクセルグリッド" +"Pixel preview 1x" = "ピクセルプレビュー 1x" +"Pixel preview 2x" = "ピクセルプレビュー 2x" +"Place automatically" = "自動で配置" +"Place image" = "画像を配置" +"Plugins" = "プラグイン" +"Plus darker" = "プラス(暗)" +"Plus lighter" = "プラス(明)" +"Point" = "ポイント" +"Points" = "ポイント" +"Polygon" = "多角形" +"Polygons" = "多角形" +"Position" = "位置" +"Post" = "投稿" +"Preferences" = "環境設定" +"Preferred" = "優先" +"Present" = "プレゼンテーション" +"Present or preview" = "プレゼンテーションまたはプレビュー" +"Present this flow" = "このフローをプレゼンテーション" +"Presentation" = "プレゼンテーション" +"Preserve scroll position" = "スクロール位置を保持" +"Presets" = "プリセット" +"Press a key…" = "キーを押す…" +"Preview" = "プレビュー" +"Preview this flow" = "このフローをプレビュー" +"Preview this frame" = "このフレームをプレビュー" +"Previous ready for dev" = "前の開発準備完了" +"Progressive" = "プログレッシブ" +"Properties" = "プロパティ" +"Prototype" = "プロトタイプ" +"Prototype preview" = "プロトタイプのプレビュー" +"Prototype settings" = "プロトタイプの設定" +"Publish" = "公開" +"Publish changes" = "変更を公開" +"Publish to server" = "サーバーに公開" +"Publish to server…" = "サーバーに公開…" +"Published version {v}" = "バージョン {v} を公開済み" +"Published version {v} to the server" = "バージョン {v} をサーバーに公開済み" +"Published version {v}: save the file so other files can use it" = "バージョン {v} を公開済み:他のファイルで使えるようにファイルを保存" +"Published · {people}" = "公開済み · {people}" +"Publishing to a server needs the desktop app; in the browser you can join a server's files" = "サーバーへの公開にはデスクトップアプリが必要。ブラウザーではサーバーのファイルに参加できる" +"Publishing…" = "公開中…" +"Push" = "プッシュ" +"Push changes to main component" = "変更をメインコンポーネントにプッシュ" +"Put text on path" = "テキストをパスに沿わせる" +"Radial" = "放射状" +"Radius" = "半径" +"Ratio" = "比率" +"Reading the library…" = "ライブラリを読み込み中…" +"Ready for dev" = "開発準備完了" +"Real name" = "本名" +"Recent" = "最近" +"Recent files" = "最近のファイル" +"Recents" = "最近使った項目" +"Recovered {n} unsaved files after the app quit unexpectedly: save them to keep them" = { other = "アプリが予期せず終了したため、未保存のファイルを {n} 個復元:残すには保存" } +"Rectangle" = "長方形" +"Rectangles" = "長方形" +"Red" = "赤" +"Reduce motion" = "動きを減らす" +"Refraction" = "屈折" +"Remove" = "削除" +"Remove all" = "すべて削除" +"Remove annotation" = "注釈を削除" +"Remove auto layout" = "オートレイアウトを解除" +"Remove dev resource" = "開発リソースを削除" +"Remove export setting" = "書き出し設定を削除" +"Remove guide" = "ガイドを削除" +"Remove interaction" = "インタラクションを削除" +"Remove library from this file" = "このファイルからライブラリを削除" +"Remove min and max" = "最小と最大を削除" +"Remove min and max height" = "最小と最大の高さを削除" +"Remove min and max width" = "最小と最大の幅を削除" +"Remove regions" = "領域を削除" +"Remove slot" = "スロットを削除" +"Remove starting point" = "開始点を削除" +"Remove stop" = "カラー分岐点を削除" +"Remove text from path" = "テキストをパスから外す" +"Remove the else and its actions" = "「それ以外」とそのアクションを削除" +"Remove this condition and its actions" = "この条件とそのアクションを削除" +"Removed" = "削除" +"Removed since it was marked" = "マーク後に削除" +"Rename" = "名前を変更" +"Rename duplicated layers" = "複製したレイヤーの名前を変更" +"Rename folder" = "フォルダー名を変更" +"Rename group" = "グループ名を変更" +"Rename mode" = "モード名を変更" +"Rename page" = "ページ名を変更" +"Replace all" = "すべて置換" +"Replace mixed export settings" = "混在した書き出し設定を置き換え" +"Replace with" = "置換後の文字列" +"Replace with a new interaction" = "新しいインタラクションで置き換え" +"Reply" = "返信" +"Reset" = "リセット" +"Reset adjustments" = "調整をリセット" +"Reset all changes" = "すべての変更をリセット" +"Reset all overrides on this layer" = "このレイヤーのすべてのオーバーライドをリセット" +"Reset overrides" = "オーバーライドをリセット" +"Reset slot" = "スロットをリセット" +"Reset this override" = "このオーバーライドをリセット" +"Reset to style" = "スタイルにリセット" +"Reset to the inherited value" = "継承された値にリセット" +"Resize by the nudge amount" = "微調整の量でサイズ変更" +"Resize frames to the device's screen (or the window without a device): their constraints and auto layout respond" = "フレームをデバイスの画面(デバイスなしの場合はウィンドウ)に合わせてサイズ変更:制約とオートレイアウトが反応" +"Resize to fit" = "サイズを合わせる" +"Resolve" = "解決" +"Resolve change" = "変更を解決" +"Resolved" = "解決済み" +"Resources" = "リソース" +"Responsive" = "レスポンシブ" +"Restart" = "再起動" +"Restore" = "復元" +"Restore main component" = "メインコンポーネントを復元" +"Restore this version" = "このバージョンを復元" +"Restored “{name}”" = "「{name}」を復元済み" +"Reverse the order" = "順序を反転" +"Reversed triangle" = "逆三角形" +"Review and merge" = "レビューしてマージ" +"Ribbon" = "リボン" +"Right" = "右" +"Right side" = "右側" +"Right side width" = "右側の幅" +"Rotate 90°" = "90° 回転" +"Rotate 90° right" = "右に 90° 回転" +"Rotate to landscape" = "横向きに回転" +"Rotate to portrait" = "縦向きに回転" +"Rotation" = "回転" +"Rotation jitter" = "回転のばらつき" +"Round" = "丸型" +"Rounded" = "丸型" +"Row" = "行" +"Row gap" = "行の間隔" +"Row sizes" = "行のサイズ" +"Row span" = "行の範囲" +"Rows" = "行" +"Rows {count}" = "行 {count}" +"Rulers" = "定規" +"Run" = "実行" +"Run {label}" = "{label}を実行" +"Same as layer" = "レイヤーと同じ" +"Saturation" = "彩度" +"Save" = "保存" +"Save as" = "名前を付けて保存" +"Save as preset…" = "プリセットとして保存…" +"Save version {key}" = "バージョンを保存 {key}" +"Saved" = "保存済み" +"Saved {name}" = "{name} を保存済み" +"Scale" = "拡大縮小" +"Scatter" = "散布" +"Scoping: where pickers offer it" = "スコープ:ピッカーで提示される場所" +"Screen" = "スクリーン" +"Scroll behavior" = "スクロール動作" +"Scroll to" = "スクロール先" +"Scroll to layer" = "レイヤーまでスクロール" +"Scroll with parent" = "親と一緒にスクロール" +"Search" = "検索" +"Search actions, layers and tools" = "アクション、レイヤー、ツールを検索" +"Search assets" = "アセットを検索" +"Search comments" = "コメントを検索" +"Search fonts" = "フォントを検索" +"Search layers" = "レイヤーを検索" +"Search shortcuts" = "ショートカットを検索" +"Section" = "セクション" +"Section color" = "セクションの色" +"Sections" = "セクション" +"Select a frame and add a starting point to present it as a flow." = "フレームを選択して開始点を追加すると、フローとしてプレゼンテーションできる。" +"Select a frame to preview it" = "フレームを選択するとプレビュー" +"Select a layer to see its properties and code" = "レイヤーを選択するとプロパティとコードを表示" +"Select all" = "すべて選択" +"Select all with same" = "同じ項目をすべて選択" +"Select layer" = "レイヤーを選択" +"Select layers to apply the style to" = "スタイルを適用するレイヤーを選択" +"Select overlapping shapes" = "重なったシェイプを選択" +"Select points to edit their position, radius and mirroring" = "ポイントを選択すると位置、半径、対称を編集できる" +"Select slot" = "スロットを選択" +"Selection" = "選択範囲" +"Selection box, {w} by {h} at {x}, {y}: arrows move it, Shift+arrows size it, Enter selects, Escape cancels" = "選択ボックス、{w} × {h}、位置 {x}, {y}:矢印キーで移動、Shift+矢印キーでサイズ変更、Enter で選択、Escape でキャンセル" +"Selection box: arrows move it, Shift+arrows size it, Enter selects, Escape cancels" = "選択ボックス:矢印キーで移動、Shift+矢印キーでサイズ変更、Enter で選択、Escape でキャンセル" +"Send backward" = "背面へ" +"Send to back" = "最背面へ" +"Server address" = "サーバーのアドレス" +"Set as default" = "デフォルトに設定" +"Set variable" = "変数を設定" +"Set variable mode" = "変数モードを設定" +"Set variable {name}" = "変数 {name} を設定" +"Set {name} to {value}" = "{name} を {value} に設定" +"Shadows" = "シャドウ" +"Shape" = "シェイプ" +"Shape builder" = "シェイプビルダー" +"Shape tools" = "シェイプツール" +"Share" = "共有" +"Share on the local network" = "ローカルネットワークで共有" +"Share: live session, export" = "共有:ライブセッション、書き出し" +"Show" = "表示" +"Show as grid" = "グリッドで表示" +"Show as list" = "リストで表示" +"Show autosaves" = "自動保存を表示" +"Show behind transparent areas" = "透明部分の背後に表示" +"Show comments (Shift+C)" = "コメントを表示(Shift+C)" +"Show device frame" = "デバイスフレームを表示" +"Show dimensions on objects" = "オブジェクトに寸法を表示" +"Show hotspot hints" = "ホットスポットのヒントを表示" +"Show only this on the canvas" = "キャンバスにこれだけを表示" +"Show open" = "未解決を表示" +"Show section contents" = "セクションのコンテンツを表示" +"Show this layer" = "このレイヤーを表示" +"Show usage" = "使用状況を表示" +"Show/Hide" = "表示/非表示" +"Show/Hide UI" = "UI の表示/非表示" +"Side by side" = "左右に並べて表示" +"Sidebar" = "サイドバー" +"Simplify stroke" = "線を単純化" +"Size" = "サイズ" +"Size jitter" = "サイズのばらつき" +"Skip ink" = "ディセンダーを避ける" +"Slashed zero" = "スラッシュ付きゼロ" +"Slice" = "スライス" +"Slices" = "スライス" +"Slide in" = "スライドイン" +"Slide out" = "スライドアウト" +"Slot" = "スロット" +"Slot content" = "スロットのコンテンツ" +"Small capitals" = "スモールキャピタル" +"Small caps" = "スモールキャップ" +"Smart animate" = "スマートアニメート" +"Snap to pixel grid" = "ピクセルグリッドにスナップ" +"Social media" = "ソーシャルメディア" +"Soft light" = "ソフトライト" +"Solid" = "実線" +"Some variants have the same property values: give each one a unique combination" = "同じプロパティ値を持つバリアントがある:それぞれ固有の組み合わせにする" +"Sort" = "並べ替え" +"Sort by date" = "日付で並べ替え" +"Sort by page" = "ページで並べ替え" +"Space around" = "周囲に均等配置" +"Space between" = "間に均等配置" +"Space drag" = "Space ドラッグ" +"Space evenly" = "均等に配置" +"Space+drag" = "Space+ドラッグ" +"Spacing" = "間隔" +"Splay" = "広がり" +"Spread" = "スプレッド" +"Square" = "正方形" +"Standard" = "標準" +"Standard ligatures" = "標準合字" +"Star" = "星" +"Stars" = "星" +"Start" = "開始" +"Start from a blank canvas" = "空白のキャンバスから始める" +"Start live session" = "ライブセッションを開始" +"Start on path" = "パス上の開始位置" +"Start point" = "始点" +"Status" = "ステータス" +"Sticky" = "固定" +"Stop following {name}" = "{name} のフォローを停止" +"Stop session" = "セッションを停止" +"Stop {n} {hex}" = "分岐点 {n} {hex}" +"Stretch" = "伸縮" +"Strikethrough" = "取り消し線" +"String" = "文字列" +"Stroke" = "線" +"Stroke style" = "線のスタイル" +"Stroke weight" = "線の太さ" +"Strokes" = "線" +"Style" = "スタイル" +"Styles" = "スタイル" +"Stylistic set 1" = "スタイルセット 1" +"Stylistic set 2" = "スタイルセット 2" +"Stylistic set 3" = "スタイルセット 3" +"Stylistic set 4" = "スタイルセット 4" +"Stylistic set 5" = "スタイルセット 5" +"Subtract" = "型抜き" +"Subtracts" = "型抜き" +"Suffix" = "サフィックス" +"Swap instance" = "インスタンスを入れ替え" +"Swap library: use another library's assets of the same names" = "ライブラリを入れ替え:同じ名前の別のライブラリのアセットを使用" +"Swap orientation" = "向きを入れ替え" +"Swap overlay" = "オーバーレイを入れ替え" +"Swap to {name}" = "{name} に入れ替え" +"Swap width and height" = "幅と高さを入れ替え" +"Swapped instance" = "入れ替えたインスタンス" +"Swapped {n} assets" = { other = "{n} 個のアセットを入れ替え済み" } +"Swapped {n} assets; {missed} had no match and still use the old library" = { other = "{n} 個のアセットを入れ替え済み。{missed} 個は一致するものがなく、古いライブラリのまま" } +"Sweep" = "範囲" +"System" = "システム" +"Tab / Shift+Tab" = "Tab / Shift+Tab" +"Table" = "表" +"Tablet" = "タブレット" +"Tabular numbers" = "等幅数字" +"Take the values from the first selected layer" = "最初に選択したレイヤーの値を使用" +"Taper" = "先細り" +"Taper both ends" = "両端を先細り" +"Temperature" = "色温度" +"Template" = "テンプレート" +"Text" = "テキスト" +"Text align" = "テキストの配置" +"Text content" = "テキストの内容" +"Text style" = "テキストスタイル" +"Text styles" = "テキストスタイル" +"Texts" = "テキスト" +"Texture" = "テクスチャ" +"The canvas previews colors in sRGB; exported PNG, JPG and WebP files are tagged Display P3." = "キャンバスは sRGB で色をプレビュー。書き出した PNG、JPG、WebP ファイルには Display P3 のタグが付く。" +"The file now holds another library" = "このファイルは別のライブラリになっている" +"The file now holds another library (\"{name}\")" = "このファイルは別のライブラリ(「{name}」)になっている" +"The link carries the session's secret: share it only with people you invite." = "リンクにはセッションの秘密情報が含まれる:招待する人とだけ共有すること。" +"The selection uses several text styles: click to apply one" = "選択範囲に複数のテキストスタイルが使われている:クリックして 1 つを適用" +"Theme" = "テーマ" +"There's no destination for that action" = "そのアクションの遷移先がない" +"Thickness" = "太さ" +"This branch can't be reviewed: {e}" = "このブランチはレビューできない:{e}" +"This branch was merged or archived." = "このブランチはマージまたはアーカイブ済み。" +"This condition is edited as an expression" = "この条件は式として編集されている" +"This file" = "このファイル" +"This file has unsaved changes" = "このファイルには未保存の変更がある" +"This frame is new on the branch." = "このフレームはブランチで新規作成。" +"This frame isn't on the branch." = "このフレームはブランチにない。" +"Tidy up" = "整列" +"Tile" = "タイル" +"Tile type" = "タイルの種類" +"Tint" = "ティント" +"Title" = "タイトル" +"Title case" = "タイトルケース" +"To share this library with your team, publish the file to a server (Share ▸ Publish to server…), then publish the library there." = "このライブラリをチームと共有するには、ファイルをサーバーに公開し(共有 ▸ サーバーに公開…)、そこでライブラリを公開する。" +"Toggle" = "切り替え" +"Toggle light/dark theme" = "ライト/ダークテーマを切り替え" +"Toggle visibility" = "表示を切り替え" +"Tools" = "ツール" +"Top" = "上" +"Top & bottom" = "上下" +"Top left radius" = "左上の半径" +"Top right radius" = "右上の半径" +"Transform" = "変形" +"Triangle arrow" = "三角矢印" +"Trigger" = "トリガー" +"True" = "true" +"Truncate text" = "テキストを切り詰める" +"Truncate with an ellipsis" = "省略記号で切り詰める" +"Try another search or filter." = "別の検索語やフィルターを試す。" +"Two digits" = "2 桁" +"Type" = "種類" +"Type settings" = "文字の設定" +"Typography" = "タイポグラフィ" +"Underline" = "下線" +"Undo takes back only your own changes; what others changed since stays." = "取り消しで戻るのは自分の変更のみ。その後に他の人が加えた変更は残る。" +"Ungroup" = "グループ解除" +"Uniform" = "均一" +"Union" = "合体" +"Unions" = "合体" +"Unknown — treated as sRGB" = "不明(sRGB として扱う)" +"Unread" = "未読" +"Unresolve" = "未解決に戻す" +"Unsaved changes" = "未保存の変更" +"Unsaved changes in {names}. Close the window and lose them?" = "{names} に未保存の変更がある。ウィンドウを閉じて変更を破棄する?" +"Unsaved changes: save first ({save}), or close the tab with {alt}-click to discard" = "未保存の変更:先に保存する({save})か、{alt}-クリックでタブを閉じて破棄" +"Unsaved changes: save first, or close again with {key} to discard" = "未保存の変更:先に保存するか、もう一度 {key} で閉じて破棄" +"Up" = "上" +"Update" = "更新" +"Update from main" = "メインから更新" +"Update from selection" = "選択範囲から更新" +"Updated {components} and {styles}" = "{components}と{styles}を更新済み" +"Uploads this file to a FigCraft server and keeps this tab in sync with it. You get a link to edit and a link to view." = "このファイルを FigCraft サーバーにアップロードし、このタブを同期した状態に保つ。編集用リンクと閲覧用リンクが発行される。" +"Uppercase" = "大文字" +"Use a fixed value" = "固定値を使用" +"Use an expression, e.g. count + 1" = "式を使用(例:count + 1)" +"Use as mask" = "マスクとして使用" +"Use auto layout" = "オートレイアウトを使用" +"Use number keys for opacity" = "数字キーで不透明度を変更" +"Use the layer's fill" = "レイヤーの塗りを使用" +"Used in {files} · {instances}" = "{files}で使用 · {instances}" +"Username" = "ユーザー名" +"Value" = "値" +"Variable" = "変数" +"Variable collections" = "変数コレクション" +"Variable modes" = "変数モード" +"Variable width" = "可変幅" +"Variables" = "変数" +"Variables JSON…" = "変数 JSON…" +"Variables store reusable values (colours, numbers, strings, booleans) with modes such as Light and Dark." = "変数には再利用できる値(カラー、数値、文字列、ブーリアン)を保存でき、ライトやダークなどのモードを持たせられる。" +"Variant" = "バリアント" +"Vector" = "ベクター" +"Vectors" = "ベクター" +"Version" = "バージョン" +"Version history" = "バージョン履歴" +"Version {version}" = "バージョン {version}" +"Version {v} · {components} · {styles} · {variables}" = "バージョン {v} · {components} · {styles} · {variables}" +"Vertical" = "垂直" +"Vertical align" = "垂直方向の配置" +"Vertical hex" = "縦向き六角形" +"Vertical padding" = "上下のパディング" +"Vertical spacing" = "垂直方向の間隔" +"Vertical trim" = "上下の余白を詰める" +"View" = "表示" +"View link" = "閲覧リンク" +"View link copied" = "閲覧リンクをコピー済み" +"View only" = "閲覧のみ" +"View only: you see every change as it happens but can't edit. Leave to keep a copy you can edit." = "閲覧のみ:すべての変更をリアルタイムで見られるが、編集はできない。退出すると編集可能なコピーが残る。" +"Viewing “{name}”" = "「{name}」を表示中" +"Violet" = "紫" +"Visibility" = "表示" +"Visible" = "表示" +"Vivid" = "ビビッド" +"Warm" = "ウォーム" +"Watch" = "ウォッチ" +"Wavy" = "波線" +"Web" = "Web" +"WebSocket URL" = "WebSocket URL" +"WebSocket URL copied" = "WebSocket URL をコピー済み" +"Wedge" = "くさび" +"Weight" = "太さ" +"What changed since it was marked ready for dev" = "開発準備完了にしてからの変更内容" +"What it's for" = "用途" +"What this changed from isn't known: it changed before FigCraft kept a copy of ready-for-dev frames. Resolve the change (or mark it ready again) to compare from now on." = "変更前の状態は不明:FigCraft が開発準備完了フレームのコピーを保存するようになる前に変更された。変更を解決する(または再度準備完了にする)と、今後はそこから比較する。" +"While hovering" = "ホバー中" +"While pressing" = "押している間" +"White" = "白" +"Why it changed" = "変更理由" +"Width" = "幅" +"Width point" = "幅のポイント" +"Width profile" = "幅プロファイル" +"With the layers' export settings" = "レイヤーの書き出し設定で" +"Wrap" = "折り返し" +"Wrap in new section" = "新しいセクションで囲む" +"Yellow" = "黄" +"Yesterday" = "昨日" +"You" = "自分" +"You'll get the host's file as a new tab and edit it together." = "ホストのファイルが新しいタブで開き、一緒に編集できる。" +"Your copy of the file stays open" = "あなたのファイルのコピーは開いたまま" +"Your name" = "あなたの名前" +"Your name in comments" = "コメントに表示する名前" +"Your system asks for reduced motion: animations stay off." = "システムで動きを減らす設定がオンのため、アニメーションはオフのまま。" +"Zoom" = "ズーム" +"Zoom around the pointer" = "ポインターを中心にズーム" +"Zoom device to fill window" = "デバイスをウィンドウいっぱいにズーム" +"Zoom in" = "ズームイン" +"Zoom out" = "ズームアウト" +"Zoom to 100%" = "100% にズーム" +"Zoom to 200%" = "200% にズーム" +"Zoom to 50%" = "50% にズーム" +"Zoom to fit" = "全体表示" +"Zoom to selection" = "選択範囲にズーム" +"Zoom tool: click to zoom in, drag an area" = "ズームツール:クリックでズームイン、ドラッグで範囲を指定" +"Zoom tool: zoom out" = "ズームツール:ズームアウト" +"and {n} more" = { other = "ほか {n} 件" } +"bleed marks" = "裁ち落としトンボ" +"can edit the document" = "ドキュメントを編集できる" +"crop marks" = "トンボ" +"development: {path}" = "開発:{path}" +"e.g. count + 1" = "例:count + 1" +"e.g. count >= 3 and not done" = "例:count >= 3 and not done" +"figcraft:// links from a browser, chat or email open this app and join the session." = "ブラウザー、チャット、メールからの figcraft:// リンクでこのアプリが開き、セッションに参加する。" +"hidden" = "非表示" +"iOS" = "iOS" +"locked" = "ロック中" +"no bleed" = "裁ち落としなし" +"nobody else here yet" = "まだ他に誰もいない" +"now" = "たった今" +"or" = "または" +"reads the document" = "ドキュメントを読み取る" +"the plugin" = "このプラグイン" +"this session only" = "このセッションのみ" +"{instances} in {files}" = "{files}内の{instances}" +"{language}: draft translation, waiting for a native speaker's review." = "{language}:下書きの翻訳。ネイティブスピーカーによるレビュー待ち。" +"{length} bleed" = "裁ち落とし {length}" +"{name}\nClick to apply to the selection" = "{name}\nクリックして選択範囲に適用" +"{name}\nDrag onto the canvas, or click to place in the middle of the view.\nHold Alt (Option) while dropping onto an instance to swap it." = "{name}\nキャンバスにドラッグするか、クリックしてビューの中央に配置。\nインスタンスの上にドロップするときに Alt(Option)を押したままにすると入れ替え。" +"{name} (from {library})" = "{name}({library} から)" +"{name} (you)" = "{name}(自分)" +"{name} ({layers} layers)" = "{name}({layers} 個のレイヤー)" +"{name} ({tag}): {min} – {max}, default {default}. Double-click the slider to go back to the style's value; Escape while dragging cancels." = "{name}({tag}):{min} – {max}、デフォルト {default}。スライダーをダブルクリックするとスタイルの値に戻る。ドラッグ中に Escape でキャンセル。" +"{name} from {path}" = "{path} の {name}" +"{name} · deleted on main" = "{name} · メインで削除" +"{name} · deleted on the branch" = "{name} · ブランチで削除" +"{name} · not published" = "{name} · 未公開" +"{name} · on a server" = "{name} · サーバー上" +"{name} · published version {v}" = "{name} · 公開バージョン {v}" +"{name} · version {v} on the server" = "{name} · サーバー上のバージョン {v}" +"{name}, {kind}, {w} by {h}, selected" = "{name}、{kind}、{w} × {h}、選択中" +"{n} added" = { other = "{n} 件追加" } +"{n} autosave versions" = { other = "自動保存バージョン {n} 件" } +"{n} changed" = { other = "{n} 件変更" } +"{n} columns" = { other = "{n} 列" } +"{n} components" = { other = "{n} 個のコンポーネント" } +"{n} components and styles have newer versions" = { other = "{n} 個のコンポーネントとスタイルに新しいバージョンあり" } +"{n} conflicts to resolve" = { other = "解決が必要な競合 {n} 件" } +"{n} days ago" = { other = "{n} 日前" } +"{n} files" = { other = "{n} 個のファイル" } +"{n} hours ago" = { other = "{n} 時間前" } +"{n} instances" = { other = "{n} 個のインスタンス" } +"{n} layers" = { other = "{n} 個のレイヤー" } +"{n} layers as one file" = { other = "{n} 個のレイヤーを 1 つのファイルに" } +"{n} layers selected" = { other = "{n} 個のレイヤーを選択中" } +"{n} layers · {parts}" = { other = "{n} 個のレイヤー · {parts}" } +"{n} matches" = { other = "{n} 件一致" } +"{n} minutes ago" = { other = "{n} 分前" } +"{n} months ago" = { other = "{n} か月前" } +"{n} of {total}" = "{n} / {total}" +"{n} people joined" = { other = "{n} 人が参加済み" } +"{n} preferred components" = { other = "優先コンポーネント {n} 個" } +"{n} ready" = { other = "{n} 件準備完了" } +"{n} removed" = { other = "{n} 件削除" } +"{n} replies" = { other = "{n} 件の返信" } +"{n} rows" = { other = "{n} 行" } +"{n} styles" = { other = "{n} 個のスタイル" } +"{n} variables" = { other = "{n} 個の変数" } +"{n} weeks ago" = { other = "{n} 週間前" } +"{n} years ago" = { other = "{n} 年前" } +"{n}d" = "{n}日" +"{n}h" = "{n}時間" +"{n}m" = "{n}分" +"{n}w" = "{n}週" +"{page}, nothing selected" = "{page}、選択なし" +"{profile} (current)" = "{profile}(現在)" +"{property} is its value; {property ? \"a\" : \"b\"} picks a string. Other {…} stays as written." = "{property} はその値になり、{property ? \"a\" : \"b\"} は文字列を選ぶ。それ以外の {…} は記述どおりに残る。" +"{tool} hold {key}" = "{tool} {key} を長押し" +"{value} isn't a colour" = "{value} はカラーではない" +"{when} · edited" = "{when} · 編集済み" +"← ↑ → ↓" = "← ↑ → ↓" +"⇥ / ⇧⇥" = "⇥ / ⇧⇥" +"⌘ arrows" = "⌘ 矢印キー" +"⌘ click" = "⌘ クリック" +"⌘ scroll" = "⌘ スクロール" +"⌥ drag" = "⌥ ドラッグ" + +[commands] +"align.bottom" = "下揃え" +"align.hcenter" = "水平方向の中央揃え" +"align.left" = "左揃え" +"align.right" = "右揃え" +"align.top" = "上揃え" +"align.vcenter" = "垂直方向の中央揃え" +"annotation.add" = "注釈を追加" +"annotation.addCategory" = "注釈カテゴリを追加" +"annotation.categories" = "注釈カテゴリ" +"annotation.edit" = "注釈を編集" +"annotation.editCategory" = "注釈カテゴリを編集" +"annotation.list" = "注釈を一覧表示" +"annotation.remove" = "注釈を削除" +"annotation.removeCategory" = "注釈カテゴリを削除" +"app.actions" = "アクション" +"app.preferences" = "環境設定" +"arrange.back" = "最背面へ" +"arrange.backward" = "背面へ" +"arrange.forward" = "前面へ" +"arrange.front" = "最前面へ" +"arrange.packH" = "水平方向に詰める" +"arrange.packV" = "垂直方向に詰める" +"arrange.roundToPixels" = "ピクセルに丸める" +"arrange.tidy" = "整列" +"bool.exclude" = "選択範囲を除外" +"bool.flatten" = "ブーリアンを平坦化" +"bool.intersect" = "選択範囲を交差" +"bool.subtract" = "選択範囲で型抜き" +"bool.union" = "選択範囲を合体" +"branch.archive" = "ブランチをアーカイブ" +"branch.create" = "ブランチを作成" +"branch.list" = "ブランチを一覧表示" +"branch.merge" = "ブランチをマージ" +"branch.open" = "ブランチを開く" +"branch.review" = "ブランチをレビュー" +"branch.updateFromMain" = "メインから更新" +"codeConnect.export" = "コード接続を書き出し" +"codeConnect.import" = "コード接続をインポート" +"codeConnect.remove" = "コードとの接続を解除" +"codeConnect.set" = "コードに接続" +"collab.cursor" = "カーソルの位置を表示" +"collab.diff" = "同期した変更を表示" +"collab.follow" = "フォロー" +"collab.host" = "ライブセッションを開始" +"collab.join" = "ライブセッションに参加" +"collab.leave" = "ライブセッションから退出" +"collab.peers" = "このファイルにいるユーザー" +"collab.publish" = "サーバーに公開" +"collab.registerLinks" = "招待リンクを FigCraft で開く" +"collab.stop" = "ライブセッションを停止" +"command.batch" = "複数のコマンドを実行" +"comment.add" = "コメントを追加" +"comment.delete" = "コメントを削除" +"comment.edit" = "コメントを編集" +"comment.link" = "コメントへのリンクをコピー" +"comment.list" = "コメントを一覧表示" +"comment.markRead" = "コメントを既読にする" +"comment.move" = "コメントを移動" +"comment.next" = "次のコメント" +"comment.open" = "コメントを開く" +"comment.people" = "コメントのユーザー" +"comment.react" = "コメントにリアクション" +"comment.reply" = "コメントに返信" +"comment.resolve" = "コメントを解決" +"comment.zoom" = "コメントにズーム" +"component.addProperty" = "コンポーネントプロパティを追加" +"component.addVariant" = "バリアントを追加" +"component.bindProperty" = "レイヤーをプロパティに割り当て" +"component.combineVariants" = "バリアントとして結合" +"component.create" = "コンポーネントを作成" +"component.createMultiple" = "複数のコンポーネントを作成" +"component.deleteProperty" = "コンポーネントプロパティを削除" +"component.detach" = "インスタンスを切り離す" +"component.editProperty" = "コンポーネントプロパティを編集" +"component.exposeInstance" = "ネストされたインスタンスを公開" +"component.goToMain" = "メインコンポーネントへ移動" +"component.list" = "コンポーネントを一覧表示" +"component.makeSlot" = "スロットにする" +"component.properties" = "コンポーネントプロパティ" +"component.pushChanges" = "変更をメインコンポーネントにプッシュ" +"component.removeSlot" = "スロットを削除" +"component.resetInstance" = "すべての変更をリセット" +"component.resetOverride" = "オーバーライドをリセット" +"component.restoreMain" = "メインコンポーネントを復元" +"dev.compare" = "変更を比較" +"dev.focus" = "フォーカスビュー" +"dev.resolveChange" = "変更を解決" +"dev.unfocus" = "フォーカスビューを終了" +"devResource.add" = "開発リソースを追加" +"devResource.edit" = "開発リソースを編集" +"devResource.list" = "開発リソースを一覧表示" +"devResource.remove" = "開発リソースを削除" +"distribute.horizontal" = "水平方向に等間隔に分布" +"distribute.vertical" = "垂直方向に等間隔に分布" +"doc.home" = "ホーム" +"doc.list" = "ドキュメントを一覧表示" +"doc.nextTab" = "次のタブ" +"doc.previousTab" = "前のタブ" +"doc.switch" = "ドキュメントを切り替え" +"edit.copy" = "コピー" +"edit.copyAsCss" = "CSS としてコピー" +"edit.copyAsPng" = "PNG としてコピー" +"edit.copyAsSvg" = "SVG としてコピー" +"edit.copyAsText" = "テキストとしてコピー" +"edit.copyLink" = "選択範囲へのリンクをコピー" +"edit.copyProperties" = "プロパティをコピー" +"edit.cut" = "カット" +"edit.delete" = "削除" +"edit.duplicate" = "複製" +"edit.findReplace" = "検索と置換" +"edit.paste" = "貼り付け" +"edit.pasteOver" = "選択範囲の上に貼り付け" +"edit.pasteProperties" = "プロパティを貼り付け" +"edit.pasteReplace" = "貼り付けて置換" +"edit.pickColor" = "色を抽出" +"edit.redo" = "やり直す" +"edit.repeat" = "最後のコマンドを繰り返す" +"edit.setDefaultProperties" = "デフォルトのプロパティを設定" +"edit.undo" = "取り消す" +"effect.add" = "エフェクトを追加" +"effect.move" = "エフェクトを移動" +"effect.remove" = "エフェクトを削除" +"effect.set" = "エフェクトを設定" +"export.add" = "書き出し設定を追加" +"export.remove" = "書き出し設定を削除" +"export.update" = "書き出し設定を編集" +"file.close" = "タブを閉じる" +"file.colorProfile" = "カラープロファイル" +"file.duplicate" = "ファイルを複製" +"file.export" = "書き出し" +"file.exportFramesPdf" = "フレームを PDF に書き出し" +"file.exportLayers" = "レイヤーを書き出し" +"file.exportSvg" = "選択範囲を SVG で書き出し" +"file.import" = "インポート" +"file.new" = "新規デザインファイル" +"file.open" = "開く" +"file.openRecent" = "最近使ったファイルを開く" +"file.placeImage" = "画像を配置" +"file.recover" = "ファイルを復元" +"file.rename" = "ファイル名を変更" +"file.revert" = "保存した状態に戻す" +"file.save" = "保存" +"file.saveAs" = "名前を付けて保存" +"file.saveVersion" = "バージョン履歴に保存" +"file.versionHistory" = "バージョン履歴を表示" +"fill.add" = "塗りを追加" +"fill.move" = "塗りを移動" +"fill.pattern" = "パターンの塗り" +"fill.remove" = "塗りを削除" +"fill.set" = "塗りを設定" +"frame.create" = "フレームを作成" +"frame.presets" = "フレームのプリセットを一覧表示" +"frame.swapOrientation" = "向きを入れ替え" +"grid.add" = "レイアウトグリッドを追加" +"grid.move" = "レイアウトグリッドを移動" +"grid.remove" = "レイアウトグリッドを削除" +"guide.add" = "ガイドを追加" +"guide.clear" = "すべてのガイドを削除" +"guide.move" = "ガイドを移動" +"guide.remove" = "ガイドを削除" +"guide.select" = "ガイドを選択" +"help.about" = "FigCraft について" +"help.page" = "ヘルプページ" +"help.shortcuts" = "キーボードショートカット" +"image.adjust" = "画像を調整" +"image.deletePreset" = "画像プリセットを削除" +"image.place" = "画像を配置" +"image.presets" = "画像プリセット" +"image.savePreset" = "画像プリセットを保存" +"inspect.assets" = "アセットを検査" +"inspect.code" = "レイヤーのコード" +"inspect.componentCode" = "コンポーネントのコード" +"inspect.properties" = "プロパティを検査" +"inspect.readyForDev" = "開発準備完了" +"instance.create" = "インスタンスを作成" +"instance.exposed" = "公開されたネストインスタンス" +"instance.place" = "インスタンスを配置" +"instance.resetSlot" = "スロットをリセット" +"instance.setProperties" = "インスタンスのプロパティを設定" +"instance.slotInsert" = "スロットに挿入" +"instance.swap" = "インスタンスを入れ替え" +"instance.swapAt" = "指定位置のインスタンスを入れ替え" +"layers.collapseAll" = "レイヤーを折りたたむ" +"layout.add" = "オートレイアウトを追加" +"layout.remove" = "オートレイアウトを解除" +"layout.setTrack" = "グリッドトラックのサイズを設定" +"layout.suggest" = "オートレイアウトを提案" +"libraries.open" = "ライブラリ" +"libraries.publish" = "ライブラリを公開…" +"library.acceptUpdates" = "ライブラリの更新を承認" +"library.add" = "ライブラリを追加" +"library.aliasVariable" = "ライブラリ変数のエイリアス" +"library.applyStyle" = "ライブラリスタイルを適用" +"library.bindVariable" = "ライブラリ変数を割り当て" +"library.extendCollection" = "ライブラリコレクションを拡張" +"library.import" = "ライブラリコンポーネントをインポート" +"library.importVariable" = "ライブラリ変数をインポート" +"library.list" = "ライブラリを一覧表示" +"library.place" = "ライブラリコンポーネントを配置" +"library.publish" = "ライブラリを公開" +"library.publishToServer" = "ライブラリをサーバーに公開" +"library.remove" = "ライブラリを削除" +"library.setVariableMode" = "ライブラリ変数のモードを設定" +"library.swap" = "ライブラリを入れ替え" +"library.swapAt" = "インスタンスをライブラリコンポーネントに入れ替え" +"library.updates" = "ライブラリの更新" +"library.usage" = "ライブラリの使用状況" +"measure.distances" = "距離を測定" +"measure.padding" = "オートレイアウトのパディングを測定" +"node.create" = "レイヤーを作成" +"node.get" = "レイヤーを取得" +"node.reorder" = "レイヤーの順序を変更" +"node.reparent" = "レイヤーを中に移動" +"node.set" = "プロパティを設定" +"object.batchRename" = "一括で名前を変更" +"object.flipH" = "左右反転" +"object.flipV" = "上下反転" +"object.frameSelection" = "選択範囲をフレームで囲む" +"object.group" = "選択範囲をグループ化" +"object.hideOthers" = "他のレイヤーを非表示" +"object.mask" = "マスクとして使用" +"object.moveToPage" = "ページに移動" +"object.opacityKeys" = "数字キーで不透明度" +"object.rasterize" = "選択範囲をラスタライズ" +"object.releaseMask" = "マスクを解除" +"object.removeFill" = "塗りを削除" +"object.removeFrame" = "フレームを削除" +"object.removeStroke" = "線を削除" +"object.rename" = "名前を変更" +"object.resizeToFit" = "サイズを合わせる" +"object.rotate180" = "180° 回転" +"object.rotateLeft" = "左に 90° 回転" +"object.rotateRight" = "右に 90° 回転" +"object.setThumbnail" = "サムネイルに設定" +"object.swapFillStroke" = "塗りと線を入れ替え" +"object.toggleLock" = "選択範囲をロック/ロック解除" +"object.toggleVisible" = "選択範囲を表示/非表示" +"object.ungroup" = "選択範囲のグループを解除" +"object.wrapInSection" = "新しいセクションで囲む" +"page.add" = "ページを追加" +"page.delete" = "ページを削除" +"page.duplicate" = "ページを複製" +"page.list" = "ページを一覧表示" +"page.move" = "ページを移動" +"page.rename" = "ページ名を変更" +"page.select" = "ページへ移動" +"page.setBackground" = "ページの背景" +"paint.documentColors" = "ドキュメントのカラー" +"plugin.close" = "プラグインパネルを閉じる" +"plugin.event" = "プラグインパネルのコントロールを使用" +"plugin.import" = "マニフェストからプラグインをインポート…" +"plugin.list" = "プラグインを一覧表示" +"plugin.remove" = "プラグインを削除" +"plugin.run" = "プラグインを実行" +"plugin.ui" = "プラグインパネル" +"plugins.manage" = "プラグインを管理…" +"plugins.runLast" = "最後のプラグインを実行" +"pref.highlightHover" = "ホバー時にレイヤーをハイライト" +"pref.keepTool" = "使用後もツールを選択したままにする" +"pref.language" = "インターフェースの言語" +"pref.nudge" = "微調整の量" +"pref.numberKeysOpacity" = "数字キーで不透明度を変更" +"pref.reduceMotion" = "動きを減らす" +"pref.renameDuplicates" = "複製したレイヤーの名前を変更" +"pref.showDimensions" = "オブジェクトに寸法を表示" +"pref.userName" = "コメントに表示する名前" +"proto.action.add" = "プロトタイプのアクションを追加" +"proto.action.move" = "プロトタイプのアクションの順序を変更" +"proto.action.remove" = "プロトタイプのアクションを削除" +"proto.action.set" = "プロトタイプのアクションを編集" +"proto.closePreview" = "プロトタイプのプレビューを閉じる" +"proto.conditional.addBlock" = "「それ以外で条件」/「それ以外」を追加" +"proto.conditional.removeBlock" = "条件 /「それ以外で条件」/「それ以外」を削除" +"proto.conditional.setCondition" = "条件を編集" +"proto.flow.add" = "フローの開始点を追加" +"proto.flow.remove" = "フローを削除" +"proto.flow.rename" = "フロー名を変更" +"proto.interaction.add" = "インタラクションを追加" +"proto.interaction.clear" = "すべてのインタラクションを削除" +"proto.interaction.remove" = "インタラクションを削除" +"proto.interaction.set" = "インタラクションを編集" +"proto.present" = "プレゼンテーション" +"proto.presentOptions" = "プレゼンテーションのオプション" +"proto.preview" = "プロトタイプのプレビューを開く" +"proto.settings" = "プロトタイプの設定" +"section.toggleContents" = "セクションのコンテンツを非表示/表示" +"select.add" = "選択範囲に追加" +"select.all" = "すべて選択" +"select.area" = "範囲を選択" +"select.byName" = "名前でレイヤーを選択" +"select.children" = "子を選択" +"select.inverse" = "選択範囲を反転" +"select.layersAt" = "指定位置のレイヤー" +"select.matching" = "一致するレイヤーを選択" +"select.next" = "次の兄弟を選択" +"select.none" = "選択を解除" +"select.parent" = "親を選択" +"select.previous" = "前の兄弟を選択" +"select.remove" = "選択範囲から削除" +"select.sameEffect" = "同じエフェクトを選択" +"select.sameFill" = "同じ塗りを選択" +"select.sameFont" = "同じフォントを選択" +"select.sameInstance" = "同じインスタンスを選択" +"select.sameProperties" = "同じプロパティを選択" +"select.sameStroke" = "同じ線を選択" +"select.sameText" = "同じテキストプロパティを選択" +"select.set" = "選択" +"shape.arrow" = "矢印" +"shape.ellipse" = "楕円" +"shape.line" = "線" +"shape.polygon" = "多角形" +"shape.rectangle" = "長方形" +"shape.star" = "星" +"shapeBuilder.merge" = "領域を結合" +"shapeBuilder.mode" = "シェイプビルダーモード" +"shapeBuilder.regions" = "シェイプビルダーの領域" +"shapeBuilder.remove" = "領域を削除" +"stroke.add" = "線を追加" +"stroke.brush" = "ブラシ" +"stroke.move" = "線を移動" +"stroke.remove" = "線を削除" +"stroke.set" = "線を設定" +"stroke.widthProfile" = "幅プロファイル" +"style.apply" = "スタイルを適用" +"style.create" = "スタイルを作成" +"style.delete" = "スタイルを削除" +"style.detach" = "スタイルを切り離す" +"style.duplicate" = "スタイルを複製" +"style.list" = "スタイルを一覧表示" +"style.move" = "スタイルを移動" +"style.renameFolder" = "スタイルフォルダー名を変更" +"style.update" = "スタイルを編集" +"text.alignCenter" = "中央揃え" +"text.alignJustify" = "両端揃え" +"text.alignLeft" = "左揃え" +"text.alignRight" = "右揃え" +"text.bold" = "太字" +"text.bulletList" = "箇条書き" +"text.case" = "大文字と小文字" +"text.caseLower" = "小文字" +"text.caseOriginal" = "元の大文字と小文字" +"text.caseSmallCaps" = "スモールキャップ" +"text.caseTitle" = "タイトルケース" +"text.caseUpper" = "大文字" +"text.create" = "テキスト" +"text.decoration" = "装飾" +"text.edit.begin" = "テキストを編集" +"text.edit.caret" = "キャレットを設定" +"text.edit.end" = "テキストの編集を終了" +"text.edit.insert" = "テキストを入力" +"text.edit.key" = "テキストのキー" +"text.edit.preedit" = "テキストを変換入力(IME)" +"text.edit.selectLine" = "行を選択" +"text.edit.selectWord" = "単語を選択" +"text.edit.selection" = "テキストの選択範囲" +"text.endPreview" = "テキストのプレビューを終了" +"text.fonts" = "フォントを一覧表示" +"text.italic" = "斜体" +"text.lineHeightDown" = "行の高さを下げる" +"text.lineHeightUp" = "行の高さを上げる" +"text.link" = "リンクを作成" +"text.listStyle" = "リストのスタイル" +"text.maxLines" = "最大行数" +"text.numberList" = "番号付きリスト" +"text.onPath" = "パス上のテキスト" +"text.paragraphIndent" = "段落インデント" +"text.paragraphSpacing" = "段落間隔" +"text.pathOptions" = "テキストパスのオプション" +"text.preview" = "テキストの変更をプレビュー" +"text.removeFromPath" = "テキストをパスから外す" +"text.set" = "テキストを設定" +"text.setFeatures" = "OpenType 機能" +"text.setVariations" = "バリアブルフォントの軸" +"text.sizeDown" = "フォントサイズを小さく" +"text.sizeUp" = "フォントサイズを大きく" +"text.strikethrough" = "取り消し線" +"text.style" = "テキスト範囲にスタイルを設定" +"text.trackingDown" = "文字間隔を狭く" +"text.trackingUp" = "文字間隔を広く" +"text.underline" = "下線" +"text.weightDown" = "フォントの太さを細く" +"text.weightUp" = "フォントの太さを太く" +"tool.arrow" = "矢印" +"tool.comment" = "コメント" +"tool.ellipse" = "楕円" +"tool.frame" = "フレーム" +"tool.hand" = "手のひら" +"tool.line" = "線" +"tool.move" = "移動" +"tool.pen" = "ペン" +"tool.pencil" = "鉛筆" +"tool.pencilBrush" = "鉛筆のブラシ" +"tool.polygon" = "多角形" +"tool.rectangle" = "長方形" +"tool.scale" = "拡大縮小" +"tool.scaleAnchor" = "拡大縮小の基準点" +"tool.section" = "セクション" +"tool.set" = "ツールを選択" +"tool.shapeBuilder" = "シェイプビルダー" +"tool.slice" = "スライス" +"tool.star" = "星" +"tool.text" = "テキスト" +"transform.move" = "移動" +"transform.moveTo" = "指定位置へ移動" +"transform.nudge" = "微調整" +"transform.nudgeSize" = "微調整でサイズ変更" +"transform.resize" = "サイズ変更" +"transform.rotate" = "回転" +"transform.scale" = "拡大縮小" +"variable.addMode" = "モードを追加" +"variable.bind" = "変数を割り当て" +"variable.create" = "変数を作成" +"variable.createCollection" = "変数コレクションを作成" +"variable.delete" = "変数を削除" +"variable.deleteCollection" = "コレクションを削除" +"variable.duplicate" = "変数を複製" +"variable.export" = "変数を書き出し" +"variable.import" = "変数をインポート" +"variable.list" = "変数を一覧表示" +"variable.moveMode" = "モードを移動" +"variable.removeMode" = "モードを削除" +"variable.renameCollection" = "コレクション名を変更" +"variable.renameMode" = "モード名を変更" +"variable.resetOverride" = "変数のオーバーライドをリセット" +"variable.set" = "変数の値を設定" +"variable.setMode" = "変数モードを設定" +"variable.update" = "変数を編集" +"vector.create" = "ベクター" +"vector.deleteHeal" = "選択範囲を削除して修復" +"vector.edit.addVertex" = "ポイントを追加" +"vector.edit.begin" = "ベクターを編集" +"vector.edit.bend" = "セグメントを曲げる" +"vector.edit.bounds" = "選択したポイントの境界" +"vector.edit.connect" = "ポイントを接続" +"vector.edit.cornerRadius" = "ポイントの角の半径" +"vector.edit.cut" = "パスを切断" +"vector.edit.delete" = "ポイントを削除" +"vector.edit.end" = "編集を完了" +"vector.edit.erase" = "消去" +"vector.edit.lasso" = "なげなわ選択" +"vector.edit.mirroring" = "ハンドルの対称" +"vector.edit.moveHandles" = "ハンドルを移動" +"vector.edit.moveVertices" = "ポイントを移動" +"vector.edit.nudge" = "ポイントを微調整" +"vector.edit.paint" = "塗りつぶし" +"vector.edit.pen" = "ペンのポイント" +"vector.edit.penEnd" = "ペンのパスを終了" +"vector.edit.position" = "ポイントの位置" +"vector.edit.resize" = "ポイントのサイズを変更" +"vector.edit.rotate" = "ポイントを回転" +"vector.edit.select" = "ポイントを選択" +"vector.edit.selectAll" = "すべてのポイントを選択" +"vector.edit.setHandle" = "ハンドルを設定" +"vector.edit.smooth" = "ポイントを滑らかに/鋭角に" +"vector.edit.state" = "ベクター編集の状態" +"vector.edit.strokeCap" = "ポイントの線端" +"vector.edit.strokeJoin" = "ポイントの角の形状" +"vector.edit.tool" = "ベクター編集ツール" +"vector.edit.transform" = "ポイントを変形" +"vector.edit.widthPoint" = "幅のポイント" +"vector.flatten" = "平坦化" +"vector.join" = "選択範囲を連結" +"vector.offset" = "パスのオフセット" +"vector.outlineStroke" = "線のアウトライン化" +"vector.reverse" = "パスの方向を反転" +"vector.simplify" = "ベクターを単純化" +"vector.smoothJoin" = "選択範囲を滑らかに連結" +"version.autosave" = "自動保存バージョン" +"version.delete" = "バージョンを削除" +"version.duplicate" = "バージョンを複製" +"version.exitPreview" = "現在のバージョンに戻る" +"version.list" = "バージョンを一覧表示" +"version.preview" = "バージョンを表示" +"version.rename" = "バージョン名を変更" +"version.restore" = "バージョンを復元" +"view.assets" = "アセットパネル" +"view.comments" = "コメント" +"view.contextMenu" = "コンテキストメニューを表示" +"view.design" = "デザインパネル" +"view.designPrototype" = "デザインとプロトタイプを切り替え" +"view.devMode" = "開発モード" +"view.frameOutlines" = "フレームのアウトライン" +"view.get" = "ビューを取得" +"view.layers" = "レイヤーパネル" +"view.layoutGrids" = "レイアウトグリッド" +"view.leftSidebar" = "左サイドバーを表示/非表示" +"view.maskOutlines" = "マスクのアウトライン" +"view.nextFrame" = "次のフレームにズーム" +"view.nextPage" = "次のページ" +"view.nextRegion" = "次の領域にフォーカス" +"view.outlines" = "アウトライン" +"view.outlinesSelection" = "選択範囲のアウトライン" +"view.pixelGrid" = "ピクセルグリッド" +"view.pixelPreview" = "ピクセルプレビュー" +"view.prevFrame" = "前のフレームにズーム" +"view.prevPage" = "前のページ" +"view.previousRegion" = "前の領域にフォーカス" +"view.proofSrgb" = "sRGB でソフトプルーフ" +"view.prototype" = "プロトタイプパネル" +"view.rulers" = "定規" +"view.set" = "ビューを設定" +"view.slices" = "スライス" +"view.snapGeometry" = "ジオメトリにスナップ" +"view.snapObjects" = "オブジェクトにスナップ" +"view.snapPixel" = "ピクセルグリッドにスナップ" +"view.themeDark" = "ダークテーマ" +"view.themeLight" = "ライトテーマ" +"view.themeSystem" = "システムのテーマに合わせる" +"view.toggleUi" = "UI の表示/非表示" +"view.zoom100" = "100% にズーム" +"view.zoom200" = "200% にズーム" +"view.zoom50" = "50% にズーム" +"view.zoomAt" = "ズームツール" +"view.zoomFit" = "全体表示" +"view.zoomIn" = "ズームイン" +"view.zoomOut" = "ズームアウト" +"view.zoomSelection" = "選択範囲にズーム" +"window.focus" = "ウィンドウを最前面に表示" +"window.new" = "新しいウィンドウ" + +[menu] +"bool.exclude" = "除外" +"bool.flatten" = "平坦化" +"bool.intersect" = "交差" +"bool.subtract" = "型抜き" +"bool.union" = "合体" +"file.duplicate" = "複製" +"file.import" = "ファイルからインポート…" +"file.rename" = "名前を変更" +"libraries.open" = "ライブラリを開く" +"select.sameEffect" = "エフェクト" +"select.sameFill" = "塗り" +"select.sameFont" = "フォント" +"select.sameInstance" = "インスタンス" +"select.sameProperties" = "プロパティ" +"select.sameStroke" = "線" +"select.sameText" = "テキストプロパティ" +"text.alignCenter" = "テキストを中央揃え" +"text.alignJustify" = "テキストを両端揃え" +"text.alignLeft" = "テキストを左揃え" +"text.alignRight" = "テキストを右揃え" +"view.assets" = "アセット" +"view.design" = "デザイン" +"view.layers" = "レイヤー" +"view.outlines" = "アウトラインを表示" +"view.outlinesSelection" = "選択範囲のアウトラインを表示" +"view.prototype" = "プロトタイプ" +"view.themeDark" = "ダーク" +"view.themeLight" = "ライト" +"view.themeSystem" = "システムに合わせる" diff --git a/crates/ui-egui/locales/ko.toml b/crates/ui-egui/locales/ko.toml new file mode 100644 index 0000000..fdea4d3 --- /dev/null +++ b/crates/ui-egui/locales/ko.toml @@ -0,0 +1,1915 @@ +# FigCraft interface strings: Korean. +# +# Draft — needs native review: machine-drafted from the English catalog. Brand names, keyboard +# glyphs and {placeholders} stay as they are. Concise UI labels without 합니다 endings +# (instructions end in -세요). No plural forms: plural entries give only `other`. +# See docs/translating.md. + +[meta] +name = "한국어" +status = "draft — needs native review" + +[ui] +"% of all commits" = "전체 커밋 중 %" +"(no longer published)" = "(게시 중단됨)" +"({n} warnings: some entries were skipped)" = { other = "(경고 {n}개: 일부 항목을 건너뜀)" } +"+ Create variable" = "+ 변수 만들기" +"1…9, 0" = "1…9, 0" +"@{login}: {prs} PRs, {commits} commits, +{added} / −{deleted} lines (Δ {delta}), +{bin_added} / −{bin_deleted} binary assets, {first} – {last}" = "@{login}: PR {prs}개, 커밋 {commits}개, +{added} / −{deleted}줄 (Δ {delta}), 바이너리 에셋 +{bin_added} / −{bin_deleted}, {first} – {last}" +"A collection of this file with these modes and variables: override their values per mode and add variables of its own" = "이 파일의 컬렉션과 그 모드 및 변수: 모드별로 값을 재정의하고 자체 변수를 추가할 수 있음" +"A spring plays until it settles: its mass, stiffness and damping set how long" = "스프링은 멈출 때까지 재생됨. 길이는 질량, 강성, 감쇠로 결정됨" +"About" = "정보" +"About FigCraft" = "FigCraft 정보" +"Action" = "액션" +"Actions" = "액션" +"Actions…" = "액션…" +"Active" = "활성" +"Actual size (100%)" = "실제 크기(100%)" +"Add a category" = "카테고리 추가" +"Add a comment" = "댓글 추가" +"Add a description" = "설명 추가" +"Add a frame (F) or a shape (R) to get started" = "프레임(F) 또는 도형(R)을 추가해 시작하세요" +"Add a layer or component to tile first" = "먼저 바둑판식으로 배열할 레이어나 컴포넌트를 추가하세요" +"Add a note for developers" = "개발자용 메모 추가" +"Add action" = "액션 추가" +"Add actions for when no condition holds" = "조건에 맞지 않을 때의 액션 추가" +"Add an annotation for developers" = "개발자용 주석 추가" +"Add another condition" = "조건 추가" +"Add auto layout" = "자동 레이아웃 추가" +"Add background behind overlay" = "오버레이 뒤에 배경 추가" +"Add content to this slot" = "이 슬롯에 콘텐츠 추가" +"Add dev resource" = "개발 리소스 추가" +"Add effect" = "효과 추가" +"Add export setting" = "내보내기 설정 추가" +"Add fill" = "채우기 추가" +"Add interaction" = "인터랙션 추가" +"Add layout grid" = "레이아웃 그리드 추가" +"Add library" = "라이브러리 추가" +"Add library file…" = "라이브러리 파일 추가…" +"Add max height" = "최대 높이 추가" +"Add max width" = "최대 너비 추가" +"Add min height" = "최소 높이 추가" +"Add min width" = "최소 너비 추가" +"Add mode" = "모드 추가" +"Add new page" = "새 페이지 추가" +"Add or update collections from a variables JSON" = "변수 JSON에서 컬렉션 추가 또는 업데이트" +"Add properties to make instances configurable" = "속성을 추가해 인스턴스를 설정 가능하게 만들기" +"Add reaction" = "반응 추가" +"Add starting point" = "시작점 추가" +"Add stroke" = "선 추가" +"Add variant" = "배리언트 추가" +"Add variant with a new value" = "새 값으로 배리언트 추가" +"Added" = "추가됨" +"Added the library \"{name}\"" = "라이브러리 \"{name}\" 추가됨" +"Adjust" = "조정" +"Adjustment presets" = "조정 프리셋" +"Advanced stroke" = "고급 선" +"After delay" = "지연 후" +"After delay {ms}ms" = "{ms}ms 지연 후" +"Align" = "정렬" +"Align bottom" = "아래쪽 정렬" +"Align center" = "가운데 정렬" +"Align horizontal centers" = "수평 가운데 정렬" +"Align left" = "왼쪽 정렬" +"Align middle" = "세로 가운데 정렬" +"Align right" = "오른쪽 정렬" +"Align text baselines" = "텍스트 기준선 정렬" +"Align top" = "위쪽 정렬" +"Align vertical centers" = "수직 가운데 정렬" +"Alignment" = "정렬" +"All" = "모두" +"All categories" = "모든 카테고리" +"All comments" = "모든 댓글" +"All components" = "모든 컴포넌트" +"All fonts" = "모든 글꼴" +"All supported properties" = "지원되는 모든 속성" +"All variables" = "모든 변수" +"Alpha" = "알파" +"Alt+drag" = "Alt+드래그" +"Anchor" = "앵커" +"Android" = "Android" +"Angular" = "각도" +"Animation" = "애니메이션" +"Annotations" = "주석" +"Annotations shown on the canvas" = "캔버스에 표시되는 주석" +"Any status" = "모든 상태" +"Anyone on your network who has the invite link can join." = "초대 링크가 있는 네트워크의 누구나 참여할 수 있음." +"Anyone with the edit link can change the file; the view link only lets people look. The links carry their secrets: share them like passwords. `figcraft-server links` makes more and revokes them." = "편집 링크가 있으면 파일을 변경할 수 있고, 보기 링크로는 보기만 가능. 링크에는 비밀 정보가 담겨 있으므로 비밀번호처럼 공유하세요. 링크 추가와 취소는 `figcraft-server links`로 가능." +"Appearance" = "모양" +"Apply a component property" = "컴포넌트 속성 적용" +"Apply variable" = "변수 적용" +"Apply variable to text" = "텍스트에 변수 적용" +"Apply variable to visibility" = "표시 여부에 변수 적용" +"Arc" = "호" +"Arc ratio" = "호 비율" +"Arc start" = "호 시작" +"Arc sweep" = "호 범위" +"Archive" = "보관" +"Archived" = "보관됨" +"Arrange" = "배치" +"Arrow" = "화살표" +"As typed" = "입력한 대로" +"Assets" = "에셋" +"Auto" = "자동" +"Auto (space around)" = "자동(주변 간격)" +"Auto (space between)" = "자동(사이 간격)" +"Auto (space evenly)" = "자동(균등 간격)" +"Auto ({mode})" = "자동({mode})" +"Auto columns" = "자동 열" +"Auto gap" = "자동 간격" +"Auto height" = "자동 높이" +"Auto layout" = "자동 레이아웃" +"Auto rows" = "자동 행" +"Auto width" = "자동 너비" +"Back to the font's value" = "글꼴 값으로 되돌리기" +"Back" = "뒤로" +"Back to Ready for dev" = "개발 준비 완료로 되돌리기" +"Back to Ready for dev: the next change compares with how it is now" = "개발 준비 완료로 되돌리기: 다음 변경은 현재 상태와 비교됨" +"Back to assets" = "에셋으로 돌아가기" +"Back to current" = "현재로 돌아가기" +"Back to styles" = "스타일로 돌아가기" +"Back to the canvas from a focused region" = "포커스된 영역에서 캔버스로 돌아가기" +"Back to the current version" = "현재 버전으로 돌아가기" +"Back to the values the font style implies" = "글꼴 스타일의 값으로 되돌리기" +"Background" = "배경" +"Background blur" = "배경 흐림" +"Basics" = "기본" +"Before" = "변경 전" +"Bend" = "구부리기" +"Bevel" = "베벨" +"Binary assets added" = "추가된 바이너리 에셋" +"Binary assets removed" = "제거된 바이너리 에셋" +"Black & white" = "흑백" +"Bleed" = "도련" +"Bleed marks" = "도련 표시" +"Bleed marks need a bleed" = "도련 표시에는 도련이 필요함" +"Blend" = "혼합" +"Blend mode" = "혼합 모드" +"Blue" = "파랑" +"Blur" = "흐림" +"Boolean" = "불리언" +"Boolean groups" = "불리언 그룹" +"Both directions" = "양방향" +"Bottom" = "아래쪽" +"Bottom left radius" = "왼쪽 아래 반경" +"Bottom right radius" = "오른쪽 아래 반경" +"Branch" = "브랜치" +"Branch archived" = "브랜치 보관됨" +"Branch merged" = "브랜치 병합됨" +"Branch name" = "브랜치 이름" +"Branch of {file}" = "{file}의 브랜치" +"Branch of {file} · merged or archived" = "{file}의 브랜치 · 병합 또는 보관됨" +"Branch updated from main" = "메인에서 브랜치 업데이트됨" +"Branch {name}" = "브랜치 {name}" +"Branches" = "브랜치" +"Bring forward" = "앞으로 가져오기" +"Bring the main file's changes into the branch" = "메인 파일의 변경 사항을 브랜치로 가져오기" +"Bring to front" = "맨 앞으로 가져오기" +"Bristle" = "강모" +"Brush" = "브러시" +"Brush rotation jitter" = "브러시 회전 지터" +"Brush scatter" = "브러시 분산" +"Brush size jitter" = "브러시 크기 지터" +"Brush spacing" = "브러시 간격" +"Bulleted list" = "글머리 기호 목록" +"CMYK colour" = "CMYK 색상" +"Color profile: {name}" = "색상 프로필: {name}" +"CSS custom properties…" = "CSS 사용자 정의 속성…" +"Can edit" = "편집 가능" +"Can't read this library: {e}" = "이 라이브러리를 읽을 수 없음: {e}" +"Cancel" = "취소" +"Canvas" = "캔버스" +"Canvas stacking" = "캔버스 쌓기 순서" +"Cap height to baseline" = "대문자 높이에서 기준선까지" +"Case" = "대소문자" +"Case-sensitive forms" = "대문자용 글리프" +"Categories" = "카테고리" +"Center" = "가운데" +"Change alias" = "별칭 변경" +"Change resolved" = "변경 사항 해결됨" +"Change style" = "스타일 변경" +"Change to" = "변경 대상" +"Change to needs a layer inside a variant" = "\"변경 대상\"에는 배리언트 안의 레이어가 필요함" +"Changed" = "변경됨" +"Changed on both sides: keep one" = "양쪽에서 변경됨: 하나를 유지하세요" +"Changes on main" = "메인의 변경 사항" +"Changes on the branch" = "브랜치의 변경 사항" +"Changes unknown" = "변경 내용 알 수 없음" +"Choose React, SwiftUI or Compose above to connect this component to its code." = "위에서 React, SwiftUI 또는 Compose를 선택해 이 컴포넌트를 코드에 연결하세요." +"Choose another profile to change it." = "변경하려면 다른 프로필을 선택하세요." +"Choose collection" = "컬렉션 선택" +"Choose image" = "이미지 선택" +"Choose mode" = "모드 선택" +"Choose variable" = "변수 선택" +"Circle" = "원" +"Clear recent" = "최근 항목 지우기" +"Click + to replace mixed content" = "+를 클릭해 혼합된 내용 바꾸기" +"Click anywhere on the canvas to leave one." = "캔버스의 아무 곳이나 클릭해 남길 수 있음." +"Click or drag to merge · {alt} removes" = "클릭하거나 드래그해 병합 · {alt}로 제거" +"Click or drag to remove · {alt} merges" = "클릭하거나 드래그해 제거 · {alt}로 병합" +"Click to record a key" = "클릭해 키 기록" +"Clip content" = "콘텐츠 자르기" +"Clip to shape" = "도형으로 클리핑" +"Close" = "닫기" +"Close overlay" = "오버레이 닫기" +"Close preview" = "미리 보기 닫기" +"Close tab" = "탭 닫기" +"Close version history" = "버전 기록 닫기" +"Close when clicking outside" = "바깥쪽을 클릭하면 닫기" +"Close without saving" = "저장하지 않고 닫기" +"Code" = "코드" +"Code syntax" = "코드 구문" +"Collapse" = "접기" +"Collapse panel" = "패널 접기" +"Collection" = "컬렉션" +"Collections" = "컬렉션" +"Color" = "색상" +"Color burn" = "색상 번" +"Color dodge" = "색상 닷지" +"Color format" = "색상 형식" +"Color profile" = "색상 프로필" +"Color styles" = "색상 스타일" +"Color values in this file are in this color space." = "이 파일의 색상 값은 이 색 공간 기준임." +"Color variables" = "색상 변수" +"Colour" = "색상" +"Column" = "열" +"Column gap" = "열 간격" +"Column sizes" = "열 크기" +"Column span" = "열 범위" +"Columns" = "열" +"Columns {count}" = "열 {count}" +"Comment" = "댓글" +"Comments" = "댓글" +"Commits" = "커밋" +"Community" = "커뮤니티" +"Company" = "회사" +"Compare changes" = "변경 사항 비교" +"Completed" = "완료됨" +"Component" = "컴포넌트" +"Component name" = "컴포넌트 이름" +"Component property" = "컴포넌트 속성" +"Component set" = "컴포넌트 세트" +"Component sets" = "컴포넌트 세트" +"Components" = "컴포넌트" +"Conditional" = "조건부" +"Confetti" = "색종이" +"Conflicts" = "충돌" +"Connect to code" = "코드에 연결" +"Connected" = "연결됨" +"Connected to code: {from}" = "코드에 연결됨: {from}" +"Connection lost, reconnecting (attempt {attempt})…" = "연결이 끊어짐. 다시 연결하는 중({attempt}번째 시도)…" +"Constrain proportions" = "비율 고정" +"Constraints" = "제약" +"Content" = "콘텐츠" +"Contents hidden" = "콘텐츠 숨김" +"Contents only" = "콘텐츠만" +"Contextual alternates" = "문맥 대체 글자" +"Contrast" = "대비" +"Contributors" = "기여자" +"Contributors: {people} · Commits: {commits}" = "기여자: {people} · 커밋: {commits}" +"Cool" = "차갑게" +"Copied as CSS" = "CSS로 복사됨" +"Copied as PNG" = "PNG로 복사됨" +"Copied as SVG" = "SVG로 복사됨" +"Copied as text" = "텍스트로 복사됨" +"Copied {value}" = "{value} 복사됨" +"Copy" = "복사" +"Copy as" = "다른 형식으로 복사" +"Copy as CSS" = "CSS로 복사" +"Copy as PNG" = "PNG로 복사" +"Copy as SVG" = "SVG로 복사" +"Copy link" = "링크 복사" +"Copy the {label}" = "{label} 복사" +"Copy {value}" = "{value} 복사" +"Corner radius" = "모서리 반경" +"Corner smoothing" = "모서리 스무딩" +"Count" = "개수" +"Create" = "만들기" +"Create a variable collection first" = "먼저 변수 컬렉션을 만드세요" +"Create a variable first" = "먼저 변수를 만드세요" +"Create alias" = "별칭 만들기" +"Create branch" = "브랜치 만들기" +"Create collection" = "컬렉션 만들기" +"Create component" = "컴포넌트 만들기" +"Create component property" = "컴포넌트 속성 만들기" +"Create components, styles or variables to publish them as a library." = "컴포넌트, 스타일 또는 변수를 만들어 라이브러리로 게시하세요." +"Create property…" = "속성 만들기…" +"Create style" = "스타일 만들기" +"Create style from the selected text" = "선택한 텍스트로 스타일 만들기" +"Crop" = "자르기" +"Crop marks" = "재단선 표시" +"Ctrl+arrows" = "Ctrl+화살표" +"Ctrl+click" = "Ctrl+클릭" +"Ctrl+scroll" = "Ctrl+스크롤" +"Current version" = "현재 버전" +"Custom" = "사용자 지정" +"Cut" = "잘라내기" +"Dark" = "다크" +"Darken" = "어둡게 하기" +"Dash" = "대시" +"Decoration style" = "장식 스타일" +"Decoration" = "장식" +"Deep select" = "깊은 선택" +"Default" = "기본값" +"Default content" = "기본 콘텐츠" +"Default value (the top-left variant)" = "기본값(왼쪽 위 배리언트)" +"Delay" = "지연" +"Delete" = "삭제" +"Delete category (its annotations stay)" = "카테고리 삭제(주석은 유지됨)" +"Delete collection" = "컬렉션 삭제" +"Delete group" = "그룹 삭제" +"Delete mode" = "모드 삭제" +"Delete page" = "페이지 삭제" +"Delete preset" = "프리셋 삭제" +"Delete property" = "속성 삭제" +"Delete the style (layers keep their values)" = "스타일 삭제(레이어는 값을 유지함)" +"Delete thread" = "스레드 삭제" +"Delete variable" = "변수 삭제" +"Delete “{name}”? This can't be undone." = "\"{name}\"을(를) 삭제할까요? 되돌릴 수 없음." +"Density" = "밀도" +"Depth" = "깊이" +"Describe how and when to use this component" = "이 컴포넌트를 언제 어떻게 쓰는지 설명" +"Describe what changed" = "변경 내용 설명" +"Description" = "설명" +"Description (optional)" = "설명(선택 사항)" +"Design" = "디자인" +"Desktop" = "데스크톱" +"Destination" = "대상" +"Detach alias" = "별칭 분리" +"Detach instance" = "인스턴스 분리" +"Detach property" = "속성 분리" +"Detach style" = "스타일 분리" +"Detach styles" = "스타일 분리" +"Detach variable" = "변수 분리" +"Details" = "세부 정보" +"Dev Mode" = "개발 모드" +"Dev resources" = "개발 리소스" +"Development" = "개발" +"Device" = "기기" +"Device at 100%" = "기기 100%" +"Diamond" = "마름모" +"Difference" = "차이" +"Dimensions" = "치수" +"Direction" = "방향" +"Disconnect from code" = "코드 연결 해제" +"Dispersion" = "분산" +"Display name" = "표시 이름" +"Dissolve" = "디졸브" +"Distribute and tidy" = "분포 및 정돈" +"Distribute horizontal spacing" = "수평 간격 균등 분포" +"Distribute vertical spacing" = "수직 간격 균등 분포" +"Don't truncate" = "자르지 않음" +"Done" = "완료" +"Done editing" = "편집 완료" +"Dots" = "점" +"Dotted" = "점선" +"Down" = "아래" +"Drafts" = "임시 보관함" +"Drag the stroke to add a width point" = "선을 드래그해 너비 점 추가" +"Draw" = "그리기" +"Drawing tools" = "그리기 도구" +"Drop shadow" = "드롭 섀도" +"Dual-licensed MIT OR Apache-2.0. Made by the ArtCraft team and community." = "MIT 또는 Apache-2.0 이중 라이선스. ArtCraft 팀과 커뮤니티가 만듦." +"Duo" = "2색" +"Duplicate" = "복제" +"Duplicate by dragging" = "드래그해 복제" +"Duplicate mode" = "모드 복제" +"Duplicate page" = "페이지 복제" +"Edit" = "편집" +"Edit as an expression" = "수식으로 편집" +"Edit colour" = "색상 편집" +"Edit comment" = "댓글 편집" +"Edit dev resource" = "개발 리소스 편집" +"Edit link" = "편집 링크" +"Edit link copied" = "편집 링크 복사됨" +"Edit style" = "스타일 편집" +"Edit variable" = "변수 편집" +"Edit with the builder" = "빌더로 편집" +"Effect settings" = "효과 설정" +"Effect styles" = "효과 스타일" +"Effects" = "효과" +"Ellipse" = "타원" +"Ellipses" = "타원" +"Else" = "그 외" +"Else if" = "그 외 조건" +"Embedded profile" = "포함된 프로필" +"Empty" = "비어 있음" +"End" = "끝" +"End point" = "끝점" +"Enter to save · Esc to cancel" = "Enter로 저장 · Esc로 취소" +"Eraser" = "지우개" +"Esc" = "Esc" +"Essential" = "기본" +"Every conflict has a choice." = "모든 충돌에 선택 사항이 있음." +"Every top-level frame already starts a flow" = "모든 최상위 프레임이 이미 플로우를 시작함" +"Exact opacity (4 then 5: 45%)" = "정확한 불투명도(4 다음 5: 45%)" +"Exclude" = "제외" +"Excluded" = "제외됨" +"Excluded from layout" = "레이아웃에서 제외됨" +"Excludes" = "제외" +"Exclusion" = "제외" +"Exit focus view (Esc)" = "포커스 보기 종료(Esc)" +"Expand" = "펼치기" +"Export" = "내보내기" +"Export all" = "모두 내보내기" +"Export page as PNG" = "페이지를 PNG로 내보내기" +"Export settings" = "내보내기 설정" +"Export variables" = "변수 내보내기" +"Export {name}" = "{name} 내보내기" +"Export {n} layers" = { other = "레이어 {n}개 내보내기" } +"Exported {file}" = "{file} 내보냄" +"Exported {name}" = "{name} 내보냄" +"Exported {n} files" = { other = "파일 {n}개 내보냄" } +"Export…" = "내보내기…" +"Expose properties to instances" = "인스턴스에 속성 노출" +"Exposure" = "노출" +"Expression" = "수식" +"Extend collection" = "컬렉션 확장" +"Extends \"{name}\": overridden values are marked" = "\"{name}\" 확장: 재정의된 값은 표시됨" +"Eye" = "눈" +"Fade" = "페이드" +"False" = "거짓" +"Fetching from the server…" = "서버에서 가져오는 중…" +"File" = "파일" +"File name" = "파일 이름" +"Fill" = "채우기" +"Fill (fr)" = "채우기(fr)" +"Fill container" = "컨테이너에 맞춤" +"Fill window" = "창 채우기" +"Fills" = "채우기" +"Fill|sizing" = "채우기" +"Filter and sort" = "필터 및 정렬" +"Find" = "찾기" +"Find and replace" = "찾기 및 바꾸기" +"Find layers" = "레이어 찾기" +"First" = "처음" +"First commit" = "첫 커밋" +"First on top" = "처음 항목을 위에" +"Fit" = "맞춤" +"Fit device to window" = "기기를 창에 맞춤" +"Fit to contents" = "콘텐츠에 맞춤" +"Fit to window" = "창에 맞춤" +"Fit width" = "너비에 맞춤" +"Fixed" = "고정" +"Fixed gap" = "고정 간격" +"Fixed size" = "고정 크기" +"Flatten" = "평면화" +"Flip" = "뒤집기" +"Flip horizontal" = "가로로 뒤집기" +"Flip text to the other side" = "텍스트를 반대쪽으로 뒤집기" +"Flip vertical" = "세로로 뒤집기" +"Flip width profile" = "너비 프로필 뒤집기" +"Flow starting point" = "플로우 시작점" +"Flow starting points" = "플로우 시작점" +"Flows" = "플로우" +"Focus view" = "포커스 보기" +"Fold autosaves" = "자동 저장 접기" +"Follow {name}" = "{name} 따라가기" +"Following" = "따라가는 중" +"Following {name} · {key} to stop" = "{name} 따라가는 중 · {key}로 중지" +"Font" = "글꼴" +"Font not installed" = "글꼴이 설치되지 않음" +"Font size" = "글꼴 크기" +"Font style" = "글꼴 스타일" +"Fractions" = "분수" +"Frame" = "프레임" +"Frame selection" = "선택 항목을 프레임으로 감싸기" +"Frame tools" = "프레임 도구" +"Frames" = "프레임" +"From the library \"{name}\": read-only" = "라이브러리 \"{name}\"에서 가져옴: 읽기 전용" +"From {name}" = "{name}에서" +"Frost" = "서리" +"Gap" = "간격" +"Gap between columns" = "열 사이 간격" +"Gap between items" = "항목 사이 간격" +"Gap between rows" = "행 사이 간격" +"Glass" = "유리" +"Go to main component" = "메인 컴포넌트로 이동" +"Go to {name}" = "{name}(으)로 이동" +"Grab bag" = "무작위 모음" +"Gradient" = "그라디언트" +"Gray" = "회색" +"Green" = "초록" +"Grid" = "그리드" +"Grid ({size})" = "그리드({size})" +"Grid styles" = "그리드 스타일" +"Grid {size}" = "그리드 {size}" +"Group" = "그룹" +"Group selection" = "선택 항목 그룹화" +"Groups" = "그룹" +"Gutter" = "거터" +"Hand tool" = "손 도구" +"Hanging list" = "내어쓰기 목록" +"Hanging punctuation" = "문장 부호 내어쓰기" +"Hard light" = "하드 라이트" +"Height" = "높이" +"Help" = "도움말" +"Help and resources" = "도움말 및 리소스" +"Help page" = "도움말 페이지" +"Hidden" = "숨김" +"Hide contents" = "콘텐츠 숨기기" +"Hide from publishing" = "게시에서 숨기기" +"Hide section contents" = "섹션 콘텐츠 숨기기" +"Highlight layers on hover" = "마우스를 올리면 레이어 강조" +"Highlights" = "밝은 영역" +"Hold Alt" = "Alt 누른 채로" +"Hold Alt+Z" = "Alt+Z 누른 채로" +"Hold Z" = "Z 누른 채로" +"Hold ⌥" = "⌥ 누른 채로" +"Hold ⌥Z" = "⌥Z 누른 채로" +"Home" = "홈" +"Horizontal" = "가로" +"Horizontal align" = "가로 정렬" +"Horizontal hex" = "가로 육각형" +"Horizontal padding" = "가로 패딩" +"Horizontal spacing" = "가로 간격" +"Hosting a session needs the desktop app; here you can join one." = "세션 호스팅에는 데스크톱 앱이 필요함. 여기서는 참여할 수 있음." +"Hover a layer to see its properties" = "레이어에 마우스를 올려 속성 보기" +"Hover other layers to measure the distance" = "다른 레이어에 마우스를 올려 거리 측정" +"Hue" = "색조" +"Hug" = "맞춤" +"Hug contents" = "내용에 맞춤" +"If" = "조건" +"If {condition}" = "조건: {condition}" +"Ignore auto layout (absolute position)" = "자동 레이아웃 무시(절대 위치)" +"Image" = "이미지" +"Import" = "가져오기" +"Import path" = "가져오기 경로" +"Import plugin from manifest" = "매니페스트에서 플러그인 가져오기" +"Import plugin from manifest…" = "매니페스트에서 플러그인 가져오기…" +"Import variables" = "변수 가져오기" +"Imported {name}" = "{name} 가져옴" +"Imported {n} new variables, updated {updated}" = { other = "새 변수 {n}개를 가져오고 {updated}개를 업데이트함" } +"Import…" = "가져오기…" +"In an instance, this comes from the main component" = "인스턴스에서는 메인 컴포넌트의 값을 사용함" +"In the browser you can join sessions the desktop app hosts and files on a FigCraft server. A page opened over https reaches other computers only through wss:// links (a server behind TLS)." = "브라우저에서는 데스크톱 앱이 호스팅하는 세션과 FigCraft 서버의 파일에 참여할 수 있음. https로 연 페이지는 wss:// 링크(TLS 뒤의 서버)를 통해서만 다른 컴퓨터에 연결됨." +"Include bounding box" = "경계 상자 포함" +"Include id attribute" = "id 속성 포함" +"Included" = "포함됨" +"Included in layout" = "레이아웃에 포함됨" +"Individual corners" = "개별 모서리" +"Individual strokes" = "개별 선" +"Ink" = "잉크" +"Inner shadow" = "내부 그림자" +"Inside" = "안쪽" +"Inspect" = "검사" +"Inspect the layer under the pointer: size, colours, typography" = "포인터 아래 레이어 검사: 크기, 색상, 타이포그래피" +"Instance" = "인스턴스" +"Instance properties" = "인스턴스 속성" +"Instance swap" = "인스턴스 교체" +"Instance swap (no other component)" = "인스턴스 교체(다른 컴포넌트 없음)" +"Instances" = "인스턴스" +"Instant" = "즉시" +"Interaction" = "인터랙션" +"Interactions" = "인터랙션" +"Interface design and prototyping. A free, open-source, clean-room design tool written from scratch in Rust, part of the ArtCraft Crafting Apps." = "인터페이스 디자인과 프로토타이핑. Rust로 처음부터 작성한 무료 오픈 소스 클린룸 디자인 도구이며 ArtCraft Crafting Apps의 하나." +"Intersect" = "교차" +"Intersects" = "교차" +"Invite link" = "초대 링크" +"Invite link copied" = "초대 링크 복사됨" +"Join" = "참여" +"Join a session…" = "세션 참여…" +"Join live session" = "라이브 세션 참여" +"Join us on Discord" = "Discord에서 함께하기" +"Joined" = "참여함" +"Joined {file}" = "{file}에 참여함" +"Joining…" = "참여하는 중…" +"Join|stroke" = "선 연결" +"Just now" = "방금" +"Justify" = "양쪽 정렬" +"Keep appearance" = "모양 유지" +"Keep appearance converts every color value to {profile} so colors look the same. Keep values leaves the numbers as they are, so colors shift." = "\"모양 유지\"는 모든 색상 값을 {profile}(으)로 변환해 색이 똑같아 보이게 함. \"값 유지\"는 숫자를 그대로 두므로 색이 달라짐." +"Keep tool selected after use" = "사용 후에도 도구 선택 유지" +"Keep values" = "값 유지" +"Key/Gamepad" = "키/게임패드" +"Key/Gamepad {key}" = "키/게임패드 {key}" +"Keyboard shortcuts" = "키보드 단축키" +"Language" = "언어" +"Lasso" = "올가미" +"Last" = "마지막" +"Last change: {note}" = "마지막 변경: {note}" +"Last commit" = "마지막 커밋" +"Last on top" = "마지막 항목을 위에" +"Layer blur" = "레이어 흐림" +"Layer name" = "레이어 이름" +"Layers" = "레이어" +"Layers in an instance take their position from the main component" = "인스턴스 안의 레이어는 메인 컴포넌트의 위치를 따름" +"Layout" = "레이아웃" +"Layout grid" = "레이아웃 그리드" +"Layout grid settings" = "레이아웃 그리드 설정" +"Layout grids" = "레이아웃 그리드" +"Leave session" = "세션 나가기" +"Leaves" = "잎" +"Left" = "왼쪽" +"Left & right" = "왼쪽 및 오른쪽" +"Left side" = "왼쪽" +"Left side width" = "왼쪽 너비" +"Letter case" = "대소문자" +"Letter spacing" = "자간" +"Libraries" = "라이브러리" +"Libraries in this file" = "이 파일의 라이브러리" +"Library updates available" = "라이브러리 업데이트 있음" +"Library: click to collapse" = "라이브러리: 클릭해 접기" +"Library: click to expand" = "라이브러리: 클릭해 펼치기" +"Library: its variables are read-only here; edit them in the library file and publish it" = "라이브러리: 여기서는 변수가 읽기 전용. 라이브러리 파일에서 편집한 뒤 게시하세요" +"Light" = "라이트" +"Lighten" = "밝게 하기" +"Light|glass" = "빛" +"Line" = "선" +"Line arrow" = "선 화살표" +"Line delta" = "줄 증감" +"Line height" = "줄 높이" +"Linear" = "선형" +"Lines" = "선" +"Lines +/−" = "줄 +/−" +"Lines added" = "추가된 줄" +"Lines deleted" = "삭제된 줄" +"Link" = "링크" +"Link copied" = "링크 복사됨" +"Link docs, code or tickets for developers." = "개발자를 위해 문서, 코드, 티켓을 연결하세요." +"Link this component to its code component: instances then show your real snippet with their values." = "이 컴포넌트를 코드 컴포넌트에 연결하면 인스턴스에 실제 스니펫이 해당 값과 함께 표시됨." +"List spacing" = "목록 간격" +"List style" = "목록 스타일" +"Live session" = "라이브 세션" +"Live · {people}" = "라이브 · {people}" +"Local components" = "로컬 컴포넌트" +"Local styles" = "로컬 스타일" +"Local variables" = "로컬 변수" +"Lock/Unlock" = "잠금/잠금 해제" +"Locked" = "잠김" +"Lowercase" = "소문자" +"Luminance" = "휘도" +"Luminosity" = "광도" +"Main" = "메인" +"Main component deleted" = "메인 컴포넌트가 삭제됨" +"Main menu" = "메인 메뉴" +"Make slot" = "슬롯으로 만들기" +"Margin" = "여백" +"Mark all as read" = "모두 읽음으로 표시" +"Mark as resolved" = "해결됨으로 표시" +"Mark as unread" = "읽지 않음으로 표시" +"Mark as unresolved" = "미해결로 표시" +"Mask" = "마스크" +"Mass · Stiffness · Damping" = "질량 · 강성 · 감쇠" +"Max H" = "최대 H" +"Max W" = "최대 W" +"Max lines" = "최대 줄 수" +"Maximize" = "최대화" +"Measure to the selection" = "선택 항목까지 측정" +"Merge into main" = "메인에 병합" +"Merge regions" = "영역 병합" +"Merge the branch into the main file (one undo step) and archive it" = "브랜치를 메인 파일에 병합(실행 취소 한 번)하고 보관" +"Merged" = "병합됨" +"Merged PRs" = "병합된 PR" +"Min H" = "최소 H" +"Min W" = "최소 W" +"Minimize" = "최소화" +"Mirror angle" = "각도 대칭" +"Mirror angle and length" = "각도와 길이 대칭" +"Mirroring" = "대칭" +"Missing" = "없음" +"Missing layer" = "레이어 없음" +"Missing style" = "스타일 없음" +"Missing variable" = "변수 없음" +"Miter" = "마이터" +"Miter angle" = "마이터 각도" +"Mixed" = "혼합" +"Mixed fonts" = "혼합 글꼴" +"Mixed interactions: click + to replace them" = "혼합된 인터랙션: +를 클릭해 바꾸기" +"Mode" = "모드" +"Model" = "모델" +"Models" = "모델" +"Mono" = "단색" +"More" = "더 보기" +"More instance actions" = "기타 인스턴스 작업" +"Mouse down" = "마우스 누름" +"Mouse enter" = "마우스 진입" +"Mouse leave" = "마우스 벗어남" +"Mouse up" = "마우스 뗌" +"Move" = "이동" +"Move column left" = "열을 왼쪽으로 이동" +"Move column right" = "열을 오른쪽으로 이동" +"Move down" = "아래로 이동" +"Move in" = "안으로 이동" +"Move out" = "밖으로 이동" +"Move tools" = "이동 도구" +"Move up" = "위로 이동" +"Moved to {name}" = "{name}(으)로 이동함" +"Multi" = "다색" +"Multiply" = "곱하기" +"Muted" = "차분하게" +"Name" = "이름" +"Name (A–Z)" = "이름(A–Z)" +"Named instance" = "명명된 인스턴스" +"Navigate to" = "이동 대상" +"Nested instance" = "중첩된 인스턴스" +"New design file" = "새 디자인 파일" +"Next or previous control in the focused region" = "포커스된 영역의 다음 또는 이전 컨트롤" +"Next ready for dev" = "다음 개발 준비 완료" +"Next size option" = "다음 크기 옵션" +"No assets: no export settings, icons or images. Add export settings in the Design tab." = "에셋 없음: 내보내기 설정, 아이콘, 이미지가 없음. 디자인 탭에서 내보내기 설정을 추가하세요." +"No boolean variables fit here." = "여기에 맞는 불리언 변수가 없음." +"No boolean variables yet. Create them in Local variables." = "아직 불리언 변수가 없음. 로컬 변수에서 만드세요." +"No branches. A branch is a copy of the file to try changes in, then review and merge." = "브랜치 없음. 브랜치는 변경을 시험해 본 뒤 검토하고 병합하는 파일 사본임." +"No category" = "카테고리 없음" +"No changes" = "변경 사항 없음" +"No colour variables fit here." = "여기에 맞는 색상 변수가 없음." +"No colour variables yet. Create them in Local variables." = "아직 색상 변수가 없음. 로컬 변수에서 만드세요." +"No comments yet" = "아직 댓글 없음" +"No components yet. Select layers and press {keys}." = "아직 컴포넌트가 없음. 레이어를 선택하고 {keys}를 누르세요." +"No conflicts." = "충돌 없음." +"No contributor data was built into this copy." = "이 사본에는 기여자 데이터가 포함되지 않음." +"No fonts match" = "일치하는 글꼴 없음" +"No layer changes to show." = "표시할 레이어 변경 사항 없음." +"No libraries yet. Add a .figcraft file that was published as a library, or paste a team library's link." = "아직 라이브러리가 없음. 라이브러리로 게시된 .figcraft 파일을 추가하거나 팀 라이브러리 링크를 붙여 넣으세요." +"No list" = "목록 없음" +"No matching comments" = "일치하는 댓글 없음" +"No matching components" = "일치하는 컴포넌트 없음" +"No matching layers" = "일치하는 레이어 없음" +"No matching styles" = "일치하는 스타일 없음" +"No matching variables" = "일치하는 변수 없음" +"No mirroring" = "대칭 없음" +"No model credits were built into this copy." = "이 사본에는 모델 크레디트가 포함되지 않음." +"No number variables fit here." = "여기에 맞는 숫자 변수가 없음." +"No number variables yet. Create them in Local variables." = "아직 숫자 변수가 없음. 로컬 변수에서 만드세요." +"No paints" = "페인트 없음" +"No plugins yet. Import a development plugin from its figcraft-plugin.json." = "아직 플러그인이 없음. figcraft-plugin.json에서 개발용 플러그인을 가져오세요." +"No preferred components" = "선호 컴포넌트 없음" +"No preset" = "프리셋 없음" +"No saved versions yet. Save a version to mark a point in your work you can come back to." = "아직 저장된 버전이 없음. 버전을 저장해 나중에 돌아올 수 있는 작업 지점을 표시하세요." +"No scrolling" = "스크롤 없음" +"No shortcuts match" = "일치하는 단축키 없음" +"No status" = "상태 없음" +"No string variables fit here." = "여기에 맞는 문자열 변수가 없음." +"No string variables yet. Create them in Local variables." = "아직 문자열 변수가 없음. 로컬 변수에서 만드세요." +"No styles yet." = "아직 스타일 없음." +"No styles yet. Click + to create one from the selection." = "아직 스타일이 없음. +를 클릭해 선택 항목으로 만드세요." +"No text styles yet. Click + to create one from the selected text." = "아직 텍스트 스타일이 없음. +를 클릭해 선택한 텍스트로 만드세요." +"No variables fit here." = "여기에 맞는 변수가 없음." +"No variables yet. Create them in Local variables." = "아직 변수가 없음. 로컬 변수에서 만드세요." +"Nobody else is here yet" = "아직 다른 사람이 없음" +"Noise" = "노이즈" +"None" = "없음" +"None." = "없음." +"Normal" = "표준" +"Not bound" = "연결 안 됨" +"Not in a live session" = "라이브 세션에 참여하지 않음" +"Not in this font" = "이 글꼴에 없음" +"Not properties, kept as written: {names}" = "속성이 아니므로 작성된 대로 유지: {names}" +"Not read yet" = "아직 읽지 않음" +"Note {n}" = "메모 {n}" +"Nothing changed since this was marked ready for dev." = "개발 준비 완료로 표시된 뒤 변경된 내용 없음." +"Nothing here yet. Set a frame's status to list it." = "아직 아무것도 없음. 프레임의 상태를 설정하면 목록에 표시됨." +"Nothing to export" = "내보낼 항목 없음" +"Now" = "현재" +"Nudge (Shift: big nudge)" = "미세 이동(Shift: 크게 이동)" +"Nudge amount" = "미세 이동 거리" +"Number" = "숫자" +"Numbered list" = "번호 매기기 목록" +"Object" = "개체" +"Off" = "끔" +"Offered first when filling the slot (any content is allowed)" = "슬롯을 채울 때 먼저 제안됨(모든 콘텐츠 허용)" +"Offered first when swapping the instance (any component is allowed)" = "인스턴스를 교체할 때 먼저 제안됨(모든 컴포넌트 허용)" +"Offset" = "오프셋" +"On click" = "클릭 시" +"On drag" = "드래그 시" +"On the server's machine, `figcraft-server key` prints it." = "서버 컴퓨터에서 `figcraft-server key`를 실행하면 표시됨." +"On this page" = "이 페이지" +"Only the first changed layers are listed." = "변경된 레이어는 처음 일부만 표시됨." +"Only the first {n} changed layers are listed." = "변경된 레이어는 처음 {n}개만 표시됨." +"Only this computer can join (turn on network sharing to invite others)." = "이 컴퓨터만 참여할 수 있음(다른 사람을 초대하려면 네트워크 공유를 켜세요)." +"Only your threads" = "내 스레드만" +"Opacity" = "불투명도" +"Opacity & blend" = "불투명도 및 혼합" +"Opacity 10%…90%, 0: 100%" = "불투명도 10%…90%, 0: 100%" +"Open" = "열기" +"Open .figcraft, .svg or images" = ".figcraft, .svg 또는 이미지 열기" +"Open branch" = "브랜치 열기" +"Open file" = "파일 열기" +"Open files" = "열린 파일" +"Open in focus view" = "포커스 보기로 열기" +"Open in new window" = "새 창에서 열기" +"Open invite links in FigCraft" = "초대 링크를 FigCraft에서 열기" +"Open link" = "링크 열기" +"Open link {url}" = "링크 {url} 열기" +"Open overlay" = "오버레이 열기" +"Open prototype preview" = "프로토타입 미리 보기 열기" +"Open variables ({count})" = "변수 열기({count})" +"Opened “{name}” in a new tab" = "\"{name}\"을(를) 새 탭에서 열었음" +"Open|comments" = "미해결" +"Options" = "옵션" +"Or keep the file on a FigCraft server and share links to edit or to view it." = "또는 파일을 FigCraft 서버에 두고 편집용이나 보기용 링크를 공유하세요." +"Orange" = "주황" +"Outline stroke" = "선 윤곽선 만들기" +"Outline text" = "텍스트 윤곽선 만들기" +"Outlines" = "윤곽선" +"Outside" = "바깥쪽" +"Overflow" = "오버플로" +"Overlay" = "오버레이" +"Overlay position" = "오버레이 위치" +"Overridden here (the collection it extends has another value)" = "여기서 재정의됨(확장하는 컬렉션에는 다른 값이 있음)" +"Overrides" = "재정의" +"PDF print options" = "PDF 인쇄 옵션" +"PDF print settings" = "PDF 인쇄 설정" +"Padding" = "패딩" +"Page" = "페이지" +"Pages" = "페이지" +"Pages: {pages}" = "페이지: {pages}" +"Paint bucket" = "페인트 통" +"Pan the canvas" = "캔버스 이동" +"Panels" = "패널" +"Paper" = "종이" +"Paragraph indent" = "단락 들여쓰기" +"Paragraph indent applies to left-aligned text" = "단락 들여쓰기는 왼쪽 정렬 텍스트에 적용됨" +"Paragraph spacing" = "단락 간격" +"Pass through" = "통과" +"Paste a link (https://…)" = "링크 붙여 넣기(https://…)" +"Paste a team library link (a view link)" = "팀 라이브러리 링크(보기 링크) 붙여 넣기" +"Paste here" = "여기에 붙여 넣기" +"Paste the invite link the host shared with you." = "호스트가 공유한 초대 링크를 붙여 넣으세요." +"Paste to replace" = "붙여 넣어 바꾸기" +"Pattern" = "패턴" +"Pattern alignment" = "패턴 정렬" +"Pattern scale" = "패턴 배율" +"Pattern source" = "패턴 소스" +"Pen" = "펜" +"Pencil" = "연필" +"People in this file" = "이 파일의 사용자" +"Phone" = "휴대폰" +"Pick color" = "색상 추출" +"Pick color (I)" = "색상 추출(I)" +"Pick one font family first" = "먼저 글꼴 패밀리를 하나 선택하세요" +"Pin a property" = "속성 고정" +"Pinch" = "오므리기" +"Pixel grid" = "픽셀 그리드" +"Pixel preview 1x" = "픽셀 미리 보기 1x" +"Pixel preview 2x" = "픽셀 미리 보기 2x" +"Place automatically" = "자동 배치" +"Place image" = "이미지 배치" +"Plugins" = "플러그인" +"Plus darker" = "더 어둡게" +"Plus lighter" = "더 밝게" +"Point" = "점" +"Points" = "점" +"Polygon" = "다각형" +"Polygons" = "다각형" +"Position" = "위치" +"Post" = "게시" +"Preferences" = "환경설정" +"Preferred" = "선호" +"Present" = "프레젠테이션" +"Present or preview" = "프레젠테이션 또는 미리 보기" +"Present this flow" = "이 플로우 프레젠테이션" +"Presentation" = "프레젠테이션" +"Preserve scroll position" = "스크롤 위치 유지" +"Presets" = "프리셋" +"Press a key…" = "키를 누르세요…" +"Preview" = "미리 보기" +"Preview this flow" = "이 플로우 미리 보기" +"Preview this frame" = "이 프레임 미리 보기" +"Previous ready for dev" = "이전 개발 준비 완료" +"Progressive" = "점진적" +"Properties" = "속성" +"Prototype" = "프로토타입" +"Prototype preview" = "프로토타입 미리 보기" +"Prototype settings" = "프로토타입 설정" +"Publish" = "게시" +"Publish changes" = "변경 사항 게시" +"Publish to server" = "서버에 게시" +"Publish to server…" = "서버에 게시…" +"Published version {v}" = "버전 {v} 게시됨" +"Published version {v} to the server" = "버전 {v}을(를) 서버에 게시함" +"Published version {v}: save the file so other files can use it" = "버전 {v} 게시됨: 다른 파일에서 사용할 수 있도록 파일을 저장하세요" +"Published · {people}" = "게시됨 · {people}" +"Publishing to a server needs the desktop app; in the browser you can join a server's files" = "서버 게시에는 데스크톱 앱이 필요함. 브라우저에서는 서버의 파일에 참여할 수 있음" +"Publishing…" = "게시하는 중…" +"Push" = "밀어내기" +"Push changes to main component" = "변경 사항을 메인 컴포넌트에 푸시" +"Put text on path" = "텍스트를 패스에 배치" +"Radial" = "방사형" +"Radius" = "반경" +"Ratio" = "비율" +"Reading the library…" = "라이브러리를 읽는 중…" +"Ready for dev" = "개발 준비 완료" +"Real name" = "실명" +"Recent" = "최근" +"Recent files" = "최근 파일" +"Recents" = "최근 항목" +"Recovered {n} unsaved files after the app quit unexpectedly: save them to keep them" = { other = "앱이 예기치 않게 종료되어 저장되지 않은 파일 {n}개를 복구함: 유지하려면 저장하세요" } +"Rectangle" = "사각형" +"Rectangles" = "사각형" +"Red" = "빨강" +"Reduce motion" = "동작 줄이기" +"Refraction" = "굴절" +"Remove" = "제거" +"Remove all" = "모두 제거" +"Remove annotation" = "주석 제거" +"Remove auto layout" = "자동 레이아웃 제거" +"Remove dev resource" = "개발 리소스 제거" +"Remove export setting" = "내보내기 설정 제거" +"Remove guide" = "안내선 제거" +"Remove interaction" = "인터랙션 제거" +"Remove library from this file" = "이 파일에서 라이브러리 제거" +"Remove min and max" = "최소 및 최대 제거" +"Remove min and max height" = "최소 및 최대 높이 제거" +"Remove min and max width" = "최소 및 최대 너비 제거" +"Remove regions" = "영역 제거" +"Remove slot" = "슬롯 제거" +"Remove starting point" = "시작점 제거" +"Remove stop" = "정지점 제거" +"Remove text from path" = "패스에서 텍스트 제거" +"Remove the else and its actions" = "\"그 외\"와 해당 액션 제거" +"Remove this condition and its actions" = "이 조건과 해당 액션 제거" +"Removed" = "제거됨" +"Removed since it was marked" = "표시된 뒤 제거됨" +"Rename" = "이름 바꾸기" +"Rename duplicated layers" = "복제한 레이어 이름 바꾸기" +"Rename folder" = "폴더 이름 바꾸기" +"Rename group" = "그룹 이름 바꾸기" +"Rename mode" = "모드 이름 바꾸기" +"Rename page" = "페이지 이름 바꾸기" +"Replace all" = "모두 바꾸기" +"Replace mixed export settings" = "혼합된 내보내기 설정 바꾸기" +"Replace with" = "바꿀 내용" +"Replace with a new interaction" = "새 인터랙션으로 바꾸기" +"Reply" = "답글" +"Reset" = "재설정" +"Reset adjustments" = "조정 재설정" +"Reset all changes" = "모든 변경 사항 재설정" +"Reset all overrides on this layer" = "이 레이어의 모든 재정의 재설정" +"Reset overrides" = "재정의 재설정" +"Reset slot" = "슬롯 재설정" +"Reset this override" = "이 재정의 재설정" +"Reset to style" = "스타일로 재설정" +"Reset to the inherited value" = "상속된 값으로 재설정" +"Resize by the nudge amount" = "미세 이동 거리만큼 크기 조정" +"Resize frames to the device's screen (or the window without a device): their constraints and auto layout respond" = "프레임 크기를 기기 화면(기기가 없으면 창)에 맞게 조정: 제약과 자동 레이아웃이 반응함" +"Resize to fit" = "크기 맞춤" +"Resolve" = "해결" +"Resolve change" = "변경 사항 해결" +"Resolved" = "해결됨" +"Resources" = "리소스" +"Responsive" = "반응형" +"Restart" = "다시 시작" +"Restore" = "복원" +"Restore main component" = "메인 컴포넌트 복원" +"Restore this version" = "이 버전 복원" +"Restored “{name}”" = "\"{name}\" 복원됨" +"Reverse the order" = "순서 뒤집기" +"Reversed triangle" = "역삼각형" +"Review and merge" = "검토 및 병합" +"Ribbon" = "리본" +"Right" = "오른쪽" +"Right side" = "오른쪽" +"Right side width" = "오른쪽 너비" +"Rotate 90°" = "90° 회전" +"Rotate 90° right" = "오른쪽으로 90° 회전" +"Rotate to landscape" = "가로로 회전" +"Rotate to portrait" = "세로로 회전" +"Rotation" = "회전" +"Rotation jitter" = "회전 지터" +"Round" = "둥글게" +"Rounded" = "둥근" +"Row" = "행" +"Row gap" = "행 간격" +"Row sizes" = "행 크기" +"Row span" = "행 범위" +"Rows" = "행" +"Rows {count}" = "행 {count}" +"Rulers" = "눈금자" +"Run" = "실행" +"Run {label}" = "{label} 실행" +"Same as layer" = "레이어와 동일" +"Saturation" = "채도" +"Save" = "저장" +"Save as" = "다른 이름으로 저장" +"Save as preset…" = "프리셋으로 저장…" +"Save version {key}" = "버전 저장 {key}" +"Saved" = "저장됨" +"Saved {name}" = "{name} 저장됨" +"Scale" = "배율" +"Scatter" = "분산" +"Scoping: where pickers offer it" = "범위: 선택기에서 제안되는 위치" +"Screen" = "스크린" +"Scroll behavior" = "스크롤 동작" +"Scroll to" = "스크롤 대상" +"Scroll to layer" = "레이어로 스크롤" +"Scroll with parent" = "부모와 함께 스크롤" +"Search" = "검색" +"Search actions, layers and tools" = "액션, 레이어, 도구 검색" +"Search assets" = "에셋 검색" +"Search comments" = "댓글 검색" +"Search fonts" = "글꼴 검색" +"Search layers" = "레이어 검색" +"Search shortcuts" = "단축키 검색" +"Section" = "섹션" +"Section color" = "섹션 색상" +"Sections" = "섹션" +"Select a frame and add a starting point to present it as a flow." = "프레임을 선택하고 시작점을 추가하면 플로우로 프레젠테이션할 수 있음." +"Select a frame to preview it" = "프레임을 선택하면 미리 볼 수 있음" +"Select a layer to see its properties and code" = "레이어를 선택하면 속성과 코드가 표시됨" +"Select all" = "모두 선택" +"Select all with same" = "같은 항목 모두 선택" +"Select layer" = "레이어 선택" +"Select layers to apply the style to" = "스타일을 적용할 레이어를 선택하세요" +"Select overlapping shapes" = "겹친 도형 선택" +"Select points to edit their position, radius and mirroring" = "점을 선택해 위치, 반경, 대칭 편집" +"Select slot" = "슬롯 선택" +"Selection" = "선택 항목" +"Selection box, {w} by {h} at {x}, {y}: arrows move it, Shift+arrows size it, Enter selects, Escape cancels" = "선택 상자, {w} × {h}, 위치 {x}, {y}: 화살표로 이동, Shift+화살표로 크기 조정, Enter로 선택, Escape로 취소" +"Selection box: arrows move it, Shift+arrows size it, Enter selects, Escape cancels" = "선택 상자: 화살표로 이동, Shift+화살표로 크기 조정, Enter로 선택, Escape로 취소" +"Send backward" = "뒤로 보내기" +"Send to back" = "맨 뒤로 보내기" +"Server address" = "서버 주소" +"Set as default" = "기본값으로 설정" +"Set variable" = "변수 설정" +"Set variable mode" = "변수 모드 설정" +"Set variable {name}" = "변수 {name} 설정" +"Set {name} to {value}" = "{name}을(를) {value}(으)로 설정" +"Shadows" = "어두운 영역" +"Shape" = "도형" +"Shape builder" = "도형 빌더" +"Shape tools" = "도형 도구" +"Share" = "공유" +"Share on the local network" = "로컬 네트워크에서 공유" +"Share: live session, export" = "공유: 라이브 세션, 내보내기" +"Show" = "표시" +"Show as grid" = "그리드로 보기" +"Show as list" = "목록으로 보기" +"Show autosaves" = "자동 저장 표시" +"Show behind transparent areas" = "투명 영역 뒤에 표시" +"Show comments (Shift+C)" = "댓글 표시(Shift+C)" +"Show device frame" = "기기 프레임 표시" +"Show dimensions on objects" = "개체에 치수 표시" +"Show hotspot hints" = "핫스팟 힌트 표시" +"Show only this on the canvas" = "캔버스에 이것만 표시" +"Show open" = "미해결 표시" +"Show section contents" = "섹션 콘텐츠 표시" +"Show this layer" = "이 레이어 표시" +"Show usage" = "사용 현황 표시" +"Show/Hide" = "표시/숨기기" +"Show/Hide UI" = "UI 표시/숨기기" +"Side by side" = "나란히 보기" +"Sidebar" = "사이드바" +"Simplify stroke" = "선 단순화" +"Size" = "크기" +"Size jitter" = "크기 지터" +"Skip ink" = "디센더 건너뛰기" +"Slashed zero" = "사선 있는 0" +"Slice" = "슬라이스" +"Slices" = "슬라이스" +"Slide in" = "슬라이드 인" +"Slide out" = "슬라이드 아웃" +"Slot" = "슬롯" +"Slot content" = "슬롯 콘텐츠" +"Small capitals" = "작은 대문자" +"Small caps" = "작은 대문자" +"Smart animate" = "스마트 애니메이트" +"Snap to pixel grid" = "픽셀 그리드에 맞춤" +"Social media" = "소셜 미디어" +"Soft light" = "소프트 라이트" +"Solid" = "실선" +"Some variants have the same property values: give each one a unique combination" = "일부 배리언트의 속성 값이 같음: 각각 고유한 조합을 지정하세요" +"Sort" = "정렬" +"Sort by date" = "날짜순 정렬" +"Sort by page" = "페이지순 정렬" +"Space around" = "주변 간격 균등" +"Space between" = "사이 간격 균등" +"Space drag" = "Space 드래그" +"Space evenly" = "균등 간격" +"Space+drag" = "Space+드래그" +"Spacing" = "간격" +"Splay" = "펼침" +"Spread" = "확산" +"Square" = "정사각형" +"Standard" = "표준" +"Standard ligatures" = "표준 합자" +"Star" = "별" +"Stars" = "별" +"Start" = "시작" +"Start from a blank canvas" = "빈 캔버스로 시작" +"Start live session" = "라이브 세션 시작" +"Start on path" = "패스 시작 위치" +"Start point" = "시작점" +"Status" = "상태" +"Sticky" = "고정" +"Stop following {name}" = "{name} 따라가기 중지" +"Stop session" = "세션 중지" +"Stop {n} {hex}" = "정지점 {n} {hex}" +"Stretch" = "늘이기" +"Strikethrough" = "취소선" +"String" = "문자열" +"Stroke" = "선" +"Stroke style" = "선 스타일" +"Stroke weight" = "선 두께" +"Strokes" = "선" +"Style" = "스타일" +"Styles" = "스타일" +"Stylistic set 1" = "스타일 세트 1" +"Stylistic set 2" = "스타일 세트 2" +"Stylistic set 3" = "스타일 세트 3" +"Stylistic set 4" = "스타일 세트 4" +"Stylistic set 5" = "스타일 세트 5" +"Subtract" = "빼기" +"Subtracts" = "빼기" +"Suffix" = "접미사" +"Swap instance" = "인스턴스 교체" +"Swap library: use another library's assets of the same names" = "라이브러리 교체: 다른 라이브러리의 같은 이름 에셋 사용" +"Swap orientation" = "방향 바꾸기" +"Swap overlay" = "오버레이 교체" +"Swap to {name}" = "{name}(으)로 교체" +"Swap width and height" = "너비와 높이 바꾸기" +"Swapped instance" = "교체된 인스턴스" +"Swapped {n} assets" = { other = "에셋 {n}개 교체함" } +"Swapped {n} assets; {missed} had no match and still use the old library" = { other = "에셋 {n}개 교체함. {missed}개는 일치 항목이 없어 이전 라이브러리를 계속 사용함" } +"Sweep" = "범위" +"System" = "시스템" +"Tab / Shift+Tab" = "Tab / Shift+Tab" +"Table" = "표" +"Tablet" = "태블릿" +"Tabular numbers" = "고정폭 숫자" +"Take the values from the first selected layer" = "처음 선택한 레이어의 값 사용" +"Taper" = "가늘게" +"Taper both ends" = "양 끝 가늘게" +"Temperature" = "색온도" +"Template" = "템플릿" +"Text" = "텍스트" +"Text align" = "텍스트 정렬" +"Text content" = "텍스트 내용" +"Text style" = "텍스트 스타일" +"Text styles" = "텍스트 스타일" +"Texts" = "텍스트" +"Texture" = "텍스처" +"The canvas previews colors in sRGB; exported PNG, JPG and WebP files are tagged Display P3." = "캔버스는 sRGB로 색상을 미리 보여 줌. 내보낸 PNG, JPG, WebP 파일에는 Display P3 태그가 붙음." +"The file now holds another library" = "이 파일은 이제 다른 라이브러리를 담고 있음" +"The file now holds another library (\"{name}\")" = "이 파일은 이제 다른 라이브러리(\"{name}\")를 담고 있음" +"The link carries the session's secret: share it only with people you invite." = "링크에는 세션의 비밀 정보가 담겨 있음: 초대할 사람과만 공유하세요." +"The selection uses several text styles: click to apply one" = "선택 항목에 여러 텍스트 스타일이 사용됨: 클릭해 하나를 적용" +"Theme" = "테마" +"There's no destination for that action" = "해당 액션의 대상이 없음" +"Thickness" = "두께" +"This branch can't be reviewed: {e}" = "이 브랜치를 검토할 수 없음: {e}" +"This branch was merged or archived." = "이 브랜치는 병합 또는 보관되었음." +"This condition is edited as an expression" = "이 조건은 수식으로 편집됨" +"This file" = "이 파일" +"This file has unsaved changes" = "이 파일에 저장되지 않은 변경 사항이 있음" +"This frame is new on the branch." = "이 프레임은 브랜치에서 새로 만들어졌음." +"This frame isn't on the branch." = "이 프레임은 브랜치에 없음." +"Tidy up" = "정돈" +"Tile" = "타일" +"Tile type" = "타일 유형" +"Tint" = "색조 보정" +"Title" = "제목" +"Title case" = "제목 대소문자" +"To share this library with your team, publish the file to a server (Share ▸ Publish to server…), then publish the library there." = "이 라이브러리를 팀과 공유하려면 파일을 서버에 게시(공유 ▸ 서버에 게시…)한 다음 그곳에서 라이브러리를 게시하세요." +"Toggle" = "전환" +"Toggle light/dark theme" = "라이트/다크 테마 전환" +"Toggle visibility" = "표시 여부 전환" +"Tools" = "도구" +"Top" = "위쪽" +"Top & bottom" = "위쪽 및 아래쪽" +"Top left radius" = "왼쪽 위 반경" +"Top right radius" = "오른쪽 위 반경" +"Transform" = "변형" +"Triangle arrow" = "삼각 화살표" +"Trigger" = "트리거" +"True" = "참" +"Truncate text" = "텍스트 자르기" +"Truncate with an ellipsis" = "줄임표로 자르기" +"Try another search or filter." = "다른 검색어나 필터를 사용해 보세요." +"Two digits" = "두 자리" +"Type" = "유형" +"Type settings" = "문자 설정" +"Typography" = "타이포그래피" +"Underline" = "밑줄" +"Undo takes back only your own changes; what others changed since stays." = "실행 취소는 내 변경 사항만 되돌림. 그 뒤 다른 사람이 변경한 내용은 유지됨." +"Ungroup" = "그룹 해제" +"Uniform" = "균일" +"Union" = "합치기" +"Unions" = "합치기" +"Unknown — treated as sRGB" = "알 수 없음 — sRGB로 처리" +"Unread" = "읽지 않음" +"Unresolve" = "미해결로 되돌리기" +"Unsaved changes" = "저장되지 않은 변경 사항" +"Unsaved changes in {names}. Close the window and lose them?" = "{names}에 저장되지 않은 변경 사항이 있음. 창을 닫고 변경 사항을 버릴까요?" +"Unsaved changes: save first ({save}), or close the tab with {alt}-click to discard" = "저장되지 않은 변경 사항: 먼저 저장({save})하거나 {alt}-클릭으로 탭을 닫아 버리세요" +"Unsaved changes: save first, or close again with {key} to discard" = "저장되지 않은 변경 사항: 먼저 저장하거나 {key}로 다시 닫아 버리세요" +"Up" = "위" +"Update" = "업데이트" +"Update from main" = "메인에서 업데이트" +"Update from selection" = "선택 항목에서 업데이트" +"Updated {components} and {styles}" = "{components} 및 {styles} 업데이트됨" +"Uploads this file to a FigCraft server and keeps this tab in sync with it. You get a link to edit and a link to view." = "이 파일을 FigCraft 서버에 업로드하고 이 탭을 동기화된 상태로 유지함. 편집 링크와 보기 링크가 생성됨." +"Uppercase" = "대문자" +"Use a fixed value" = "고정 값 사용" +"Use an expression, e.g. count + 1" = "수식 사용(예: count + 1)" +"Use as mask" = "마스크로 사용" +"Use auto layout" = "자동 레이아웃 사용" +"Use number keys for opacity" = "숫자 키로 불투명도 변경" +"Use the layer's fill" = "레이어의 채우기 사용" +"Used in {files} · {instances}" = "{files}에서 사용 · {instances}" +"Username" = "사용자 이름" +"Value" = "값" +"Variable" = "변수" +"Variable collections" = "변수 컬렉션" +"Variable modes" = "변수 모드" +"Variable width" = "가변 너비" +"Variables" = "변수" +"Variables JSON…" = "변수 JSON…" +"Variables store reusable values (colours, numbers, strings, booleans) with modes such as Light and Dark." = "변수는 재사용 가능한 값(색상, 숫자, 문자열, 불리언)을 라이트와 다크 같은 모드와 함께 저장함." +"Variant" = "배리언트" +"Vector" = "벡터" +"Vectors" = "벡터" +"Version" = "버전" +"Version history" = "버전 기록" +"Version {version}" = "버전 {version}" +"Version {v} · {components} · {styles} · {variables}" = "버전 {v} · {components} · {styles} · {variables}" +"Vertical" = "세로" +"Vertical align" = "세로 정렬" +"Vertical hex" = "세로 육각형" +"Vertical padding" = "세로 패딩" +"Vertical spacing" = "세로 간격" +"Vertical trim" = "세로 여백 자르기" +"View" = "보기" +"View link" = "보기 링크" +"View link copied" = "보기 링크 복사됨" +"View only" = "보기 전용" +"View only: you see every change as it happens but can't edit. Leave to keep a copy you can edit." = "보기 전용: 모든 변경을 실시간으로 볼 수 있지만 편집은 불가. 나가면 편집 가능한 사본이 남음." +"Viewing “{name}”" = "\"{name}\" 보는 중" +"Violet" = "보라" +"Visibility" = "표시 여부" +"Visible" = "표시됨" +"Vivid" = "선명하게" +"Warm" = "따뜻하게" +"Watch" = "시계" +"Wavy" = "물결선" +"Web" = "웹" +"WebSocket URL" = "WebSocket URL" +"WebSocket URL copied" = "WebSocket URL 복사됨" +"Wedge" = "쐐기" +"Weight" = "굵기" +"What changed since it was marked ready for dev" = "개발 준비 완료로 표시된 뒤 변경된 내용" +"What it's for" = "용도" +"What this changed from isn't known: it changed before FigCraft kept a copy of ready-for-dev frames. Resolve the change (or mark it ready again) to compare from now on." = "무엇에서 바뀌었는지 알 수 없음: FigCraft가 개발 준비 완료 프레임의 사본을 보관하기 전에 변경됨. 변경을 해결(또는 다시 준비 완료로 표시)하면 이후부터 비교함." +"While hovering" = "마우스를 올린 동안" +"While pressing" = "누르는 동안" +"White" = "흰색" +"Why it changed" = "변경 이유" +"Width" = "너비" +"Width point" = "너비 점" +"Width profile" = "너비 프로필" +"With the layers' export settings" = "레이어의 내보내기 설정으로" +"Wrap" = "줄 바꿈" +"Wrap in new section" = "새 섹션으로 감싸기" +"Yellow" = "노랑" +"Yesterday" = "어제" +"You" = "나" +"You'll get the host's file as a new tab and edit it together." = "호스트의 파일이 새 탭으로 열리고 함께 편집할 수 있음." +"Your copy of the file stays open" = "내 파일 사본은 열린 상태로 유지됨" +"Your name" = "내 이름" +"Your name in comments" = "댓글에 표시할 이름" +"Your system asks for reduced motion: animations stay off." = "시스템에서 동작 줄이기를 요청하므로 애니메이션이 꺼져 있음." +"Zoom" = "확대/축소" +"Zoom around the pointer" = "포인터 중심으로 확대/축소" +"Zoom device to fill window" = "기기를 창에 꽉 차게 확대/축소" +"Zoom in" = "확대" +"Zoom out" = "축소" +"Zoom to 100%" = "100%로 확대/축소" +"Zoom to 200%" = "200%로 확대/축소" +"Zoom to 50%" = "50%로 확대/축소" +"Zoom to fit" = "화면에 맞게 확대/축소" +"Zoom to selection" = "선택 항목으로 확대/축소" +"Zoom tool: click to zoom in, drag an area" = "확대/축소 도구: 클릭해 확대, 영역을 드래그" +"Zoom tool: zoom out" = "확대/축소 도구: 축소" +"and {n} more" = { other = "외 {n}개" } +"bleed marks" = "도련 표시" +"can edit the document" = "문서를 편집할 수 있음" +"crop marks" = "재단선 표시" +"development: {path}" = "개발: {path}" +"e.g. count + 1" = "예: count + 1" +"e.g. count >= 3 and not done" = "예: count >= 3 and not done" +"figcraft:// links from a browser, chat or email open this app and join the session." = "브라우저, 채팅, 이메일의 figcraft:// 링크로 이 앱을 열고 세션에 참여함." +"hidden" = "숨김" +"iOS" = "iOS" +"locked" = "잠김" +"no bleed" = "도련 없음" +"nobody else here yet" = "아직 다른 사람이 없음" +"now" = "방금" +"or" = "또는" +"reads the document" = "문서를 읽음" +"the plugin" = "이 플러그인" +"this session only" = "이 세션만" +"{instances} in {files}" = "{files}의 {instances}" +"{language}: draft translation, waiting for a native speaker's review." = "{language}: 초안 번역, 원어민 검토 대기 중." +"{length} bleed" = "도련 {length}" +"{name}\nClick to apply to the selection" = "{name}\n클릭해 선택 항목에 적용" +"{name}\nDrag onto the canvas, or click to place in the middle of the view.\nHold Alt (Option) while dropping onto an instance to swap it." = "{name}\n캔버스로 드래그하거나 클릭해 보기 가운데에 배치하세요.\n인스턴스 위에 놓을 때 Alt(Option)를 누르고 있으면 교체됨." +"{name} (from {library})" = "{name}({library}에서)" +"{name} (you)" = "{name}(나)" +"{name} ({layers} layers)" = "{name}(레이어 {layers}개)" +"{name} ({tag}): {min} – {max}, default {default}. Double-click the slider to go back to the style's value; Escape while dragging cancels." = "{name}({tag}): {min} – {max}, 기본값 {default}. 슬라이더를 두 번 클릭하면 스타일 값으로 돌아감. 드래그 중 Escape를 누르면 취소됨." +"{name} from {path}" = "{path}의 {name}" +"{name} · deleted on main" = "{name} · 메인에서 삭제됨" +"{name} · deleted on the branch" = "{name} · 브랜치에서 삭제됨" +"{name} · not published" = "{name} · 게시되지 않음" +"{name} · on a server" = "{name} · 서버에 있음" +"{name} · published version {v}" = "{name} · 게시된 버전 {v}" +"{name} · version {v} on the server" = "{name} · 서버의 버전 {v}" +"{name}, {kind}, {w} by {h}, selected" = "{name}, {kind}, {w} × {h}, 선택됨" +"{n} added" = { other = "{n}개 추가됨" } +"{n} autosave versions" = { other = "자동 저장 버전 {n}개" } +"{n} changed" = { other = "{n}개 변경됨" } +"{n} columns" = { other = "{n}열" } +"{n} components" = { other = "컴포넌트 {n}개" } +"{n} components and styles have newer versions" = { other = "컴포넌트 및 스타일 {n}개에 새 버전이 있음" } +"{n} conflicts to resolve" = { other = "해결할 충돌 {n}개" } +"{n} days ago" = { other = "{n}일 전" } +"{n} files" = { other = "파일 {n}개" } +"{n} hours ago" = { other = "{n}시간 전" } +"{n} instances" = { other = "인스턴스 {n}개" } +"{n} layers" = { other = "레이어 {n}개" } +"{n} layers as one file" = { other = "레이어 {n}개를 파일 하나로" } +"{n} layers selected" = { other = "레이어 {n}개 선택됨" } +"{n} layers · {parts}" = { other = "레이어 {n}개 · {parts}" } +"{n} matches" = { other = "{n}개 일치" } +"{n} minutes ago" = { other = "{n}분 전" } +"{n} months ago" = { other = "{n}개월 전" } +"{n} of {total}" = "{n} / {total}" +"{n} people joined" = { other = "{n}명 참여함" } +"{n} preferred components" = { other = "선호 컴포넌트 {n}개" } +"{n} ready" = { other = "{n}개 준비 완료" } +"{n} removed" = { other = "{n}개 제거됨" } +"{n} replies" = { other = "답글 {n}개" } +"{n} rows" = { other = "{n}행" } +"{n} styles" = { other = "스타일 {n}개" } +"{n} variables" = { other = "변수 {n}개" } +"{n} weeks ago" = { other = "{n}주 전" } +"{n} years ago" = { other = "{n}년 전" } +"{n}d" = "{n}일" +"{n}h" = "{n}시간" +"{n}m" = "{n}분" +"{n}w" = "{n}주" +"{page}, nothing selected" = "{page}, 선택된 항목 없음" +"{profile} (current)" = "{profile}(현재)" +"{property} is its value; {property ? \"a\" : \"b\"} picks a string. Other {…} stays as written." = "{property}는 그 값이 되고, {property ? \"a\" : \"b\"}는 문자열을 고름. 그 밖의 {…}는 작성된 대로 유지됨." +"{tool} hold {key}" = "{tool} {key} 길게 누르기" +"{value} isn't a colour" = "{value}은(는) 색상이 아님" +"{when} · edited" = "{when} · 편집됨" +"← ↑ → ↓" = "← ↑ → ↓" +"⇥ / ⇧⇥" = "⇥ / ⇧⇥" +"⌘ arrows" = "⌘ 화살표" +"⌘ click" = "⌘ 클릭" +"⌘ scroll" = "⌘ 스크롤" +"⌥ drag" = "⌥ 드래그" + +[commands] +"align.bottom" = "아래쪽 정렬" +"align.hcenter" = "수평 가운데 정렬" +"align.left" = "왼쪽 정렬" +"align.right" = "오른쪽 정렬" +"align.top" = "위쪽 정렬" +"align.vcenter" = "수직 가운데 정렬" +"annotation.add" = "주석 추가" +"annotation.addCategory" = "주석 카테고리 추가" +"annotation.categories" = "주석 카테고리" +"annotation.edit" = "주석 편집" +"annotation.editCategory" = "주석 카테고리 편집" +"annotation.list" = "주석 목록" +"annotation.remove" = "주석 제거" +"annotation.removeCategory" = "주석 카테고리 삭제" +"app.actions" = "액션" +"app.preferences" = "환경설정" +"arrange.back" = "맨 뒤로 보내기" +"arrange.backward" = "뒤로 보내기" +"arrange.forward" = "앞으로 가져오기" +"arrange.front" = "맨 앞으로 가져오기" +"arrange.packH" = "가로로 붙이기" +"arrange.packV" = "세로로 붙이기" +"arrange.roundToPixels" = "픽셀에 맞춰 반올림" +"arrange.tidy" = "정돈" +"bool.exclude" = "선택 항목 제외" +"bool.flatten" = "불리언 평면화" +"bool.intersect" = "선택 항목 교차" +"bool.subtract" = "선택 항목 빼기" +"bool.union" = "선택 항목 합치기" +"branch.archive" = "브랜치 보관" +"branch.create" = "브랜치 만들기" +"branch.list" = "브랜치 목록" +"branch.merge" = "브랜치 병합" +"branch.open" = "브랜치 열기" +"branch.review" = "브랜치 검토" +"branch.updateFromMain" = "메인에서 업데이트" +"codeConnect.export" = "코드 연결 내보내기" +"codeConnect.import" = "코드 연결 가져오기" +"codeConnect.remove" = "코드 연결 해제" +"codeConnect.set" = "코드에 연결" +"collab.cursor" = "커서 위치 표시" +"collab.diff" = "동기화된 변경 사항 표시" +"collab.follow" = "따라가기" +"collab.host" = "라이브 세션 시작" +"collab.join" = "라이브 세션 참여" +"collab.leave" = "라이브 세션 나가기" +"collab.peers" = "이 파일의 사용자" +"collab.publish" = "서버에 게시" +"collab.registerLinks" = "초대 링크를 FigCraft에서 열기" +"collab.stop" = "라이브 세션 중지" +"command.batch" = "여러 명령 실행" +"comment.add" = "댓글 추가" +"comment.delete" = "댓글 삭제" +"comment.edit" = "댓글 편집" +"comment.link" = "댓글 링크 복사" +"comment.list" = "댓글 목록" +"comment.markRead" = "댓글을 읽음으로 표시" +"comment.move" = "댓글 이동" +"comment.next" = "다음 댓글" +"comment.open" = "댓글 열기" +"comment.people" = "댓글 참여자" +"comment.react" = "댓글에 반응" +"comment.reply" = "댓글에 답글" +"comment.resolve" = "댓글 해결" +"comment.zoom" = "댓글로 확대/축소" +"component.addProperty" = "컴포넌트 속성 추가" +"component.addVariant" = "배리언트 추가" +"component.bindProperty" = "레이어를 속성에 연결" +"component.combineVariants" = "배리언트로 결합" +"component.create" = "컴포넌트 만들기" +"component.createMultiple" = "여러 컴포넌트 만들기" +"component.deleteProperty" = "컴포넌트 속성 삭제" +"component.detach" = "인스턴스 분리" +"component.editProperty" = "컴포넌트 속성 편집" +"component.exposeInstance" = "중첩된 인스턴스 노출" +"component.goToMain" = "메인 컴포넌트로 이동" +"component.list" = "컴포넌트 목록" +"component.makeSlot" = "슬롯으로 만들기" +"component.properties" = "컴포넌트 속성" +"component.pushChanges" = "변경 사항을 메인 컴포넌트에 푸시" +"component.removeSlot" = "슬롯 제거" +"component.resetInstance" = "모든 변경 사항 재설정" +"component.resetOverride" = "재정의 재설정" +"component.restoreMain" = "메인 컴포넌트 복원" +"dev.compare" = "변경 사항 비교" +"dev.focus" = "포커스 보기" +"dev.resolveChange" = "변경 사항 해결" +"dev.unfocus" = "포커스 보기 종료" +"devResource.add" = "개발 리소스 추가" +"devResource.edit" = "개발 리소스 편집" +"devResource.list" = "개발 리소스 목록" +"devResource.remove" = "개발 리소스 제거" +"distribute.horizontal" = "수평 간격 균등 분포" +"distribute.vertical" = "수직 간격 균등 분포" +"doc.home" = "홈" +"doc.list" = "문서 목록" +"doc.nextTab" = "다음 탭" +"doc.previousTab" = "이전 탭" +"doc.switch" = "문서 전환" +"edit.copy" = "복사" +"edit.copyAsCss" = "CSS로 복사" +"edit.copyAsPng" = "PNG로 복사" +"edit.copyAsSvg" = "SVG로 복사" +"edit.copyAsText" = "텍스트로 복사" +"edit.copyLink" = "선택 항목 링크 복사" +"edit.copyProperties" = "속성 복사" +"edit.cut" = "잘라내기" +"edit.delete" = "삭제" +"edit.duplicate" = "복제" +"edit.findReplace" = "찾기 및 바꾸기" +"edit.paste" = "붙여 넣기" +"edit.pasteOver" = "선택 항목 위에 붙여 넣기" +"edit.pasteProperties" = "속성 붙여 넣기" +"edit.pasteReplace" = "붙여 넣어 바꾸기" +"edit.pickColor" = "색상 추출" +"edit.redo" = "다시 실행" +"edit.repeat" = "마지막 명령 반복" +"edit.setDefaultProperties" = "기본 속성 설정" +"edit.undo" = "실행 취소" +"effect.add" = "효과 추가" +"effect.move" = "효과 이동" +"effect.remove" = "효과 제거" +"effect.set" = "효과 설정" +"export.add" = "내보내기 설정 추가" +"export.remove" = "내보내기 설정 제거" +"export.update" = "내보내기 설정 편집" +"file.close" = "탭 닫기" +"file.colorProfile" = "색상 프로필" +"file.duplicate" = "파일 복제" +"file.export" = "내보내기" +"file.exportFramesPdf" = "프레임을 PDF로 내보내기" +"file.exportLayers" = "레이어 내보내기" +"file.exportSvg" = "선택 항목을 SVG로 내보내기" +"file.import" = "가져오기" +"file.new" = "새 디자인 파일" +"file.open" = "열기" +"file.openRecent" = "최근 파일 열기" +"file.placeImage" = "이미지 배치" +"file.recover" = "파일 복구" +"file.rename" = "파일 이름 바꾸기" +"file.revert" = "저장된 상태로 되돌리기" +"file.save" = "저장" +"file.saveAs" = "다른 이름으로 저장" +"file.saveVersion" = "버전 기록에 저장" +"file.versionHistory" = "버전 기록 표시" +"fill.add" = "채우기 추가" +"fill.move" = "채우기 이동" +"fill.pattern" = "패턴 채우기" +"fill.remove" = "채우기 제거" +"fill.set" = "채우기 설정" +"frame.create" = "프레임 만들기" +"frame.presets" = "프레임 프리셋 목록" +"frame.swapOrientation" = "방향 바꾸기" +"grid.add" = "레이아웃 그리드 추가" +"grid.move" = "레이아웃 그리드 이동" +"grid.remove" = "레이아웃 그리드 제거" +"guide.add" = "안내선 추가" +"guide.clear" = "모든 안내선 제거" +"guide.move" = "안내선 이동" +"guide.remove" = "안내선 제거" +"guide.select" = "안내선 선택" +"help.about" = "FigCraft 정보" +"help.page" = "도움말 페이지" +"help.shortcuts" = "키보드 단축키" +"image.adjust" = "이미지 조정" +"image.deletePreset" = "이미지 프리셋 삭제" +"image.place" = "이미지 배치" +"image.presets" = "이미지 프리셋" +"image.savePreset" = "이미지 프리셋 저장" +"inspect.assets" = "에셋 검사" +"inspect.code" = "레이어 코드" +"inspect.componentCode" = "컴포넌트 코드" +"inspect.properties" = "속성 검사" +"inspect.readyForDev" = "개발 준비 완료" +"instance.create" = "인스턴스 만들기" +"instance.exposed" = "노출된 중첩 인스턴스" +"instance.place" = "인스턴스 배치" +"instance.resetSlot" = "슬롯 재설정" +"instance.setProperties" = "인스턴스 속성 설정" +"instance.slotInsert" = "슬롯에 삽입" +"instance.swap" = "인스턴스 교체" +"instance.swapAt" = "위치의 인스턴스 교체" +"layers.collapseAll" = "레이어 접기" +"layout.add" = "자동 레이아웃 추가" +"layout.remove" = "자동 레이아웃 제거" +"layout.setTrack" = "그리드 트랙 크기 설정" +"layout.suggest" = "자동 레이아웃 제안" +"libraries.open" = "라이브러리" +"libraries.publish" = "라이브러리 게시…" +"library.acceptUpdates" = "라이브러리 업데이트 수락" +"library.add" = "라이브러리 추가" +"library.aliasVariable" = "라이브러리 변수 별칭" +"library.applyStyle" = "라이브러리 스타일 적용" +"library.bindVariable" = "라이브러리 변수 연결" +"library.extendCollection" = "라이브러리 컬렉션 확장" +"library.import" = "라이브러리 컴포넌트 가져오기" +"library.importVariable" = "라이브러리 변수 가져오기" +"library.list" = "라이브러리 목록" +"library.place" = "라이브러리 컴포넌트 배치" +"library.publish" = "라이브러리 게시" +"library.publishToServer" = "라이브러리를 서버에 게시" +"library.remove" = "라이브러리 제거" +"library.setVariableMode" = "라이브러리 변수 모드 설정" +"library.swap" = "라이브러리 교체" +"library.swapAt" = "인스턴스를 라이브러리 컴포넌트로 교체" +"library.updates" = "라이브러리 업데이트" +"library.usage" = "라이브러리 사용 현황" +"measure.distances" = "거리 측정" +"measure.padding" = "자동 레이아웃 패딩 측정" +"node.create" = "레이어 만들기" +"node.get" = "레이어 가져오기" +"node.reorder" = "레이어 순서 변경" +"node.reparent" = "레이어를 안으로 이동" +"node.set" = "속성 설정" +"object.batchRename" = "일괄 이름 바꾸기" +"object.flipH" = "가로로 뒤집기" +"object.flipV" = "세로로 뒤집기" +"object.frameSelection" = "선택 항목을 프레임으로 감싸기" +"object.group" = "선택 항목 그룹화" +"object.hideOthers" = "다른 레이어 숨기기" +"object.mask" = "마스크로 사용" +"object.moveToPage" = "페이지로 이동" +"object.opacityKeys" = "숫자 키로 불투명도" +"object.rasterize" = "선택 항목 래스터화" +"object.releaseMask" = "마스크 해제" +"object.removeFill" = "채우기 제거" +"object.removeFrame" = "프레임 제거" +"object.removeStroke" = "선 제거" +"object.rename" = "이름 바꾸기" +"object.resizeToFit" = "크기 맞춤" +"object.rotate180" = "180° 회전" +"object.rotateLeft" = "왼쪽으로 90° 회전" +"object.rotateRight" = "오른쪽으로 90° 회전" +"object.setThumbnail" = "썸네일로 설정" +"object.swapFillStroke" = "채우기와 선 바꾸기" +"object.toggleLock" = "선택 항목 잠금/잠금 해제" +"object.toggleVisible" = "선택 항목 표시/숨기기" +"object.ungroup" = "선택 항목 그룹 해제" +"object.wrapInSection" = "새 섹션으로 감싸기" +"page.add" = "페이지 추가" +"page.delete" = "페이지 삭제" +"page.duplicate" = "페이지 복제" +"page.list" = "페이지 목록" +"page.move" = "페이지 이동" +"page.rename" = "페이지 이름 바꾸기" +"page.select" = "페이지로 이동" +"page.setBackground" = "페이지 배경" +"paint.documentColors" = "문서 색상" +"plugin.close" = "플러그인 패널 닫기" +"plugin.event" = "플러그인 패널 컨트롤 사용" +"plugin.import" = "매니페스트에서 플러그인 가져오기…" +"plugin.list" = "플러그인 목록" +"plugin.remove" = "플러그인 제거" +"plugin.run" = "플러그인 실행" +"plugin.ui" = "플러그인 패널" +"plugins.manage" = "플러그인 관리…" +"plugins.runLast" = "마지막 플러그인 실행" +"pref.highlightHover" = "마우스를 올리면 레이어 강조" +"pref.keepTool" = "사용 후에도 도구 선택 유지" +"pref.language" = "인터페이스 언어" +"pref.nudge" = "미세 이동 거리" +"pref.numberKeysOpacity" = "숫자 키로 불투명도 변경" +"pref.reduceMotion" = "동작 줄이기" +"pref.renameDuplicates" = "복제한 레이어 이름 바꾸기" +"pref.showDimensions" = "개체에 치수 표시" +"pref.userName" = "댓글에 표시할 이름" +"proto.action.add" = "프로토타입 액션 추가" +"proto.action.move" = "프로토타입 액션 순서 변경" +"proto.action.remove" = "프로토타입 액션 제거" +"proto.action.set" = "프로토타입 액션 편집" +"proto.closePreview" = "프로토타입 미리 보기 닫기" +"proto.conditional.addBlock" = "그 외 조건 / 그 외 추가" +"proto.conditional.removeBlock" = "조건 / 그 외 조건 / 그 외 제거" +"proto.conditional.setCondition" = "조건 편집" +"proto.flow.add" = "플로우 시작점 추가" +"proto.flow.remove" = "플로우 제거" +"proto.flow.rename" = "플로우 이름 바꾸기" +"proto.interaction.add" = "인터랙션 추가" +"proto.interaction.clear" = "모든 인터랙션 제거" +"proto.interaction.remove" = "인터랙션 제거" +"proto.interaction.set" = "인터랙션 편집" +"proto.present" = "프레젠테이션" +"proto.presentOptions" = "프레젠테이션 옵션" +"proto.preview" = "프로토타입 미리 보기 열기" +"proto.settings" = "프로토타입 설정" +"section.toggleContents" = "섹션 콘텐츠 숨기기/표시" +"select.add" = "선택 항목에 추가" +"select.all" = "모두 선택" +"select.area" = "영역 선택" +"select.byName" = "이름으로 레이어 선택" +"select.children" = "하위 항목 선택" +"select.inverse" = "선택 반전" +"select.layersAt" = "위치의 레이어" +"select.matching" = "일치하는 레이어 선택" +"select.next" = "다음 형제 선택" +"select.none" = "선택 해제" +"select.parent" = "부모 선택" +"select.previous" = "이전 형제 선택" +"select.remove" = "선택 항목에서 제거" +"select.sameEffect" = "같은 효과 선택" +"select.sameFill" = "같은 채우기 선택" +"select.sameFont" = "같은 글꼴 선택" +"select.sameInstance" = "같은 인스턴스 선택" +"select.sameProperties" = "같은 속성 선택" +"select.sameStroke" = "같은 선 선택" +"select.sameText" = "같은 텍스트 속성 선택" +"select.set" = "선택" +"shape.arrow" = "화살표" +"shape.ellipse" = "타원" +"shape.line" = "선" +"shape.polygon" = "다각형" +"shape.rectangle" = "사각형" +"shape.star" = "별" +"shapeBuilder.merge" = "영역 병합" +"shapeBuilder.mode" = "도형 빌더 모드" +"shapeBuilder.regions" = "도형 빌더 영역" +"shapeBuilder.remove" = "영역 제거" +"stroke.add" = "선 추가" +"stroke.brush" = "브러시" +"stroke.move" = "선 이동" +"stroke.remove" = "선 제거" +"stroke.set" = "선 설정" +"stroke.widthProfile" = "너비 프로필" +"style.apply" = "스타일 적용" +"style.create" = "스타일 만들기" +"style.delete" = "스타일 삭제" +"style.detach" = "스타일 분리" +"style.duplicate" = "스타일 복제" +"style.list" = "스타일 목록" +"style.move" = "스타일 이동" +"style.renameFolder" = "스타일 폴더 이름 바꾸기" +"style.update" = "스타일 편집" +"text.alignCenter" = "가운데 정렬" +"text.alignJustify" = "양쪽 정렬" +"text.alignLeft" = "왼쪽 정렬" +"text.alignRight" = "오른쪽 정렬" +"text.bold" = "굵게" +"text.bulletList" = "글머리 기호 목록" +"text.case" = "대소문자" +"text.caseLower" = "소문자" +"text.caseOriginal" = "원래 대소문자" +"text.caseSmallCaps" = "작은 대문자" +"text.caseTitle" = "제목 대소문자" +"text.caseUpper" = "대문자" +"text.create" = "텍스트" +"text.decoration" = "장식" +"text.edit.begin" = "텍스트 편집" +"text.edit.caret" = "캐럿 설정" +"text.edit.end" = "텍스트 편집 종료" +"text.edit.insert" = "텍스트 입력" +"text.edit.key" = "텍스트 키" +"text.edit.preedit" = "텍스트 조합 입력(IME)" +"text.edit.selectLine" = "줄 선택" +"text.edit.selectWord" = "단어 선택" +"text.edit.selection" = "텍스트 선택 영역" +"text.endPreview" = "텍스트 미리 보기 종료" +"text.fonts" = "글꼴 목록" +"text.italic" = "기울임꼴" +"text.lineHeightDown" = "줄 높이 줄이기" +"text.lineHeightUp" = "줄 높이 늘리기" +"text.link" = "링크 만들기" +"text.listStyle" = "목록 스타일" +"text.maxLines" = "최대 줄 수" +"text.numberList" = "번호 매기기 목록" +"text.onPath" = "패스 위 텍스트" +"text.paragraphIndent" = "단락 들여쓰기" +"text.paragraphSpacing" = "단락 간격" +"text.pathOptions" = "텍스트 패스 옵션" +"text.preview" = "텍스트 변경 미리 보기" +"text.removeFromPath" = "패스에서 텍스트 제거" +"text.set" = "텍스트 설정" +"text.setFeatures" = "OpenType 기능" +"text.setVariations" = "가변 글꼴 축" +"text.sizeDown" = "글꼴 크기 줄이기" +"text.sizeUp" = "글꼴 크기 늘리기" +"text.strikethrough" = "취소선" +"text.style" = "텍스트 범위 스타일 지정" +"text.trackingDown" = "자간 줄이기" +"text.trackingUp" = "자간 늘리기" +"text.underline" = "밑줄" +"text.weightDown" = "글꼴 굵기 줄이기" +"text.weightUp" = "글꼴 굵기 늘리기" +"tool.arrow" = "화살표" +"tool.comment" = "댓글" +"tool.ellipse" = "타원" +"tool.frame" = "프레임" +"tool.hand" = "손" +"tool.line" = "선" +"tool.move" = "이동" +"tool.pen" = "펜" +"tool.pencil" = "연필" +"tool.pencilBrush" = "연필 브러시" +"tool.polygon" = "다각형" +"tool.rectangle" = "사각형" +"tool.scale" = "배율" +"tool.scaleAnchor" = "배율 기준점" +"tool.section" = "섹션" +"tool.set" = "도구 선택" +"tool.shapeBuilder" = "도형 빌더" +"tool.slice" = "슬라이스" +"tool.star" = "별" +"tool.text" = "텍스트" +"transform.move" = "이동" +"transform.moveTo" = "위치로 이동" +"transform.nudge" = "미세 이동" +"transform.nudgeSize" = "미세 이동으로 크기 조정" +"transform.resize" = "크기 조정" +"transform.rotate" = "회전" +"transform.scale" = "배율" +"variable.addMode" = "모드 추가" +"variable.bind" = "변수 연결" +"variable.create" = "변수 만들기" +"variable.createCollection" = "변수 컬렉션 만들기" +"variable.delete" = "변수 삭제" +"variable.deleteCollection" = "컬렉션 삭제" +"variable.duplicate" = "변수 복제" +"variable.export" = "변수 내보내기" +"variable.import" = "변수 가져오기" +"variable.list" = "변수 목록" +"variable.moveMode" = "모드 이동" +"variable.removeMode" = "모드 삭제" +"variable.renameCollection" = "컬렉션 이름 바꾸기" +"variable.renameMode" = "모드 이름 바꾸기" +"variable.resetOverride" = "변수 재정의 재설정" +"variable.set" = "변수 값 설정" +"variable.setMode" = "변수 모드 설정" +"variable.update" = "변수 편집" +"vector.create" = "벡터" +"vector.deleteHeal" = "선택 항목 삭제 후 복구" +"vector.edit.addVertex" = "점 추가" +"vector.edit.begin" = "벡터 편집" +"vector.edit.bend" = "세그먼트 구부리기" +"vector.edit.bounds" = "선택한 점의 경계" +"vector.edit.connect" = "점 연결" +"vector.edit.cornerRadius" = "점 모서리 반경" +"vector.edit.cut" = "패스 자르기" +"vector.edit.delete" = "점 삭제" +"vector.edit.end" = "편집 완료" +"vector.edit.erase" = "지우기" +"vector.edit.lasso" = "올가미 선택" +"vector.edit.mirroring" = "핸들 대칭" +"vector.edit.moveHandles" = "핸들 이동" +"vector.edit.moveVertices" = "점 이동" +"vector.edit.nudge" = "점 미세 이동" +"vector.edit.paint" = "페인트 통" +"vector.edit.pen" = "펜 점" +"vector.edit.penEnd" = "펜 패스 끝내기" +"vector.edit.position" = "점 위치" +"vector.edit.resize" = "점 크기 조정" +"vector.edit.rotate" = "점 회전" +"vector.edit.select" = "점 선택" +"vector.edit.selectAll" = "모든 점 선택" +"vector.edit.setHandle" = "핸들 설정" +"vector.edit.smooth" = "점 부드럽게/날카롭게" +"vector.edit.state" = "벡터 편집 상태" +"vector.edit.strokeCap" = "점 선 끝" +"vector.edit.strokeJoin" = "점 선 연결" +"vector.edit.tool" = "벡터 편집 도구" +"vector.edit.transform" = "점 변형" +"vector.edit.widthPoint" = "너비 점" +"vector.flatten" = "평면화" +"vector.join" = "선택 항목 연결" +"vector.offset" = "패스 오프셋" +"vector.outlineStroke" = "선 윤곽선 만들기" +"vector.reverse" = "패스 방향 반전" +"vector.simplify" = "벡터 단순화" +"vector.smoothJoin" = "선택 항목 부드럽게 연결" +"version.autosave" = "자동 저장 버전" +"version.delete" = "버전 삭제" +"version.duplicate" = "버전 복제" +"version.exitPreview" = "현재 버전으로 돌아가기" +"version.list" = "버전 목록" +"version.preview" = "버전 보기" +"version.rename" = "버전 이름 바꾸기" +"version.restore" = "버전 복원" +"view.assets" = "에셋 패널" +"view.comments" = "댓글" +"view.contextMenu" = "컨텍스트 메뉴 표시" +"view.design" = "디자인 패널" +"view.designPrototype" = "디자인과 프로토타입 전환" +"view.devMode" = "개발 모드" +"view.frameOutlines" = "프레임 윤곽선" +"view.get" = "보기 가져오기" +"view.layers" = "레이어 패널" +"view.layoutGrids" = "레이아웃 그리드" +"view.leftSidebar" = "왼쪽 사이드바 표시/숨기기" +"view.maskOutlines" = "마스크 윤곽선" +"view.nextFrame" = "다음 프레임으로 확대/축소" +"view.nextPage" = "다음 페이지" +"view.nextRegion" = "다음 영역에 포커스" +"view.outlines" = "윤곽선" +"view.outlinesSelection" = "선택 항목 윤곽선" +"view.pixelGrid" = "픽셀 그리드" +"view.pixelPreview" = "픽셀 미리 보기" +"view.prevFrame" = "이전 프레임으로 확대/축소" +"view.prevPage" = "이전 페이지" +"view.previousRegion" = "이전 영역에 포커스" +"view.proofSrgb" = "sRGB 교정 미리 보기" +"view.prototype" = "프로토타입 패널" +"view.rulers" = "눈금자" +"view.set" = "보기 설정" +"view.slices" = "슬라이스" +"view.snapGeometry" = "도형에 맞춤" +"view.snapObjects" = "개체에 맞춤" +"view.snapPixel" = "픽셀 그리드에 맞춤" +"view.themeDark" = "다크 테마" +"view.themeLight" = "라이트 테마" +"view.themeSystem" = "시스템 테마 따르기" +"view.toggleUi" = "UI 표시/숨기기" +"view.zoom100" = "100%로 확대/축소" +"view.zoom200" = "200%로 확대/축소" +"view.zoom50" = "50%로 확대/축소" +"view.zoomAt" = "확대/축소 도구" +"view.zoomFit" = "화면에 맞게 확대/축소" +"view.zoomIn" = "확대" +"view.zoomOut" = "축소" +"view.zoomSelection" = "선택 항목으로 확대/축소" +"window.focus" = "창을 맨 앞으로 가져오기" +"window.new" = "새 창" + +[menu] +"bool.exclude" = "제외" +"bool.flatten" = "평면화" +"bool.intersect" = "교차" +"bool.subtract" = "빼기" +"bool.union" = "합치기" +"file.duplicate" = "복제" +"file.import" = "파일에서 가져오기…" +"file.rename" = "이름 바꾸기" +"libraries.open" = "라이브러리 열기" +"select.sameEffect" = "효과" +"select.sameFill" = "채우기" +"select.sameFont" = "글꼴" +"select.sameInstance" = "인스턴스" +"select.sameProperties" = "속성" +"select.sameStroke" = "선" +"select.sameText" = "텍스트 속성" +"text.alignCenter" = "텍스트 가운데 정렬" +"text.alignJustify" = "텍스트 양쪽 정렬" +"text.alignLeft" = "텍스트 왼쪽 정렬" +"text.alignRight" = "텍스트 오른쪽 정렬" +"view.assets" = "에셋" +"view.design" = "디자인" +"view.layers" = "레이어" +"view.outlines" = "윤곽선 표시" +"view.outlinesSelection" = "선택 항목 윤곽선 표시" +"view.prototype" = "프로토타입" +"view.themeDark" = "다크" +"view.themeLight" = "라이트" +"view.themeSystem" = "시스템 따르기" diff --git a/crates/ui-egui/src/bidi.rs b/crates/ui-egui/src/bidi.rs index fdb2f82..915c7e1 100644 --- a/crates/ui-egui/src/bidi.rs +++ b/crates/ui-egui/src/bidi.rs @@ -298,9 +298,7 @@ pub fn script_fallbacks(have: &dyn Fn(char) -> bool) -> Vec<(String, egui::FontD continue; } let Some(face) = figcraft_text::face_with_char(c, &FAMILIES) else { continue }; - let mut data = egui::FontData::from_owned(face.bytes.data().to_vec()); - data.index = face.index; - out.push((format!("system-{}-{}", face.family, face.style), data)); + out.push((format!("system-{}-{}", face.family, face.style), crate::theme::font_data(&face))); taken.push(face); } out diff --git a/crates/ui-egui/src/cjk.rs b/crates/ui-egui/src/cjk.rs new file mode 100644 index 0000000..25b98dd --- /dev/null +++ b/crates/ui-egui/src/cjk.rs @@ -0,0 +1,143 @@ +//! Chinese, Japanese and Korean text in the UI. egui's own fonts and Inter have no CJK glyphs, so +//! the UI adds a face per script it needs: the UI language's, the scripts in the open file's names +//! and comments, the language picker's and typed text. Desktop finds them among the installed +//! fonts (the system font scan), only once one is needed, so English users load none; the web +//! build has only the CJK faces built in from craft-fonts (`FIGCRAFT_EMBED_CJK`), else none. + +use std::sync::Arc; + +use figcraft_text::Face; + +pub const KANA: u8 = 1; +pub const HANGUL: u8 = 2; +/// Han characters (and CJK punctuation and full-width forms). +pub const HAN: u8 = 4; + +/// Japanese faces, the built-in one first: Windows, macOS, then Linux names. +const JAPANESE: &[&str] = &[ + "BIZ UDPGothic", + "Yu Gothic UI", + "Yu Gothic", + "Meiryo UI", + "Meiryo", + "MS UI Gothic", + "Hiragino Sans", + "Hiragino Kaku Gothic ProN", + "Noto Sans CJK JP", + "Noto Sans JP", + "Source Han Sans JP", + "IPAexGothic", + "IPAPGothic", + "TakaoPGothic", +]; +const KOREAN: &[&str] = + &["Malgun Gothic", "Apple SD Gothic Neo", "Noto Sans CJK KR", "Noto Sans KR", "Source Han Sans KR", "NanumGothic", "NanumBarunGothic", "UnDotum"]; +const CHINESE: &[&str] = &[ + "Noto Sans CJK SC", + "Microsoft YaHei UI", + "Microsoft YaHei", + "PingFang SC", + "Noto Sans SC", + "Source Han Sans SC", + "WenQuanYi Micro Hei", + "WenQuanYi Zen Hei", + "Droid Sans Fallback", +]; + +/// The CJK scripts in `s`. +pub fn scripts(s: &str) -> u8 { + s.chars().fold(0, |m, c| { + m | match u32::from(c) { + 0x3040..=0x30FF | 0x31F0..=0x31FF | 0xFF66..=0xFF9F => KANA, + 0x1100..=0x11FF | 0x3130..=0x318F | 0xA960..=0xA97F | 0xAC00..=0xD7FF | 0xFFA0..=0xFFDC => HANGUL, + 0x3000..=0x303F | 0x3400..=0x4DBF | 0x4E00..=0x9FFF | 0xF900..=0xFAFF | 0xFF01..=0xFF65 | 0x20000..=0x3FFFF => HAN, + _ => 0, + } + }) +} + +/// The CJK scripts a UI language (a catalog code) is written in. +pub fn language(code: &str) -> u8 { + match code.split('-').next() { + Some("ja") => KANA | HAN, + Some("ko") => HANGUL, + Some("zh") => HAN, + _ => 0, + } +} + +/// Whether the UI can draw language `code`: always on desktop (a system face is found when it's +/// needed; tofu at worst), on the web only with built-in faces for its scripts. The language +/// picker and the system language skip a language it can't. +pub fn can_show(code: &str) -> bool { + let need = language(code); + need == 0 + || !cfg!(target_arch = "wasm32") + || samples(need, false).iter().all(|(c, _)| figcraft_text::face_with_char(*c, &["BIZ UDPGothic", "Noto Sans CJK SC"]).is_some()) +} + +/// A character standing for each script in `need`, with the families to look for it in, the +/// language's own script first. Han without kana in a non-Japanese, non-Korean UI reads as Chinese +/// (a simplified character, Chinese faces first); else a Japanese or Korean face draws it. +fn samples(need: u8, korean_first: bool) -> Vec<(char, Vec<&'static str>)> { + let chinese = need & HAN != 0 && need & KANA == 0 && !korean_first; + let han: (char, Vec<&str>) = match (chinese, korean_first) { + (true, _) => ('们', [CHINESE, JAPANESE, KOREAN].concat()), + (false, true) => ('漢', [KOREAN, JAPANESE, CHINESE].concat()), + (false, false) => ('漢', [JAPANESE, KOREAN, CHINESE].concat()), + }; + let mut v = vec![(KANA, ('あ', JAPANESE.to_vec())), (HAN, han), (HANGUL, ('한', KOREAN.to_vec()))]; + if korean_first { + v.reverse(); + } + v.into_iter().filter(|(bit, _)| need & bit != 0).map(|(_, s)| s).collect() +} + +/// Faces (built-in or installed) drawing the scripts in `need` that `have` (the UI's other fonts) +/// lacks, in fallback order: one per script, unless an earlier one draws it too. Only the families +/// tried are read from disk. +pub fn faces(need: u8, lang: &str, have: &dyn Fn(char) -> bool) -> Vec> { + let mut out: Vec> = Vec::new(); + for (c, families) in samples(need, language(lang) == HANGUL) { + if have(c) || out.iter().any(|f| f.has_char(c)) { + continue; + } + if let Some(face) = figcraft_text::face_with_char(c, &families) { + out.push(face); + } + } + out +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn scripts_and_languages() { + assert_eq!(scripts("Frame 1"), 0); + assert_eq!(scripts("ボタン"), KANA); + assert_eq!(scripts("버튼"), HANGUL); + assert_eq!(scripts("按钮"), HAN); + assert_eq!(scripts("日本語のレイヤー(1)"), KANA | HAN); + assert_eq!(language("ja"), KANA | HAN); + assert_eq!(language("ko"), HANGUL); + assert_eq!(language("zh-Hant"), HAN); + assert_eq!(language("fr"), 0); + assert!(["en", "es", "fr", "de", "pt-BR"].iter().all(|c| can_show(c))); + } + + #[test] + fn the_ui_language_script_comes_first() { + let order = |need, ko| samples(need, ko).into_iter().map(|(c, _)| c).collect::(); + assert_eq!(order(KANA | HAN | HANGUL, false), "あ漢한"); + assert_eq!(order(KANA | HAN | HANGUL, true), "한漢あ"); + assert_eq!(order(HANGUL, false), "한"); + // Han without kana outside a Japanese or Korean UI reads as Chinese. + assert_eq!(order(HAN, false), "们"); + assert_eq!(samples(HAN, false).first().and_then(|(_, f)| f.first()).copied(), Some("Noto Sans CJK SC")); + assert_eq!(samples(HAN, true).first().and_then(|(_, f)| f.first()).copied(), Some("Malgun Gothic")); + assert!(faces(0, "en", &|_| false).is_empty()); + assert!(faces(KANA | HANGUL | HAN, "ja", &|_| true).is_empty(), "nothing is looked up for scripts the UI draws"); + } +} diff --git a/crates/ui-egui/src/credits_tests.rs b/crates/ui-egui/src/credits_tests.rs index 4dc7a2d..993aa44 100644 --- a/crates/ui-egui/src/credits_tests.rs +++ b/crates/ui-egui/src/credits_tests.rs @@ -43,7 +43,7 @@ struct Ui { impl Ui { fn new() -> Self { let ctx = egui::Context::default(); - crate::theme::install_fonts(&ctx, false); + crate::theme::install_fonts(&ctx, false, 0); crate::theme::apply(&ctx, Tokens::light()); let mut u = Self { ctx, time: 0.0 }; // Fonts set now take effect on the next frame. diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index ec15d70..7149f19 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -208,7 +208,7 @@ pub fn show(app: &mut FigApp, ctx: &Context) { ui.horizontal(|ui| { ui.label(tr("Language")); // Each language by its own name; System follows the OS (the browser on the web). - let langs = i18n::languages().iter().map(|l| (l.code, l.name)); + let langs = i18n::languages().iter().filter(|l| crate::cjk::can_show(l.code)).map(|l| (l.code, l.name)); for (code, name) in [("system", tr("System"))].into_iter().chain(langs) { if ui.selectable_label(app.session.prefs.language.eq_ignore_ascii_case(code), name).clicked() { app.run("pref.language", json!({"language": code})); diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index ee091a6..e4e3fb4 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -61,13 +61,14 @@ fn resolve(pref: &str, system: Option<&str>) -> usize { } /// The [`LANGS`] index for one tag: the exact tag ("pt-BR"), else its base language ("es" for -/// "es_ES.UTF-8"), else a regional catalog of that language ("pt-BR" for "pt-PT"). +/// "es_ES.UTF-8"), else a regional catalog of that language ("pt-BR" for "pt-PT"). A language the +/// UI can't draw (CJK on the web without CJK faces built in) doesn't count. fn resolve_one(want: &str) -> Option { let tag = want.trim().split(['.', '@']).next().unwrap_or("").replace('_', "-"); let base = tag.split('-').next().unwrap_or(""); let find = |t: &str| LANGS.iter().position(|l| l.code.eq_ignore_ascii_case(t)); let regional = || LANGS.iter().position(|l| !base.is_empty() && l.code.split('-').next().is_some_and(|b| b.eq_ignore_ascii_case(base))); - find(&tag).or_else(|| find(base)).or_else(regional) + find(&tag).or_else(|| find(base)).or_else(regional).filter(|i| LANGS.get(*i).is_some_and(|l| crate::cjk::can_show(l.code))) } fn find(table: &'static [(&'static str, Text)], key: &str) -> Option<&'static Text> { @@ -112,13 +113,16 @@ pub fn trn(key: &str, n: usize, args: &[(&str, &dyn Display)]) -> String { fill(text, &all) } -/// Whether count `n` takes the "one" form: 0 and 1 in French and Brazilian Portuguese, 1 elsewhere -/// (CLDR's integer rules). +/// Whether count `n` takes the "one" form: 0 and 1 in French and Brazilian Portuguese, never in +/// Japanese and Korean (no plural forms: always "other"), 1 elsewhere (CLDR's integer rules). // shortcut: CLDR's "many" (French, Spanish and Portuguese millions) reads as "other" here; add it // when a language needs a third form. fn plural_one(lang: usize, n: usize) -> bool { - let zero_is_one = LANGS.get(lang).is_some_and(|l| matches!(l.code, "fr" | "pt-BR")); - n == 1 || (n == 0 && zero_is_one) + match LANGS.get(lang).map(|l| l.code) { + Some("ja" | "ko") => false, + Some("fr" | "pt-BR") => n <= 1, + _ => n == 1, + } } /// Replace each `{name}` in `text` with its argument, in one pass (an argument's own braces stay). diff --git a/crates/ui-egui/src/i18n_tests.rs b/crates/ui-egui/src/i18n_tests.rs index 77d6dab..a86b0fb 100644 --- a/crates/ui-egui/src/i18n_tests.rs +++ b/crates/ui-egui/src/i18n_tests.rs @@ -328,6 +328,20 @@ fn french_and_portuguese_count_zero_as_singular() { } } +#[test] +fn japanese_and_korean_have_no_plural_forms() { + let code = |pref: &str, system: Option<&str>| LANGS[resolve(pref, system)].code; + assert_eq!(code("system", Some("ja-JP")), "ja"); + assert_eq!(code("system", Some("ko_KR.UTF-8")), "ko"); + assert_eq!(code("system", Some("ja,en-US")), "ja"); + for code in ["ja", "ko"] { + let lang = LANGS.iter().position(|l| l.code == code).unwrap(); + assert!(!plural_one(lang, 0) && !plural_one(lang, 1) && !plural_one(lang, 2), "{code}"); + let ones: Vec<_> = LANGS[lang].ui.iter().filter(|(_, t)| matches!(t, Text::Plural(Some(_), _))).map(|(k, _)| k).collect(); + assert!(ones.is_empty(), "{code}: plural entries give only `other`: {ones:?}"); + } +} + #[test] fn the_key_scanner_reads_rust_literals() { let src = r#"x(tr("A \"b\"")); trf( diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index e297a0c..b3b8dd5 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -10,6 +10,7 @@ pub mod assets_panel; pub mod bidi; pub mod branch_ui; pub mod canvas; +pub mod cjk; pub mod colorpicker; pub mod comments; pub mod component_panel; @@ -406,8 +407,11 @@ pub struct FigApp { pub services: Box, worker: Option, fonts_installed: bool, - /// System faces for scripts the built-in fonts lack were added (after the font scan). - script_fonts: bool, + /// System faces for scripts the built-in fonts lack were added (after the font scan), with + /// faces for these CJK scripts ([`cjk`]). + script_fonts: Option, + /// The tab (uid) and revision whose names were last checked for CJK scripts. + cjk_checked: Option<(u64, u64)>, /// The language preference the UI strings follow (applied when it changes). language: Option, /// A field had the keyboard when the last frame ended. @@ -433,7 +437,8 @@ impl FigApp { services, worker: None, fonts_installed: false, - script_fonts: false, + script_fonts: None, + cjk_checked: None, language: None, field_focus: false, control_queue: Vec::new(), @@ -663,20 +668,52 @@ impl FigApp { self.session.prefs.reduce_motion || self.services.reduce_motion() } + /// The CJK scripts the UI shows: the language's, the language picker's (Preferences open), + /// typed text's, and those in the open file's names and comments (read when it changes, not + /// mid-drag). Nothing is checked once every script has a face. + fn cjk_needed(&mut self, ctx: &egui::Context, installed: u8) -> u8 { + if installed == cjk::KANA | cjk::HANGUL | cjk::HAN { + return installed; + } + let mut need = i18n::current().map_or(0, |l| cjk::language(l.code)); + if self.ui.preferences { + need |= i18n::languages().iter().filter(|l| cjk::can_show(l.code)).fold(0, |m, l| m | cjk::language(l.code)); + } + need |= ctx.input(|i| { + i.events.iter().fold(0, |m, e| match e { + egui::Event::Text(t) | egui::Event::Ime(egui::ImeEvent::Preedit { text: t, .. } | egui::ImeEvent::Commit(t)) => m | cjk::scripts(t), + _ => m, + }) + }); + let dragging = ctx.input(|i| i.pointer.any_down()); + if let Some(d) = self.session.docs.get(self.session.active).filter(|d| !dragging && self.cjk_checked != Some((d.uid, d.revision))) { + self.cjk_checked = Some((d.uid, d.revision)); + let doc = &d.doc; + let comments = doc.comments.iter().flat_map(|c| std::iter::once(&c.first).chain(&c.replies)).flat_map(|m| [&m.author, &m.text]); + need |= std::iter::once(&doc.name).chain(doc.nodes().map(|n| &n.name)).chain(comments).fold(0, |m, s| m | cjk::scripts(s)); + } + need + } + /// Per-frame logic that doesn't draw (control requests, theme, language). pub fn logic(&mut self, ctx: &egui::Context) { - if !self.fonts_installed { - theme::install_fonts(ctx, false); - self.fonts_installed = true; - } else if !self.script_fonts && figcraft_text::system_fonts_scanned() { - // Once the system fonts are indexed: faces for names in scripts the UI fonts lack. - self.script_fonts = true; - theme::install_fonts(ctx, true); - } if self.language.as_ref() != Some(&self.session.prefs.language) { i18n::set(&self.session.prefs.language, self.services.system_language().as_deref()); self.language = Some(self.session.prefs.language.clone()); } + if !self.fonts_installed { + theme::install_fonts(ctx, false, 0); + self.fonts_installed = true; + } else if figcraft_text::system_fonts_scanned() { + // Once the system fonts are indexed: faces for names in scripts the UI fonts lack, and + // for each CJK script once something shows it. + let installed = self.script_fonts.unwrap_or(0); + let cjk = installed | self.cjk_needed(ctx, installed); + if self.script_fonts != Some(cjk) { + self.script_fonts = Some(cjk); + theme::install_fonts(ctx, true, cjk); + } + } let dark = match self.session.prefs.theme.as_str() { "dark" => true, "system" => ctx.global_style().visuals.dark_mode, diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 2f64d70..15aff1f 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -227,8 +227,9 @@ pub fn on_dark(ui: &mut egui::Ui, f: impl FnOnce(&mut egui::Ui) -> R) -> R { } /// UI fonts: Inter (from the craft-fonts build input) when present, else egui's defaults; with -/// `system`, also system faces for scripts those lack (Hebrew, joined Arabic) so names in them show. -pub fn install_fonts(ctx: &Context, system: bool) { +/// `system`, also system faces for scripts those lack (Hebrew, joined Arabic) so names in them show, +/// and faces for the CJK scripts in `cjk` ([`crate::cjk`]). +pub fn install_fonts(ctx: &Context, system: bool, cjk: u8) { let mut fonts = FontDefinitions::default(); let find = |family: &str, style: &str| figcraft_text::CRAFT_FONTS.iter().find(|f| f.family == family && f.style == style).map(|f| f.bytes); let regular = find("Inter", "Regular"); @@ -251,9 +252,10 @@ pub fn install_fonts(ctx: &Context, system: bool) { } semi.extend(fonts.families.get(&FontFamily::Proportional).cloned().unwrap_or_default()); fonts.families.insert(FontFamily::Name("semibold".into()), semi); - // CJK and other scripts from craft-fonts as fallbacks. + // CJK and other scripts from craft-fonts as fallbacks (Noto Sans CJK only with FIGCRAFT_EMBED_CJK). + const BUILT_IN: [&str; 4] = ["Inter", "BIZ UDPGothic", "Noto Sans CJK SC", "Noto Sans Arabic"]; for f in figcraft_text::CRAFT_FONTS.iter().filter(|f| f.family != "Inter" && f.style == "Regular") { - if matches!(f.family, "BIZ UDPGothic" | "Noto Sans Arabic") { + if BUILT_IN.contains(&f.family) { let key = format!("craft-{}", f.family); fonts.font_data.insert(key.clone(), Arc::new(FontData::from_static(f.bytes))); for fam in [FontFamily::Proportional, FontFamily::Name("semibold".into())] { @@ -266,13 +268,15 @@ pub fn install_fonts(ctx: &Context, system: bool) { if system { // What the built-in faces above already draw. let embedded = |c: char| { - ["Inter", "BIZ UDPGothic", "Noto Sans Arabic"] + BUILT_IN .into_iter() .filter(|f| figcraft_text::CRAFT_FONTS.iter().any(|cf| cf.family == *f)) .filter_map(|f| figcraft_text::find_face(f, "Regular")) .any(|x| x.has_char(c)) }; - let extra = crate::bidi::script_fallbacks(&embedded); + let mut extra = crate::bidi::script_fallbacks(&embedded); + let lang = crate::i18n::current().map_or("en", |l| l.code); + extra.extend(crate::cjk::faces(cjk, lang, &embedded).iter().map(|f| (format!("system-{}-{}", f.family, f.style), font_data(f)))); for (key, data) in extra { fonts.font_data.insert(key.clone(), Arc::new(data)); for fam in [FontFamily::Proportional, FontFamily::Name("semibold".into())] { @@ -285,6 +289,19 @@ pub fn install_fonts(ctx: &Context, system: bool) { ctx.set_fonts(fonts); } +/// egui font data over a face's bytes, without copying them (CJK faces are 10–20 MB). Font +/// database faces are never dropped, so a system face's shared bytes are kept for good: leaking +/// one more reference to them costs a pointer and gives egui the `'static` slice it needs. +pub fn font_data(face: &figcraft_text::Face) -> FontData { + let bytes: &'static [u8] = match &face.bytes { + figcraft_text::fontdb::FontBytes::Static(b) => b, + figcraft_text::fontdb::FontBytes::Shared(v) => Box::leak(Box::new(v.clone())).as_slice(), + }; + let mut data = FontData::from_static(bytes); + data.index = face.index; + data +} + pub fn semibold(size: f32) -> FontId { FontId::new(size, FontFamily::Name("semibold".into())) } diff --git a/docs/gaps.md b/docs/gaps.md index 4da81c1..e09d4f7 100644 --- a/docs/gaps.md +++ b/docs/gaps.md @@ -1,6 +1,6 @@ # Where FigCraft falls short of Figma -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; `.fig` import: editable vector networks, more layer kinds, variable prototype actions; `.fig` import, best effort: gap 1 down to its tail; Windows QA pass: everyday workflows on Windows 11, eight fixes incl. unsaved work kept after a crash or a forced quit; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings: gap 14 down to its tail) · **Target:** Figma Design (desktop app 126.10.7) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Japanese and Korean draft catalogs and CJK UI fonts; plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; `.fig` import: editable vector networks, more layer kinds, variable prototype actions; `.fig` import, best effort: gap 1 down to its tail; Windows QA pass: everyday workflows on Windows 11, eight fixes incl. unsaved work kept after a crash or a forced quit; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings: gap 14 down to its tail) · **Target:** Figma Design (desktop app 126.10.7) Every known shortfall against Figma, one entry each, ranked by how much it stops a Figma user from doing real work in FigCraft. Agents: pick work from the top unless the owner says otherwise. The @@ -18,7 +18,7 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe | 2 | Multiplayer and sharing are a preview, without accounts (**beta blocker**) | Feature | 42–84 | [collaboration-parity](collaboration-parity.md) | | 3 | Nothing checked against real Figma files | Fidelity | 15–30 | [target-app-parity](target-app-parity.md) | | 4 | Interaction fidelity not compared tool by tool | UI/UX | 40–60 | [ui-parity](ui-parity.md) | -| 5 | Localization: English plus unreviewed Spanish, French, German and Brazilian Portuguese drafts; no Japanese or Korean | Localization | 40–65 | [localization-parity](localization-parity.md) | +| 5 | Localization: English plus unreviewed Spanish, French, German, Brazilian Portuguese, Japanese and Korean drafts | Localization | 32–55 | [localization-parity](localization-parity.md) | | 6 | Plugins: no distribution, widgets take clicks only; Figma's plugins don't run | Ecosystem | 10–30 | [target-app-parity](target-app-parity.md) | | 7 | CPU canvas where Figma uses the GPU | Hardware/performance | 30–60 | [hardware-parity](hardware-parity.md) | | 8 | Platform QA: Linux and the browser left (Windows pass done 2026-10-11) | Stability/platforms | 10–20 | [hardware-parity](hardware-parity.md) | @@ -100,19 +100,21 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe - **Impact:** Figma users notice the feel within minutes; it decides whether they stay. - **Estimate:** 40–60 h. Detail in [`ui-parity.md`](ui-parity.md). -### 5. Localization: English plus unreviewed drafts; no Japanese or Korean -- **Missing:** Figma's Japanese and Korean, native reviews of the Spanish, French, German and - Brazilian Portuguese drafts, localized engine messages and number formatting. +### 5. Localization: English plus unreviewed drafts +- **Missing:** native reviews of the Spanish, French, German, Brazilian Portuguese, Japanese and + Korean drafts, Latin American Spanish, localized engine messages and number formatting; CJK UI + text on the web without the craft-fonts CJK build. - **Evidence (measured from source):** the layer landed 2026-10-11: catalogs in `crates/ui-egui/locales/` (1,351 UI keys plus 519 command labels and 29 menu wordings), Preferences ▸ Language, `pref.language`; `en.toml` is complete, and `es.toml`, `fr.toml`, - `de.toml` and `pt-BR.toml` (2026-10-12) are complete machine drafts (only Spanish is held to - completeness by the check; the others show English for strings added later). Engine error - messages and Dev Mode values stay English. -- **Impact:** keeps out non-English designers, including Figma's large Japanese and Korean user - bases. + `de.toml`, `pt-BR.toml`, `ja.toml` and `ko.toml` (2026-10-12) are complete machine drafts (only + Spanish is held to completeness by the check; the others show English for strings added later). + CJK UI text uses an installed CJK face the desktop app loads when something on screen needs it + (`crates/ui-egui/src/cjk.rs`). Engine error messages and Dev Mode values stay English. +- **Impact:** non-English designers get machine drafts nobody has reviewed yet, and English + errors. - **Estimate:** 3–7 h per language plus native review, 4–6 h for engine messages and numbers; - 40–65 h for the key languages left and the drafts' follow-ups. Detail in + 32–55 h for the key languages left and the drafts' follow-ups. Detail in [`localization-parity.md`](localization-parity.md); how to add one in [`translating.md`](translating.md). @@ -334,6 +336,7 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe | Date | Change | Summary | |---|---|---| +| 2026-10-12 | minor | Japanese and Korean draft catalogs and CJK UI fonts (gap 5): `ja.toml` and `ko.toml` translate every UI string (1,351 keys; plurals give only `other`, and `plural_one` never picks "one" in either), command label (519) and menu wording (29), machine-drafted and marked as drafts awaiting native review; Preferences ▸ Language lists 日本語 and 한국어, System picks ja* and ko*. CJK UI text renders: once the UI language, the open file's names or comments, typed text or the language picker needs Japanese kana, Hangul or Han, the desktop app appends one installed face per script to egui's fallbacks (Windows Yu Gothic UI / Meiryo / Malgun Gothic / Microsoft YaHei, macOS Hiragino Sans / Apple SD Gothic Neo / PingFang SC, Linux Noto Sans CJK; the craft-fonts build's BIZ UDPGothic first), reading only that face's file and sharing its bytes with egui (English users load none: startup and memory unchanged); the web shows Japanese and Korean only when built with craft-fonts' Noto Sans CJK (`FIGCRAFT_EMBED_CJK`), else it keeps them out of the picker and System. Gap 5 40–65 h → 32–55 h, rank unchanged | | 2026-10-12 | minor | Plugin widgets (API 3) and the panel tail (panels side by side, colour picker on plugin fields) added to gap 6's landed list; gap 6 now 10–30 h; ranking unchanged | | 2026-10-12 | minor | French, German and Brazilian Portuguese draft catalogs (gap 5): every UI string, command label and menu wording (1,899 entries) machine-drafted in each and marked as drafts awaiting native review, falling back to English per key (new strings need only English and Spanish); 0 counts as singular in French and Brazilian Portuguese; System picks the first OS language with a catalog (pt-PT and pt read pt-BR); long translations elide with a tooltip in dropdowns, two-column labels and the home cards. Gap 5 45–75 h → 40–65 h, rank unchanged | | 2026-10-12 | minor | Cursor chat and spotlight in live sessions (gap 2): `/` opens a chat bubble at your pointer, a spotlight makes everyone follow your view; ephemeral presence the host validates and rate-limits. Gap 2 45–90 h → 42–84 h | diff --git a/docs/localization-parity.md b/docs/localization-parity.md index ca476b4..3eb5c24 100644 --- a/docs/localization-parity.md +++ b/docs/localization-parity.md @@ -1,9 +1,10 @@ # Localization parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (French, German and Brazilian Portuguese drafts) · **Target:** Figma Design (desktop app 126.10.7) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Japanese and Korean drafts, CJK UI fonts) · **Target:** Figma Design (desktop app 126.10.7) FigCraft's interface has a localization layer with an English catalog and complete Spanish, French, -German and Brazilian Portuguese drafts (machine-drafted, waiting for native speakers' review). This +German, Brazilian Portuguese, Japanese and Korean drafts (machine-drafted, waiting for native +speakers' review). This page lists the twelve key languages of the craftrules standard, then the other languages Figma ships. How to add a language: [`translating.md`](translating.md). @@ -28,20 +29,20 @@ supported by both apps (CJK, Arabic and Devanagari shaping, IME); Figma has no v and 29 menu wordings by command id: 1,899 entries. Command ids, the CLI, MCP and the control channel stay English. Accessibility names come from the same strings. - **Language preference:** Preferences ▸ Language (System, English, Deutsch, Español, Français, - Português (Brasil)), applied at once without a restart; System takes the first of the OS's + 日本語, 한국어, Português (Brasil)), applied at once without a restart; System takes the first of the OS's preferred languages that has a catalog (Windows' language list, macOS AppleLanguages, `LANGUAGE` then the locale variables on Linux and BSD; a regional tag falls back to its language, and pt-PT or pt to pt-BR) or the browser's language on the web. `pref.language {language}` sets it from the CLI, MCP and the control channel. - **Check:** `cargo test -p figcraft-ui-egui i18n` fails on keys the code uses that `en.toml` lacks, keys no code uses, unknown command ids, placeholders that differ from English and, for - complete languages (Spanish), anything untranslated. The French, German and Brazilian Portuguese - drafts translate everything today but are not held to it: a string added later shows English + complete languages (Spanish), anything untranslated. The French, German, Brazilian Portuguese, + Japanese and Korean drafts translate everything today but are not held to it: a string added later shows English there until someone translates it. - **Not yet localized:** messages the engine writes (errors, a few toasts, Dev Mode property values such as "inside"), number formatting (decimal points stay `.`), and plural forms beyond one/other - (French and Brazilian Portuguese take the singular for 0 as well; CLDR's "many" for millions - reads as the plural). + (French and Brazilian Portuguese take the singular for 0 as well; Japanese and Korean have one + form; CLDR's "many" for millions reads as the plural). - **Script support in documents:** Unicode bidi with Arabic shaping and mirrored brackets in text layers; right-to-left list markers and indents; right-to-left names in the layers panel, tabs and canvas labels (visual order, joined Arabic); inline IME composition with the candidate window @@ -50,23 +51,35 @@ supported by both apps (CJK, Arabic and Devanagari shaping, IME); Figma has no v - **Script support in the UI:** menus widen to their longest label; dropdowns, the two-column labels of the right panel and the home screen's cards keep a long translation on one line with an ellipsis and show it in full on hover (checked in German, the longest); no mirrored - (right-to-left) layout of panels. + (right-to-left) layout of panels. CJK translations are shorter than English; the same ellipsis + and tooltip cover the few that don't fit (the sizing dropdowns). +- **CJK UI fonts:** egui's fonts and Inter have no CJK glyphs. Once the UI language, the open + file's names or comments, typed text or the language picker needs Japanese kana, Hangul or Han, + the desktop app adds one installed face per script to the UI's fallbacks (Windows: Yu Gothic UI, + Meiryo, Malgun Gothic, Microsoft YaHei; macOS: Hiragino Sans, Apple SD Gothic Neo, PingFang SC; + Linux and BSD: Noto Sans CJK, Source Han Sans, Nanum, WenQuanYi; the craft-fonts build's BIZ + UDPGothic first), the UI language's script first; Han without kana outside a Japanese or Korean UI + reads as Chinese. Only that face's file is read and egui shares its bytes, so English users load + nothing (startup and memory measured unchanged); no CJK font installed means tofu, never a + crash. The web build has no system fonts: built with craft-fonts and `FIGCRAFT_EMBED_CJK=1` it + embeds Noto Sans CJK (+16 MB) and offers Japanese and Korean; otherwise the language picker and + System leave them out. No font file is in this repo. ## Languages | Language | Code | UI strings translated | Dialogs / tooltips / help | Script support | Native review | Status | Hours to full | |---|---|---|---|---|---|---|---| | English | en | 1,899 / 1,899 (100%, source) | yes | Latin | yes (source) | full | 0 | -| Simplified Chinese (Mandarin) | zh-Hans | 0 (0%) | no | CJK text, IME and font fallback work in documents; UI font needs CJK coverage | no | none | 4–7 | +| Simplified Chinese (Mandarin) | zh-Hans | 0 (0%) | no | CJK text, IME and font fallback work in documents; CJK UI faces load on demand (desktop) | no | none | 3–5 | | Spanish | es | 1,899 / 1,899 (100%, draft) | yes | Latin | no | draft | 1–2 (es-419 differences, after native review) | | Hindi | hi | 0 (0%) | no | Devanagari shaping works in documents; UI font fallback to check | no | none | 4–7 | | Arabic | ar | 0 (0%) | no | Bidi, shaping and RTL names work; the UI does not mirror | no | none | 9–15 | | French | fr | 1,899 / 1,899 (100%, draft) | yes | Latin | no | draft | 1–2 (after native review) | | Portuguese | pt-BR | 1,899 / 1,899 (100%, draft) | yes | Latin | no | draft | 1–2 (after native review) | | Indonesian | id | 0 (0%) | no | Latin | no | none | 3–5 | -| Japanese | ja | 0 (0%) | no | CJK text and IME work in documents; UI font needs CJK coverage | no | none | 4–7 | +| Japanese | ja | 1,899 / 1,899 (100%, draft) | yes | CJK text and IME in documents; UI text in an installed Japanese face (web: the `FIGCRAFT_EMBED_CJK` build) | no | draft | 1–2 (after native review) | | German | de | 1,899 / 1,899 (100%, draft) | yes | Latin; long words elide in narrow fields | no | draft | 1–2 (after native review) | -| Korean | ko | 0 (0%) | no | Hangul text and IME work in documents; UI font needs coverage | no | none | 3–5 | +| Korean | ko | 1,899 / 1,899 (100%, draft) | yes | Hangul text and IME in documents; UI text in an installed Korean face (web: the `FIGCRAFT_EMBED_CJK` build) | no | draft | 1–2 (after native review) | | Vietnamese | vi | 0 (0%) | no | Latin with stacked diacritics | no | none | 3–5 | Other languages: none shipped (Figma ships none beyond the eight above). @@ -75,15 +88,16 @@ The layer is done. Per-language hours above are agent hours for a catalog of ~1, (a machine draft, then a pass over the panels for overflow), plus each language's plural rule where it isn't one/other; every language also needs a native speaker's review (human). Left before full parity besides the languages: localizing engine messages and number formatting (4–6 h); -right-to-left mirroring of the panels is in Arabic's hours. Total: **40–65 h**. +right-to-left mirroring of the panels is in Arabic's hours. Total: **32–55 h**. -Priority: Japanese and Korean next (the last of Figma's own languages, so their users expect -them), and native reviews of the Spanish, French, German and Brazilian Portuguese drafts. +Priority: native reviews of the six drafts (every one of Figma's languages now has one; Latin +American Spanish is the last Figma variant), then Simplified Chinese, whose UI fonts already work. ## Revision history | Date | Change | Summary | |---|---|---| +| 2026-10-12 | minor | Japanese and Korean draft catalogs and CJK UI fonts (gap 5): `ja.toml` and `ko.toml` translate every UI string (1,351 keys; plurals give only `other`, and `plural_one` never picks "one" in either), command label (519) and menu wording (29), machine-drafted and marked as drafts awaiting native review; Preferences ▸ Language lists 日本語 and 한국어, System picks ja* and ko*. CJK UI text renders: once the UI language, the open file's names or comments, typed text or the language picker needs Japanese kana, Hangul or Han, the desktop app appends one installed face per script to egui's fallbacks (Windows Yu Gothic UI / Meiryo / Malgun Gothic / Microsoft YaHei, macOS Hiragino Sans / Apple SD Gothic Neo / PingFang SC, Linux Noto Sans CJK; the craft-fonts build's BIZ UDPGothic first), reading only that face's file and sharing its bytes with egui (English users load none: startup and memory unchanged); the web shows Japanese and Korean only when built with craft-fonts' Noto Sans CJK (`FIGCRAFT_EMBED_CJK`), else it keeps them out of the picker and System. Localization 30% → 35%, 40–65 h → 32–55 h | | 2026-10-12 | minor | French, German and Brazilian Portuguese draft catalogs (gap 5): `fr.toml`, `de.toml` and `pt-BR.toml` translate every UI string (1,351 keys, 36 with plural forms), command label (519) and menu wording (29), machine-drafted and marked as drafts awaiting native review; they fall back to English per key, so new strings need only English and Spanish. French and Brazilian Portuguese count 0 as singular (`plural_one`); System picks the first OS language with a catalog (Windows' and macOS's preferred-language lists, `LANGUAGE` then the locale on Linux and BSD; pt-PT and pt read pt-BR); Preferences ▸ Language lists Français, Deutsch and Português (Brasil). Dropdowns, two-column labels and the home cards keep long translations on one line with an ellipsis and show them in full on hover. Localization 20% → 30%, 45–75 h → 40–65 h | | 2026-10-11 | major | Localization layer landed (gap 5): catalogs per language baked in at build time, English text as keys and fallback, `{named}` placeholders and one/other plurals, command labels by command id, Preferences ▸ Language (System follows the OS or the browser) applied live, `pref.language`, and a catalog check; English catalog (1,280 UI keys) and a complete Spanish draft (1,810 entries with command labels) waiting for native review; localization 10% → 20%, 60–100 h → 45–75 h | | 2026-10-10 | major | Created: English only, string counts measured from source, Figma's eight UI languages from its help center | diff --git a/docs/mcp.md b/docs/mcp.md index 8b92b50..8828c2d 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -271,7 +271,7 @@ on; `key` resolves keys the way the canvas does. Commands behind keys: nested layers), Escape or a click drops it. - `pref.reduceMotion {on?}`: reduced motion (the interface's own animations off; the system's accessibility setting turns it on too). Prototype transitions still play. -- `pref.language {language: system|en|es|fr|de|pt-BR|…}`: the app's interface language, applied live ("system": +- `pref.language {language: system|en|es|fr|de|pt-BR|ja|ko|…}`: the app's interface language, applied live ("system": the OS or browser language; a language without a catalog shows English). Command ids, labels and every result stay English. diff --git a/docs/roadmap.md b/docs/roadmap.md index 67c6f17..979c950 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,6 +1,6 @@ # FigCraft roadmap: milestones and what's next -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; `.fig` import, best effort; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~79%) · **Target:** Figma Design (desktop app 126.10.7) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Japanese and Korean draft catalogs and CJK UI fonts; plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; `.fig` import, best effort; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~79%) · **Target:** Figma Design (desktop app 126.10.7) Forward-looking plan. Where FigCraft stands today: [`ROADMAP.md`](../ROADMAP.md) and [`target-app-parity.md`](target-app-parity.md); the full ranked list: [`gaps.md`](gaps.md). Hours @@ -15,8 +15,9 @@ are one Opus 5.5 agent; most milestones split across 4–6 agents on disjoint cr exports, turn estimated percentages into measured ones: 15–30 h. 3. **Tool-by-tool interaction pass** against the running Figma ([`ui-parity.md`](ui-parity.md)): 40–60 h, parallel by tool. -4. **Languages** on the landed localization layer, Figma's own first (ja, ko; es, fr, de and pt-BR - are drafts awaiting native review): 3–7 h per language plus native review. +4. **Languages** on the landed localization layer: native reviews of the es, fr, de, pt-BR, ja and + ko drafts (people), Latin American Spanish, then the other key languages: 3–7 h per language + plus native review. 5. **Multiplayer M9**: accounts and teams on top of the live sessions and the standalone server (the WebSocket transport, hosting from the app, invite links that open the app, document sync, live cursors, selections, text carets, avatars and follow, per-user undo, reconnect with offline edits, collision-free ids for styles, variables, collections and comments, joining from the browser, and `figcraft-server` with persistence, publishing from the app and share links to edit or view landed), per [`collab-protocol.md`](collab-protocol.md) and [`server.md`](server.md): 45–90 h. ## Alpha gate @@ -72,6 +73,7 @@ blockers. | Date | Change | Summary | |---|---|---| +| 2026-10-12 | minor | Japanese and Korean draft catalogs and CJK UI fonts (gap 5): `ja.toml` and `ko.toml` translate every UI string (1,351 keys; plurals give only `other`, and `plural_one` never picks "one" in either), command label (519) and menu wording (29), machine-drafted and marked as drafts awaiting native review; Preferences ▸ Language lists 日本語 and 한국어, System picks ja* and ko*. CJK UI text renders: once the UI language, the open file's names or comments, typed text or the language picker needs Japanese kana, Hangul or Han, the desktop app appends one installed face per script to egui's fallbacks (Windows Yu Gothic UI / Meiryo / Malgun Gothic / Microsoft YaHei, macOS Hiragino Sans / Apple SD Gothic Neo / PingFang SC, Linux Noto Sans CJK; the craft-fonts build's BIZ UDPGothic first), reading only that face's file and sharing its bytes with egui (English users load none: startup and memory unchanged); the web shows Japanese and Korean only when built with craft-fonts' Noto Sans CJK (`FIGCRAFT_EMBED_CJK`), else it keeps them out of the picker and System. Current focus 4 now lists the drafts' native reviews | | 2026-10-12 | minor | M11: plugin widgets (API 3: plugin-drawn layers on the canvas, redrawn on clicks from state kept in the document), panels of several plugins side by side and the colour picker on plugin colour fields; 15–40 h → 10–30 h | | 2026-10-12 | minor | French, German and Brazilian Portuguese draft catalogs (gap 5): every UI string, command label and menu wording (1,899 entries) machine-drafted in each and marked as drafts awaiting native review, falling back to English per key (new strings need only English and Spanish); 0 counts as singular in French and Brazilian Portuguese; System picks the first OS language with a catalog (pt-PT and pt read pt-BR); long translations elide with a tooltip in dropdowns, two-column labels and the home cards. Current focus 4 now lists Japanese and Korean | | 2026-10-11 | minor | `.fig` import, best effort: current focus 1 and the alpha gate's `.fig` row move to the import's tail (30–60 h → 8–15 h); M6 ~55% → ~65%, 37–75 h → 15–30 h | diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 75b2ccc..b102fff 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -1,6 +1,6 @@ # FigCraft parity with Figma -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; headline percentages recomputed from the area table: feature breadth ~84%, core ~94%, mainstream ~50%; text lists, hanging punctuation and decoration styles; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; export and inspect behaviour suite and fixes; .fig import: editable vector networks and more layer kinds; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; styles and variables behaviour suite and fixes; prototyping behaviour suite and fixes; components behaviour suite and fixes; embedded image colour profiles; layers panel keyboard: F2 rename, Shift+F10 context menu, keyboard box selection, 10k-layer QA; per-side stroke weight variables; text behaviour suite: CJK line breaking, metrics, vertical trim; selection and transform behaviour suite and fixes; `.fig` import, best effort; auto layout behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~80%; ready ~49%; last major: full re-measure against Figma desktop 126.10.7) · **Target:** Figma Design (desktop app 126.10.7, macOS) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Japanese and Korean draft catalogs and CJK UI fonts; plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; headline percentages recomputed from the area table: feature breadth ~84%, core ~94%, mainstream ~50%; text lists, hanging punctuation and decoration styles; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; export and inspect behaviour suite and fixes; .fig import: editable vector networks and more layer kinds; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; styles and variables behaviour suite and fixes; prototyping behaviour suite and fixes; components behaviour suite and fixes; embedded image colour profiles; layers panel keyboard: F2 rename, Shift+F10 context menu, keyboard box selection, 10k-layer QA; per-side stroke weight variables; text behaviour suite: CJK line breaking, metrics, vertical trim; selection and transform behaviour suite and fixes; `.fig` import, best effort; auto layout behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~80%; ready ~49%; last major: full re-measure against Figma desktop 126.10.7) · **Target:** Figma Design (desktop app 126.10.7, macOS) The authoritative assessment of how close FigCraft is to Figma Design. [`ROADMAP.md`](../ROADMAP.md) summarizes it; [`gaps.md`](gaps.md) is the ranked work list; the measured menu checklist is @@ -17,11 +17,11 @@ summarizes it; [`gaps.md`](gaps.md) is the ranked work list; the measured menu c |---|---|---| | Menu/command breadth | **100%** (204 / 204 catalogued menu items have a live command) | **measured** (`cargo xtask parity`, 2026-10-11) | | Feature breadth (does each Figma Design feature exist, weighted) | **~84%** (core editor areas 1–16: ~94%) | estimated from the area table below | -| Ready for real work | **~52%** | estimated (dimension table below: written weights × written per-dimension scores) | +| Ready for real work | **~53%** | estimated (dimension table below: written weights × written per-dimension scores) | | Essentials user | **~57%** | estimated ([below](#essentials-user): core features 77.8% × discounts 0.92 × 0.92 × 0.88) | | Mainstream practitioner | **~49%** | estimated ([below](#mainstream-practitioner): weekly areas 72.6% × discounts 0.9 × 0.9 × 0.85) | -| Remaining to beta | **~162–292 h** one Opus 5.5 agent (~33–67 h wall-clock with 5 parallel agents) | estimated | -| Remaining to full parity | **~276–538 h** one agent (~85–148 h wall-clock with 5 parallel agents) | estimated | +| Remaining to beta | **~155–280 h** one Opus 5.5 agent (~32–64 h wall-clock with 5 parallel agents) | estimated | +| Remaining to full parity | **~268–528 h** one agent (~83–145 h wall-clock with 5 parallel agents) | estimated | | Stage | **alpha**: the alpha gate passes ([roadmap](roadmap.md#alpha-gate)); multiplayer and checking the best-effort `.fig` import on real files are beta gaps (see [ROADMAP](../ROADMAP.md#stage)) | | The previous figures (ROADMAP of 2026-10-10, "feature depth ~79%", "full parity 115–195 h") were @@ -35,7 +35,7 @@ tool; presence was being graded as behaviour in places. | Audience | Ready % | Opus 5.5 agent wall-clock hours to ~95% | Work that dominates | |---|---|---|---| -| Full target (ready for real work) | ~52% | ~281–540 h | multiplayer (42–84), localization (40–65), plugins (10–30), the interaction pass (40–60), GPU canvas (30–60), AI (30–60), the `.fig` import's tail (5–10) | +| Full target (ready for real work) | ~53% | ~273–530 h | multiplayer (42–84), localization (32–55), plugins (10–30), the interaction pass (40–60), GPU canvas (30–60), AI (30–60), the `.fig` import's tail (5–10) | | Mainstream practitioner | ~49% | ~130–244 h | core editor depth incl. the `.fig` import's tail (49–98), the interaction pass (40–60), real-file corpus and platform QA (25–50), `.fig` export for handing work back (15–30) | | Essentials user | ~57% | ~60–110 h | the `.fig` import's tail so the files people send open well (5–10), core tool polish (25–45), interaction pass on the core tools (15–25), stability QA (10–20), onboarding and starter templates (5–10) | @@ -129,11 +129,11 @@ Breadth: does it exist. Ready: depth, correctness and fidelity for real projects | Stability | 8 | 55% | 20–40 | Never-crash lints, command guard with rollback, recovery copies, 963 tests incl. junk-parameter sweeps and a seeded retained-render walk; but two days old, one release (v0.2.0), no field reports, QA mostly on macOS | [gaps](gaps.md) | | Performance | 6 | 60% | 30–60 | `cargo xtask bench`: 50k-layer page ~8 ms zoomed out, 10k-layer edits ~0.2 ms, 2,000-instance design system edits 4–64 ms; CPU (tiny-skia) canvas where Figma renders on the GPU; nothing timed against Figma on the same file | [hardware-parity](hardware-parity.md) | | Hardware | 3 | 60% | 10–21 | Trackpad pinch and HiDPI yes; pen pressure on Windows and from browser styluses (none from macOS/Linux tablets); several windows (screen-reader tree in the main one only); no GPU canvas, no P3 on screen | [hardware-parity](hardware-parity.md) | -| Localization | 3 | 30% | 40–65 | The layer, an English catalog and complete machine drafts of Spanish, French, German and Brazilian Portuguese (none reviewed by a native speaker); Figma's Japanese, Korean and Latin American Spanish are missing; engine messages stay English | [localization-parity](localization-parity.md) | +| Localization | 3 | 35% | 32–55 | The layer, an English catalog and complete machine drafts of Spanish, French, German, Brazilian Portuguese, Japanese and Korean (none reviewed by a native speaker), CJK UI text in installed faces loaded on demand (web: only the craft-fonts CJK build); Latin American Spanish is missing; engine messages stay English | [localization-parity](localization-parity.md) | | Platforms | 3 | 75% | 10–20 | macOS, Windows (x64/x86/arm64), Linux, FreeBSD, web all packaged (v0.2.0); Figma also has iOS/Android apps; non-macOS QA thin | [hardware-parity](hardware-parity.md) | | Ecosystem/plugins | 3 | 34% | 10–30 | Own WASM plugins with a Rust SDK and three examples (#101), plugin panels and settings (ABI v2), widgets that take clicks (API 3); no Figma plugin compatibility, no distribution or community files; the CLI, control channel and MCP server are ahead of Figma for agents | [gaps](gaps.md) | | AI features | 2 | 0% | 30–60 | None | [gaps](gaps.md) | -| **Ready for real work** | 100 | **~52%** | **~276–538** | | | +| **Ready for real work** | 100 | **~53%** | **~268–528** | | | Dimension hours add up to the full-parity total without double counting: the feature-area rows for import/export (14), multiplayer and team libraries (17, 19), plugins (18) and AI (21) are @@ -204,7 +204,7 @@ from anyone but the maintainers (`gh issue list`, `gh api .../issues/comments`; private, 1 star, PRs only from maintainers). No outside evidence either way; nothing raises the number. -**Why it is lower than ready for real work (~52%), unusually.** The full number averages +**Why it is lower than ready for real work (~53%), unusually.** The full number averages dimensions additively, so the missing `.fig` exchange costs only the file-format dimension's 12% weight, and FigCraft earns points the mainstream number doesn't count (platforms 75%: Linux, FreeBSD and the web, where Figma has no desktop app). The mainstream number applies file exchange @@ -617,6 +617,7 @@ Carried over from the ROADMAP's "Shipped so far" (2026-10-10). The test count th | Date | Change | Summary | |---|---|---| +| 2026-10-12 | minor | Japanese and Korean draft catalogs and CJK UI fonts (gap 5): `ja.toml` and `ko.toml` translate every UI string (1,351 keys; plurals give only `other`, and `plural_one` never picks "one" in either), command label (519) and menu wording (29), machine-drafted and marked as drafts awaiting native review; Preferences ▸ Language lists 日本語 and 한국어, System picks ja* and ko*. CJK UI text renders: once the UI language, the open file's names or comments, typed text or the language picker needs Japanese kana, Hangul or Han, the desktop app appends one installed face per script to egui's fallbacks (Windows Yu Gothic UI / Meiryo / Malgun Gothic / Microsoft YaHei, macOS Hiragino Sans / Apple SD Gothic Neo / PingFang SC, Linux Noto Sans CJK; the craft-fonts build's BIZ UDPGothic first), reading only that face's file and sharing its bytes with egui (English users load none: startup and memory unchanged); the web shows Japanese and Korean only when built with craft-fonts' Noto Sans CJK (`FIGCRAFT_EMBED_CJK`), else it keeps them out of the picker and System. Localization 30% → 35% (drafts, not reviewed: graded low), 40–65 h → 32–55 h; ready for real work ~52% → ~53% (52.9 → 53.1 by the dimension table); full parity ~284–554 h → ~276–544 h; beta ~162–292 h → ~155–280 h (Japanese and Korean leave the beta list; their native reviews need people) | | 2026-10-12 | minor | Plugin widgets and the panel tail (gap 6, plugin API 3; v1 and v2 plugins unchanged): a plugin marked as a widget puts a layer of its own on the canvas from Plugins ▸ Widgets or `widget.insert`: it describes the layer (frames with auto layout, text, rectangles, ellipses, images it carries) and FigCraft validates the description (size, layer count, depth, numbers, colours, text and image sizes) and builds it as a frame with locked layers inside; a click on a part the plugin named (on the canvas with the Move tool, a pointing hand over it, or `widget.click`) calls the plugin back in a fresh, metered sandbox with the widget's state, as one undo step, and the widget is redrawn; the state lives in the widget's own layer data, so widgets survive save and reload, copying, undo, export and live sessions; no plugin can write that data or call `widget.*`. `widget.list` lists them. A Counter example widget. Plugin panels of different plugins open side by side, and a colour field's swatch opens the colour picker (the plugin hears of the colour when a drag ends). Plugins & widgets 45%/28% → 55%/32%, 15–40 h → 10–30 h; Ecosystem dimension 28% → 34%; weighted totals unchanged at this rounding; full parity ~286–558 h → ~281–548 h | | 2026-10-12 | minor | French, German and Brazilian Portuguese draft catalogs (gap 5): every UI string, command label and menu wording (1,899 entries) machine-drafted in each and marked as drafts awaiting native review, falling back to English per key (new strings need only English and Spanish); 0 counts as singular in French and Brazilian Portuguese; System picks the first OS language with a catalog (pt-PT and pt read pt-BR); long translations elide with a tooltip in dropdowns, two-column labels and the home cards. Localization 20% → 30%, 45–75 h → 40–65 h; ready for real work unchanged (~52%; 52.6 → 52.9); full parity ~289–564 h → ~284–554 h; beta ~170–305 h → ~162–292 h (Figma's languages left on the way to beta: Japanese and Korean, 7–12 h) | | 2026-10-12 | minor | Cursor chat and spotlight in live sessions: `/` opens a chat bubble at your pointer that everyone sees as you type and that fades a few seconds after the last change; a spotlight (your avatar's menu, `collab.spotlight`) makes everyone follow your view and page, latecomers included, until they move their own. Both are ephemeral presence the host validates and rate-limits, passed only to clients that read them. Multiplayer & sharing breadth 15% → 17%, ready unchanged (5%), 45–90 h → 42–84 h; the Collaboration dimension's hours 55–110 → 52–104 h (the dimension hours still add up to the total); feature breadth (~84%) and ready for real work (~51%) unchanged at this rounding; full parity ~301–587 h → ~298–581 h | diff --git a/docs/translating.md b/docs/translating.md index 3a5b352..45a2e19 100644 --- a/docs/translating.md +++ b/docs/translating.md @@ -8,8 +8,9 @@ a catalog (the browser's language on the web): a regional tag reads its language (`fr-CA` → `fr`), and a language with only a regional catalog reads that one (`pt-PT` → `pt-BR`). `pref.language {language}` does the same from the CLI, MCP and the control channel. -The catalogs: English (`en`, the source), and Spanish (`es`), French (`fr`), German (`de`) and -Brazilian Portuguese (`pt-BR`), machine-drafted and waiting for native speakers' review. +The catalogs: English (`en`, the source), and Spanish (`es`), French (`fr`), German (`de`), +Brazilian Portuguese (`pt-BR`), Japanese (`ja`) and Korean (`ko`), machine-drafted and waiting for +native speakers' review. ## The catalogs @@ -29,7 +30,15 @@ A key a catalog lacks shows its English text, so a partial catalog is safe to sh Typography follows each language: French puts a no-break space (`\u00A0` in the TOML) before `:` `;` `?` `!`, inside « » and before `%`; German uses „ “ and formal address (Sie); Brazilian -Portuguese uses Brazilian words (arquivo, salvar, tela, você), not European ones. +Portuguese uses Brazilian words (arquivo, salvar, tela, você), not European ones. Japanese is +concise, without です/ます endings, with full-width ()「」:、。 where Japanese UI text has them; +Korean labels end without 합니다 (instructions in -세요). Neither has plural forms. + +CJK text needs a CJK font, which egui and Inter lack: the desktop app adds an installed one when +something on screen needs it (see `crates/ui-egui/src/cjk.rs`). The web build has no system fonts, +so Japanese and Korean appear there only in a build with craft-fonts and `FIGCRAFT_EMBED_CJK=1` +(Noto Sans CJK, +16 MB); otherwise they are left out of the picker. A new CJK or other non-Latin +language also needs its script in `cjk::language`. ## Adding a language @@ -38,13 +47,14 @@ Portuguese uses Brazilian words (arquivo, salvar, tela, você), not European one 2. Translate every value; keep the keys. Keep `{placeholders}` exactly, "…" where English has it, brand names and keyboard glyphs. English labels of commands: `figcraft-cli commands`. 3. Plurals: give `one` only if the language has a singular form (Japanese, Korean and Chinese give - only `other`). `trn` picks `one` for a count of 1, and also for 0 in French and Brazilian - Portuguese (keep `{n}` in their `one` forms); a language with other rules needs its rule in + only `other`, and `plural_one` returns false for them). `trn` picks `one` for a count of 1, and + also for 0 in French and Brazilian Portuguese (keep `{n}` in their `one` forms); a language with other rules needs its rule in `plural_one` in [`crates/ui-egui/src/i18n.rs`](../crates/ui-egui/src/i18n.rs). 4. To require full coverage, add the code to `COMPLETE` in [`crates/ui-egui/src/i18n_tests.rs`](../crates/ui-egui/src/i18n_tests.rs). Every later PR that adds a string then has to translate it into each complete language, so only Spanish is there: - French, German and Brazilian Portuguese are complete today but registered as drafts, and a + French, German, Brazilian Portuguese, Japanese and Korean are complete today but registered as + drafts, and a string added later shows English in them until it is translated. To list what a draft lacks, add its code to `COMPLETE` locally and run the check. 5. Run the check and look at the panels in the app (longer words must fit the right panel):