Compare commits

...

56 Commits

Author SHA1 Message Date
bherbruck 18a734d029 Add a trademark policy for the SolidCraft name and logo
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 11:19:36 -04:00
github-actions[bot] 48bcc83e2e Regenerate generated files and fold pending files [skip ci] 2026-10-28 14:56:01 +00:00
austin62jake 1e3cb3e36e Motion interference: a check cut short is not clear, and budget_s gives it time (#7855) (#7934)
* claim: #7855

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

* Motion interference: a check cut short by its work budget is not clear (#7855)

motion.interference stops when its work budget runs out (truncated) but
answered clear: collisions.is_empty(), so a check that reached only the first
steps read as a pass: a gear pair checked for 14 of 61 samples was "clear".
clear is now true only when every sample was checked and none collide.

The budget is an argument of interference_within, so a test can cut a check
short: B slides up to touching A, a full check is clear, and the least work
that checks a first step stops after 1 of 16 samples with clear: false (it
was clear: true before). The guide and the mechanisms skill say the same.

The issue's second request, a budget_s on motion.interference, is not here.

Refs #7855.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

* Motion interference: budget_s gives a check the time it needs (#7855)

The work budget is fixed, so a gear pair drawn in detail was cut short
after a few samples, or refused before its first one. motion.interference
now takes budget_s (seconds, above 0, at most 86400, as inspect.interference
allows): the check then runs until that time instead of the work budget,
looked at before each sample, and echoes budget_s in its answer. Without
budget_s nothing changes. The refusal before a first step now names the
budget that ran out and suggests budget_s.

Tests: given a time, the smallest work budget (which checks no step) no
longer stops the check, through motion.interference too; budget_s 0, -1,
1e9 and "soon" are refused.

Fixes #7855.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 12:19:10 +00:00
Inguss 4d6664e4ca fix(ui): expose Redefine Sketch Plane in History menus (#8024) 2026-10-28 12:18:53 +00:00
raykholo d56dc310b0 Browser: Collapse All keeps the clicked row open (#8032) (#8033)
Collapse All from a component or placement row folds everything under that
row and leaves the row itself open, matching the whole-tree Collapse All,
which already keeps the design row open.
2026-10-28 12:18:28 +00:00
semmelrinde 4ab612ea67 Standard Parts and Contact Set: label the rows in words, not with raw keys (#8005)
* Standard Parts and Contact Set: label the rows in words, not with raw keys

The Insert Part dialog listed a size's dimensions under the library's
keys (d, head height, socket depth), and the Contact Set dialog's
checkbox read "enabled". The dimensions now take messages (Nominal
diameter, Head height, Socket depth, ...) and the checkbox reads
Enabled, translated like the rest of the dialogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Contact Set: translate the Enabled checkbox's label

ui_kit::checkbox paints the text it is given; the callers translate it,
as Configuration Rules' Enabled does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:17:07 +00:00
semmelrinde 73f06753b6 Swedish: translate 946 messages the catalog was missing (batch 1) (#8181)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:16:54 +00:00
semmelrinde 292177e085 Preferences: the tab colour strip names the tabs as the ribbon does (#8027)
The Interface page's strip of tab accent colours looked up its own
word-cased names ("Sheet Metal", "Surface"), which the catalogs
mostly don't carry or carry with another meaning: in German it read
"Sheet Metal" and "Flächenkörper" where the ribbon says Blech and
Fläche. It now names each tab the way the ribbon does, through the
tab's heading message, and the Form tab gets one.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:16:48 +00:00
Colin Faulkingham d7111c7326 Ribbon: keep workspace captions inside the switcher (#7931) (#7956)
* claim: #7931

* Fix translated workspace captions overflowing the switcher (#7931)
2026-10-28 12:16:19 +00:00
github-actions[bot] 745184f2fc Regenerate generated files and fold pending files [skip ci] 2026-10-28 14:26:54 +00:00
semmelrinde 942f11169c Preferences: the snap-suppress choice and Direct interaction in the user's language (#8067)
* Preferences: the snap-suppress choice and Direct interaction in the user's language

The Hold to stop snapping choice joined its keys with an English "or"
("Cmd or Option", the default) in every language, and Navigation's
Direct interaction setting and its note had no message. The choice now
reads through a message with the keys as placeholders, and the setting
gets its two messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the new test away from where another open PR adds one

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:15:48 +00:00
semmelrinde 029cf29b49 Dialogs: 54 labels that read English in every language get messages (#8049)
* Dialogs: 54 labels that read English in every language get messages

The construction dialogs' selection fields (First edge, Second point,
Through point, ...), the joint types (Rigid, Revolute, Slider, ...), the
Sheet Metal and Plastic rules' rows (K Factor, Flange Gap, Min Draft,
...) and a few options and prompts are passed to the label translator as
English source text that no catalog carried, so they showed English in
every language. They are added in one pending file, with the eleven
usual translations, and a test makes sure every dialog's selection
fields keep a message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dialog labels: German Flange Gap is Flanschspalt, as the catalog's Flansch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:15:35 +00:00
semmelrinde 7ad059aec9 Italian: translate 719 messages the catalog was missing (batch 1, all but the Render workspace) (#8062)
The Italian catalog lacked 1350 of the English messages. This batch
translates the 719 outside the Render workspace: Preferences, the
Assistant, the help texts, command labels, materials, navigation and
the rest. It uses the catalog's own terms (Schizzo, Lavorazione, Corpo,
Giunto, Cronologia, Struttura, Risalto, Appoggio, Aggancio a scatto).
The Render workspace's 600 messages are left for a second batch while
that workspace is still being built.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:15:24 +00:00
github-actions[bot] a2a00aa9ee Regenerate generated files and fold pending files [skip ci] 2026-10-28 13:58:14 +00:00
github-actions[bot] 59551c59ab Regenerate generated files and fold pending files [skip ci] 2026-10-28 13:49:47 +00:00
semmelrinde bf1b09698c Insert Part: the part families and the Name hint in the user's language (#8018)
* Insert Part: name the part families in the user's language

The Type list of Insert Part and the Change Part Size dialog showed the
library's English family names (Socket head cap screw, Hex nut, ...) in
every language. Each family now has a message under its library id,
and a family the catalogs don't know keeps the library's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Insert Part: the Name field's automatic hint in the user's language

The hint was the English word "automatic"; it now takes the catalogs'
parts.automatic_name, which every language already translates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the family-name helper and its test away from where #8005 adds its own

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:15:15 +00:00
semmelrinde fc2142b407 Turkish: translate the 200 messages the catalog was missing (#8070)
* Turkish: translate the 113 messages the catalog was missing

The Turkish catalog lacked 113 of the English messages: the newer
Preferences settings, the hole presets, the slicer messages, the
Assistant's start-up options and tool summaries, and the Render
workspace's stage, shots and inspector labels. They are translated in
one pending file, with the catalog's own terms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Translate the 87 messages main added since (the navigation bar's)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:15:03 +00:00
semmelrinde d3b2c715d3 Dialogs: translate the texts a few dialogs draw themselves (#8056)
* Dialogs: translate the texts a few dialogs draw themselves

The joints' Play/Stop buttons, the Motion Study's Loop and the BOM's
sub-parts checkboxes, the Stitch tolerance hint, the Flange type and the
Emboss wrap note were drawn as English literals; the joint lists named
each joint's type by its Rust name (PinSlot, PointOnPlane). They now take
messages, and the joint lists use the Type box's label, translated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the new test away from where another open PR adds one

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:14:51 +00:00
semmelrinde 09308fceb1 Dialogs: 96 hints and refusals that read English in every language get messages (#8083)
The Surface, Sheet Metal, Plastic, Frame, Move, Align, Assembly, Cam,
Coupling, Sweep, Part Size and sketch editing dialogs refuse their
inputs with English sentences ("select bodies first", "pick faces of
one body"). The dialog translates a refusal through the catalogs as it
shows it, but no catalog carried these 96, so they showed English in
every language. They are added in one pending file with the eleven
usual translations.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:14:41 +00:00
semmelrinde 8f87509f7d Russian: translate 841 messages the catalog was missing (batch 1) (#8077)
Everything outside the Render workspace, which is still being built:
Preferences and the new navigation bar, the Assistant, the help texts,
command labels, materials, hole presets, the slicer messages and the
remaining dialog labels, with the catalog's own terms.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:14:34 +00:00
semmelrinde c962e5e8cd Traditional Chinese: translate 897 messages the catalog was missing (batch 1) (#8078)
Everything outside the Render workspace, which is still being built:
Preferences and the new navigation bar, the Assistant, the help texts,
command labels, materials, hole presets, the slicer messages and the
remaining dialog labels, with the catalog's own terms.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:14:33 +00:00
semmelrinde 7df858594d Indonesian: translate 898 messages the catalog was missing (batch 1) (#8098)
Everything outside the Render workspace, which is still being built:
Preferences and the new navigation bar, the Assistant, the help texts,
command labels, materials, hole presets, the slicer messages and the
remaining dialog labels, with the catalog's own terms.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:14:22 +00:00
semmelrinde fed9605357 Sketch: the status in the view and the browser's editing mark in the user's language (#8084)
* Sketch: the status in the view and the browser's editing mark in the user's language

While a sketch is edited, the view's corner said "Sketch1 — 2 degrees of
freedom" (or "fully constrained", "constraints conflict") and the
browser marked the sketch "(editing)" or "(attachment lost)", in
English whatever the language; one degree of freedom read "1 degrees of
freedom". They now take messages: the catalogs' existing degrees-of-
freedom ones and four new ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch status and editing mark: the sketch's default name as shown elsewhere

The browser shows a default name in the user's language ("Skizze 1")
except on the edited sketch's row, whose mark made it a different text;
the view's status kept the stored name too. Both now use the name as the
browser shows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:13:38 +00:00
semmelrinde bf1886e90a Motion dialogs: translate the notes and refusals they draw themselves (#8096)
Motion Study, Motion Trace, the motion plot, Explode and the contact
check drew their notes and refusals as they got them ("add a key for a
joint first", "select a point on a component", "none"), so they read
English in every language. They now go through the label translator, and
the four that no catalog carried get messages.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:13:38 +00:00
phanoob dfa9afd39f Sketch: leaving a sketch opened inside a component gives the active component back (#8127) (#8157)
Double-clicking a sketch row inside a component (an inserted fastener's sketch)
activates that component so the sketch is edited in its placement. Finish and
Cancel only closed the sketch, so the component stayed active and every other
body stayed faded.

Edit Sketch now remembers the component and placement active before it
activated the sketch's own (also when sketch.edit activates the component of a
face-attached sketch), and leaving the sketch makes that one active again, as
Finish already puts the history marker back. A component activated while the
sketch is open stays active.

Co-authored-by: Phanoob <phanoob@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:13:15 +00:00
semmelrinde 944c658c90 Czech: translate 867 messages the catalog was missing (batch 1) (#8188)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:12:06 +00:00
semmelrinde 8f8df03358 Navigation: Maya and HFSS mouse presets (#6474, #2742) (#8184)
Maya moves the camera with Alt and any button (left orbits, middle pans,
right zooms), middle drag also pans. HFSS pans with Alt+left drag and zooms
with Shift+Alt+left; its Ctrl+left orbit is the drag from empty space every
preset already has, so a Ctrl+click on geometry still adds to the selection.
The help texts are in the catalog for every locale that has the other
presets' help.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:12:05 +00:00
github-actions[bot] 92fc868aa9 Regenerate generated files and fold pending files [skip ci] 2026-10-28 13:22:20 +00:00
github-actions[bot] 33281cf3bc Regenerate generated files and fold pending files [skip ci] 2026-10-28 13:13:50 +00:00
semmelrinde d64816437a Dutch: translate 942 messages the catalog was missing (batch 1) (#8172)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:12:02 +00:00
semmelrinde 8210e94b6d Malay: translate 888 messages the catalog was missing (batch 1) (#8216)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:11:08 +00:00
semmelrinde f6d969f98a Hungarian: translate 946 messages the catalog was missing (batch 1) (#8199)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:11:06 +00:00
dudedagger42 59faca3850 Canvas and Decal: send the picked face, so a large design takes the image (#5592) (#5593)
* claim: #5592

* Canvas and Decal: send the picked face, so a large design takes the image (#5592)

A click with Canvas or Decal sent only the point, so the engine searched every face of every
body for it and gave up on a large design ("face capture work limit exceeded"). Send the
picked body, face index and path as Create Sketch does; canvas.decal takes that face pick too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Canvas and Decal test: drop the check that a point alone gives up

On upstream main a sketch on a face by its point alone no longer gives up on this design, so
the test keeps only what the picked face has to do: both images land on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:11:01 +00:00
semmelrinde 29a2f33664 Galician: translate 888 messages the catalog was missing (batch 1) (#8214)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:10:58 +00:00
sascha2101 9d4d7932ee Sketch: offer an arc length dimension for a selected arc (#6039) (#6264)
* claim: #6039

* Sketch: offer an arc length dimension for a selected arc (#6039)

The arc length dimension already existed in the engine (sketch.dimension with
type arc_length), but nothing in the UI led to it: the Dimension tool and the
context menu always gave an arc its radius.

With exactly one arc selected, the sketch context menu now offers Arc Length
Dimension next to Sketch Dimension, which adds the dimension through the
existing command.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FN5eEMrqWWXqi65FcK8GXq

* test: move the arc length menu test up to avoid a merge conflict

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: sascha2101 <221609842+sascha2101@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:10:45 +00:00
github-actions[bot] 54a207cb8b Regenerate generated files and fold pending files [skip ci] 2026-10-28 12:44:09 +00:00
github-actions[bot] 5bf5de49a5 Regenerate generated files and fold pending files [skip ci] 2026-10-28 12:35:35 +00:00
semmelrinde cee995e776 Norwegian Bokmål: translate 693 messages the catalog was missing (batch 1) (#8218)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:10:34 +00:00
Nathan Dane b86c75544e Appearance: read the look chain and replace a look everywhere in one undo step (#6428) 2026-10-28 12:10:31 +00:00
yhamil04 249318cffb Right-click opens the menu despite tiny pointer movement (#5517) (#7939)
* claim: #5517

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Right-click opens the menu despite tiny pointer movement (#5517)

A Magic Mouse moves the pointer a fraction of a point as it is clicked.
The right button orbited on any movement, and the menu needed exactly
zero movement in the release frame, so most right-clicks only nudged
the view. The right button now navigates once the press can no longer
be a click (egui's click distance and time), catching up with the
travel since the press, and a right-click is egui's click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:08:27 +00:00
Colin Faulkingham 6f8ee10a86 Appearance: apply browser actions to all selected bodies (#7935) (#7941)
* claim: #7935

* fix: apply browser appearance changes to selected bodies (#7935)
2026-10-28 12:08:21 +00:00
N3MI-DG 30cb1238f7 Browser: reveal a placed body's row when it is picked or found (#7947) (#7948)
* claim: #7947

* Browser: reveal a placed body's row when it is picked or found (#7947)

The off-screen skip in `entry_row` keeps the reveal target's row alive so it
still has a rect to scroll to, but it matched `app.tree.reveal` (a world body
name) against `Entry::key` (the placement-local name). For a placed body those
never match, so the row returned early and the `scroll_to_rect` below it, which
does use `row_key`, was never reached. `app.tree.reveal` is then cleared at the
end of the frame, so there was no second chance.

Match the skip on `row_key` minus its `b:` prefix, as the `scroll_to_rect`
already does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-10-28 12:08:01 +00:00
raykholo db999b2a98 Control protocol: the ui.prefs settings as a sorted list, one per line (#7747) (#7988) 2026-10-28 12:07:43 +00:00
semmelrinde e59decda95 Primitive dialogs: label the size fields in words, not with the parameter names (#7995)
The Box, Cylinder, Cone, Sphere, Torus and Coil dialogs labelled their
size rows with the command's parameter names (length, top_diameter,
section_size), in every language. Each row now takes a message: Length,
Top diameter, Major radius, Section size, translated as the rest of the
dialog is.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:07:37 +00:00
github-actions[bot] aca80f2054 Regenerate generated files and fold pending files [skip ci] 2026-10-28 10:25:10 +00:00
Nathan Dane 0b2efd60b9 Render browser: scene tree with Environment, Lights, Shots and Objects rows, resolved appearances and a Browser selection (#6427) 2026-10-28 09:58:57 +00:00
amolinari-autotex 54f613e4dd Preserve linked component materials and appearances (#7609) (#7616)
* Fix linked component materials and appearances (#7609)

* Linked components: the cached link read carries the source properties

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Update Links: a link without recorded inherited properties is read again

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preserve authored linked-face overrides and apply cached source properties

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:33:49 +00:00
github-actions[bot] ae07e36a7d Regenerate generated files and fold pending files [skip ci] 2026-10-28 07:57:59 +00:00
Nathan Dane 18fe82ab26 Render workspace: focus view, compact docks, a Browser chip at narrow widths and a localisation pass (#7376) 2026-10-28 07:29:53 +00:00
github-actions[bot] 372badfc1b Regenerate generated files and fold pending files [skip ci] 2026-10-28 06:43:04 +00:00
Nathan Dane 1781b4d323 Render workspace: move the Inspector or Browser dock to either side with view.render_dock and a header menu (#7230) 2026-10-28 06:15:13 +00:00
github-actions[bot] cf5dc813e2 Regenerate generated files and fold pending files [skip ci] 2026-10-28 04:43:28 +00:00
Nathan Dane b0c8c466b0 Navigation bar: icons for visual styles, selection modes and display (#6585) (#6898)
* Navigation bar: slot model and one-row renderer (#6585)

* Navigation bar: customisation section in Preferences (#6585)

* Navigation bar: icons for visual styles, selection modes and display (#6585)

* Navigation bar: redraw the Bodies, Parts and Components selection icons (#6585)

* Navigation bar: refine the Ground shadow, Ambient occlusion, Parts and Components icons (#6585)

* Navigation bar: solid cube and a longer arc for the Ground shadow icon (#6585)

* Navigation bar: the owner accepts the new icons as final (#6585)
2026-10-28 04:16:44 +00:00
github-actions[bot] 85aaed2ccb Regenerate generated files and fold pending files [skip ci] 2026-10-28 03:48:50 +00:00
Nathan Dane 110efa3598 Render: allow picking in the product view with a Body, Face or Component filter and outline the selection in the product pass only (#6426) 2026-10-28 03:20:43 +00:00
P'tite Tête 9fb41f8378 feat: Start a new selection's preview without waiting for the obsolete one (#7167) (#7261)
- Leave the running preview behind when the selection moves to another setup, asked to stop
- Keep at most two obsolete previews running; streaming, tools and other inputs wait as before
- Keep no result of a cancelled watched evaluation in the shared evaluation cache
- Test the detaching, the cancel reaching the spawned job, and the cache guard

Co-authored-by: P'tite Tête <asso@ptitetete.com>
2026-10-28 01:32:17 +00:00
175 changed files with 23892 additions and 1153 deletions
+16
View File
@@ -429,6 +429,20 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
| assets/icons/ui/design/svg/model/status_recovery.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/frame_member.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/render_environment.svg | SolidCraft contributors | original Studio icon master (64 grid): dome with a grey cube inside | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/style_shaded.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/style_wireframe.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/style_hidden_edges.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/style_translucent.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/select_faces_edges.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/select_bodies.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/select_features.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/select_parts.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/select_components.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/select_sketch.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/display.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/grid.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/ground_shadow.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/ambient_occlusion.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/placeholder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/plane.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/plane_angle.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
@@ -581,6 +595,8 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
| assets/styles/ui/themes/cga.json | SolidCraft contributors | original SolidCraft theme file using the 16 colours of the IBM Color Graphics Adapter (black, cyan, magenta, and white of its high-intensity palette 1 for the interface) | MIT OR Apache-2.0 |
| assets/styles/ui/themes/1-bit.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
| assets/styles/ui/themes/1-bit-dark.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
| `assets/locales/pending/navbar-customisation.json` | SolidCraft contributors | Original navigation bar editor translations | MIT OR Apache-2.0 |
| `assets/locales/pending/navbar-slots.json` | SolidCraft contributors | Original navigation slot translations | MIT OR Apache-2.0 |
## Code adapted from sibling projects
+3
View File
@@ -287,6 +287,9 @@ and a fresh CI run:
- **Toolbar commands without help** (`BACKLOG` in `crates/ui-egui/src/command_help.rs`): sorted,
one id per line, and it only shrinks. Writing a command's help removes its line; a new command
is never added to it.
- **`ui.prefs` settings** (`docs/control-protocol.md`): one line per setting, sorted by name, in
the list under the protocol table; add a new setting on its own line rather than editing a shared
row.
- **Languages** (`crates/ui-egui/src/i18n.rs`): one per line, English first, then by id (a test
checks it).
- **Generated files**: `THIRD-PARTY-LICENSES.txt` and `docs/features.md` are rewritten on `main`
+2 -1
View File
@@ -131,7 +131,8 @@ them: read [DISCLAIMER.md](DISCLAIMER.md).
MIT OR Apache-2.0, at your option. Developed under the
[clean-room contribution rules](AGENTS.md); third-party code and assets retain their
documented licences and attribution.
documented licences and attribution. The licence covers the code, not the name and logo: see
[TRADEMARKS.md](TRADEMARKS.md) for how to name a fork or a product built on SolidCraft.
SolidCraft is independent. Behaviour is designed from public documentation, general CAD
conventions and user feedback. Reference tests use analytic values and open-source tools.
+36
View File
@@ -0,0 +1,36 @@
# SolidCraft name and logo
The code is yours to use under MIT OR Apache-2.0 (see [NOTICE](NOTICE)). The name is not part of
that licence: "SolidCraft" and the SolidCraft logo identify this project and the builds its
maintainers publish, and Tangency Labs, which maintains SolidCraft, uses them as its trademarks.
Neither licence grants rights to them.
This page says how you can use the name. It is meant to be easy to follow: most uses are fine.
## Fine without asking
- Saying what your work is built on: "based on SolidCraft", "a fork of SolidCraft", "works with
SolidCraft", "SolidCraft plugin for …".
- Writing, teaching, reviewing or making videos about SolidCraft, including in titles.
- Redistributing unmodified official builds under the SolidCraft name, for example in a Linux
distribution or package manager.
- Using the logo to link to the project or to show that something supports SolidCraft.
- User groups, meetups and community spaces about SolidCraft, as long as they don't look official.
## Use your own name
- A fork, a modified build or a product built on SolidCraft needs its own name and logo. "SolidCraft"
may appear in its description ("based on SolidCraft"), not as its name or the main part of it.
- Don't use names or logos that could be mistaken for SolidCraft, such as "SolidCraft Pro",
"SolidKraft" or a lightly changed version of the logo.
- Don't imply that SolidCraft's maintainers made, endorse or support your product or service unless
they do.
- Don't use the name in domain names, app store listings or social media accounts in a way that
looks official.
## Questions
If you're not sure whether a use is fine, open an issue or ask on [Discord](https://discord.gg/FtU4NQNVDH).
For anything this page doesn't allow, ask first; we're generally happy to say yes.
Other companies' trademarks named in this repository are covered in [NOTICE](NOTICE).
+3
View File
@@ -27,6 +27,9 @@ error = { master = "status_error", accent = "surface" }
warning = { master = "status_warning", accent = "mesh" }
ground = "c_fix"
# Visual style: Shaded with edges is the generic style icon.
style_shaded_edges = "style"
# Same finished drawing, different semantic operation. Colours live only in palette.toml.
sketch_break = { master = "break", accent = "sketch" }
sketch_cancel = { master = "close", accent = "sketch" }
@@ -1,6 +1,8 @@
accessibility false
activate false
agent_chat false
align false
ambient_occlusion false
appearance false
arc3 false
arc_center false
@@ -83,6 +85,8 @@ decal false
delete false
delete_face false
dimension false
display false
dots false
draft false
draft_analysis false
drive false
@@ -110,7 +114,9 @@ folder false
frame_member false
gear false
graph false
grid false
ground false
ground_shadow false
help false
hem false
hole false
@@ -210,6 +216,11 @@ section false
select false
send false
settings false
settings_keyboard false
settings_monitor false
settings_mouse false
settings_palette false
settings_plug false
sheet_rules false
shell false
shield false
@@ -247,6 +258,11 @@ star false
status_error false
status_recovery false
style false
style_hidden_edges false
style_shaded false
style_shaded_edges false
style_translucent false
style_wireframe false
suppress false
surface false
surface_blend false
+15
View File
@@ -6,6 +6,7 @@
"agent_chat": "4a9ae0e7e2c360b4858b3175674c93d096705c92318fecd481e849f3ae650bf4",
"agent_link": "2f20d89a0e3e9b28744910dddf7f282a1099ccd91aa160c9841c5b1d9ea9ed0f",
"align": "05615db7dd9e4be56ae898e59a68c548b8a8447794442a9a394940651204bc4f",
"ambient_occlusion": "973f8ef2326aeaf0face576e5a2c79c7ef3d13638b2c51a5aad199e4ef7edb02",
"appearance": "b3162edd92291a5ef402e8499cd52be05beb2fa7eda641163c3f6e98325de2bf",
"arc3": "fdca3d501fd557ac989376a12e9c4fa8231fde2b455c20724d1079a466153e9c",
"arc_center": "3a5fdeb1d64fc6741f944c4435870b05fccab62293e270da692c6681155cbc51",
@@ -88,6 +89,7 @@
"dimension": "a926b7c64bc8ca99d8d6dcbb81b95235bd3fc34fbed049aca8b01b4d1147c15d",
"disclosure_closed": "49a350c6f2efae78de0be96c524ebee1fd1291ea449a84224b88d37164a4e807",
"disclosure_open": "d13ce3f97e3e362a9904fa2bf3412f3f00e4136bc23538b92d41483961d280de",
"display": "58b45e5e2230eaf2c80f74b3be2e02a23714c90d6fb03b59ed093a1949993163",
"dots": "600f7ff209d93145fc938bc4f6a1e34473e6b9ee22a5b4718f133bc7da5ee58d",
"draft": "9c0fc361cacd0ad95ccd54794f4825dfc9901a83a3de752a588faec365d0ee09",
"draft_analysis": "eb39c0f90e9cf226da6307365a76015e900dd692dc3f0fdc8f02fe717226261f",
@@ -117,7 +119,9 @@
"folder": "c19f5230df45a1bda1e92e89de38bba21c91e6eca0517eb15847a7712012d1e5",
"gear": "25a1ca48a587850da1104a46005a330873ed196246e3d04e12cf61f26ad2b0d5",
"graph": "7156caedd2dbfa2ae53da18b7a2204b8db66c45126859d36caf049a3fd4335a4",
"grid": "084b5040d57e9d5183b3db1fad0d17a13ab5bae64676eef703cc06622f9c7438",
"ground": "23e2471a9d6872e83028e0e219e330cef1930a4d89456a0fefa1bda8a7e3eb81",
"ground_shadow": "a96809ed87f5047c2d7f1274908ed7b65b180613322ac9c10eb0f9d6296c1b66",
"help": "8ce4060577483dbdb510be147d2827de50ac20029354008fca55abc0c7edf05d",
"hem": "f9b1aafbedcf3dc90c26be308814638e0095fbe31b0647092507343fa60af011",
"hole": "f82d47751f826e08682db847a270897474661bfe9f35b6d3678f49a203172563",
@@ -263,6 +267,12 @@
"screw": "5e30570785360d6a591ea22862a82f1cf62228385c1e96382536db8a453ac791",
"section": "cdd13f99f15f6d59bfa21c747810608d6afd00cb8207faf0337928c8521e7eae",
"select": "fdf6431270006ca7409c60c37cfed59572de04229f104ec723e6010ffa2b7163",
"select_bodies": "8e6e61e083e6097535da3b98d41b607b40fc81b72bbd8c7fb903618c5b35c568",
"select_components": "3e6cc847b334e92ce7ec5e5f35dfa929572e0974239790d76563ca4e20b26789",
"select_faces_edges": "7b99b5370b1647bf8cea57df7a1053caab641c2f4a94c4d797b9679e6f38d6f1",
"select_features": "b050bc19ce86d135cbe50998be681555110e92e179c4c7b101170c6b62c19943",
"select_parts": "569adc5595a64187411d8ffeea69eab3b76ddfa33aeead6fd728efdd993bcccc",
"select_sketch": "b0605b34a14d4173f7ed80d877109ec0b891a1b395bcab5743a603ed2eae240a",
"send": "f83b6cdab792f9567a81d46d7828ed20795513c57a2c7d00fbbe6bd14d2f5848",
"settings": "9193dd3a1007c43660d0d47b6499cb2571338b67949e1a99df112057b9bf2b8a",
"settings_keyboard": "4968c70788094365af9c6e2b1c15b2aac45cf21212a14b8a256daf1ffe17f41a",
@@ -309,6 +319,11 @@
"stitch": "6c3205d64007b771ed78d6f8055867578439fb25d591563b32dbd3343c98732d",
"stop": "36967eb4d423370d0d6c679b0a71f8d09f4fb2c73eed3e8cc50c604c44b0c32b",
"style": "6c2b04234b82ea4858c80190cc7208c60f549358253005afc35ab4e29506b578",
"style_hidden_edges": "a707dfc0bdcabe9144865f569abfcb478e493143cbd4331efc1404cf3082f6d2",
"style_shaded": "6e5f8f9a9030ab3717f8b2192bbfd3f6b515ad398acf6cb41bc24f1298bc73b4",
"style_shaded_edges": "6c2b04234b82ea4858c80190cc7208c60f549358253005afc35ab4e29506b578",
"style_translucent": "c46b0cd485cfb9023514908357048b5cba9017a0c4976239da1e98f50e4ab5f9",
"style_wireframe": "af7e575d378b5b6850bee9d3ca384efab95c8d4c876c5e3524f3ea771c4380a3",
"suppress": "c54fbc01c12c0175d78cd63f692e8aaf73fc2cac79752b2a3ad821ac32734343",
"surface": "ba0e839ce0ee03e7ff95a2389a5ecb20bd80c713064d9b1bd5f461f4a80d1921",
"surface_blend": "0642f3b4af7d22f379a3c74f54c7b1c9eef0bdda19372ce4df73c0e56bdd7bbc",
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Ambient occlusion</title>
<g opacity="0.22"><path d="M13 51L51 51A38 38 0 0 0 13 13Z" fill="currentColor" stroke="currentColor" stroke-width="0" stroke-linejoin="round" stroke-linecap="round"/></g>
<g opacity="0.38"><path d="M13 51L40 51A27 27 0 0 0 13 24Z" fill="currentColor" stroke="currentColor" stroke-width="0" stroke-linejoin="round" stroke-linecap="round"/></g>
<g opacity="0.62"><path d="M13 51L29 51A16 16 0 0 0 13 35Z" fill="currentColor" stroke="currentColor" stroke-width="0" stroke-linejoin="round" stroke-linecap="round"/></g>
<path d="M13 10L13 51L54 51" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 758 B

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Display</title>
<path d="M10 22L54 22M10 42L54 42" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="24" cy="22" r="10.5" fill="#ffffff"/>
<circle cx="42" cy="42" r="10.5" fill="#ffffff"/>
<circle cx="24" cy="22" r="6.4" fill="currentColor"/>
<circle cx="42" cy="42" r="6.4" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 448 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Grid</title>
<path d="M12 12L52 12L52 52L12 52Z" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M25.3 12L25.3 52M38.7 12L38.7 52M12 25.3L52 25.3M12 38.7L52 38.7" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 407 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Ground shadow</title>
<path d="M32 4.8 L48.1 13.9 L48.1 32.1 L32 41.2 L15.9 32.1 L15.9 13.9Z" fill="currentColor" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M9.34 31.35A25 11 0 1 0 54.66 31.35" fill="none" stroke="currentColor" stroke-width="5.2" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 433 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Bodies</title>
<path d="M32 6 L55 19 L55 45 L32 58 L9 45 L9 19Z" fill="currentColor" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 254 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Components</title>
<path d="M22.91 5.75 L41.09 16.25 L22.91 26.75 L4.72 16.25ZM4.72 16.25 L22.91 26.75 L22.91 47.75 L4.72 37.25ZM41.09 16.25 L59.28 26.75 L41.09 37.25 L22.91 26.75ZM22.91 26.75 L41.09 37.25 L41.09 58.25 L22.91 47.75ZM59.28 26.75 L41.09 37.25 L41.09 58.25 L59.28 47.75Z" fill="currentColor" stroke="currentColor" stroke-width="4.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M37.46 18.35L22.91 26.75L22.91 43.55" fill="none" stroke="#ffffff" stroke-width="3.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 621 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Faces and edges</title>
<path d="M32 6 L55 19 L32 32 L9 19Z" fill="currentColor" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 6 L55 19 L55 45 L32 58 L9 45 L9 19Z" fill="none" stroke="currentColor" stroke-width="4.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L9 19M32 32L55 19M32 32L32 58" fill="none" stroke="currentColor" stroke-width="3.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 554 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Features</title>
<path d="M32 6 L55 19 L55 45 L32 58 L9 45 L9 19Z" fill="none" stroke="currentColor" stroke-width="4.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M9 19L32 32M32 32L55 19M32 32L32 58" fill="none" stroke="currentColor" stroke-width="3.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M42 19C42 22.2 37.52 24.8 32 24.8C26.48 24.8 22 22.2 22 19C22 15.8 26.48 13.2 32 13.2C37.52 13.2 42 15.8 42 19Z" fill="currentColor" stroke="currentColor" stroke-width="0.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 632 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Parts</title>
<path d="M22.91 5.75 L41.09 16.25 L22.91 26.75 L4.72 16.25ZM4.72 16.25 L22.91 26.75 L22.91 47.75 L4.72 37.25Z" fill="none" stroke="currentColor" stroke-width="4.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M41.09 16.25 L59.28 26.75 L41.09 37.25 L22.91 26.75ZM22.91 26.75 L41.09 37.25 L41.09 58.25 L22.91 47.75ZM59.28 26.75 L41.09 37.25 L41.09 58.25 L59.28 47.75Z" fill="currentColor" stroke="currentColor" stroke-width="4.2" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 585 B

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Sketch features</title>
<path d="M10 46C18 14 46 14 54 46" fill="none" stroke="currentColor" stroke-width="5" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="10" cy="46" r="8.6" fill="#ffffff"/>
<circle cx="54" cy="46" r="8.6" fill="#ffffff"/>
<circle cx="32" cy="22.5" r="8.6" fill="#ffffff"/>
<circle cx="10" cy="46" r="5.8" fill="currentColor"/>
<circle cx="54" cy="46" r="5.8" fill="currentColor"/>
<circle cx="32" cy="22.5" r="5.8" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 563 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Shaded with hidden edges</title>
<path d="M32 6 L55 19 L55 45 L32 58 L9 45 L9 19Z" fill="currentColor" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L15.44 22.64M32 32L48.56 22.64M32 32L32 50.72" fill="none" stroke="#ffffff" stroke-width="3.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L32 13.28M32 32L48.56 41.36M32 32L15.44 41.36" fill="none" stroke="#ffffff" stroke-width="3.2" stroke-linejoin="round" stroke-linecap="round" stroke-dasharray="4.5 4"/>
</svg>

After

Width:  |  Height:  |  Size: 619 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Shaded</title>
<g opacity="0.5"><path d="M32 6 L55 19 L32 32 L9 19Z" fill="currentColor" stroke="currentColor" stroke-width="0.8" stroke-linejoin="round" stroke-linecap="round"/></g>
<g opacity="0.8"><path d="M9 19 L32 32 L32 58 L9 45Z" fill="currentColor" stroke="currentColor" stroke-width="0.8" stroke-linejoin="round" stroke-linecap="round"/></g>
<path d="M32 32 L55 19 L55 45 L32 58Z" fill="currentColor" stroke="currentColor" stroke-width="0.8" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 583 B

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Translucent</title>
<defs>
<clipPath id="tr-clip"><path d="M32 8.6 L52.7 20.3 L52.7 43.7 L32 55.4 L11.3 43.7 L11.3 20.3Z"/></clipPath>
</defs>
<g clip-path="url(#tr-clip)"><path d="M-71 72L9 -8M-60.5 72L19.5 -8M-50 72L30 -8M-39.5 72L40.5 -8M-29 72L51 -8M-18.5 72L61.5 -8M-8 72L72 -8M2.5 72L82.5 -8M13 72L93 -8M23.5 72L103.5 -8M34 72L114 -8M44.5 72L124.5 -8M55 72L135 -8" fill="none" stroke="currentColor" stroke-width="2.8" stroke-linejoin="round" stroke-linecap="round"/></g>
<path d="M32 6 L55 19 L55 45 L32 58 L9 45 L9 19Z" fill="none" stroke="currentColor" stroke-width="5.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L11.76 20.56M32 32L52.24 20.56M32 32L32 54.88" fill="none" stroke="#ffffff" stroke-width="6.4" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L11.3 20.3M32 32L52.7 20.3M32 32L32 55.4" fill="none" stroke="currentColor" stroke-width="3.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Wireframe</title>
<path d="M32 6 L55 19 L55 45 L32 58 L9 45 L9 19Z" fill="none" stroke="currentColor" stroke-width="5.2" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L32 6M32 32L55 19M32 32L55 45M32 32L32 58M32 32L9 45M32 32L9 19" fill="none" stroke="currentColor" stroke-width="3.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 433 B

+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(القاعدة النشطة)",
"0 turns it off": "القيمة 0 تُوقفه",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. افتح مسودة GitHub أدناه، ثم الصق التقرير المنسوخ إلى الحافظة.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. افتح مسودة GitHub أدناه. سيُملأ العنوان والتقرير تلقائيًا.",
@@ -51,16 +52,20 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "طبّق المظهر أولًا. يُصدِّر المظاهر المعيّنة والمواد المُنشأة في هذا التصميم.",
"Arc length": "طول القوس",
"Area": "المساحة",
"As Picked": "كما تم الاختيار",
"As-Built": "حسب الوضع",
"Assign Rule": "تعيين قاعدة",
"Attachment": "الارتباط",
"BLEND SURFACE": "سطح مزج",
"BOUNDARY SURFACE": "سطح حدودي",
"BROWSER": "المستعرض",
"Ball": "كروي",
"Bar": "قضيب",
"Base Center": "مركز القاعدة",
"Base Height": "ارتفاع القاعدة",
"Bend": "زاوية الثني",
"Bend Edges": "حواف الثني",
"Bend Line": "خط الثني",
"Bend Line Position": "موضع خط الثني",
"Bend Position": "موضع الثني",
"Bend Radius": "نصف قطر الثني",
@@ -72,6 +77,7 @@
"Body (last if none)": "الجسم (الأخير إن لم يُحدد)",
"Body to split": "الجسم المراد تقسيمه",
"Body, or faces to take out": "الجسم، أو الأوجه المراد إزالتها",
"Both": "كلاهما",
"Bottom Left": "أسفل اليسار",
"Bottom Middle": "أسفل الوسط",
"Bottom Right": "أسفل اليمين",
@@ -103,6 +109,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "اختر مستوى جديدًا. تبقى هندسة الرسم وأبعاده دون تغيير في إحداثياته ثنائية الأبعاد.",
"Choose…": "اختيار…",
"Circle center": "مركز الدائرة",
"Circle or sphere": "دائرة أو كرة",
"Circular": "دائري",
"Circumference": "المحيط",
"Clockwise": "باتجاه عقارب الساعة",
@@ -119,6 +126,7 @@
"Config Table": "جدول التكوين",
"Configuration": "التكوين",
"Configuration rules": "قواعد التكوين",
"Constant radius": "نصف قطر ثابت",
"Contact": "التلامس",
"Contact Sets": "مجموعات التلامس",
"Contact sets": "مجموعات التلامس",
@@ -154,7 +162,9 @@
"Custom": "مخصص",
"Customize Toolbar": "تخصيص شريط الأدوات",
"Customize…": "تخصيص…",
"Cylindrical": "أسطواني",
"Cylindrical face": "وجه أسطواني",
"Deboss": "نقش غائر",
"Delete": "حذف",
"Delete Folders and Features…": "حذف المجلدات مع ميزاتها…",
"Delete Selected Features…": "حذف الميزات المحددة…",
@@ -186,6 +196,7 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "اسحب لتدوير المسند بخطوات 5°. اضغط Alt أو Ctrl لتدويره بحرية.",
"Drive Joint": "تحريك المفصل",
"Duration": "المدة",
"Edge": "حافة",
"Edges": "الحواف",
"Edit": "تعديل",
"Edit Profile Sketch": "تعديل رسم المقطع",
@@ -194,6 +205,7 @@
"End Radius": "نصف القطر النهائي",
"End bulge": "انتفاخ النهاية",
"End continuity": "استمرارية النهاية",
"Equal Distance": "مسافة متساوية",
"Expand": "توسيع",
"Expected result (optional)": "النتيجة المتوقعة (اختياري)",
"Explode": "تفكيك",
@@ -221,6 +233,8 @@
"Faces": "الأوجه",
"Faces / edges / vertices": "الأوجه / الحواف / الرؤوس",
"Faces to split": "الأوجه المراد تقسيمها",
"Faces/Body": "الأوجه/الجسم",
"Factor must be a positive number": "يجب أن يكون المعامل عددًا موجبًا",
"Fastener": "أداة تثبيت",
"Favorites": "المفضلة",
"Favourite": "المفضلة",
@@ -230,9 +244,12 @@
"Filter…": "تصفية…",
"Find in Browser": "البحث في المستعرض",
"Finish": "إنهاء",
"First edge": "الحافة الأولى",
"First plane": "المستوى الأول",
"First point": "النقطة الأولى",
"Fit and G2 corners require Constant radius.": "الملاءمة وزوايا G2 تتطلب نصف قطر ثابتًا.",
"Fixed Face": "الوجه الثابت",
"Flange Gap": "فجوة الحافة المثنية",
"Flange thickness": "سماكة الشفة",
"Flanges": "الحواف المثنية",
"Flat Pattern": "النمط المسطح",
@@ -240,8 +257,10 @@
"Follow camera (Look At sketches)": "تتبّع الكاميرا (النظر إلى الرسومات)",
"Follow the camera (Look At sketches)": "تتبّع الكاميرا (النظر إلى الرسومات)",
"Font": "الخط",
"Free Move": "تحريك حر",
"From": "من",
"From Bodies": "من الأجسام",
"From Snap": "من نقطة الالتقاط",
"From edges": "من الحواف",
"Full Length": "الطول الكامل",
"Full thread depth": "سن لولبي بكامل العمق",
@@ -253,10 +272,13 @@
"Halo under sketch curves": "هالة أسفل منحنيات الرسم",
"Height": "الارتفاع",
"Height From": "الارتفاع من",
"Hem Gap": "فجوة ثنية الحافة",
"Hidden edges": "الحواف المخفية",
"History layout": "تخطيط السجل",
"History names": "أسماء السجل",
"Hole (optional)": "الثقب (اختياري)",
"Hole Depth": "عمق الثقب",
"Hole Diameter": "قطر الثقب",
"Holes": "الثقوب",
"Holes (edges on them)": "الثقوب (الحواف عليها)",
"Home view": "العرض الرئيسي",
@@ -279,12 +301,16 @@
"Issue title": "عنوان البلاغ",
"Items": "العناصر",
"JOINTS": "المفاصل",
"Joint 1": "المفصل 1",
"Joint 2": "المفصل 2",
"Joint Origin1": "أصل المفصل 1",
"K Factor": "معامل K",
"Keep (points on it)": "الإبقاء (النقاط عليه)",
"Keep Tools": "الإبقاء على الأدوات",
"Keep of the other surface": "الإبقاء على جزء من السطح الآخر",
"Key a joint's value at this step": "تثبيت قيمة مفصل عند هذه الخطوة",
"Keys": "المفاتيح",
"Knife Edge": "حافة حادة",
"L-Angle": "زاوية L",
"LIBRARY": "المكتبة",
"LINKS": "الروابط",
@@ -297,9 +323,11 @@
"Letter Spacing": "تباعد الأحرف",
"Library": "المكتبة",
"Library file": "ملف المكتبة",
"Library response is missing": "استجابة المكتبة مفقودة",
"Limits": "الحدود",
"Line Spacing": "تباعد الأسطر",
"Line Type": "نوع الخط",
"Line on plane": "خط على مستوى",
"Lines": "الخطوط",
"Listing the installed fonts…": "جارٍ سرد الخطوط المثبتة…",
"Load library": "تحميل مكتبة",
@@ -319,11 +347,14 @@
"Material Outside": "المادة للخارج",
"Material copied. Existing body assignments are unchanged.": "نُسخت المادة. تعيينات الأجسام الحالية لم تتغير.",
"Max": "الأقصى",
"Max Thickness": "أقصى سماكة",
"Maximum": "الحد الأقصى",
"Mesh body": "جسم شبكي",
"Mid Radius": "نصف القطر الأوسط",
"Middle double-click": "النقر المزدوج بالزر الأوسط",
"Min": "الأدنى",
"Min Draft": "أدنى ميل سحب",
"Min Thickness": "أدنى سماكة",
"Minimum": "الحد الأدنى",
"Mirror Plane": "مستوى المرآة",
"Mitre": "تقاطع مائل",
@@ -343,6 +374,7 @@
"Name": "الاسم",
"Name on import": "الاسم عند الاستيراد",
"Nearest": "الأقرب",
"Neutral plane": "المستوى المحايد",
"New": "جديد",
"New Comp.": "مكوّن جديد",
"New Sketch": "رسم جديد",
@@ -353,6 +385,7 @@
"No matching appearances": "لا توجد مظاهر مطابقة",
"No matching physical materials.": "لا توجد مواد فيزيائية مطابقة.",
"No visible bodies or sketches to export.": "لا توجد أجسام أو رسومات ظاهرة للتصدير.",
"Nominal Radius": "نصف القطر الاسمي",
"Nominal diameter": "القطر الاسمي",
"None": "لا شيء",
"Not available yet": "غير متاح بعد",
@@ -381,22 +414,28 @@
"Overall length": "الطول الكلي",
"Param. Graph": "مخطط المعاملات",
"Parameter": "المعامل",
"Part length must be greater than zero and at most 2000 mm": "يجب أن يكون طول القطعة أكبر من صفر وألا يزيد على 2000 mm",
"Parts": "القطع",
"Pass through": "المرور عبر",
"Path": "المسار",
"Pattern": "نمط",
"Per Edge": "لكل حافة",
"Physical material definitions": "تعريفات المواد الفيزيائية",
"Pick a part size": "اختر مقاسًا للقطعة",
"Pick the tool bodies": "اختر أجسام الأدوات",
"Picked": "مُختار",
"Picked point": "النقطة المختارة",
"Pin-slot": "مسمار-شق",
"Pitch": "الخطوة",
"Pivot": "نقطة الارتكاز",
"Place at the origin instead": "الوضع عند نقطة الأصل بدلًا من ذلك",
"Planar": "مستوٍ",
"Plastic Rules": "قواعد البلاستيك",
"Play the joint's motion in the view": "تشغيل حركة المفصل في العرض",
"Playback": "التشغيل",
"Plot": "رسم بياني",
"Point on line": "نقطة على خط",
"Point on plane": "نقطة على مستوى",
"Position": "الموضع",
"Position (0 to 1)": "الموضع (من 0 إلى 1)",
"Position (G0)": "الموضع (G0)",
@@ -409,6 +448,7 @@
"Profiles or curves": "المقاطع أو المنحنيات",
"Profiles/Curves": "المقاطع/المنحنيات",
"Quantity": "الكمية",
"Quantity must be at least 2": "يجب ألا تقل الكمية عن 2",
"RECENT": "الأخيرة",
"REFERENCE": "مرجع",
"RULED SURFACE": "سطح مسطّر",
@@ -422,6 +462,8 @@
"Rectangular": "مستطيلي",
"Rectangular Tube": "أنبوب مستطيل",
"Reference face": "الوجه المرجعي",
"Relief Depth": "عمق التفريغ",
"Relief Width": "عرض التفريغ",
"Remove Tools": "إزالة الأدوات",
"Remove condition": "إزالة الشرط",
"Remove from Folder": "إزالة من المجلد",
@@ -450,6 +492,7 @@
"Restore this studio's tools": "استعادة أدوات هذه البيئة",
"Result": "النتيجة",
"Retake screenshot": "إعادة التقاط الشاشة",
"Reveal Height": "ارتفاع الدرجة",
"Reverse": "عكس",
"Reverse Direction": "عكس الاتجاه",
"Revert": "تراجع عن التغيير",
@@ -458,12 +501,15 @@
"Revert Position": "إرجاع الموضع",
"Review the report and screenshot before opening GitHub.": "راجع التقرير ولقطة الشاشة قبل فتح GitHub.",
"Review your report on GitHub and click Submit new issue to publish it.": "راجع بلاغك في GitHub وانقر Submit new issue لنشره.",
"Revolute": "دوراني",
"Rib Length": "طول الضلع",
"Rib Offset": "إزاحة الضلع",
"Rib Thickness": "سماكة الضلع",
"Ribs": "أضلاع التقوية",
"Right Middle": "وسط اليمين",
"Rigid": "صلب",
"Rim Edge": "حافة الإطار",
"Rim face": "وجه الحافة",
"Ring of tools on the right button": "حلقة أدوات على الزر الأيمن",
"Roll Back Here": "نقل مؤشر الخط الزمني إلى هنا",
"Roll History Marker Here": "نقل مؤشر السجل إلى هنا",
@@ -488,16 +534,28 @@
"Search": "بحث",
"Search commands": "البحث في الأوامر",
"Search this library": "البحث في هذه المكتبة",
"Second edge": "الحافة الثانية",
"Second plane": "المستوى الثاني",
"Second point": "النقطة الثانية",
"Section": "مقطع",
"Section (optional)": "المقطع (اختياري)",
"Section position": "موضع المقطع",
"Sections (one sketch each)": "المقاطع (رسم واحد لكل منها)",
"Select Other": "تحديد آخر",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "تحديد آخر: أبقِ الزر الأيسر ثابتًا على النموذج (أو انقر بالزر الأيمن › تحديد آخر…) لعرض كل ما تحت المؤشر؛ وانقر مرة أخرى في الموضع نفسه لتحديد العنصر التالي هناك. انقر نقرًا مزدوجًا بالزر الأوسط للانتقال إلى العرض الرئيسي (التفضيلات › التنقل).",
"Select Same Look": "تحديد المظهر نفسه",
"Select bodies (a face picks its body)": "حدد الأجسام (الوجه يحدد جسمه)",
"Select bodies or faces instead": "حدد أجسامًا أو أوجهًا بدلًا من ذلك",
"Select edges": "حدد الحواف",
"Select points of the sketch being edited": "حدد نقاطًا من الرسم الجاري تعديله",
"Select the centre the pattern turns around first": "حدد أولًا المركز الذي يدور النمط حوله",
"Select the curves to offset first": "حدد أولًا المنحنيات المراد إزاحتها",
"Select the mirror line": "حدد خط المرآة",
"Select the sketch curves or points to mirror first": "حدد أولًا منحنيات الرسم أو النقاط المراد عكسها",
"Select the sketch curves or points to move first": "حدد أولًا منحنيات الرسم أو النقاط المراد تحريكها",
"Select the sketch curves or points to pattern first": "حدد أولًا منحنيات الرسم أو النقاط المراد تكرارها في نمط",
"Select the sketch curves or points to scale first": "حدد أولًا منحنيات الرسم أو النقاط المراد تحجيمها",
"Select the sketch curves or points to transform first": "حدد أولًا منحنيات الرسم أو النقاط المراد تحويلها",
"Selection filter": "مرشّح التحديد",
"Semantic faces share their appearance across instances.": "الأوجه الدلالية تتشارك مظهرها بين النسخ.",
"Send your report on GitHub": "أرسل تقريرك عبر GitHub",
@@ -517,9 +575,12 @@
"Sketch geometry and profiles": "هندسة الرسم ومقاطعه",
"Sketch plane has no body-face attachment.": "مستوى الرسم غير مرتبط بوجه جسم.",
"Sketch points": "نقاط الرسم",
"Slider": "منزلق",
"Slot width": "عرض الشق",
"Snap to face and edge centres": "الالتقاط إلى مراكز الأوجه والحواف",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "أُغلق SolidCraft قبل حفظ هذه التصاميم. يمكن فتح آخر حفظ تلقائي لها.",
"Spacing 2 must be a non-zero number": "يجب أن يكون التباعد 2 عددًا غير صفري",
"Spacing must be a non-zero number": "يجب أن يكون التباعد عددًا غير صفري",
"Specialise": "تخصيص",
"Speed": "السرعة",
"Splitting tool": "أداة التقسيم",
@@ -530,6 +591,7 @@
"Start angle": "زاوية البداية",
"Start bulge": "انتفاخ البداية",
"Start continuity": "استمرارية البداية",
"Stationary Side": "الجانب الثابت",
"Step": "الخطوة",
"Steps": "الخطوات",
"Steps to reproduce (optional)": "خطوات إعادة المشكلة (اختياري)",
@@ -544,6 +606,7 @@
"Suppressed": "مُعطّل",
"Surface": "السطح",
"Surface, or faces to turn over": "السطح، أو الأوجه المراد قلبها",
"Surfaces": "الأسطح",
"Swap Ends": "تبديل الطرفين",
"TRIM": "قص",
"Tangent": "مماس",
@@ -554,24 +617,34 @@
"Tap drill diameter": "قطر ثقب التسنين",
"Target": "الهدف",
"Target Body": "الجسم الهدف",
"Target Face (optional)": "الوجه الهدف (اختياري)",
"Tear": "تمزيق",
"Technical details": "التفاصيل التقنية",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "الرسم المتقطع دليل مستوى محفوظ. حدد وجهًا جديدًا لإصلاح الارتباط.",
"The design changed. Reopen Change Part Size for the component.": "تغيّر التصميم. أعد فتح تغيير مقاس القطعة للمكوّن.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "يجب أن يكون الاتجاه محورًا أو منحنى رسم مستقيمًا يقع في مستوى الرسم",
"The mirror line cannot also be mirrored": "لا يمكن عكس خط المرآة نفسه",
"The mirror line must be a straight curve of this sketch, not an origin axis": "يجب أن يكون خط المرآة منحنى مستقيمًا من هذا الرسم، وليس أحد محاور نقطة الأصل",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "نسخة المؤلف المحفوظة مفقودة. حدد موضع مؤلف صالحًا قبل إعادة الربط.",
"Then": "ثم",
"These features will be deleted:": "ستُحذف هذه الميزات:",
"These features will fail:": "ستفشل هذه الميزات:",
"Thickness Outside": "السماكة للخارج",
"Thickness Variation": "تفاوت السماكة",
"Thin": "رقيق",
"Thin Extrude": "بثق رقيق",
"Third plane": "المستوى الثالث",
"Third point": "النقطة الثالثة",
"This child is shared. Deleting it removes it from every copy of its parent.": "هذا العنصر الفرعي مشترك. حذفه يزيله من كل نسخة من العنصر الأب.",
"This child is shared. Position changes apply to every copy of its parent.": "هذا العنصر الفرعي مشترك. تغييرات الموضع تنطبق على كل نسخة من العنصر الأب.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "لا يمكن لهذا الوجه توفير ارتباط دائم. اختر وجهًا آخر أو استخدم مستوى ثابتًا صراحةً.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "هذه الصورة غير مرفقة في GitHub بعد. انسخها أو احفظها، ثم أرفقها في GitHub.",
"Thread depth": "عمق السن اللولبي",
"Thread diameter": "قطر السن اللولبي",
"Through point": "عبر نقطة",
"To": "إلى",
"To Offset": "إلى الإزاحة",
"To Snap": "إلى نقطة الالتقاط",
"To edges": "إلى الحواف",
"Toe radius": "نصف قطر الطرف",
"Tolerance": "التفاوت",
@@ -585,6 +658,7 @@
"Trimming tool (plane, face or curves)": "أداة القص (مستوى أو وجه أو منحنيات)",
"Turn off section analysis before exporting the view.": "أوقف تحليل المقطع قبل تصدير العرض.",
"Type": "النوع",
"Type a distance or an angle to move by": "اكتب مسافة أو زاوية للتحريك بها",
"UNTRIM": "إلغاء القص",
"Unit": "الوحدة",
"Unsuppress": "إلغاء التعطيل",
@@ -629,6 +703,17 @@
"Z angle": "زاوية Z",
"Z distance": "مسافة Z",
"Zebra": "زيبرا",
"`joint` must be an id or a name": "يجب أن يكون `joint` معرّفًا أو اسمًا",
"`params` must be an object": "يجب أن يكون `params` كائنًا",
"`values` must be a list": "يجب أن يكون `values` قائمة",
"a chamfer needs a corner of exactly two lines": "يحتاج الشطف إلى زاوية من خطين اثنين بالضبط",
"a file operation is in progress": "عملية ملف قيد التنفيذ",
"a picked curve is no longer in a sketch": "لم يعد المنحنى المحدد ضمن أي رسم",
"a picked curve's sketch has not been solved": "لم يُحَل رسم المنحنى المحدد بعد",
"a picked edge has no points": "لا تحتوي الحافة المحددة على نقاط",
"a picked edge is gone": "الحافة المحددة لم تعد موجودة",
"a picked edge's body is gone": "جسم الحافة المحددة لم يعد موجودًا",
"add a key for a joint first": "أضف أولًا مفتاحًا لمفصل",
"ai.connected_toast": "أصبح SolidCraft متاحًا في {clients}. أعد تشغيلها لاستخدامه (الإعدادات > المساعد).",
"ai.prefs.allow_control": "السماح لوكلاء الذكاء الاصطناعي بالاتصال (قناة التحكم / MCP)",
"ai.prefs.allow_control_note": "يفتح قناة تحكم على هذا الحاسوب فقط (127.0.0.1، المنفذ 27878 أو أول منفذ متاح بعده). على البرنامج الذي يتصل أن يقدّم أيضًا رمزًا سريًا لا يقرؤه إلا حساب المستخدم الخاص بك، ويُنشأ من جديد عند كل تشغيل. يُطبّق في المرة القادمة التي يبدأ فيها SolidCraft. عند الإيقاف: لا شيء يستمع ما لم تشغّل SolidCraft مع --control.",
@@ -669,6 +754,7 @@
"appearance.pbr_opaque": "PBR معتم",
"appearance.roughness": "الخشونة",
"appearance.surface_response": "استجابة السطح",
"bom.group_children": "الأجزاء الفرعية في صف الجزء الأصلي",
"browser.body_name": "جسم {number}",
"browser.calibrate_title": "معايرة: {name}",
"browser.capture_many": "تم تحريك {count} مكوّنات دون تثبيت مواضعها.",
@@ -679,6 +765,8 @@
"browser.move_title": "تحريك: {name}",
"browser.parameters": "المعاملات ({count})",
"browser.precision": "الدقة: {precision}",
"browser.sketch_attachment_lost": "{name} (فُقد الارتباط)",
"browser.sketch_editing": "{name} (قيد التحرير)",
"browser.sketch_name": "رسم {number}",
"browser.units": "الوحدات: {units}",
"cam.flat": "وجه مسطح",
@@ -688,7 +776,13 @@
"cam.roller": "بكرة",
"cam.roller_pick": "بكرة (اختياري)",
"cam.tip_pick": "الطرف (اختياري)",
"choose a profile": "اختر مقطعًا",
"choose the cam's and the follower's joints": "اختر مفصلَي الكامة والتابع",
"choose the joints to couple": "اختر المفاصل المراد ربطها",
"click a plane or planar face": "انقر على مستوى أو وجه مستوٍ",
"click sketch curves": "انقر على منحنيات الرسم",
"cmd.appearance_assign": "المظهر",
"cmd.appearance_chain": "سلسلة المظهر",
"cmd.appearance_library": "مكتبة المظاهر",
"cmd.appearance_list": "قائمة المظاهر",
"cmd.appearance_paint": "تلوين المظهر",
@@ -1073,6 +1167,9 @@
"cmd.timeline_roll_to": "نقل مؤشر السجل",
"cmd.timeline_rollback": "نقل مؤشر الخط الزمني",
"cmd.timeline_suppress": "تعطيل الميزة",
"cmd.view.render_browser": "متصفح التصيير",
"cmd.view.render_dock": "نقل لوحة التصيير",
"cmd.view.render_focus": "عرض تركيز التصيير",
"cmd.view_ambient_occlusion": "الإظلال المحيطي",
"cmd.view_apply": "استعادة عرض مسمّى",
"cmd.view_back": "العرض الخلفي",
@@ -1183,6 +1280,8 @@
"dxf.progress.write": "كتابة DXF (5/5)",
"dxf.tolerance": "تفاوت المنحنى",
"dxf.tolerance_help": "الأجسام الظاهرة فقط. المنحنيات تُمثَّل بقطع مستقيمة. التفاوت الأصغر يعطي منحنيات أنعم ويستهلك وقتًا وذاكرة أكثر.",
"each rail's curves must be in one sketch": "يجب أن تكون منحنيات كل دليل في رسم واحد",
"feature computation ended without a result": "انتهى حساب الميزة دون نتيجة",
"file.open.drawing_filter": "التصاميم وملفات CAD والشبكات والرسومات",
"file_load.built": "بُني حتى الآن: {built} من {total} ميزة.",
"file_load.converting": "تحويل الجسم الصلب {done} من {total}",
@@ -1344,6 +1443,8 @@
"keymap.command_id": "معرّف الأمر",
"keymap.empty": "لا توجد أوامر مطابقة",
"keymap.use_anyway": "استخدام {key} هنا على أي حال",
"label.move_to_left_side": "نقل إلى الجانب الأيسر",
"label.move_to_right_side": "نقل إلى الجانب الأيمن",
"manage.appearance_hint": "اختر مظهرًا للتحديد، أو اسحب عيّنة إلى جسم أو وجه.",
"manage.assign_hint": "حدد الأجسام واختر قاعدة تصميم البلاستيك لها.",
"manage.config_hint": "عدّل صفوف التكوين وأعمدته وقواعده، ثم نشّط صفًا أو عاينه.",
@@ -1428,7 +1529,9 @@
"nav.free_orbit_upright.help": "سحب الفأرة جانبيًا يدوّر النموذج حول المحور الرأسي للعالم؛ والسحب لأعلى ولأسفل يميله فوق القمة دون حد.",
"nav.free_orbit_upright.label": "الدوران حول المحور الرأسي",
"nav.fusion.help": "السحب بالزر الأوسط يُزيح العرض، وShift مع الأوسط يدوّره، والسحب بالأيمن يدوّره",
"nav.hfss.help": "Alt مع السحب بالزر الأيسر يُزيح العرض، وShift+Alt مع الأيسر يكبّره، وCtrl مع السحب بالأيسر من مساحة فارغة يدوّره",
"nav.inventor.help": "السحب بالزر الأوسط يُزيح العرض، وShift مع الأوسط يدوّره، وCtrl مع الأوسط يكبّره، والسحب بالأيمن يدوّره",
"nav.maya.help": "Alt مع السحب بالزر الأيسر يدوّر العرض، وAlt مع الأوسط يُزيحه، وAlt مع الأيمن يكبّره؛ والسحب بالزر الأوسط يُزيح أيضًا",
"nav.openscad.help": "السحب بالزر الأيسر على مساحة فارغة يدوّر العرض، وShift مع السحب بالأيسر يحدد بمربع، وسحب هندسة الرسم يعدّلها؛ والسحب بالأيمن أو الأوسط يُزيح، وShift مع السحب بالأيمن أو الأوسط يكبّر",
"nav.perspective.sketch": "تحرير الرسم يستخدم العرض المتعامد. أنهِ الرسم للتبديل إلى المنظور.",
"nav.solidworks.help": "السحب بالزر الأوسط يدوّر العرض، وCtrl مع الأوسط يُزيحه، وShift مع الأوسط يكبّره، والسحب بالأيمن يدوّره",
@@ -1439,6 +1542,93 @@
"nav.touchpad.pan": "الإزاحة (اضغط Shift وحرّك؛ بدون زر فأرة)",
"nav.touchpad.scroll": "تستخدم لوحة اللمس التمرير العمودي للتكبير. يُحتفظ بإعداد الإزاحة بإصبعين للإعدادات الأخرى.",
"nav.touchpad.zoom": "التكبير (تمرير عمودي أو قرص)",
"navbar.agent_chat": "لوحة دردشة المساعد",
"navbar.agent_cursor": "إظهار مؤشر الوكيل",
"navbar.ambient_occlusion": "الإظلال المحيطي",
"navbar.assistant": "المساعد",
"navbar.custom.add_slot": "إضافة {slot}",
"navbar.custom.always": "ظاهر دائماً",
"navbar.custom.available": "{available} · اسحبها إلى الشريط، أو اضغط إضافة",
"navbar.custom.buttons": "الأزرار",
"navbar.custom.compact": "مضغوط",
"navbar.custom.count": "{count} من 16 خانة",
"navbar.custom.customise": "تخصيص شريط التنقل…",
"navbar.custom.design": "التصميم",
"navbar.custom.duplicate": "هذه الخانة موجودة بالفعل على الشريط.",
"navbar.custom.fade": "تلاشٍ",
"navbar.custom.full": "أزل خانة لإضافة أخرى.",
"navbar.custom.hidden_design": "مخفي في التصميم",
"navbar.custom.hidden_render": "مخفي في التصيير",
"navbar.custom.hide": "إخفاء شريط التنقل",
"navbar.custom.hide_idle": "إخفاء حتى التمرير",
"navbar.custom.icon_only": "الأيقونة فقط",
"navbar.custom.icon_value": "الأيقونة والقيمة",
"navbar.custom.icons": "الأيقونات",
"navbar.custom.idle": "عند الخمول",
"navbar.custom.intro": "اختر عناصر التحكم على الشريط أسفل العرض ثلاثي الأبعاد وترتيبها. اسحب خانة لنقلها، أو اسحبها خارج الشريط لإزالتها.",
"navbar.custom.labels": "الأيقونات والتسميات",
"navbar.custom.left": "نقل إلى اليسار",
"navbar.custom.position": "الموضع",
"navbar.custom.position_centre": "وسط",
"navbar.custom.position_left": "يسار",
"navbar.custom.position_right": "يمين",
"navbar.custom.preview_as": "معاينة كـ",
"navbar.custom.regular": "عادي",
"navbar.custom.remove": "إزالة",
"navbar.custom.remove_bar": "إزالة من الشريط",
"navbar.custom.render": "التصيير",
"navbar.custom.reset": "إعادة ضبط شريط التنقل",
"navbar.custom.reset_default": "إعادة الضبط إلى الافتراضي",
"navbar.custom.right": "نقل إلى اليمين",
"navbar.custom.select": "لم يتم تحديد أي خانة. حدّد خانة على الشريط لنقلها أو إزالتها أو تغيير مظهرها.",
"navbar.custom.separators_full": "يحتوي الشريط بالفعل على أربعة فواصل.",
"navbar.custom.show": "إظهار شريط التنقل",
"navbar.custom.shows": "يعرض",
"navbar.custom.size": "الحجم",
"navbar.custom.stale": "تغيّر الشريط. حدّد الخانة مرة أخرى.",
"navbar.custom.title": "شريط التنقل",
"navbar.custom.unknown": "هذه الخانة غير متاحة.",
"navbar.description.ambient_occlusion": "يُعتّم الطيات والزوايا لإضافة عمق.",
"navbar.description.display": "يضم إعدادات العرض: الإعداد المسبق للرسوميات والشبكة وظل الأرض والإظلال المحيطي والإسقاط.",
"navbar.description.fit": "يضبط العرض على التحديد، أو على النموذج كله إن لم يكن هناك تحديد.",
"navbar.description.grid": "يُظهر شبكة الأرضية أو يُخفيها.",
"navbar.description.ground_shadow": "يُظهر الظل تحت النموذج أو يُخفيه.",
"navbar.description.home": "يعود إلى المنظور الأيزومتري للنموذج كله.",
"navbar.description.look_at": "يوجّه العرض نحو الوجه أو المستوى المحدد أو الرسم المفتوح.",
"navbar.description.orbit": "يدير العرض حول النموذج.",
"navbar.description.pan": "يزيح العرض جانبياً أو لأعلى أو لأسفل.",
"navbar.description.projection": "يبدّل بين العرض المتعامد والمنظوري.",
"navbar.description.separator": "خط رفيع يجمع الخانات المتجاورة.",
"navbar.description.spin": "يُبقي العرض يدور حتى تنقر أو تضغط مفتاحاً.",
"navbar.description.visual_style": "يبدّل طريقة رسم النموذج: مظلل أو إطار سلكي أو مع الحواف المخفية.",
"navbar.description.zoom": "يقرّب العرض من النموذج أو يبعده عنه.",
"navbar.display": "العرض",
"navbar.fit": "ملاءمة",
"navbar.graphics": "الرسوميات",
"navbar.grid": "الشبكة",
"navbar.ground_shadow": "ظل الأرض",
"navbar.home": "الرئيسية",
"navbar.later": "لاحقاً",
"navbar.look_at": "النظر إلى",
"navbar.more": "المزيد",
"navbar.orbit": "تدوير العرض",
"navbar.orthographic": "إسقاط متعامد",
"navbar.pan": "إزاحة العرض",
"navbar.perspective": "منظور",
"navbar.preset": "الإعداد المسبق",
"navbar.projection": "الإسقاط",
"navbar.projection_heading": "الإسقاط",
"navbar.separator": "فاصل",
"navbar.show": "إظهار",
"navbar.spin": "دوران مستمر",
"navbar.style.shaded": "مظلل",
"navbar.style.shaded_with_edges": "مظلل مع الحواف",
"navbar.style.shaded_with_hidden_edges": "مظلل مع الحواف المخفية",
"navbar.style.wireframe": "إطار سلكي",
"navbar.translucent": "شفاف",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "نمط العرض",
"navbar.zoom": "تكبير",
"needs two joints": "يحتاج إلى مفصلين",
"network.allow_once": "السماح مرة واحدة",
"network.always_allow": "السماح لهذا الخادم دائمًا",
@@ -1449,9 +1639,34 @@
"no hole": "لا يوجد ثقب",
"no interference": "لا يوجد تداخل",
"no joint that moves yet": "لا يوجد مفصل يتحرك بعد",
"no motion study yet": "لا توجد دراسة حركة بعد",
"no picture": "لا توجد صورة",
"no such joint": "لا يوجد مفصل بهذا الاسم",
"none": "لا شيء",
"not a move": "ليس تحريكًا",
"not a number": "ليس عددًا",
"open a sketch first": "افتح رسمًا أولًا",
"parts.automatic_name": "تلقائي",
"parts.dimension.across_flats": "مقاس المفتاح",
"parts.dimension.bore": "قطر الثقب",
"parts.dimension.d": "القطر الاسمي",
"parts.dimension.head_diameter": "قطر الرأس",
"parts.dimension.head_height": "ارتفاع الرأس",
"parts.dimension.height": "الارتفاع",
"parts.dimension.inner": "القطر الداخلي",
"parts.dimension.outer": "القطر الخارجي",
"parts.dimension.pitch": "الخطوة",
"parts.dimension.socket": "مقاس السداسي",
"parts.dimension.socket_depth": "عمق السداسي",
"parts.dimension.thickness": "السماكة",
"parts.dimension.width": "العرض",
"parts.family.bearing": "محمل كريات أخدودي عميق (الغلاف)",
"parts.family.dowel_pin": "مسمار توجيه أسطواني",
"parts.family.hex_bolt": "برغي سداسي الرأس",
"parts.family.hex_nut": "صامولة سداسية",
"parts.family.set_screw": "برغي تثبيت بتجويف سداسي، طرف مسطح",
"parts.family.socket_head_cap_screw": "برغي برأس أسطواني بتجويف سداسي",
"parts.family.washer": "حلقة مسطحة",
"pattern.alignment_2": "المحاذاة 2",
"pattern.alignment_hint": "العدد يشمل الأصل. «توسيط» يوازن النسخ؛ و«قلب» يختار الجانب الإضافي عندما يكون العدد زوجيًا.",
"pattern.direction_1": "الاتجاه 1",
@@ -1467,9 +1682,25 @@
"perf.ui_time": "زمن الواجهة",
"perf.viewport": "منطقة العرض",
"perf.worst": "الأسوأ",
"pick a body or some of its faces": "حدد جسمًا أو بعض أوجهه",
"pick a hole to seat it, or OK places it at the origin": "اختر ثقبًا لتثبيته فيه، أو اضغط موافق لوضعه عند نقطة الأصل",
"pick a planar face": "حدد وجهًا مستويًا",
"pick a plane or a face as the tool": "حدد مستوى أو وجهًا ليكون الأداة",
"pick a size": "اختر مقاسًا",
"pick edges of a body": "حدد حوافّ جسم",
"pick edges of one body": "حدد حوافّ جسم واحد",
"pick edges of the holes to remove": "حدد حواف الثقوب المراد إزالتها",
"pick faces of one body": "حدد أوجه جسم واحد",
"pick faces to offset": "حدد الأوجه المراد إزاحتها",
"pick lines of one sketch": "حدد خطوطًا من رسم واحد",
"pick one or two vertices, edges or faces": "اختر رأسًا أو اثنين، أو حافة، أو وجهًا",
"pick one plane or face as the tool, or sketch curves": "حدد مستوى واحدًا أو وجهًا واحدًا ليكون الأداة، أو منحنيات رسم",
"pick sections in two or more sketches": "حدد مقاطع في رسمين أو أكثر",
"pick sketch curves or edges": "حدد منحنيات رسم أو حوافّ",
"pick the face to untrim": "حدد الوجه المراد إلغاء قصه",
"pick the path": "اختر المسار",
"pick what to keep": "حدد ما تريد الإبقاء عليه",
"pick what to keep of the other surface": "حدد ما تريد الإبقاء عليه من السطح الآخر",
"prefs.add_item": "إضافة العنصر",
"prefs.alt_frees_manipulators": "Alt / Option يحرر أسهم أدوات التحريك أيضًا",
"prefs.anti_aliasing_amd_dx12": "يستخدم تنعيم الحواف 1× لأن فحص بدء التشغيل لم يرسم شيئًا مع أخذ العينات المتعددة ونجح عند 1×. يمكنك اختيار إعداد آخر أعلاه؛ أعد التشغيل لتطبيقه إن نجح الفحص.",
@@ -1837,6 +2068,64 @@
"render.effects_help": "اجمع مظاهر لونية مرتبة وتأثيرات عدسة في فضاء الصورة. يستخدم التصيير وإعادة تدريج النسخة الخام الإعدادات المحفوظة نفسها. يبقى EXR الخام دون تغيير. هذه عناصر تحكم فنية أصلية، لا محاكاة معايَرة لعدسات أو لأفلام تجارية.",
"render.effects_reset_lens": "إعادة ضبط تأثيرات العدسة",
"render.effects_seed": "بذرة النمط",
"render.emitted_axis": "المحور المنبعث",
"render.error_area_samples": "يجب أن تكون area_samples 1 أو 4 أو 16 أو 64",
"render.error_binding_allocation": "تعذّر حجز ربط المادة",
"render.error_body_bound": "معاينة المنتج تتجاوز حد الأجسام الملتقطة",
"render.error_checkpoint_dimensions": "أبعاد نقطة الحفظ تختلف عن الطلب الملتقط",
"render.error_decode_budget": "فيض في ميزانية فك ترميز الصورة",
"render.error_denoise_setting": "إعداد إزالة ضجيج أصلي غير صالح",
"render.error_display_dimensions": "أبعاد عرض الصورة غير صالحة",
"render.error_display_fit": "لا يمكن لعرض الصورة أن يلائم هذا الجهاز",
"render.error_display_height": "فيض في ارتفاع العرض",
"render.error_display_width": "فيض في عرض العرض",
"render.error_duplicate_face": "مظهر وجه منتج مكرر",
"render.error_export_document": "تغيّرت وثيقة تصدير التصيير أثناء اختيار وجهتها",
"render.error_face_cap": "معاينة المنتج تتجاوز سقف قبول مظاهر الوجوه",
"render.error_finish_gesture": "أنهِ إيماءة النمذجة قبل المعاينة",
"render.error_finish_operation": "أنهِ عملية النمذجة الحالية قبل الدخول إلى التصيير",
"render.error_fixed_preview": "معاينة الاستوديو الثابت تتطلب تعريضًا 0 وتدوير بيئة 0 وشدة 1",
"render.error_geometry_size": "فيض في حجم هندسة المنتج",
"render.error_glass_recipe": "وصفة زجاج غير معروفة",
"render.error_gpu_preview": "معاينة المنتج على GPU غير متاحة على هذا المضيف. تبقى الإعدادات المحفوظة متاحة.",
"render.error_gpu_samples": "عدد عينات GPU غير مدعوم",
"render.error_image_dimensions": "أبعاد صورة التصيير لا تطابق مهمتها",
"render.error_image_profile": "صورة التصيير تتجاوز ملف الموارد الملتقط",
"render.error_interactive_command": "أمر تصيير تفاعلي غير مربوط",
"render.error_job_action": "ليس إجراء مهمة صورة تفاعليًا",
"render.error_job_identity": "هوية مهمة التصيير غير صالحة: {error}",
"render.error_library_reply": "استجابة مكتبة التصيير غير صالحة",
"render.error_material_binding": "ربط المادة مفقود",
"render.error_no_completed_image": "لا توجد صورة مكتملة للتصيير",
"render.error_no_geometry": "لا توجد هندسة منتج",
"render.error_no_scene": "لا يوجد مشهد منتج",
"render.error_opacity": "عتامة مظهر المنتج غير صالحة",
"render.error_pbr_opacity": "PBR المعتم يتطلب عتامة 1",
"render.error_physical_glass": "الوصفة المحددة ليست زجاجًا فيزيائيًا",
"render.error_preview_device": "معاينة المنتج تتطلب جهازًا مثبّتًا بمخزن عمق",
"render.error_product_triangle": "مثلث منتج غير صالح",
"render.error_provisional_identity": "هوية تصيير مؤقتة أو عدد عينات غير صالح",
"render.error_quality_bounds": "إسقاط الجودة يتجاوز الحدود الأصلية",
"render.error_quality_method": "إسقاط الجودة يتطلب طريقة GPU صريحة نفسها",
"render.error_quality_projection": "إسقاط جودة أصلي غير صالح",
"render.error_regrade_identity": "هوية إعادة التدرّج غير صالحة: {error}",
"render.error_scene_bodies": "أجسام مشهد التصيير مفقودة",
"render.error_scene_body_limit": "مشهد التصيير يتجاوز حد الأجسام",
"render.error_scene_identity": "هوية مشهد التصيير غير صالحة",
"render.error_setup_panicked": "حدث ذعر في إعداد متتبع المسار على بطاقة الرسومات",
"render.error_setup_stopped": "توقف عامل الإعداد دون إرجاع مضيف",
"render.error_setup_worker": "تعذّر بدء عامل الإعداد: {error}",
"render.error_source_preview": "معاينة المصدر تتجاوز غلاف البايتات",
"render.error_surface_normals": "PBR يتطلب متجهات عادية غير صفرية للسطح",
"render.error_surface_reply": "استجابة السطح المؤلَّف غير صالحة",
"render.error_triangle_bound": "معاينة المنتج تتجاوز حد المصدر البالغ ثمانية ملايين مثلث",
"render.error_triangle_count": "فيض في عدد مثلثات المنتج",
"render.error_upload_slot": "خانة رفع معاينة المنتج غير متاحة",
"render.error_vertex_allocation": "فشل تخصيص رؤوس معاينة المنتج",
"render.error_vertex_envelope": "معاينة المنتج تتجاوز غلاف حمولة الرؤوس البالغ {limit} ميبي بايت؛ لم تُبسَّط الهندسة",
"render.error_vertex_packing": "تغليف معاينة المنتج يختلف عن حمولة الرؤوس المقبولة",
"render.error_visible_solid": "أنشئ جسمًا مصمتًا مرئيًا في التصميم لمعاينته هنا.",
"render.exit_focus": "الخروج من التركيز",
"render.export_display": "تصدير: PNG للعرض",
"render.export_image_label": "تصدير الصورة",
"render.export_linear": "تصدير: EXR خطي خام",
@@ -1850,6 +2139,7 @@
"render.flare_streak": "خط ضوئي بأسلوب أنامورفي",
"render.flare_strength": "شدة وهج الإضاءات العالية",
"render.flare_threshold": "عتبة الوهج الخطية للمشهد",
"render.fold_browser": "طيّ المتصفح",
"render.gpu_depth": "أقصى عمق للمسار",
"render.gpu_options_help": "تُحفظ العيّنات والعمق والبذرة والتعريض مع هذا الإعداد. تُحفظ طريقة الصورة النشطة فقط.",
"render.gpu_path_failed": "متتبع المسارات على GPU غير متاح",
@@ -1907,11 +2197,13 @@
"render.image_use_largest": "استخدم أكبر حجم بهذه النسبة:",
"render.image_width": "العرض",
"render.include_rig_cards": "تضمين البطاقات والأعلام السلبية",
"render.inner_half_angle": "نصف الزاوية الداخلية",
"render.inspect_scene": "تحديث ملخص المشهد الملتقط",
"render.inspector": "المفتش",
"render.keep_editing": "متابعة التحرير",
"render.layer_down": "نقل للأسفل",
"render.layer_enabled": "الطبقة مفعّلة",
"render.layer_off_suffix": " (متوقفة)",
"render.layer_remove": "إزالة الطبقة",
"render.layer_strength": "شدة الطبقة",
"render.layer_up": "نقل للأعلى",
@@ -2059,6 +2351,7 @@
"render.optics_save": "حفظ هذه البصريات في الإعداد",
"render.optics_saved": "الأهداف البصرية المحفوظة",
"render.optics_saved_help": "تبقى هوية التعريف والميزة والتواجد بالضبط بعد إعادة الفتح دون اتصال. الأهداف المفقودة أو المستبدلة أو المخفية تُرفض؛ والمواد الهندسية دون تغيير. احفظ التعديلات الرقمية أو تجاهلها قبل إزالة هدف محفوظ.",
"render.outer_half_angle": "نصف الزاوية الخارجية",
"render.output_format_status": "PNG هو صورة العرض المكتملة بالضبط. EXR الاختياري على GPU يحتفظ بالإشعاع الخام الخطي للمشهد بصيغة FLOAT32 قبل مرشحات العرض. التصدير لا يستبدل أبدًا ذاكرة المعاينة المؤقتة أو مهمة أخرى.",
"render.output_lock_ratio": "قفل نسبة الأبعاد",
"render.output_over_budget": "الصورة المطلوبة تتجاوز نطاق الموارد المختار. اختر حجمًا أو ملفًا متوافقًا صراحةً؛ لا يحدث تخفيض تلقائي.",
@@ -2092,7 +2385,10 @@
"render.physical_prepare_plan": "تجهيز خطة الإنشاء (دون تطبيق)",
"render.physical_separate": "المظهر ليس تعريفًا للمادة. هذه مراجع موثقة المصدر، لا خصائص فعلية معتمدة. تبقى الكتلة والمواد الهندسية والبصريات الحالية دون تغيير.",
"render.physical_unknown": "لم يثبت أي مرشح رقمي. يجب تحديد الدرجة أو التركيبة أو البنية؛ وغير المعروف لا يعني صفرًا.",
"render.pick_body": "الجسم",
"render.pick_component": "مكوّن",
"render.pick_face": "الوجه",
"render.pick_help": "اختر جسمًا أو وجهًا أو مكوّنًا. انقر في فراغ للمسح؛ Shift أو Ctrl للإضافة أو التبديل. لا يظهر التمييز إلا في عرض المنتج الحي.",
"render.pick_label": "التقاط",
"render.pick_up_label": "التقاط المظهر",
"render.pick_waiting": "اختيار المنتج غير مدعوم بعد.",
@@ -2114,6 +2410,12 @@
"render.preview_upload": "حمولة رؤوس المعاينة الحية",
"render.preview_upload_help": "بايتات رؤوس المعاينة بالضبط، لا ذاكرة GPU أو العملية الكلية. لا تُبسَّط الهندسة. مهام الصور تستخدم قبولها وإضاءتها الخاصة.",
"render.progressive_image_summary": "معاينة PNG · PBR وزجاج · عيّنات تدريجية",
"render.property_conditions": "الشروط: {value}",
"render.property_fallback": "خاصية",
"render.property_qualifier": "المؤهِّل: {value}",
"render.property_source": "المصدر: {id} - {locator}",
"render.property_uncertainty": "عدم اليقين: {value}",
"render.property_unknown": "غير معروف",
"render.quality_ack": "الإقرار بإسقاط الميزانية الثابتة وما أُغفل",
"render.quality_apply": "استخدام ميزانية العيّنات الثابتة هذه",
"render.quality_projection_help": "إعدادات Q الجاهزة تتضمن متطلبات مستقبلية. هذا الإجراء يُسقط فقط ميزانية PNG مدعومة بعيّنات ثابتة، ويُغفل صراحةً الإيقاف التكيّفي والإخراج الخطي الخام وحدود النفاذ المستقلة.",
@@ -2129,6 +2431,7 @@
"render.replace_saved_surface": "استبدال ربط محفوظ موجود لهذا الهدف",
"render.restore_camera": "استعادة الكاميرا المحفوظة",
"render.result_actual_help": "بكسل صورة واحد لكل بكسل عرض.",
"render.result_actual_size": "100%",
"render.result_capture": "المراجعة الملتقطة",
"render.result_current": "مراجعة النموذج الملتقطة هي الحالية.",
"render.result_empty": "لا توجد صورة مكتملة بعد. افحص الإعدادات ثم ابدأ التصيير.",
@@ -2203,10 +2506,14 @@
"render.shot_rename": "إعادة تسمية اللقطة المحفوظة",
"render.shot_saved_only": "احفظ المسودة الحالية أولًا. التكرار وإعادة التسمية يحافظان على الخيارات المحفوظة ومراجع الموارد بالضبط.",
"render.show_shots_label": "إظهار شريط اللقطات",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "الأرض · RGB خطي",
"render.sky_horizon": "الأفق · RGB خطي",
"render.sky_zenith": "السمت · RGB خطي",
"render.soft_focus": "تركيز ناعم",
"render.spot_cone": "مخروط الكشّاف",
"render.stage_frame": "الإطار",
"render.stage_light": "الضوء",
"render.stage_look": "المظهر",
@@ -2257,9 +2564,45 @@
"render.subsurface_enable": "مسار عشوائي للتشتت الداخلي",
"render.subsurface_help": "للعوازل المغلقة فقط. التشتت وامتصاص RGB معاملان منفصلان لكل mm. تتشتت المسارات داخل الهندسة الفعلية، ثم تنكسر أو تنعكس عند الحد. عطّل نفاذ الظل المستقيم وإزالة تشويش السطح والحجم الخارجي؛ واستخدم طبقة فرينل واحدة. ليس مظلل انتشار ولا شبكة كثافة ولا مادة مقيسة. الأوساط الكثيفة قد تحتاج مزيدًا من العيّنات وعمق المسار.",
"render.subsurface_rate": "معدل اصطدامات التشتت",
"render.tone_aces_fitted": "ACES مُلاءَم",
"render.tone_reinhard": "راينهارد",
"render.transmission_scope": "يدعم زجاج GPU الأوساط المنفصلة المعتمدة. لا تتوفر الأوساط المتداخلة غير المقيدة ولا مقدّر نفاذ خالٍ من التشويش.",
"render.transmission_strata": "طبقات فرينل الشرطية",
"render.transmission_strata_help": "القيمة 1 تحافظ على التدفق الأصلي. 2 أو 4 مسارات فرعية تقسّم أول اختيار انعكاس أو نفاذ في الزجاج إلى طبقات مع بقاء قانوني سنل والامتصاص دون تغيير. المزيد من المسارات يكلف عملًا أكثر؛ وهذا ليس إزالة تشويش ولا دعمًا للأوساط المتداخلة ولا وعدًا بتصيير أسرع.",
"render.tree_add_light": "إضافة ضوء",
"render.tree_add_shot": "إضافة لقطة",
"render.tree_browser": "متصفح التصيير",
"render.tree_by_look": "حسب المظهر",
"render.tree_by_object": "حسب الكائن",
"render.tree_constant": "بيئة ثابتة",
"render.tree_default": "افتراضي",
"render.tree_directional": "اتجاهي",
"render.tree_environment": "البيئة",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} وجوه",
"render.tree_face_one": "{count} وجه",
"render.tree_fixed_studio": "استوديو ثابت",
"render.tree_hdr": "HDR",
"render.tree_lights": "الأضواء",
"render.tree_lights_pending": "أوامر الأضواء المسمّاة غير متاحة بعد.",
"render.tree_mixed": "مختلط",
"render.tree_more": "{count} أخرى",
"render.tree_mute": "كتم الضوء",
"render.tree_no_environment": "لا توجد بيئة",
"render.tree_objects": "الكائنات",
"render.tree_output": "المخرجات",
"render.tree_point": "نقطي",
"render.tree_rectangle": "مستطيل",
"render.tree_search": "بحث في الكائنات",
"render.tree_selection": "تحديد التصيير",
"render.tree_shots": "اللقطات",
"render.tree_sky": "السماء",
"render.tree_solo": "عزل الضوء",
"render.tree_spot": "كشّاف",
"render.tree_sun": "الشمس",
"render.tree_switch": "تبديل",
"render.tree_user_one": "{count} كائن",
"render.tree_users": "{count} كائنات",
"render.unavailable_preview": "هذا الإعداد يطلب ملف معاينة غير متاح.",
"render.unsaved": "تغييرات معاينة غير محفوظة",
"render.use_preview": "استخدام المعاينة المدمجة",
@@ -2303,6 +2646,26 @@
"search.try": "اكتب اسم أمر، أو ميزة في هذا التصميم، أو معاملًا. لتشغيل أمر بقيم، اكتب معرّفه وكائن JSON: {example}",
"search.valid": "صالح",
"section.off_hint": "لم يُختر أي مستوى: «موافق» يوقف المقطع.",
"select a direction (an axis, a sketch line or a straight edge) first": "حدد أولًا اتجاهًا (محورًا أو خط رسم أو حافة مستقيمة)",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "حدد اتجاهًا (محورًا أو خط رسم أو حافة مستقيمة) ليتبعه المقطع",
"select a point on a component": "اختر نقطة على مكوّن",
"select a profile, edges or sketch lines first": "حدد أولًا مقطعًا أو حوافّ أو خطوط رسم",
"select an axis": "حدد محورًا",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "حدد أولًا محورًا أو حافة مستقيمة أو دائرية أو وجه أسطوانة أو مخروط أو طارة",
"select bodies first": "حدد الأجسام أولًا",
"select corner points, or the two lines of one corner": "حدد نقاط الزوايا، أو الخطين اللذين يكوّنان زاوية واحدة",
"select one corner point, or the two lines of one corner": "حدد نقطة زاوية واحدة، أو الخطين اللذين يكوّنان زاوية واحدة",
"select sheet edges first": "حدد حواف الصفيحة أولًا",
"select the bend line (a sketch line) first": "حدد خط الثني (خط رسم) أولًا",
"select the cam's profile (a sketch profile or the cam's edges)": "حدد مقطع الكامة (مقطع رسم أو حواف الكامة)",
"select the corner to cut first": "حدد أولًا الزاوية المراد قطعها",
"select the corners to round first": "حدد أولًا الزوايا المراد تدويرها",
"select the fixed face first (a plate's large face)": "حدد أولًا الوجه الثابت (الوجه الكبير للوح)",
"select the frame sketch's lines first": "حدد أولًا خطوط رسم الهيكل",
"select the path (sketch lines across the edge)": "حدد المسار (خطوط رسم عبر الحافة)",
"select the rim face first": "حدد وجه الإطار أولًا",
"select the sheet edge first": "حدد حافة الصفيحة أولًا",
"select two components": "حدد مكوّنين اثنين",
"set by the sketch's lines": "تحدده خطوط الرسم",
"settings.display_quality_note": "المستويات الأدق ترسم الأوجه والحواف المنحنية بنعومة أكبر وتستغرق وقتًا أطول لإنشاء الشبكة. يتغير العرض فقط، لا التصميم ولا الملفات المصدّرة.",
"settings.frame_rate_details_note": "يضيف رسمًا لأزمنة الإطارات الأخيرة مع المثلثات المرسومة فوقه، ومدرّجًا تكراريًا لأزمنة الإطارات، وما رسمته وحدة GPU. انقر معدل الإطارات في العرض لإظهارها أو إخفائها.",
@@ -2320,17 +2683,23 @@
"settings.window_system_details": "التفاصيل",
"settings.window_system_note_now": "يُطبَّق بعد إعادة التشغيل. الحالي: {now}.",
"settings.window_system_wayland_limited": "بعض الميزات محدودة على Wayland الأصلي.",
"sheet.flange_type_base": "أساسية",
"sheet.flange_type_contour": "محيط",
"sheet.flange_type_edge": "حافة",
"sheet.no_body": "لا يوجد جسم صفائح معدنية: ابدأ واحدًا من حافة مثنية > أساسية، أو حوّل لوحًا إلى صفائح معدنية بأمر تحويل إلى صفائح معدنية (اختر وجهه المسطح الكبير)",
"shortcut.json_error": "يجب أن تكون المعاملات بصيغة JSON: {error}",
"shortcut.no_command": "لا يوجد أمر `{id}`، ويجب أن يكون النص قبل JSON معرّف أمر",
"shortcut.pin": "تثبيت في أعلى مربع S",
"shortcut.unpin": "إلغاء التثبيت",
"sketch is missing": "الرسم مفقود",
"sketch.degrees_of_freedom": "{count} درجات حرية",
"sketch.dof_left": "تبقّت {count} درجات حرية",
"sketch.dof_left_one": "تبقّت {count} درجة حرية",
"sketch.draw_curves": "الرسم كـ {linetype}",
"sketch.make_selection": "تحويل التحديد إلى {linetype}",
"sketch.open_ends": "مفتوحة {count}",
"sketch.status_conflict": "تعارض القيود",
"sketch.status_fully_constrained": "مقيّد بالكامل",
"sketch.untied_ends": "غير مربوطة {count}",
"sketch_panel.attached": "مرتبط بـ {body} / {path}",
"sketch_panel.author": "موضع المؤلف: {path}",
@@ -2357,7 +2726,24 @@
"sketch_text.path_hint": "منحنى من الرسم يتبعه النص: انقر هنا ثم على المنحنى",
"sketch_text.use_font_file": "استخدام ملف الخط {path}",
"solid": "مصمت",
"the angle must be a number": "يجب أن تكون الزاوية عددًا",
"the curves must be in one sketch": "يجب أن تكون المنحنيات في رسم واحد",
"the direction must be an axis, a sketch line or a straight edge": "يجب أن يكون الاتجاه محورًا أو خط رسم أو حافة مستقيمة",
"the duration must be a number of seconds, 0.001 or more": "يجب أن تكون المدة عددًا من الثواني، 0.001 أو أكثر",
"the line's sketch is gone": "رسم الخط لم يعد موجودًا",
"the lines must be in one sketch": "يجب أن تكون الخطوط في رسم واحد",
"the lines must be in one sketch, not the section's": "يجب أن تكون الخطوط في رسم واحد، غير رسم المقطع العرضي",
"the parts library is empty": "مكتبة القطع فارغة",
"the parts library is not available": "مكتبة القطع غير متاحة",
"the path curves must be in one other sketch": "يجب أن تكون منحنيات المسار في رسم آخر واحد",
"the path's sketch is gone": "رسم المسار لم يعد موجودًا",
"the position must be a number": "يجب أن يكون الموضع عددًا",
"the preview failed": "فشلت المعاينة",
"the profiles and curves must be in one sketch": "يجب أن تكون المقاطع والمنحنيات في رسم واحد",
"the reference face must be on the edges' body": "يجب أن يكون وجه المرجع على جسم الحواف",
"the scale must be above 0": "يجب أن يكون المقياس أكبر من 0",
"the section's profiles must be in one sketch": "يجب أن تكون مقاطع المقطع العرضي في رسم واحد",
"the two origins are on the same component": "يقع الأصلان على المكوّن نفسه",
"thread.automatic_size": "حجم تلقائي",
"thread.designation": "التسمية",
"thread.direction": "اتجاه السن اللولبي",
@@ -2397,6 +2783,7 @@
"trace.points": "{count} نقطة على طول المسار",
"trace.stopped_by_contact": "ينتهي عند العيّنة {sample}: سيخترق {a} الجسم {b}",
"trace.stopped_by_loop": "ينتهي عند العيّنة {sample}: لا يمكن للحلقة عبر {joint} أن تنغلق أكثر",
"trim by sketch curves, or by one plane or face": "اقصّ بمنحنيات رسم، أو بمستوى واحد أو وجه واحد",
"ui.1_degree_of_freedom": "درجة حرية واحدة",
"ui.3d_mouse_axes_reassigned": "المحاور مُعاد تعيينها في التفضيلات، وذلك لا يزال يُطبَّق فوق هذه المعايرة.",
"ui.3d_mouse_button": "الزر {number}",
@@ -2873,6 +3260,8 @@
"ui.design_properties.revision": "المراجعة",
"ui.diameter": "القطر",
"ui.dimension": "البُعد",
"ui.direct_interaction": "التفاعل المباشر",
"ui.direct_interaction_note": "اعمل على النموذج مباشرة في منطقة العرض. اضغط على وجه مستوٍ أو مقطع واسحب: إلى الأعلى للبثق، وإلى الأسفل داخل جسم للقطع، والحركة الجانبية تحدد حجم الخطوة",
"ui.direction": "الاتجاه",
"ui.display_quality": "جودة العرض",
"ui.display_quality_coarse": "خشنة",
@@ -2896,6 +3285,7 @@
"ui.editJointLimits": "تعديل حدود المفصل",
"ui.edit_section_analysis": "تعديل تحليل المقطع",
"ui.ellipse": "قطع ناقص",
"ui.emboss_wrap_note": "تلتف ملامح الخطوط المتعامدة المماسة لأسطوانة مدعومة تلقائيًا. اختر جدارًا لتحديد الهدف.",
"ui.end_radius": "نصف قطر النهاية",
"ui.end_scale": "مقياس النهاية",
"ui.entities": "العناصر",
@@ -2968,6 +3358,7 @@
"ui.heading_extrude": "بثق",
"ui.heading_fillet": "تقويس",
"ui.heading_finish_sketch": "إنهاء الرسم",
"ui.heading_form": "تشكيل",
"ui.heading_front": "أمام",
"ui.heading_hole": "ثقب",
"ui.heading_home": "الرئيسي",
@@ -3016,6 +3407,7 @@
"ui.heading_utilities": "أدوات مساعدة",
"ui.heading_utility": "أداة مساعدة",
"ui.heading_weldments": "اللحامات",
"ui.height": "الارتفاع",
"ui.help": "المساعدة",
"ui.hide": "إخفاء",
"ui.hideAxes": "إخفاء المحاور",
@@ -3053,11 +3445,14 @@
"ui.intersect": "تقاطع",
"ui.isolate": "عزل",
"ui.join": "ضم",
"ui.joint_play": "▶ تشغيل",
"ui.joint_stop": "■ إيقاف",
"ui.joints": "المفاصل",
"ui.keyboard_shortcuts": "الاختصارات",
"ui.language": "اللغة",
"ui.layout_compact": "مضغوط",
"ui.layout_floating": "عائم",
"ui.length": "الطول",
"ui.length_decimals": "المنازل العشرية للأطوال",
"ui.light": "فاتح",
"ui.line": "خط",
@@ -3069,6 +3464,7 @@
"ui.loft": "تشكيل انتقالي",
"ui.look_at": "النظر إلى",
"ui.look_at_anim_desc": "عرض المحور، النظر إلى، الرئيسي، الملاءمة",
"ui.major_radius": "نصف القطر الأكبر",
"ui.manipulator_free_alt": "السحب الحر للمُعالج أيضًا مع Alt/Option",
"ui.manipulator_free_alt_tip": "عند التفعيل: Alt/Option أو Ctrl/Cmd على أسهم البثق / أداة التحويل يعطّل التقاط القيم. عند الإيقاف: Ctrl/Cmd فقط.",
"ui.manufacture": "التصنيع",
@@ -3098,8 +3494,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF مع وسوم الأوجه",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "نصف القطر الأصغر",
"ui.mirror": "مرآة",
"ui.mirror_line": "خط المرآة",
"ui.modifiers_either": "{first} أو {second}",
"ui.move": "تحريك",
"ui.multiple": "متعدد",
"ui.named_views": "العروض المسمّاة",
@@ -3156,6 +3554,7 @@
"ui.pinToShortcuts": "تثبيت في الاختصارات",
"ui.pinToToolbar": "تثبيت في شريط الأدوات",
"ui.pipe": "أنبوب",
"ui.pitch": "الخطوة",
"ui.placement": "الموضع",
"ui.placement_handles": "مقابض الموضع",
"ui.placement_handles_tip": "مقابض على معاينة المسند أو النتوء أو وصلة الكبس: اسحب العلامة لتحريكها على النموذج، وأدِرها من حلقتها",
@@ -3218,6 +3617,7 @@
"ui.reverse_horizontal_pan_direction": "عكس اتجاه الإزاحة الأفقية",
"ui.reverse_horizontal_pan_tip": "التمرير الأفقي بإصبعين وعجلة الإبهام يزيحان في الاتجاه المعاكس",
"ui.reverse_zoom_direction": "عكس اتجاه التكبير",
"ui.revolutions": "عدد اللفات",
"ui.revolve": "دوران",
"ui.ribbon_exit": "خروج",
"ui.ribbon_labels": "إظهار النص تحت أيقونات الشريط",
@@ -3234,6 +3634,7 @@
"ui.scale": "تحجيم",
"ui.second_rail": "الدليل الثاني",
"ui.section_analysis": "تحليل المقطع",
"ui.section_size": "حجم المقطع",
"ui.select": "تحديد",
"ui.selectOther": "تحديد آخر…",
"ui.selectTangentChain": "تحديد سلسلة مماسية",
@@ -3305,6 +3706,7 @@
"ui.start_page": "صفحة البداية",
"ui.step_values": "تغيير القيم بمفاتيح الأسهم وعجلة الفأرة",
"ui.step_values_tip": "في حقل قيمة تكتب فيه، يغيّر السهمان لأعلى ولأسفل الرقم العادي بمقدار 1 (Shift: 10، Alt: 0.1)، وكذلك عجلة الفأرة فوق الحقل. أما التعابير فتبقى كما كُتبت.",
"ui.stitch_tolerance_hint": "دقيقة",
"ui.stretch": "مطّ",
"ui.supersampling": "التنعيم الفائق (SSAA)",
"ui.supersampling_adaptive": "فقط عندما يكون العرض ساكنًا",
@@ -3335,6 +3737,8 @@
"ui.to_object": "إلى كائن",
"ui.tool_direction": "اتجاه الأداة",
"ui.top": "أعلى",
"ui.top_diameter": "القطر العلوي",
"ui.top_radius": "نصف القطر العلوي",
"ui.torus": "طارة",
"ui.total_angle": "الزاوية الكلية",
"ui.trackpad_pan_tip": "إيماءات لوحة اللمس تُزيح (عند الإيقاف: تكبّر مثل العجلة)؛ عجلة الفأرة تكبّر، وعجلة الإبهام تزيح جانبيًا، والقرص يكبّر دائمًا",
@@ -3363,6 +3767,7 @@
"ui.visual_shaded_with_edges": "مظلل مع الحواف",
"ui.visual_style": "نمط العرض",
"ui.visual_wireframe": "إطار سلكي",
"ui.width": "العرض",
"ui.window_system": "نظام النوافذ",
"ui.window_system_auto": "تلقائي",
"ui.window_system_wayland": "Wayland",
@@ -3423,6 +3828,9 @@
"update.up_to_date": "SolidCraft محدّث.",
"update.update_now": "التحديث الآن",
"update.you_have": "لديك {version}.",
"use a positive nominal diameter and a pitch smaller than it": "استخدم قطرًا اسميًا موجبًا وخطوة أصغر منه",
"values must be finite numbers": "يجب أن تكون القيم أعدادًا منتهية",
"values must be numbers or expressions": "يجب أن تكون القيم أعدادًا أو تعابير",
"view.auto_ortho_faces": "منظوري أثناء التدوير، ومتعامد على الأوجه",
"web.files.insert_drawings_hint": "ملفات CAD أو شبكات أو DXF أو SVG إلى التصميم المفتوح",
"web.files.insert_stored_drawings_hint": "إلى التصميم المفتوح (ملفات CAD، شبكات، DXF، SVG)",
+874 -1
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -1190,7 +1190,9 @@
"nav.free_orbit.help": "Musen og 3D-musen roterer gennem begge poler og bevarer rulning. Snap til akser med Shift er slået fra.",
"nav.free_orbit.label": "Fri rotation af visningen",
"nav.fusion.help": "Træk med midterste museknap panorerer, Shift+midterste roterer visningen, træk med højre roterer visningen",
"nav.hfss.help": "Alt+træk med venstre museknap panorerer, Shift+Alt+venstre zoomer, Ctrl+træk med venstre fra et tomt område roterer visningen",
"nav.inventor.help": "Træk med midterste museknap panorerer, Shift+midterste roterer visningen, Ctrl+midterste zoomer, træk med højre roterer visningen",
"nav.maya.help": "Alt+træk med venstre museknap roterer visningen, Alt+midterste panorerer, Alt+højre zoomer; træk med midterste museknap panorerer også",
"nav.openscad.help": "Træk med venstre museknap i et tomt område roterer visningen, Shift+venstre markerer med en ramme, træk i skitsegeometri redigerer den; træk med højre eller midterste museknap panorerer, Shift+højre eller Shift+midterste zoomer",
"nav.solidworks.help": "Træk med midterste museknap roterer visningen, Ctrl+midterste panorerer, Shift+midterste zoomer, træk med højre roterer visningen",
"nav.tinkercad.help": "Træk med højre museknap roterer visningen, træk med midterste eller Shift+højre panorerer",
@@ -1209,6 +1211,11 @@
"no picture": "intet billede",
"none": "ingen",
"parts.automatic_name": "automatisk",
"parts.dimension.d": "Nominel diameter",
"parts.dimension.height": "Højde",
"parts.dimension.pitch": "Stigning",
"parts.dimension.thickness": "Tykkelse",
"parts.dimension.width": "Bredde",
"pattern.alignment_2": "Justering 2",
"pattern.alignment_hint": "Antal omfatter originalen. Centrér fordeler kopierne ligeligt; Vend vælger siden med den ekstra kopi ved et lige samlet antal.",
"pattern.direction_1": "Retning 1",
@@ -2057,6 +2064,7 @@
"ui.heading_utilities": "VÆRKTØJER",
"ui.heading_utility": "VÆRKTØJ",
"ui.heading_weldments": "SVEJSNING",
"ui.height": "Højde",
"ui.help": "Hjælp",
"ui.hide": "Skjul",
"ui.hideAxes": "Skjul akser",
@@ -2095,6 +2103,7 @@
"ui.language": "Sprog",
"ui.layout_compact": "Kompakt",
"ui.layout_floating": "Flydende",
"ui.length": "Længde",
"ui.length_decimals": "Længdedecimaler",
"ui.light": "Lys",
"ui.line": "Linje",
@@ -2182,6 +2191,7 @@
"ui.pinToShortcuts": "Fastgør til genveje",
"ui.pinToToolbar": "Fastgør til værktøjslinje",
"ui.pipe": "Rør",
"ui.pitch": "Stigning",
"ui.placement": "Placering",
"ui.plane": "Plan",
"ui.plane_at_angle": "Plan i vinkel",
@@ -2365,6 +2375,7 @@
"ui.visual_shaded_with_edges": "Skyggelagt med kanter",
"ui.visual_style": "Visuel stil",
"ui.visual_wireframe": "Trådmodel",
"ui.width": "Bredde",
"ui.workspace": "arbejdsområde",
"ui.workspace_animation_description": "Eksploderede visninger, bevægelsesstudier og storyboards",
"ui.workspace_available": "Tilgængelig",
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(aktive Regel)",
"0 turns it off": "0 schaltet es aus",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Unten den GitHub-Entwurf öffnen und den kopierten Bericht aus der Zwischenablage einfügen.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Unten den GitHub-Entwurf öffnen. Titel und Bericht werden vorausgefüllt.",
@@ -51,15 +52,19 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "Wenden Sie zuerst Ihr Erscheinungsbild an. Exportiert zugewiesene Erscheinungsbilder und in diesem Design erstellte Materialien.",
"Arc length": "Bogenlänge",
"Area": "Fläche",
"As Picked": "Wie gewählt",
"As-Built": "Wie gebaut",
"Assign Rule": "Regel zuweisen",
"Attachment": "Anbindung",
"BLEND SURFACE": "ÜBERGANGSFLÄCHE",
"BOUNDARY SURFACE": "BERANDUNGSFLÄCHE",
"BROWSER": "BROWSER",
"Ball": "Kugelgelenk",
"Bar": "Flachstab",
"Base Height": "Sockelhöhe",
"Bend": "Biegung",
"Bend Edges": "Biegekanten",
"Bend Line": "Biegelinie",
"Bend Line Position": "Position der Biegelinie",
"Bend Position": "Biegeposition",
"Bend Radius": "Biegeradius",
@@ -71,6 +76,7 @@
"Body (last if none)": "Körper (letzter, wenn keiner)",
"Body to split": "Zu teilender Körper",
"Body, or faces to take out": "Körper oder zu entfernende Flächen",
"Both": "Beide",
"Bottom Left": "Unten links",
"Bottom Middle": "Unten Mitte",
"Bottom Right": "Unten rechts",
@@ -102,6 +108,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "Wählen Sie eine neue Ebene. Skizzengeometrie und Bemaßungen bleiben in ihren zweidimensionalen Koordinaten unverändert.",
"Choose…": "Auswählen…",
"Circle center": "Kreismittelpunkt",
"Circle or sphere": "Kreis oder Kugel",
"Circular": "Kreisförmig",
"Circumference": "Umfang",
"Clockwise": "Im Uhrzeigersinn",
@@ -118,6 +125,7 @@
"Config Table": "Konfigurationstabelle",
"Configuration": "Konfiguration",
"Configuration rules": "Configuration rules",
"Constant radius": "Konstanter Radius",
"Contact": "Kontakt",
"Contact Sets": "Kontaktsätze",
"Contact sets": "Kontaktsätze",
@@ -153,7 +161,9 @@
"Custom": "Benutzerdefiniert",
"Customize Toolbar": "Symbolleiste anpassen",
"Customize…": "Anpassen…",
"Cylindrical": "Drehschubgelenk",
"Cylindrical face": "Zylindrische Fläche",
"Deboss": "Vertiefen",
"Delete": "Löschen",
"Delete Folders and Features…": "Ordner mit Features löschen…",
"Delete Selected Features…": "Ausgewählte Merkmale löschen…",
@@ -180,6 +190,7 @@
"Drag to move the hole; click to remove it": "Ziehen, um die Bohrung zu verschieben; anklicken, um sie zu entfernen",
"Drive Joint": "Gelenk antreiben",
"Duration": "Dauer",
"Edge": "Kante",
"Edges": "Kanten",
"Edit": "Bearbeiten",
"Edit Profile Sketch": "Profile-Skizze bearbeiten",
@@ -188,6 +199,7 @@
"End Radius": "Endradius",
"End bulge": "Endausbauchung",
"End continuity": "Endstetigkeit",
"Equal Distance": "Gleicher Abstand",
"Expand": "Ausklappen",
"Expected result (optional)": "Erwartetes Ergebnis (optional)",
"Explode": "Explodieren",
@@ -215,6 +227,8 @@
"Faces": "Flächen",
"Faces / edges / vertices": "Flächen / Kanten / Ecken",
"Faces to split": "Zu teilende Flächen",
"Faces/Body": "Flächen/Körper",
"Factor must be a positive number": "Der Faktor muss eine positive Zahl sein",
"Fastener": "Verbindungselement",
"Favorites": "Favoriten",
"Favourite": "Favourite",
@@ -224,9 +238,12 @@
"Filter…": "Filtern…",
"Find in Browser": "Im Browser suchen",
"Finish": "Oberfläche",
"First edge": "Erste Kante",
"First plane": "Erste Ebene",
"First point": "Erster Punkt",
"Fit and G2 corners require Constant radius.": "Passung und G2-Ecken erfordern Constant radius.",
"Fixed Face": "Feste Fläche",
"Flange Gap": "Flanschspalt",
"Flange thickness": "Flanschdicke",
"Flanges": "Flansche",
"Flat Pattern": "Flachmuster",
@@ -234,8 +251,10 @@
"Follow camera (Look At sketches)": "Kamera folgen (Skizzen ansehen)",
"Follow the camera (Look At sketches)": "Der Kamera folgen (Skizzen ansehen)",
"Font": "Schriftart",
"Free Move": "Frei verschieben",
"From": "Von",
"From Bodies": "Aus Körpern",
"From Snap": "Von Fangpunkt",
"From edges": "Ausgangskanten",
"Full Length": "Volle Länge",
"Full thread depth": "Volle Gewindetiefe",
@@ -247,10 +266,13 @@
"Halo under sketch curves": "Hervorhebung unter Skizzenkurven",
"Height": "Höhe",
"Height From": "Höhe ab",
"Hem Gap": "Umkantungsspalt",
"Hidden edges": "Verdeckte Kanten",
"History layout": "Verlaufslayout",
"History names": "Namen im Konstruktionsverlauf",
"Hole (optional)": "Bohrung (optional)",
"Hole Depth": "Bohrungstiefe",
"Hole Diameter": "Bohrungsdurchmesser",
"Holes": "Löcher",
"Holes (edges on them)": "Löcher (ihre Kanten)",
"Home view": "Startansicht",
@@ -273,12 +295,16 @@
"Issue title": "Issue-Titel",
"Items": "Elemente",
"JOINTS": "GELENKE",
"Joint 1": "Gelenk 1",
"Joint 2": "Gelenk 2",
"Joint Origin1": "Gelenkursprung1",
"K Factor": "K-Faktor",
"Keep (points on it)": "Behalten (Punkte darauf)",
"Keep Tools": "Werkzeuge behalten",
"Keep of the other surface": "Vom anderen Flächenkörper behalten",
"Key a joint's value at this step": "Gelenkwert in diesem Schritt als Schlüsselbild setzen",
"Keys": "Schlüsselbilder",
"Knife Edge": "Messerkante",
"L-Angle": "L-Profil",
"LIBRARY": "BIBLIOTHEK",
"LINKS": "VERKNÜPFUNGEN",
@@ -291,9 +317,11 @@
"Letter Spacing": "Zeichenabstand",
"Library": "Bibliothek",
"Library file": "Bibliotheksdatei",
"Library response is missing": "Die Antwort der Bibliothek fehlt",
"Limits": "Grenzen",
"Line Spacing": "Zeilenabstand",
"Line Type": "Linientyp",
"Line on plane": "Linie auf Ebene",
"Lines": "Linien",
"Listing the installed fonts…": "Installierte Schriftarten werden aufgelistet…",
"Load library": "Bibliothek laden",
@@ -313,11 +341,14 @@
"Material Outside": "Material außen",
"Material copied. Existing body assignments are unchanged.": "Material kopiert. Bestehende Materialzuweisungen der Körper bleiben unverändert.",
"Max": "Max",
"Max Thickness": "Max. Dicke",
"Maximum": "Maximum",
"Mesh body": "Netzkörper",
"Mid Radius": "Mittlerer Radius",
"Middle double-click": "Doppelklick mit mittlerer Taste",
"Min": "Min",
"Min Draft": "Min. Formschräge",
"Min Thickness": "Min. Dicke",
"Minimum": "Minimum",
"Mirror Plane": "Spiegelebene",
"Mitre": "Gehrung",
@@ -337,6 +368,7 @@
"Name": "Name",
"Name on import": "Name beim Import",
"Nearest": "Nächstgelegen",
"Neutral plane": "Neutrale Ebene",
"New": "Neu",
"New Comp.": "Neue Komp.",
"New Sketch": "Neue Skizze",
@@ -347,6 +379,7 @@
"No matching appearances": "Keine passenden Erscheinungsbilder",
"No matching physical materials.": "Keine passenden physikalischen Materialien gefunden.",
"No visible bodies or sketches to export.": "Keine sichtbaren Körper oder Skizzen zum Exportieren.",
"Nominal Radius": "Nennradius",
"Nominal diameter": "Nenndurchmesser",
"None": "Keine",
"Not available yet": "Noch nicht verfügbar",
@@ -375,22 +408,28 @@
"Overall length": "Gesamtlänge",
"Param. Graph": "Param.-Graph",
"Parameter": "Parameter",
"Part length must be greater than zero and at most 2000 mm": "Die Bauteillänge muss größer als null und höchstens 2000 mm sein",
"Parts": "Teile",
"Pass through": "Durch Punkte",
"Path": "Pfad",
"Pattern": "Muster",
"Per Edge": "Pro Kante",
"Physical material definitions": "Definitionen physikalischer Materialien",
"Pick a part size": "Eine Bauteilgröße wählen",
"Pick the tool bodies": "Werkzeugkörper wählen",
"Picked": "Ausgewählte",
"Picked point": "Gewählter Punkt",
"Pin-slot": "Stift-Nut-Gelenk",
"Pitch": "Steigung",
"Pivot": "Drehpunkt",
"Place at the origin instead": "Stattdessen im Ursprung platzieren",
"Planar": "Ebenengelenk",
"Plastic Rules": "Kunststoffregeln",
"Play the joint's motion in the view": "Die Bewegung des Gelenks in der Ansicht abspielen",
"Playback": "Wiedergabe",
"Plot": "Diagramm",
"Point on line": "Punkt auf Linie",
"Point on plane": "Punkt auf Ebene",
"Position": "Position",
"Position (0 to 1)": "Position (0 bis 1)",
"Position (G0)": "Position (G0)",
@@ -403,6 +442,7 @@
"Profiles or curves": "Profile oder Kurven",
"Profiles/Curves": "Profile/Kurven",
"Quantity": "Anzahl",
"Quantity must be at least 2": "Die Anzahl muss mindestens 2 sein",
"RECENT": "ZULETZT",
"REFERENCE": "REFERENZ",
"RULED SURFACE": "REGELFLÄCHE",
@@ -416,6 +456,8 @@
"Rectangular": "Rechteckig",
"Rectangular Tube": "Rechteckrohr",
"Reference face": "Referenzfläche",
"Relief Depth": "Freistellungstiefe",
"Relief Width": "Freistellungsbreite",
"Remove Tools": "Werkzeuge entfernen",
"Remove condition": "Bedingung entfernen",
"Remove from Folder": "Aus Ordner entfernen",
@@ -442,6 +484,7 @@
"Restore this studio's tools": "Werkzeuge dieses Studios wiederherstellen",
"Result": "Ergebnis",
"Retake screenshot": "Screenshot erneut aufnehmen",
"Reveal Height": "Absatzhöhe",
"Reverse": "Umkehren",
"Reverse Direction": "Richtung umkehren",
"Revert": "Zurücksetzen",
@@ -450,12 +493,15 @@
"Revert Position": "Position zurücksetzen",
"Review the report and screenshot before opening GitHub.": "Prüfen Sie Bericht und Screenshot, bevor Sie GitHub öffnen.",
"Review your report on GitHub and click Submit new issue to publish it.": "Prüfen Sie Ihren Bericht auf GitHub und klicken Sie auf „Submit new issue“, um ihn zu veröffentlichen.",
"Revolute": "Drehgelenk",
"Rib Length": "Rippenlänge",
"Rib Offset": "Rippenversatz",
"Rib Thickness": "Rippendicke",
"Ribs": "Rippen",
"Right Middle": "Rechts Mitte",
"Rigid": "Starr",
"Rim Edge": "Randkante",
"Rim face": "Randfläche",
"Ring of tools on the right button": "Werkzeugring auf der rechten Maustaste",
"Roll Back Here": "Hierher zurücksetzen",
"Roll History Marker Here": "Verlaufsmarkierung hierher verschieben",
@@ -480,16 +526,28 @@
"Search": "Suchen",
"Search commands": "Befehle suchen",
"Search this library": "Diese Bibliothek durchsuchen",
"Second edge": "Zweite Kante",
"Second plane": "Zweite Ebene",
"Second point": "Zweiter Punkt",
"Section": "Schnitt",
"Section (optional)": "Abschnitt (optional)",
"Section position": "Lage des Querschnitts",
"Sections (one sketch each)": "Querschnitte (je eine Skizze)",
"Select Other": "Andere auswählen",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "Anderes auswählen: Halten Sie die linke Taste ruhig auf dem Modell gedrückt (oder Rechtsklick › Anderes auswählen…), um alles unter dem Cursor aufzulisten; klicken Sie erneut an dieselbe Stelle, um das nächste Element dort auszuwählen. Doppelklick mit der mittleren Taste wechselt zur Startansicht (Einstellungen › Navigation).",
"Select Same Look": "Gleiches Aussehen auswählen",
"Select bodies (a face picks its body)": "Körper auswählen (eine Fläche wählt ihren Körper)",
"Select bodies or faces instead": "Stattdessen Körper oder Flächen auswählen",
"Select edges": "Kanten auswählen",
"Select points of the sketch being edited": "Punkte der bearbeiteten Skizze auswählen",
"Select the centre the pattern turns around first": "Zuerst den Mittelpunkt auswählen, um den sich das Muster dreht",
"Select the curves to offset first": "Zuerst die zu versetzenden Kurven auswählen",
"Select the mirror line": "Die Spiegellinie auswählen",
"Select the sketch curves or points to mirror first": "Zuerst die zu spiegelnden Skizzenkurven oder -punkte auswählen",
"Select the sketch curves or points to move first": "Zuerst die zu verschiebenden Skizzenkurven oder -punkte auswählen",
"Select the sketch curves or points to pattern first": "Zuerst die Skizzenkurven oder -punkte für das Muster auswählen",
"Select the sketch curves or points to scale first": "Zuerst die zu skalierenden Skizzenkurven oder -punkte auswählen",
"Select the sketch curves or points to transform first": "Zuerst die zu transformierenden Skizzenkurven oder -punkte auswählen",
"Selection filter": "Auswahlfilter",
"Semantic faces share their appearance across instances.": "Semantische Flächen teilen ihr Erscheinungsbild über alle Instanzen hinweg.",
"Send your report on GitHub": "Bericht auf GitHub senden",
@@ -509,9 +567,12 @@
"Sketch geometry and profiles": "Skizzengeometrie und Profile",
"Sketch plane has no body-face attachment.": "Die Skizzenebene hat keine Anbindung an eine Körperfläche.",
"Sketch points": "Skizzenpunkte",
"Slider": "Schubgelenk",
"Slot width": "Langlochbreite",
"Snap to face and edge centres": "An Flächen- und Kantenmittelpunkten einrasten",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft wurde beendet, bevor diese Designs gespeichert wurden. Ihr letzter Autosave kann geöffnet werden.",
"Spacing 2 must be a non-zero number": "Abstand 2 muss eine Zahl ungleich null sein",
"Spacing must be a non-zero number": "Der Abstand muss eine Zahl ungleich null sein",
"Specialise": "Spezialisieren",
"Speed": "Geschwindigkeit",
"Splitting tool": "Trennwerkzeug",
@@ -522,6 +583,7 @@
"Start angle": "Startwinkel",
"Start bulge": "Startausbauchung",
"Start continuity": "Startstetigkeit",
"Stationary Side": "Feste Seite",
"Step": "Schritt",
"Steps": "Schritte",
"Steps to reproduce (optional)": "Schritte zur Reproduktion (optional)",
@@ -536,6 +598,7 @@
"Suppressed": "Unterdrückt",
"Surface": "Flächenkörper",
"Surface, or faces to turn over": "Fläche oder umzudrehende Flächen",
"Surfaces": "Flächen",
"Swap Ends": "Enden vertauschen",
"TRIM": "TRIMMEN",
"Tangent": "Tangential",
@@ -546,24 +609,34 @@
"Tap drill diameter": "Kernlochdurchmesser",
"Target": "Ziel",
"Target Body": "Zielkörper",
"Target Face (optional)": "Zielfläche (optional)",
"Tear": "Reißen",
"Technical details": "Technische Details",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "Die gestrichelte Skizze ist eine gespeicherte Ebenenführung. Wählen Sie eine neue Fläche, um die Anbindung zu reparieren.",
"The design changed. Reopen Change Part Size for the component.": "Das Design hat sich geändert. Bauteilgröße ändern für die Komponente erneut öffnen.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "Die Richtung muss eine Achse oder eine gerade Skizzenkurve in der Skizzenebene sein",
"The mirror line cannot also be mirrored": "Die Spiegellinie kann nicht gleichzeitig gespiegelt werden",
"The mirror line must be a straight curve of this sketch, not an origin axis": "Die Spiegellinie muss eine gerade Kurve dieser Skizze sein, keine Ursprungsachse",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "Das gespeicherte Autorvorkommen fehlt. Wählen Sie vor dem erneuten Anbinden eine gültige Autorplatzierung.",
"Then": "Then",
"These features will be deleted:": "Diese Merkmale werden gelöscht:",
"These features will fail:": "Diese Merkmale schlagen fehl:",
"Thickness Outside": "Dicke außen",
"Thickness Variation": "Dickenschwankung",
"Thin": "Dünnwandig",
"Thin Extrude": "Dünnwandig extrudieren",
"Third plane": "Dritte Ebene",
"Third point": "Dritter Punkt",
"This child is shared. Deleting it removes it from every copy of its parent.": "Dieses untergeordnete Element ist geteilt. Löschen entfernt es aus jeder Kopie des übergeordneten Elements.",
"This child is shared. Position changes apply to every copy of its parent.": "Dieses untergeordnete Element ist geteilt. Positionsänderungen gelten für jede Kopie des übergeordneten Elements.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "Diese Fläche kann keine dauerhafte Anbindung bieten. Wählen Sie eine andere Fläche oder verwenden Sie ausdrücklich eine feste Ebene.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "Dieses Bild wurde noch nicht an GitHub angehängt. Kopieren oder speichern Sie es und fügen Sie es anschließend Ihrem GitHub-Bericht hinzu.",
"Thread depth": "Gewindetiefe",
"Thread diameter": "Gewindedurchmesser",
"Through point": "Durch Punkt",
"To": "Bis",
"To Offset": "Bis Versatz",
"To Snap": "Zu Fangpunkt",
"To edges": "Zielkanten",
"Toe radius": "Kantenradius",
"Tolerance": "Toleranz",
@@ -577,6 +650,7 @@
"Trimming tool (plane, face or curves)": "Trimmwerkzeug (Ebene, Fläche oder Kurven)",
"Turn off section analysis before exporting the view.": "Deaktivieren Sie die Schnittanalyse, bevor Sie die Ansicht exportieren.",
"Type": "Typ",
"Type a distance or an angle to move by": "Einen Abstand oder einen Winkel zum Verschieben eingeben",
"UNTRIM": "TRIMMEN AUFHEBEN",
"Unit": "Einheit",
"Unsuppress": "Unterdrückung aufheben",
@@ -621,6 +695,17 @@
"Z angle": "Z-Winkel",
"Z distance": "Z-Abstand",
"Zebra": "Zebra",
"`joint` must be an id or a name": "`joint` muss eine ID oder ein Name sein",
"`params` must be an object": "`params` muss ein Objekt sein",
"`values` must be a list": "`values` muss eine Liste sein",
"a chamfer needs a corner of exactly two lines": "eine Abschrägung braucht eine Ecke aus genau zwei Linien",
"a file operation is in progress": "ein Dateivorgang läuft gerade",
"a picked curve is no longer in a sketch": "eine gewählte Kurve liegt in keiner Skizze mehr",
"a picked curve's sketch has not been solved": "die Skizze einer gewählten Kurve wurde nicht gelöst",
"a picked edge has no points": "eine gewählte Kante hat keine Punkte",
"a picked edge is gone": "eine gewählte Kante existiert nicht mehr",
"a picked edge's body is gone": "der Körper einer gewählten Kante existiert nicht mehr",
"add a key for a joint first": "zuerst einen Schlüssel für ein Gelenk hinzufügen",
"ai.connected_toast": "SolidCraft ist jetzt in {clients} verfügbar. Starten Sie diese neu, um es zu nutzen (Einstellungen > Assistent).",
"ai.prefs.allow_control": "Verbindungen von KI-Agenten zulassen (Steuerkanal / MCP)",
"ai.prefs.allow_control_note": "Öffnet einen Steuerkanal nur auf diesem Computer (127.0.0.1, Port 27878 oder der nächste freie). Ein verbindendes Programm muss zusätzlich ein geheimes Token vorweisen, das nur Ihr Benutzerkonto lesen kann und bei jedem Start neu erzeugt wird. Wirkt ab dem nächsten Start von SolidCraft. Aus: Es wartet nichts auf Verbindungen, außer Sie starten SolidCraft mit --control.",
@@ -657,6 +742,7 @@
"appearance.pbr_opaque": "Opakes PBR",
"appearance.roughness": "Rauheit",
"appearance.surface_response": "Oberflächenverhalten",
"bom.group_children": "Unterteile in der Zeile ihres Teils",
"browser.body_name": "Körper {number}",
"browser.calibrate_title": "Kalibrieren: {name}",
"browser.capture_many": "{count} Komponenten wurden verschoben, ihre Positionen sind aber nicht erfasst.",
@@ -667,6 +753,8 @@
"browser.move_title": "Verschieben: {name}",
"browser.parameters": "Parameter ({count})",
"browser.precision": "Genauigkeit: {precision}",
"browser.sketch_attachment_lost": "{name} (Bezug verloren)",
"browser.sketch_editing": "{name} (in Bearbeitung)",
"browser.sketch_name": "Skizze {number}",
"browser.units": "Einheiten: {units}",
"cam.flat": "Flachstößel",
@@ -676,7 +764,13 @@
"cam.roller": "Rolle",
"cam.roller_pick": "Rolle (optional)",
"cam.tip_pick": "Spitze (optional)",
"choose a profile": "ein Profil wählen",
"choose the cam's and the follower's joints": "die Gelenke von Nocken und Stößel wählen",
"choose the joints to couple": "die zu koppelnden Gelenke wählen",
"click a plane or planar face": "Ebene oder ebene Fläche anklicken",
"click sketch curves": "Skizzenkurven anklicken",
"cmd.appearance_assign": "Erscheinungsbild",
"cmd.appearance_chain": "Aussehen-Herkunft",
"cmd.appearance_library": "Erscheinungsbild-Bibliothek",
"cmd.appearance_list": "Erscheinungsbilder auflisten",
"cmd.appearance_paint": "Aussehen aufmalen",
@@ -1056,6 +1150,9 @@
"cmd.timeline_roll_to": "Verlaufsmarkierung verschieben",
"cmd.timeline_rollback": "Zeitleistenmarkierung verschieben",
"cmd.timeline_suppress": "Merkmal unterdrücken",
"cmd.view.render_browser": "Render-Browser",
"cmd.view.render_dock": "Render-Panel verschieben",
"cmd.view.render_focus": "Render-Fokusansicht",
"cmd.view_ambient_occlusion": "Umgebungsverdeckung",
"cmd.view_apply": "Benannte Ansicht wiederherstellen",
"cmd.view_back": "Rückansicht",
@@ -1157,6 +1254,8 @@
"dxf.progress.write": "DXF schreiben (5/5)",
"dxf.tolerance": "Kurventoleranz",
"dxf.tolerance_help": "Nur sichtbare Körper und angezeigte Skizzen. Kurven werden durch gerade Segmente angenähert. Eine kleinere Toleranz liefert feinere Kurven und benötigt mehr Zeit und Speicher.",
"each rail's curves must be in one sketch": "die Kurven jeder Führungskurve müssen in derselben Skizze liegen",
"feature computation ended without a result": "die Berechnung des Merkmals wurde ohne Ergebnis beendet",
"file.open.drawing_filter": "Designs, CAD-Dateien, Netze und Zeichnungen",
"file_load.built": "Bisher erstellt: {built} von {total} Merkmalen.",
"file_load.converting": "Volumenkörper {done} von {total} wird konvertiert",
@@ -1282,6 +1381,8 @@
"keymap.command_id": "Befehls-ID",
"keymap.empty": "Keine passenden Befehle",
"keymap.use_anyway": "{key} hier trotzdem verwenden",
"label.move_to_left_side": "Auf die linke Seite verschieben",
"label.move_to_right_side": "Auf die rechte Seite verschieben",
"manage.appearance_hint": "Wählen Sie ein Erscheinungsbild für die Auswahl oder ziehen Sie ein Farbmuster auf einen Körper oder eine Fläche.",
"manage.assign_hint": "Wählen Sie Körper und deren Kunststoff-Konstruktionsregel aus.",
"manage.config_hint": "Bearbeiten Sie Konfigurationszeilen, Spalten und Regeln und aktivieren Sie dann eine Zeile oder zeigen Sie deren Vorschau an.",
@@ -1366,7 +1467,9 @@
"nav.free_orbit_upright.help": "Seitliches Ziehen mit der Maus dreht das Modell um die senkrechte Achse der Welt; Ziehen nach oben und unten neigt es ohne Begrenzung über den Pol hinweg.",
"nav.free_orbit_upright.label": "Um die senkrechte Achse drehen",
"nav.fusion.help": "Mittlere Maustaste verschiebt, Umschalt+Mitte dreht, rechte Maustaste dreht",
"nav.hfss.help": "Alt+Linksziehen verschiebt, Umschalt+Alt+Linksziehen zoomt, Strg+Linksziehen auf leerer Fläche dreht",
"nav.inventor.help": "Mittlere Maustaste verschiebt, Umschalt+Mitte dreht, Strg+Mitte zoomt, rechte Maustaste dreht",
"nav.maya.help": "Alt+Linksziehen dreht, Alt+Mitte verschiebt, Alt+Rechtsziehen zoomt; mittleres Ziehen verschiebt ebenfalls",
"nav.openscad.help": "Linksziehen auf leerem Hintergrund dreht, Umschalt+Linksziehen zieht ein Auswahlrechteck auf, Skizzengeometrie wird durch Ziehen bearbeitet; rechtes oder mittleres Ziehen verschiebt, Umschalt+rechtes oder Umschalt+mittleres Ziehen zoomt",
"nav.perspective.sketch": "Beim Bearbeiten einer Skizze wird die orthografische Ansicht verwendet. Beenden Sie die Skizze, um die Perspektive umzuschalten.",
"nav.solidworks.help": "Mittlere Maustaste dreht, Strg+Mitte verschiebt, Umschalt+Mitte zoomt, rechte Maustaste dreht",
@@ -1377,22 +1480,150 @@
"nav.touchpad.pan": "Verschieben (Umschalt halten und bewegen; ohne Maustaste)",
"nav.touchpad.scroll": "Touchpad verwendet vertikales Scrollen zum Zoomen. Die Zwei-Finger-Verschiebung bleibt für andere Vorgaben gespeichert.",
"nav.touchpad.zoom": "Zoom (vertikal scrollen oder Finger spreizen/zusammenziehen)",
"navbar.agent_chat": "Chat-Bereich des Assistenten",
"navbar.agent_cursor": "Agentencursor zeigen",
"navbar.ambient_occlusion": "Umgebungsverdeckung",
"navbar.assistant": "Assistent",
"navbar.custom.add_slot": "{slot} hinzufügen",
"navbar.custom.always": "Immer sichtbar",
"navbar.custom.available": "{available} · auf die Leiste ziehen oder auf Hinzufügen klicken",
"navbar.custom.buttons": "Schaltflächen",
"navbar.custom.compact": "Kompakt",
"navbar.custom.count": "{count} von 16 Feldern",
"navbar.custom.customise": "Navigationsleiste anpassen…",
"navbar.custom.design": "Entwurf",
"navbar.custom.duplicate": "Dieses Feld ist bereits in der Leiste.",
"navbar.custom.fade": "Abblenden",
"navbar.custom.full": "Entfernen Sie ein Feld, um ein weiteres hinzuzufügen.",
"navbar.custom.hidden_design": "Im Entwurf ausgeblendet",
"navbar.custom.hidden_render": "Im Rendern ausgeblendet",
"navbar.custom.hide": "Navigationsleiste ausblenden",
"navbar.custom.hide_idle": "Ausblenden, bis die Maus darüber ist",
"navbar.custom.icon_only": "Nur Symbol",
"navbar.custom.icon_value": "Symbol und Wert",
"navbar.custom.icons": "Symbole",
"navbar.custom.idle": "Bei Inaktivität",
"navbar.custom.intro": "Wählen Sie die Bedienelemente der Leiste am unteren Rand der 3D-Ansicht und ihre Reihenfolge. Ziehen Sie ein Feld, um es zu verschieben, oder aus der Leiste heraus, um es zu entfernen.",
"navbar.custom.labels": "Symbole und Beschriftungen",
"navbar.custom.left": "Nach links",
"navbar.custom.position": "Position",
"navbar.custom.position_centre": "Mitte",
"navbar.custom.position_left": "Links",
"navbar.custom.position_right": "Rechts",
"navbar.custom.preview_as": "Vorschau als",
"navbar.custom.regular": "Normal",
"navbar.custom.remove": "Entfernen",
"navbar.custom.remove_bar": "Aus der Leiste entfernen",
"navbar.custom.render": "Rendern",
"navbar.custom.reset": "Navigationsleiste zurücksetzen",
"navbar.custom.reset_default": "Auf Standard zurücksetzen",
"navbar.custom.right": "Nach rechts",
"navbar.custom.select": "Kein Feld ausgewählt. Wählen Sie ein Feld in der Leiste, um es zu verschieben, zu entfernen oder sein Aussehen zu ändern.",
"navbar.custom.separators_full": "Die Leiste hat bereits vier Trennlinien.",
"navbar.custom.show": "Navigationsleiste anzeigen",
"navbar.custom.shows": "Zeigt",
"navbar.custom.size": "Größe",
"navbar.custom.stale": "Die Leiste hat sich geändert. Wählen Sie das Feld erneut aus.",
"navbar.custom.title": "Navigationsleiste",
"navbar.custom.unknown": "Dieses Feld ist nicht verfügbar.",
"navbar.description.ambient_occlusion": "Dunkelt Falten und Ecken ab und erzeugt Tiefe.",
"navbar.description.display": "Enthält die Ansichtseinstellungen: Grafikvoreinstellung, Raster, Bodenschatten, Umgebungsverdeckung und Projektion.",
"navbar.description.fit": "Zeigt die Auswahl formatfüllend, oder das ganze Modell, wenn nichts ausgewählt ist.",
"navbar.description.grid": "Zeigt oder verbirgt das Bodenraster.",
"navbar.description.ground_shadow": "Zeigt oder verbirgt den Schatten unter dem Modell.",
"navbar.description.home": "Kehrt zur isometrischen Ansicht des ganzen Modells zurück.",
"navbar.description.look_at": "Dreht die Ansicht zur gewählten Fläche, Ebene oder offenen Skizze.",
"navbar.description.orbit": "Dreht die Ansicht um das Modell.",
"navbar.description.pan": "Verschiebt die Ansicht seitwärts, nach oben oder unten.",
"navbar.description.projection": "Schaltet zwischen orthografischer und perspektivischer Ansicht um.",
"navbar.description.separator": "Eine dünne Linie, die benachbarte Felder gruppiert.",
"navbar.description.spin": "Dreht die Ansicht weiter, bis Sie klicken oder eine Taste drücken.",
"navbar.description.visual_style": "Schaltet um, wie das Modell gezeichnet wird: schattiert, Drahtmodell oder mit verdeckten Kanten.",
"navbar.description.zoom": "Bringt die Ansicht näher an das Modell heran oder weiter davon weg.",
"navbar.display": "Anzeige",
"navbar.fit": "Einpassen",
"navbar.graphics": "Grafik",
"navbar.grid": "Raster",
"navbar.ground_shadow": "Bodenschatten",
"navbar.home": "Start",
"navbar.later": "Später",
"navbar.look_at": "Ansehen",
"navbar.more": "Mehr",
"navbar.orbit": "Drehen",
"navbar.orthographic": "Orthografisch",
"navbar.pan": "Verschieben",
"navbar.perspective": "Perspektivisch",
"navbar.preset": "Voreinstellung",
"navbar.projection": "Projektion",
"navbar.projection_heading": "Projektion",
"navbar.separator": "Trennlinie",
"navbar.show": "Einblenden",
"navbar.spin": "Dauerdrehung",
"navbar.style.shaded": "Schattiert",
"navbar.style.shaded_with_edges": "Schattiert mit Kanten",
"navbar.style.shaded_with_hidden_edges": "Schattiert mit verdeckten Kanten",
"navbar.style.wireframe": "Drahtmodell",
"navbar.translucent": "Durchscheinend",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "Darstellung",
"navbar.zoom": "Zoomen",
"needs two joints": "benötigt zwei Gelenke",
"new configuration": "neue Konfiguration",
"new parameter": "new parameter",
"no hole": "keine Bohrung",
"no interference": "keine Überschneidung",
"no joint that moves yet": "noch kein Gelenk, das sich bewegt",
"no motion study yet": "noch keine Bewegungsuntersuchung",
"no picture": "kein Bild",
"no such joint": "kein solches Gelenk",
"none": "keine",
"not a move": "keine Verschiebung",
"not a number": "keine Zahl",
"open a sketch first": "zuerst eine Skizze öffnen",
"parts.automatic_name": "automatisch",
"parts.dimension.across_flats": "Schlüsselweite",
"parts.dimension.bore": "Bohrung",
"parts.dimension.d": "Nenndurchmesser",
"parts.dimension.head_diameter": "Kopfdurchmesser",
"parts.dimension.head_height": "Kopfhöhe",
"parts.dimension.height": "Höhe",
"parts.dimension.inner": "Innendurchmesser",
"parts.dimension.outer": "Außendurchmesser",
"parts.dimension.pitch": "Steigung",
"parts.dimension.socket": "Innensechskant",
"parts.dimension.socket_depth": "Sechskanttiefe",
"parts.dimension.thickness": "Dicke",
"parts.dimension.width": "Breite",
"parts.family.bearing": "Rillenkugellager (Hüllform)",
"parts.family.dowel_pin": "Zylinderstift",
"parts.family.hex_bolt": "Sechskantschraube",
"parts.family.hex_nut": "Sechskantmutter",
"parts.family.set_screw": "Gewindestift mit Innensechskant und Kegelstumpf",
"parts.family.socket_head_cap_screw": "Zylinderschraube mit Innensechskant",
"parts.family.washer": "Unterlegscheibe",
"pattern.alignment_2": "Ausrichtung 2",
"pattern.alignment_hint": "Die Anzahl enthält das Original. Die zentrierte Anordnung verteilt Kopien auf beide Seiten; bei gerader Anzahl legt die Richtungsumkehr die Seite mit der zusätzlichen Kopie fest.",
"pattern.direction_1": "Richtung 1",
"pattern.direction_2": "Richtung 2",
"pattern.flip_direction": "Richtung umkehren",
"pick a body or some of its faces": "einen Körper oder einige seiner Flächen wählen",
"pick a hole to seat it, or OK places it at the origin": "Wählen Sie eine Bohrung zum Einsetzen, oder OK platziert es im Ursprung",
"pick a planar face": "eine ebene Fläche wählen",
"pick a plane or a face as the tool": "eine Ebene oder eine Fläche als Werkzeug wählen",
"pick a size": "eine Größe wählen",
"pick edges of a body": "Kanten eines Körpers wählen",
"pick edges of one body": "Kanten eines einzigen Körpers wählen",
"pick edges of the holes to remove": "die Kanten der zu entfernenden Bohrungen wählen",
"pick faces of one body": "Flächen eines einzigen Körpers wählen",
"pick faces to offset": "zu versetzende Flächen wählen",
"pick lines of one sketch": "Linien einer einzigen Skizze wählen",
"pick one or two vertices, edges or faces": "Wählen Sie ein oder zwei Ecken, Kanten oder Flächen",
"pick one plane or face as the tool, or sketch curves": "eine Ebene oder Fläche als Werkzeug wählen, oder Skizzenkurven",
"pick sections in two or more sketches": "Querschnitte in zwei oder mehr Skizzen wählen",
"pick sketch curves or edges": "Skizzenkurven oder Kanten wählen",
"pick the face to untrim": "die Fläche wählen, deren Trimmung aufgehoben werden soll",
"pick what to keep": "wählen, was behalten werden soll",
"pick what to keep of the other surface": "wählen, was vom anderen Flächenkörper behalten werden soll",
"prefs.bodies_folders": "Körperordner",
"prefs.bodies_folders_always": "Immer",
"prefs.bodies_folders_never": "Nie",
@@ -1445,11 +1676,70 @@
"render.cpu_budget_studio": "Studio (große Bilder)",
"render.cpu_budget_triangles": "Dreiecksobergrenze",
"render.cpu_budget_workstation": "Workstation (komplexe Szenen)",
"render.emitted_axis": "Abstrahlachse",
"render.error_area_samples": "area_samples muss 1, 4, 16 oder 64 sein",
"render.error_binding_allocation": "Materialzuordnung konnte nicht reserviert werden",
"render.error_body_bound": "Produktvorschau überschreitet die Grenze erfasster Körper",
"render.error_checkpoint_dimensions": "Checkpoint-Abmessungen weichen von der erfassten Anfrage ab",
"render.error_decode_budget": "Überlauf des Bilddekodierungsbudgets",
"render.error_denoise_setting": "Ungültige native Entrauschungseinstellung",
"render.error_display_dimensions": "Ungültige Bildanzeigeabmessungen",
"render.error_display_fit": "Bildanzeige passt nicht auf dieses Gerät",
"render.error_display_height": "Überlauf der Anzeigehöhe",
"render.error_display_width": "Überlauf der Anzeigebreite",
"render.error_duplicate_face": "Doppelte Produktflächendarstellung",
"render.error_export_document": "Das Render-Exportdokument wurde während der Zielauswahl geändert",
"render.error_face_cap": "Produktvorschau überschreitet die Grenze für Flächendarstellungen",
"render.error_finish_gesture": "Modellierungsgeste vor der Vorschau abschließen",
"render.error_finish_operation": "Aktuellen Modellierungsvorgang vor Render abschließen",
"render.error_fixed_preview": "Feste Studiovorschau benötigt Belichtung 0, Umgebungsdrehung 0 und Intensität 1",
"render.error_geometry_size": "Überlauf der Produktgeometriegröße",
"render.error_glass_recipe": "Unbekanntes Glasrezept",
"render.error_gpu_preview": "GPU-Produktvorschau ist auf diesem Host nicht verfügbar. Gespeicherte Setups bleiben verfügbar.",
"render.error_gpu_samples": "Nicht unterstützte GPU-Sampleanzahl",
"render.error_image_dimensions": "Renderbildabmessungen stimmen nicht mit dem Auftrag überein",
"render.error_image_profile": "Renderbild überschreitet das erfasste Ressourcenprofil",
"render.error_interactive_command": "Nicht zugeordneter interaktiver Renderbefehl",
"render.error_job_action": "Keine interaktive Bildauftragsaktion",
"render.error_job_identity": "Ungültige Renderauftragskennung: {error}",
"render.error_library_reply": "Ungültige Render-Bibliotheksantwort",
"render.error_material_binding": "Materialzuordnung fehlt",
"render.error_no_completed_image": "Kein fertiges Renderbild vorhanden",
"render.error_no_geometry": "Keine Produktgeometrie",
"render.error_no_scene": "Keine Produktszene",
"render.error_opacity": "Ungültige Deckkraft der Produktdarstellung",
"render.error_pbr_opacity": "Undurchsichtiges PBR benötigt Deckkraft 1",
"render.error_physical_glass": "Das gewählte Rezept ist kein physikalisches Glas",
"render.error_preview_device": "Produktvorschau benötigt ein Gerät mit Tiefenpuffer",
"render.error_product_triangle": "Ungültiges Produktdreieck",
"render.error_provisional_identity": "Ungültige vorläufige Renderkennung oder Sampleanzahl",
"render.error_quality_bounds": "Qualitätsübertragung überschreitet native Grenzen",
"render.error_quality_method": "Qualitätsübertragung benötigt dieselbe explizite GPU-Methode",
"render.error_quality_projection": "Ungültige native Qualitätsübertragung",
"render.error_regrade_identity": "Ungültige Nachbearbeitungskennung: {error}",
"render.error_scene_bodies": "Körper der Renderszene fehlen",
"render.error_scene_body_limit": "Renderszene überschreitet ihre Körpergrenze",
"render.error_scene_identity": "Ungültige Renderszenenkennung",
"render.error_setup_panicked": "GPU-Pfadverfolgung konnte nicht initialisiert werden",
"render.error_setup_stopped": "Initialisierung ohne Host beendet",
"render.error_setup_worker": "Initialisierung konnte nicht gestartet werden: {error}",
"render.error_source_preview": "Quellvorschau überschreitet ihr Datenlimit",
"render.error_surface_normals": "PBR benötigt Oberflächennormalen ungleich null",
"render.error_surface_reply": "Ungültige Antwort der erstellten Oberfläche",
"render.error_triangle_bound": "Produktvorschau überschreitet acht Millionen Quelldreiecke",
"render.error_triangle_count": "Überlauf der Produktdreiecksanzahl",
"render.error_upload_slot": "Upload-Platz für Produktvorschau nicht verfügbar",
"render.error_vertex_allocation": "Scheitelpunktspeicher für Produktvorschau konnte nicht reserviert werden",
"render.error_vertex_envelope": "Produktvorschau überschreitet {limit} MiB Scheitelpunktdaten; Geometrie wurde nicht vereinfacht",
"render.error_vertex_packing": "Produktvorschau stimmt nicht mit den zugelassenen Scheitelpunktdaten überein",
"render.error_visible_solid": "In Design einen sichtbaren Volumenkörper erstellen, um ihn hier anzuzeigen.",
"render.exit_focus": "Fokus beenden",
"render.export_image_label": "Bild exportieren",
"render.exr_pending": "Die GPU kann rohe lineare EXR-Dateien behalten. Kompression, mehrschichtige Bilder und zusätzliche Renderpässe bleiben nicht verfügbar.",
"render.fit": "Produkt einpassen",
"render.fixed_camera": "Kamera",
"render.fixed_world": "Welt",
"render.fold_browser": "Browser einklappen",
"render.heading_batch": "Stapel",
"render.heading_frame": "Bildrahmen",
"render.heading_lens": "Objektiv",
@@ -1479,7 +1769,9 @@
"render.image_use_largest": "Größte Größe mit diesem Seitenverhältnis verwenden:",
"render.image_width": "Breite",
"render.include_rig_cards": "Include passive cards and flags",
"render.inner_half_angle": "Innerer Halbwinkel",
"render.inspector": "Inspektor",
"render.layer_off_suffix": " (aus)",
"render.library_applied": "Ressourcenvariante angewendet. Vollständigen Renderauftrag vor dem Start prüfen.",
"render.library_apply_hdr": "Mit dieser HDR-Umgebung speichern",
"render.library_apply_maps": "Erstellte GPU-Oberflächenmaps verwenden",
@@ -1525,6 +1817,7 @@
"render.navigation_help": "Die Kamera bewegt sich wie im Konstruieren (Einstellungen › Navigation). Setup speichern übernimmt die aktuelle Kamera.",
"render.opaque_image_summary": "Vorschau-PNG · opakes PBR · Transparenz durch Blending",
"render.opaque_preview_help": "Opakes PBR und einfache Farben; Transparenz durch Blending. Brechung, HDRI und finales Rendering sind noch nicht verfügbar.",
"render.outer_half_angle": "Äußerer Halbwinkel",
"render.output_format_status": "PNG enthält das exakte fertige Anzeigebild. Optionales GPU-EXR bewahrt rohe lineare FLOAT32-Strahldichte vor Filtern. Export ersetzt nie durch Vorschaucache oder anderen Auftrag.",
"render.output_tools_inspector": "Größe und Format im Ausgabe-Inspektor bearbeiten.",
"render.paint_label": "Aufmalen",
@@ -1540,18 +1833,28 @@
"render.physical_prepare_plan": "Prepare creation plan (does not apply)",
"render.physical_separate": "Appearance is not material identification. These are sourced references, not certified effective properties. Existing mass, engineering materials and optics are unchanged.",
"render.physical_unknown": "No numerical candidate is established. Grade, formulation or construction must be specified; unknown is not zero.",
"render.pick_body": "Körper",
"render.pick_component": "Komponente",
"render.pick_face": "Fläche",
"render.pick_help": "Körper, Fläche oder Komponente wählen. Ein Klick ins Leere löscht die Auswahl; Umschalt oder Strg fügt hinzu oder schaltet um. Hervorhebungen erscheinen nur in der Live-Produktansicht.",
"render.pick_label": "Auswahl",
"render.pick_up_label": "Aufnehmen",
"render.pick_waiting": "Die Produktauswahl wird noch nicht unterstützt.",
"render.preview": "Integrierte Vorschau",
"render.preview_help": "Rasterdarstellung mit gemischter Transparenz. Brechung, HDRI und finales Rendering sind noch nicht verfügbar.",
"render.preview_lighting_help": "Die Live-Vorschau zeigt nur direktes Licht und keine Schatten.",
"render.property_conditions": "Bedingungen: {value}",
"render.property_fallback": "Eigenschaft",
"render.property_qualifier": "Qualifikator: {value}",
"render.property_source": "Quelle: {id} - {locator}",
"render.property_uncertainty": "Unsicherheit: {value}",
"render.property_unknown": "unbekannt",
"render.regrade_label": "Neu abstimmen",
"render.reload_settings": "Gespeicherte Einstellungen laden",
"render.replace_label": "Ersetzen",
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.restore_camera": "Gespeicherte Kamera laden",
"render.result_actual_size": "100%",
"render.result_reduced_display": "Anzeigevorschau auf die Geräte-/Cachegrenze reduziert. PNG und Export behalten die volle Auflösung; native 100%-Ansicht ist hier nicht verfügbar.",
"render.return_design": "Zurück zu Design",
"render.ribbon_backgrounds": "Hintergründe",
@@ -1586,6 +1889,10 @@
"render.shell_tab_camera": "Kamera",
"render.shell_tab_scene": "SZENE",
"render.show_shots_label": "Aufnahmenleiste einblenden",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.spot_cone": "Spotkegel",
"render.stage_frame": "Bildausschnitt",
"render.stage_light": "Licht",
"render.stage_look": "Aussehen",
@@ -1594,6 +1901,42 @@
"render.stage_panel_count": "Saved panels",
"render.stage_preview_note": "Integrierte Vorschau · direktes Licht",
"render.strip_label": "Leiste",
"render.tone_aces_fitted": "ACES angepasst",
"render.tone_reinhard": "Reinhard",
"render.tree_add_light": "Licht hinzufügen",
"render.tree_add_shot": "Aufnahme hinzufügen",
"render.tree_browser": "Render-Browser",
"render.tree_by_look": "Nach Aussehen",
"render.tree_by_object": "Nach Objekt",
"render.tree_constant": "Konstante Umgebung",
"render.tree_default": "Standard",
"render.tree_directional": "Gerichtet",
"render.tree_environment": "Umgebung",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} Flächen",
"render.tree_face_one": "{count} Fläche",
"render.tree_fixed_studio": "Festes Studio",
"render.tree_hdr": "HDR",
"render.tree_lights": "Lichter",
"render.tree_lights_pending": "Befehle für benannte Lichter sind noch nicht verfügbar.",
"render.tree_mixed": "Gemischt",
"render.tree_more": "{count} weitere",
"render.tree_mute": "Licht stummschalten",
"render.tree_no_environment": "Keine Umgebung",
"render.tree_objects": "Objekte",
"render.tree_output": "Ausgabe",
"render.tree_point": "Punkt",
"render.tree_rectangle": "Rechteck",
"render.tree_search": "Objekte suchen",
"render.tree_selection": "Render-Auswahl",
"render.tree_shots": "Aufnahmen",
"render.tree_sky": "Himmel",
"render.tree_solo": "Licht solo schalten",
"render.tree_spot": "Spot",
"render.tree_sun": "Sonne",
"render.tree_switch": "Wechseln",
"render.tree_user_one": "{count} Objekt",
"render.tree_users": "{count} Objekte",
"render.unavailable_preview": "Dieses Setup verlangt ein nicht verfügbares Vorschauprofil.",
"render.unsaved": "Ungespeicherte Vorschauänderungen",
"render.use_preview": "Integrierte Vorschau verwenden",
@@ -1628,6 +1971,26 @@
"search.suggest": "Meinten Sie {label}?",
"search.try": "Geben Sie einen Befehlsnamen, ein Merkmal in diesem Design oder einen Parameter ein. Um einen Befehl mit Werten auszuführen, geben Sie seine ID und ein JSON-Objekt ein: {example}",
"search.valid": "Gültig",
"select a direction (an axis, a sketch line or a straight edge) first": "zuerst eine Richtung auswählen (eine Achse, eine Skizzenlinie oder eine gerade Kante)",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "eine Richtung auswählen (eine Achse, eine Skizzenlinie oder eine gerade Kante), der das Profil folgen soll",
"select a point on a component": "einen Punkt auf einer Komponente auswählen",
"select a profile, edges or sketch lines first": "zuerst ein Profil, Kanten oder Skizzenlinien auswählen",
"select an axis": "eine Achse auswählen",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "zuerst eine Achse, eine gerade oder kreisförmige Kante oder eine Zylinder-, Kegel- oder Torusfläche auswählen",
"select bodies first": "zuerst Körper auswählen",
"select corner points, or the two lines of one corner": "Eckpunkte oder die zwei Linien einer Ecke auswählen",
"select one corner point, or the two lines of one corner": "einen Eckpunkt oder die zwei Linien einer Ecke auswählen",
"select sheet edges first": "zuerst Blechkanten auswählen",
"select the bend line (a sketch line) first": "zuerst die Biegelinie (eine Skizzenlinie) auswählen",
"select the cam's profile (a sketch profile or the cam's edges)": "das Profil des Nockens auswählen (ein Skizzenprofil oder die Kanten des Nockens)",
"select the corner to cut first": "zuerst die abzuschrägende Ecke auswählen",
"select the corners to round first": "zuerst die zu verrundenden Ecken auswählen",
"select the fixed face first (a plate's large face)": "zuerst die feste Fläche auswählen (die große Fläche einer Platte)",
"select the frame sketch's lines first": "zuerst die Linien der Rahmenskizze auswählen",
"select the path (sketch lines across the edge)": "den Pfad auswählen (Skizzenlinien, die die Kante überqueren)",
"select the rim face first": "zuerst die Randfläche auswählen",
"select the sheet edge first": "zuerst die Blechkante auswählen",
"select two components": "zwei Komponenten auswählen",
"settings.display_quality_note": "Feinere Stufen zeigen gekrümmte Flächen und Kanten glatter und brauchen länger zum Vernetzen. Nur die Ansicht ändert sich, nie das Design oder Exporte.",
"settings.frame_rate_note": "Zeigt die Bilder pro Sekunde unten rechts in der Ansicht.",
"settings.measure_axis_distances": "X/Y/Z-Maße anzeigen",
@@ -1640,16 +2003,22 @@
"settings.reset_intro": "Diese Einstellungen funktionieren auf diesem Computer nicht und würden den Start von SolidCraft verhindern. Sie wurden daher geändert:",
"settings.reset_title": "Einstellungen wurden geändert",
"settings.supersampling_note": "Zeichnet die Ansicht in höherer Auflösung und rechnet sie herunter: glattere Kanten, Linien und Raster auf Bildschirmen unter 4K. Kostet GPU-Zeit: etwa 2,25-mal so viele Pixel bei 1,5× und 4-mal bei 2×.",
"sheet.flange_type_base": "Basislasche",
"sheet.flange_type_contour": "Konturlasche",
"sheet.flange_type_edge": "Kantenlasche",
"shortcut.json_error": "Parameter müssen JSON sein: {error}",
"shortcut.no_command": "kein Befehl `{id}`; der Text vor dem JSON muss eine Befehls-ID sein",
"shortcut.pin": "Oben im S-Feld anheften",
"shortcut.unpin": "Loslösen",
"sketch is missing": "die Skizze fehlt",
"sketch.degrees_of_freedom": "{count} Freiheitsgrade",
"sketch.dof_left": "{count} Freiheitsgrade übrig",
"sketch.dof_left_one": "{count} Freiheitsgrad übrig",
"sketch.draw_curves": "Als {linetype} zeichnen",
"sketch.make_selection": "Auswahl als {linetype} markieren",
"sketch.open_ends": "Offen {count}",
"sketch.status_conflict": "Bedingungen widersprechen sich",
"sketch.status_fully_constrained": "vollständig bestimmt",
"sketch.untied_ends": "Unverknüpft {count}",
"sketch_panel.attached": "Angehängt an {body} / {path}",
"sketch_panel.author": "Autorenplatzierung: {path}",
@@ -1671,7 +2040,24 @@
"sketch_text.path_hint": "Eine Skizzenkurve, der der Text folgt: hier klicken, dann die Kurve",
"sketch_text.use_font_file": "Schriftdatei {path} verwenden",
"solid": "Volumenkörper",
"the angle must be a number": "der Winkel muss eine Zahl sein",
"the curves must be in one sketch": "die Kurven müssen in einer Skizze liegen",
"the direction must be an axis, a sketch line or a straight edge": "die Richtung muss eine Achse, eine Skizzenlinie oder eine gerade Kante sein",
"the duration must be a number of seconds, 0.001 or more": "die Dauer muss eine Zahl in Sekunden sein, mindestens 0.001",
"the line's sketch is gone": "die Skizze der Linie existiert nicht mehr",
"the lines must be in one sketch": "die Linien müssen in einer Skizze liegen",
"the lines must be in one sketch, not the section's": "die Linien müssen in einer Skizze liegen, nicht in der des Querschnitts",
"the parts library is empty": "die Bauteilbibliothek ist leer",
"the parts library is not available": "Die Teilebibliothek ist nicht verfügbar",
"the path curves must be in one other sketch": "die Pfadkurven müssen in einer einzigen anderen Skizze liegen",
"the path's sketch is gone": "die Skizze des Pfads existiert nicht mehr",
"the position must be a number": "die Position muss eine Zahl sein",
"the preview failed": "die Vorschau ist fehlgeschlagen",
"the profiles and curves must be in one sketch": "die Profile und Kurven müssen in einer Skizze liegen",
"the reference face must be on the edges' body": "die Referenzfläche muss auf dem Körper der Kanten liegen",
"the scale must be above 0": "der Maßstab muss größer als 0 sein",
"the section's profiles must be in one sketch": "die Profile des Querschnitts müssen in einer Skizze liegen",
"the two origins are on the same component": "die beiden Ursprünge liegen auf derselben Komponente",
"thread.automatic_size": "Automatische Größe",
"thread.designation": "Bezeichnung",
"thread.iso_metric": "ISO metrisch",
@@ -1702,6 +2088,7 @@
"trace.points": "{count} Punkte entlang der Bahn",
"trace.stopped_by_contact": "Endet bei Probe {sample}: {a} würde {b} durchdringen",
"trace.stopped_by_loop": "Endet bei Probe {sample}: die Schleife über {joint} lässt sich nicht weiter schließen",
"trim by sketch curves, or by one plane or face": "mit Skizzenkurven oder mit einer Ebene oder Fläche trimmen",
"ui.1_degree_of_freedom": "1 Freiheitsgrad",
"ui.3d_mouse_axes_reassigned": "Die Achsen sind in den Einstellungen neu zugeordnet, und das gilt auch nach dieser Kalibrierung.",
"ui.3d_mouse_button": "Taste {number}",
@@ -2126,6 +2513,8 @@
"ui.design_properties.revision": "Revision",
"ui.diameter": "Durchmesser",
"ui.dimension": "Maß",
"ui.direct_interaction": "Direkte Bearbeitung",
"ui.direct_interaction_note": "Das Modell direkt in der Ansicht bearbeiten. Eine ebene Fläche oder ein Profil drücken und ziehen: nach oben extrudiert, nach unten in einen Körper schneidet, seitliche Bewegung legt die Schrittweite fest",
"ui.direction": "Richtung",
"ui.display_quality": "Darstellungsqualität",
"ui.display_quality_coarse": "Grob",
@@ -2149,6 +2538,7 @@
"ui.editJointLimits": "Gelenkgrenzen bearbeiten",
"ui.edit_section_analysis": "Querschnittsanalyse bearbeiten",
"ui.ellipse": "Ellipse",
"ui.emboss_wrap_note": "Senkrechte Linienprofile, die einen unterstützten Zylinder berühren, werden automatisch aufgewickelt. Eine Wand auswählen, um ein Ziel festzulegen.",
"ui.end_radius": "Endradius",
"ui.end_scale": "Endskalierung",
"ui.entities": "Elemente",
@@ -2218,6 +2608,7 @@
"ui.heading_extrude": "EXTRUDIEREN",
"ui.heading_fillet": "VOLLRUNDUNG",
"ui.heading_finish_sketch": "SKIZZE BEENDEN",
"ui.heading_form": "FORM",
"ui.heading_front": "VORNE",
"ui.heading_hole": "BOHRUNG",
"ui.heading_home": "START",
@@ -2266,6 +2657,7 @@
"ui.heading_utilities": "WERKZEUGE",
"ui.heading_utility": "HILFSMITTEL",
"ui.heading_weldments": "SCHWEISSTEILE",
"ui.height": "Höhe",
"ui.help": "Hilfe",
"ui.hide": "Ausblenden",
"ui.hideAxes": "Achsen ausblenden",
@@ -2292,11 +2684,14 @@
"ui.intersect": "Schnitt",
"ui.isolate": "Isolieren",
"ui.join": "Verbinden",
"ui.joint_play": "▶ Abspielen",
"ui.joint_stop": "■ Stopp",
"ui.joints": "Gelenke",
"ui.keyboard_shortcuts": "Tastenkürzel",
"ui.language": "Sprache",
"ui.layout_compact": "Kompakt",
"ui.layout_floating": "Schwebend",
"ui.length": "Länge",
"ui.length_decimals": "Längen-Dezimalstellen",
"ui.light": "Hell",
"ui.line": "Linie",
@@ -2308,6 +2703,7 @@
"ui.loft": "Loft",
"ui.look_at": "Ansehen",
"ui.look_at_anim_desc": "Achsenansicht, Ansehen, Home und Einpassen",
"ui.major_radius": "Großer Radius",
"ui.manipulator_free_alt": "Freies Ziehen des Manipulators auch mit Alt/Option",
"ui.manipulator_free_alt_tip": "An: Alt/Option oder Strg/Cmd auf Extrusions-/Gizmo-Pfeilen deaktiviert das Einrasten von Werten. Aus: nur Strg/Cmd.",
"ui.manufacture": "Fertigung",
@@ -2337,8 +2733,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF mit Flächenmarken",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "Kleiner Radius",
"ui.mirror": "Spiegeln",
"ui.mirror_line": "Spiegelachse",
"ui.modifiers_either": "{first} oder {second}",
"ui.move": "Verschieben",
"ui.multiple": "Mehrfach",
"ui.named_views": "Benannte Ansichten",
@@ -2385,6 +2783,7 @@
"ui.pinToShortcuts": "An Verknüpfungen anheften",
"ui.pinToToolbar": "An Symbolleiste anheften",
"ui.pipe": "Rohr",
"ui.pitch": "Steigung",
"ui.placement": "Platzierung",
"ui.plane": "Ebene",
"ui.plane_at_angle": "Ebene im Winkel",
@@ -2440,6 +2839,7 @@
"ui.reverse_horizontal_pan_direction": "Horizontale Schwenkrichtung umkehren",
"ui.reverse_horizontal_pan_tip": "Horizontales Zwei-Finger-Scrollen und das Daumenrad schwenken in die andere Richtung",
"ui.reverse_zoom_direction": "Zoomrichtung umkehren",
"ui.revolutions": "Windungen",
"ui.revolve": "Drehen",
"ui.ribbon_exit": "Beenden",
"ui.ribbon_labels": "Text unter den Symbolen im Menüband anzeigen",
@@ -2455,6 +2855,7 @@
"ui.scale": "Skalieren",
"ui.second_rail": "Zweite Leitkurve",
"ui.section_analysis": "Querschnittsanalyse",
"ui.section_size": "Querschnittsgröße",
"ui.select": "Auswählen",
"ui.selectOther": "Andere auswählen…",
"ui.selectTangentChain": "Tangentialkette auswählen",
@@ -2511,6 +2912,7 @@
"ui.start": "Start",
"ui.start_over": "Von vorn beginnen",
"ui.start_page": "Startseite",
"ui.stitch_tolerance_hint": "eng",
"ui.stretch": "Strecken",
"ui.supersampling": "Supersampling (SSAA)",
"ui.supersampling_adaptive": "Nur bei ruhender Ansicht",
@@ -2541,6 +2943,8 @@
"ui.to_object": "Bis Objekt",
"ui.tool_direction": "Werkzeugrichtung",
"ui.top": "Oben",
"ui.top_diameter": "Oberer Durchmesser",
"ui.top_radius": "Oberer Radius",
"ui.torus": "Torus",
"ui.total_angle": "Gesamtwinkel",
"ui.trackpad_pan_tip": "Scrollen mit zwei Fingern verschiebt die Ansicht; bei Fusion dreht Umschalt + zwei Finger die Ansicht. Aus: Scrollen zoomt. Mausrad und Pinch-Geste zoomen; das Daumenrad verschiebt seitlich.",
@@ -2567,6 +2971,7 @@
"ui.visual_shaded_with_edges": "Schattiert mit Kanten",
"ui.visual_style": "Ansichtsstil",
"ui.visual_wireframe": "Drahtmodell",
"ui.width": "Breite",
"ui.workspace": "Arbeitsbereich",
"ui.workspace_animation_description": "Explosionsansichten, Bewegungsstudien und Storyboards",
"ui.workspace_available": "Verfügbar",
@@ -2623,6 +3028,9 @@
"update.up_to_date": "SolidCraft ist aktuell.",
"update.update_now": "Jetzt aktualisieren",
"update.you_have": "Installiert ist {version}.",
"use a positive nominal diameter and a pitch smaller than it": "einen positiven Nenndurchmesser und eine kleinere Steigung verwenden",
"values must be finite numbers": "Werte müssen endliche Zahlen sein",
"values must be numbers or expressions": "Werte müssen Zahlen oder Ausdrücke sein",
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ auswählen · Eingabe / Tab vervollständigen · Esc schließen",
"⌘Enter continues on GitHub.": "⌘Enter geht weiter zu GitHub."
}
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(active rule)",
"0 turns it off": "0 turns it off",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Open GitHub draft below, then paste the report copied to your clipboard.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Open GitHub draft below. Your title and report will be filled in.",
@@ -51,16 +52,20 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "Apply your appearance first. Exports assigned appearances and materials created in this design.",
"Arc length": "Arc length",
"Area": "Area",
"As Picked": "As Picked",
"As-Built": "As-Built",
"Assign Rule": "Assign Rule",
"Attachment": "Attachment",
"BLEND SURFACE": "BLEND SURFACE",
"BOUNDARY SURFACE": "BOUNDARY SURFACE",
"BROWSER": "BROWSER",
"Ball": "Ball",
"Bar": "Bar",
"Base Center": "Base Center",
"Base Height": "Base Height",
"Bend": "Bend",
"Bend Edges": "Bend Edges",
"Bend Line": "Bend Line",
"Bend Line Position": "Bend Line Position",
"Bend Position": "Bend Position",
"Bend Radius": "Bend Radius",
@@ -72,6 +77,7 @@
"Body (last if none)": "Body (last if none)",
"Body to split": "Body to split",
"Body, or faces to take out": "Body, or faces to take out",
"Both": "Both",
"Bottom Left": "Bottom Left",
"Bottom Middle": "Bottom Middle",
"Bottom Right": "Bottom Right",
@@ -103,6 +109,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.",
"Choose…": "Choose…",
"Circle center": "Circle center",
"Circle or sphere": "Circle or sphere",
"Circular": "Circular",
"Circumference": "Circumference",
"Clockwise": "Clockwise",
@@ -119,6 +126,7 @@
"Config Table": "Config Table",
"Configuration": "Configuration",
"Configuration rules": "Configuration rules",
"Constant radius": "Constant radius",
"Contact": "Contact",
"Contact Sets": "Contact Sets",
"Contact sets": "Contact sets",
@@ -154,7 +162,9 @@
"Custom": "Custom",
"Customize Toolbar": "Customize Toolbar",
"Customize…": "Customize…",
"Cylindrical": "Cylindrical",
"Cylindrical face": "Cylindrical face",
"Deboss": "Deboss",
"Delete": "Delete",
"Delete Folders and Features…": "Delete Folders and Features…",
"Delete Selected Features…": "Delete Selected Features…",
@@ -186,6 +196,7 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.",
"Drive Joint": "Drive Joint",
"Duration": "Duration",
"Edge": "Edge",
"Edges": "Edges",
"Edit": "Edit",
"Edit Profile Sketch": "Edit Profile Sketch",
@@ -194,6 +205,7 @@
"End Radius": "End Radius",
"End bulge": "End bulge",
"End continuity": "End continuity",
"Equal Distance": "Equal Distance",
"Expand": "Expand",
"Expected result (optional)": "Expected result (optional)",
"Explode": "Explode",
@@ -221,6 +233,8 @@
"Faces": "Faces",
"Faces / edges / vertices": "Faces / edges / vertices",
"Faces to split": "Faces to split",
"Faces/Body": "Faces/Body",
"Factor must be a positive number": "Factor must be a positive number",
"Fastener": "Fastener",
"Favorites": "Favorites",
"Favourite": "Favourite",
@@ -230,9 +244,12 @@
"Filter…": "Filter…",
"Find in Browser": "Find in Browser",
"Finish": "Finish",
"First edge": "First edge",
"First plane": "First plane",
"First point": "First point",
"Fit and G2 corners require Constant radius.": "Fit and G2 corners require Constant radius.",
"Fixed Face": "Fixed Face",
"Flange Gap": "Flange Gap",
"Flange thickness": "Flange thickness",
"Flanges": "Flanges",
"Flat Pattern": "Flat Pattern",
@@ -240,8 +257,10 @@
"Follow camera (Look At sketches)": "Follow camera (Look At sketches)",
"Follow the camera (Look At sketches)": "Follow the camera (Look At sketches)",
"Font": "Font",
"Free Move": "Free Move",
"From": "From",
"From Bodies": "From Bodies",
"From Snap": "From Snap",
"From edges": "From edges",
"Full Length": "Full Length",
"Full thread depth": "Full thread depth",
@@ -253,10 +272,13 @@
"Halo under sketch curves": "Halo under sketch curves",
"Height": "Height",
"Height From": "Height From",
"Hem Gap": "Hem Gap",
"Hidden edges": "Hidden edges",
"History layout": "History layout",
"History names": "History names",
"Hole (optional)": "Hole (optional)",
"Hole Depth": "Hole Depth",
"Hole Diameter": "Hole Diameter",
"Holes": "Holes",
"Holes (edges on them)": "Holes (edges on them)",
"Home view": "Home view",
@@ -279,12 +301,16 @@
"Issue title": "Issue title",
"Items": "Items",
"JOINTS": "JOINTS",
"Joint 1": "Joint 1",
"Joint 2": "Joint 2",
"Joint Origin1": "Joint Origin1",
"K Factor": "K Factor",
"Keep (points on it)": "Keep (points on it)",
"Keep Tools": "Keep Tools",
"Keep of the other surface": "Keep of the other surface",
"Key a joint's value at this step": "Key a joint's value at this step",
"Keys": "Keys",
"Knife Edge": "Knife Edge",
"L-Angle": "L-Angle",
"LIBRARY": "LIBRARY",
"LINKS": "LINKS",
@@ -297,9 +323,11 @@
"Letter Spacing": "Letter Spacing",
"Library": "Library",
"Library file": "Library file",
"Library response is missing": "Library response is missing",
"Limits": "Limits",
"Line Spacing": "Line Spacing",
"Line Type": "Line Type",
"Line on plane": "Line on plane",
"Lines": "Lines",
"Listing the installed fonts…": "Listing the installed fonts…",
"Load library": "Load library",
@@ -319,11 +347,14 @@
"Material Outside": "Material Outside",
"Material copied. Existing body assignments are unchanged.": "Material copied. Existing body assignments are unchanged.",
"Max": "Max",
"Max Thickness": "Max Thickness",
"Maximum": "Maximum",
"Mesh body": "Mesh body",
"Mid Radius": "Mid Radius",
"Middle double-click": "Middle double-click",
"Min": "Min",
"Min Draft": "Min Draft",
"Min Thickness": "Min Thickness",
"Minimum": "Minimum",
"Mirror Plane": "Mirror Plane",
"Mitre": "Mitre",
@@ -343,6 +374,7 @@
"Name": "Name",
"Name on import": "Name on import",
"Nearest": "Nearest",
"Neutral plane": "Neutral plane",
"New": "New",
"New Comp.": "New Comp.",
"New Sketch": "New Sketch",
@@ -353,6 +385,7 @@
"No matching appearances": "No matching appearances",
"No matching physical materials.": "No matching physical materials.",
"No visible bodies or sketches to export.": "No visible bodies or sketches to export.",
"Nominal Radius": "Nominal Radius",
"Nominal diameter": "Nominal diameter",
"None": "None",
"Not available yet": "Not available yet",
@@ -381,22 +414,28 @@
"Overall length": "Overall length",
"Param. Graph": "Param. Graph",
"Parameter": "Parameter",
"Part length must be greater than zero and at most 2000 mm": "Part length must be greater than zero and at most 2000 mm",
"Parts": "Parts",
"Pass through": "Pass through",
"Path": "Path",
"Pattern": "Pattern",
"Per Edge": "Per Edge",
"Physical material definitions": "Physical material definitions",
"Pick a part size": "Pick a part size",
"Pick the tool bodies": "Pick the tool bodies",
"Picked": "Picked",
"Picked point": "Picked point",
"Pin-slot": "Pin-slot",
"Pitch": "Pitch",
"Pivot": "Pivot",
"Place at the origin instead": "Place at the origin instead",
"Planar": "Planar",
"Plastic Rules": "Plastic Rules",
"Play the joint's motion in the view": "Play the joint's motion in the view",
"Playback": "Playback",
"Plot": "Plot",
"Point on line": "Point on line",
"Point on plane": "Point on plane",
"Position": "Position",
"Position (0 to 1)": "Position (0 to 1)",
"Position (G0)": "Position (G0)",
@@ -409,6 +448,7 @@
"Profiles or curves": "Profiles or curves",
"Profiles/Curves": "Profiles/Curves",
"Quantity": "Quantity",
"Quantity must be at least 2": "Quantity must be at least 2",
"RECENT": "RECENT",
"REFERENCE": "REFERENCE",
"RULED SURFACE": "RULED SURFACE",
@@ -422,6 +462,8 @@
"Rectangular": "Rectangular",
"Rectangular Tube": "Rectangular Tube",
"Reference face": "Reference face",
"Relief Depth": "Relief Depth",
"Relief Width": "Relief Width",
"Remove Tools": "Remove Tools",
"Remove condition": "Remove condition",
"Remove from Folder": "Remove from Folder",
@@ -450,6 +492,7 @@
"Restore this studio's tools": "Restore this studio's tools",
"Result": "Result",
"Retake screenshot": "Retake screenshot",
"Reveal Height": "Reveal Height",
"Reverse": "Reverse",
"Reverse Direction": "Reverse Direction",
"Revert": "Revert",
@@ -458,12 +501,15 @@
"Revert Position": "Revert Position",
"Review the report and screenshot before opening GitHub.": "Review the report and screenshot before opening GitHub.",
"Review your report on GitHub and click Submit new issue to publish it.": "Review your report on GitHub and click Submit new issue to publish it.",
"Revolute": "Revolute",
"Rib Length": "Rib Length",
"Rib Offset": "Rib Offset",
"Rib Thickness": "Rib Thickness",
"Ribs": "Ribs",
"Right Middle": "Right Middle",
"Rigid": "Rigid",
"Rim Edge": "Rim Edge",
"Rim face": "Rim face",
"Ring of tools on the right button": "Ring of tools on the right button",
"Roll Back Here": "Roll Back Here",
"Roll History Marker Here": "Roll History Marker Here",
@@ -488,16 +534,28 @@
"Search": "Search",
"Search commands": "Search commands",
"Search this library": "Search this library",
"Second edge": "Second edge",
"Second plane": "Second plane",
"Second point": "Second point",
"Section": "Section",
"Section (optional)": "Section (optional)",
"Section position": "Section position",
"Sections (one sketch each)": "Sections (one sketch each)",
"Select Other": "Select Other",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).",
"Select Same Look": "Select Same Look",
"Select bodies (a face picks its body)": "Select bodies (a face picks its body)",
"Select bodies or faces instead": "Select bodies or faces instead",
"Select edges": "Select edges",
"Select points of the sketch being edited": "Select points of the sketch being edited",
"Select the centre the pattern turns around first": "Select the centre the pattern turns around first",
"Select the curves to offset first": "Select the curves to offset first",
"Select the mirror line": "Select the mirror line",
"Select the sketch curves or points to mirror first": "Select the sketch curves or points to mirror first",
"Select the sketch curves or points to move first": "Select the sketch curves or points to move first",
"Select the sketch curves or points to pattern first": "Select the sketch curves or points to pattern first",
"Select the sketch curves or points to scale first": "Select the sketch curves or points to scale first",
"Select the sketch curves or points to transform first": "Select the sketch curves or points to transform first",
"Selection filter": "Selection filter",
"Semantic faces share their appearance across instances.": "Semantic faces share their appearance across instances.",
"Send your report on GitHub": "Send your report on GitHub",
@@ -517,9 +575,12 @@
"Sketch geometry and profiles": "Sketch geometry and profiles",
"Sketch plane has no body-face attachment.": "Sketch plane has no body-face attachment.",
"Sketch points": "Sketch points",
"Slider": "Slider",
"Slot width": "Slot width",
"Snap to face and edge centres": "Snap to face and edge centres",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft closed before these designs were saved. Their last autosave can be opened.",
"Spacing 2 must be a non-zero number": "Spacing 2 must be a non-zero number",
"Spacing must be a non-zero number": "Spacing must be a non-zero number",
"Specialise": "Specialise",
"Speed": "Speed",
"Splitting tool": "Splitting tool",
@@ -530,6 +591,7 @@
"Start angle": "Start angle",
"Start bulge": "Start bulge",
"Start continuity": "Start continuity",
"Stationary Side": "Stationary Side",
"Step": "Step",
"Steps": "Steps",
"Steps to reproduce (optional)": "Steps to reproduce (optional)",
@@ -544,6 +606,7 @@
"Suppressed": "Suppressed",
"Surface": "Surface",
"Surface, or faces to turn over": "Surface, or faces to turn over",
"Surfaces": "Surfaces",
"Swap Ends": "Swap Ends",
"TRIM": "TRIM",
"Tangent": "Tangent",
@@ -554,24 +617,34 @@
"Tap drill diameter": "Tap drill diameter",
"Target": "Target",
"Target Body": "Target Body",
"Target Face (optional)": "Target Face (optional)",
"Tear": "Tear",
"Technical details": "Technical details",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "The dashed sketch is a saved plane guide. Select a new face to repair the attachment.",
"The design changed. Reopen Change Part Size for the component.": "The design changed. Reopen Change Part Size for the component.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "The direction must be an axis or a straight sketch curve that lies in the sketch plane",
"The mirror line cannot also be mirrored": "The mirror line cannot also be mirrored",
"The mirror line must be a straight curve of this sketch, not an origin axis": "The mirror line must be a straight curve of this sketch, not an origin axis",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "The saved author occurrence is missing. Select a valid author placement before rebinding.",
"Then": "Then",
"These features will be deleted:": "These features will be deleted:",
"These features will fail:": "These features will fail:",
"Thickness Outside": "Thickness Outside",
"Thickness Variation": "Thickness Variation",
"Thin": "Thin",
"Thin Extrude": "Thin Extrude",
"Third plane": "Third plane",
"Third point": "Third point",
"This child is shared. Deleting it removes it from every copy of its parent.": "This child is shared. Deleting it removes it from every copy of its parent.",
"This child is shared. Position changes apply to every copy of its parent.": "This child is shared. Position changes apply to every copy of its parent.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.",
"Thread depth": "Thread depth",
"Thread diameter": "Thread diameter",
"Through point": "Through point",
"To": "To",
"To Offset": "To Offset",
"To Snap": "To Snap",
"To edges": "To edges",
"Toe radius": "Toe radius",
"Tolerance": "Tolerance",
@@ -585,6 +658,7 @@
"Trimming tool (plane, face or curves)": "Trimming tool (plane, face or curves)",
"Turn off section analysis before exporting the view.": "Turn off section analysis before exporting the view.",
"Type": "Type",
"Type a distance or an angle to move by": "Type a distance or an angle to move by",
"UNTRIM": "UNTRIM",
"Unit": "Unit",
"Unsuppress": "Unsuppress",
@@ -629,6 +703,17 @@
"Z angle": "Z angle",
"Z distance": "Z distance",
"Zebra": "Zebra",
"`joint` must be an id or a name": "`joint` must be an id or a name",
"`params` must be an object": "`params` must be an object",
"`values` must be a list": "`values` must be a list",
"a chamfer needs a corner of exactly two lines": "a chamfer needs a corner of exactly two lines",
"a file operation is in progress": "a file operation is in progress",
"a picked curve is no longer in a sketch": "a picked curve is no longer in a sketch",
"a picked curve's sketch has not been solved": "a picked curve's sketch has not been solved",
"a picked edge has no points": "a picked edge has no points",
"a picked edge is gone": "a picked edge is gone",
"a picked edge's body is gone": "a picked edge's body is gone",
"add a key for a joint first": "add a key for a joint first",
"ai.connected_toast": "SolidCraft is now available in {clients}. Restart them to use it (Settings > Assistant).",
"ai.prefs.allow_control": "Let AI agents connect (control channel / MCP)",
"ai.prefs.allow_control_note": "Opens a control channel on this computer only (127.0.0.1, port 27878 or the next free one). A program that connects must also show a secret token that only your user account can read, made fresh at every start. Takes effect the next time SolidCraft starts. Off: nothing listens unless you start SolidCraft with --control.",
@@ -669,6 +754,7 @@
"appearance.pbr_opaque": "Opaque PBR",
"appearance.roughness": "Roughness",
"appearance.surface_response": "Surface response",
"bom.group_children": "Sub-parts in their part's row",
"browser.body_name": "Body{number}",
"browser.calibrate_title": "Calibrate: {name}",
"browser.capture_many": "{count} components were moved but their positions aren't captured.",
@@ -679,6 +765,8 @@
"browser.move_title": "Move: {name}",
"browser.parameters": "Parameters ({count})",
"browser.precision": "Precision: {precision}",
"browser.sketch_attachment_lost": "{name} (attachment lost)",
"browser.sketch_editing": "{name} (editing)",
"browser.sketch_name": "Sketch{number}",
"browser.units": "Units: {units}",
"cam.flat": "Flat face",
@@ -688,7 +776,13 @@
"cam.roller": "Roller",
"cam.roller_pick": "Roller (optional)",
"cam.tip_pick": "Tip (optional)",
"choose a profile": "choose a profile",
"choose the cam's and the follower's joints": "choose the cam's and the follower's joints",
"choose the joints to couple": "choose the joints to couple",
"click a plane or planar face": "click a plane or planar face",
"click sketch curves": "click sketch curves",
"cmd.appearance_assign": "Appearance",
"cmd.appearance_chain": "Appearance Chain",
"cmd.appearance_library": "Appearance Library",
"cmd.appearance_list": "List Appearances",
"cmd.appearance_paint": "Paint Appearance",
@@ -1073,6 +1167,9 @@
"cmd.timeline_roll_to": "Roll History Marker",
"cmd.timeline_rollback": "Move Timeline Marker",
"cmd.timeline_suppress": "Suppress Feature",
"cmd.view.render_browser": "Render Browser",
"cmd.view.render_dock": "Move Render Dock",
"cmd.view.render_focus": "Render Focus View",
"cmd.view_ambient_occlusion": "Ambient Occlusion",
"cmd.view_apply": "Restore Named View",
"cmd.view_back": "Back View",
@@ -1183,6 +1280,8 @@
"dxf.progress.write": "Writing DXF (5/5)",
"dxf.tolerance": "Curve tolerance",
"dxf.tolerance_help": "Visible bodies and shown sketches only. Curves use straight segments. Smaller tolerance gives finer curves and uses more time and memory.",
"each rail's curves must be in one sketch": "each rail's curves must be in one sketch",
"feature computation ended without a result": "feature computation ended without a result",
"file.open.drawing_filter": "Designs, CAD files, meshes and drawings",
"file_load.built": "Built so far: {built} of {total} features.",
"file_load.converting": "Converting solid {done} of {total}",
@@ -1344,6 +1443,8 @@
"keymap.command_id": "Command ID",
"keymap.empty": "No matching commands",
"keymap.use_anyway": "Use {key} here anyway",
"label.move_to_left_side": "Move to left side",
"label.move_to_right_side": "Move to right side",
"manage.appearance_hint": "Choose a look for the selection, or drag a swatch onto a body or face.",
"manage.assign_hint": "Select bodies and choose their plastic design rule.",
"manage.config_hint": "Edit configuration rows, columns and rules, then activate or preview a row.",
@@ -1428,7 +1529,9 @@
"nav.free_orbit_upright.help": "Sideways mouse drags spin the model around the world's vertical axis; up and down drags tilt over the top without a limit.",
"nav.free_orbit_upright.label": "Turn around the vertical axis",
"nav.fusion.help": "Middle drag pans, Shift+middle orbits, right drag orbits",
"nav.hfss.help": "Alt+left drag pans, Shift+Alt+left zooms, Ctrl+left drag on empty space orbits",
"nav.inventor.help": "Middle drag pans, Shift+middle orbits, Ctrl+middle zooms, right drag orbits",
"nav.maya.help": "Alt+left drag orbits, Alt+middle pans, Alt+right zooms; middle drag also pans",
"nav.openscad.help": "Left drag on empty space orbits, Shift+left drag box-selects, sketch geometry drags edit; right or middle drag pans, Shift+right or Shift+middle drag zooms",
"nav.perspective.sketch": "Sketch editing uses orthographic view. Finish the sketch to switch perspective.",
"nav.solidworks.help": "Middle drag orbits, Ctrl+middle pans, Shift+middle zooms, right drag orbits",
@@ -1439,6 +1542,93 @@
"nav.touchpad.pan": "Pan (hold Shift and move; no mouse button)",
"nav.touchpad.scroll": "Touchpad uses vertical scroll to zoom. Your two-finger pan setting is kept for other presets.",
"nav.touchpad.zoom": "Zoom (vertical scroll or pinch)",
"navbar.agent_chat": "Assistant chat panel",
"navbar.agent_cursor": "Show agent cursor",
"navbar.ambient_occlusion": "Ambient occlusion",
"navbar.assistant": "Assistant",
"navbar.custom.add_slot": "Add {slot}",
"navbar.custom.always": "Always visible",
"navbar.custom.available": "{available} · drag onto the bar, or press Add",
"navbar.custom.buttons": "Buttons",
"navbar.custom.compact": "Compact",
"navbar.custom.count": "{count} of 16 slots",
"navbar.custom.customise": "Customise navigation bar…",
"navbar.custom.design": "Design",
"navbar.custom.duplicate": "This slot is already on the bar.",
"navbar.custom.fade": "Fade",
"navbar.custom.full": "Remove a slot to add another.",
"navbar.custom.hidden_design": "Hidden in Design",
"navbar.custom.hidden_render": "Hidden in Render",
"navbar.custom.hide": "Hide navigation bar",
"navbar.custom.hide_idle": "Hide until hovered",
"navbar.custom.icon_only": "Icon only",
"navbar.custom.icon_value": "Icon and value",
"navbar.custom.icons": "Icons",
"navbar.custom.idle": "When idle",
"navbar.custom.intro": "Choose the controls on the bar at the bottom of the 3D view, and in what order. Drag a slot to move it, or drag it off the bar to remove it.",
"navbar.custom.labels": "Icons and labels",
"navbar.custom.left": "Move left",
"navbar.custom.position": "Position",
"navbar.custom.position_centre": "Centre",
"navbar.custom.position_left": "Left",
"navbar.custom.position_right": "Right",
"navbar.custom.preview_as": "Preview as",
"navbar.custom.regular": "Regular",
"navbar.custom.remove": "Remove",
"navbar.custom.remove_bar": "Remove from bar",
"navbar.custom.render": "Render",
"navbar.custom.reset": "Reset navigation bar",
"navbar.custom.reset_default": "Reset to default",
"navbar.custom.right": "Move right",
"navbar.custom.select": "No slot selected. Select a slot on the bar to move it, remove it or change how it looks.",
"navbar.custom.separators_full": "The bar already has four separators.",
"navbar.custom.show": "Show navigation bar",
"navbar.custom.shows": "Shows",
"navbar.custom.size": "Size",
"navbar.custom.stale": "The bar changed. Select the slot again.",
"navbar.custom.title": "Navigation bar",
"navbar.custom.unknown": "This slot is not available.",
"navbar.description.ambient_occlusion": "Darkens creases and corners to add depth.",
"navbar.description.display": "Holds the view settings: graphics preset, grid, ground shadow, ambient occlusion and projection.",
"navbar.description.fit": "Frames the selection, or the whole model if nothing is selected.",
"navbar.description.grid": "Shows or hides the ground grid.",
"navbar.description.ground_shadow": "Shows or hides the shadow under the model.",
"navbar.description.home": "Returns to the isometric view of the whole model.",
"navbar.description.look_at": "Turns the view to face the selected face, plane or open sketch.",
"navbar.description.orbit": "Turns the view around the model.",
"navbar.description.pan": "Slides the view sideways, up or down.",
"navbar.description.projection": "Switches between orthographic and perspective views.",
"navbar.description.separator": "A thin line that groups neighbouring slots.",
"navbar.description.spin": "Keeps the view turning until you click or press a key.",
"navbar.description.visual_style": "Switches how the model is drawn: shaded, wireframe or with hidden edges.",
"navbar.description.zoom": "Moves the view closer to or further from the model.",
"navbar.display": "Display",
"navbar.fit": "Fit",
"navbar.graphics": "Graphics",
"navbar.grid": "Grid",
"navbar.ground_shadow": "Ground shadow",
"navbar.home": "Home",
"navbar.later": "Later",
"navbar.look_at": "Look at",
"navbar.more": "More",
"navbar.orbit": "Orbit",
"navbar.orthographic": "Orthographic",
"navbar.pan": "Pan",
"navbar.perspective": "Perspective",
"navbar.preset": "Preset",
"navbar.projection": "Projection",
"navbar.projection_heading": "Projection",
"navbar.separator": "Separator",
"navbar.show": "Show",
"navbar.spin": "Spin",
"navbar.style.shaded": "Shaded",
"navbar.style.shaded_with_edges": "Shaded with edges",
"navbar.style.shaded_with_hidden_edges": "Shaded with hidden edges",
"navbar.style.wireframe": "Wireframe",
"navbar.translucent": "Translucent",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "Visual style",
"navbar.zoom": "Zoom",
"needs two joints": "needs two joints",
"network.allow_once": "Allow once",
"network.always_allow": "Always allow this server",
@@ -1449,9 +1639,34 @@
"no hole": "no hole",
"no interference": "no interference",
"no joint that moves yet": "no joint that moves yet",
"no motion study yet": "no motion study yet",
"no picture": "no picture",
"no such joint": "no such joint",
"none": "none",
"not a move": "not a move",
"not a number": "not a number",
"open a sketch first": "open a sketch first",
"parts.automatic_name": "automatic",
"parts.dimension.across_flats": "Across flats",
"parts.dimension.bore": "Bore",
"parts.dimension.d": "Nominal diameter",
"parts.dimension.head_diameter": "Head diameter",
"parts.dimension.head_height": "Head height",
"parts.dimension.height": "Height",
"parts.dimension.inner": "Inner diameter",
"parts.dimension.outer": "Outer diameter",
"parts.dimension.pitch": "Pitch",
"parts.dimension.socket": "Socket size",
"parts.dimension.socket_depth": "Socket depth",
"parts.dimension.thickness": "Thickness",
"parts.dimension.width": "Width",
"parts.family.bearing": "Deep groove ball bearing (envelope)",
"parts.family.dowel_pin": "Parallel pin (dowel)",
"parts.family.hex_bolt": "Hex head bolt / screw",
"parts.family.hex_nut": "Hex nut",
"parts.family.set_screw": "Hex socket set screw, flat point",
"parts.family.socket_head_cap_screw": "Socket head cap screw",
"parts.family.washer": "Plain washer",
"pattern.alignment_2": "Alignment 2",
"pattern.alignment_hint": "Counts include the original. Center balances copies; Flip chooses the extra side for even totals.",
"pattern.direction_1": "Direction 1",
@@ -1467,9 +1682,25 @@
"perf.ui_time": "UI time",
"perf.viewport": "Viewport",
"perf.worst": "worst",
"pick a body or some of its faces": "pick a body or some of its faces",
"pick a hole to seat it, or OK places it at the origin": "pick a hole to seat it, or OK places it at the origin",
"pick a planar face": "pick a planar face",
"pick a plane or a face as the tool": "pick a plane or a face as the tool",
"pick a size": "pick a size",
"pick edges of a body": "pick edges of a body",
"pick edges of one body": "pick edges of one body",
"pick edges of the holes to remove": "pick edges of the holes to remove",
"pick faces of one body": "pick faces of one body",
"pick faces to offset": "pick faces to offset",
"pick lines of one sketch": "pick lines of one sketch",
"pick one or two vertices, edges or faces": "pick one or two vertices, edges or faces",
"pick one plane or face as the tool, or sketch curves": "pick one plane or face as the tool, or sketch curves",
"pick sections in two or more sketches": "pick sections in two or more sketches",
"pick sketch curves or edges": "pick sketch curves or edges",
"pick the face to untrim": "pick the face to untrim",
"pick the path": "pick the path",
"pick what to keep": "pick what to keep",
"pick what to keep of the other surface": "pick what to keep of the other surface",
"prefs.add_item": "Add the item",
"prefs.alt_frees_manipulators": "Alt / Option also frees manipulator arrows",
"prefs.anti_aliasing_amd_dx12": "Anti-aliasing uses 1× because the startup check drew nothing with multisampling and passed at 1×. You can choose another setting above; restart to apply it if the check passes.",
@@ -1837,6 +2068,64 @@
"render.effects_help": "Combine ordered colour looks and image-space lens effects. Rendering and raw-master regrading use the same saved settings. Raw EXR stays unchanged. These are original artistic controls, not calibrated lens or branded-film emulations.",
"render.effects_reset_lens": "Reset lens effects",
"render.effects_seed": "Pattern seed",
"render.emitted_axis": "Emitted axis",
"render.error_area_samples": "area_samples must be 1, 4, 16 or 64",
"render.error_binding_allocation": "could not reserve material binding",
"render.error_body_bound": "product preview exceeds its captured-body bound",
"render.error_checkpoint_dimensions": "checkpoint dimensions differ from the captured request",
"render.error_decode_budget": "image decode budget overflow",
"render.error_denoise_setting": "invalid native denoise setting",
"render.error_display_dimensions": "invalid image display dimensions",
"render.error_display_fit": "image display cannot fit this device",
"render.error_display_height": "display height overflow",
"render.error_display_width": "display width overflow",
"render.error_duplicate_face": "duplicate product face appearance",
"render.error_export_document": "The render export document changed while choosing its destination",
"render.error_face_cap": "product preview exceeds the face-appearance admission cap",
"render.error_finish_gesture": "finish the modelling gesture before previewing",
"render.error_finish_operation": "finish the current modelling operation before entering Render",
"render.error_fixed_preview": "fixed studio preview requires exposure 0, environment rotation 0 and intensity 1",
"render.error_geometry_size": "product geometry size overflow",
"render.error_glass_recipe": "unknown glass recipe",
"render.error_gpu_preview": "GPU product preview is unavailable on this host. Saved setups remain available.",
"render.error_gpu_samples": "unsupported GPU sample count",
"render.error_image_dimensions": "render image dimensions do not match its job",
"render.error_image_profile": "render image exceeds its captured resource profile",
"render.error_interactive_command": "unbound interactive Render command",
"render.error_job_action": "not an interactive image-job action",
"render.error_job_identity": "invalid render job identity: {error}",
"render.error_library_reply": "invalid render-library response",
"render.error_material_binding": "missing material binding",
"render.error_no_completed_image": "render has no completed image",
"render.error_no_geometry": "no product geometry",
"render.error_no_scene": "no product scene",
"render.error_opacity": "invalid product appearance opacity",
"render.error_pbr_opacity": "opaque PBR requires opacity 1",
"render.error_physical_glass": "the selected recipe is not physical glass",
"render.error_preview_device": "product preview requires an installed device with a depth buffer",
"render.error_product_triangle": "invalid product triangle",
"render.error_provisional_identity": "invalid provisional render identity or sample count",
"render.error_quality_bounds": "quality projection exceeds native bounds",
"render.error_quality_method": "quality projection requires the same explicit GPU method",
"render.error_quality_projection": "invalid native quality projection",
"render.error_regrade_identity": "invalid regrade identity: {error}",
"render.error_scene_bodies": "missing render scene bodies",
"render.error_scene_body_limit": "render scene exceeds its body limit",
"render.error_scene_identity": "invalid render scene identity",
"render.error_setup_panicked": "GPU path tracer setup panicked",
"render.error_setup_stopped": "setup worker stopped without returning a host",
"render.error_setup_worker": "could not start setup worker: {error}",
"render.error_source_preview": "source preview exceeds its byte envelope",
"render.error_surface_normals": "PBR requires nonzero surface normals",
"render.error_surface_reply": "invalid authored surface reply",
"render.error_triangle_bound": "product preview exceeds its eight-million-triangle source bound",
"render.error_triangle_count": "product triangle count overflow",
"render.error_upload_slot": "product preview upload slot unavailable",
"render.error_vertex_allocation": "product preview vertex allocation failed",
"render.error_vertex_envelope": "product preview exceeds its {limit} MiB vertex payload envelope; geometry was not simplified",
"render.error_vertex_packing": "product preview packing differs from its admitted vertex payload",
"render.error_visible_solid": "Create a visible solid in Design to preview it here.",
"render.exit_focus": "Exit focus",
"render.export_display": "Export: display PNG",
"render.export_image_label": "Export Image",
"render.export_linear": "Export: raw linear EXR",
@@ -1850,6 +2139,7 @@
"render.flare_streak": "Anamorphic-style streak",
"render.flare_strength": "Highlight flare strength",
"render.flare_threshold": "Scene-linear flare threshold",
"render.fold_browser": "Fold Browser",
"render.gpu_depth": "Maximum path depth",
"render.gpu_options_help": "Samples, depth, seed and exposure are saved with this setup. Only the active image method is saved.",
"render.gpu_path_failed": "GPU path tracer unavailable",
@@ -1907,11 +2197,13 @@
"render.image_use_largest": "Use the largest size at this aspect:",
"render.image_width": "Width",
"render.include_rig_cards": "Include passive cards and flags",
"render.inner_half_angle": "Inner half angle",
"render.inspect_scene": "Refresh captured scene summary",
"render.inspector": "Inspector",
"render.keep_editing": "Keep editing",
"render.layer_down": "Move down",
"render.layer_enabled": "Layer enabled",
"render.layer_off_suffix": " (off)",
"render.layer_remove": "Remove layer",
"render.layer_strength": "Layer strength",
"render.layer_up": "Move up",
@@ -2059,6 +2351,7 @@
"render.optics_save": "Save these optics to the setup",
"render.optics_saved": "Saved optical targets",
"render.optics_saved_help": "Exact definition, feature and occurrence identity survives offline reopen. Missing/replaced/hidden targets refuse; engineering materials are unchanged. Save or discard numeric edits before removing a saved target.",
"render.outer_half_angle": "Outer half angle",
"render.output_format_status": "PNG is the exact completed display image. Optional GPU EXR retains raw scene-linear FLOAT32 radiance before display filters. Export never substitutes the preview cache or a different job.",
"render.output_lock_ratio": "Lock aspect ratio",
"render.output_over_budget": "The requested image exceeds the selected resource envelope. Choose a compatible size or profile explicitly; no automatic downgrade occurs.",
@@ -2092,7 +2385,10 @@
"render.physical_prepare_plan": "Prepare creation plan (does not apply)",
"render.physical_separate": "Appearance is not material identification. These are sourced references, not certified effective properties. Existing mass, engineering materials and optics are unchanged.",
"render.physical_unknown": "No numerical candidate is established. Grade, formulation or construction must be specified; unknown is not zero.",
"render.pick_body": "Body",
"render.pick_component": "Component",
"render.pick_face": "Face",
"render.pick_help": "Choose Body, Face or Component. Click empty space to clear; Shift or Ctrl adds or toggles. Highlights appear only in the live product view.",
"render.pick_label": "Pick",
"render.pick_up_label": "Pick Up",
"render.pick_waiting": "Product picking is not supported yet.",
@@ -2114,6 +2410,12 @@
"render.preview_upload": "Live-preview vertex payload",
"render.preview_upload_help": "Exact preview vertex bytes, not total GPU or process memory. Geometry is not simplified. Image jobs use their own admission and lighting.",
"render.progressive_image_summary": "Preview PNG · PBR and glass · progressive samples",
"render.property_conditions": "Conditions: {value}",
"render.property_fallback": "property",
"render.property_qualifier": "Qualifier: {value}",
"render.property_source": "Source: {id} - {locator}",
"render.property_uncertainty": "Uncertainty: {value}",
"render.property_unknown": "unknown",
"render.quality_ack": "Acknowledge the fixed-budget projection and omissions",
"render.quality_apply": "Use this fixed sampling budget",
"render.quality_projection_help": "Q presets include future requirements. This action projects only a supported fixed-sample PNG budget and explicitly omits adaptive stopping, raw linear output and independent transmission limits.",
@@ -2129,6 +2431,7 @@
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.restore_camera": "Restore Saved Camera",
"render.result_actual_help": "One image pixel per display pixel.",
"render.result_actual_size": "100%",
"render.result_capture": "Captured revision",
"render.result_current": "The captured model revision is current.",
"render.result_empty": "No completed image yet. Check the settings, then start a render.",
@@ -2203,10 +2506,14 @@
"render.shot_rename": "Rename saved shot",
"render.shot_saved_only": "Save the current draft first. Duplicate and rename preserve exact saved options and resource references.",
"render.show_shots_label": "Show Shots strip",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Ground · linear RGB",
"render.sky_horizon": "Horizon · linear RGB",
"render.sky_zenith": "Zenith · linear RGB",
"render.soft_focus": "Soft focus",
"render.spot_cone": "Spot cone",
"render.stage_frame": "Frame",
"render.stage_light": "Light",
"render.stage_look": "Look",
@@ -2257,9 +2564,45 @@
"render.subsurface_enable": "Interior scattering random walk",
"render.subsurface_help": "Closed dielectric only. Scattering and RGB absorption are separate per-mm coefficients. Paths scatter inside actual geometry, then refract or reflect at the boundary. Disable straight shadow transmission, surface denoising and exterior volume; use one Fresnel stratum. Not a diffusion shader, density grid or measured material. Dense media may need more samples and path depth.",
"render.subsurface_rate": "Scattering collision rate",
"render.tone_aces_fitted": "ACES fitted",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "GPU glass supports certified disjoint media. Unrestricted nested media and a noise-free transmission estimator are not provided.",
"render.transmission_strata": "Conditional Fresnel strata",
"render.transmission_strata_help": "1 preserves the original stream. 2 or 4 subpaths stratify the first glass reflection/transmission choice with unchanged Snell and absorption laws. More paths cost more work; this is not denoising, nested-media support or a promise of faster rendering.",
"render.tree_add_light": "Add light",
"render.tree_add_shot": "Add shot",
"render.tree_browser": "Render Browser",
"render.tree_by_look": "By look",
"render.tree_by_object": "By object",
"render.tree_constant": "Constant environment",
"render.tree_default": "Default",
"render.tree_directional": "Directional",
"render.tree_environment": "Environment",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} faces",
"render.tree_face_one": "{count} face",
"render.tree_fixed_studio": "Fixed studio",
"render.tree_hdr": "HDR",
"render.tree_lights": "Lights",
"render.tree_lights_pending": "Named light commands are not available yet.",
"render.tree_mixed": "Mixed",
"render.tree_more": "{count} more",
"render.tree_mute": "Mute light",
"render.tree_no_environment": "No environment",
"render.tree_objects": "Objects",
"render.tree_output": "Output",
"render.tree_point": "Point",
"render.tree_rectangle": "Rectangle",
"render.tree_search": "Search objects",
"render.tree_selection": "Render selection",
"render.tree_shots": "Shots",
"render.tree_sky": "Sky",
"render.tree_solo": "Solo light",
"render.tree_spot": "Spot",
"render.tree_sun": "Sun",
"render.tree_switch": "Switch",
"render.tree_user_one": "{count} object",
"render.tree_users": "{count} objects",
"render.unavailable_preview": "This setup requests an unavailable preview profile.",
"render.unsaved": "Unsaved preview changes",
"render.use_preview": "Use Integrated Preview",
@@ -2303,6 +2646,26 @@
"search.try": "Type a command name, a feature in this design, or a parameter. To run a command with values, type its id and a JSON object: {example}",
"search.valid": "Valid",
"section.off_hint": "No plane picked: OK turns the section off.",
"select a direction (an axis, a sketch line or a straight edge) first": "select a direction (an axis, a sketch line or a straight edge) first",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "select a direction (an axis, a sketch line or a straight edge) for the profile to follow",
"select a point on a component": "select a point on a component",
"select a profile, edges or sketch lines first": "select a profile, edges or sketch lines first",
"select an axis": "select an axis",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "select an axis, a straight or circular edge, or a cylinder, cone or torus face first",
"select bodies first": "select bodies first",
"select corner points, or the two lines of one corner": "select corner points, or the two lines of one corner",
"select one corner point, or the two lines of one corner": "select one corner point, or the two lines of one corner",
"select sheet edges first": "select sheet edges first",
"select the bend line (a sketch line) first": "select the bend line (a sketch line) first",
"select the cam's profile (a sketch profile or the cam's edges)": "select the cam's profile (a sketch profile or the cam's edges)",
"select the corner to cut first": "select the corner to cut first",
"select the corners to round first": "select the corners to round first",
"select the fixed face first (a plate's large face)": "select the fixed face first (a plate's large face)",
"select the frame sketch's lines first": "select the frame sketch's lines first",
"select the path (sketch lines across the edge)": "select the path (sketch lines across the edge)",
"select the rim face first": "select the rim face first",
"select the sheet edge first": "select the sheet edge first",
"select two components": "select two components",
"set by the sketch's lines": "set by the sketch's lines",
"settings.display_quality_note": "Only the display. Designs and exports are not affected.",
"settings.frame_rate_details_note": "Adds a graph of the last frames' times with the triangles drawn over it, a histogram of frame times and what the GPU drew. Click the frame rate in the view to show or hide them.",
@@ -2320,17 +2683,23 @@
"settings.window_system_details": "Details",
"settings.window_system_note_now": "Applies after a restart. Now: {now}.",
"settings.window_system_wayland_limited": "Some features are limited on native Wayland.",
"sheet.flange_type_base": "Base",
"sheet.flange_type_contour": "Contour",
"sheet.flange_type_edge": "Edge",
"sheet.no_body": "there is no sheet metal body: start one with Flange > Base, or turn a plate into sheet metal with Convert to Sheet Metal (pick its large flat face)",
"shortcut.json_error": "parameters must be JSON: {error}",
"shortcut.no_command": "no command `{id}`; the text before the JSON must be a command id",
"shortcut.pin": "Pin to the top of the S box",
"shortcut.unpin": "Unpin",
"sketch is missing": "sketch is missing",
"sketch.degrees_of_freedom": "{count} degrees of freedom",
"sketch.dof_left": "{count} degrees of freedom left",
"sketch.dof_left_one": "{count} degree of freedom left",
"sketch.draw_curves": "Draw as {linetype}",
"sketch.make_selection": "Convert the selection to {linetype}",
"sketch.open_ends": "Open {count}",
"sketch.status_conflict": "constraints conflict",
"sketch.status_fully_constrained": "fully constrained",
"sketch.untied_ends": "Untied {count}",
"sketch_panel.attached": "Attached to {body} / {path}",
"sketch_panel.author": "Author placement: {path}",
@@ -2357,7 +2726,24 @@
"sketch_text.path_hint": "A curve of the sketch the text follows: click here, then the curve",
"sketch_text.use_font_file": "Use the font file {path}",
"solid": "solid",
"the angle must be a number": "the angle must be a number",
"the curves must be in one sketch": "the curves must be in one sketch",
"the direction must be an axis, a sketch line or a straight edge": "the direction must be an axis, a sketch line or a straight edge",
"the duration must be a number of seconds, 0.001 or more": "the duration must be a number of seconds, 0.001 or more",
"the line's sketch is gone": "the line's sketch is gone",
"the lines must be in one sketch": "the lines must be in one sketch",
"the lines must be in one sketch, not the section's": "the lines must be in one sketch, not the section's",
"the parts library is empty": "the parts library is empty",
"the parts library is not available": "the parts library is not available",
"the path curves must be in one other sketch": "the path curves must be in one other sketch",
"the path's sketch is gone": "the path's sketch is gone",
"the position must be a number": "the position must be a number",
"the preview failed": "the preview failed",
"the profiles and curves must be in one sketch": "the profiles and curves must be in one sketch",
"the reference face must be on the edges' body": "the reference face must be on the edges' body",
"the scale must be above 0": "the scale must be above 0",
"the section's profiles must be in one sketch": "the section's profiles must be in one sketch",
"the two origins are on the same component": "the two origins are on the same component",
"thread.automatic_size": "Automatic size",
"thread.designation": "Designation",
"thread.direction": "Thread direction",
@@ -2397,6 +2783,7 @@
"trace.points": "{count} points along the path",
"trace.stopped_by_contact": "Ends at sample {sample}: {a} would pass through {b}",
"trace.stopped_by_loop": "Ends at sample {sample}: the loop through {joint} can't close any further",
"trim by sketch curves, or by one plane or face": "trim by sketch curves, or by one plane or face",
"ui.1_degree_of_freedom": "1 degree of freedom",
"ui.3d_mouse_axes_reassigned": "Axes are reassigned in Preferences, and that still applies on top of this calibration.",
"ui.3d_mouse_button": "Button {number}",
@@ -2873,6 +3260,8 @@
"ui.design_properties.revision": "Revision",
"ui.diameter": "Diameter",
"ui.dimension": "Dimension",
"ui.direct_interaction": "Direct interaction",
"ui.direct_interaction_note": "Work on the model directly in the viewport. Press a flat face or a profile and pull: up extrudes, down into a body cuts, and sideways movement sets the step size",
"ui.direction": "Direction",
"ui.display_quality": "Display quality",
"ui.display_quality_coarse": "Coarse",
@@ -2896,6 +3285,7 @@
"ui.editJointLimits": "Edit Joint Limits",
"ui.edit_section_analysis": "Edit Section Analysis",
"ui.ellipse": "Ellipse",
"ui.emboss_wrap_note": "Orthogonal line profiles tangent to one supported cylinder wrap automatically. Pick a wall to choose a target.",
"ui.end_radius": "End Radius",
"ui.end_scale": "End Scale",
"ui.entities": "Entities",
@@ -2968,6 +3358,7 @@
"ui.heading_extrude": "EXTRUDE",
"ui.heading_fillet": "FILLET",
"ui.heading_finish_sketch": "FINISH SKETCH",
"ui.heading_form": "FORM",
"ui.heading_front": "FRONT",
"ui.heading_hole": "HOLE",
"ui.heading_home": "HOME",
@@ -3016,6 +3407,7 @@
"ui.heading_utilities": "UTILITIES",
"ui.heading_utility": "UTILITY",
"ui.heading_weldments": "WELDMENTS",
"ui.height": "Height",
"ui.help": "Help",
"ui.hide": "Hide",
"ui.hideAxes": "Hide Axes",
@@ -3053,11 +3445,14 @@
"ui.intersect": "Intersect",
"ui.isolate": "Isolate",
"ui.join": "Join",
"ui.joint_play": "▶ Play",
"ui.joint_stop": "■ Stop",
"ui.joints": "Joints",
"ui.keyboard_shortcuts": "Keyboard Shortcuts",
"ui.language": "Language",
"ui.layout_compact": "Compact",
"ui.layout_floating": "Floating",
"ui.length": "Length",
"ui.length_decimals": "Length decimals",
"ui.light": "Light",
"ui.line": "Line",
@@ -3069,6 +3464,7 @@
"ui.loft": "Loft",
"ui.look_at": "Look At",
"ui.look_at_anim_desc": "Axis view, Look At, Home and Fit",
"ui.major_radius": "Major radius",
"ui.manipulator_free_alt": "Manipulator free drag also on Alt/Option",
"ui.manipulator_free_alt_tip": "On: Alt/Option or Ctrl/Cmd on extrude / gizmo arrows disables value snapping. Off: Ctrl/Cmd only.",
"ui.manufacture": "Manufacture",
@@ -3098,8 +3494,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF with face tags",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "Minor radius",
"ui.mirror": "Mirror",
"ui.mirror_line": "Mirror line",
"ui.modifiers_either": "{first} or {second}",
"ui.move": "Move",
"ui.multiple": "Multiple",
"ui.named_views": "Named Views",
@@ -3156,6 +3554,7 @@
"ui.pinToShortcuts": "Pin to Shortcuts",
"ui.pinToToolbar": "Pin to Toolbar",
"ui.pipe": "Pipe",
"ui.pitch": "Pitch",
"ui.placement": "Placement",
"ui.placement_handles": "Placement handles",
"ui.placement_handles_tip": "Handles on the preview of a Rest, Boss or Snap Fit: drag the marker to move it across the model, turn it by its ring",
@@ -3218,6 +3617,7 @@
"ui.reverse_horizontal_pan_direction": "Reverse horizontal pan direction",
"ui.reverse_horizontal_pan_tip": "Horizontal two-finger scrolling and the thumb wheel pan the other way",
"ui.reverse_zoom_direction": "Reverse zoom direction",
"ui.revolutions": "Revolutions",
"ui.revolve": "Revolve",
"ui.ribbon_exit": "Exit",
"ui.ribbon_labels": "Show text under ribbon icons",
@@ -3234,6 +3634,7 @@
"ui.scale": "Scale",
"ui.second_rail": "Second Rail",
"ui.section_analysis": "Section Analysis",
"ui.section_size": "Section size",
"ui.select": "Select",
"ui.selectOther": "Select Other…",
"ui.selectTangentChain": "Select Tangent Chain",
@@ -3305,6 +3706,7 @@
"ui.start_page": "Start page",
"ui.step_values": "Step values with the arrow keys and the wheel",
"ui.step_values_tip": "In a value field you are typing in, Up/Down change a plain number by 1 (Shift: 10, Alt: 0.1), and so does the mouse wheel over the field. Expressions are left as typed.",
"ui.stitch_tolerance_hint": "tight",
"ui.stretch": "Stretch",
"ui.supersampling": "Supersampling (SSAA)",
"ui.supersampling_adaptive": "Only when the view is still",
@@ -3335,6 +3737,8 @@
"ui.to_object": "To Object",
"ui.tool_direction": "Tool direction",
"ui.top": "Top",
"ui.top_diameter": "Top diameter",
"ui.top_radius": "Top radius",
"ui.torus": "Torus",
"ui.total_angle": "Total angle",
"ui.trackpad_pan_tip": "Two-finger scroll pans; in Fusion, Shift + two fingers orbits. Off: scroll zooms. Mouse wheel and pinch zoom; thumb wheel pans sideways.",
@@ -3363,6 +3767,7 @@
"ui.visual_shaded_with_edges": "Shaded with edges",
"ui.visual_style": "Visual style",
"ui.visual_wireframe": "Wireframe",
"ui.width": "Width",
"ui.window_system": "Window system",
"ui.window_system_auto": "Automatic",
"ui.window_system_wayland": "Wayland",
@@ -3423,6 +3828,9 @@
"update.up_to_date": "SolidCraft is up to date.",
"update.update_now": "Update now",
"update.you_have": "You have {version}.",
"use a positive nominal diameter and a pitch smaller than it": "use a positive nominal diameter and a pitch smaller than it",
"values must be finite numbers": "values must be finite numbers",
"values must be numbers or expressions": "values must be numbers or expressions",
"view.auto_ortho_faces": "Perspective while orbiting, ortho on faces",
"web.files.insert_drawings_hint": "CAD files, meshes, DXF or SVG into the open design",
"web.files.insert_stored_drawings_hint": "Into the open design (CAD files, meshes, DXF, SVG)",
+197
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(regla activa)",
"0 turns it off": "0 lo desactiva",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Abre el borrador de GitHub de abajo y pega el informe copiado al portapapeles.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Abre el borrador de GitHub de abajo. El título y el informe se rellenarán automáticamente.",
@@ -35,12 +36,16 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "Aplique primero la apariencia. Exporta las apariencias asignadas y los materiales creados en este diseño.",
"Arc length": "Longitud del arco",
"Area": "Área",
"As Picked": "Según la selección",
"As-Built": "Tal como se construyó",
"Assign Rule": "Asignar regla",
"Attachment": "Vinculación",
"BLEND SURFACE": "SUPERFICIE DE TRANSICIÓN",
"BOUNDARY SURFACE": "SUPERFICIE DE CONTORNO",
"BROWSER": "EXPLORADOR",
"Ball": "Rótula",
"Base Height": "Altura de la base",
"Bend Line": "Línea de plegado",
"Bend Line Position": "Posición de la línea de plegado",
"Bend Position": "Posición del pliegue",
"Bend Radius": "Radio de plegado",
@@ -48,6 +53,7 @@
"Bends": "Pliegues",
"Bodies": "Cuerpos",
"Body": "Cuerpo",
"Both": "Ambos",
"Boundary": "Contorno",
"Bounding box": "Caja delimitadora",
"CHECK": "COMPROBAR",
@@ -70,6 +76,7 @@
"Checked": "Comprobado",
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "Elige un plano nuevo. La geometría y las cotas del boceto se mantienen en sus coordenadas bidimensionales.",
"Choose…": "Elegir…",
"Circle or sphere": "Círculo o esfera",
"Circular": "Circular",
"Circumference": "Circunferencia",
"Clockwise": "Horario",
@@ -81,6 +88,7 @@
"Config Table": "Tabla de config.",
"Configuration": "Configuración",
"Configuration rules": "Reglas de configuración",
"Constant radius": "Radio constante",
"Contact": "Contacto",
"Contact Sets": "Conjuntos de contacto",
"Contact sets": "Conjuntos de contacto",
@@ -105,6 +113,8 @@
"Curvature (G2)": "Curvatura (G2)",
"Curvature change (G3)": "Cambio de curvatura (G3)",
"Customize Toolbar": "Personalizar barra de herramientas",
"Cylindrical": "Cilíndrica",
"Deboss": "Grabado",
"Delete": "Eliminar",
"Delete all": "Eliminar todo",
"Delete rule": "Eliminar regla",
@@ -122,6 +132,7 @@
"Double-clicking the middle button in the view: Home (the home view, framing what is shown), Fit (frame what is shown, keeping the orientation) or nothing": "Doble clic con el botón central en la vista: Inicio (vista inicial que encuadra lo visible), Ajustar (encuadrar sin cambiar la orientación) o nada",
"Drive Joint": "Accionar unión",
"Duration": "Duración",
"Edge": "Arista",
"Edges": "Aristas",
"Edit": "Editar",
"Edit Profile Sketch": "Editar boceto del perfil",
@@ -129,6 +140,7 @@
"Enabled": "Activado",
"End bulge": "Abombamiento final",
"End continuity": "Continuidad final",
"Equal Distance": "Distancia igual",
"Explode": "Explosionar",
"Explode Text": "Descomponer texto",
"Export Animation…": "Exportar animación…",
@@ -148,6 +160,8 @@
"Face attachment lost": "Se ha perdido la vinculación de la cara",
"Faces": "Caras",
"Faces / edges / vertices": "Caras / aristas / vértices",
"Faces/Body": "Caras/Cuerpo",
"Factor must be a positive number": "El factor debe ser un número positivo",
"Fastener": "Sujeción",
"Favorites": "Favoritos",
"Favourite": "Favorito",
@@ -156,20 +170,28 @@
"Filter": "Filtrar",
"Find in Browser": "Buscar en el explorador",
"Finish": "Acabado",
"First edge": "Primera arista",
"First point": "Primer punto",
"Flange Gap": "Separación de pestaña",
"Flat Pattern": "Desarrollo plano",
"Flat size": "Tamaño del desarrollo",
"Follow camera (Look At sketches)": "Seguir cámara (orientar hacia los bocetos)",
"Follow the camera (Look At sketches)": "Seguir la cámara (orientar hacia los bocetos)",
"Font": "Fuente",
"Free Move": "Movimiento libre",
"From Bodies": "Desde cuerpos",
"From Snap": "Desde el enganche",
"From edges": "Aristas de origen",
"Full Length": "Longitud total",
"Gap": "Separación",
"Grid": "Cuadrícula",
"HISTORY": "HISTORIAL",
"Height": "Altura",
"Hem Gap": "Separación de reborde",
"Hidden edges": "Aristas ocultas",
"History layout": "Disposición del historial",
"Hole Depth": "Profundidad del agujero",
"Hole Diameter": "Diámetro del agujero",
"Holes": "Agujeros",
"Holes (edges on them)": "Agujeros (aristas que contienen)",
"Home view": "Vista de inicio",
@@ -185,10 +207,14 @@
"Isocurve": "Isocurva",
"Issue title": "Título de la incidencia",
"JOINTS": "UNIONES",
"Joint 1": "Unión 1",
"Joint 2": "Unión 2",
"Joint Origin1": "Origen de unión1",
"K Factor": "Factor K",
"Keep (points on it)": "Conservar (puntos sobre ella)",
"Keep Tools": "Conservar herramientas",
"Keep of the other surface": "Conservar de la otra superficie",
"Knife Edge": "Borde afilado",
"LIBRARY": "BIBLIOTECA",
"LINKS": "VÍNCULOS",
"Later": "Más tarde",
@@ -199,7 +225,9 @@
"Letter Spacing": "Espaciado entre letras",
"Library": "Biblioteca",
"Library file": "Archivo de biblioteca",
"Library response is missing": "Falta la respuesta de la biblioteca",
"Line Spacing": "Interlineado",
"Line on plane": "Línea en plano",
"Local library": "Biblioteca local",
"Loop": "Bucle",
"MANAGE": "GESTIONAR",
@@ -213,9 +241,12 @@
"Material": "Material",
"Material copied. Existing body assignments are unchanged.": "Material copiado. Se conservan las asignaciones actuales de los cuerpos.",
"Max": "Máx.",
"Max Thickness": "Espesor máx.",
"Mid Radius": "Radio intermedio",
"Middle double-click": "Doble clic central",
"Min": "Mín.",
"Min Draft": "Ángulo de salida mín.",
"Min Thickness": "Espesor mín.",
"Mitre": "Inglete",
"Model Parameters": "Parámetros del modelo",
"Modeled": "Modelado",
@@ -230,6 +261,7 @@
"Name": "Nombre",
"Name on import": "Nombre al importar",
"Nearest": "Más cercano",
"Neutral plane": "Plano neutro",
"New": "Nuevo",
"New Comp.": "Nuevo comp.",
"New Sketch": "Nuevo boceto",
@@ -240,6 +272,7 @@
"No matching appearances": "No hay apariencias coincidentes",
"No matching physical materials.": "No hay materiales físicos coincidentes.",
"No visible bodies or sketches to export.": "No hay cuerpos ni bocetos visibles para exportar.",
"Nominal Radius": "Radio nominal",
"None": "Ninguno",
"Not available yet": "Todavía no disponible",
"Notch": "Muesca",
@@ -255,19 +288,25 @@
"Overall length": "Longitud total",
"Param. Graph": "Gráfico de parám.",
"Parameter": "Parámetro",
"Part length must be greater than zero and at most 2000 mm": "La longitud de la pieza debe ser mayor que cero y como máximo 2000 mm",
"Parts": "Piezas",
"Pass through": "Pasante",
"Path": "Trayectoria",
"Pattern": "Patrón",
"Per Edge": "Por arista",
"Physical material definitions": "Definiciones de materiales físicos",
"Pick a part size": "Elige un tamaño de pieza",
"Pick the tool bodies": "Selecciona los cuerpos herramienta",
"Picked": "Seleccionado",
"Picked point": "Punto seleccionado",
"Pin-slot": "Pasador-ranura",
"Place at the origin instead": "Colocar en el origen",
"Planar": "Plana",
"Plastic Rules": "Reglas de plástico",
"Playback": "Reproducción",
"Plot": "Graficar",
"Point on line": "Punto en línea",
"Point on plane": "Punto en plano",
"Position": "Posición",
"Position (0 to 1)": "Posición (de 0 a 1)",
"Position (G0)": "Posición (G0)",
@@ -277,6 +316,7 @@
"Preview leaves the current design unchanged.": "La vista previa no modifica el diseño actual.",
"Profiles/Curves": "Perfiles/curvas",
"Quantity": "Cantidad",
"Quantity must be at least 2": "La cantidad debe ser al menos 2",
"RECENT": "RECIENTES",
"REFERENCE": "REFERENCIA",
"RULED SURFACE": "SUPERFICIE REGLADA",
@@ -288,6 +328,8 @@
"Recover unsaved design?": "¿Recuperar el diseño sin guardar?",
"Rectangular": "Rectangular",
"Reference face": "Cara de referencia",
"Relief Depth": "Profundidad de alivio",
"Relief Width": "Ancho de alivio",
"Remove Tools": "Eliminar herramientas",
"Remove from list": "Quitar de la lista",
"Remove override": "Quitar anulación",
@@ -304,6 +346,7 @@
"Restore the inherited component or physical material appearance": "Restaurar la apariencia heredada del componente o del material físico",
"Result": "Resultado",
"Retake screenshot": "Repetir captura de pantalla",
"Reveal Height": "Altura del escalón",
"Reverse": "Invertir",
"Reverse Direction": "Invertir dirección",
"Revert": "Revertir",
@@ -311,7 +354,10 @@
"Revert Pos.": "Revertir pos.",
"Revert Position": "Revertir posición",
"Review the report and screenshot before opening GitHub.": "Revisa el informe y la captura antes de abrir GitHub.",
"Revolute": "Revolución",
"Rigid": "Rígida",
"Rim Edge": "Arista del borde",
"Rim face": "Cara del borde",
"Roll History Marker Here": "Desplazar marcador de la línea de tiempo hasta aquí",
"Round": "Redondo",
"Rule": "Regla",
@@ -328,11 +374,22 @@
"Search": "Buscar",
"Search commands": "Buscar comandos",
"Search this library": "Buscar en esta biblioteca",
"Second edge": "Segunda arista",
"Second point": "Segundo punto",
"Section": "Sección",
"Section position": "Posición de la sección",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "Seleccionar otro: mantén pulsado el botón izquierdo sobre el modelo (o haz clic derecho › Seleccionar otro…) para ver todo lo que hay bajo el cursor; vuelve a pulsar en el mismo lugar para seleccionar el siguiente elemento. Haz doble clic con el botón central para volver a Inicio (Preferencias › Navegación).",
"Select bodies (a face picks its body)": "Selecciona cuerpos (al seleccionar una cara se selecciona su cuerpo)",
"Select bodies or faces instead": "Selecciona cuerpos o caras en su lugar",
"Select points of the sketch being edited": "Selecciona puntos del boceto que se está editando",
"Select the centre the pattern turns around first": "Selecciona primero el centro alrededor del cual gira el patrón",
"Select the curves to offset first": "Selecciona primero las curvas que se van a desfasar",
"Select the mirror line": "Selecciona la línea de simetría",
"Select the sketch curves or points to mirror first": "Selecciona primero las curvas o puntos del boceto que se van a reflejar",
"Select the sketch curves or points to move first": "Selecciona primero las curvas o puntos del boceto que se van a mover",
"Select the sketch curves or points to pattern first": "Selecciona primero las curvas o puntos del boceto para el patrón",
"Select the sketch curves or points to scale first": "Selecciona primero las curvas o puntos del boceto que se van a escalar",
"Select the sketch curves or points to transform first": "Selecciona primero las curvas o puntos del boceto que se van a transformar",
"Selection filter": "Filtro de selección",
"Semantic faces share their appearance across instances.": "Las caras semánticas comparten su apariencia entre instancias.",
"Send your report on GitHub": "Enviar tu informe a GitHub",
@@ -350,8 +407,11 @@
"Sketch geometry and profiles": "Geometría y perfiles del boceto",
"Sketch plane has no body-face attachment.": "El plano del boceto no está vinculado a ninguna cara del cuerpo.",
"Sketch points": "Puntos del boceto",
"Slider": "Deslizante",
"Slot width": "Anchura de la ranura",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft se cerró antes de guardar estos diseños. Puedes abrir su último guardado automático.",
"Spacing 2 must be a non-zero number": "El espaciado 2 debe ser un número distinto de cero",
"Spacing must be a non-zero number": "El espaciado debe ser un número distinto de cero",
"Specialise": "Especializar",
"Speed": "Velocidad",
"Square": "Cuadrado",
@@ -361,6 +421,7 @@
"Start angle": "Ángulo inicial",
"Start bulge": "Abombamiento inicial",
"Start continuity": "Continuidad inicial",
"Stationary Side": "Lado fijo",
"Step": "Paso",
"Steps": "Pasos",
"Stitch the kept pieces": "Coser las piezas conservadas",
@@ -369,29 +430,41 @@
"Style": "Estilo",
"Suppressed": "Suprimido",
"Surface": "Superficie",
"Surfaces": "Superficies",
"Swap Ends": "Intercambiar extremos",
"TRIM": "RECORTAR",
"Tangent (G1)": "Tangencia (G1)",
"Tangent Chain": "Cadena tangente",
"Target Face (optional)": "Cara de destino (opcional)",
"Tear": "Desgarro",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "El boceto discontinuo sirve de guía del plano guardado. Selecciona una cara nueva para reparar la vinculación.",
"The design changed. Reopen Change Part Size for the component.": "El diseño ha cambiado. Vuelve a abrir Cambiar tamaño de pieza para el componente.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "La dirección debe ser un eje o una curva recta del boceto que esté en el plano del boceto",
"The mirror line cannot also be mirrored": "La línea de simetría no puede reflejarse también",
"The mirror line must be a straight curve of this sketch, not an origin axis": "La línea de simetría debe ser una curva recta de este boceto, no un eje del origen",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "Falta la instancia de autor guardada. Selecciona una posición de autor válida antes de volver a vincular.",
"Then": "Entonces",
"These features will be deleted:": "Se eliminarán estas operaciones:",
"These features will fail:": "Estas operaciones fallarán:",
"Thickness Outside": "Espesor hacia fuera",
"Thickness Variation": "Variación de espesor",
"Thin": "Delgado",
"Thin Extrude": "Extrusión delgada",
"Third plane": "Tercer plano",
"Third point": "Tercer punto",
"This child is shared. Deleting it removes it from every copy of its parent.": "Este elemento secundario es compartido. Si lo eliminas, desaparecerá de todas las copias de su elemento principal.",
"This child is shared. Position changes apply to every copy of its parent.": "Este elemento secundario es compartido. Los cambios de posición se aplican a todas las copias de su elemento principal.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "Esta cara no permite una vinculación persistente. Elige otra cara o utiliza expresamente un plano fijo.",
"Through point": "Por un punto",
"To Offset": "Hasta desfase",
"To Snap": "Hasta el enganche",
"To edges": "Aristas de destino",
"Tolerance": "Tolerancia",
"Too close": "Demasiado cerca",
"Trimming tool (plane, face or curves)": "Herramienta de recorte (plano, cara o curvas)",
"Turn off section analysis before exporting the view.": "Desactiva el análisis de sección antes de exportar la vista.",
"Type": "Tipo",
"Type a distance or an angle to move by": "Escribe una distancia o un ángulo para mover",
"UNTRIM": "ANULAR RECORTE",
"Unit": "Unidad",
"Updating the preview": "Actualizando vista previa",
@@ -420,6 +493,17 @@
"Z angle": "Ángulo Z",
"Z distance": "Distancia Z",
"Zebra": "Cebra",
"`joint` must be an id or a name": "`joint` debe ser un id o un nombre",
"`params` must be an object": "`params` debe ser un objeto",
"`values` must be a list": "`values` debe ser una lista",
"a chamfer needs a corner of exactly two lines": "un chaflán necesita una esquina de exactamente dos líneas",
"a file operation is in progress": "hay una operación de archivo en curso",
"a picked curve is no longer in a sketch": "una curva elegida ya no está en un boceto",
"a picked curve's sketch has not been solved": "el boceto de una curva elegida no se ha resuelto",
"a picked edge has no points": "una arista elegida no tiene puntos",
"a picked edge is gone": "una arista elegida ya no existe",
"a picked edge's body is gone": "el cuerpo de una arista elegida ya no existe",
"add a key for a joint first": "añade primero una clave para una unión",
"angle, height": "ángulo, altura",
"appearance.dielectric_ior": "Índice de refracción dieléctrico",
"appearance.metallic": "Metalicidad",
@@ -428,6 +512,7 @@
"appearance.pbr_opaque": "PBR opaco",
"appearance.roughness": "Rugosidad",
"appearance.surface_response": "Respuesta de la superficie",
"bom.group_children": "Subpiezas en la fila de su pieza",
"browser.body_name": "Cuerpo{number}",
"browser.calibrate_title": "Calibrar: {name}",
"browser.capture_many": "Se han movido {count} componentes, pero sus posiciones no se han capturado.",
@@ -438,6 +523,8 @@
"browser.move_title": "Mover: {name}",
"browser.parameters": "Parámetros ({count})",
"browser.precision": "Precisión: {precision}",
"browser.sketch_attachment_lost": "{name} (fijación perdida)",
"browser.sketch_editing": "{name} (en edición)",
"browser.sketch_name": "Boceto{number}",
"browser.units": "Unidades: {units}",
"cam.flat": "Cara plana",
@@ -447,6 +534,11 @@
"cam.roller": "Rodillo",
"cam.roller_pick": "Rodillo (opcional)",
"cam.tip_pick": "Punta (opcional)",
"choose a profile": "elige un perfil",
"choose the cam's and the follower's joints": "elige las uniones de la leva y del seguidor",
"choose the joints to couple": "elige las uniones que acoplar",
"click a plane or planar face": "hacer clic en un plano o una cara plana",
"click sketch curves": "hacer clic en curvas del boceto",
"cmd.appearance_assign": "Apariencia",
"cmd.appearance_library": "Biblioteca de apariencias",
"cmd.appearance_list": "Listar apariencias",
@@ -884,6 +976,8 @@
"dxf.progress.write": "Escribiendo DXF (5/5)",
"dxf.tolerance": "Tolerancia de curva",
"dxf.tolerance_help": "Solo cuerpos visibles y bocetos mostrados. Las curvas usan segmentos rectos. Una tolerancia menor da curvas más finas y consume más tiempo y memoria.",
"each rail's curves must be in one sketch": "las curvas de cada guía deben estar en un solo boceto",
"feature computation ended without a result": "el cálculo de la operación terminó sin resultado",
"file_load.built": "Construido hasta ahora: {built} de {total} operaciones.",
"file_load.converting": "Convirtiendo sólido {done} de {total}",
"file_load.inserting": "Insertando geometría",
@@ -1078,16 +1172,55 @@
"no hole": "sin agujero",
"no interference": "sin interferencias",
"no joint that moves yet": "todavía no hay ninguna unión móvil",
"no motion study yet": "todavía no hay ningún estudio de movimiento",
"no picture": "sin imagen",
"no such joint": "no existe esa unión",
"none": "ninguno",
"not a move": "no es un movimiento",
"not a number": "no es un número",
"open a sketch first": "abre primero un boceto",
"parts.automatic_name": "automático",
"parts.dimension.across_flats": "Entrecaras",
"parts.dimension.bore": "Diámetro interior",
"parts.dimension.head_diameter": "Diámetro cabeza",
"parts.dimension.head_height": "Altura cabeza",
"parts.dimension.height": "Altura",
"parts.dimension.inner": "Diámetro interior",
"parts.dimension.outer": "Diámetro exterior",
"parts.dimension.socket": "Hexágono interior",
"parts.dimension.socket_depth": "Profundidad hexágono",
"parts.dimension.thickness": "Espesor",
"parts.dimension.width": "Anchura",
"parts.family.bearing": "Rodamiento rígido de bolas (envolvente)",
"parts.family.dowel_pin": "Pasador cilíndrico",
"parts.family.hex_bolt": "Tornillo de cabeza hexagonal",
"parts.family.hex_nut": "Tuerca hexagonal",
"parts.family.set_screw": "Prisionero con hexágono interior, punta plana",
"parts.family.socket_head_cap_screw": "Tornillo cilíndrico con hexágono interior",
"parts.family.washer": "Arandela plana",
"pattern.alignment_2": "Alineación 2",
"pattern.alignment_hint": "Los recuentos incluyen el original. Centrar equilibra las copias; Invertir elige el lado adicional cuando el total es par.",
"pattern.direction_1": "Dirección 1",
"pattern.direction_2": "Dirección 2",
"pattern.flip_direction": "Invertir dirección",
"pick a body or some of its faces": "elige un cuerpo o algunas de sus caras",
"pick a hole to seat it, or OK places it at the origin": "selecciona un agujero para colocarlo o pulsa Aceptar para situarlo en el origen",
"pick a planar face": "elige una cara plana",
"pick a plane or a face as the tool": "elige un plano o una cara como herramienta",
"pick a size": "elige un tamaño",
"pick edges of a body": "elige aristas de un cuerpo",
"pick edges of one body": "elige aristas de un solo cuerpo",
"pick edges of the holes to remove": "elige las aristas de los agujeros que quitar",
"pick faces of one body": "elige caras de un solo cuerpo",
"pick faces to offset": "elige las caras que desfasar",
"pick lines of one sketch": "elige líneas de un solo boceto",
"pick one or two vertices, edges or faces": "selecciona uno o dos vértices, aristas o caras",
"pick one plane or face as the tool, or sketch curves": "elige un plano o una cara como herramienta, o curvas de boceto",
"pick sections in two or more sketches": "elige secciones en dos o más bocetos",
"pick sketch curves or edges": "elige curvas de boceto o aristas",
"pick the face to untrim": "elige la cara a la que quitar el recorte",
"pick what to keep": "elige qué conservar",
"pick what to keep of the other surface": "elige qué conservar de la otra superficie",
"prefs.cpu": "CPU (software)",
"prefs.minutes_suffix": " min",
"prefs.theme_follow": "Seguir un archivo de tema",
@@ -1720,6 +1853,26 @@
"search.suggest": "¿Quisiste decir {label}?",
"search.try": "Escribe el nombre de un comando, una operación de este diseño o un parámetro. Para ejecutar un comando con valores, escribe su id y un objeto JSON: {example}",
"search.valid": "Válido",
"select a direction (an axis, a sketch line or a straight edge) first": "selecciona primero una dirección (un eje, una línea de boceto o una arista recta)",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "selecciona una dirección (un eje, una línea de boceto o una arista recta) que seguirá el perfil",
"select a point on a component": "selecciona un punto en un componente",
"select a profile, edges or sketch lines first": "selecciona primero un perfil, aristas o líneas de boceto",
"select an axis": "selecciona un eje",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "selecciona primero un eje, una arista recta o circular, o una cara cilíndrica, cónica o toroidal",
"select bodies first": "selecciona primero cuerpos",
"select corner points, or the two lines of one corner": "selecciona puntos de esquina, o las dos líneas de una esquina",
"select one corner point, or the two lines of one corner": "selecciona un punto de esquina, o las dos líneas de una esquina",
"select sheet edges first": "selecciona primero aristas de chapa",
"select the bend line (a sketch line) first": "selecciona primero la línea de plegado (una línea de boceto)",
"select the cam's profile (a sketch profile or the cam's edges)": "selecciona el perfil de la leva (un perfil de boceto o las aristas de la leva)",
"select the corner to cut first": "selecciona primero la esquina que cortar",
"select the corners to round first": "selecciona primero las esquinas que redondear",
"select the fixed face first (a plate's large face)": "selecciona primero la cara fija (la cara grande de una placa)",
"select the frame sketch's lines first": "selecciona primero las líneas del boceto del marco",
"select the path (sketch lines across the edge)": "selecciona la trayectoria (líneas de boceto a lo largo de la arista)",
"select the rim face first": "selecciona primero la cara del borde",
"select the sheet edge first": "selecciona primero la arista de la chapa",
"select two components": "selecciona dos componentes",
"settings.display_quality_note": "Los niveles más finos muestran las caras y aristas curvas con mayor suavidad, pero tardan más en generar la malla. Solo cambia el visor, nunca el diseño ni las exportaciones.",
"settings.frame_rate_note": "Muestra los fotogramas por segundo en la esquina inferior derecha de la vista.",
"settings.measure_axis_distances": "Mostrar distancias X/Y/Z",
@@ -1732,16 +1885,22 @@
"settings.reset_intro": "Estos ajustes no funcionan en este ordenador e impedirían iniciar SolidCraft, por lo que se han cambiado:",
"settings.reset_title": "Se han cambiado los ajustes",
"settings.supersampling_note": "Dibuja la vista a mayor resolución y después la reduce: bordes, líneas y cuadrícula más suaves en pantallas inferiores a 4K. Consume recursos de GPU: unos 2,25× píxeles a 1,5× y 4× a 2×.",
"sheet.flange_type_base": "Base",
"sheet.flange_type_contour": "Contorno",
"sheet.flange_type_edge": "Arista",
"shortcut.json_error": "los parámetros deben estar en formato JSON: {error}",
"shortcut.no_command": "no existe el comando `{id}`; el texto anterior al JSON debe ser un ID de comando",
"shortcut.pin": "Fijar en la parte superior del cuadro S",
"shortcut.unpin": "Desfijar",
"sketch is missing": "falta el boceto",
"sketch.degrees_of_freedom": "{count} grados de libertad",
"sketch.dof_left": "Quedan {count} grados de libertad",
"sketch.dof_left_one": "Queda {count} grado de libertad",
"sketch.draw_curves": "Dibujar como {linetype}",
"sketch.make_selection": "Convertir la selección a {linetype}",
"sketch.open_ends": "Abiertos {count}",
"sketch.status_conflict": "restricciones en conflicto",
"sketch.status_fully_constrained": "totalmente restringido",
"sketch.untied_ends": "Sin vincular {count}",
"sketch_panel.attached": "Vinculado a {body} / {path}",
"sketch_panel.author": "Ubicación de autoría: {path}",
@@ -1763,7 +1922,24 @@
"sketch_text.path_hint": "Curva del boceto que seguirá el texto: haz clic aquí y después en la curva",
"sketch_text.use_font_file": "Usar el archivo de fuente {path}",
"solid": "sólido",
"the angle must be a number": "el ángulo debe ser un número",
"the curves must be in one sketch": "las curvas deben estar en un solo boceto",
"the direction must be an axis, a sketch line or a straight edge": "la dirección debe ser un eje, una línea de boceto o una arista recta",
"the duration must be a number of seconds, 0.001 or more": "la duración debe ser un número de segundos, 0.001 o más",
"the line's sketch is gone": "el boceto de la línea ya no existe",
"the lines must be in one sketch": "las líneas deben estar en un solo boceto",
"the lines must be in one sketch, not the section's": "las líneas deben estar en un solo boceto, no en el de la sección",
"the parts library is empty": "la biblioteca de piezas está vacía",
"the parts library is not available": "la biblioteca de piezas no está disponible",
"the path curves must be in one other sketch": "las curvas de la trayectoria deben estar en un solo boceto distinto",
"the path's sketch is gone": "el boceto de la trayectoria ya no existe",
"the position must be a number": "la posición debe ser un número",
"the preview failed": "falló la vista previa",
"the profiles and curves must be in one sketch": "los perfiles y las curvas deben estar en un solo boceto",
"the reference face must be on the edges' body": "la cara de referencia debe estar en el cuerpo de las aristas",
"the scale must be above 0": "la escala debe ser mayor que 0",
"the section's profiles must be in one sketch": "los perfiles de la sección deben estar en un solo boceto",
"the two origins are on the same component": "los dos orígenes están en el mismo componente",
"thread.automatic_size": "Tamaño automático",
"thread.designation": "Designación",
"thread.iso_metric": "Métrica ISO",
@@ -1790,6 +1966,7 @@
"trace.points": "{count} puntos a lo largo de la trayectoria",
"trace.stopped_by_contact": "Termina en la muestra {sample}: {a} atravesaría {b}",
"trace.stopped_by_loop": "Termina en la muestra {sample}: el bucle que pasa por {joint} no puede cerrarse más",
"trim by sketch curves, or by one plane or face": "recorta con curvas de boceto, o con un plano o una cara",
"ui.1_degree_of_freedom": "1 grado de libertad",
"ui.3d_mouse_axes_reassigned": "Los ejes están reasignados en Preferencias, y eso sigue aplicándose sobre esta calibración.",
"ui.3d_mouse_button": "Botón {number}",
@@ -2216,6 +2393,8 @@
"ui.design_properties.revision": "Revisión",
"ui.diameter": "Diámetro",
"ui.dimension": "Cota",
"ui.direct_interaction": "Interacción directa",
"ui.direct_interaction_note": "Trabaja directamente sobre el modelo en la vista. Pulsa una cara plana o un perfil y tira: hacia arriba extruye, hacia abajo dentro de un cuerpo corta, y el movimiento lateral fija el paso",
"ui.direction": "Dirección",
"ui.display_quality": "Calidad de visualización",
"ui.display_quality_coarse": "Baja",
@@ -2239,6 +2418,7 @@
"ui.editJointLimits": "Editar límites de unión",
"ui.edit_section_analysis": "Editar análisis de sección",
"ui.ellipse": "Elipse",
"ui.emboss_wrap_note": "Los perfiles de líneas ortogonales tangentes a un cilindro compatible se envuelven automáticamente. Elegir una pared para definir el destino.",
"ui.end_radius": "Radio final",
"ui.end_scale": "Escala final",
"ui.entities": "Entidades",
@@ -2304,6 +2484,7 @@
"ui.heading_extrude": "EXTRUIR",
"ui.heading_fillet": "REDONDEO",
"ui.heading_finish_sketch": "FINALIZAR BOCETO",
"ui.heading_form": "FORMA",
"ui.heading_front": "FRONTAL",
"ui.heading_hole": "AGUJERO",
"ui.heading_home": "INICIO",
@@ -2352,6 +2533,7 @@
"ui.heading_utilities": "UTILIDADES",
"ui.heading_utility": "UTILIDAD",
"ui.heading_weldments": "SOLDADURA",
"ui.height": "Altura",
"ui.help": "Ayuda",
"ui.hide": "Ocultar",
"ui.hideAxes": "Ocultar ejes",
@@ -2379,11 +2561,14 @@
"ui.intersect": "Intersecar",
"ui.isolate": "Aislar",
"ui.join": "Unir",
"ui.joint_play": "▶ Reproducir",
"ui.joint_stop": "■ Detener",
"ui.joints": "Uniones",
"ui.keyboard_shortcuts": "Atajos de teclado",
"ui.language": "Idioma",
"ui.layout_compact": "Compacta",
"ui.layout_floating": "Flotante",
"ui.length": "Longitud",
"ui.length_decimals": "Decimales de longitud",
"ui.light": "Claro",
"ui.line": "Línea",
@@ -2391,6 +2576,7 @@
"ui.loft": "Solevación",
"ui.look_at": "Mirar hacia",
"ui.look_at_anim_desc": "Vista de eje, Mirar hacia, Inicio y Ajustar",
"ui.major_radius": "Radio mayor",
"ui.manipulator_free_alt": "Arrastre libre del manipulador también con Alt/Option",
"ui.manipulator_free_alt_tip": "Activado: Alt/Option o Ctrl/Cmd sobre las flechas de extrusión / manipulador desactiva el ajuste de valores. Desactivado: solo Ctrl/Cmd.",
"ui.manufacture": "Fabricación",
@@ -2420,8 +2606,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF con etiquetas de cara",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "Radio menor",
"ui.mirror": "Simetría",
"ui.mirror_line": "Línea de simetría",
"ui.modifiers_either": "{first} o {second}",
"ui.move": "Mover",
"ui.multiple": "Múltiple",
"ui.named_views": "Vistas guardadas",
@@ -2520,6 +2708,7 @@
"ui.reverse_horizontal_pan_direction": "Invertir dirección del desplazamiento horizontal",
"ui.reverse_horizontal_pan_tip": "El desplazamiento horizontal con dos dedos y la rueda de pulgar desplazan en sentido contrario",
"ui.reverse_zoom_direction": "Invertir dirección del zoom",
"ui.revolutions": "Vueltas",
"ui.revolve": "Revolución",
"ui.ribbon_exit": "Salir",
"ui.ribbon_labels": "Mostrar texto bajo los iconos de la cinta",
@@ -2535,6 +2724,7 @@
"ui.scale": "Escala",
"ui.second_rail": "Segunda línea guía",
"ui.section_analysis": "Análisis de sección",
"ui.section_size": "Tamaño de la sección",
"ui.select": "Seleccionar",
"ui.selectOther": "Seleccionar otro…",
"ui.selectTangentChain": "Seleccionar cadena tangente",
@@ -2585,6 +2775,7 @@
"ui.start": "Iniciar",
"ui.start_over": "Volver a empezar",
"ui.start_page": "Página de inicio",
"ui.stitch_tolerance_hint": "estricta",
"ui.stretch": "Estirar",
"ui.supersampling": "Supermuestreo (SSAA)",
"ui.supersampling_adaptive": "Solo cuando la vista está inmóvil",
@@ -2615,6 +2806,8 @@
"ui.to_object": "Hasta objeto",
"ui.tool_direction": "Dirección de herramienta",
"ui.top": "Superior",
"ui.top_diameter": "Diámetro superior",
"ui.top_radius": "Radio superior",
"ui.torus": "Toro",
"ui.total_angle": "Ángulo total",
"ui.trackpad_pan_tip": "Los gestos del panel táctil desplazan la vista (desactivado: hacen zoom como la rueda); la rueda del ratón hace zoom, la rueda lateral desplaza horizontalmente y el gesto de pellizco siempre hace zoom",
@@ -2640,6 +2833,7 @@
"ui.visual_shaded_with_edges": "Sombreado con aristas",
"ui.visual_style": "Estilo visual",
"ui.visual_wireframe": "Estructura alámbrica",
"ui.width": "Anchura",
"ui.workspace": "espacio de trabajo",
"ui.workspace_animation_description": "Vistas explosionadas, estudios de movimiento y guiones gráficos",
"ui.workspace_available": "Disponible",
@@ -2695,5 +2889,8 @@
"update.up_to_date": "SolidCraft está actualizado.",
"update.update_now": "Actualizar ahora",
"update.you_have": "Tienes la versión {version}.",
"use a positive nominal diameter and a pitch smaller than it": "usa un diámetro nominal positivo y un paso menor que él",
"values must be finite numbers": "los valores deben ser números finitos",
"values must be numbers or expressions": "los valores deben ser números o expresiones",
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ elegir · Intro / Tab completar · Esc cerrar"
}
+202
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(règle active)",
"0 turns it off": "0 le désactive",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Ouvrir le brouillon GitHub ci-dessous, puis coller le rapport copié dans le presse-papiers.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Ouvrir le brouillon GitHub ci-dessous. Votre titre et votre rapport y seront déjà remplis.",
@@ -49,15 +50,19 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "Appliquez d’abord votre apparence. Exporte les apparences attribuées et les matériaux créés dans cette conception.",
"Arc length": "Longueur d'arc",
"Area": "Aire",
"As Picked": "Tel que sélectionné",
"As-Built": "Tel que construit",
"Assign Rule": "Attribuer une règle",
"Attachment": "Rattachement",
"BLEND SURFACE": "SURFACE DE RACCORD",
"BOUNDARY SURFACE": "SURFACE FRONTIÈRE",
"BROWSER": "NAVIGATEUR",
"Ball": "Rotule",
"Bar": "Plat",
"Base Height": "Hauteur de la base",
"Bend": "Angle de pli",
"Bend Edges": "Arêtes de pli",
"Bend Line": "Ligne de pli",
"Bend Line Position": "Position de la ligne de pli",
"Bend Position": "Position du pli",
"Bend Radius": "Rayon de pliage",
@@ -69,6 +74,7 @@
"Body (last if none)": "Corps (le dernier si aucun)",
"Body to split": "Corps à scinder",
"Body, or faces to take out": "Corps, ou faces à retirer",
"Both": "Les deux",
"Bottom Left": "Bas gauche",
"Bottom Middle": "Bas centre",
"Bottom Right": "Bas droite",
@@ -100,6 +106,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "Choisir un nouveau plan. La géométrie et les cotes de l'esquisse restent inchangées dans ses coordonnées bidimensionnelles.",
"Choose…": "Choisir…",
"Circle center": "Centre du cercle",
"Circle or sphere": "Cercle ou sphère",
"Circular": "Circulaire",
"Circumference": "Circonférence",
"Clockwise": "Horaire",
@@ -116,6 +123,7 @@
"Config Table": "Table de config.",
"Configuration": "Configuration",
"Configuration rules": "Règles de configuration",
"Constant radius": "Rayon constant",
"Contact": "Contact",
"Contact Sets": "Jeux de contacts",
"Contact sets": "Jeux de contact",
@@ -150,7 +158,9 @@
"Custom": "Personnalisé",
"Customize Toolbar": "Personnaliser la barre d'outils",
"Customize…": "Personnaliser…",
"Cylindrical": "Pivot glissant",
"Cylindrical face": "Face cylindrique",
"Deboss": "Embossage en creux",
"Delete": "Supprimer",
"Delete Selected Features…": "Supprimer les fonctions sélectionnées…",
"Delete Selected Folders": "Supprimer les dossiers sélectionnés",
@@ -176,6 +186,7 @@
"Drag to move the hole; click to remove it": "Faire glisser pour déplacer le perçage ; cliquer pour le retirer",
"Drive Joint": "Piloter la liaison",
"Duration": "Durée",
"Edge": "Arête",
"Edges": "Arêtes",
"Edit": "Modifier",
"Edit Profile Sketch": "Modifier l'esquisse du profil",
@@ -184,6 +195,7 @@
"End Radius": "Rayon final",
"End bulge": "Renflement de fin",
"End continuity": "Continuité de fin",
"Equal Distance": "Distance égale",
"Expand": "Développer",
"Expected result (optional)": "Résultat attendu (facultatif)",
"Explode": "Éclater",
@@ -211,6 +223,8 @@
"Faces": "Faces",
"Faces / edges / vertices": "Faces / arêtes / sommets",
"Faces to split": "Faces à scinder",
"Faces/Body": "Faces/Corps",
"Factor must be a positive number": "Le facteur doit être un nombre strictement positif",
"Fastener": "Fixation",
"Favorites": "Favoris",
"Favourite": "Favori",
@@ -220,9 +234,12 @@
"Filter…": "Filtrer…",
"Find in Browser": "Trouver dans le navigateur",
"Finish": "Terminer",
"First edge": "Première arête",
"First plane": "Premier plan",
"First point": "Premier point",
"Fit and G2 corners require Constant radius.": "L'ajustement et les angles G2 nécessitent un rayon constant.",
"Fixed Face": "Face fixe",
"Flange Gap": "Jeu de bord tombé",
"Flange thickness": "Épaisseur d'aile",
"Flanges": "Bords tombés",
"Flat Pattern": "Dépliage",
@@ -230,8 +247,10 @@
"Follow camera (Look At sketches)": "Suivre la caméra (vue normale aux esquisses)",
"Follow the camera (Look At sketches)": "Suivre la caméra (vue normale aux esquisses)",
"Font": "Police",
"Free Move": "Déplacement libre",
"From": "De",
"From Bodies": "À partir de corps",
"From Snap": "Depuis l'accrochage",
"From edges": "Arêtes de départ",
"Full Length": "Longueur totale",
"Full thread depth": "Profondeur de filetage complète",
@@ -243,10 +262,13 @@
"Halo under sketch curves": "Halo sous les courbes d'esquisse",
"Height": "Hauteur",
"Height From": "Hauteur depuis",
"Hem Gap": "Jeu d'ourlet",
"Hidden edges": "Arêtes cachées",
"History layout": "Disposition de l’historique",
"History names": "Noms dans l'historique",
"Hole (optional)": "Perçage (facultatif)",
"Hole Depth": "Profondeur du trou",
"Hole Diameter": "Diamètre du trou",
"Holes": "Trous",
"Holes (edges on them)": "Trous (par leurs arêtes)",
"Home view": "Vue d'accueil",
@@ -269,12 +291,16 @@
"Issue title": "Titre du ticket",
"Items": "Éléments",
"JOINTS": "LIAISONS",
"Joint 1": "Liaison 1",
"Joint 2": "Liaison 2",
"Joint Origin1": "Origine de liaison1",
"K Factor": "Facteur K",
"Keep (points on it)": "À conserver (points dessus)",
"Keep Tools": "Conserver les outils",
"Keep of the other surface": "À conserver de l'autre surface",
"Key a joint's value at this step": "Placer une image clé de la valeur d'une liaison à cette étape",
"Keys": "Images clés",
"Knife Edge": "Arête vive",
"L-Angle": "Cornière",
"LIBRARY": "BIBLIOTHÈQUE",
"LINKS": "LIENS",
@@ -287,9 +313,11 @@
"Letter Spacing": "Espacement des lettres",
"Library": "Bibliothèque",
"Library file": "Fichier de bibliothèque",
"Library response is missing": "La réponse de la bibliothèque est manquante",
"Limits": "Limites",
"Line Spacing": "Interligne",
"Line Type": "Type de ligne",
"Line on plane": "Ligne sur plan",
"Lines": "Lignes",
"Listing the installed fonts…": "Liste des polices installées…",
"Load library": "Charger la bibliothèque",
@@ -309,11 +337,14 @@
"Material Outside": "Matière à l'extérieur",
"Material copied. Existing body assignments are unchanged.": "Matériau copié. Les affectations existantes des corps sont inchangées.",
"Max": "Max",
"Max Thickness": "Épaisseur max.",
"Maximum": "Maximum",
"Mesh body": "Corps maillé",
"Mid Radius": "Rayon intermédiaire",
"Middle double-click": "Double-clic milieu",
"Min": "Min",
"Min Draft": "Dépouille min.",
"Min Thickness": "Épaisseur min.",
"Minimum": "Minimum",
"Mirror Plane": "Plan de symétrie",
"Mitre": "Onglet",
@@ -333,6 +364,7 @@
"Name": "Nom",
"Name on import": "Nom à l'importation",
"Nearest": "Corps le plus proche",
"Neutral plane": "Plan neutre",
"New": "Nouveau",
"New Comp.": "Nouv. comp.",
"New Sketch": "Nouvelle esquisse",
@@ -343,6 +375,7 @@
"No matching appearances": "Aucune apparence correspondante",
"No matching physical materials.": "Aucun matériau physique correspondant.",
"No visible bodies or sketches to export.": "Aucun corps ni esquisse visible à exporter.",
"Nominal Radius": "Rayon nominal",
"Nominal diameter": "Diamètre nominal",
"None": "Aucun",
"Not available yet": "Pas encore disponible",
@@ -371,22 +404,28 @@
"Overall length": "Longueur hors tout",
"Param. Graph": "Graphe param.",
"Parameter": "Paramètre",
"Part length must be greater than zero and at most 2000 mm": "La longueur de la pièce doit être supérieure à zéro et d'au plus 2000 mm",
"Parts": "Pièces",
"Pass through": "Passer par",
"Path": "Trajectoire",
"Pattern": "Répétition",
"Per Edge": "Par arête",
"Physical material definitions": "Définitions de matériaux physiques",
"Pick a part size": "Choisir une taille de pièce",
"Pick the tool bodies": "Choisir les corps outils",
"Picked": "Sélectionnés",
"Picked point": "Point choisi",
"Pin-slot": "Axe-rainure",
"Pitch": "Pas",
"Pivot": "Pivot",
"Place at the origin instead": "Placer plutôt à l'origine",
"Planar": "Plan",
"Plastic Rules": "Règles plastique",
"Play the joint's motion in the view": "Lire le mouvement de la liaison dans la vue",
"Playback": "Lecture",
"Plot": "Graphique",
"Point on line": "Point sur ligne",
"Point on plane": "Point sur plan",
"Position": "Position",
"Position (0 to 1)": "Position (0 à 1)",
"Position (G0)": "Position (G0)",
@@ -399,6 +438,7 @@
"Profiles or curves": "Profils ou courbes",
"Profiles/Curves": "Profils/Courbes",
"Quantity": "Quantité",
"Quantity must be at least 2": "La quantité doit être d'au moins 2",
"RECENT": "RÉCENTS",
"REFERENCE": "RÉFÉRENCE",
"RULED SURFACE": "SURFACE RÉGLÉE",
@@ -412,6 +452,8 @@
"Rectangular": "Rectangulaire",
"Rectangular Tube": "Tube rectangulaire",
"Reference face": "Face de référence",
"Relief Depth": "Profondeur de dégagement",
"Relief Width": "Largeur de dégagement",
"Remove Tools": "Retirer les outils",
"Remove condition": "Supprimer la condition",
"Remove from Folder": "Retirer du dossier",
@@ -437,6 +479,7 @@
"Restore this studio's tools": "Restaurer les outils de ce studio",
"Result": "Résultat",
"Retake screenshot": "Reprendre la capture d'écran",
"Reveal Height": "Hauteur de décroché",
"Reverse": "Inverser",
"Reverse Direction": "Inverser la direction",
"Revert": "Rétablir",
@@ -445,12 +488,15 @@
"Revert Position": "Rétablir la position",
"Review the report and screenshot before opening GitHub.": "Relisez le rapport et la capture d'écran avant d'ouvrir GitHub.",
"Review your report on GitHub and click Submit new issue to publish it.": "Vérifiez votre rapport sur GitHub et cliquez sur Submit new issue pour le publier.",
"Revolute": "Pivot",
"Rib Length": "Longueur de nervure",
"Rib Offset": "Décalage de nervure",
"Rib Thickness": "Épaisseur de nervure",
"Ribs": "Nervures",
"Right Middle": "Milieu droite",
"Rigid": "Rigide",
"Rim Edge": "Arête du bord",
"Rim face": "Face de bord",
"Ring of tools on the right button": "Anneau d'outils sur le bouton droit",
"Roll Back Here": "Revenir ici dans l'historique",
"Roll History Marker Here": "Placer le marqueur d'historique ici",
@@ -475,7 +521,9 @@
"Search": "Rechercher",
"Search commands": "Rechercher des commandes",
"Search this library": "Rechercher dans cette bibliothèque",
"Second edge": "Deuxième arête",
"Second plane": "Second plan",
"Second point": "Deuxième point",
"Section": "Coupe",
"Section (optional)": "Section (facultative)",
"Section position": "Position de la section",
@@ -485,6 +533,15 @@
"Select bodies (a face picks its body)": "Sélectionner des corps (une face sélectionne son corps)",
"Select bodies or faces instead": "Sélectionner plutôt des corps ou des faces",
"Select edges": "Sélectionner des arêtes",
"Select points of the sketch being edited": "Sélectionner des points de l'esquisse en cours de modification",
"Select the centre the pattern turns around first": "Sélectionner d'abord le centre autour duquel la répétition pivote",
"Select the curves to offset first": "Sélectionner d'abord les courbes à décaler",
"Select the mirror line": "Sélectionner la ligne de symétrie",
"Select the sketch curves or points to mirror first": "Sélectionner d'abord les courbes ou points d'esquisse à symétriser",
"Select the sketch curves or points to move first": "Sélectionner d'abord les courbes ou points d'esquisse à déplacer",
"Select the sketch curves or points to pattern first": "Sélectionner d'abord les courbes ou points d'esquisse à répéter",
"Select the sketch curves or points to scale first": "Sélectionner d'abord les courbes ou points d'esquisse à mettre à l'échelle",
"Select the sketch curves or points to transform first": "Sélectionner d'abord les courbes ou points d'esquisse à transformer",
"Selection filter": "Filtre de sélection",
"Semantic faces share their appearance across instances.": "Les faces sémantiques partagent leur apparence entre les instances.",
"Send your report on GitHub": "Envoyer votre rapport sur GitHub",
@@ -504,9 +561,12 @@
"Sketch geometry and profiles": "Géométrie et profils d'esquisse",
"Sketch plane has no body-face attachment.": "Le plan d'esquisse n'est rattaché à aucune face de corps.",
"Sketch points": "Points d'esquisse",
"Slider": "Glissière",
"Slot width": "Largeur de rainure",
"Snap to face and edge centres": "Accrocher aux centres des faces et des arêtes",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft s'est fermé avant l'enregistrement de ces conceptions. Leur dernier enregistrement automatique peut être ouvert.",
"Spacing 2 must be a non-zero number": "L'espacement 2 doit être un nombre non nul",
"Spacing must be a non-zero number": "L'espacement doit être un nombre non nul",
"Specialise": "Spécialiser",
"Speed": "Vitesse",
"Splitting tool": "Outil de scission",
@@ -517,6 +577,7 @@
"Start angle": "Angle de départ",
"Start bulge": "Renflement de début",
"Start continuity": "Continuité de début",
"Stationary Side": "Côté fixe",
"Step": "Étape",
"Steps": "Étapes",
"Steps to reproduce (optional)": "Étapes pour reproduire le problème (facultatives)",
@@ -530,6 +591,7 @@
"Suppressed": "Désactivé",
"Surface": "Surface",
"Surface, or faces to turn over": "Surface, ou faces à retourner",
"Surfaces": "Surfaces",
"Swap Ends": "Permuter les extrémités",
"TRIM": "AJUSTER",
"Tangent": "Tangence",
@@ -540,24 +602,34 @@
"Tap drill diameter": "Diamètre de l'avant-trou",
"Target": "Cible",
"Target Body": "Corps cible",
"Target Face (optional)": "Face cible (facultatif)",
"Tear": "Déchirure",
"Technical details": "Détails techniques",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "L'esquisse en pointillés est un guide de plan enregistré. Sélectionnez une nouvelle face pour réparer le rattachement.",
"The design changed. Reopen Change Part Size for the component.": "La conception a changé. Rouvrir Changer la taille de la pièce pour le composant.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "La direction doit être un axe ou une courbe d'esquisse droite située dans le plan de l'esquisse",
"The mirror line cannot also be mirrored": "La ligne de symétrie ne peut pas être elle-même symétrisée",
"The mirror line must be a straight curve of this sketch, not an origin axis": "La ligne de symétrie doit être une courbe droite de cette esquisse, et non un axe de l'origine",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "L'occurrence d'auteur enregistrée est introuvable. Sélectionnez un placement d'auteur valide avant de relier.",
"Then": "Alors",
"These features will be deleted:": "Ces fonctions seront supprimées :",
"These features will fail:": "Ces fonctions échoueront :",
"Thickness Outside": "Épaisseur extérieure",
"Thickness Variation": "Variation d'épaisseur",
"Thin": "Mince",
"Thin Extrude": "Extrusion mince",
"Third plane": "Troisième plan",
"Third point": "Troisième point",
"This child is shared. Deleting it removes it from every copy of its parent.": "Cet enfant est partagé. Le supprimer le retire de toutes les copies de son parent.",
"This child is shared. Position changes apply to every copy of its parent.": "Cet enfant est partagé. Les changements de position s'appliquent à toutes les copies de son parent.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "Cette face ne peut pas fournir de rattachement durable. Choisissez une autre face ou utilisez explicitement un plan fixe.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "Cette image n'est pas encore jointe sur GitHub. Copiez-la ou enregistrez-la, puis joignez-la sur GitHub.",
"Thread depth": "Profondeur de filetage",
"Thread diameter": "Diamètre de filetage",
"Through point": "Par un point",
"To": "À",
"To Offset": "Jusqu'au décalage",
"To Snap": "Vers l'accrochage",
"To edges": "Arêtes d'arrivée",
"Toe radius": "Rayon d'extrémité",
"Tolerance": "Tolérance",
@@ -571,6 +643,7 @@
"Trimming tool (plane, face or curves)": "Outil d'ajustement (plan, face ou courbes)",
"Turn off section analysis before exporting the view.": "Désactivez l'analyse de coupe avant d'exporter la vue.",
"Type": "Type",
"Type a distance or an angle to move by": "Saisir une distance ou un angle de déplacement",
"UNTRIM": "ANNULER L'AJUSTEMENT",
"Unit": "Unité",
"Unsuppress": "Réactiver",
@@ -614,6 +687,17 @@
"Z angle": "Angle Z",
"Z distance": "Distance Z",
"Zebra": "Zébrures",
"`joint` must be an id or a name": "`joint` doit être un identifiant ou un nom",
"`params` must be an object": "`params` doit être un objet",
"`values` must be a list": "`values` doit être une liste",
"a chamfer needs a corner of exactly two lines": "un chanfrein nécessite un coin formé d'exactement deux lignes",
"a file operation is in progress": "une opération sur un fichier est en cours",
"a picked curve is no longer in a sketch": "une courbe sélectionnée ne se trouve plus dans une esquisse",
"a picked curve's sketch has not been solved": "l'esquisse d'une courbe sélectionnée n'a pas été résolue",
"a picked edge has no points": "une arête sélectionnée n'a aucun point",
"a picked edge is gone": "une arête sélectionnée n'existe plus",
"a picked edge's body is gone": "le corps d'une arête sélectionnée n'existe plus",
"add a key for a joint first": "ajouter d'abord une clé pour une liaison",
"ai.connected_toast": "SolidCraft est maintenant disponible dans {clients}. Redémarrez-les pour l'utiliser (Paramètres > Assistant).",
"ai.prefs.allow_control": "Autoriser la connexion des agents IA (canal de contrôle / MCP)",
"ai.prefs.allow_control_note": "Ouvre un canal de contrôle limité à cet ordinateur (127.0.0.1, port 27878 ou le suivant disponible). Un programme qui se connecte doit aussi présenter un jeton secret lisible uniquement par votre compte utilisateur, régénéré à chaque démarrage. Prend effet au prochain démarrage de SolidCraft. Désactivé : rien n'écoute, sauf si vous lancez SolidCraft avec --control.",
@@ -650,6 +734,7 @@
"appearance.pbr_opaque": "PBR opaque",
"appearance.roughness": "Rugosité",
"appearance.surface_response": "Réponse de la surface",
"bom.group_children": "Sous-pièces dans la ligne de leur pièce",
"browser.body_name": "Corps{number}",
"browser.calibrate_title": "Calibrer : {name}",
"browser.capture_many": "{count} composants ont été déplacés, mais leurs positions ne sont pas capturées.",
@@ -660,6 +745,8 @@
"browser.move_title": "Déplacer : {name}",
"browser.parameters": "Paramètres ({count})",
"browser.precision": "Précision : {precision}",
"browser.sketch_attachment_lost": "{name} (attache perdue)",
"browser.sketch_editing": "{name} (en cours de modification)",
"browser.sketch_name": "Esquisse{number}",
"browser.units": "Unités : {units}",
"cam.flat": "Plateau",
@@ -669,6 +756,11 @@
"cam.roller": "Galet",
"cam.roller_pick": "Galet (facultatif)",
"cam.tip_pick": "Pointe (facultatif)",
"choose a profile": "choisir un profilé",
"choose the cam's and the follower's joints": "choisir les liaisons de la came et du suiveur",
"choose the joints to couple": "choisir les liaisons à coupler",
"click a plane or planar face": "cliquer sur un plan ou une face plane",
"click sketch curves": "cliquer sur des courbes d'esquisse",
"cmd.appearance_assign": "Apparence",
"cmd.appearance_library": "Bibliothèque d'apparences",
"cmd.appearance_list": "Lister les apparences",
@@ -1139,6 +1231,8 @@
"dxf.progress.write": "Écriture du DXF (5/5)",
"dxf.tolerance": "Tolérance des courbes",
"dxf.tolerance_help": "Corps visibles et esquisses affichées uniquement. Les courbes sont approchées par des segments de droite. Une tolérance plus faible donne des courbes plus fines, au prix de plus de temps et de mémoire.",
"each rail's curves must be in one sketch": "les courbes de chaque rail de guidage doivent être dans une seule esquisse",
"feature computation ended without a result": "le calcul de la fonction s'est terminé sans résultat",
"file.open.drawing_filter": "Conceptions, fichiers CAO, maillages et dessins",
"file_load.built": "Construit jusqu’ici : {built} entités sur {total}.",
"file_load.converting": "Conversion du solide {done} sur {total}",
@@ -1356,7 +1450,9 @@
"nav.free_orbit.help": "La souris et la souris 3D tournent en passant par les deux pôles et conservent le roulis. L'alignement des axes avec Maj est désactivé.",
"nav.free_orbit.label": "Orbite libre",
"nav.fusion.help": "Glisser avec le milieu fait un panoramique, Maj+milieu fait orbiter, glisser avec le droit fait orbiter",
"nav.hfss.help": "Alt+glisser gauche fait un panoramique, Maj+Alt+gauche zoome, Ctrl+glisser gauche sur un espace vide fait orbiter",
"nav.inventor.help": "Glisser avec le milieu fait un panoramique, Maj+milieu fait orbiter, Ctrl+milieu zoome, glisser avec le droit fait orbiter",
"nav.maya.help": "Alt+glisser gauche fait orbiter, Alt+milieu fait un panoramique, Alt+droit zoome ; glisser avec le milieu fait aussi un panoramique",
"nav.openscad.help": "Glisser avec le gauche dans le vide fait orbiter, Maj+glisser gauche sélectionne par rectangle, glisser la géométrie d'esquisse la modifie ; glisser avec le droit ou le milieu fait un panoramique, Maj+droit ou Maj+milieu zoome",
"nav.solidworks.help": "Glisser avec le milieu fait orbiter, Ctrl+milieu fait un panoramique, Maj+milieu zoome, glisser avec le droit fait orbiter",
"nav.tinkercad.help": "Glisser avec le droit fait orbiter, glisser avec le milieu ou Maj+droit fait un panoramique",
@@ -1372,9 +1468,34 @@
"no hole": "sans perçage",
"no interference": "aucune interférence",
"no joint that moves yet": "aucune liaison mobile pour l'instant",
"no motion study yet": "pas encore d'étude de mouvement",
"no picture": "aucune image",
"no such joint": "liaison introuvable",
"none": "aucun",
"not a move": "pas un déplacement",
"not a number": "pas un nombre",
"open a sketch first": "ouvrir d'abord une esquisse",
"parts.automatic_name": "automatique",
"parts.dimension.across_flats": "Sur plats",
"parts.dimension.bore": "Alésage",
"parts.dimension.d": "Diamètre nominal",
"parts.dimension.head_diameter": "Diamètre de tête",
"parts.dimension.head_height": "Hauteur de tête",
"parts.dimension.height": "Hauteur",
"parts.dimension.inner": "Diamètre intérieur",
"parts.dimension.outer": "Diamètre extérieur",
"parts.dimension.pitch": "Pas",
"parts.dimension.socket": "Empreinte",
"parts.dimension.socket_depth": "Profondeur empreinte",
"parts.dimension.thickness": "Épaisseur",
"parts.dimension.width": "Largeur",
"parts.family.bearing": "Roulement à billes à gorge profonde (enveloppe)",
"parts.family.dowel_pin": "Goupille cylindrique",
"parts.family.hex_bolt": "Vis à tête hexagonale",
"parts.family.hex_nut": "Écrou hexagonal",
"parts.family.set_screw": "Vis sans tête à six pans creux, bout plat",
"parts.family.socket_head_cap_screw": "Vis à tête cylindrique à six pans creux",
"parts.family.washer": "Rondelle plate",
"pattern.alignment_2": "Alignement 2",
"pattern.alignment_hint": "La quantité inclut l’original. Le centrage répartit les copies de chaque côté ; si la quantité est paire, l’inversion choisit le côté qui reçoit la copie supplémentaire.",
"pattern.direction_1": "Direction 1",
@@ -1390,9 +1511,25 @@
"perf.ui_time": "Temps de l'interface",
"perf.viewport": "Vue 3D",
"perf.worst": "pire",
"pick a body or some of its faces": "choisir un corps ou certaines de ses faces",
"pick a hole to seat it, or OK places it at the origin": "choisir un trou pour la loger, ou OK la place à l'origine",
"pick a planar face": "choisir une face plane",
"pick a plane or a face as the tool": "choisir un plan ou une face comme outil",
"pick a size": "choisir une taille",
"pick edges of a body": "choisir des arêtes d'un corps",
"pick edges of one body": "choisir des arêtes d'un seul corps",
"pick edges of the holes to remove": "choisir les arêtes des perçages à supprimer",
"pick faces of one body": "choisir des faces d'un seul corps",
"pick faces to offset": "choisir les faces à décaler",
"pick lines of one sketch": "choisir des lignes d'une seule esquisse",
"pick one or two vertices, edges or faces": "choisir un ou deux sommets, arêtes ou faces",
"pick one plane or face as the tool, or sketch curves": "choisir un plan ou une face comme outil, ou des courbes d'esquisse",
"pick sections in two or more sketches": "choisir des sections dans au moins deux esquisses",
"pick sketch curves or edges": "choisir des courbes d'esquisse ou des arêtes",
"pick the face to untrim": "choisir la face dont l'ajustement doit être annulé",
"pick the path": "choisir la trajectoire",
"pick what to keep": "choisir ce qu'il faut conserver",
"pick what to keep of the other surface": "choisir ce qu'il faut conserver de l'autre surface",
"prefs.add_item": "Ajouter l'élément",
"prefs.alt_frees_manipulators": "Alt / Option libère aussi les flèches du manipulateur",
"prefs.anti_aliasing_amd_dx12": "L'anticrénelage est à 1× car la vérification au démarrage n'a rien dessiné avec le multiéchantillonnage et a réussi à 1×. Vous pouvez choisir un autre réglage ci-dessus ; redémarrez pour l'appliquer si la vérification réussit.",
@@ -2156,6 +2293,26 @@
"search.try": "Saisissez un nom de commande, une entité de cette conception ou un paramètre. Pour exécuter une commande avec des valeurs, saisissez son id et un objet JSON : {example}",
"search.valid": "Valide",
"section.off_hint": "Aucun plan choisi : OK désactive la coupe.",
"select a direction (an axis, a sketch line or a straight edge) first": "sélectionner d'abord une direction (un axe, une ligne d'esquisse ou une arête droite)",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "sélectionner une direction (un axe, une ligne d'esquisse ou une arête droite) que le profil doit suivre",
"select a point on a component": "sélectionner un point sur un composant",
"select a profile, edges or sketch lines first": "sélectionner d'abord un profil, des arêtes ou des lignes d'esquisse",
"select an axis": "sélectionner un axe",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "sélectionner d'abord un axe, une arête droite ou circulaire, ou une face cylindrique, conique ou torique",
"select bodies first": "sélectionner d'abord des corps",
"select corner points, or the two lines of one corner": "sélectionner des points de coin, ou les deux lignes d'un coin",
"select one corner point, or the two lines of one corner": "sélectionner un point de coin, ou les deux lignes d'un coin",
"select sheet edges first": "sélectionner d'abord des arêtes de tôle",
"select the bend line (a sketch line) first": "sélectionner d'abord la ligne de pli (une ligne d'esquisse)",
"select the cam's profile (a sketch profile or the cam's edges)": "sélectionner le profil de la came (un profil d'esquisse ou les arêtes de la came)",
"select the corner to cut first": "sélectionner d'abord le coin à chanfreiner",
"select the corners to round first": "sélectionner d'abord les coins à arrondir",
"select the fixed face first (a plate's large face)": "sélectionner d'abord la face fixe (la grande face d'une plaque)",
"select the frame sketch's lines first": "sélectionner d'abord les lignes de l'esquisse de la structure",
"select the path (sketch lines across the edge)": "sélectionner la trajectoire (lignes d'esquisse qui traversent l'arête)",
"select the rim face first": "sélectionner d'abord la face du bord",
"select the sheet edge first": "sélectionner d'abord l'arête de la tôle",
"select two components": "sélectionner deux composants",
"set by the sketch's lines": "défini par les lignes de l'esquisse",
"settings.display_quality_note": "Les niveaux plus fins affichent plus lisses les faces et arêtes courbes, mais leur maillage prend plus de temps. Seule la vue change, jamais la conception ni les exports.",
"settings.frame_rate_details_note": "Ajoute un graphe des temps des dernières images avec les triangles dessinés superposés, un histogramme des temps d'image et ce que le GPU a dessiné. Cliquez sur la fréquence d'images dans la vue pour les afficher ou les masquer.",
@@ -2173,17 +2330,23 @@
"settings.window_system_details": "Détails",
"settings.window_system_note_now": "S'applique après un redémarrage. Actuellement : {now}.",
"settings.window_system_wayland_limited": "Certaines fonctionnalités sont limitées sous Wayland natif.",
"sheet.flange_type_base": "Base",
"sheet.flange_type_contour": "Contour",
"sheet.flange_type_edge": "Arête",
"sheet.no_body": "il n'y a pas de corps de tôlerie : commencez-en un avec Bord tombé > Base, ou transformez une plaque en tôlerie avec Convertir en tôlerie (choisissez sa grande face plane)",
"shortcut.json_error": "les paramètres doivent être au format JSON : {error}",
"shortcut.no_command": "la commande `{id}` n’existe pas ; le texte avant le JSON doit être un ID de commande",
"shortcut.pin": "Épingler en haut de la boîte S",
"shortcut.unpin": "Désépingler",
"sketch is missing": "l'esquisse est manquante",
"sketch.degrees_of_freedom": "{count} degrés de liberté",
"sketch.dof_left": "{count} degrés de liberté restants",
"sketch.dof_left_one": "{count} degré de liberté restant",
"sketch.draw_curves": "Dessiner en {linetype}",
"sketch.make_selection": "Convertir la sélection en {linetype}",
"sketch.open_ends": "{count} ouvertes",
"sketch.status_conflict": "contraintes en conflit",
"sketch.status_fully_constrained": "entièrement contrainte",
"sketch.untied_ends": "{count} sans coïncidence",
"sketch_panel.attached": "Attaché à {body} / {path}",
"sketch_panel.author": "Placement d’origine : {path}",
@@ -2210,7 +2373,24 @@
"sketch_text.path_hint": "Une courbe de l'esquisse que le texte suit : cliquer ici, puis sur la courbe",
"sketch_text.use_font_file": "Utiliser le fichier de police {path}",
"solid": "plein (sans paroi)",
"the angle must be a number": "l'angle doit être un nombre",
"the curves must be in one sketch": "les courbes doivent être dans une seule esquisse",
"the direction must be an axis, a sketch line or a straight edge": "la direction doit être un axe, une ligne d'esquisse ou une arête droite",
"the duration must be a number of seconds, 0.001 or more": "la durée doit être un nombre de secondes, d'au moins 0.001",
"the line's sketch is gone": "l'esquisse de la ligne n'existe plus",
"the lines must be in one sketch": "les lignes doivent être dans une seule esquisse",
"the lines must be in one sketch, not the section's": "les lignes doivent être dans une seule esquisse, pas celle de la section",
"the parts library is empty": "la bibliothèque de pièces est vide",
"the parts library is not available": "la bibliothèque de pièces n'est pas disponible",
"the path curves must be in one other sketch": "les courbes de la trajectoire doivent être dans une seule autre esquisse",
"the path's sketch is gone": "l'esquisse de la trajectoire n'existe plus",
"the position must be a number": "la position doit être un nombre",
"the preview failed": "l'aperçu a échoué",
"the profiles and curves must be in one sketch": "les profils et les courbes doivent être dans une seule esquisse",
"the reference face must be on the edges' body": "la face de référence doit appartenir au corps des arêtes",
"the scale must be above 0": "l'échelle doit être supérieure à 0",
"the section's profiles must be in one sketch": "les profils de la section doivent être dans une seule esquisse",
"the two origins are on the same component": "les deux origines se trouvent sur le même composant",
"thread.automatic_size": "Taille automatique",
"thread.designation": "Désignation",
"thread.iso_metric": "Métrique ISO",
@@ -2238,6 +2418,7 @@
"trace.points": "{count} points le long de la trajectoire",
"trace.stopped_by_contact": "Se termine à l'échantillon {sample} : {a} traverserait {b}",
"trace.stopped_by_loop": "Se termine à l'échantillon {sample} : la boucle passant par {joint} ne peut plus se fermer",
"trim by sketch curves, or by one plane or face": "ajuster avec des courbes d'esquisse, ou avec un plan ou une face",
"ui.1_degree_of_freedom": "1 degré de liberté",
"ui.3d_mouse_axes_reassigned": "Les axes sont réattribués dans les Préférences, et cela s'applique toujours en plus de ce calibrage.",
"ui.3d_mouse_button": "Bouton {number}",
@@ -2692,6 +2873,8 @@
"ui.design_properties.revision": "Indice",
"ui.diameter": "Diamètre",
"ui.dimension": "Cote",
"ui.direct_interaction": "Interaction directe",
"ui.direct_interaction_note": "Travailler directement sur le modèle dans la vue. Appuyer sur une face plane ou un profil et tirer : vers le haut extrude, vers le bas dans un corps découpe, et un mouvement latéral règle le pas",
"ui.direction": "Direction",
"ui.display_quality": "Qualité d'affichage",
"ui.display_quality_coarse": "Grossière",
@@ -2715,6 +2898,7 @@
"ui.editJointLimits": "Modifier les limites de liaison",
"ui.edit_section_analysis": "Modifier l'analyse de coupe",
"ui.ellipse": "Ellipse",
"ui.emboss_wrap_note": "Les profils de lignes orthogonales tangents à un cylindre pris en charge s'enroulent automatiquement. Choisir une paroi pour définir une cible.",
"ui.end_radius": "Rayon final",
"ui.end_scale": "Échelle finale",
"ui.entities": "Entités",
@@ -2786,6 +2970,7 @@
"ui.heading_extrude": "EXTRUSION",
"ui.heading_fillet": "CONGÉ",
"ui.heading_finish_sketch": "TERMINER L'ESQUISSE",
"ui.heading_form": "FORME",
"ui.heading_front": "AVANT",
"ui.heading_hole": "PERÇAGE",
"ui.heading_home": "ACCUEIL",
@@ -2834,6 +3019,7 @@
"ui.heading_utilities": "UTILITAIRES",
"ui.heading_utility": "UTILITAIRE",
"ui.heading_weldments": "MÉCANO-SOUDURE",
"ui.height": "Hauteur",
"ui.help": "Aide",
"ui.hide": "Masquer",
"ui.hideAxes": "Masquer les axes",
@@ -2870,11 +3056,14 @@
"ui.intersect": "Intersection",
"ui.isolate": "Isoler",
"ui.join": "Joindre",
"ui.joint_play": "▶ Lire",
"ui.joint_stop": "■ Arrêter",
"ui.joints": "Liaisons",
"ui.keyboard_shortcuts": "Raccourcis clavier",
"ui.language": "Langue",
"ui.layout_compact": "Compacte",
"ui.layout_floating": "Flottante",
"ui.length": "Longueur",
"ui.length_decimals": "Décimales des longueurs",
"ui.light": "Clair",
"ui.line": "Ligne",
@@ -2886,6 +3075,7 @@
"ui.loft": "Lissage",
"ui.look_at": "Vue normale",
"ui.look_at_anim_desc": "Vue d'axe, Vue normale, Accueil et Cadrer",
"ui.major_radius": "Grand rayon",
"ui.manipulator_free_alt": "Glissement libre du manipulateur aussi avec Alt/Option",
"ui.manipulator_free_alt_tip": "Activé : Alt/Option ou Ctrl/Cmd sur les flèches d’extrusion / du manipulateur désactive l’accrochage aux valeurs. Désactivé : Ctrl/Cmd uniquement.",
"ui.manufacture": "Fabrication",
@@ -2915,8 +3105,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF avec étiquettes de faces",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "Petit rayon",
"ui.mirror": "Symétrie",
"ui.mirror_line": "Ligne de symétrie",
"ui.modifiers_either": "{first} ou {second}",
"ui.move": "Déplacer",
"ui.multiple": "Multiple",
"ui.named_views": "Vues nommées",
@@ -2968,6 +3160,7 @@
"ui.pinToShortcuts": "Épingler aux raccourcis",
"ui.pinToToolbar": "Épingler à la barre d'outils",
"ui.pipe": "Tuyau",
"ui.pitch": "Pas",
"ui.placement": "Placement",
"ui.plane": "Plan",
"ui.plane_at_angle": "Plan incliné",
@@ -3027,6 +3220,7 @@
"ui.reverse_horizontal_pan_direction": "Inverser le sens du panoramique horizontal",
"ui.reverse_horizontal_pan_tip": "Le défilement horizontal à deux doigts et la molette latérale font le panoramique dans l'autre sens",
"ui.reverse_zoom_direction": "Inverser le sens du zoom",
"ui.revolutions": "Tours",
"ui.revolve": "Révolution",
"ui.ribbon_exit": "Quitter",
"ui.ribbon_labels": "Afficher le texte sous les icônes du ruban",
@@ -3042,6 +3236,7 @@
"ui.scale": "Échelle",
"ui.second_rail": "Second rail",
"ui.section_analysis": "Analyse de coupe",
"ui.section_size": "Taille de la section",
"ui.select": "Sélectionner",
"ui.selectOther": "Sélectionner un autre…",
"ui.selectTangentChain": "Sélectionner la chaîne tangente",
@@ -3102,6 +3297,7 @@
"ui.start_page": "Page d’accueil",
"ui.step_values": "Incrémenter les valeurs avec les flèches et la molette",
"ui.step_values_tip": "Dans un champ de valeur en cours de saisie, Haut/Bas modifient un nombre simple de 1 (Maj : 10, Alt : 0,1), de même que la molette de la souris au-dessus du champ. Les expressions restent telles que saisies.",
"ui.stitch_tolerance_hint": "serrée",
"ui.stretch": "Étirer",
"ui.supersampling": "Suréchantillonnage (SSAA)",
"ui.supersampling_adaptive": "Seulement quand la vue est immobile",
@@ -3132,6 +3328,8 @@
"ui.to_object": "Jusqu'à l'objet",
"ui.tool_direction": "Direction de l'outil",
"ui.top": "Dessus",
"ui.top_diameter": "Diamètre supérieur",
"ui.top_radius": "Rayon supérieur",
"ui.torus": "Tore",
"ui.total_angle": "Angle total",
"ui.trackpad_pan_tip": "Les gestes du pavé tactile font un panoramique (désactivé : ils zooment comme la molette) ; la molette zoome, la molette latérale fait un panoramique horizontal, le pincement zoome toujours",
@@ -3160,6 +3358,7 @@
"ui.visual_shaded_with_edges": "Ombré avec arêtes",
"ui.visual_style": "Style visuel",
"ui.visual_wireframe": "Filaire",
"ui.width": "Largeur",
"ui.window_system": "Système de fenêtrage",
"ui.window_system_auto": "Automatique",
"ui.window_system_wayland": "Wayland",
@@ -3220,6 +3419,9 @@
"update.up_to_date": "SolidCraft est à jour.",
"update.update_now": "Mettre à jour maintenant",
"update.you_have": "Vous avez la version {version}.",
"use a positive nominal diameter and a pitch smaller than it": "utiliser un diamètre nominal positif et un pas inférieur à ce diamètre",
"values must be finite numbers": "les valeurs doivent être des nombres finis",
"values must be numbers or expressions": "les valeurs doivent être des nombres ou des expressions",
"web.files.insert_drawings_hint": "Fichiers CAO, maillages, DXF ou SVG dans la conception ouverte",
"web.files.insert_stored_drawings_hint": "Dans la conception ouverte (fichiers CAO, maillages, DXF, SVG)",
"web.open_full": "Ouvrir dans SolidCraft",
+895 -1
View File
File diff suppressed because it is too large Load Diff
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(כלל פעיל)",
"0 turns it off": "הערך 0 מכבה",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. יש לפתוח למטה את הטיוטה ב־GitHub, ואז להדביק את הדוח שהועתק ללוח.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. יש לפתוח למטה את הטיוטה ב־GitHub. הכותרת והדוח ימולאו אוטומטית.",
@@ -51,16 +52,20 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "יש להחיל קודם את המראה. הייצוא כולל מראים שהוקצו וחומרים שנוצרו בתכן זה.",
"Arc length": "אורך קשת",
"Area": "שטח",
"As Picked": "כפי שנבחר",
"As-Built": "במצב הקיים",
"Assign Rule": "הקצאת כלל",
"Attachment": "הצמדה",
"BLEND SURFACE": "משטח מעבר",
"BOUNDARY SURFACE": "משטח גבול",
"BROWSER": "עץ התכן",
"Ball": "כדורי",
"Bar": "מוט",
"Base Center": "מרכז הבסיס",
"Base Height": "גובה הבסיס",
"Bend": "זווית כיפוף",
"Bend Edges": "מקצועות כיפוף",
"Bend Line": "קו כיפוף",
"Bend Line Position": "מיקום קו הכיפוף",
"Bend Position": "מיקום הכיפוף",
"Bend Radius": "רדיוס כיפוף",
@@ -72,6 +77,7 @@
"Body (last if none)": "גוף (האחרון אם לא נבחר)",
"Body to split": "הגוף לפיצול",
"Body, or faces to take out": "גוף, או פאות להסרה",
"Both": "שניהם",
"Bottom Left": "למטה משמאל",
"Bottom Middle": "למטה באמצע",
"Bottom Right": "למטה מימין",
@@ -103,6 +109,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "יש לבחור מישור חדש. הגאומטריה והמידות של הסקיצה נשארות ללא שינוי בקואורדינטות הדו־ממדיות שלה.",
"Choose…": "בחירה…",
"Circle center": "מרכז המעגל",
"Circle or sphere": "מעגל או כדור",
"Circular": "מעגלי",
"Circumference": "היקף",
"Clockwise": "בכיוון השעון",
@@ -119,6 +126,7 @@
"Config Table": "טבלת תצורות",
"Configuration": "תצורה",
"Configuration rules": "כללי תצורה",
"Constant radius": "רדיוס קבוע",
"Contact": "מגע",
"Contact Sets": "קבוצות מגע",
"Contact sets": "קבוצות מגע",
@@ -154,7 +162,9 @@
"Custom": "מותאם אישית",
"Customize Toolbar": "התאמת סרגל הכלים",
"Customize…": "התאמה אישית…",
"Cylindrical": "גלילי",
"Cylindrical face": "פאה גלילית",
"Deboss": "הטבעה",
"Delete": "מחיקה",
"Delete Folders and Features…": "מחיקת תיקיות עם הפיצ'רים שבהן…",
"Delete Selected Features…": "מחיקת הפיצ'רים שנבחרו…",
@@ -186,6 +196,7 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "יש לגרור כדי לסובב את המשען בצעדים של 5°. יש להחזיק Alt או Ctrl לסיבוב חופשי.",
"Drive Joint": "הנעת מפרק",
"Duration": "משך",
"Edge": "מקצוע",
"Edges": "מקצועות",
"Edit": "עריכה",
"Edit Profile Sketch": "עריכת סקיצת הפרופיל",
@@ -194,6 +205,7 @@
"End Radius": "רדיוס סיום",
"End bulge": "תפיחה בסוף",
"End continuity": "רציפות בסוף",
"Equal Distance": "מרחק שווה",
"Expand": "הרחבה",
"Expected result (optional)": "התוצאה הצפויה (אופציונלי)",
"Explode": "פירוק",
@@ -221,6 +233,8 @@
"Faces": "פאות",
"Faces / edges / vertices": "פאות / מקצועות / קודקודים",
"Faces to split": "פאות לפיצול",
"Faces/Body": "פאות/גוף",
"Factor must be a positive number": "המקדם חייב להיות מספר חיובי",
"Fastener": "מחבר",
"Favorites": "מועדפים",
"Favourite": "מועדף",
@@ -230,9 +244,12 @@
"Filter…": "סינון…",
"Find in Browser": "איתור בעץ התכן",
"Finish": "סיום",
"First edge": "מקצוע ראשון",
"First plane": "מישור ראשון",
"First point": "נקודה ראשונה",
"Fit and G2 corners require Constant radius.": "התאמה ופינות G2 דורשות רדיוס קבוע.",
"Fixed Face": "פאה קבועה",
"Flange Gap": "פער אוגן",
"Flange thickness": "עובי אוגן",
"Flanges": "אוגנים",
"Flat Pattern": "פריסה",
@@ -240,8 +257,10 @@
"Follow camera (Look At sketches)": "מעקב אחר המצלמה (הבטה אל סקיצות)",
"Follow the camera (Look At sketches)": "מעקב אחר המצלמה (הבטה אל סקיצות)",
"Font": "גופן",
"Free Move": "הזזה חופשית",
"From": "מ־",
"From Bodies": "מגופים",
"From Snap": "מנקודת הצמדה",
"From edges": "ממקצועות",
"Full Length": "לכל האורך",
"Full thread depth": "הברגה לכל העומק",
@@ -253,10 +272,13 @@
"Halo under sketch curves": "הילה מתחת לעקומות סקיצה",
"Height": "גובה",
"Height From": "גובה מ־",
"Hem Gap": "פער קיפול שפה",
"Hidden edges": "מקצועות נסתרים",
"History layout": "פריסת ציר הזמן",
"History names": "שמות בציר הזמן",
"Hole (optional)": "חור (אופציונלי)",
"Hole Depth": "עומק החור",
"Hole Diameter": "קוטר החור",
"Holes": "חורים",
"Holes (edges on them)": "חורים (המקצועות שלהם)",
"Home view": "תצוגת בית",
@@ -279,12 +301,16 @@
"Issue title": "כותרת הדיווח",
"Items": "פריטים",
"JOINTS": "מפרקים",
"Joint 1": "מפרק 1",
"Joint 2": "מפרק 2",
"Joint Origin1": "ראשית מפרק1",
"K Factor": "מקדם K",
"Keep (points on it)": "שמירה (נקודות עליו)",
"Keep Tools": "שמירת הכלים",
"Keep of the other surface": "החלק שנשמר מהמשטח השני",
"Key a joint's value at this step": "הוספת נקודת מפתח עם ערך המפרק בשלב זה",
"Keys": "נקודות מפתח",
"Knife Edge": "קצה חד",
"L-Angle": "זוויתן L",
"LIBRARY": "ספרייה",
"LINKS": "קישורים",
@@ -297,9 +323,11 @@
"Letter Spacing": "ריווח אותיות",
"Library": "ספרייה",
"Library file": "קובץ ספרייה",
"Library response is missing": "תגובת הספרייה חסרה",
"Limits": "גבולות",
"Line Spacing": "ריווח שורות",
"Line Type": "סוג קו",
"Line on plane": "קו על מישור",
"Lines": "קווים",
"Listing the installed fonts…": "טעינת רשימת הגופנים המותקנים…",
"Load library": "טעינת ספרייה",
@@ -319,11 +347,14 @@
"Material Outside": "חומר כלפי חוץ",
"Material copied. Existing body assignments are unchanged.": "החומר הועתק. הקצאות הגופים הקיימות לא השתנו.",
"Max": "מקסימום",
"Max Thickness": "עובי מרבי",
"Maximum": "מקסימום",
"Mesh body": "גוף רשת משולשים",
"Mid Radius": "רדיוס ביניים",
"Middle double-click": "לחיצה כפולה אמצעית",
"Min": "מינימום",
"Min Draft": "שיפוע יציקה מזערי",
"Min Thickness": "עובי מזערי",
"Minimum": "מינימום",
"Mirror Plane": "מישור שיקוף",
"Mitre": "מיטר",
@@ -343,6 +374,7 @@
"Name": "שם",
"Name on import": "שם בעת הייבוא",
"Nearest": "הקרוב ביותר",
"Neutral plane": "מישור ניטרלי",
"New": "חדש",
"New Comp.": "רכיב חדש",
"New Sketch": "סקיצה חדשה",
@@ -353,6 +385,7 @@
"No matching appearances": "אין מראות תואמים",
"No matching physical materials.": "לא נמצאו חומרים פיזיקליים תואמים.",
"No visible bodies or sketches to export.": "אין גופים או סקיצות גלויים לייצוא.",
"Nominal Radius": "רדיוס נומינלי",
"Nominal diameter": "קוטר נומינלי",
"None": "ללא",
"Not available yet": "עדיין לא זמין",
@@ -381,22 +414,28 @@
"Overall length": "אורך כולל",
"Param. Graph": "גרף פרמטרים",
"Parameter": "פרמטר",
"Part length must be greater than zero and at most 2000 mm": "אורך החלק חייב להיות גדול מאפס ולא יותר מ־2000 mm",
"Parts": "חלקים",
"Pass through": "מעבר דרך",
"Path": "מסלול",
"Pattern": "מערך",
"Per Edge": "לכל מקצוע",
"Physical material definitions": "הגדרות חומרים פיזיקליים",
"Pick a part size": "יש לבחור גודל לחלק",
"Pick the tool bodies": "יש לבחור את גופי הכלי",
"Picked": "נבחר",
"Picked point": "הנקודה שנבחרה",
"Pin-slot": "פין-חריץ",
"Pitch": "פסיעה",
"Pivot": "נקודת ציר",
"Place at the origin instead": "מיקום בראשית במקום זאת",
"Planar": "מישורי",
"Plastic Rules": "כללי פלסטיק",
"Play the joint's motion in the view": "הפעלת תנועת המפרק בתצוגה",
"Playback": "הפעלה",
"Plot": "גרף",
"Point on line": "נקודה על קו",
"Point on plane": "נקודה על מישור",
"Position": "מיקום",
"Position (0 to 1)": "מיקום (0 עד 1)",
"Position (G0)": "מיקום (G0)",
@@ -409,6 +448,7 @@
"Profiles or curves": "פרופילים או עקומות",
"Profiles/Curves": "פרופילים/עקומות",
"Quantity": "כמות",
"Quantity must be at least 2": "הכמות חייבת להיות 2 לפחות",
"RECENT": "אחרונים",
"REFERENCE": "ייחוס",
"RULED SURFACE": "משטח ישרים",
@@ -422,6 +462,8 @@
"Rectangular": "מלבני",
"Rectangular Tube": "צינור מלבני",
"Reference face": "פאת ייחוס",
"Relief Depth": "עומק הקלה",
"Relief Width": "רוחב הקלה",
"Remove Tools": "הסרת הכלים",
"Remove condition": "הסרת תנאי",
"Remove from Folder": "הסרה מהתיקייה",
@@ -450,6 +492,7 @@
"Restore this studio's tools": "שחזור הכלים של סביבה זו",
"Result": "תוצאה",
"Retake screenshot": "צילום מסך מחדש",
"Reveal Height": "גובה מדרגה",
"Reverse": "היפוך",
"Reverse Direction": "היפוך כיוון",
"Revert": "החזרה",
@@ -458,12 +501,15 @@
"Revert Position": "החזרת המיקום",
"Review the report and screenshot before opening GitHub.": "יש לבדוק את הדוח ואת צילום המסך לפני פתיחת GitHub.",
"Review your report on GitHub and click Submit new issue to publish it.": "יש לבדוק את הדיווח ב־GitHub וללחוץ על Submit new issue כדי לפרסם אותו.",
"Revolute": "סיבובי",
"Rib Length": "אורך צלע",
"Rib Offset": "היסט צלע",
"Rib Thickness": "עובי צלע",
"Ribs": "צלעות",
"Right Middle": "באמצע מימין",
"Rigid": "קשיח",
"Rim Edge": "מקצוע השפה",
"Rim face": "פאת שפה",
"Ring of tools on the right button": "טבעת כלים בלחצן הימני",
"Roll Back Here": "החזרת ציר הזמן עד כאן",
"Roll History Marker Here": "העברת סמן ציר הזמן לכאן",
@@ -488,16 +534,28 @@
"Search": "חיפוש",
"Search commands": "חיפוש פקודות",
"Search this library": "חיפוש בספרייה זו",
"Second edge": "מקצוע שני",
"Second plane": "מישור שני",
"Second point": "נקודה שנייה",
"Section": "חתך",
"Section (optional)": "חתך (אופציונלי)",
"Section position": "מיקום החתך",
"Sections (one sketch each)": "חתכים (סקיצה אחת לכל אחד)",
"Select Other": "בחירת אחר",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "בחירת אחר: החזקת הכפתור השמאלי ללא תזוזה על המודל (או לחיצה ימנית › בחירת אחר…) מציגה את כל מה שמתחת לסמן; לחיצה נוספת באותה נקודה בוחרת את הפריט הבא שם. לחיצה כפולה על הכפתור האמצעי חוזרת לתצוגת הבית (העדפות › ניווט).",
"Select Same Look": "בחר אותו מראה",
"Select bodies (a face picks its body)": "בחירת גופים (בחירת פאה בוחרת את הגוף שלה)",
"Select bodies or faces instead": "בחירת גופים או פאות במקום זאת",
"Select edges": "בחירת מקצועות",
"Select points of the sketch being edited": "יש לבחור נקודות של הסקיצה הנערכת",
"Select the centre the pattern turns around first": "יש לבחור תחילה את המרכז שסביבו המערך מסתובב",
"Select the curves to offset first": "יש לבחור תחילה את העקומות להיסט",
"Select the mirror line": "יש לבחור את קו השיקוף",
"Select the sketch curves or points to mirror first": "יש לבחור תחילה את עקומות הסקיצה או הנקודות לשיקוף",
"Select the sketch curves or points to move first": "יש לבחור תחילה את עקומות הסקיצה או הנקודות להזזה",
"Select the sketch curves or points to pattern first": "יש לבחור תחילה את עקומות הסקיצה או הנקודות למערך",
"Select the sketch curves or points to scale first": "יש לבחור תחילה את עקומות הסקיצה או הנקודות לשינוי קנה מידה",
"Select the sketch curves or points to transform first": "יש לבחור תחילה את עקומות הסקיצה או הנקודות להתמרה",
"Selection filter": "מסנן בחירה",
"Semantic faces share their appearance across instances.": "פאות סמנטיות חולקות את המראה שלהן בין המופעים.",
"Send your report on GitHub": "שליחת הדוח ב־GitHub",
@@ -517,9 +575,12 @@
"Sketch geometry and profiles": "גאומטריה ופרופילים של סקיצה",
"Sketch plane has no body-face attachment.": "למישור הסקיצה אין הצמדה לפאת גוף.",
"Sketch points": "נקודות סקיצה",
"Slider": "הזזה",
"Slot width": "רוחב חריץ",
"Snap to face and edge centres": "הצמדה למרכזי פאות ומקצועות",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft נסגרה לפני שתכנים אלה נשמרו. אפשר לפתוח את השמירה האוטומטית האחרונה שלהם.",
"Spacing 2 must be a non-zero number": "מרווח 2 חייב להיות מספר שונה מאפס",
"Spacing must be a non-zero number": "המרווח חייב להיות מספר שונה מאפס",
"Specialise": "התמחות",
"Speed": "מהירות",
"Splitting tool": "כלי פיצול",
@@ -530,6 +591,7 @@
"Start angle": "זווית התחלה",
"Start bulge": "תפיחה בהתחלה",
"Start continuity": "רציפות בהתחלה",
"Stationary Side": "צד קבוע",
"Step": "צעד",
"Steps": "צעדים",
"Steps to reproduce (optional)": "שלבים לשחזור (אופציונלי)",
@@ -544,6 +606,7 @@
"Suppressed": "מושבת",
"Surface": "משטח",
"Surface, or faces to turn over": "משטח, או פאות להיפוך",
"Surfaces": "משטחים",
"Swap Ends": "החלפת קצוות",
"TRIM": "גיזום",
"Tangent": "משיק",
@@ -554,24 +617,34 @@
"Tap drill diameter": "קוטר קידוח להברגה",
"Target": "יעד",
"Target Body": "גוף יעד",
"Target Face (optional)": "פאת יעד (אופציונלי)",
"Tear": "קריעה",
"Technical details": "פרטים טכניים",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "הסקיצה המקווקוות מסמנת מישור שמור. יש לבחור פאה חדשה כדי לתקן את ההצמדה.",
"The design changed. Reopen Change Part Size for the component.": "התכן השתנה. יש לפתוח מחדש את שינוי גודל חלק עבור הרכיב.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "הכיוון חייב להיות ציר או עקומת סקיצה ישרה הנמצאת במישור הסקיצה",
"The mirror line cannot also be mirrored": "אי אפשר לשקף גם את קו השיקוף עצמו",
"The mirror line must be a straight curve of this sketch, not an origin axis": "קו השיקוף חייב להיות עקומה ישרה של הסקיצה הזו, ולא אחד מצירי הראשית",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "מופע היצירה השמור חסר. יש לבחור מיקום יצירה תקין לפני הקישור מחדש.",
"Then": "אז",
"These features will be deleted:": "הפיצ'רים הבאים יימחקו:",
"These features will fail:": "הפיצ'רים הבאים ייכשלו:",
"Thickness Outside": "עובי כלפי חוץ",
"Thickness Variation": "שינוי עובי",
"Thin": "דופן דקה",
"Thin Extrude": "שליפה דקה",
"Third plane": "מישור שלישי",
"Third point": "נקודה שלישית",
"This child is shared. Deleting it removes it from every copy of its parent.": "צאצא זה משותף. מחיקתו מסירה אותו מכל עותק של רכיב האב.",
"This child is shared. Position changes apply to every copy of its parent.": "צאצא זה משותף. שינויי מיקום חלים על כל עותק של רכיב האב.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "פאה זו אינה מאפשרת הצמדה יציבה. יש לבחור פאה אחרת או להשתמש במפורש במישור קבוע.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "התמונה עדיין לא צורפה ב־GitHub. יש להעתיק או לשמור אותה, ואז לצרף אותה ב־GitHub.",
"Thread depth": "עומק הברגה",
"Thread diameter": "קוטר הברגה",
"Through point": "דרך נקודה",
"To": "אל",
"To Offset": "עד היסט",
"To Snap": "אל נקודת הצמדה",
"To edges": "עד המקצועות",
"Toe radius": "רדיוס קצה",
"Tolerance": "סבולת",
@@ -585,6 +658,7 @@
"Trimming tool (plane, face or curves)": "כלי גיזום (מישור, פאה או עקומות)",
"Turn off section analysis before exporting the view.": "יש לכבות את ניתוח החתך לפני ייצוא התצוגה.",
"Type": "סוג",
"Type a distance or an angle to move by": "יש להקליד מרחק או זווית להזזה",
"UNTRIM": "ביטול גיזום",
"Unit": "יחידה",
"Unsuppress": "ביטול השבתה",
@@ -629,6 +703,17 @@
"Z angle": "זווית Z",
"Z distance": "מרחק Z",
"Zebra": "זברה",
"`joint` must be an id or a name": "`joint` חייב להיות מזהה או שם",
"`params` must be an object": "`params` חייב להיות אובייקט",
"`values` must be a list": "`values` חייב להיות רשימה",
"a chamfer needs a corner of exactly two lines": "פאזה דורשת פינה של שני קווים בדיוק",
"a file operation is in progress": "פעולת קובץ מתבצעת כעת",
"a picked curve is no longer in a sketch": "העקומה שנבחרה כבר אינה בסקיצה",
"a picked curve's sketch has not been solved": "הסקיצה של העקומה שנבחרה טרם נפתרה",
"a picked edge has no points": "למקצוע שנבחר אין נקודות",
"a picked edge is gone": "המקצוע שנבחר כבר לא קיים",
"a picked edge's body is gone": "הגוף של המקצוע שנבחר כבר לא קיים",
"add a key for a joint first": "יש להוסיף תחילה מפתח למפרק",
"ai.connected_toast": "SolidCraft זמין עכשיו ב־{clients}. יש להפעיל אותם מחדש כדי להשתמש בו (הגדרות > עוזר).",
"ai.prefs.allow_control": "התרת חיבור לסוכני בינה מלאכותית (ערוץ בקרה / MCP)",
"ai.prefs.allow_control_note": "פותח ערוץ בקרה במחשב זה בלבד (127.0.0.1, פורט 27878 או הפנוי הבא). תוכנה שמתחברת צריכה גם להציג אסימון סודי שרק חשבון המשתמש שלך יכול לקרוא, ונוצר מחדש בכל הפעלה. ייכנס לתוקף בהפעלה הבאה של SolidCraft. כבוי: שום דבר אינו מאזין, אלא אם SolidCraft מופעל עם --control.",
@@ -669,6 +754,7 @@
"appearance.pbr_opaque": "PBR אטום",
"appearance.roughness": "חספוס",
"appearance.surface_response": "תגובת המשטח",
"bom.group_children": "תת-חלקים בשורת החלק שלהם",
"browser.body_name": "גוף{number}",
"browser.calibrate_title": "כיול: {name}",
"browser.capture_many": "{count} רכיבים הוזזו, אך המיקומים שלהם לא נלכדו.",
@@ -679,6 +765,8 @@
"browser.move_title": "הזזה: {name}",
"browser.parameters": "פרמטרים ({count})",
"browser.precision": "דיוק: {precision}",
"browser.sketch_attachment_lost": "{name} (ההצמדה אבדה)",
"browser.sketch_editing": "{name} (בעריכה)",
"browser.sketch_name": "סקיצה{number}",
"browser.units": "יחידות: {units}",
"cam.flat": "פאה שטוחה",
@@ -688,7 +776,13 @@
"cam.roller": "גלגלת",
"cam.roller_pick": "גלגלת (אופציונלי)",
"cam.tip_pick": "חוד (אופציונלי)",
"choose a profile": "יש לבחור פרופיל",
"choose the cam's and the follower's joints": "יש לבחור את מפרק הפיקה ואת מפרק העוקב",
"choose the joints to couple": "יש לבחור את המפרקים לצימוד",
"click a plane or planar face": "יש ללחוץ על מישור או על פאה מישורית",
"click sketch curves": "יש ללחוץ על עקומות סקיצה",
"cmd.appearance_assign": "מראה",
"cmd.appearance_chain": "שרשרת מראה",
"cmd.appearance_library": "ספריית מראים",
"cmd.appearance_list": "רשימת מראים",
"cmd.appearance_paint": "צביעת מראה",
@@ -1073,6 +1167,9 @@
"cmd.timeline_roll_to": "העברת סמן ציר הזמן",
"cmd.timeline_rollback": "הזזת סמן ציר הזמן",
"cmd.timeline_suppress": "השבתת פיצ'ר",
"cmd.view.render_browser": "דפדפן רינדור",
"cmd.view.render_dock": "הזז את עגינת הרינדור",
"cmd.view.render_focus": "תצוגת מיקוד רינדור",
"cmd.view_ambient_occlusion": "הצללה סביבתית",
"cmd.view_apply": "שחזור תצוגה שמורה",
"cmd.view_back": "תצוגה אחורית",
@@ -1183,6 +1280,8 @@
"dxf.progress.write": "כתיבת DXF (5/5)",
"dxf.tolerance": "סבולת עקומה",
"dxf.tolerance_help": "גופים גלויים בלבד. עקומות מורכבות מקטעים ישרים. סבולת קטנה יותר יוצרת עקומות עדינות יותר ודורשת יותר זמן וזיכרון.",
"each rail's curves must be in one sketch": "עקומות כל מסילה חייבות להיות בסקיצה אחת",
"feature computation ended without a result": "חישוב הפיצ'ר הסתיים ללא תוצאה",
"file.open.drawing_filter": "תכנים, קובצי CAD, רשתות משולשים ושרטוטים",
"file_load.built": "נבנו עד כה: {built} מתוך {total} פיצ'רים.",
"file_load.converting": "המרת גוף מוצק {done} מתוך {total}",
@@ -1344,6 +1443,8 @@
"keymap.command_id": "מזהה פקודה",
"keymap.empty": "אין פקודות תואמות",
"keymap.use_anyway": "שימוש ב־{key} כאן בכל זאת",
"label.move_to_left_side": "העבר לצד שמאל",
"label.move_to_right_side": "העבר לצד ימין",
"manage.appearance_hint": "יש לבחור מראה עבור הבחירה, או לגרור דוגמית אל גוף או פאה.",
"manage.assign_hint": "יש לבחור גופים ואת כלל הפלסטיק שלהם.",
"manage.config_hint": "עריכת השורות, העמודות והכללים של התצורה, ואז הפעלה או תצוגה מקדימה של שורה.",
@@ -1428,7 +1529,9 @@
"nav.free_orbit_upright.help": "גרירת העכבר הצידה מסובבת את המודל סביב הציר האנכי של העולם; גרירה למעלה ולמטה מטה אותו מעבר לקודקוד ללא הגבלה.",
"nav.free_orbit_upright.label": "סיבוב סביב הציר האנכי",
"nav.fusion.help": "גרירה אמצעית מזיזה, Shift וגרירה אמצעית מסובבים, גרירה ימנית מסובבת",
"nav.hfss.help": "Alt וגרירה שמאלית מזיזים, Shift+Alt וגרירה שמאלית מבצעים זום, Ctrl וגרירה שמאלית משטח ריק מסובבים",
"nav.inventor.help": "גרירה אמצעית מזיזה, Shift וגרירה אמצעית מסובבים, Ctrl וגרירה אמצעית מבצעים זום, גרירה ימנית מסובבת",
"nav.maya.help": "Alt וגרירה שמאלית מסובבים, Alt וגרירה אמצעית מזיזים, Alt וגרירה ימנית מבצעים זום; גם גרירה אמצעית מזיזה",
"nav.openscad.help": "גרירה שמאלית על שטח ריק מסובבת, Shift וגרירה שמאלית בוחרים במלבן, גרירת גאומטריית סקיצה עורכת אותה; גרירה ימנית או אמצעית מזיזה, Shift וגרירה ימנית או אמצעית מבצעים זום",
"nav.perspective.sketch": "עריכת סקיצה משתמשת בתצוגה אורתוגרפית. יש לסיים את הסקיצה כדי לעבור לפרספקטיבה.",
"nav.solidworks.help": "גרירה אמצעית מסובבת, Ctrl וגרירה אמצעית מזיזים, Shift וגרירה אמצעית מבצעים זום, גרירה ימנית מסובבת",
@@ -1439,6 +1542,93 @@
"nav.touchpad.pan": "הזזת תצוגה (החזקת Shift והזזה; ללא לחצן עכבר)",
"nav.touchpad.scroll": "במשטח מגע, גלילה אנכית מבצעת זום. הגדרת ההזזה בשתי אצבעות נשמרת עבור הערכות האחרות.",
"nav.touchpad.zoom": "זום (גלילה אנכית או צביטה)",
"navbar.agent_chat": "חלונית שיחת העוזר",
"navbar.agent_cursor": "הצגת סמן הסוכן",
"navbar.ambient_occlusion": "הצללה סביבתית (AO)",
"navbar.assistant": "עוזר",
"navbar.custom.add_slot": "הוספת {slot}",
"navbar.custom.always": "תמיד מוצג",
"navbar.custom.available": "{available} · גררו אל הסרגל או לחצו על הוספה",
"navbar.custom.buttons": "לחצנים",
"navbar.custom.compact": "דחוס",
"navbar.custom.count": "{count} מתוך 16 משבצות",
"navbar.custom.customise": "התאמת סרגל הניווט…",
"navbar.custom.design": "תכן",
"navbar.custom.duplicate": "המשבצת הזו כבר בסרגל.",
"navbar.custom.fade": "דהייה",
"navbar.custom.full": "הסירו משבצת כדי להוסיף אחרת.",
"navbar.custom.hidden_design": "מוסתר בתכן",
"navbar.custom.hidden_render": "מוסתר בהדמיה",
"navbar.custom.hide": "הסתרת סרגל הניווט",
"navbar.custom.hide_idle": "הסתרה עד מעבר עכבר",
"navbar.custom.icon_only": "סמל בלבד",
"navbar.custom.icon_value": "סמל וערך",
"navbar.custom.icons": "סמלים",
"navbar.custom.idle": "כשאין פעילות",
"navbar.custom.intro": "בחרו את הפקדים בסרגל שבתחתית התצוגה התלת־ממדית ואת סדרם. גררו משבצת כדי להזיז אותה, או גררו אותה מחוץ לסרגל כדי להסיר אותה.",
"navbar.custom.labels": "סמלים ותוויות",
"navbar.custom.left": "הזזה שמאלה",
"navbar.custom.position": "מיקום",
"navbar.custom.position_centre": "מרכז",
"navbar.custom.position_left": "שמאל",
"navbar.custom.position_right": "ימין",
"navbar.custom.preview_as": "תצוגה מקדימה כ",
"navbar.custom.regular": "רגיל",
"navbar.custom.remove": "הסרה",
"navbar.custom.remove_bar": "הסרה מהסרגל",
"navbar.custom.render": "הדמיה",
"navbar.custom.reset": "איפוס סרגל הניווט",
"navbar.custom.reset_default": "איפוס לברירת מחדל",
"navbar.custom.right": "הזזה ימינה",
"navbar.custom.select": "לא נבחרה משבצת. בחרו משבצת בסרגל כדי להזיז אותה, להסיר אותה או לשנות את המראה שלה.",
"navbar.custom.separators_full": "בסרגל כבר יש ארבעה מפרידים.",
"navbar.custom.show": "הצגת סרגל הניווט",
"navbar.custom.shows": "מציג",
"navbar.custom.size": "גודל",
"navbar.custom.stale": "הסרגל השתנה. בחרו שוב את המשבצת.",
"navbar.custom.title": "סרגל ניווט",
"navbar.custom.unknown": "המשבצת הזו אינה זמינה.",
"navbar.description.ambient_occlusion": "מכהה קפלים ופינות כדי להוסיף עומק.",
"navbar.description.display": "מכיל את הגדרות התצוגה: הגדרת גרפיקה מוכנה, רשת, צל על הקרקע, הצללה סביבתית והטלה.",
"navbar.description.fit": "ממסגר את הבחירה, או את כל המודל אם דבר לא נבחר.",
"navbar.description.grid": "מציג או מסתיר את רשת הקרקע.",
"navbar.description.ground_shadow": "מציג או מסתיר את הצל שמתחת למודל.",
"navbar.description.home": "חוזר לתצוגה האיזומטרית של כל המודל.",
"navbar.description.look_at": "מסובב את התצוגה אל הפאה, המישור או הסקיצה הפתוחה שנבחרו.",
"navbar.description.orbit": "מסובב את התצוגה סביב המודל.",
"navbar.description.pan": "מזיז את התצוגה הצדה, למעלה או למטה.",
"navbar.description.projection": "מחליף בין תצוגה אורתוגרפית לפרספקטיבה.",
"navbar.description.separator": "קו דק שמקבץ משבצות שכנות.",
"navbar.description.spin": "ממשיך לסובב את התצוגה עד ללחיצה או הקשה על מקש.",
"navbar.description.visual_style": "מחליף את אופן הציור של המודל: מוצלל, מסגרת תיל או עם קצוות נסתרים.",
"navbar.description.zoom": "מקרב את התצוגה אל המודל או מרחיק אותה ממנו.",
"navbar.display": "תצוגה",
"navbar.fit": "התאמה לחלון",
"navbar.graphics": "גרפיקה",
"navbar.grid": "רשת",
"navbar.ground_shadow": "צל על הקרקע",
"navbar.home": "בית",
"navbar.later": "בהמשך",
"navbar.look_at": "מבט אל",
"navbar.more": "עוד",
"navbar.orbit": "סיבוב מבט",
"navbar.orthographic": "אורתוגרפי",
"navbar.pan": "הזזת מבט",
"navbar.perspective": "פרספקטיבה",
"navbar.preset": "הגדרה מוכנה",
"navbar.projection": "הטלה",
"navbar.projection_heading": "הטלה",
"navbar.separator": "מפריד",
"navbar.show": "הצגה",
"navbar.spin": "סיבוב רציף",
"navbar.style.shaded": "מוצלל",
"navbar.style.shaded_with_edges": "מוצלל עם קצוות",
"navbar.style.shaded_with_hidden_edges": "מוצלל עם קצוות נסתרים",
"navbar.style.wireframe": "מסגרת תיל",
"navbar.translucent": "שקוף למחצה",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "סגנון תצוגה",
"navbar.zoom": "זום",
"needs two joints": "נדרשים שני מפרקים",
"network.allow_once": "התרה פעם אחת",
"network.always_allow": "התרה תמיד לשרת הזה",
@@ -1449,9 +1639,34 @@
"no hole": "אין חור",
"no interference": "אין התנגשות",
"no joint that moves yet": "אין עדיין מפרק שזז",
"no motion study yet": "אין עדיין חקר תנועה",
"no picture": "אין תמונה",
"no such joint": "אין מפרק כזה",
"none": "ללא",
"not a move": "זו אינה הזזה",
"not a number": "לא מספר",
"open a sketch first": "יש לפתוח סקיצה תחילה",
"parts.automatic_name": "אוטומטי",
"parts.dimension.across_flats": "מידת מפתח",
"parts.dimension.bore": "קוטר קדח",
"parts.dimension.d": "קוטר נומינלי",
"parts.dimension.head_diameter": "קוטר הראש",
"parts.dimension.head_height": "גובה הראש",
"parts.dimension.height": "גובה",
"parts.dimension.inner": "קוטר פנימי",
"parts.dimension.outer": "קוטר חיצוני",
"parts.dimension.pitch": "פסיעה",
"parts.dimension.socket": "מידת השקע",
"parts.dimension.socket_depth": "עומק השקע",
"parts.dimension.thickness": "עובי",
"parts.dimension.width": "רוחב",
"parts.family.bearing": "מסב כדורי חריץ עמוק (מעטפת)",
"parts.family.dowel_pin": "פין גלילי",
"parts.family.hex_bolt": "בורג ראש משושה",
"parts.family.hex_nut": "אום משושה",
"parts.family.set_screw": "בורג אלן ללא ראש, קצה שטוח",
"parts.family.socket_head_cap_screw": "בורג ראש גלילי עם משושה פנימי",
"parts.family.washer": "דסקית שטוחה",
"pattern.alignment_2": "יישור 2",
"pattern.alignment_hint": "הספירה כוללת את המקור. מרכוז מאזן את העותקים; היפוך בוחר את הצד שמקבל את העותק הנוסף כשהסך זוגי.",
"pattern.direction_1": "כיוון 1",
@@ -1467,9 +1682,25 @@
"perf.ui_time": "זמן ממשק",
"perf.viewport": "אזור התצוגה",
"perf.worst": "הגרוע ביותר",
"pick a body or some of its faces": "יש לבחור גוף או כמה מפאותיו",
"pick a hole to seat it, or OK places it at the origin": "יש לבחור חור להושבה, או ללחוץ על אישור למיקום בראשית",
"pick a planar face": "יש לבחור פאה מישורית",
"pick a plane or a face as the tool": "יש לבחור מישור או פאה ככלי",
"pick a size": "יש לבחור גודל",
"pick edges of a body": "יש לבחור מקצועות של גוף",
"pick edges of one body": "יש לבחור מקצועות של גוף אחד",
"pick edges of the holes to remove": "יש לבחור מקצועות של החורים להסרה",
"pick faces of one body": "יש לבחור פאות של גוף אחד",
"pick faces to offset": "יש לבחור פאות להיסט",
"pick lines of one sketch": "יש לבחור קווים מסקיצה אחת",
"pick one or two vertices, edges or faces": "יש לבחור אחד או שניים: קודקודים, מקצועות או פאות",
"pick one plane or face as the tool, or sketch curves": "יש לבחור מישור אחד או פאה אחת ככלי, או עקומות סקיצה",
"pick sections in two or more sketches": "יש לבחור חתכים בשתי סקיצות או יותר",
"pick sketch curves or edges": "יש לבחור עקומות סקיצה או מקצועות",
"pick the face to untrim": "יש לבחור את הפאה לביטול גיזום",
"pick the path": "יש לבחור את המסלול",
"pick what to keep": "יש לבחור מה לשמור",
"pick what to keep of the other surface": "יש לבחור מה לשמור מהמשטח השני",
"prefs.add_item": "הוספת הפריט",
"prefs.alt_frees_manipulators": "Alt / Option משחרר גם את חיצי המניפולטור",
"prefs.anti_aliasing_amd_dx12": "החלקת הקצוות משתמשת ב־1× כי בדיקת ההפעלה לא ציירה דבר עם דגימה מרובה ועברה ב־1×. אפשר לבחור הגדרה אחרת למעלה; יש להפעיל מחדש כדי להחיל אותה אם הבדיקה עוברת.",
@@ -1837,6 +2068,64 @@
"render.effects_help": "ניתן לשלב מראות צבע מסודרים ואפקטי עדשה במרחב התמונה. ההדמיה ותיקון הצבע מחדש של המאסטר הגולמי משתמשים באותן הגדרות שמורות. ה־EXR הגולמי אינו משתנה. אלה פקדים אמנותיים מקוריים, לא חיקויים מכוילים של עדשות או של סרטי צילום ממותגים.",
"render.effects_reset_lens": "איפוס אפקטי העדשה",
"render.effects_seed": "זרע הדוגמה",
"render.emitted_axis": "ציר פליטה",
"render.error_area_samples": "area_samples חייב להיות 1, 4, 16 או 64",
"render.error_binding_allocation": "לא ניתן היה להקצות קישור חומר",
"render.error_body_bound": "תצוגת המוצר חורגת ממגבלת הגופים שנקלטו",
"render.error_checkpoint_dimensions": "ממדי נקודת הביקורת שונים מהבקשה שנקלטה",
"render.error_decode_budget": "גלישה בתקציב פענוח התמונה",
"render.error_denoise_setting": "הגדרת הפחתת רעש מקורית לא תקינה",
"render.error_display_dimensions": "ממדי תצוגת התמונה לא תקינים",
"render.error_display_fit": "תצוגת התמונה אינה יכולה להתאים להתקן זה",
"render.error_display_height": "גלישה בגובה התצוגה",
"render.error_display_width": "גלישה ברוחב התצוגה",
"render.error_duplicate_face": "מראה פאת מוצר כפול",
"render.error_export_document": "מסמך ייצוא הרינדור השתנה בזמן בחירת היעד שלו",
"render.error_face_cap": "תצוגת המוצר חורגת ממכסת הקבלה של מראות פאות",
"render.error_finish_gesture": "סיים את מחוות המידול לפני התצוגה המקדימה",
"render.error_finish_operation": "סיים את פעולת המידול הנוכחית לפני הכניסה לרינדור",
"render.error_fixed_preview": "תצוגת סטודיו קבוע דורשת חשיפה 0, סיבוב סביבה 0 ועוצמה 1",
"render.error_geometry_size": "גלישה בגודל גאומטריית המוצר",
"render.error_glass_recipe": "מתכון זכוכית לא מוכר",
"render.error_gpu_preview": "תצוגת מוצר ב-GPU אינה זמינה במארח זה. הגדרות שמורות נשארות זמינות.",
"render.error_gpu_samples": "מספר דגימות GPU לא נתמך",
"render.error_image_dimensions": "ממדי תמונת הרינדור אינם תואמים למשימה שלה",
"render.error_image_profile": "תמונת הרינדור חורגת מפרופיל המשאבים שנקלט",
"render.error_interactive_command": "פקודת רינדור אינטראקטיבית לא קשורה",
"render.error_job_action": "אינה פעולה אינטראקטיבית של משימת תמונה",
"render.error_job_identity": "זהות משימת רינדור לא תקינה: {error}",
"render.error_library_reply": "תגובת ספריית הרינדור לא תקינה",
"render.error_material_binding": "קישור חומר חסר",
"render.error_no_completed_image": "לרינדור אין תמונה שהושלמה",
"render.error_no_geometry": "אין גאומטריית מוצר",
"render.error_no_scene": "אין סצנת מוצר",
"render.error_opacity": "אטימות מראה מוצר לא תקינה",
"render.error_pbr_opacity": "PBR אטום דורש אטימות 1",
"render.error_physical_glass": "המתכון שנבחר אינו זכוכית פיזיקלית",
"render.error_preview_device": "תצוגה מקדימה של מוצר דורשת התקן מותקן עם מאגר עומק",
"render.error_product_triangle": "משולש מוצר לא תקין",
"render.error_provisional_identity": "זהות רינדור זמנית או מספר דגימות לא תקינים",
"render.error_quality_bounds": "הטלת האיכות חורגת מהגבולות המקוריים",
"render.error_quality_method": "הטלת איכות דורשת את אותה שיטת GPU מפורשת",
"render.error_quality_projection": "הטלת איכות מקורית לא תקינה",
"render.error_regrade_identity": "זהות כיול מחדש לא תקינה: {error}",
"render.error_scene_bodies": "גופי סצנת הרינדור חסרים",
"render.error_scene_body_limit": "סצנת הרינדור חורגת ממגבלת הגופים",
"render.error_scene_identity": "זהות סצנת הרינדור לא תקינה",
"render.error_setup_panicked": "הגדרת מעקב הנתיב ב-GPU קרסה",
"render.error_setup_stopped": "עובד ההגדרה נעצר בלי להחזיר מארח",
"render.error_setup_worker": "לא ניתן להפעיל את עובד ההגדרה: {error}",
"render.error_source_preview": "תצוגת המקור חורגת ממעטפת הבתים",
"render.error_surface_normals": "PBR דורש נורמלי משטח שאינם אפס",
"render.error_surface_reply": "תגובת משטח מחבר לא תקינה",
"render.error_triangle_bound": "תצוגת המוצר חורגת ממגבלת המקור של שמונה מיליון משולשים",
"render.error_triangle_count": "גלישה במספר משולשי המוצר",
"render.error_upload_slot": "חריץ ההעלאה של תצוגת המוצר אינו זמין",
"render.error_vertex_allocation": "הקצאת קודקודי תצוגת המוצר נכשלה",
"render.error_vertex_envelope": "תצוגת המוצר חורגת ממעטפת עומס הקודקודים של {limit} MiB; הגאומטריה לא פושטה",
"render.error_vertex_packing": "אריזת תצוגת המוצר שונה מעומס הקודקודים שהתקבל",
"render.error_visible_solid": "צור גוף מלא גלוי בעיצוב כדי לצפות בו כאן.",
"render.exit_focus": "צא ממיקוד",
"render.export_display": "ייצוא: PNG לתצוגה",
"render.export_image_label": "ייצוא תמונה",
"render.export_linear": "ייצוא: EXR ליניארי גולמי",
@@ -1850,6 +2139,7 @@
"render.flare_streak": "פס בסגנון אנמורפי",
"render.flare_strength": "עוצמת בוהק ההבהרות",
"render.flare_threshold": "סף בוהק ליניארי של הסצנה",
"render.fold_browser": "קפל דפדפן",
"render.gpu_depth": "עומק מסלול מרבי",
"render.gpu_options_help": "הדגימות, העומק, הזרע והחשיפה נשמרים עם ההגדרה הזאת. נשמרת רק שיטת התמונה הפעילה.",
"render.gpu_path_failed": "מעקב המסלולים ב־GPU אינו זמין",
@@ -1907,11 +2197,13 @@
"render.image_use_largest": "שימוש בגודל הגדול ביותר ביחס הממדים הזה:",
"render.image_width": "רוחב",
"render.include_rig_cards": "הכללת כרטיסים ודגלים סבילים",
"render.inner_half_angle": "חצי זווית פנימית",
"render.inspect_scene": "רענון סיכום הסצנה שנלכדה",
"render.inspector": "מפקח",
"render.keep_editing": "המשך עריכה",
"render.layer_down": "הזזה למטה",
"render.layer_enabled": "השכבה מופעלת",
"render.layer_off_suffix": " (כבוי)",
"render.layer_remove": "הסרת השכבה",
"render.layer_strength": "עוצמת השכבה",
"render.layer_up": "הזזה למעלה",
@@ -2059,6 +2351,7 @@
"render.optics_save": "שמירת האופטיקה הזאת בהגדרה",
"render.optics_saved": "יעדים אופטיים שמורים",
"render.optics_saved_help": "זהות ההגדרה, הפיצ'ר והמופע המדויקת נשמרת גם בפתיחה מחדש ללא חיבור. יעדים חסרים, מוחלפים או מוסתרים נדחים; החומרים ההנדסיים אינם משתנים. יש לשמור או לבטל עריכות מספריות לפני הסרת יעד שמור.",
"render.outer_half_angle": "חצי זווית חיצונית",
"render.output_format_status": "PNG הוא תמונת התצוגה הגמורה המדויקת. EXR אופציונלי ב־GPU שומר קרינה גולמית ליניארית של הסצנה ב־FLOAT32 לפני מסנני התצוגה. הייצוא לעולם אינו מחליף אותה במטמון התצוגה המקדימה או במשימה אחרת.",
"render.output_lock_ratio": "נעילת יחס הממדים",
"render.output_over_budget": "התמונה המבוקשת חורגת ממעטפת המשאבים שנבחרה. יש לבחור במפורש גודל או פרופיל מתאימים; אין הורדה אוטומטית.",
@@ -2092,7 +2385,10 @@
"render.physical_prepare_plan": "הכנת תוכנית יצירה (ללא החלה)",
"render.physical_separate": "מראה אינו זיהוי חומר. אלה ייחוסים מתועדי מקור, לא תכונות אפקטיביות מאושרות. המסה, החומרים ההנדסיים והאופטיקה הקיימים אינם משתנים.",
"render.physical_unknown": "לא נקבע מועמד מספרי. יש לציין דרגה, הרכב או מבנה; לא ידוע אינו אפס.",
"render.pick_body": "גוף",
"render.pick_component": "רכיב",
"render.pick_face": "פאה",
"render.pick_help": "בחר גוף, פאה או רכיב. לחץ על שטח ריק כדי לנקות; Shift או Ctrl להוספה או להחלפה. ההדגשה מופיעה רק בתצוגת המוצר החיה.",
"render.pick_label": "בחירה",
"render.pick_up_label": "בחירת מראה",
"render.pick_waiting": "בחירת מוצר אינה נתמכת עדיין.",
@@ -2114,6 +2410,12 @@
"render.preview_upload": "מטען הקודקודים של התצוגה המקדימה החיה",
"render.preview_upload_help": "בתי הקודקודים המדויקים של התצוגה המקדימה, לא זיכרון ה־GPU או התהליך הכולל. הגאומטריה אינה מפושטת. משימות תמונה משתמשות בקבלה ובתאורה משלהן.",
"render.progressive_image_summary": "PNG לתצוגה מקדימה · PBR וזכוכית · דגימות הדרגתיות",
"render.property_conditions": "תנאים: {value}",
"render.property_fallback": "מאפיין",
"render.property_qualifier": "מגדיר: {value}",
"render.property_source": "מקור: {id} - {locator}",
"render.property_uncertainty": "אי-ודאות: {value}",
"render.property_unknown": "לא ידוע",
"render.quality_ack": "אישור ההשלכה בתקציב קבוע וההשמטות",
"render.quality_apply": "שימוש בתקציב הדגימה הקבוע הזה",
"render.quality_projection_help": "פרופילי Q מוכנים כוללים דרישות עתידיות. פעולה זו משליכה רק תקציב PNG נתמך בדגימות קבועות, ומשמיטה במפורש עצירה אדפטיבית, פלט ליניארי גולמי ומגבלות העברה עצמאיות.",
@@ -2129,6 +2431,7 @@
"render.replace_saved_surface": "החלפת קישור שמור קיים ליעד הזה",
"render.restore_camera": "שחזור המצלמה השמורה",
"render.result_actual_help": "פיקסל תמונה אחד לכל פיקסל תצוגה.",
"render.result_actual_size": "100%",
"render.result_capture": "הגרסה שנלכדה",
"render.result_current": "גרסת המודל שנלכדה היא הנוכחית.",
"render.result_empty": "עדיין אין תמונה גמורה. יש לבדוק את ההגדרות ואז להתחיל הדמיה.",
@@ -2203,10 +2506,14 @@
"render.shot_rename": "שינוי שם הצילום השמור",
"render.shot_saved_only": "יש לשמור קודם את הטיוטה הנוכחית. שכפול ושינוי שם שומרים על האפשרויות השמורות ועל הפניות המשאבים במדויק.",
"render.show_shots_label": "הצג את סרגל הצילומים",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "קרקע · RGB ליניארי",
"render.sky_horizon": "אופק · RGB ליניארי",
"render.sky_zenith": "זנית · RGB ליניארי",
"render.soft_focus": "מיקוד רך",
"render.spot_cone": "חרוט זרקור",
"render.stage_frame": "מסגרת",
"render.stage_light": "אור",
"render.stage_look": "מראה",
@@ -2257,9 +2564,45 @@
"render.subsurface_enable": "הילוך אקראי לפיזור פנימי",
"render.subsurface_help": "לדיאלקטרי סגור בלבד. פיזור ובליעת RGB הם מקדמים נפרדים לכל mm. המסלולים מתפזרים בתוך הגאומטריה בפועל, ואז נשברים או מוחזרים בגבול. יש לבטל העברת צל ישרה, הסרת רעש משטחית ונפח חיצוני; ולהשתמש בשכבת פרנל אחת. אינו שיידר דיפוזיה, אינו רשת צפיפות ואינו חומר מדוד. תווך צפוף עשוי לדרוש יותר דגימות ועומק מסלול.",
"render.subsurface_rate": "קצב התנגשויות הפיזור",
"render.tone_aces_fitted": "ACES מותאם",
"render.tone_reinhard": "ריינהרד",
"render.transmission_scope": "זכוכית GPU תומכת בתווכים נפרדים מאושרים. תווכים מקוננים ללא הגבלה ומעריך העברה ללא רעש אינם מסופקים.",
"render.transmission_strata": "שכבות פרנל מותנות",
"render.transmission_strata_help": "1 שומר על הזרם המקורי. 2 או 4 תת־מסלולים מרבדים את בחירת ההחזרה או ההעברה הראשונה בזכוכית, וחוקי סנל והבליעה אינם משתנים. יותר מסלולים דורשים יותר עבודה; זו אינה הסרת רעש, אינה תמיכה בתווכים מקוננים ואינה הבטחה להדמיה מהירה יותר.",
"render.tree_add_light": "הוסף אור",
"render.tree_add_shot": "הוסף צילום",
"render.tree_browser": "דפדפן רינדור",
"render.tree_by_look": "לפי מראה",
"render.tree_by_object": "לפי אובייקט",
"render.tree_constant": "סביבה קבועה",
"render.tree_default": "ברירת מחדל",
"render.tree_directional": "כיווני",
"render.tree_environment": "סביבה",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} פאות",
"render.tree_face_one": "פאה {count}",
"render.tree_fixed_studio": "סטודיו קבוע",
"render.tree_hdr": "HDR",
"render.tree_lights": "אורות",
"render.tree_lights_pending": "פקודות אורות בעלי שם עדיין אינן זמינות.",
"render.tree_mixed": "מעורב",
"render.tree_more": "{count} נוספים",
"render.tree_mute": "השתק אור",
"render.tree_no_environment": "ללא סביבה",
"render.tree_objects": "אובייקטים",
"render.tree_output": "פלט",
"render.tree_point": "נקודתי",
"render.tree_rectangle": "מלבן",
"render.tree_search": "חיפוש אובייקטים",
"render.tree_selection": "בחירת רינדור",
"render.tree_shots": "צילומים",
"render.tree_sky": "שמיים",
"render.tree_solo": "בידוד אור",
"render.tree_spot": "זרקור",
"render.tree_sun": "שמש",
"render.tree_switch": "החלף",
"render.tree_user_one": "אובייקט {count}",
"render.tree_users": "{count} אובייקטים",
"render.unavailable_preview": "הגדרה זו מבקשת פרופיל תצוגה מקדימה שאינו זמין.",
"render.unsaved": "שינויים בתצוגה המקדימה שלא נשמרו",
"render.use_preview": "שימוש בתצוגה המקדימה המובנית",
@@ -2303,6 +2646,26 @@
"search.try": "יש להקליד שם פקודה, פיצ'ר בתכן זה או פרמטר. כדי להריץ פקודה עם ערכים, יש להקליד את המזהה שלה ואובייקט JSON: {example}",
"search.valid": "תקין",
"section.off_hint": "לא נבחר מישור: אישור מכבה את החתך.",
"select a direction (an axis, a sketch line or a straight edge) first": "יש לבחור תחילה כיוון (ציר, קו סקיצה או מקצוע ישר)",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "יש לבחור כיוון (ציר, קו סקיצה או מקצוע ישר) שהפרופיל ילך לאורכו",
"select a point on a component": "יש לבחור נקודה על רכיב",
"select a profile, edges or sketch lines first": "יש לבחור תחילה פרופיל, מקצועות או קווי סקיצה",
"select an axis": "יש לבחור ציר",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "יש לבחור תחילה ציר, מקצוע ישר או מעגלי, או פאה של גליל, חרוט או טורוס",
"select bodies first": "יש לבחור גופים תחילה",
"select corner points, or the two lines of one corner": "יש לבחור נקודות פינה, או את שני הקווים של פינה אחת",
"select one corner point, or the two lines of one corner": "יש לבחור נקודת פינה אחת, או את שני הקווים של פינה אחת",
"select sheet edges first": "יש לבחור תחילה מקצועות של הפח",
"select the bend line (a sketch line) first": "יש לבחור תחילה את קו הכיפוף (קו סקיצה)",
"select the cam's profile (a sketch profile or the cam's edges)": "יש לבחור את הפרופיל של הפיקה (פרופיל סקיצה או מקצועות הפיקה)",
"select the corner to cut first": "יש לבחור תחילה את הפינה לחיתוך",
"select the corners to round first": "יש לבחור תחילה את הפינות לעיגול",
"select the fixed face first (a plate's large face)": "יש לבחור תחילה את הפאה הקבועה (הפאה הגדולה של לוח)",
"select the frame sketch's lines first": "יש לבחור תחילה את קווי סקיצת המסגרת",
"select the path (sketch lines across the edge)": "יש לבחור את המסלול (קווי סקיצה על פני המקצוע)",
"select the rim face first": "יש לבחור תחילה את פאת השפה",
"select the sheet edge first": "יש לבחור תחילה את מקצוע הפח",
"select two components": "יש לבחור שני רכיבים",
"set by the sketch's lines": "נקבע לפי קווי הסקיצה",
"settings.display_quality_note": "ברמות עדינות יותר, פאות ומקצועות מעוקלים מוצגים חלקים יותר ויצירת הרשת אורכת זמן רב יותר. רק אזור התצוגה משתנה, לא התכן ולא קובצי הייצוא.",
"settings.frame_rate_details_note": "מוסיף גרף של זמני התמונות האחרונות עם המשולשים שצוירו מעליו, היסטוגרמה של זמני התמונות ואת מה שה־GPU צייר. לחיצה על קצב התמונות בתצוגה מציגה או מסתירה אותם.",
@@ -2320,17 +2683,23 @@
"settings.window_system_details": "פרטים",
"settings.window_system_note_now": "ייכנס לתוקף אחרי הפעלה מחדש. כעת: {now}.",
"settings.window_system_wayland_limited": "חלק מהתכונות מוגבלות ב־Wayland מקורי.",
"sheet.flange_type_base": "בסיס",
"sheet.flange_type_contour": "מתאר",
"sheet.flange_type_edge": "מקצוע",
"sheet.no_body": "אין גוף פח: יש להתחיל אחד עם אוגן > בסיס, או להמיר לוח לפח עם המרה לפח (יש לבחור את הפאה השטוחה הגדולה שלו)",
"shortcut.json_error": "הפרמטרים חייבים להיות JSON: {error}",
"shortcut.no_command": "אין פקודה `{id}`; הטקסט שלפני ה־JSON חייב להיות מזהה פקודה",
"shortcut.pin": "הצמדה לראש תיבת S",
"shortcut.unpin": "ביטול הצמדה",
"sketch is missing": "הסקיצה חסרה",
"sketch.degrees_of_freedom": "{count} דרגות חופש",
"sketch.dof_left": "נותרו {count} דרגות חופש",
"sketch.dof_left_one": "נותרה {count} דרגת חופש",
"sketch.draw_curves": "שרטוט כ־{linetype}",
"sketch.make_selection": "המרת הבחירה ל־{linetype}",
"sketch.open_ends": "קצוות פתוחים: {count}",
"sketch.status_conflict": "אילוצים סותרים",
"sketch.status_fully_constrained": "מאולץ במלואו",
"sketch.untied_ends": "קצוות לא מחוברים: {count}",
"sketch_panel.attached": "מוצמד ל־{body} / {path}",
"sketch_panel.author": "מיקום היצירה: {path}",
@@ -2357,7 +2726,24 @@
"sketch_text.path_hint": "עקומה בסקיצה שהטקסט עוקב אחריה: יש ללחוץ כאן ואז על העקומה",
"sketch_text.use_font_file": "שימוש בקובץ הגופן {path}",
"solid": "מוצק",
"the angle must be a number": "הזווית חייבת להיות מספר",
"the curves must be in one sketch": "העקומות חייבות להיות בסקיצה אחת",
"the direction must be an axis, a sketch line or a straight edge": "הכיוון חייב להיות ציר, קו סקיצה או מקצוע ישר",
"the duration must be a number of seconds, 0.001 or more": "משך הזמן חייב להיות מספר שניות, 0.001 או יותר",
"the line's sketch is gone": "הסקיצה של הקו כבר לא קיימת",
"the lines must be in one sketch": "הקווים חייבים להיות בסקיצה אחת",
"the lines must be in one sketch, not the section's": "הקווים חייבים להיות בסקיצה אחת, ולא בסקיצת החתך",
"the parts library is empty": "ספריית החלקים ריקה",
"the parts library is not available": "ספריית החלקים אינה זמינה",
"the path curves must be in one other sketch": "עקומות המסלול חייבות להיות בסקיצה אחרת אחת",
"the path's sketch is gone": "הסקיצה של המסלול כבר לא קיימת",
"the position must be a number": "המיקום חייב להיות מספר",
"the preview failed": "התצוגה המקדימה נכשלה",
"the profiles and curves must be in one sketch": "הפרופילים והעקומות חייבים להיות בסקיצה אחת",
"the reference face must be on the edges' body": "פאת הייחוס חייבת להיות על הגוף של המקצועות",
"the scale must be above 0": "קנה המידה חייב להיות גדול מ־0",
"the section's profiles must be in one sketch": "הפרופילים של החתך חייבים להיות בסקיצה אחת",
"the two origins are on the same component": "שתי הראשיות נמצאות על אותו רכיב",
"thread.automatic_size": "גודל אוטומטי",
"thread.designation": "סימון",
"thread.direction": "כיוון ההברגה",
@@ -2397,6 +2783,7 @@
"trace.points": "{count} נקודות לאורך המסלול",
"trace.stopped_by_contact": "מסתיים בדגימה {sample}: {a} היה עובר דרך {b}",
"trace.stopped_by_loop": "מסתיים בדגימה {sample}: הלולאה דרך {joint} לא יכולה להיסגר יותר",
"trim by sketch curves, or by one plane or face": "יש לגזום באמצעות עקומות סקיצה, או באמצעות מישור אחד או פאה אחת",
"ui.1_degree_of_freedom": "דרגת חופש אחת",
"ui.3d_mouse_axes_reassigned": "הקצאת הצירים מחדש בהעדפות עדיין חלה בנוסף לכיול הזה.",
"ui.3d_mouse_button": "לחצן {number}",
@@ -2873,6 +3260,8 @@
"ui.design_properties.revision": "גרסה",
"ui.diameter": "קוטר",
"ui.dimension": "מידה",
"ui.direct_interaction": "אינטראקציה ישירה",
"ui.direct_interaction_note": "עבודה ישירה על המודל בחלון התצוגה. יש ללחוץ על פאה מישורית או על פרופיל ולמשוך: למעלה משיכה, למטה לתוך גוף חיתוך, ותנועה לצדדים קובעת את גודל הצעד",
"ui.direction": "כיוון",
"ui.display_quality": "איכות תצוגה",
"ui.display_quality_coarse": "גסה",
@@ -2896,6 +3285,7 @@
"ui.editJointLimits": "עריכת גבולות מפרק",
"ui.edit_section_analysis": "עריכת ניתוח חתך",
"ui.ellipse": "אליפסה",
"ui.emboss_wrap_note": "פרופילי קווים ניצבים המשיקים לגליל נתמך נכרכים אוטומטית. יש לבחור דופן כדי לקבוע יעד.",
"ui.end_radius": "רדיוס סיום",
"ui.end_scale": "קנה מידה בסיום",
"ui.entities": "ישויות",
@@ -2968,6 +3358,7 @@
"ui.heading_extrude": "שליפה",
"ui.heading_fillet": "עיגול פינה",
"ui.heading_finish_sketch": "סיום סקיצה",
"ui.heading_form": "צורה",
"ui.heading_front": "חזית",
"ui.heading_hole": "חור",
"ui.heading_home": "בית",
@@ -3016,6 +3407,7 @@
"ui.heading_utilities": "כלים",
"ui.heading_utility": "כלי עזר",
"ui.heading_weldments": "ריתוכים",
"ui.height": "גובה",
"ui.help": "עזרה",
"ui.hide": "הסתרה",
"ui.hideAxes": "הסתרת צירים",
@@ -3053,11 +3445,14 @@
"ui.intersect": "חיתוך משותף",
"ui.isolate": "בידוד",
"ui.join": "איחוד",
"ui.joint_play": "▶ הפעלה",
"ui.joint_stop": "■ עצירה",
"ui.joints": "מפרקים",
"ui.keyboard_shortcuts": "קיצורי מקלדת",
"ui.language": "שפה",
"ui.layout_compact": "דחוס",
"ui.layout_floating": "צף",
"ui.length": "אורך",
"ui.length_decimals": "ספרות עשרוניות באורך",
"ui.light": "בהיר",
"ui.line": "קו",
@@ -3069,6 +3464,7 @@
"ui.loft": "לופט",
"ui.look_at": "מבט אל",
"ui.look_at_anim_desc": "תצוגת צירים, מבט אל, בית והתאמה לחלון",
"ui.major_radius": "רדיוס גדול",
"ui.manipulator_free_alt": "גרירה חופשית של הידית גם עם Alt/Option",
"ui.manipulator_free_alt_tip": "פעיל: Alt/Option או Ctrl/Cmd על חיצי השליפה / הידית מבטלים הצמדת ערכים. כבוי: Ctrl/Cmd בלבד.",
"ui.manufacture": "ייצור",
@@ -3098,8 +3494,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF עם תגי פאות",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "רדיוס קטן",
"ui.mirror": "שיקוף",
"ui.mirror_line": "קו שיקוף",
"ui.modifiers_either": "{first} או {second}",
"ui.move": "הזזה",
"ui.multiple": "מרובה",
"ui.named_views": "תצוגות שמורות",
@@ -3156,6 +3554,7 @@
"ui.pinToShortcuts": "הצמדה לקיצורי הדרך",
"ui.pinToToolbar": "הצמדה לסרגל הכלים",
"ui.pipe": "צינור",
"ui.pitch": "פסיעה",
"ui.placement": "מיקום",
"ui.placement_handles": "ידיות מיקום",
"ui.placement_handles_tip": "ידיות בתצוגה המקדימה של משען, בליטה או חיבור הצמדה: יש לגרור את הסמן כדי להזיז על פני המודל, ולסובב בעזרת הטבעת",
@@ -3218,6 +3617,7 @@
"ui.reverse_horizontal_pan_direction": "היפוך כיוון ההזזה האופקית",
"ui.reverse_horizontal_pan_tip": "גלילה אופקית בשתי אצבעות וגלגל האגודל מזיזים את המבט לכיוון ההפוך",
"ui.reverse_zoom_direction": "היפוך כיוון הזום",
"ui.revolutions": "סיבובים",
"ui.revolve": "סיבוב",
"ui.ribbon_exit": "יציאה",
"ui.ribbon_labels": "הצגת טקסט מתחת לסמלי רצועת הכלים",
@@ -3234,6 +3634,7 @@
"ui.scale": "שינוי קנה מידה",
"ui.second_rail": "מסילה שנייה",
"ui.section_analysis": "ניתוח חתך",
"ui.section_size": "גודל החתך",
"ui.select": "בחירה",
"ui.selectOther": "בחירת אחר…",
"ui.selectTangentChain": "בחירת שרשרת משיקה",
@@ -3305,6 +3706,7 @@
"ui.start_page": "דף פתיחה",
"ui.step_values": "שינוי ערכים בעזרת מקשי החצים והגלגלת",
"ui.step_values_tip": "בשדה ערך שמקלידים בו, החצים למעלה ולמטה משנים מספר רגיל ב־1 (Shift: 10, Alt: 0.1), וכך גם גלגלת העכבר מעל השדה. ביטויים נשארים כפי שהוקלדו.",
"ui.stitch_tolerance_hint": "הדוקה",
"ui.stretch": "מתיחה",
"ui.supersampling": "דגימת־על (SSAA)",
"ui.supersampling_adaptive": "רק כשהמבט נייח",
@@ -3335,6 +3737,8 @@
"ui.to_object": "עד אובייקט",
"ui.tool_direction": "כיוון הכלי",
"ui.top": "עליון",
"ui.top_diameter": "קוטר עליון",
"ui.top_radius": "רדיוס עליון",
"ui.torus": "טורוס",
"ui.total_angle": "זווית כוללת",
"ui.trackpad_pan_tip": "מחוות משטח המגע מזיזות את המבט (כבוי: הן מבצעות זום כמו הגלגלת); גלגלת העכבר מבצעת זום, גלגל האגודל מזיז הצידה, צביטה תמיד מבצעת זום",
@@ -3363,6 +3767,7 @@
"ui.visual_shaded_with_edges": "מוצלל עם מקצועות",
"ui.visual_style": "סגנון תצוגה",
"ui.visual_wireframe": "מסגרת תיל",
"ui.width": "רוחב",
"ui.window_system": "מערכת חלונות",
"ui.window_system_auto": "אוטומטי",
"ui.window_system_wayland": "Wayland",
@@ -3423,6 +3828,9 @@
"update.up_to_date": "SolidCraft מעודכן.",
"update.update_now": "עדכון עכשיו",
"update.you_have": "הגרסה המותקנת: {version}.",
"use a positive nominal diameter and a pitch smaller than it": "יש להשתמש בקוטר נומינלי חיובי ובפסיעה קטנה ממנו",
"values must be finite numbers": "הערכים חייבים להיות מספרים סופיים",
"values must be numbers or expressions": "הערכים חייבים להיות מספרים או ביטויים",
"view.auto_ortho_faces": "פרספקטיבה בזמן סיבוב, אורתוגרפי על פאות",
"web.files.insert_drawings_hint": "קובצי CAD, רשתות משולשים, DXF או SVG אל התכן הפתוח",
"web.files.insert_stored_drawings_hint": "אל התכן הפתוח (קובצי CAD, רשתות משולשים, DXF, SVG)",
+953 -1
View File
File diff suppressed because it is too large Load Diff
+905 -1
View File
File diff suppressed because it is too large Load Diff
+920 -1
View File
File diff suppressed because it is too large Load Diff
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(使用中のルール)",
"0 turns it off": "0で無効化",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. 下のボタンでGitHubの下書きを開き、クリップボードにコピーされたレポートを貼り付けます。",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. 下のボタンでGitHubの下書きを開きます。タイトルとレポートは入力済みです。",
@@ -51,16 +52,20 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "先に外観を適用してください。割り当てた外観と、このデザインで作成したマテリアルを書き出します。",
"Arc length": "円弧の長さ",
"Area": "表面積",
"As Picked": "選択どおり",
"As-Built": "現状位置",
"Assign Rule": "ルールを割当",
"Attachment": "アタッチメント",
"BLEND SURFACE": "ブレンドサーフェス",
"BOUNDARY SURFACE": "境界サーフェス",
"BROWSER": "ブラウザ",
"Ball": "ボール",
"Bar": "平鋼",
"Base Center": "底面の中心",
"Base Height": "ベースの高さ",
"Bend": "曲げ角度",
"Bend Edges": "曲げエッジ",
"Bend Line": "曲げ線",
"Bend Line Position": "曲げ線位置",
"Bend Position": "曲げ位置",
"Bend Radius": "曲げ半径",
@@ -72,6 +77,7 @@
"Body (last if none)": "ボディ (未指定時は最後)",
"Body to split": "分割するボディ",
"Body, or faces to take out": "ボディ、または取り除く面",
"Both": "両方",
"Bottom Left": "左下",
"Bottom Middle": "下中央",
"Bottom Right": "右下",
@@ -103,6 +109,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "新しい平面を選択してください。スケッチジオメトリと寸法は2次元座標系のまま維持されます。",
"Choose…": "選択…",
"Circle center": "円の中心",
"Circle or sphere": "円または球",
"Circular": "円形",
"Circumference": "円周",
"Clockwise": "時計回り",
@@ -119,6 +126,7 @@
"Config Table": "構成テーブル",
"Configuration": "構成",
"Configuration rules": "構成ルール",
"Constant radius": "一定半径",
"Contact": "接触",
"Contact Sets": "接触セット",
"Contact sets": "接触セット",
@@ -154,7 +162,9 @@
"Custom": "カスタム",
"Customize Toolbar": "ツールバーのカスタマイズ",
"Customize…": "カスタマイズ…",
"Cylindrical": "円筒",
"Cylindrical face": "円筒面",
"Deboss": "デボス",
"Delete": "削除",
"Delete Folders and Features…": "フォルダーとフィーチャーを削除…",
"Delete Selected Features…": "選択したフィーチャーを削除…",
@@ -186,6 +196,7 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "ドラッグしてレストを 5° 刻みで回転します。Alt または Ctrl を押したままにすると自由に回転します。",
"Drive Joint": "ジョイントを駆動",
"Duration": "時間",
"Edge": "エッジ",
"Edges": "エッジ",
"Edit": "編集",
"Edit Profile Sketch": "プロファイルスケッチを編集",
@@ -194,6 +205,7 @@
"End Radius": "終了半径",
"End bulge": "終了側の膨らみ",
"End continuity": "終了側の連続性",
"Equal Distance": "等距離",
"Expand": "展開",
"Expected result (optional)": "期待した結果(任意)",
"Explode": "分解",
@@ -221,6 +233,8 @@
"Faces": "面",
"Faces / edges / vertices": "面 / エッジ / 頂点",
"Faces to split": "分割する面",
"Faces/Body": "面/ボディ",
"Factor must be a positive number": "係数は正の数にしてください",
"Fastener": "締結部品",
"Favorites": "お気に入り",
"Favourite": "お気に入り",
@@ -230,9 +244,12 @@
"Filter…": "フィルター…",
"Find in Browser": "ブラウザで検索",
"Finish": "終了",
"First edge": "1つ目のエッジ",
"First plane": "第1平面",
"First point": "1点目",
"Fit and G2 corners require Constant radius.": "フィットと G2 コーナーには Constant radius が必要です。",
"Fixed Face": "固定面",
"Flange Gap": "フランジ間隔",
"Flange thickness": "フランジ厚",
"Flanges": "フランジ",
"Flat Pattern": "フラットパターン",
@@ -240,8 +257,10 @@
"Follow camera (Look At sketches)": "カメラ追従(スケッチを正面視)",
"Follow the camera (Look At sketches)": "カメラ追従(スケッチを正面視)",
"Font": "フォント",
"Free Move": "自由移動",
"From": "開始",
"From Bodies": "ボディから",
"From Snap": "移動元スナップ",
"From edges": "開始側エッジ",
"Full Length": "全長",
"Full thread depth": "ねじ深さ全体",
@@ -253,10 +272,13 @@
"Halo under sketch curves": "スケッチ曲線の下に縁取りを表示",
"Height": "高さ",
"Height From": "高さの基準",
"Hem Gap": "ヘミング間隔",
"Hidden edges": "隠線",
"History layout": "履歴のレイアウト",
"History names": "履歴名",
"Hole (optional)": "穴 (オプション)",
"Hole Depth": "穴の深さ",
"Hole Diameter": "穴径",
"Holes": "穴",
"Holes (edges on them)": "穴(そのエッジ)",
"Home view": "ホームビュー",
@@ -279,12 +301,16 @@
"Issue title": "Issueタイトル",
"Items": "項目",
"JOINTS": "ジョイント",
"Joint 1": "ジョイント 1",
"Joint 2": "ジョイント 2",
"Joint Origin1": "ジョイント原点1",
"K Factor": "K係数",
"Keep (points on it)": "残す部分(その上の点)",
"Keep Tools": "ツールボディを保持",
"Keep of the other surface": "相手のサーフェスで残す部分",
"Key a joint's value at this step": "このステップでジョイントの値をキー設定",
"Keys": "キー",
"Knife Edge": "ナイフエッジ",
"L-Angle": "山形鋼",
"LIBRARY": "ライブラリ",
"LINKS": "リンク",
@@ -297,9 +323,11 @@
"Letter Spacing": "文字間隔",
"Library": "ライブラリ",
"Library file": "ライブラリファイル",
"Library response is missing": "ライブラリからの応答がありません",
"Limits": "制限",
"Line Spacing": "行間",
"Line Type": "線種",
"Line on plane": "線-平面",
"Lines": "線分",
"Listing the installed fonts…": "インストール済みフォントを一覧表示中…",
"Load library": "ライブラリを読み込む",
@@ -319,11 +347,14 @@
"Material Outside": "材料外側",
"Material copied. Existing body assignments are unchanged.": "マテリアルをコピーしました。既存のボディの割り当ては変わりません。",
"Max": "最大",
"Max Thickness": "最大厚さ",
"Maximum": "最大",
"Mesh body": "メッシュボディ",
"Mid Radius": "中間半径",
"Middle double-click": "中ボタンのダブルクリック",
"Min": "最小",
"Min Draft": "最小勾配",
"Min Thickness": "最小厚さ",
"Minimum": "最小",
"Mirror Plane": "ミラー平面",
"Mitre": "留め継ぎ",
@@ -343,6 +374,7 @@
"Name": "名前",
"Name on import": "インポート名",
"Nearest": "最も近い",
"Neutral plane": "中立面",
"New": "新規",
"New Comp.": "新規\nコンポ",
"New Sketch": "新規スケッチ",
@@ -353,6 +385,7 @@
"No matching appearances": "一致する外観がありません",
"No matching physical materials.": "一致する物理マテリアルがありません。",
"No visible bodies or sketches to export.": "出力する表示中のボディまたはスケッチがありません。",
"Nominal Radius": "公称半径",
"Nominal diameter": "呼び径",
"None": "なし",
"Not available yet": "まだ利用できません",
@@ -381,22 +414,28 @@
"Overall length": "全長",
"Param. Graph": "パラメータ図",
"Parameter": "パラメータ",
"Part length must be greater than zero and at most 2000 mm": "パーツの長さは0より大きく、2000 mm以下にしてください",
"Parts": "部品",
"Pass through": "通過点",
"Path": "パス",
"Pattern": "パターン",
"Per Edge": "エッジごと",
"Physical material definitions": "物理マテリアル定義",
"Pick a part size": "パーツのサイズを選択してください",
"Pick the tool bodies": "ツールボディを選択",
"Picked": "選択したもの",
"Picked point": "選択した点",
"Pin-slot": "ピン スロット",
"Pitch": "ピッチ",
"Pivot": "ピボット",
"Place at the origin instead": "代わりに原点に配置",
"Planar": "平面",
"Plastic Rules": "樹脂ルール",
"Play the joint's motion in the view": "ビューでジョイントの動きを再生",
"Playback": "再生",
"Plot": "グラフ",
"Point on line": "点-線",
"Point on plane": "点-平面",
"Position": "位置",
"Position (0 to 1)": "位置 (0〜1)",
"Position (G0)": "位置 (G0)",
@@ -409,6 +448,7 @@
"Profiles or curves": "プロファイルまたは曲線",
"Profiles/Curves": "プロファイル/曲線",
"Quantity": "数量",
"Quantity must be at least 2": "数量は2以上にしてください",
"RECENT": "最近使用した項目",
"REFERENCE": "参照",
"RULED SURFACE": "ルールドサーフェス",
@@ -422,6 +462,8 @@
"Rectangular": "長方形",
"Rectangular Tube": "角形鋼管",
"Reference face": "参照面",
"Relief Depth": "リリーフ深さ",
"Relief Width": "リリーフ幅",
"Remove Tools": "ツールボディを削除",
"Remove condition": "条件を削除",
"Remove from Folder": "フォルダーから削除",
@@ -450,6 +492,7 @@
"Restore this studio's tools": "このスタジオのツールを復元",
"Result": "結果",
"Retake screenshot": "スクリーンショットを再取得",
"Reveal Height": "見切り高さ",
"Reverse": "反転",
"Reverse Direction": "方向を反転",
"Revert": "元に戻す",
@@ -458,12 +501,15 @@
"Revert Position": "位置を元に戻す",
"Review the report and screenshot before opening GitHub.": "GitHubを開く前にレポートとスクリーンショットを確認してください。",
"Review your report on GitHub and click Submit new issue to publish it.": "GitHubで内容を確認し、Submit new issueをクリックすると公開されます。",
"Revolute": "回転",
"Rib Length": "リブの長さ",
"Rib Offset": "リブのオフセット",
"Rib Thickness": "リブの厚さ",
"Ribs": "リブ",
"Right Middle": "右中央",
"Rigid": "剛体",
"Rim Edge": "リムエッジ",
"Rim face": "縁の面",
"Ring of tools on the right button": "右ボタンのツールリング",
"Roll Back Here": "ここまでロールバック",
"Roll History Marker Here": "履歴マーカーをここに移動",
@@ -488,16 +534,28 @@
"Search": "検索",
"Search commands": "コマンドを検索",
"Search this library": "このライブラリを検索",
"Second edge": "2つ目のエッジ",
"Second plane": "第2平面",
"Second point": "2点目",
"Section": "断面",
"Section (optional)": "断面(任意)",
"Section position": "断面の位置",
"Sections (one sketch each)": "セクション (各1スケッチ)",
"Select Other": "その他を選択",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "その他を選択: モデル上で左ボタンを長押し(または右クリック › その他を選択…)するとカーソル下の要素が一覧表示されます。同じ場所を再度クリックすると次の要素が選択されます。中ボタンをダブルクリックするとホームビューに戻ります(環境設定 › ナビゲーション)。",
"Select Same Look": "同じ外観を選択",
"Select bodies (a face picks its body)": "ボディを選択(面をクリックするとそのボディが選択されます)",
"Select bodies or faces instead": "代わりにボディまたは面を選択",
"Select edges": "エッジを選択",
"Select points of the sketch being edited": "編集中のスケッチの点を選択してください",
"Select the centre the pattern turns around first": "パターンの回転中心を先に選択してください",
"Select the curves to offset first": "オフセットする曲線を先に選択してください",
"Select the mirror line": "ミラー線を選択してください",
"Select the sketch curves or points to mirror first": "ミラーするスケッチの曲線または点を先に選択してください",
"Select the sketch curves or points to move first": "移動するスケッチの曲線または点を先に選択してください",
"Select the sketch curves or points to pattern first": "パターンにするスケッチの曲線または点を先に選択してください",
"Select the sketch curves or points to scale first": "尺度を変更するスケッチの曲線または点を先に選択してください",
"Select the sketch curves or points to transform first": "変換するスケッチの曲線または点を先に選択してください",
"Selection filter": "選択フィルター",
"Semantic faces share their appearance across instances.": "セマンティック面はインスタンス間で外観を共有します。",
"Send your report on GitHub": "GitHubでレポートを送信",
@@ -517,9 +575,12 @@
"Sketch geometry and profiles": "スケッチジオメトリとプロファイル",
"Sketch plane has no body-face attachment.": "スケッチ平面にボディ面のアタッチメントがありません。",
"Sketch points": "スケッチ点",
"Slider": "スライダ",
"Slot width": "長穴の幅",
"Snap to face and edge centres": "面とエッジの中心にスナップ",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "これらのデザインが保存される前にSolidCraftが終了しました。最後の自動保存ファイルを開くことができます。",
"Spacing 2 must be a non-zero number": "間隔 2は0以外の数値にしてください",
"Spacing must be a non-zero number": "間隔は0以外の数値にしてください",
"Specialise": "特殊操作",
"Speed": "速度",
"Splitting tool": "分割ツール",
@@ -530,6 +591,7 @@
"Start angle": "開始角度",
"Start bulge": "開始側の膨らみ",
"Start continuity": "開始側の連続性",
"Stationary Side": "固定側",
"Step": "ステップ",
"Steps": "ステップ数",
"Steps to reproduce (optional)": "再現手順(任意)",
@@ -544,6 +606,7 @@
"Suppressed": "抑制",
"Surface": "サーフェス",
"Surface, or faces to turn over": "サーフェス、または裏返す面",
"Surfaces": "サーフェス",
"Swap Ends": "端点を入れ替え",
"TRIM": "トリム",
"Tangent": "正接",
@@ -554,24 +617,34 @@
"Tap drill diameter": "タップ下穴径",
"Target": "ターゲット",
"Target Body": "ターゲットボディ",
"Target Face (optional)": "対象面 (オプション)",
"Tear": "引き裂き",
"Technical details": "技術情報",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "破線のスケッチは保存された平面ガイドです。新しい面を選択してアタッチメントを修復してください。",
"The design changed. Reopen Change Part Size for the component.": "デザインが変更されました。コンポーネントの「パーツ サイズを変更」を開き直してください。",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "方向は、軸、またはスケッチ平面上にある直線のスケッチ曲線にしてください",
"The mirror line cannot also be mirrored": "ミラー線自体をミラーすることはできません",
"The mirror line must be a straight curve of this sketch, not an origin axis": "ミラー線は、原点の軸ではなく、このスケッチの直線にしてください",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "保存された作成元のオカレンスが見つかりません。再バインドする前に有効な作成元配置を選択してください。",
"Then": "次を実行 (Then)",
"These features will be deleted:": "以下のフィーチャーが削除されます:",
"These features will fail:": "以下のフィーチャーでエラーが発生します:",
"Thickness Outside": "外側の厚さ",
"Thickness Variation": "厚さの変化",
"Thin": "薄肉",
"Thin Extrude": "薄肉押し出し",
"Third plane": "3つ目の平面",
"Third point": "3点目",
"This child is shared. Deleting it removes it from every copy of its parent.": "この子要素は共有されています。削除すると親のすべてのコピーから削除されます。",
"This child is shared. Position changes apply to every copy of its parent.": "この子要素は共有されています。位置の変更は親のすべてのコピーに適用されます。",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "この面は安定したアタッチメントを提供できません。別の面を選択するか、固定平面を明示的に使用してください。",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "この画像はまだGitHubに添付されていません。コピーまたは保存し、GitHubで添付してください。",
"Thread depth": "ねじ深さ",
"Thread diameter": "ねじ径",
"Through point": "通過点",
"To": "終了",
"To Offset": "オフセットまで",
"To Snap": "移動先スナップ",
"To edges": "終了側エッジ",
"Toe radius": "先端半径",
"Tolerance": "公差",
@@ -585,6 +658,7 @@
"Trimming tool (plane, face or curves)": "トリムツール(平面、面、または曲線)",
"Turn off section analysis before exporting the view.": "断面解析をオフにしてからエクスポートしてください。",
"Type": "タイプ",
"Type a distance or an angle to move by": "移動する距離または角度を入力してください",
"UNTRIM": "トリム解除",
"Unit": "単位",
"Unsuppress": "抑制を解除",
@@ -629,6 +703,17 @@
"Z angle": "Z角度",
"Z distance": "Z距離",
"Zebra": "ゼブラ",
"`joint` must be an id or a name": "`joint` にはIDまたは名前を指定してください",
"`params` must be an object": "`params` はオブジェクトにしてください",
"`values` must be a list": "`values` はリストにしてください",
"a chamfer needs a corner of exactly two lines": "面取りには、ちょうど2本の線からなるコーナーが必要です",
"a file operation is in progress": "ファイル操作の実行中です",
"a picked curve is no longer in a sketch": "選択した曲線がスケッチ内にありません",
"a picked curve's sketch has not been solved": "選択した曲線のスケッチがまだ解かれていません",
"a picked edge has no points": "選択したエッジに点がありません",
"a picked edge is gone": "選択したエッジが存在しなくなりました",
"a picked edge's body is gone": "選択したエッジのボディが存在しなくなりました",
"add a key for a joint first": "先にジョイントのキーを追加してください",
"ai.connected_toast": "SolidCraft が {clients} で使えるようになりました。使うには再起動してください(設定 > アシスタント)。",
"ai.prefs.allow_control": "AI エージェントの接続を許可(コントロールチャンネル / MCP)",
"ai.prefs.allow_control_note": "このコンピューター内だけのコントロールチャンネル(127.0.0.1、ポート 27878 または次に空いているポート)を開きます。接続するプログラムは、起動のたびに作られ、あなたのユーザーアカウントだけが読める秘密のトークンも提示する必要があります。次に SolidCraft を起動したときから有効です。オフ:--control を付けて起動しない限り、何も待ち受けません。",
@@ -669,6 +754,7 @@
"appearance.pbr_opaque": "不透明PBR",
"appearance.roughness": "粗さ",
"appearance.surface_response": "表面の応答",
"bom.group_children": "サブパーツを親パーツの行に含める",
"browser.body_name": "ボディ{number}",
"browser.calibrate_title": "尺度を設定: {name}",
"browser.capture_many": "{count}個のコンポーネントが移動されましたが、位置がキャプチャされていません。",
@@ -679,6 +765,8 @@
"browser.move_title": "移動: {name}",
"browser.parameters": "パラメータ ({count})",
"browser.precision": "精度: {precision}",
"browser.sketch_attachment_lost": "{name} (アタッチメント消失)",
"browser.sketch_editing": "{name} (編集中)",
"browser.sketch_name": "スケッチ{number}",
"browser.units": "単位: {units}",
"cam.flat": "平面",
@@ -688,7 +776,13 @@
"cam.roller": "ローラー",
"cam.roller_pick": "ローラー (オプション)",
"cam.tip_pick": "先端 (オプション)",
"choose a profile": "プロファイルを選択してください",
"choose the cam's and the follower's joints": "カムと従動節のジョイントを選択してください",
"choose the joints to couple": "連結するジョイントを選択してください",
"click a plane or planar face": "平面または平らな面をクリック",
"click sketch curves": "スケッチ曲線をクリック",
"cmd.appearance_assign": "外観",
"cmd.appearance_chain": "外観の由来",
"cmd.appearance_library": "外観ライブラリ",
"cmd.appearance_list": "外観を一覧表示",
"cmd.appearance_paint": "外観をペイント",
@@ -1073,6 +1167,9 @@
"cmd.timeline_roll_to": "履歴マーカーを移動",
"cmd.timeline_rollback": "タイムライン マーカーを移動",
"cmd.timeline_suppress": "フィーチャーを抑制",
"cmd.view.render_browser": "Renderブラウザー",
"cmd.view.render_dock": "レンダードックを移動",
"cmd.view.render_focus": "Renderフォーカス表示",
"cmd.view_ambient_occlusion": "アンビエントオクルージョン",
"cmd.view_apply": "名前付きビューを復元",
"cmd.view_back": "背面ビュー",
@@ -1183,6 +1280,8 @@
"dxf.progress.write": "DXFを書き込み中 (5/5)",
"dxf.tolerance": "曲線の許容誤差",
"dxf.tolerance_help": "表示中のボディとスケッチを出力し、曲線は線分で近似します。許容誤差を小さくすると曲線が滑らかになりますが、処理時間とメモリ使用量が増えます。",
"each rail's curves must be in one sketch": "各レールの曲線は1つのスケッチ内にある必要があります",
"feature computation ended without a result": "フィーチャーの計算が結果なしで終了しました",
"file.open.drawing_filter": "デザイン、CADファイル、メッシュ、図面",
"file_load.built": "構築済み: 全{total}フィーチャー中{built}件。",
"file_load.converting": "ソリッドを変換中: {done}/{total}",
@@ -1344,6 +1443,8 @@
"keymap.command_id": "コマンドID",
"keymap.empty": "一致するコマンドはありません",
"keymap.use_anyway": "ここでは{key}をそのまま使用",
"label.move_to_left_side": "左側へ移動",
"label.move_to_right_side": "右側へ移動",
"manage.appearance_hint": "選択対象の外観を選ぶか、スウォッチをボディまたは面にドラッグしてください。",
"manage.assign_hint": "ボディを選択し、プラスチック設計ルールを指定してください。",
"manage.config_hint": "構成の行、列、ルールを編集し、行を有効にするかプレビューしてください。",
@@ -1428,7 +1529,9 @@
"nav.free_orbit_upright.help": "マウスを左右にドラッグするとワールドの垂直軸を中心にモデルが回転し、上下にドラッグすると制限なく真上を越えて傾きます。",
"nav.free_orbit_upright.label": "垂直軸を中心に回転",
"nav.fusion.help": "中ドラッグでパン、Shift+中ドラッグで回転、右ドラッグで回転。",
"nav.hfss.help": "Alt+左ドラッグでパン、Shift+Alt+左ドラッグでズーム、何もない所からの Ctrl+左ドラッグで回転。",
"nav.inventor.help": "中ドラッグでパン、Shift+中ドラッグで回転、Ctrl+中ドラッグでズーム、右ドラッグで回転。",
"nav.maya.help": "Alt+左ドラッグで回転、Alt+中ドラッグでパン、Alt+右ドラッグでズーム。中ドラッグでもパン。",
"nav.openscad.help": "空きスペースで左ドラッグすると回転、Shift+左ドラッグで矩形選択、スケッチ ジオメトリはドラッグで編集。右または中ドラッグでパン、Shift+右または Shift+中ドラッグでズーム。",
"nav.perspective.sketch": "スケッチ編集中は平行投影で表示されます。透視投影に切り替えるにはスケッチを終了してください。",
"nav.solidworks.help": "中ドラッグで回転、Ctrl+中ドラッグでパン、Shift+中ドラッグでズーム、右ドラッグで回転。",
@@ -1439,6 +1542,93 @@
"nav.touchpad.pan": "パン(Shift を押しながら移動、マウスボタン不要)",
"nav.touchpad.scroll": "タッチパッドでは縦スクロールでズームします。2 本指パンの設定は他のプリセット用に保持されます。",
"nav.touchpad.zoom": "ズーム(縦スクロールまたはピンチ)",
"navbar.agent_chat": "アシスタントチャットパネル",
"navbar.agent_cursor": "エージェントカーソルを表示",
"navbar.ambient_occlusion": "アンビエントオクルージョン",
"navbar.assistant": "アシスタント",
"navbar.custom.add_slot": "{slot} を追加",
"navbar.custom.always": "常に表示",
"navbar.custom.available": "{available} · バーへドラッグ、または「追加」",
"navbar.custom.buttons": "ボタン",
"navbar.custom.compact": "コンパクト",
"navbar.custom.count": "16 個中 {count} 個のスロット",
"navbar.custom.customise": "ナビゲーションバーをカスタマイズ…",
"navbar.custom.design": "デザイン",
"navbar.custom.duplicate": "このスロットは既にバーにあります。",
"navbar.custom.fade": "薄く表示",
"navbar.custom.full": "別のスロットを追加するには、スロットを削除してください。",
"navbar.custom.hidden_design": "デザインでは非表示",
"navbar.custom.hidden_render": "レンダーでは非表示",
"navbar.custom.hide": "ナビゲーションバーを非表示",
"navbar.custom.hide_idle": "ホバー時のみ表示",
"navbar.custom.icon_only": "アイコンのみ",
"navbar.custom.icon_value": "アイコンと値",
"navbar.custom.icons": "アイコン",
"navbar.custom.idle": "操作していないとき",
"navbar.custom.intro": "3Dビューの下部に表示する操作と順序を選びます。スロットをドラッグして移動し、バーの外へドラッグして削除します。",
"navbar.custom.labels": "アイコンとラベル",
"navbar.custom.left": "左へ移動",
"navbar.custom.position": "位置",
"navbar.custom.position_centre": "中央",
"navbar.custom.position_left": "左",
"navbar.custom.position_right": "右",
"navbar.custom.preview_as": "プレビュー",
"navbar.custom.regular": "標準",
"navbar.custom.remove": "削除",
"navbar.custom.remove_bar": "バーから削除",
"navbar.custom.render": "レンダー",
"navbar.custom.reset": "ナビゲーションバーをリセット",
"navbar.custom.reset_default": "既定値に戻す",
"navbar.custom.right": "右へ移動",
"navbar.custom.select": "スロットが選択されていません。バーのスロットを選択して移動、削除、表示の変更ができます。",
"navbar.custom.separators_full": "区切りは既に4個あります。",
"navbar.custom.show": "ナビゲーションバーを表示",
"navbar.custom.shows": "表示内容",
"navbar.custom.size": "サイズ",
"navbar.custom.stale": "バーが変更されました。スロットを再選択してください。",
"navbar.custom.title": "ナビゲーションバー",
"navbar.custom.unknown": "このスロットは使用できません。",
"navbar.description.ambient_occlusion": "くぼみや隅を暗くして奥行きを表現します。",
"navbar.description.display": "描画プリセット、グリッド、地面の影、アンビエントオクルージョン、投影を設定します。",
"navbar.description.fit": "選択対象、未選択ならモデル全体が収まるように表示します。",
"navbar.description.grid": "地面のグリッドを表示または非表示にします。",
"navbar.description.ground_shadow": "モデルの下の影を表示または非表示にします。",
"navbar.description.home": "モデル全体の等角投影ビューに戻します。",
"navbar.description.look_at": "選択した面、平面、編集中のスケッチに正対します。",
"navbar.description.orbit": "モデルの周りに視点を回転します。",
"navbar.description.pan": "視点を左右上下に移動します。",
"navbar.description.projection": "平行投影と透視投影を切り替えます。",
"navbar.description.separator": "隣接するスロットをまとめる細い区切り線です。",
"navbar.description.spin": "クリックまたはキー入力まで視点を回転し続けます。",
"navbar.description.visual_style": "シェーディング、ワイヤーフレーム、隠線表示などの描画方法を切り替えます。",
"navbar.description.zoom": "モデルに視点を近づけたり遠ざけたりします。",
"navbar.display": "表示",
"navbar.fit": "フィット",
"navbar.graphics": "グラフィックス",
"navbar.grid": "グリッド",
"navbar.ground_shadow": "地面の影",
"navbar.home": "ホームビュー",
"navbar.later": "後日対応",
"navbar.look_at": "正面から見る",
"navbar.more": "その他",
"navbar.orbit": "オービット",
"navbar.orthographic": "平行投影",
"navbar.pan": "パン",
"navbar.perspective": "透視投影",
"navbar.preset": "プリセット",
"navbar.projection": "透視投影",
"navbar.projection_heading": "投影",
"navbar.separator": "区切り",
"navbar.show": "表示",
"navbar.spin": "連続オービット",
"navbar.style.shaded": "シェーディング",
"navbar.style.shaded_with_edges": "エッジ付きシェーディング",
"navbar.style.shaded_with_hidden_edges": "隠線付きシェーディング",
"navbar.style.wireframe": "ワイヤーフレーム",
"navbar.translucent": "半透明",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "表示スタイル",
"navbar.zoom": "ズーム",
"needs two joints": "2つのジョイントが必要",
"network.allow_once": "今回のみ許可",
"network.always_allow": "このサーバーを常に許可",
@@ -1449,9 +1639,34 @@
"no hole": "穴なし",
"no interference": "干渉なし",
"no joint that moves yet": "可動ジョイントがまだありません",
"no motion study yet": "モーション スタディがまだありません",
"no picture": "画像なし",
"no such joint": "そのジョイントはありません",
"none": "なし",
"not a move": "移動ではありません",
"not a number": "数値ではありません",
"open a sketch first": "先にスケッチを開いてください",
"parts.automatic_name": "自動",
"parts.dimension.across_flats": "二面幅",
"parts.dimension.bore": "内径",
"parts.dimension.d": "呼び径",
"parts.dimension.head_diameter": "頭部径",
"parts.dimension.head_height": "頭部高さ",
"parts.dimension.height": "高さ",
"parts.dimension.inner": "内径",
"parts.dimension.outer": "外径",
"parts.dimension.pitch": "ピッチ",
"parts.dimension.socket": "六角穴の二面幅",
"parts.dimension.socket_depth": "六角穴の深さ",
"parts.dimension.thickness": "厚さ",
"parts.dimension.width": "幅",
"parts.family.bearing": "深溝玉軸受(外形)",
"parts.family.dowel_pin": "平行ピン",
"parts.family.hex_bolt": "六角ボルト",
"parts.family.hex_nut": "六角ナット",
"parts.family.set_screw": "六角穴付き止めねじ 平先",
"parts.family.socket_head_cap_screw": "六角穴付きボルト",
"parts.family.washer": "平座金",
"pattern.alignment_2": "配置 2",
"pattern.alignment_hint": "個数には元の図形が含まれます。中央配置ではコピーを両側に配置し、反転で偶数個の場合に多く配置する側を切り替えます。",
"pattern.direction_1": "方向 1",
@@ -1467,9 +1682,25 @@
"perf.ui_time": "UI 時間",
"perf.viewport": "ビュー",
"perf.worst": "最悪",
"pick a body or some of its faces": "ボディ、またはそのボディの面を選択してください",
"pick a hole to seat it, or OK places it at the origin": "配置先の穴を選択するか、[OK]を押すと原点に配置します。",
"pick a planar face": "平面状の面を選択してください",
"pick a plane or a face as the tool": "ツールとして平面または面を選択してください",
"pick a size": "サイズを選択してください",
"pick edges of a body": "ボディのエッジを選択してください",
"pick edges of one body": "1つのボディのエッジを選択してください",
"pick edges of the holes to remove": "削除する穴のエッジを選択してください",
"pick faces of one body": "1つのボディの面を選択してください",
"pick faces to offset": "オフセットする面を選択してください",
"pick lines of one sketch": "1つのスケッチの線を選択してください",
"pick one or two vertices, edges or faces": "1つまたは2つの頂点、エッジ、面を選択",
"pick one plane or face as the tool, or sketch curves": "ツールとして平面または面を1つ、またはスケッチ曲線を選択してください",
"pick sections in two or more sketches": "2つ以上のスケッチにあるセクションを選択してください",
"pick sketch curves or edges": "スケッチ曲線またはエッジを選択してください",
"pick the face to untrim": "トリム解除する面を選択してください",
"pick the path": "パスを選択",
"pick what to keep": "残す部分を選択してください",
"pick what to keep of the other surface": "相手のサーフェスで残す部分を選択してください",
"prefs.add_item": "項目を追加",
"prefs.alt_frees_manipulators": "Alt / Option でマニピュレーターの矢印も自由に動かす",
"prefs.anti_aliasing_amd_dx12": "起動時のチェックでマルチサンプリングでは何も描画されず、1×では正常に描画されたため、アンチエイリアシングを1×に設定しました。上で別の設定を選択できます。再起動後のチェックに合格すると、その設定が適用されます。",
@@ -1837,6 +2068,64 @@
"render.effects_help": "順序付きカラー効果と画像空間レンズ効果を組み合わせます。レンダーと生マスター再調整は同じ保存設定を使います。生 EXR は不変です。校正済みレンズや市販フィルムの模倣ではありません。",
"render.effects_reset_lens": "レンズ効果をリセット",
"render.effects_seed": "パターンシード",
"render.emitted_axis": "照射軸",
"render.error_area_samples": "area_samplesは1、4、16、64のいずれかです",
"render.error_binding_allocation": "マテリアルの割り当て領域を確保できません",
"render.error_body_bound": "製品プレビューが取得ボディ数の上限を超えています",
"render.error_checkpoint_dimensions": "チェックポイントの寸法が取得済みリクエストと異なります",
"render.error_decode_budget": "画像デコードの容量が上限を超えています",
"render.error_denoise_setting": "ネイティブノイズ除去設定が無効です",
"render.error_display_dimensions": "画像の表示寸法が無効です",
"render.error_display_fit": "このデバイスに画像表示を収められません",
"render.error_display_height": "表示高さが上限を超えています",
"render.error_display_width": "表示幅が上限を超えています",
"render.error_duplicate_face": "製品の面の外観が重複しています",
"render.error_export_document": "出力先の選択中にレンダリング書き出し元のドキュメントが変更されました",
"render.error_face_cap": "製品プレビューが面の外観数の上限を超えています",
"render.error_finish_gesture": "プレビューの前にモデリング操作を完了してください",
"render.error_finish_operation": "Renderに入る前に現在のモデリング操作を完了してください",
"render.error_fixed_preview": "固定スタジオプレビューには露出0、環境回転0、強度1が必要です",
"render.error_geometry_size": "製品形状のサイズが上限を超えています",
"render.error_glass_recipe": "不明なガラスレシピ",
"render.error_gpu_preview": "このホストではGPU製品プレビューを利用できません。保存済み設定は引き続き利用できます。",
"render.error_gpu_samples": "未対応のGPUサンプル数",
"render.error_image_dimensions": "レンダリング画像の寸法がジョブと一致しません",
"render.error_image_profile": "レンダリング画像が取得済みリソース枠を超えています",
"render.error_interactive_command": "未接続の対話型Renderコマンド",
"render.error_job_action": "対話型画像ジョブ操作ではありません",
"render.error_job_identity": "レンダリングジョブの識別情報が無効です: {error}",
"render.error_library_reply": "Renderライブラリーの応答が無効です",
"render.error_material_binding": "マテリアルの割り当てがありません",
"render.error_no_completed_image": "完了したレンダリング画像がありません",
"render.error_no_geometry": "製品形状がありません",
"render.error_no_scene": "製品シーンがありません",
"render.error_opacity": "製品の外観の不透明度が無効です",
"render.error_pbr_opacity": "不透明PBRには不透明度1が必要です",
"render.error_physical_glass": "選択したレシピは物理ガラスではありません",
"render.error_preview_device": "製品プレビューには深度バッファーを備えたデバイスが必要です",
"render.error_product_triangle": "製品の三角形が無効です",
"render.error_provisional_identity": "仮レンダリングの識別情報またはサンプル数が無効です",
"render.error_quality_bounds": "品質設定の反映がネイティブ上限を超えています",
"render.error_quality_method": "品質設定の反映には同じ明示的なGPU方式が必要です",
"render.error_quality_projection": "ネイティブ品質設定の反映が無効です",
"render.error_regrade_identity": "再調整の識別情報が無効です: {error}",
"render.error_scene_bodies": "レンダリングシーンのボディがありません",
"render.error_scene_body_limit": "レンダリングシーンがボディ数の上限を超えています",
"render.error_scene_identity": "レンダリングシーンの識別情報が無効です",
"render.error_setup_panicked": "GPUパストレーサーの初期化に失敗しました",
"render.error_setup_stopped": "初期化ワーカーがホストを返さずに停止しました",
"render.error_setup_worker": "初期化ワーカーを開始できません: {error}",
"render.error_source_preview": "ソースプレビューがデータ容量の上限を超えています",
"render.error_surface_normals": "PBRにはゼロでない面法線が必要です",
"render.error_surface_reply": "作成済みサーフェスの応答が無効です",
"render.error_triangle_bound": "製品プレビューが元データの800万三角形の上限を超えています",
"render.error_triangle_count": "製品の三角形数が上限を超えています",
"render.error_upload_slot": "製品プレビューのアップロード枠が利用できません",
"render.error_vertex_allocation": "製品プレビューの頂点メモリー確保に失敗しました",
"render.error_vertex_envelope": "製品プレビューが頂点データの上限{limit} MiBを超えています。形状は簡略化されていません",
"render.error_vertex_packing": "製品プレビューの配置が許可済み頂点データと異なります",
"render.error_visible_solid": "ここでプレビューするにはDesignで表示可能なソリッドを作成してください。",
"render.exit_focus": "フォーカス表示を終了",
"render.export_display": "書き出し:表示PNG",
"render.export_image_label": "画像を書き出す",
"render.export_linear": "書き出し:生の線形EXR",
@@ -1850,6 +2139,7 @@
"render.flare_streak": "アナモルフィック風の筋",
"render.flare_strength": "ハイライトフレア強度",
"render.flare_threshold": "シーンリニアしきい値",
"render.fold_browser": "ブラウザーを折りたたむ",
"render.gpu_depth": "最大パス深度",
"render.gpu_options_help": "サンプル数、深度、シード、露出をこの設定に保存します。保存するのは選択中の画像方式だけです。",
"render.gpu_path_failed": "GPUパストレーサーを利用できません",
@@ -1907,11 +2197,13 @@
"render.image_use_largest": "この縦横比での最大サイズを使用:",
"render.image_width": "幅",
"render.include_rig_cards": "Include passive cards and flags",
"render.inner_half_angle": "内側半角",
"render.inspect_scene": "記録するシーンの概要を更新",
"render.inspector": "インスペクター",
"render.keep_editing": "編集を続ける",
"render.layer_down": "下へ",
"render.layer_enabled": "層を有効にする",
"render.layer_off_suffix": "(オフ)",
"render.layer_remove": "層を削除",
"render.layer_strength": "層の強さ",
"render.layer_up": "上へ",
@@ -2059,6 +2351,7 @@
"render.optics_save": "この光学設定を撮影に保存",
"render.optics_saved": "保存済み光学対象",
"render.optics_saved_help": "定義・フィーチャー・配置の正確な識別子をオフライン再開時も保持します。欠落・置換・非表示の対象は拒否し、工学材料は変更しません。削除前に数値編集を保存または破棄してください。",
"render.outer_half_angle": "外側半角",
"render.output_format_status": "PNGは完了した表示画像そのものです。GPUの任意EXRは表示フィルター前の生の線形FLOAT32放射輝度を保持します。プレビューキャッシュや別ジョブへの置換はありません。",
"render.output_lock_ratio": "縦横比を固定",
"render.output_over_budget": "要求画像が選択したリソース枠を超えています。対応するサイズかプロファイルを明示的に選択してください。自動的な品質低下は行いません。",
@@ -2092,7 +2385,10 @@
"render.physical_prepare_plan": "Prepare creation plan (does not apply)",
"render.physical_separate": "Appearance is not material identification. These are sourced references, not certified effective properties. Existing mass, engineering materials and optics are unchanged.",
"render.physical_unknown": "No numerical candidate is established. Grade, formulation or construction must be specified; unknown is not zero.",
"render.pick_body": "ボディ",
"render.pick_component": "コンポーネント",
"render.pick_face": "面",
"render.pick_help": "ボディ、面、コンポーネントを選択します。空白をクリックすると選択解除、Shift または Ctrl で追加・切り替えます。ハイライトはライブ製品ビューのみに表示されます。",
"render.pick_label": "選択",
"render.pick_up_label": "取得",
"render.pick_waiting": "製品の選択はまだサポートされていません。",
@@ -2114,6 +2410,12 @@
"render.preview_upload": "ライブプレビューの頂点データ量",
"render.preview_upload_help": "プレビュー頂点の正確なバイト数です。GPU全体やプロセス全体のメモリ量ではありません。形状は簡略化せず、画像ジョブは独自の准入と照明を使用します。",
"render.progressive_image_summary": "プレビューPNG · 不透明PBR · プログレッシブサンプリング",
"render.property_conditions": "条件: {value}",
"render.property_fallback": "プロパティ",
"render.property_qualifier": "修飾条件: {value}",
"render.property_source": "出典: {id} - {locator}",
"render.property_uncertainty": "不確かさ: {value}",
"render.property_unknown": "不明",
"render.quality_ack": "固定予算への部分適用と省略項目を確認",
"render.quality_apply": "この固定サンプリング予算を使用",
"render.quality_projection_help": "Qプリセットには将来の要件も含まれます。この操作は対応する固定サンプルPNG予算のみを適用し、適応的停止、生の線形出力、独立した透過制限は含みません。",
@@ -2129,6 +2431,7 @@
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.restore_camera": "保存したカメラを復元",
"render.result_actual_help": "画像の1ピクセルを画面の1ピクセルで表示します。",
"render.result_actual_size": "100%",
"render.result_capture": "キャプチャ時のリビジョン",
"render.result_current": "キャプチャしたモデルのリビジョンは最新です。",
"render.result_empty": "完成した画像はまだありません。設定を確認してレンダリングを開始してください。",
@@ -2203,10 +2506,14 @@
"render.shot_rename": "保存済みショットの名前を変更",
"render.shot_saved_only": "先に現在の下書きを保存してください。複製と名前変更では正確な保存オプションとリソース参照を保持します。",
"render.show_shots_label": "ショットストリップを表示",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "フルHD",
"render.size_hd": "HD",
"render.sky_ground": "地面・線形RGB",
"render.sky_horizon": "地平線・線形RGB",
"render.sky_zenith": "天頂・線形RGB",
"render.soft_focus": "ソフトフォーカス",
"render.spot_cone": "スポット円錐",
"render.stage_frame": "構図",
"render.stage_light": "照明",
"render.stage_look": "外観",
@@ -2257,9 +2564,45 @@
"render.subsurface_enable": "内部散乱ランダムウォーク",
"render.subsurface_help": "閉じた誘電体専用。散乱とRGB吸収は別々の毎mm係数です。実際の形状内で散乱し、境界で屈折・反射します。直線透過影、表面ノイズ除去、外部ボリュームを無効にし、フレネル層数を1にします。拡散シェーダー、密度グリッド、実測物性ではありません。高密度ではサンプル数と深度が必要です。",
"render.subsurface_rate": "散乱衝突率",
"render.tone_aces_fitted": "ACES近似",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "GPUガラスは検証された非交差媒体に対応します。無制限の入れ子媒体やノイズのない透過推定器は提供しません。",
"render.transmission_strata": "条件付きフレネル層数",
"render.transmission_strata_help": "1 は従来の系列を保持します。2 または4経路で最初のガラス反射・透過の選択を層化します。スネル則と吸収則は不変です。処理量は増えます。ノイズ除去、入れ子媒質、高速化の保証ではありません。",
"render.tree_add_light": "ライトを追加",
"render.tree_add_shot": "ショットを追加",
"render.tree_browser": "レンダーブラウザー",
"render.tree_by_look": "外観別",
"render.tree_by_object": "オブジェクト別",
"render.tree_constant": "一定の環境光",
"render.tree_default": "既定",
"render.tree_directional": "平行光",
"render.tree_environment": "環境",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} 面",
"render.tree_face_one": "{count} 面",
"render.tree_fixed_studio": "固定スタジオ",
"render.tree_hdr": "HDR",
"render.tree_lights": "ライト",
"render.tree_lights_pending": "名前付きライトのコマンドはまだ利用できません。",
"render.tree_mixed": "混在",
"render.tree_more": "ほか{count}件",
"render.tree_mute": "ライトをミュート",
"render.tree_no_environment": "環境なし",
"render.tree_objects": "オブジェクト",
"render.tree_output": "出力",
"render.tree_point": "点光源",
"render.tree_rectangle": "矩形",
"render.tree_search": "オブジェクトを検索",
"render.tree_selection": "レンダー選択",
"render.tree_shots": "ショット",
"render.tree_sky": "空",
"render.tree_solo": "ライトをソロにする",
"render.tree_spot": "スポット",
"render.tree_sun": "太陽",
"render.tree_switch": "切り替え",
"render.tree_user_one": "{count} オブジェクト",
"render.tree_users": "{count} オブジェクト",
"render.unavailable_preview": "このセットアップは利用できないプレビュープロファイルを要求しています。",
"render.unsaved": "未保存のプレビュー変更",
"render.use_preview": "統合プレビューを使用",
@@ -2303,6 +2646,26 @@
"search.try": "コマンド名、このデザインのフィーチャー、またはパラメーターを入力します。値を指定して実行するには、IDとJSONオブジェクトを入力します:{example}",
"search.valid": "有効",
"section.off_hint": "平面が選択されていません。OK を押すとセクションを解除します。",
"select a direction (an axis, a sketch line or a straight edge) first": "方向(軸、スケッチ線、または直線のエッジ)を先に選択してください",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "プロファイルが沿う方向(軸、スケッチ線、または直線のエッジ)を選択してください",
"select a point on a component": "コンポーネント上の点を選択してください",
"select a profile, edges or sketch lines first": "プロファイル、エッジ、またはスケッチ線を先に選択してください",
"select an axis": "軸を選択してください",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "軸、直線または円のエッジ、あるいは円柱・円錐・トーラスの面を先に選択してください",
"select bodies first": "ボディを先に選択してください",
"select corner points, or the two lines of one corner": "コーナーの点、または1つのコーナーの2本の線を選択してください",
"select one corner point, or the two lines of one corner": "コーナーの点を1つ、または1つのコーナーの2本の線を選択してください",
"select sheet edges first": "板金のエッジを先に選択してください",
"select the bend line (a sketch line) first": "曲げ線(スケッチ線)を先に選択してください",
"select the cam's profile (a sketch profile or the cam's edges)": "カムのプロファイル(スケッチのプロファイル、またはカムのエッジ)を選択してください",
"select the corner to cut first": "切り落とすコーナーを先に選択してください",
"select the corners to round first": "丸めるコーナーを先に選択してください",
"select the fixed face first (a plate's large face)": "固定面(プレートの大きな面)を先に選択してください",
"select the frame sketch's lines first": "フレームスケッチの線を先に選択してください",
"select the path (sketch lines across the edge)": "パス(エッジをまたぐスケッチ線)を選択してください",
"select the rim face first": "リム面を先に選択してください",
"select the sheet edge first": "板金のエッジを先に選択してください",
"select two components": "2つのコンポーネントを選択してください",
"set by the sketch's lines": "スケッチの線で決まります",
"settings.display_quality_note": "表示だけに影響します。設計や書き出しは変わりません。",
"settings.frame_rate_details_note": "直近のフレーム時間のグラフ(描画した三角形数を重ねて表示)、フレーム時間のヒストグラム、GPU が描画した内容を追加します。ビューのフレームレートをクリックすると表示/非表示を切り替えます。",
@@ -2320,17 +2683,23 @@
"settings.window_system_details": "詳細",
"settings.window_system_note_now": "再起動後に適用されます。現在: {now}。",
"settings.window_system_wayland_limited": "ネイティブ Wayland では一部の機能が制限されます。",
"sheet.flange_type_base": "ベース",
"sheet.flange_type_contour": "輪郭",
"sheet.flange_type_edge": "エッジ",
"sheet.no_body": "板金ボディがありません。フランジ > Base で作成するか、板金に変換でプレートを板金に変換してください(広い平面を選択)。",
"shortcut.json_error": "パラメータはJSON形式で指定してください: {error}",
"shortcut.no_command": "コマンド`{id}`がありません。JSONの前のテキストはコマンドIDである必要があります",
"shortcut.pin": "Sボックスの先頭にピン留め",
"shortcut.unpin": "ピン留めを解除",
"sketch is missing": "スケッチが見つかりません",
"sketch.degrees_of_freedom": "自由度 {count}",
"sketch.dof_left": "残り自由度 {count}",
"sketch.dof_left_one": "残り自由度 {count}",
"sketch.draw_curves": "{linetype}として描く",
"sketch.make_selection": "選択を{linetype}にする",
"sketch.open_ends": "開放 {count}",
"sketch.status_conflict": "拘束が競合しています",
"sketch.status_fully_constrained": "完全拘束",
"sketch.untied_ends": "未拘束 {count}",
"sketch_panel.attached": "接続先: {body} / {path}",
"sketch_panel.author": "作成時の配置: {path}",
@@ -2357,7 +2726,24 @@
"sketch_text.path_hint": "文字が沿うスケッチの曲線: ここをクリックしてから曲線をクリック",
"sketch_text.use_font_file": "フォント ファイル {path} を使用",
"solid": "中実",
"the angle must be a number": "角度は数値にしてください",
"the curves must be in one sketch": "曲線は1つのスケッチ内にある必要があります",
"the direction must be an axis, a sketch line or a straight edge": "方向は、軸、スケッチ線、または直線のエッジにしてください",
"the duration must be a number of seconds, 0.001 or more": "時間は0.001秒以上の秒数で指定してください",
"the line's sketch is gone": "線のスケッチが存在しなくなりました",
"the lines must be in one sketch": "線は1つのスケッチ内にある必要があります",
"the lines must be in one sketch, not the section's": "線は、セクションのスケッチではなく、1つのスケッチ内にある必要があります",
"the parts library is empty": "パーツライブラリが空です",
"the parts library is not available": "パーツライブラリは利用できません",
"the path curves must be in one other sketch": "パスの曲線は、別の1つのスケッチ内にある必要があります",
"the path's sketch is gone": "パスのスケッチが存在しなくなりました",
"the position must be a number": "位置は数値にしてください",
"the preview failed": "プレビューに失敗しました",
"the profiles and curves must be in one sketch": "プロファイルと曲線は1つのスケッチ内にある必要があります",
"the reference face must be on the edges' body": "参照面はエッジのボディ上にある必要があります",
"the scale must be above 0": "尺度は0より大きくしてください",
"the section's profiles must be in one sketch": "セクションのプロファイルは1つのスケッチ内にある必要があります",
"the two origins are on the same component": "2つの原点が同じコンポーネント上にあります",
"thread.automatic_size": "サイズを自動選択",
"thread.designation": "ねじの呼び",
"thread.direction": "ねじの方向",
@@ -2397,6 +2783,7 @@
"trace.points": "経路上の {count} 点",
"trace.stopped_by_contact": "サンプル {sample} で終了: {a} が {b} を通り抜けてしまいます",
"trace.stopped_by_loop": "サンプル {sample} で終了: {joint} を通るループはこれ以上閉じられません",
"trim by sketch curves, or by one plane or face": "スケッチ曲線、または1つの平面か面でトリムしてください",
"ui.1_degree_of_freedom": "自由度 1",
"ui.3d_mouse_axes_reassigned": "軸の割り当ては環境設定で変更されており、このキャリブレーションの後も適用されます。",
"ui.3d_mouse_button": "ボタン {number}",
@@ -2873,6 +3260,8 @@
"ui.design_properties.revision": "リビジョン",
"ui.diameter": "直径",
"ui.dimension": "寸法",
"ui.direct_interaction": "ダイレクト操作",
"ui.direct_interaction_note": "ビューポートでモデルを直接操作します。平らな面またはプロファイルを押して引きます。上に引くと押し出し、ボディの中へ下げるとカット、横の動きで刻み幅を設定します",
"ui.direction": "方向",
"ui.display_quality": "表示品質",
"ui.display_quality_coarse": "粗い",
@@ -2896,6 +3285,7 @@
"ui.editJointLimits": "ジョイント制限を編集",
"ui.edit_section_analysis": "断面解析を編集",
"ui.ellipse": "楕円",
"ui.emboss_wrap_note": "サポートされる円柱に接する直交線のプロファイルは自動的に巻き付けられます。対象を選ぶには壁を選択してください。",
"ui.end_radius": "終了半径",
"ui.end_scale": "終端スケール",
"ui.entities": "エンティティ",
@@ -2968,6 +3358,7 @@
"ui.heading_extrude": "押し出し",
"ui.heading_fillet": "フィレット",
"ui.heading_finish_sketch": "スケッチを終了",
"ui.heading_form": "フォーム",
"ui.heading_front": "正面",
"ui.heading_hole": "穴",
"ui.heading_home": "ホーム",
@@ -3016,6 +3407,7 @@
"ui.heading_utilities": "ユーティリティ",
"ui.heading_utility": "ユーティリティ",
"ui.heading_weldments": "溶接構造",
"ui.height": "高さ",
"ui.help": "ヘルプ",
"ui.hide": "非表示",
"ui.hideAxes": "軸を非表示",
@@ -3053,11 +3445,14 @@
"ui.intersect": "交差",
"ui.isolate": "分離表示",
"ui.join": "結合",
"ui.joint_play": "▶ 再生",
"ui.joint_stop": "■ 停止",
"ui.joints": "ジョイント",
"ui.keyboard_shortcuts": "キーボードショートカット",
"ui.language": "言語",
"ui.layout_compact": "コンパクト",
"ui.layout_floating": "フローティング",
"ui.length": "長さ",
"ui.length_decimals": "長さの小数点以下の桁数",
"ui.light": "ライト",
"ui.line": "線分",
@@ -3069,6 +3464,7 @@
"ui.loft": "ロフト",
"ui.look_at": "正面視",
"ui.look_at_anim_desc": "軸ビュー、正面視、ホーム、全体表示",
"ui.major_radius": "大半径",
"ui.manipulator_free_alt": "マニピュレータのフリードラッグを Alt/Option でも有効",
"ui.manipulator_free_alt_tip": "オン: 押し出し/ギズモ矢印で Alt/Option または Ctrl/Cmd が値スナップを無効にします。オフ: Ctrl/Cmd のみ。",
"ui.manufacture": "製造",
@@ -3098,8 +3494,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "面タグ付き 3MF",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "小半径",
"ui.mirror": "ミラー",
"ui.mirror_line": "ミラー線",
"ui.modifiers_either": "{first} または {second}",
"ui.move": "移動",
"ui.multiple": "複数",
"ui.named_views": "名前付きビュー",
@@ -3156,6 +3554,7 @@
"ui.pinToShortcuts": "ショートカットに固定",
"ui.pinToToolbar": "ツールバーに固定",
"ui.pipe": "パイプ",
"ui.pitch": "ピッチ",
"ui.placement": "配置",
"ui.placement_handles": "配置ハンドル",
"ui.placement_handles_tip": "レスト、ボス、スナップ フィットのプレビューに表示されるハンドル: マーカーをドラッグしてモデル上を移動し、リングで回転します",
@@ -3218,6 +3617,7 @@
"ui.reverse_horizontal_pan_direction": "水平パンの方向を反転",
"ui.reverse_horizontal_pan_tip": "水平方向の2本指スクロールとサムホイールで、反対方向にパンします",
"ui.reverse_zoom_direction": "ズーム方向を反転",
"ui.revolutions": "巻き数",
"ui.revolve": "回転",
"ui.ribbon_exit": "終了",
"ui.ribbon_labels": "リボンのアイコンの下にテキストを表示",
@@ -3234,6 +3634,7 @@
"ui.scale": "尺度",
"ui.second_rail": "第2レール",
"ui.section_analysis": "断面解析",
"ui.section_size": "断面サイズ",
"ui.select": "選択",
"ui.selectOther": "その他を選択…",
"ui.selectTangentChain": "接線チェーンを選択",
@@ -3305,6 +3706,7 @@
"ui.start_page": "スタートページ",
"ui.step_values": "矢印キーとホイールで数値を増減",
"ui.step_values_tip": "入力中の値フィールドでは、上下矢印キーとフィールド上のマウスホイールで数値を 1 ずつ増減します(Shift: 10、Alt: 0.1)。式はそのまま残ります。",
"ui.stitch_tolerance_hint": "厳密",
"ui.stretch": "伸縮",
"ui.supersampling": "スーパーサンプリング (SSAA)",
"ui.supersampling_adaptive": "ビューが静止しているときのみ",
@@ -3335,6 +3737,8 @@
"ui.to_object": "オブジェクトまで",
"ui.tool_direction": "工具方向",
"ui.top": "上面",
"ui.top_diameter": "上面の直径",
"ui.top_radius": "上面の半径",
"ui.torus": "トーラス",
"ui.total_angle": "合計角度",
"ui.trackpad_pan_tip": "2本指スクロールでパンします。FusionではShift + 2本指スクロールで回転します。オフの場合はスクロールでズームします。マウスホイールとピンチ操作はズーム、サイドホイールは横方向のパンになります。",
@@ -3363,6 +3767,7 @@
"ui.visual_shaded_with_edges": "エッジ付きシェーディング",
"ui.visual_style": "表示スタイル",
"ui.visual_wireframe": "ワイヤーフレーム",
"ui.width": "幅",
"ui.window_system": "ウィンドウシステム",
"ui.window_system_auto": "自動",
"ui.window_system_wayland": "Wayland",
@@ -3423,6 +3828,9 @@
"update.up_to_date": "SolidCraft は最新です。",
"update.update_now": "今すぐ更新",
"update.you_have": "現在のバージョンは {version} です。",
"use a positive nominal diameter and a pitch smaller than it": "正の呼び径と、それより小さいピッチを使用してください",
"values must be finite numbers": "値は有限の数値にしてください",
"values must be numbers or expressions": "値は数値または式にしてください",
"view.auto_ortho_faces": "回転中は透視投影、面を正面に見ると平行投影",
"web.files.insert_drawings_hint": "CADファイル、メッシュ、DXF、SVGを開いているデザインに挿入",
"web.files.insert_stored_drawings_hint": "開いているデザインに挿入(CADファイル、メッシュ、DXF、SVG)",
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(활성 규칙)",
"0 turns it off": "0이면 끕니다",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. 아래에서 GitHub 초안을 열고 클립보드에 복사된 보고서를 붙여넣으세요.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. 아래에서 GitHub 초안을 여세요. 제목과 보고서가 자동으로 입력됩니다.",
@@ -43,13 +44,17 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "먼저 외관을 적용하세요. 지정된 외관과 이 디자인에서 만든 재질을 내보냅니다.",
"Arc length": "호 길이",
"Area": "면적",
"As Picked": "선택한 대로",
"As-Built": "As-Built",
"Assign Rule": "규칙 지정",
"Attachment": "부착",
"BLEND SURFACE": "블렌드 곡면",
"BOUNDARY SURFACE": "경계 곡면",
"BROWSER": "브라우저",
"Ball": "볼",
"Base Height": "베이스 높이",
"Bend Edges": "벤딩 모서리",
"Bend Line": "굽힘선",
"Bend Line Position": "벤딩 선 위치",
"Bend Position": "벤딩 위치",
"Bend Radius": "벤딩 반지름",
@@ -61,6 +66,7 @@
"Body (last if none)": "바디 (없으면 마지막)",
"Body to split": "분할할 바디",
"Body, or faces to take out": "바디 또는 제거할 면",
"Both": "양쪽",
"Boundary": "경계",
"Bounding box": "경계 상자",
"CHECK": "검사",
@@ -86,6 +92,7 @@
"Choose Variable radius or Spline in Type.": "유형에서 가변 반지름 또는 스플라인을 선택하세요.",
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "새 평면을 선택하세요. 스케치 기하와 치수는 2차원 좌표 그대로 유지됩니다.",
"Choose…": "선택…",
"Circle or sphere": "원 또는 구",
"Circular": "원형",
"Circumference": "원주",
"Clockwise": "시계 방향",
@@ -102,6 +109,7 @@
"Config Table": "구성 표",
"Configuration": "구성",
"Configuration rules": "Configuration rules",
"Constant radius": "일정 반지름",
"Contact": "접촉",
"Contact Sets": "접촉 집합",
"Contact sets": "접촉 집합",
@@ -132,7 +140,9 @@
"Custom": "사용자 지정",
"Customize Toolbar": "도구 모음 사용자 지정",
"Customize…": "사용자 지정…",
"Cylindrical": "원통형",
"Cylindrical face": "원통면",
"Deboss": "디보스",
"Delete": "삭제",
"Delete Selected Features…": "선택한 피처 삭제…",
"Delete Selected Folders": "선택한 폴더 삭제",
@@ -157,6 +167,7 @@
"Double-clicking the middle button in the view: Home (the home view, framing what is shown), Fit (frame what is shown, keeping the orientation) or nothing": "뷰에서 가운데 버튼을 더블 클릭: 홈(홈 뷰, 표시된 항목에 맞춤), 맞춤(방향을 유지하며 표시된 항목에 맞춤) 또는 없음",
"Drive Joint": "조인트 구동",
"Duration": "지속 시간",
"Edge": "모서리",
"Edges": "모서리",
"Edit": "편집",
"Edit Profile Sketch": "윤곽 스케치 편집",
@@ -165,6 +176,7 @@
"End Radius": "끝 반지름",
"End bulge": "끝 벌지",
"End continuity": "끝 연속성",
"Equal Distance": "같은 거리",
"Expand": "펼치기",
"Expected result (optional)": "예상 결과 (선택 사항)",
"Explode": "분해",
@@ -190,6 +202,8 @@
"Faces": "면",
"Faces / edges / vertices": "면 / 모서리 / 꼭짓점",
"Faces to split": "분할할 면",
"Faces/Body": "면/바디",
"Factor must be a positive number": "계수는 양수여야 합니다",
"Fastener": "체결 부품",
"Favorites": "즐겨찾기",
"Favourite": "Favourite",
@@ -199,16 +213,21 @@
"Filter…": "필터…",
"Find in Browser": "브라우저에서 찾기",
"Finish": "완료",
"First edge": "첫 번째 모서리",
"First plane": "첫 번째 평면",
"First point": "첫 번째 점",
"Fit and G2 corners require Constant radius.": "맞춤 및 G2 모서리에는 일정 반지름이 필요합니다.",
"Fixed Face": "고정 면",
"Flange Gap": "플랜지 간격",
"Flat Pattern": "플랫 패턴",
"Flat size": "전개 크기",
"Follow camera (Look At sketches)": "카메라 따라가기 (스케치 보기)",
"Follow the camera (Look At sketches)": "카메라 따라가기 (스케치 보기)",
"Font": "글꼴",
"Free Move": "자유 이동",
"From": "시작",
"From Bodies": "바디에서",
"From Snap": "시작 스냅",
"From edges": "시작 모서리",
"Full Length": "전체 길이",
"G2 corners require a constant radius and Exact fit. G2 corner construction is not supported yet.": "G2 모서리에는 일정 반지름과 정확한 맞춤이 필요합니다. G2 모서리 생성은 아직 지원되지 않습니다.",
@@ -216,10 +235,13 @@
"Grid": "격자",
"HISTORY": "이력",
"Height": "높이",
"Hem Gap": "헴 간격",
"Hidden edges": "숨겨진 모서리",
"History layout": "기록 레이아웃",
"History names": "이력 이름",
"Hole (optional)": "구멍 (선택 사항)",
"Hole Depth": "구멍 깊이",
"Hole Diameter": "구멍 지름",
"Holes": "구멍",
"Holes (edges on them)": "구멍 (구멍의 모서리)",
"Home view": "홈 뷰",
@@ -238,12 +260,16 @@
"Issue title": "이슈 제목",
"Items": "항목",
"JOINTS": "조인트",
"Joint 1": "관절 1",
"Joint 2": "관절 2",
"Joint Origin1": "조인트 원점1",
"K Factor": "K 계수",
"Keep (points on it)": "유지할 부분(그 위의 점)",
"Keep Tools": "공구 유지",
"Keep of the other surface": "다른 곡면에서 유지할 부분",
"Key a joint's value at this step": "이 단계에서 조인트 값을 키프레임으로 설정",
"Keys": "키프레임",
"Knife Edge": "칼날 모서리",
"LIBRARY": "라이브러리",
"LINKS": "링크",
"Later": "나중에",
@@ -254,9 +280,11 @@
"Letter Spacing": "글자 간격",
"Library": "라이브러리",
"Library file": "라이브러리 파일",
"Library response is missing": "라이브러리 응답이 없습니다",
"Limits": "제한",
"Line Spacing": "줄 간격",
"Line Type": "선 유형",
"Line on plane": "평면 위의 선",
"Listing the installed fonts…": "설치된 글꼴 목록을 불러오는 중…",
"Load library": "라이브러리 불러오기",
"Local library": "로컬 라이브러리",
@@ -272,11 +300,14 @@
"Matched restrictions check the final values.": "조건이 충족된 제한 규칙은 최종 값을 검사합니다.",
"Material": "재질",
"Max": "최대",
"Max Thickness": "최대 두께",
"Maximum": "최대",
"Mesh body": "메쉬 바디",
"Mid Radius": "중간 반지름",
"Middle double-click": "가운데 버튼 더블 클릭",
"Min": "최소",
"Min Draft": "최소 구배",
"Min Thickness": "최소 두께",
"Minimum": "최소",
"Mirror Plane": "대칭 평면",
"Mitre": "연귀",
@@ -294,6 +325,7 @@
"Move up": "위로 이동",
"Name": "Name",
"Nearest": "가장 가까운",
"Neutral plane": "중립면",
"New": "새로 만들기",
"New Comp.": "새 구성요소",
"New Sketch": "새 스케치",
@@ -303,6 +335,7 @@
"No matching appearance presets.": "일치하는 외관 프리셋이 없습니다.",
"No matching appearances": "일치하는 외관 없음",
"No visible bodies or sketches to export.": "표시된 바디나 스케치가 없어 내보낼 수 없습니다.",
"Nominal Radius": "공칭 반지름",
"Nominal diameter": "호칭 지름",
"None": "없음",
"Not available yet": "아직 사용할 수 없음",
@@ -324,21 +357,27 @@
"Overall length": "전체 길이",
"Param. Graph": "매개변수 그래프",
"Parameter": "매개변수",
"Part length must be greater than zero and at most 2000 mm": "부품 길이는 0보다 크고 2000 mm 이하여야 합니다",
"Parts": "부품",
"Pass through": "통과점",
"Path": "경로",
"Pattern": "패턴",
"Per Edge": "모서리별",
"Pick a part size": "부품 크기를 선택하세요",
"Pick the tool bodies": "공구 바디를 선택하세요",
"Picked": "선택한 항목",
"Picked point": "선택한 점",
"Pin-slot": "핀-슬롯",
"Pitch": "피치",
"Pivot": "피벗",
"Place at the origin instead": "대신 원점에 배치",
"Planar": "평면",
"Plastic Rules": "플라스틱 규칙",
"Play the joint's motion in the view": "뷰에서 조인트의 모션 재생",
"Playback": "재생",
"Plot": "그래프",
"Point on line": "선 위의 점",
"Point on plane": "평면 위의 점",
"Position": "위치",
"Position (0 to 1)": "위치 (0~1)",
"Position (G0)": "위치 (G0)",
@@ -351,6 +390,7 @@
"Profiles or curves": "프로파일 또는 곡선",
"Profiles/Curves": "프로파일/곡선",
"Quantity": "수량",
"Quantity must be at least 2": "수량은 2 이상이어야 합니다",
"RECENT": "최근",
"REFERENCE": "참조",
"RULED SURFACE": "룰드 서피스",
@@ -363,6 +403,8 @@
"Recover unsaved design?": "저장되지 않은 디자인을 복구할까요?",
"Rectangular": "직사각형",
"Reference face": "참조 면",
"Relief Depth": "릴리프 깊이",
"Relief Width": "릴리프 너비",
"Remove Tools": "공구 제거",
"Remove condition": "조건 제거",
"Remove from Folder": "폴더에서 제거",
@@ -388,6 +430,7 @@
"Restore this studio's tools": "이 스튜디오의 도구 복원",
"Result": "결과",
"Retake screenshot": "스크린샷 다시 찍기",
"Reveal Height": "단차 높이",
"Reverse": "반전",
"Reverse Direction": "방향 반전",
"Revert": "되돌리기",
@@ -396,11 +439,14 @@
"Revert Position": "위치 복원",
"Review the report and screenshot before opening GitHub.": "GitHub를 열기 전에 보고서와 스크린샷을 검토하세요.",
"Review your report on GitHub and click Submit new issue to publish it.": "GitHub에서 보고서를 검토한 뒤 Submit new issue를 클릭해 게시하세요.",
"Revolute": "회전",
"Rib Length": "리브 길이",
"Rib Offset": "리브 오프셋",
"Rib Thickness": "리브 두께",
"Ribs": "리브",
"Rigid": "고정",
"Rim Edge": "테두리 모서리",
"Rim face": "테두리 면",
"Ring of tools on the right button": "오른쪽 버튼의 도구 링",
"Roll Back Here": "여기로 롤백",
"Roll History Marker Here": "여기로 히스토리 마커 이동",
@@ -421,15 +467,27 @@
"Search": "검색",
"Search commands": "명령 검색",
"Search this library": "이 라이브러리 검색",
"Second edge": "두 번째 모서리",
"Second plane": "두 번째 평면",
"Second point": "두 번째 점",
"Section": "단면",
"Section position": "단면 위치",
"Sections (one sketch each)": "단면 (각각 스케치 하나)",
"Select Other": "다른 항목 선택",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "다른 항목 선택: 모델 위에서 왼쪽 버튼을 가만히 누르고 있거나(또는 오른쪽 클릭 › 다른 항목 선택…) 커서 아래의 모든 항목을 나열합니다. 같은 위치를 다시 클릭하면 다음 항목이 선택됩니다. 가운데 버튼을 더블 클릭하면 홈으로 이동합니다(환경설정 › 탐색).",
"Select Same Look": "같은 외관 선택",
"Select bodies (a face picks its body)": "바디 선택(면을 클릭하면 해당 바디 선택)",
"Select bodies or faces instead": "대신 바디 또는 면을 선택하세요",
"Select edges": "모서리 선택",
"Select points of the sketch being edited": "편집 중인 스케치의 점을 선택하세요",
"Select the centre the pattern turns around first": "패턴이 회전할 중심을 먼저 선택하세요",
"Select the curves to offset first": "오프셋할 곡선을 먼저 선택하세요",
"Select the mirror line": "대칭선을 선택하세요",
"Select the sketch curves or points to mirror first": "대칭 복사할 스케치 곡선 또는 점을 먼저 선택하세요",
"Select the sketch curves or points to move first": "이동할 스케치 곡선 또는 점을 먼저 선택하세요",
"Select the sketch curves or points to pattern first": "패턴으로 만들 스케치 곡선 또는 점을 먼저 선택하세요",
"Select the sketch curves or points to scale first": "축척을 바꿀 스케치 곡선 또는 점을 먼저 선택하세요",
"Select the sketch curves or points to transform first": "변환할 스케치 곡선 또는 점을 먼저 선택하세요",
"Selection filter": "선택 필터",
"Semantic faces share their appearance across instances.": "시맨틱 면은 인스턴스 간에 외관을 공유합니다.",
"Send your report on GitHub": "GitHub에서 보고서 보내기",
@@ -448,8 +506,11 @@
"Sketch geometry and profiles": "스케치 기하 및 프로파일",
"Sketch plane has no body-face attachment.": "스케치 평면에 바디 면 부착이 없습니다.",
"Sketch points": "스케치 점",
"Slider": "슬라이더",
"Slot width": "슬롯 폭",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "이 디자인들이 저장되기 전에 SolidCraft가 종료되었습니다. 마지막 자동 저장본을 열 수 있습니다.",
"Spacing 2 must be a non-zero number": "간격 2는 0이 아닌 숫자여야 합니다",
"Spacing must be a non-zero number": "간격은 0이 아닌 숫자여야 합니다",
"Specialise": "특수화",
"Speed": "속도",
"Splitting tool": "분할 도구",
@@ -460,6 +521,7 @@
"Start angle": "시작 각도",
"Start bulge": "시작 벌지",
"Start continuity": "시작 연속성",
"Stationary Side": "고정 측",
"Step": "단계",
"Steps": "단계",
"Steps to reproduce (optional)": "재현 단계 (선택 사항)",
@@ -473,6 +535,7 @@
"Suppressed": "억제됨",
"Surface": "곡면",
"Surface, or faces to turn over": "곡면 또는 뒤집을 면",
"Surfaces": "곡면",
"Swap Ends": "양 끝 바꾸기",
"TRIM": "트림",
"Tangent (G1)": "접선 (G1)",
@@ -481,22 +544,32 @@
"Tap drill diameter": "탭 드릴 지름",
"Target": "대상",
"Target Body": "대상 바디",
"Target Face (optional)": "대상 면 (선택 사항)",
"Tear": "찢김",
"Technical details": "기술 세부 정보",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "점선 스케치는 저장된 평면 가이드입니다. 새 면을 선택하여 부착을 복구하세요.",
"The design changed. Reopen Change Part Size for the component.": "설계가 변경되었습니다. 구성요소의 '부품 크기 변경'을 다시 여세요.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "방향은 축이거나 스케치 평면 위에 있는 직선 스케치 곡선이어야 합니다",
"The mirror line cannot also be mirrored": "대칭선 자체를 대칭 복사할 수 없습니다",
"The mirror line must be a straight curve of this sketch, not an origin axis": "대칭선은 원점 축이 아니라 이 스케치의 직선이어야 합니다",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "저장된 작성자 인스턴스가 없습니다. 다시 연결하기 전에 올바른 작성자 배치를 선택하세요.",
"Then": "Then",
"These features will be deleted:": "다음 피처가 삭제됩니다:",
"These features will fail:": "다음 피처가 실패합니다:",
"Thickness Outside": "바깥쪽 두께",
"Thickness Variation": "두께 변화",
"Thin": "얇은 벽",
"Thin Extrude": "얇은 벽 돌출",
"Third plane": "세 번째 평면",
"Third point": "세 번째 점",
"This child is shared. Deleting it removes it from every copy of its parent.": "이 하위 항목은 공유됩니다. 삭제하면 상위 항목의 모든 복사본에서 제거됩니다.",
"This child is shared. Position changes apply to every copy of its parent.": "이 하위 항목은 공유됩니다. 위치 변경은 상위 항목의 모든 복사본에 적용됩니다.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "이 면은 안정적인 부착을 제공할 수 없습니다. 다른 면을 선택하거나 고정 평면을 명시적으로 사용하세요.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "이 이미지는 아직 GitHub에 첨부되지 않았습니다. 복사하거나 저장한 뒤 GitHub에서 첨부하세요.",
"Through point": "통과점",
"To": "끝",
"To Offset": "오프셋까지",
"To Snap": "대상 스냅",
"To edges": "끝 모서리",
"Tolerance": "공차",
"Too close": "너무 가까움",
@@ -506,6 +579,7 @@
"Trimming tool (plane, face or curves)": "트림 도구(평면, 면 또는 곡선)",
"Turn off section analysis before exporting the view.": "뷰를 내보내기 전에 단면 분석을 끄세요.",
"Type": "유형",
"Type a distance or an angle to move by": "이동할 거리 또는 각도를 입력하세요",
"UNTRIM": "트림 해제",
"Unit": "단위",
"Unsuppress": "비활성화 해제",
@@ -548,6 +622,17 @@
"Z angle": "Z 각도",
"Z distance": "Z 거리",
"Zebra": "제브라",
"`joint` must be an id or a name": "`joint`는 ID 또는 이름이어야 합니다",
"`params` must be an object": "`params`는 객체여야 합니다",
"`values` must be a list": "`values`는 목록이어야 합니다",
"a chamfer needs a corner of exactly two lines": "모따기에는 정확히 두 선으로 이루어진 코너가 필요합니다",
"a file operation is in progress": "파일 작업이 진행 중입니다",
"a picked curve is no longer in a sketch": "선택한 곡선이 더 이상 스케치에 없습니다",
"a picked curve's sketch has not been solved": "선택한 곡선의 스케치가 아직 풀리지 않았습니다",
"a picked edge has no points": "선택한 모서리에 점이 없습니다",
"a picked edge is gone": "선택한 모서리가 더 이상 없습니다",
"a picked edge's body is gone": "선택한 모서리의 바디가 더 이상 없습니다",
"add a key for a joint first": "먼저 관절의 키를 추가하세요",
"ai.prefs.availability": "어시스턴트 제어",
"ai.prefs.background_commands": "에이전트 명령을 백그라운드에서 실행",
"ai.prefs.follow_camera": "카메라를 스케치로 돌리기",
@@ -579,6 +664,7 @@
"appearance.pbr_opaque": "불투명 PBR",
"appearance.roughness": "거칠기",
"appearance.surface_response": "표면 반응",
"bom.group_children": "하위 부품을 상위 부품 행에 표시",
"browser.body_name": "바디{number}",
"browser.calibrate_title": "보정: {name}",
"browser.capture_many": "구성요소 {count}개가 이동되었지만 위치가 캡처되지 않았습니다.",
@@ -589,6 +675,8 @@
"browser.move_title": "이동: {name}",
"browser.parameters": "매개변수 ({count})",
"browser.precision": "정밀도: {precision}",
"browser.sketch_attachment_lost": "{name} (부착 해제됨)",
"browser.sketch_editing": "{name} (편집 중)",
"browser.sketch_name": "스케치{number}",
"browser.units": "단위: {units}",
"cam.flat": "평면",
@@ -598,7 +686,13 @@
"cam.roller": "롤러",
"cam.roller_pick": "롤러 (선택 사항)",
"cam.tip_pick": "끝점 (선택 사항)",
"choose a profile": "프로파일을 선택하세요",
"choose the cam's and the follower's joints": "캠과 종동절의 관절을 선택하세요",
"choose the joints to couple": "연결할 관절을 선택하세요",
"click a plane or planar face": "평면 또는 평평한 면 클릭",
"click sketch curves": "스케치 곡선 클릭",
"cmd.appearance_assign": "외관",
"cmd.appearance_chain": "외관 출처",
"cmd.appearance_library": "외관 라이브러리",
"cmd.appearance_list": "외관 목록",
"cmd.appearance_paint": "모양 칠하기",
@@ -950,6 +1044,9 @@
"cmd.timeline_roll_to": "이력 마커 이동",
"cmd.timeline_rollback": "타임라인 마커 이동",
"cmd.timeline_suppress": "특성 비활성화",
"cmd.view.render_browser": "렌더 브라우저",
"cmd.view.render_dock": "렌더 도크 이동",
"cmd.view.render_focus": "렌더 집중 보기",
"cmd.view_ambient_occlusion": "앰비언트 오클루전",
"cmd.view_apply": "이름 있는 보기 복원",
"cmd.view_delete": "이름 있는 보기 삭제",
@@ -1032,6 +1129,8 @@
"dxf.progress.write": "DXF 쓰는 중 (5/5)",
"dxf.tolerance": "곡선 허용 오차",
"dxf.tolerance_help": "표시된 바디와 스케치만 내보내며 곡선은 직선 구간으로 근사합니다. 허용 오차가 작을수록 곡선이 매끄러워지지만 처리 시간과 메모리 사용량이 늘어납니다.",
"each rail's curves must be in one sketch": "각 레일의 곡선은 하나의 스케치 안에 있어야 합니다",
"feature computation ended without a result": "특성 계산이 결과 없이 끝났습니다",
"file_load.built": "지금까지 빌드됨: 피처 {total}개 중 {built}개.",
"file_load.converting": "솔리드 변환 중 {done}/{total}",
"file_load.inserting": "기하 삽입 중",
@@ -1140,6 +1239,8 @@
"keymap.command_id": "명령 ID",
"keymap.empty": "일치하는 명령이 없습니다",
"keymap.use_anyway": "그래도 여기서 {key} 사용",
"label.move_to_left_side": "왼쪽으로 이동",
"label.move_to_right_side": "오른쪽으로 이동",
"manage.appearance_hint": "선택 항목의 외관을 선택하거나 견본을 바디 또는 면으로 끌어다 놓으세요.",
"manage.assign_hint": "바디를 선택하고 플라스틱 설계 규칙을 지정하세요.",
"manage.config_hint": "구성 행, 열 및 규칙을 편집한 다음 행을 활성화하거나 미리 보세요.",
@@ -1181,7 +1282,9 @@
"nav.free_orbit_upright.help": "마우스를 좌우로 드래그하면 모델이 월드의 수직 축을 중심으로 회전하고, 위아래로 드래그하면 제한 없이 극점을 넘어 기울어집니다.",
"nav.free_orbit_upright.label": "수직 축을 중심으로 회전",
"nav.fusion.help": "가운데 드래그는 이동, Shift+가운데 드래그는 회전, 오른쪽 드래그는 회전입니다",
"nav.hfss.help": "Alt+왼쪽 드래그는 이동, Shift+Alt+왼쪽 드래그는 확대/축소, 빈 공간에서 Ctrl+왼쪽 드래그는 회전입니다",
"nav.inventor.help": "가운데 드래그는 이동, Shift+가운데 드래그는 회전, Ctrl+가운데 드래그는 확대/축소, 오른쪽 드래그는 회전입니다",
"nav.maya.help": "Alt+왼쪽 드래그는 회전, Alt+가운데 드래그는 이동, Alt+오른쪽 드래그는 확대/축소입니다. 가운데 드래그로도 이동합니다",
"nav.openscad.help": "빈 공간에서 왼쪽 드래그는 회전, Shift+왼쪽 드래그는 상자 선택, 스케치 형상 드래그는 편집입니다. 오른쪽 또는 가운데 드래그는 이동, Shift+오른쪽 또는 Shift+가운데 드래그는 확대/축소입니다",
"nav.perspective.sketch": "스케치 편집 중에는 직교 뷰를 사용합니다. 원근 뷰를 전환하려면 스케치를 마치세요.",
"nav.solidworks.help": "가운데 드래그는 회전, Ctrl+가운데 드래그는 이동, Shift+가운데 드래그는 확대/축소, 오른쪽 드래그는 회전입니다",
@@ -1192,22 +1295,150 @@
"nav.touchpad.pan": "화면 이동 (Shift를 누르고 이동, 마우스 버튼 불필요)",
"nav.touchpad.scroll": "터치패드는 세로 스크롤로 확대/축소합니다. 두 손가락 이동 설정은 다른 프리셋을 위해 유지됩니다.",
"nav.touchpad.zoom": "확대/축소 (세로 스크롤 또는 핀치)",
"navbar.agent_chat": "어시스턴트 채팅 패널",
"navbar.agent_cursor": "에이전트 커서 표시",
"navbar.ambient_occlusion": "앰비언트 오클루전",
"navbar.assistant": "어시스턴트",
"navbar.custom.add_slot": "{slot} 추가",
"navbar.custom.always": "항상 표시",
"navbar.custom.available": "{available} · 막대로 끌어 놓거나 추가를 누르세요",
"navbar.custom.buttons": "버튼",
"navbar.custom.compact": "컴팩트",
"navbar.custom.count": "{count}/16칸",
"navbar.custom.customise": "탐색 막대 사용자 지정…",
"navbar.custom.design": "설계",
"navbar.custom.duplicate": "이 칸은 이미 막대에 있습니다.",
"navbar.custom.fade": "흐리게",
"navbar.custom.full": "다른 칸을 추가하려면 칸을 하나 제거하세요.",
"navbar.custom.hidden_design": "설계에서 숨김",
"navbar.custom.hidden_render": "렌더에서 숨김",
"navbar.custom.hide": "탐색 막대 숨기기",
"navbar.custom.hide_idle": "가리킬 때까지 숨김",
"navbar.custom.icon_only": "아이콘만",
"navbar.custom.icon_value": "아이콘과 값",
"navbar.custom.icons": "아이콘",
"navbar.custom.idle": "사용하지 않을 때",
"navbar.custom.intro": "3D 보기 아래쪽 막대에 둘 컨트롤과 순서를 고르세요. 칸을 끌어 옮기거나, 막대 밖으로 끌어 제거할 수 있습니다.",
"navbar.custom.labels": "아이콘과 레이블",
"navbar.custom.left": "왼쪽으로 이동",
"navbar.custom.position": "위치",
"navbar.custom.position_centre": "가운데",
"navbar.custom.position_left": "왼쪽",
"navbar.custom.position_right": "오른쪽",
"navbar.custom.preview_as": "미리 보기 모드",
"navbar.custom.regular": "보통",
"navbar.custom.remove": "제거",
"navbar.custom.remove_bar": "막대에서 제거",
"navbar.custom.render": "렌더",
"navbar.custom.reset": "탐색 막대 재설정",
"navbar.custom.reset_default": "기본값으로 재설정",
"navbar.custom.right": "오른쪽으로 이동",
"navbar.custom.select": "선택한 칸이 없습니다. 막대에서 칸을 선택하면 이동하거나 제거하거나 모양을 바꿀 수 있습니다.",
"navbar.custom.separators_full": "막대에 구분선이 이미 네 개 있습니다.",
"navbar.custom.show": "탐색 막대 표시",
"navbar.custom.shows": "표시 내용",
"navbar.custom.size": "크기",
"navbar.custom.stale": "막대가 바뀌었습니다. 칸을 다시 선택하세요.",
"navbar.custom.title": "탐색 막대",
"navbar.custom.unknown": "이 칸은 사용할 수 없습니다.",
"navbar.description.ambient_occlusion": "주름과 모서리를 어둡게 하여 깊이를 더합니다.",
"navbar.description.display": "보기 설정을 담고 있습니다: 그래픽 프리셋, 격자, 바닥 그림자, 앰비언트 오클루전, 투영.",
"navbar.description.fit": "선택 항목을, 선택이 없으면 모델 전체를 화면에 맞춥니다.",
"navbar.description.grid": "바닥 격자를 표시하거나 숨깁니다.",
"navbar.description.ground_shadow": "모델 아래 그림자를 표시하거나 숨깁니다.",
"navbar.description.home": "모델 전체의 등각 보기로 돌아갑니다.",
"navbar.description.look_at": "선택한 면, 평면 또는 열린 스케치를 정면으로 바라보게 보기를 돌립니다.",
"navbar.description.orbit": "모델을 중심으로 보기를 회전합니다.",
"navbar.description.pan": "보기를 옆으로, 위나 아래로 이동합니다.",
"navbar.description.projection": "직교 투영과 원근 투영을 전환합니다.",
"navbar.description.separator": "이웃한 칸을 묶는 가는 선입니다.",
"navbar.description.spin": "클릭하거나 키를 누를 때까지 보기를 계속 회전합니다.",
"navbar.description.visual_style": "모델을 그리는 방식을 바꿉니다: 음영, 와이어프레임 또는 숨은 모서리 포함.",
"navbar.description.zoom": "보기를 모델에 더 가까이 또는 더 멀리 옮깁니다.",
"navbar.display": "표시",
"navbar.fit": "맞춤",
"navbar.graphics": "그래픽",
"navbar.grid": "격자",
"navbar.ground_shadow": "바닥 그림자",
"navbar.home": "홈",
"navbar.later": "나중에",
"navbar.look_at": "바라보기",
"navbar.more": "더 보기",
"navbar.orbit": "회전",
"navbar.orthographic": "직교 투영",
"navbar.pan": "이동",
"navbar.perspective": "원근 투영",
"navbar.preset": "프리셋",
"navbar.projection": "투영",
"navbar.projection_heading": "투영",
"navbar.separator": "구분선",
"navbar.show": "표시",
"navbar.spin": "연속 회전",
"navbar.style.shaded": "음영 처리",
"navbar.style.shaded_with_edges": "모서리 포함 음영",
"navbar.style.shaded_with_hidden_edges": "숨은 모서리 포함 음영",
"navbar.style.wireframe": "와이어프레임",
"navbar.translucent": "반투명",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "시각 스타일",
"navbar.zoom": "확대/축소",
"needs two joints": "조인트 두 개가 필요함",
"new configuration": "새 구성",
"new parameter": "new parameter",
"no hole": "구멍 없음",
"no interference": "간섭 없음",
"no joint that moves yet": "아직 움직이는 조인트 없음",
"no motion study yet": "아직 운동 연구가 없습니다",
"no picture": "이미지 없음",
"no such joint": "해당 관절이 없습니다",
"none": "없음",
"not a move": "이동이 아닙니다",
"not a number": "숫자가 아닙니다",
"open a sketch first": "먼저 스케치를 여세요",
"parts.automatic_name": "자동",
"parts.dimension.across_flats": "대변 거리",
"parts.dimension.bore": "내경",
"parts.dimension.d": "호칭 지름",
"parts.dimension.head_diameter": "머리 지름",
"parts.dimension.head_height": "머리 높이",
"parts.dimension.height": "높이",
"parts.dimension.inner": "내경",
"parts.dimension.outer": "외경",
"parts.dimension.pitch": "피치",
"parts.dimension.socket": "육각 구멍 크기",
"parts.dimension.socket_depth": "육각 구멍 깊이",
"parts.dimension.thickness": "두께",
"parts.dimension.width": "너비",
"parts.family.bearing": "깊은 홈 볼 베어링 (외형)",
"parts.family.dowel_pin": "평행 핀",
"parts.family.hex_bolt": "육각 볼트",
"parts.family.hex_nut": "육각 너트",
"parts.family.set_screw": "육각 구멍붙이 멈춤나사, 평형 끝",
"parts.family.socket_head_cap_screw": "육각 구멍붙이 볼트",
"parts.family.washer": "평와셔",
"pattern.alignment_2": "정렬 2",
"pattern.alignment_hint": "개수에는 원본이 포함됩니다. 가운데 정렬은 복사본을 양쪽에 배치하며, 개수가 짝수이면 방향 반전으로 복사본이 하나 더 배치되는 쪽을 선택합니다.",
"pattern.direction_1": "방향 1",
"pattern.direction_2": "방향 2",
"pattern.flip_direction": "방향 반전",
"pick a body or some of its faces": "바디 또는 바디의 면을 선택하세요",
"pick a hole to seat it, or OK places it at the origin": "안착시킬 구멍을 선택하거나, 확인을 누르면 원점에 배치됩니다",
"pick a planar face": "평평한 면을 선택하세요",
"pick a plane or a face as the tool": "도구로 사용할 평면 또는 면을 선택하세요",
"pick a size": "크기를 선택하세요",
"pick edges of a body": "바디의 모서리를 선택하세요",
"pick edges of one body": "하나의 바디의 모서리를 선택하세요",
"pick edges of the holes to remove": "제거할 구멍의 모서리를 선택하세요",
"pick faces of one body": "하나의 바디의 면을 선택하세요",
"pick faces to offset": "오프셋할 면을 선택하세요",
"pick lines of one sketch": "하나의 스케치의 선을 선택하세요",
"pick one or two vertices, edges or faces": "꼭짓점, 모서리 또는 면을 하나나 두 개 선택하세요",
"pick one plane or face as the tool, or sketch curves": "도구로 사용할 평면 또는 면 하나, 또는 스케치 곡선을 선택하세요",
"pick sections in two or more sketches": "둘 이상의 스케치에 있는 단면을 선택하세요",
"pick sketch curves or edges": "스케치 곡선 또는 모서리를 선택하세요",
"pick the face to untrim": "트림을 해제할 면을 선택하세요",
"pick what to keep": "남길 부분을 선택하세요",
"pick what to keep of the other surface": "다른 곡면에서 남길 부분을 선택하세요",
"prefs.add_item": "항목 추가",
"prefs.alt_frees_manipulators": "Alt / Option 키로 조작 화살표도 자유롭게 움직입니다",
"prefs.anti_aliasing_note": "울퉁불퉁한 모서리를 부드럽게 합니다.",
@@ -1384,11 +1615,70 @@
"render.cpu_budget_studio": "스튜디오 (큰 이미지)",
"render.cpu_budget_triangles": "삼각형 수 상한",
"render.cpu_budget_workstation": "워크스테이션 (대규모 장면)",
"render.emitted_axis": "방출 축",
"render.error_area_samples": "area_samples는 1, 4, 16 또는 64여야 함",
"render.error_binding_allocation": "재질 연결을 할당할 수 없음",
"render.error_body_bound": "제품 미리 보기가 캡처된 바디 한도를 초과함",
"render.error_checkpoint_dimensions": "체크포인트 크기가 캡처된 요청과 다름",
"render.error_decode_budget": "이미지 디코딩 한도 초과",
"render.error_denoise_setting": "기본 노이즈 제거 설정이 잘못됨",
"render.error_display_dimensions": "이미지 표시 크기가 잘못됨",
"render.error_display_fit": "이미지 표시가 이 장치에 맞지 않음",
"render.error_display_height": "표시 높이 초과",
"render.error_display_width": "표시 너비 초과",
"render.error_duplicate_face": "제품 면 모양이 중복됨",
"render.error_export_document": "대상 위치를 선택하는 동안 렌더 내보내기 문서가 변경됨",
"render.error_face_cap": "제품 미리 보기가 면 모양 허용 한도를 초과함",
"render.error_finish_gesture": "미리 보기 전에 모델링 동작을 완료하세요",
"render.error_finish_operation": "렌더로 전환하기 전에 현재 모델링 작업을 완료하세요",
"render.error_fixed_preview": "고정 스튜디오 미리 보기에는 노출 0, 환경 회전 0, 강도 1이 필요함",
"render.error_geometry_size": "제품 형상 크기 초과",
"render.error_glass_recipe": "알 수 없는 유리 레시피",
"render.error_gpu_preview": "이 호스트에서는 GPU 제품 미리 보기를 사용할 수 없습니다. 저장된 설정은 계속 사용할 수 있습니다.",
"render.error_gpu_samples": "지원하지 않는 GPU 샘플 수",
"render.error_image_dimensions": "렌더 이미지 크기가 작업과 일치하지 않음",
"render.error_image_profile": "렌더 이미지가 캡처된 리소스 한도를 초과함",
"render.error_interactive_command": "연결되지 않은 대화형 렌더 명령",
"render.error_job_action": "대화형 이미지 작업 동작이 아님",
"render.error_job_identity": "렌더 작업 식별자가 잘못됨: {error}",
"render.error_library_reply": "렌더 라이브러리 응답이 잘못됨",
"render.error_material_binding": "재질 연결이 없음",
"render.error_no_completed_image": "완료된 렌더 이미지가 없음",
"render.error_no_geometry": "제품 형상 없음",
"render.error_no_scene": "제품 장면 없음",
"render.error_opacity": "제품 모양 불투명도가 잘못됨",
"render.error_pbr_opacity": "불투명 PBR에는 불투명도 1이 필요함",
"render.error_physical_glass": "선택한 레시피가 물리 유리가 아님",
"render.error_preview_device": "제품 미리 보기에는 깊이 버퍼가 있는 장치가 필요함",
"render.error_product_triangle": "제품 삼각형이 잘못됨",
"render.error_provisional_identity": "임시 렌더 식별자 또는 샘플 수가 잘못됨",
"render.error_quality_bounds": "품질 투영이 기본 한도를 초과함",
"render.error_quality_method": "품질 투영에는 동일한 명시적 GPU 방식이 필요함",
"render.error_quality_projection": "기본 품질 투영이 잘못됨",
"render.error_regrade_identity": "재보정 식별자가 잘못됨: {error}",
"render.error_scene_bodies": "렌더 장면 바디가 없음",
"render.error_scene_body_limit": "렌더 장면이 바디 한도를 초과함",
"render.error_scene_identity": "렌더 장면 식별자가 잘못됨",
"render.error_setup_panicked": "GPU 경로 추적기 초기화 오류",
"render.error_setup_stopped": "초기화 작업이 호스트를 반환하지 않고 중지됨",
"render.error_setup_worker": "초기화 작업을 시작할 수 없음: {error}",
"render.error_source_preview": "원본 미리 보기가 바이트 한도를 초과함",
"render.error_surface_normals": "PBR에는 0이 아닌 표면 법선이 필요함",
"render.error_surface_reply": "작성된 표면 응답이 잘못됨",
"render.error_triangle_bound": "제품 미리 보기가 원본 삼각형 800만 개 한도를 초과함",
"render.error_triangle_count": "제품 삼각형 수 초과",
"render.error_upload_slot": "제품 미리 보기 업로드 슬롯을 사용할 수 없음",
"render.error_vertex_allocation": "제품 미리 보기 꼭짓점 메모리 할당 실패",
"render.error_vertex_envelope": "제품 미리 보기가 {limit} MiB 꼭짓점 데이터 한도를 초과함. 형상은 단순화되지 않음",
"render.error_vertex_packing": "제품 미리 보기 패킹이 허용된 꼭짓점 데이터와 다름",
"render.error_visible_solid": "여기서 미리 보려면 디자인에서 보이는 솔리드를 만드세요.",
"render.exit_focus": "집중 보기 종료",
"render.export_image_label": "이미지 내보내기",
"render.exr_pending": "GPU는 원본 선형 EXR을 보존할 수 있습니다. 압축, 다중 레이어 이미지 및 보조 렌더 패스는 아직 사용할 수 없습니다.",
"render.fit": "제품에 맞추기",
"render.fixed_camera": "카메라",
"render.fixed_world": "월드",
"render.fold_browser": "브라우저 접기",
"render.heading_batch": "일괄 처리",
"render.heading_frame": "프레임",
"render.heading_lens": "렌즈",
@@ -1418,7 +1708,9 @@
"render.image_use_largest": "이 비율에서 가장 큰 크기 사용:",
"render.image_width": "너비",
"render.include_rig_cards": "Include passive cards and flags",
"render.inner_half_angle": "내부 반각",
"render.inspector": "속성 검사기",
"render.layer_off_suffix": " (꺼짐)",
"render.library_applied": "리소스 변환을 적용했습니다. 시작 전에 전체 렌더 요청을 확인하세요.",
"render.library_apply_hdr": "이 HDR 환경과 함께 저장",
"render.library_apply_maps": "제작된 GPU 표면 맵 사용",
@@ -1464,6 +1756,7 @@
"render.navigation_help": "카메라는 디자인에서와 같이 움직입니다(환경설정 › 탐색). 설정 저장은 현재 카메라를 기록합니다.",
"render.opaque_image_summary": "미리보기 PNG · 불투명 PBR · 블렌딩 투명도",
"render.opaque_preview_help": "불투명 PBR 및 단색 표시, 블렌딩 투명도를 지원합니다. 굴절, HDRI 및 최종 렌더링은 아직 지원하지 않습니다.",
"render.outer_half_angle": "외부 반각",
"render.output_format_status": "PNG는 완료된 표시 이미지 그대로입니다. 선택적 GPU EXR은 표시 필터 전 선형 FLOAT32 방사 휘도를 보존합니다. 미리보기 캐시나 다른 작업으로 바꾸어 내보내지 않습니다.",
"render.output_tools_inspector": "출력 검사기에서 크기와 형식을 편집하세요.",
"render.paint_label": "칠하기",
@@ -1479,18 +1772,28 @@
"render.physical_prepare_plan": "Prepare creation plan (does not apply)",
"render.physical_separate": "Appearance is not material identification. These are sourced references, not certified effective properties. Existing mass, engineering materials and optics are unchanged.",
"render.physical_unknown": "No numerical candidate is established. Grade, formulation or construction must be specified; unknown is not zero.",
"render.pick_body": "바디",
"render.pick_component": "구성요소",
"render.pick_face": "면",
"render.pick_help": "바디, 면 또는 구성요소를 선택합니다. 빈 공간을 클릭하면 선택이 해제되고 Shift 또는 Ctrl로 추가하거나 전환합니다. 강조 표시는 실시간 제품 뷰에만 나타납니다.",
"render.pick_label": "선택",
"render.pick_up_label": "가져오기",
"render.pick_waiting": "제품 선택은 아직 지원되지 않습니다.",
"render.preview": "통합 미리보기",
"render.preview_help": "래스터 셰이딩과 블렌딩 투명도를 사용합니다. 굴절, HDRI 및 최종 렌더링은 아직 지원하지 않습니다.",
"render.preview_lighting_help": "실시간 미리 보기에는 직접 조명만 표시되며 그림자는 표시되지 않습니다.",
"render.property_conditions": "조건: {value}",
"render.property_fallback": "속성",
"render.property_qualifier": "한정 조건: {value}",
"render.property_source": "출처: {id} - {locator}",
"render.property_uncertainty": "불확도: {value}",
"render.property_unknown": "알 수 없음",
"render.regrade_label": "색상 재조정",
"render.reload_settings": "저장된 설정 다시 불러오기",
"render.replace_label": "바꾸기",
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.restore_camera": "저장된 카메라 복원",
"render.result_actual_size": "100%",
"render.result_reduced_display": "표시 미리보기를 뷰포트 장치 또는 캐시 제한에 맞춰 축소했습니다. 보관된 PNG와 내보내기는 전체 해상도를 유지합니다. 이 축소 보기에서는 원본 100% 검사가 불가능합니다.",
"render.return_design": "설계로 돌아가기",
"render.ribbon_backgrounds": "배경",
@@ -1525,6 +1828,10 @@
"render.shell_tab_camera": "카메라",
"render.shell_tab_scene": "장면",
"render.show_shots_label": "샷 스트립 표시",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "풀 HD",
"render.size_hd": "HD",
"render.spot_cone": "스폿 원뿔",
"render.stage_frame": "구도",
"render.stage_light": "조명",
"render.stage_look": "외관",
@@ -1533,6 +1840,42 @@
"render.stage_panel_count": "Saved panels",
"render.stage_preview_note": "통합 미리 보기 · 직접광",
"render.strip_label": "스트립",
"render.tone_aces_fitted": "ACES 근사",
"render.tone_reinhard": "Reinhard",
"render.tree_add_light": "조명 추가",
"render.tree_add_shot": "샷 추가",
"render.tree_browser": "렌더 브라우저",
"render.tree_by_look": "외관별",
"render.tree_by_object": "객체별",
"render.tree_constant": "일정한 환경광",
"render.tree_default": "기본",
"render.tree_directional": "방향광",
"render.tree_environment": "환경",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "면 {count}개",
"render.tree_face_one": "면 {count}개",
"render.tree_fixed_studio": "고정 스튜디오",
"render.tree_hdr": "HDR",
"render.tree_lights": "조명",
"render.tree_lights_pending": "이름이 지정된 조명 명령은 아직 사용할 수 없습니다.",
"render.tree_mixed": "혼합",
"render.tree_more": "{count}개 더",
"render.tree_mute": "조명 끄기",
"render.tree_no_environment": "환경 없음",
"render.tree_objects": "객체",
"render.tree_output": "출력",
"render.tree_point": "점광원",
"render.tree_rectangle": "사각형",
"render.tree_search": "객체 검색",
"render.tree_selection": "렌더 선택",
"render.tree_shots": "샷",
"render.tree_sky": "하늘",
"render.tree_solo": "조명 단독 표시",
"render.tree_spot": "스포트",
"render.tree_sun": "태양",
"render.tree_switch": "전환",
"render.tree_user_one": "객체 {count}개",
"render.tree_users": "객체 {count}개",
"render.unavailable_preview": "이 설정은 사용할 수 없는 미리보기 프로필을 요청합니다.",
"render.unsaved": "저장하지 않은 미리보기 변경 사항",
"render.use_preview": "통합 미리보기 사용",
@@ -1567,6 +1910,26 @@
"search.suggest": "{label}을(를) 찾으셨나요?",
"search.try": "명령 이름, 이 디자인의 피처 또는 매개변수를 입력하세요. 값과 함께 명령을 실행하려면 명령 ID와 JSON 객체를 입력하세요: {example}",
"search.valid": "올바름",
"select a direction (an axis, a sketch line or a straight edge) first": "방향(축, 스케치 선 또는 직선 모서리)을 먼저 선택하세요",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "프로파일이 따라갈 방향(축, 스케치 선 또는 직선 모서리)을 선택하세요",
"select a point on a component": "구성요소 위의 점을 선택하세요",
"select a profile, edges or sketch lines first": "프로파일, 모서리 또는 스케치 선을 먼저 선택하세요",
"select an axis": "축을 선택하세요",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "축, 직선 또는 원형 모서리, 또는 원기둥·원뿔·토러스 면을 먼저 선택하세요",
"select bodies first": "바디를 먼저 선택하세요",
"select corner points, or the two lines of one corner": "코너 점, 또는 하나의 코너를 이루는 두 선을 선택하세요",
"select one corner point, or the two lines of one corner": "코너 점 하나, 또는 하나의 코너를 이루는 두 선을 선택하세요",
"select sheet edges first": "판금 모서리를 먼저 선택하세요",
"select the bend line (a sketch line) first": "벤딩 선(스케치 선)을 먼저 선택하세요",
"select the cam's profile (a sketch profile or the cam's edges)": "캠의 프로파일(스케치 프로파일 또는 캠의 모서리)을 선택하세요",
"select the corner to cut first": "잘라낼 코너를 먼저 선택하세요",
"select the corners to round first": "둥글게 만들 코너를 먼저 선택하세요",
"select the fixed face first (a plate's large face)": "고정 면(플레이트의 큰 면)을 먼저 선택하세요",
"select the frame sketch's lines first": "프레임 스케치의 선을 먼저 선택하세요",
"select the path (sketch lines across the edge)": "경로(모서리를 가로지르는 스케치 선)를 선택하세요",
"select the rim face first": "테두리 면을 먼저 선택하세요",
"select the sheet edge first": "판금 모서리를 먼저 선택하세요",
"select two components": "구성요소 두 개를 선택하세요",
"settings.display_quality_note": "세밀할수록 곡면과 모서리가 더 매끄럽게 표시되지만 메시 생성 시간이 늘어납니다. 뷰포트만 바뀌며 설계나 내보내기는 바뀌지 않습니다.",
"settings.frame_rate_note": "뷰의 오른쪽 아래에 초당 프레임 수를 표시합니다.",
"settings.measure_axis_distances": "X/Y/Z 거리 표시",
@@ -1579,16 +1942,22 @@
"settings.reset_intro": "다음 설정은 이 컴퓨터에서 작동하지 않아 SolidCraft를 시작할 수 없게 하므로 변경되었습니다:",
"settings.reset_title": "설정이 변경되었습니다",
"settings.supersampling_note": "뷰를 더 높은 해상도로 그린 뒤 축소합니다. 4K 미만 화면에서 모서리, 선, 그리드가 더 매끄러워집니다. GPU 시간이 듭니다: 1.5×에서 약 2.25배, 2×에서 4배의 픽셀.",
"sheet.flange_type_base": "베이스",
"sheet.flange_type_contour": "윤곽",
"sheet.flange_type_edge": "모서리",
"shortcut.json_error": "매개변수는 JSON 형식이어야 합니다: {error}",
"shortcut.no_command": "`{id}` 명령이 없습니다. JSON 앞의 텍스트는 명령 ID여야 합니다",
"shortcut.pin": "S 상자 맨 위에 고정",
"shortcut.unpin": "고정 해제",
"sketch is missing": "스케치가 없습니다",
"sketch.degrees_of_freedom": "자유도 {count}개",
"sketch.dof_left": "남은 자유도 {count}개",
"sketch.dof_left_one": "남은 자유도 {count}개",
"sketch.draw_curves": "{linetype}(으)로 그리기",
"sketch.make_selection": "선택 항목을 {linetype}(으)로 변경",
"sketch.open_ends": "열림 {count}",
"sketch.status_conflict": "구속 조건 충돌",
"sketch.status_fully_constrained": "완전 구속",
"sketch.untied_ends": "미연결 {count}",
"sketch_panel.attached": "부착 대상: {body} / {path}",
"sketch_panel.author": "작성 배치: {path}",
@@ -1610,7 +1979,24 @@
"sketch_text.path_hint": "텍스트가 따라갈 스케치 곡선: 여기를 클릭한 다음 곡선을 클릭",
"sketch_text.use_font_file": "글꼴 파일 {path} 사용",
"solid": "솔리드",
"the angle must be a number": "각도는 숫자여야 합니다",
"the curves must be in one sketch": "곡선은 하나의 스케치 안에 있어야 합니다",
"the direction must be an axis, a sketch line or a straight edge": "방향은 축, 스케치 선 또는 직선 모서리여야 합니다",
"the duration must be a number of seconds, 0.001 or more": "지속 시간은 0.001초 이상의 초 단위 숫자여야 합니다",
"the line's sketch is gone": "선이 속한 스케치가 더 이상 없습니다",
"the lines must be in one sketch": "선은 하나의 스케치 안에 있어야 합니다",
"the lines must be in one sketch, not the section's": "선은 단면의 스케치가 아닌 하나의 스케치 안에 있어야 합니다",
"the parts library is empty": "부품 라이브러리가 비어 있습니다",
"the parts library is not available": "부품 라이브러리를 사용할 수 없습니다",
"the path curves must be in one other sketch": "경로 곡선은 다른 하나의 스케치 안에 있어야 합니다",
"the path's sketch is gone": "경로의 스케치가 더 이상 없습니다",
"the position must be a number": "위치는 숫자여야 합니다",
"the preview failed": "미리보기에 실패했습니다",
"the profiles and curves must be in one sketch": "프로파일과 곡선은 하나의 스케치 안에 있어야 합니다",
"the reference face must be on the edges' body": "참조 면은 모서리가 속한 바디에 있어야 합니다",
"the scale must be above 0": "축척은 0보다 커야 합니다",
"the section's profiles must be in one sketch": "단면의 프로파일은 하나의 스케치 안에 있어야 합니다",
"the two origins are on the same component": "두 원점이 같은 구성요소에 있습니다",
"thread.automatic_size": "자동 크기",
"thread.designation": "호칭",
"thread.iso_metric": "ISO 미터",
@@ -1639,6 +2025,7 @@
"trace.points": "경로를 따라 {count}개 점",
"trace.stopped_by_contact": "샘플 {sample}에서 끝남: {a}이(가) {b}을(를) 통과합니다",
"trace.stopped_by_loop": "샘플 {sample}에서 끝남: {joint}을(를) 지나는 루프를 더 이상 닫을 수 없습니다",
"trim by sketch curves, or by one plane or face": "스케치 곡선 또는 평면이나 면 하나로 트림하세요",
"ui.1_degree_of_freedom": "자유도 1개",
"ui.3d_mouse_axes_reassigned": "축이 환경설정에서 다시 지정되어 있으며, 이 보정 후에도 적용됩니다.",
"ui.3d_mouse_button": "버튼 {number}",
@@ -2065,6 +2452,8 @@
"ui.design_properties.revision": "리비전",
"ui.diameter": "지름",
"ui.dimension": "치수",
"ui.direct_interaction": "직접 조작",
"ui.direct_interaction_note": "뷰포트에서 모델을 직접 다룹니다. 평평한 면이나 프로파일을 누르고 끌면 위로는 돌출, 바디 안쪽 아래로는 잘라내기이며, 옆으로 움직이면 단계 크기를 정합니다",
"ui.direction": "방향",
"ui.display_quality": "표시 품질",
"ui.display_quality_coarse": "거침",
@@ -2088,6 +2477,7 @@
"ui.editJointLimits": "조인트 제한 편집",
"ui.edit_section_analysis": "단면 분석 편집",
"ui.ellipse": "타원",
"ui.emboss_wrap_note": "지원되는 원통에 접하는 직교 선 프로파일은 자동으로 감깁니다. 대상을 고르려면 벽을 선택하세요.",
"ui.end_radius": "끝 반지름",
"ui.end_scale": "끝 배율",
"ui.entities": "요소",
@@ -2153,6 +2543,7 @@
"ui.heading_extrude": "돌출",
"ui.heading_fillet": "필렛",
"ui.heading_finish_sketch": "스케치 종료",
"ui.heading_form": "폼",
"ui.heading_front": "정면",
"ui.heading_hole": "구멍",
"ui.heading_home": "홈",
@@ -2201,6 +2592,7 @@
"ui.heading_utilities": "유틸리티",
"ui.heading_utility": "유틸리티",
"ui.heading_weldments": "용접 구조물",
"ui.height": "높이",
"ui.help": "도움말",
"ui.hide": "숨기기",
"ui.hideAxes": "축 숨기기",
@@ -2234,11 +2626,14 @@
"ui.intersect": "교차",
"ui.isolate": "분리 표시",
"ui.join": "접합",
"ui.joint_play": "▶ 재생",
"ui.joint_stop": "■ 정지",
"ui.joints": "조인트",
"ui.keyboard_shortcuts": "키보드 단축키",
"ui.language": "언어",
"ui.layout_compact": "컴팩트",
"ui.layout_floating": "플로팅",
"ui.length": "길이",
"ui.length_decimals": "길이 소수점 자릿수",
"ui.light": "밝게",
"ui.line": "선",
@@ -2246,6 +2641,7 @@
"ui.loft": "로프트",
"ui.look_at": "바라보기",
"ui.look_at_anim_desc": "축 뷰, 보기, 홈 및 맞춤",
"ui.major_radius": "큰 반지름",
"ui.manipulator_free_alt": "Alt/Option으로도 매니퓰레이터 자유 드래그",
"ui.manipulator_free_alt_tip": "켬: 돌출 / 기즈모 화살표에서 Alt/Option 또는 Ctrl/Cmd를 누르면 값 스냅이 해제됩니다. 끔: Ctrl/Cmd만 해당.",
"ui.manufacture": "제조",
@@ -2275,8 +2671,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "면 태그가 있는 3MF",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "작은 반지름",
"ui.mirror": "대칭 복사",
"ui.mirror_line": "대칭선",
"ui.modifiers_either": "{first} 또는 {second}",
"ui.move": "이동",
"ui.multiple": "다중",
"ui.named_views": "명명된 뷰",
@@ -2323,6 +2721,7 @@
"ui.pinToShortcuts": "바로 가기에 고정",
"ui.pinToToolbar": "도구 모음에 고정",
"ui.pipe": "파이프",
"ui.pitch": "피치",
"ui.placement": "배치",
"ui.plane": "평면",
"ui.plane_at_angle": "각도 평면",
@@ -2377,6 +2776,7 @@
"ui.reverse_horizontal_pan_direction": "수평 이동 방향 반전",
"ui.reverse_horizontal_pan_tip": "두 손가락 수평 스크롤과 엄지 휠이 반대 방향으로 이동합니다",
"ui.reverse_zoom_direction": "확대/축소 방향 반전",
"ui.revolutions": "권수",
"ui.revolve": "회전",
"ui.ribbon_exit": "종료",
"ui.ribbon_labels": "리본 아이콘 아래에 텍스트 표시",
@@ -2392,6 +2792,7 @@
"ui.scale": "축척",
"ui.second_rail": "두 번째 레일",
"ui.section_analysis": "단면 분석",
"ui.section_size": "단면 크기",
"ui.select": "선택",
"ui.selectOther": "기타 선택…",
"ui.selectTangentChain": "접선 체인 선택",
@@ -2448,6 +2849,7 @@
"ui.start": "시작",
"ui.start_over": "처음부터 다시",
"ui.start_page": "시작 페이지",
"ui.stitch_tolerance_hint": "엄격",
"ui.stretch": "늘이기",
"ui.supersampling": "슈퍼샘플링 (SSAA)",
"ui.supersampling_adaptive": "뷰가 멈춰 있을 때만",
@@ -2478,6 +2880,8 @@
"ui.to_object": "객체까지",
"ui.tool_direction": "공구 방향",
"ui.top": "상면",
"ui.top_diameter": "윗면 지름",
"ui.top_radius": "윗면 반지름",
"ui.torus": "토러스",
"ui.total_angle": "전진 각도",
"ui.trackpad_pan_tip": "두 손가락 스크롤로 화면을 이동합니다. Fusion에서는 Shift + 두 손가락 스크롤로 회전합니다. 끄면 스크롤로 확대/축소합니다. 마우스 휠과 핀치는 확대/축소하고, 엄지 휠은 좌우로 이동합니다.",
@@ -2504,6 +2908,7 @@
"ui.visual_shaded_with_edges": "음영 처리 및 모서리",
"ui.visual_style": "시각 스타일",
"ui.visual_wireframe": "와이어프레임",
"ui.width": "너비",
"ui.workspace": "작업 공간",
"ui.workspace_animation_description": "분해도, 모션 스터디 및 스토리보드",
"ui.workspace_available": "사용 가능",
@@ -2560,5 +2965,8 @@
"update.up_to_date": "SolidCraft가 최신 버전입니다.",
"update.update_now": "지금 업데이트",
"update.you_have": "현재 버전은 {version}입니다.",
"use a positive nominal diameter and a pitch smaller than it": "양수인 호칭 지름과 그보다 작은 피치를 사용하세요",
"values must be finite numbers": "값은 유한한 숫자여야 합니다",
"values must be numbers or expressions": "값은 숫자 또는 식이어야 합니다",
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ 선택 · Enter / Tab 완성 · Esc 닫기"
}
+895 -1
View File
File diff suppressed because it is too large Load Diff
+705 -1
View File
File diff suppressed because it is too large Load Diff
+949 -1
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -1057,6 +1057,11 @@
"no picture": "brak obrazu",
"none": "brak",
"parts.automatic_name": "automatycznie",
"parts.dimension.d": "Średnica nominalna",
"parts.dimension.height": "Wysokość",
"parts.dimension.pitch": "Skok",
"parts.dimension.thickness": "Grubość",
"parts.dimension.width": "Szerokość",
"pattern.alignment_2": "Wyrównanie 2",
"pattern.alignment_hint": "Liczba obejmuje oryginał. Wyśrodkuj rozkłada kopie po obu stronach; Odwróć wybiera stronę z dodatkową kopią przy parzystej liczbie.",
"pattern.direction_1": "Kierunek 1",
@@ -1893,6 +1898,7 @@
"ui.heading_utilities": "NARZĘDZIA",
"ui.heading_utility": "NARZĘDZIE",
"ui.heading_weldments": "SPAWANIE",
"ui.height": "Wysokość",
"ui.help": "Pomoc",
"ui.hide": "Ukryj",
"ui.hideAxes": "Ukryj osie",
@@ -1931,6 +1937,7 @@
"ui.language": "Język",
"ui.layout_compact": "Kompaktowy",
"ui.layout_floating": "Pływający",
"ui.length": "Długość",
"ui.length_decimals": "Miejsca dziesiętne długości",
"ui.light": "Jasny",
"ui.line": "Linia",
@@ -2019,6 +2026,7 @@
"ui.pinToShortcuts": "Przypnij do skrótów",
"ui.pinToToolbar": "Przypnij do paska narzędzi",
"ui.pipe": "Rura",
"ui.pitch": "Skok",
"ui.placement": "Umiejscowienie",
"ui.placement_handles": "Uchwyty umieszczania",
"ui.placement_handles_tip": "Uchwyty na podglądzie podparcia, występu lub zatrzasku: przeciągnij znacznik, aby przesunąć element po modelu, obróć go pierścieniem",
@@ -2194,6 +2202,7 @@
"ui.visual_shaded_with_edges": "Cieniowany z krawędziami",
"ui.visual_style": "Styl wizualny",
"ui.visual_wireframe": "Model krawędziowy",
"ui.width": "Szerokość",
"ui.workspace": "środowisko pracy",
"ui.workspace_animation_description": "Widoki rozstrzelone, badania ruchu i scenorysy",
"ui.workspace_available": "Dostępne",
+11
View File
@@ -1159,7 +1159,9 @@
"nav.free_orbit.label": "Órbita livre",
"nav.free_orbit.snap_help": "Mouse e mouse 3D giram através dos dois polos e preservam a rotação da imagem. Mantenha Shift pressionado durante uma órbita por arraste para alinhar a direção da vista e a rotação da imagem.",
"nav.fusion.help": "Arrastar com o meio desloca, Shift+meio orbita, arrastar com o direito orbita",
"nav.hfss.help": "Alt+arrastar com o esquerdo desloca, Shift+Alt+esquerdo aplica zoom, Ctrl+arrastar com o esquerdo em área vazia orbita",
"nav.inventor.help": "Arrastar com o meio desloca, Shift+meio orbita, Ctrl+meio aplica zoom, arrastar com o direito orbita",
"nav.maya.help": "Alt+arrastar com o esquerdo orbita, Alt+meio desloca, Alt+direito aplica zoom; arrastar com o meio também desloca",
"nav.openscad.help": "Arrastar com o esquerdo no espaço vazio orbita, Shift+arrastar com o esquerdo seleciona por caixa, arrastar a geometria do esboço a edita; arrastar com o direito ou o meio desloca, Shift+arrastar com o direito ou o meio aplica zoom",
"nav.solidworks.help": "Arrastar com o meio orbita, Ctrl+meio desloca, Shift+meio aplica zoom, arrastar com o direito orbita",
"nav.tinkercad.help": "Arrastar com o direito orbita, arrastar com o meio ou Shift+direito desloca",
@@ -1178,6 +1180,11 @@
"no picture": "sem imagem",
"none": "nenhum",
"parts.automatic_name": "automático",
"parts.dimension.d": "Diâmetro nominal",
"parts.dimension.height": "Altura",
"parts.dimension.pitch": "Passo",
"parts.dimension.thickness": "Espessura",
"parts.dimension.width": "Largura",
"pattern.alignment_2": "Alinhamento 2",
"pattern.alignment_hint": "As contagens incluem o original. Centralizar equilibra as cópias; Inverter escolhe o lado extra para totais pares.",
"pattern.direction_1": "Direção 1",
@@ -2023,6 +2030,7 @@
"ui.heading_utilities": "UTILITÁRIOS",
"ui.heading_utility": "UTILITÁRIO",
"ui.heading_weldments": "SOLDAGEM",
"ui.height": "Altura",
"ui.help": "Ajuda",
"ui.hide": "Ocultar",
"ui.hideAxes": "Ocultar eixos",
@@ -2061,6 +2069,7 @@
"ui.language": "Idioma",
"ui.layout_compact": "Compacto",
"ui.layout_floating": "Flutuante",
"ui.length": "Comprimento",
"ui.length_decimals": "Casas decimais de comprimento",
"ui.light": "Claro",
"ui.line": "Linha",
@@ -2148,6 +2157,7 @@
"ui.pinToShortcuts": "Fixar nos atalhos",
"ui.pinToToolbar": "Fixar na barra de ferramentas",
"ui.pipe": "Tubo",
"ui.pitch": "Passo",
"ui.placement": "Posicionamento",
"ui.plane": "Plano",
"ui.plane_at_angle": "Plano em ângulo",
@@ -2322,6 +2332,7 @@
"ui.visual_shaded_with_edges": "Sombreado com arestas",
"ui.visual_style": "Estilo visual",
"ui.visual_wireframe": "Aramado",
"ui.width": "Largura",
"ui.workspace": "espaço de trabalho",
"ui.workspace_animation_description": "Vistas explodidas, estudos de movimento e storyboards",
"ui.workspace_available": "Disponível",
+6
View File
@@ -993,6 +993,9 @@
"no picture": "fără imagine",
"none": "niciunul",
"parts.automatic_name": "automat",
"parts.dimension.height": "Înălțime",
"parts.dimension.thickness": "Grosime",
"parts.dimension.width": "Lățime",
"pattern.alignment_2": "Aliniere 2",
"pattern.alignment_hint": "Numărul include originalul. Centrat echilibrează copiile; Inversare alege partea suplimentară pentru totaluri pare.",
"pattern.direction_1": "Direcția 1",
@@ -1642,6 +1645,7 @@
"ui.heading_utilities": "UTILITARE",
"ui.heading_utility": "UTILITAR",
"ui.heading_weldments": "SUDURĂ",
"ui.height": "Înălțime",
"ui.help": "Ajutor",
"ui.hide": "Ascunde",
"ui.hideAxes": "Ascunde axele",
@@ -1673,6 +1677,7 @@
"ui.language": "Limbă",
"ui.layout_compact": "Compact",
"ui.layout_floating": "Plutitor",
"ui.length": "Lungime",
"ui.length_decimals": "Zecimale lungime",
"ui.light": "Luminos",
"ui.line": "Linie",
@@ -1929,6 +1934,7 @@
"ui.visual_shaded_with_edges": "Umbrit cu muchii",
"ui.visual_style": "Stil vizual",
"ui.visual_wireframe": "Cadru de sârmă",
"ui.width": "Lățime",
"ui.workspace": "spațiu de lucru",
"ui.workspace_animation_description": "Vederi explodate, studii de mișcare și storyboard-uri",
"ui.workspace_available": "Disponibil",
+848 -1
View File
File diff suppressed because it is too large Load Diff
+953 -1
View File
File diff suppressed because it is too large Load Diff
+212 -1
View File
@@ -22,10 +22,12 @@
"Add Mid Radius": "Ara yarıçap ekle",
"Add Row": "Satır ekle",
"Add a tool": "Araç ekle",
"Add all bodies": "Tüm gövdeleri ekle",
"Add bend": "Büküm ekle",
"Add condition": "Koşul ekle",
"Add or edit rule": "Kural ekle veya düzenle",
"Add to New Folder": "Yeni Klasöre Ekle",
"Add visible bodies": "Görünür gövdeleri ekle",
"Advanced": "Gelişmiş",
"Against": "Karşı",
"Alignment": "Hizalama",
@@ -56,6 +58,7 @@
"BOUNDARY SURFACE": "SINIR YÜZEYİ",
"BROWSER": "TARAYICI",
"Bar": "Çubuk",
"Base Center": "Taban Merkezi",
"Bend": "Büküm",
"Bend Edges": "Büküm kenarları",
"Bend Line Position": "Büküm çizgisi konumu",
@@ -140,6 +143,7 @@
"Create Issue — review draft": "Sorun oluştur — taslağı gözden geçirin",
"Create Issue…": "Sorun Oluştur…",
"Cross curves": "Çapraz eğriler",
"Ctrl+Enter continues on GitHub.": "Ctrl+Enter ile GitHub'da devam edilir.",
"Cube": "Küp",
"Current orthographic view (1:1 mm)": "Geçerli ortografik görünüm (1:1 mm)",
"Current perspective view": "Geçerli perspektif görünüm",
@@ -152,6 +156,7 @@
"Customize…": "Özelleştir…",
"Cylindrical face": "Silindirik yüz",
"Delete": "Sil",
"Delete Folders and Features…": "Klasörleri ve Özellikleri Sil…",
"Delete Selected Features…": "Seçili Özellikleri Sil…",
"Delete Selected Folders": "Seçili Klasörleri Sil",
"Delete all": "Tümünü sil",
@@ -430,6 +435,7 @@
"Remove this point": "Bu noktayı kaldır",
"Rename Feature": "Özelliği Yeniden Adlandır",
"Rename Folder": "Klasörü Yeniden Adlandır",
"Render Stage": "Render Platosu",
"Reopen designs": "Tasarımları yeniden aç",
"Reopen the designs that were open when SolidCraft was last closed": "SolidCraft son kapatıldığında açık olan tasarımları yeniden aç",
"Replace existing library file": "Mevcut kitaplık dosyasının üzerine yaz",
@@ -534,6 +540,7 @@
"Style": "Stil",
"Summary": "Özet",
"Suppress": "Bastır",
"Suppress Selected Folders": "Seçili Klasörleri Bastır",
"Suppressed": "Bastırılmış",
"Surface": "Yüzey",
"Surface, or faces to turn over": "Yüzey veya çevrilecek yüzler",
@@ -581,6 +588,7 @@
"UNTRIM": "KIRPMAYI KALDIR",
"Unit": "Birim",
"Unsuppress": "Bastırmayı kaldır",
"Unsuppress Selected Folders": "Seçili Klasörlerin Bastırmasını Kaldır",
"Updating the preview": "Önizleme güncelleniyor",
"Use active author placement": "Etkin kaynak yerleşimini kullan",
"Use fixed plane": "Sabit düzlem kullan",
@@ -628,6 +636,8 @@
"ai.prefs.background_commands": "Ajan komutlarını arka planda çalıştır",
"ai.prefs.connect_apps": "SolidCraft'ı bu bilgisayardaki AI uygulamalarına aç",
"ai.prefs.connect_apps_note": "SolidCraft başladığında, bu bilgisayarda bulduğu AI uygulamalarına (OpenCode, Claude Desktop, Claude Code, Cursor, Codex, Gemini CLI, Copilot CLI, Windsurf, Zed, VS Code) onu bir MCP sunucusu olarak ekler; böylece bir ajan kurulum yapmadan kullanabilir. Yalnızca solidcraft girdisi eklenir veya yolu yenilenir; değiştirdiğiniz bir girdiye dokunulmaz ve dosya önce yedeklenir. Kapalı: eklediği girdiler kaldırılır. Yardım > AI asistanlarını bağla… bunu elle yapar.",
"ai.prefs.connect_at_start": "SolidCraft başladığında en son kullanılan ajana bağlan",
"ai.prefs.connect_at_start_note": "SolidCraft her başladığında, en son bağlandığınız ajanı (veya varsayılanı) arka planda başlatır; böylece sohbete hazır olur. SolidCraft --control ile başlatıldığında çalışmaz. Bağlanamazsa Asistan, Bağlantı başarısız mesajını ve bir Yeniden dene düğmesini gösterir.",
"ai.prefs.follow_camera": "Kamerayı eskizlere çevir",
"ai.prefs.follow_camera_off": "Otomatik kamera takibi kapalı.",
"ai.prefs.follow_camera_on": "Kamera, ajanın oluşturduğu eskizleri görecek şekilde döner.",
@@ -635,6 +645,8 @@
"ai.prefs.make_default": "Varsayılan olarak kullan",
"ai.prefs.no_agents": "Henüz ajan yok. Ajan ekleyin veya yüklü ajanları bulmak için yenileyin.",
"ai.prefs.no_saved_approvals": "Kaydedilmiş onay yok.",
"ai.prefs.open_at_start": "SolidCraft başladığında Asistan panelini aç",
"ai.prefs.open_at_start_note": "SolidCraft her başladığında Asistan panelini (veya kendi penceresini) gösterir. SolidCraft --control ile başlatıldığında gösterilmez.",
"ai.prefs.override_all_warning": "Bu ajan, sormadan tasarımı kaydedebilir, üzerine yazabilir, dışa aktarabilir veya değiştirebilir.",
"ai.prefs.permission_all": "Her şeye izin ver",
"ai.prefs.permission_all_summary": "Kullanılabilir SolidCraft araçları sormadan çalışır.",
@@ -679,6 +691,9 @@
"cmd.appearance_assign": "Görünüm",
"cmd.appearance_library": "Görünüm kitaplığı",
"cmd.appearance_list": "Görünümleri listele",
"cmd.appearance_paint": "Görünümü Boya",
"cmd.appearance_pick_up": "Görünümü Al",
"cmd.appearance_replace": "Görünümü Değiştir",
"cmd.assembly_bom": "Malzeme listesi",
"cmd.body_rename": "Gövdeyi yeniden adlandır",
"cmd.browser_collapse_all": "Tümünü Daralt",
@@ -766,6 +781,7 @@
"cmd.document_revision": "Tasarım Revizyonu",
"cmd.document_units": "Tasarımın birimlerini değiştir",
"cmd.edit_checkpoint": "Kontrol noktası",
"cmd.edit_repeat": "Son Komutu Tekrarla",
"cmd.edit_restore_checkpoint": "Kontrol noktasını geri yükle",
"cmd.engine_commands": "Komutları listele",
"cmd.engine_describe": "Komutu açıkla",
@@ -879,9 +895,11 @@
"cmd.plastic_snap_fit": "Geçmeli bağlantı",
"cmd.render_aging_describe": "Katmanlı Yüzey Yaşlanması",
"cmd.render_backends": "Render arka uçları",
"cmd.render_batch": "Tüm Çekimleri Render Et",
"cmd.render_camera_fit": "Render Konusunu Çerçevele",
"cmd.render_camera_get": "Render Kamerasını İncele",
"cmd.render_cancel": "Render'ı iptal et",
"cmd.render_compare": "Görüntüleri Karşılaştır",
"cmd.render_effects_describe": "Mercek ve Yaratıcı Efektler",
"cmd.render_export": "PNG dışa aktar",
"cmd.render_hdr_inspect": "HDR Kaynağını İncele",
@@ -897,6 +915,7 @@
"cmd.render_library_surface_prepare": "Oluşturulmuş Yüzey Haritalarını Hazırla",
"cmd.render_library_surface_unbind": "Yüzey Bağlamını Kaldır",
"cmd.render_library_targets": "Render Kitaplık Hedeflerini Bul",
"cmd.render_lights_solo": "Işığı Solo Yap",
"cmd.render_optics_bind": "Optik Bağlamı Kaydet",
"cmd.render_optics_unbind": "Optik Bağlamı Kaldır",
"cmd.render_preflight": "Render isteğini kontrol et",
@@ -1006,7 +1025,9 @@
"cmd.sketch_spline_control_point": "Kontrol noktalı spline",
"cmd.sketch_spline_control_point_5": "Kontrol noktalı spline (derece 5)",
"cmd.sketch_spline_fit_point": "Uydurma noktalı spline",
"cmd.sketch_spline_insert_point": "Spline Noktası Ekle",
"cmd.sketch_spun_profile": "Döndürülmüş profil",
"cmd.sketch_toggle_diameter": "Yarıçap / Çap Arasında Geçiş Yap",
"cmd.sketch_toggle_driven": "Türetilmiş ölçüyü aç/kapat",
"cmd.sketch_transform": "Dönüşüm",
"cmd.sketch_trim_path": "Yol boyunca buda",
@@ -1072,6 +1093,7 @@
"cmd.view_rename": "Adlandırılmış görünümü yeniden adlandır",
"cmd.view_right": "Sağ Görünüm",
"cmd.view_save": "Yeni adlandırılmış görünüm",
"cmd.view_shots_strip": "Çekim Şeridi",
"cmd.view_spin": "Sürekli döndürme",
"cmd.view_tool": "Gezinme aracı",
"cmd.view_top": "Üst Görünüm",
@@ -1145,6 +1167,7 @@
"document.save_changes": "{name} içindeki değişiklikler kaydedilsin mi?",
"document.save_copy": "Bir Kopya Kaydet…",
"document.unsaved_changes": "{name} kaydedilmemiş değişiklikler içeriyor. Kaydetmezseniz bunlar kaybolur.",
"drive.rigid": "{joint} rijit bir bağlantıdır: parçalarını sabit tutar, bu yüzden tahrik edilecek bir şey yoktur. Hareket etmelerini sağlamak için türünü Bağlantıyı düzenle içinde değiştirin: dönmek için Döner, kaymak için Kayar, ikisi için Silindirik.",
"drive.stopped_by_contact": "{value} değerinde durdu: {a} ile {b} iç içe geçerdi",
"drive.stopped_by_loop": "{value} değerinde durdu: {joint} üzerinden geçen döngü daha fazla kapatılamıyor",
"drive.unconnected": "Hiçbir şey hareket etmiyor: {part} sabitlenmiş hiçbir parçaya bağlı değil",
@@ -1180,28 +1203,44 @@
"from the profile": "profilden",
"from the rule": "kuraldan",
"help.apache": "Apache lisansı 2.0",
"help.appearance.assign": "Seçili gövdelere, yüzlere veya bileşenlere ağırlıklarını değiştirmeden bir renk veya malzeme görünümü verir. Parçaları ayırt etmek veya bir kaplamayı önizlemek için kullanın.",
"help.attributions": "Atıflar (ATTRIBUTION.md)",
"help.build": "Sürüm {version} · commit {commit} · derleme tarihi {date}",
"help.connect_note": "SolidCraft sunucusunu yüklemek için her asistanı yeniden başlatın. Değişmeden önce her dosya .bak olarak yedeklendi.",
"help.connect_title": "AI asistanlarını bağla",
"help.face.delete": "Seçili yüzleri kaldırır ve komşu yüzlerin boşluğu kapatmasını sağlar ya da boşluğu yüzey olarak açık bırakır. Yuvarlatılmış bir kenarı, bir deliği veya yolda duran bir çıkıntıyı gidermek için kullanın.",
"help.font_details": "Arayüz, egui'nin yerleşik yazı tiplerini kullanır (Ubuntu Font Licence ve MIT/Bitstream Vera lisansları altında Ubuntu Light ve Hack; OFL ve MIT altında Noto Emoji ve emoji simge yazı tipi). Eskiz metni Liberation Sans (SIL OFL 1.1) kullanır. The Crafting Apps'in isteğe bağlı yazı tipi paketi craft-fonts (BIZ UDPGothic, Shippori Mincho, BIZ UDMincho, Noto Sans CJK SC, Noto Sans Arabic; SIL OFL 1.1), SolidCraft derlemelerine dahil değildir.",
"help.fonts": "Yazı tipleri",
"help.licences": "Lisanslar",
"help.material.assign": "Seçili gövdelerin neyden yapıldığını belirler: çelik, alüminyum veya ABS gibi. Kütle ve ağırlığın gerçek parçayla uyuşması için kullanın.",
"help.mit": "MIT lisansı",
"help.notice": "NOTICE",
"help.parameters.change": "Tasarımın ölçülerini yöneten adlandırılmış değerlerin ve ifadelerin tablosunu açar. Bir ölçüyü tek yerden değiştirip onu kullanan her özelliğin buna uymasını sağlamak için kullanın.",
"help.solid.align": "Seçili gövdeleri, üzerlerindeki bir nokta, yüz veya düzlem başka bir yerdeki nokta, yüz veya düzlemle buluşacak şekilde taşır. Ofseti ölçmeden bir parçayı diğerinin yanına yerleştirmek için kullanın.",
"help.solid.chamfer": "Seçili kenarları, belirlediğiniz mesafede düz bir pahla keser. Keskin kenarları kırmak veya bir pim ya da vidanın girişini kolaylaştırmak için kullanın.",
"help.solid.combine": "Gövdeleri birleştirir, bir hedef gövdeden çıkarır veya yalnızca paylaştıkları hacmi tutar ve araç gövdelerini tutabilir. Parçaları kaynaştırmak, bir şekli diğeriyle kesmek veya iki gövdenin örtüştüğü yeri bulmak için kullanın.",
"help.solid.draft": "Seçili yüzleri, nötr bir düzlemden ölçülen belirlediğiniz açı kadar eğerek koniklik verir. Kalıplanan veya dökülen parçaların kalıptan kolayca çıkması için kullanın.",
"help.solid.extrude": "Bir eskiz profilini, malzeme ekleyerek veya kaldırarak bir mesafe boyunca 3B'ye taşır. Düz bir konturu blok, kabarıklık veya cep haline getirmek için kullanın.",
"help.solid.fillet": "Seçili kenarları, belirlediğiniz yarıçapta pürüzsüz dairesel bir uyumla yuvarlatır. Keskin kenarları sağlamlık, konfor veya görünüm için yumuşatmak amacıyla kullanın.",
"help.solid.hole": "Bir yüzeyde seçtiğiniz noktada, belirlediğiniz çapta yuvarlak bir delik deler. Vida boşlukları, pimleri ve diğer basit yuvarlak açıklıklar için kullanın.",
"help.solid.loft": "İki veya daha fazla eskiz profili arasında, ya da bir profille bir nokta arasında pürüzsüz bir katı karıştırır. Geçişler, huniler, saplar ve uzunluğu boyunca kesiti değişen şekiller için kullanın.",
"help.solid.mirror": "Seçili gövdelerin veya özelliklerin bir düzlem boyunca ayna görüntüsünü kopyasını oluşturur ve orijinalle birleştirebilir. Simetrik parçalar için kullanın; yarısını modelleyip ikisini de alın.",
"help.solid.move": "Seçili gövdeleri ya da kopyalarını, belirlediğiniz mesafe ve açıyla taşır veya döndürür. Bir gövdenin yerini değiştirmek ya da başka bir yerde ikincisini oluşturmak için kullanın.",
"help.solid.offset_face": "Seçili yüzleri belirlediğiniz mesafe kadar içeri veya dışarı iter, çevrelerindeki yüzler de buna uyar. Eskizi düzenlemeden bir duvarı kalınlaştırmak, bir cebi derinleştirmek veya bir çıkıntıyı yükseltmek için kullanın.",
"help.solid.pattern.circular": "Seçili nesneleri, belirlediğiniz adet ve toplam açı boyunca bir eksen etrafında yineler. Cıvata daireleri, jant kolları, kanatçıklar ve dişler için kullanın.",
"help.solid.pattern.rectangular": "Seçili nesneleri, belirlediğiniz adet ve aralıkla bir veya iki yönde yineler. Delik, nervür, pim veya ayak dizileri ve ızgaraları için kullanın.",
"help.solid.press_pull": "Bir yüzü sürüklerken malzeme ekler veya kaldırır, kenarları sürüklerken yuvarlatır. Doğrudan model üzerinde hızlı değişiklikler için kullanın.",
"help.solid.remove": "Seçili gövdeleri tasarımdan, zaman çizelgesindeki bu noktadan itibaren çıkarır; önceki adımlar onları korur. Artık gerekmeyen bir kesici araç gibi yardımcı bir gövdeyi atmak için kullanın.",
"help.solid.replace_face": "Seçili düz yüzleri bir düzleme veya paralel bir yüze taşır, gövde de onunla buluşmak için büyür veya küçülür. Bir yüzü başka bir parçayla ya da bir yapı düzlemiyle aynı hizaya getirmek için kullanın.",
"help.solid.revolve": "Bir eskiz profilini bir eksen etrafında döndürerek yuvarlak bir katı oluşturur. Miller, topuzlar, kaseler ve bir merkez çizgisi etrafında yuvarlak olan parçalar için kullanın.",
"help.solid.scale": "Seçili gövdeleri bir çarpanla büyütür veya küçültür; her yönde aynı ya da eksen başına ayrı olabilir. İçe aktarılan bir şekli yeniden boyutlandırmak veya büzülme payı bırakmak için kullanın.",
"help.solid.shell": "Bir katıyı içini oyarak boşaltır, belirlediğiniz kalınlıkta duvarlar bırakır ve seçtiğiniz yüzleri açabilir. Kutular, kapaklar ve diğer ince cidarlı parçalar için kullanın.",
"help.solid.split_body": "Bir gövdeyi bir düzlemle, başka bir gövdenin yüzüyle veya bir eskiz çizgisiyle ayrı gövdelere keser. Ayrı ayrı basılan, işlenen veya renklendirilen parçalar elde etmek için kullanın.",
"help.solid.split_face": "Seçili yüzleri, gövdeyi kesmeden bir düzlem, başka bir gövdenin yüzü veya eskiz eğrileri boyunca böler. Bir yüzün bir kısmına kendi koniklik, renk veya ofsetini vermek için kullanın.",
"help.solid.sweep": "Bir eskiz profilini bir yol boyunca sürükleyerek katı oluşturur. Borular, raylar, saplar ve bir eğriyi izleyen sabit kesitli parçalar için kullanın.",
"help.third_party": "Üçüncü taraf lisansları",
"help.timeline.compute_all": "Zaman çizelgesindeki her özelliği baştan yeniden oluşturur. Modeli tazelemek ve hangi özelliklerin başarısız olduğunu görmek için kullanın.",
"help.timeline.delete": "Seçili özellikleri zaman çizelgesinden siler; bir eskizi silmek ondan oluşturulan özellikleri de siler. Artık istenmeyen bir adımı kaldırmak için kullanın.",
"hole_presets.confirm_delete": "Silmeyi onayla",
"hole_presets.delete": "Sil",
"hole_presets.delete_prompt": "Bu kişisel ön ayar silinsin mi? Mevcut delikler değişmez.",
@@ -1286,6 +1325,9 @@
"install.steps_intro": "Safari web uygulamalarını kendi menüleri üzerinden yükler:",
"install.title": "SolidCraft'ı yükle",
"issue.body_label": "Rapor metni",
"issue.note_changed_while_waiting": "Önizleme beklenirken ayarlar veya model değişti. Teknik ayrıntıları geçerli görünüme göre güncellemek için ekran görüntüsünü yeniden alın.",
"issue.note_details_kept": "Ekran görüntüsü yerel olarak alındı. Düzenlediğiniz teknik ayrıntılar korundu: hâlâ geçerli görünümle uyuştuklarını kontrol edin.",
"issue.note_details_updated": "Teknik ayrıntılar geçerli görünümle uyuşacak şekilde güncellendi. Ekran görüntüsü yerel olarak alındı. GitHub'a eklemeden önce gözden geçirin.",
"issue.note_image_copied": "Görseli GitHub taslağına yapıştırın; görsel kopyalama kullanılamıyorsa PNG'yi kaydedin.",
"issue.note_opened": "GitHub taslağını gözden geçirin ve ekran görüntüsünü ekleyin. GitHub'daki Submit new issue düğmesi raporu yayımlar.",
"issue.note_opened_copied": "Rapor kopyalandı. GitHub taslağına yapıştırın, ekran görüntüsünü ekleyin, ardından GitHub'da Submit new issue düğmesine tıklayın.",
@@ -1352,6 +1394,8 @@
"material.editor.unknown_card": "Mühendislik özellikleri bilinmiyor. Kaydetme yalnızca atanan yoğunluğu ve mevcut görünümü koruyabilir.",
"material.editor.user_supplied": "Kullanıcı tarafından sağlanan",
"material.editor.wood": "Ahşap",
"material.selection.choose": "Bir malzeme seçin",
"material.selection.mixed": "Farklı malzemeler",
"measure.at": "Konum",
"measure.item": "Öğe {number}",
"messages.ago_h": "{n} sa. önce",
@@ -1381,8 +1425,12 @@
"nav.free_orbit.help": "Fare ve 3B fare, her iki kutuptan geçerek döndürür ve yuvarlanmayı korur. Shift eksen hizalama devre dışı.",
"nav.free_orbit.label": "Serbest döndürme",
"nav.free_orbit.snap_help": "Fare ve 3B fare, her iki kutuptan geçerek döndürür ve yuvarlanmayı korur. Görünüm yönünü ve yuvarlanmayı hizalamak için döndürme sürüklemesi sırasında Shift tuşunu basılı tutun.",
"nav.free_orbit_upright.help": "Fareyle yana sürüklemek modeli dünyanın dikey ekseni etrafında döndürür; yukarı ve aşağı sürüklemek tepe noktasını da aşarak sınırsız eğim verir.",
"nav.free_orbit_upright.label": "Dikey eksen etrafında döndür",
"nav.fusion.help": "Orta sürükleme kaydırır, Shift+orta döndürür, sağ sürükleme döndürür",
"nav.hfss.help": "Alt+sol sürükleme kaydırır, Shift+Alt+sol yakınlaştırır, boş alanda Ctrl+sol sürükleme döndürür",
"nav.inventor.help": "Orta sürükleme kaydırır, Shift+orta döndürür, Ctrl+orta yakınlaştırır, sağ sürükleme döndürür",
"nav.maya.help": "Alt+sol sürükleme döndürür, Alt+orta kaydırır, Alt+sağ yakınlaştırır; orta sürükleme ayrıca kaydırır",
"nav.openscad.help": "Boşlukta sol sürükleme döndürür, Shift+sol sürükleme kutu seçimi yapar, eskiz geometrisi sürükleyerek düzenlenir; sağ veya orta sürükleme kaydırır, Shift+sağ veya Shift+orta sürükleme yakınlaştırır",
"nav.perspective.sketch": "Eskiz düzenleme dik görünüm kullanır. Perspektife geçmek için eskizi bitirin.",
"nav.solidworks.help": "Orta sürükleme döndürür, Ctrl+orta kaydırır, Shift+orta yakınlaştırır, sağ sürükleme döndürür",
@@ -1393,6 +1441,93 @@
"nav.touchpad.pan": "Kaydır (Shift tuşunu basılı tutup hareket ettirin; fare tuşu olmadan)",
"nav.touchpad.scroll": "Dokunmatik yüzey yakınlaştırmak için dikey kaydırmayı kullanır. İki parmakla kaydırma diğer ön ayarlar için kayıtlı kalır.",
"nav.touchpad.zoom": "Yakınlaştır (dikey kaydırın veya parmaklarınızı açıp kapatın)",
"navbar.agent_chat": "Asistan sohbet paneli",
"navbar.agent_cursor": "Ajan imlecini göster",
"navbar.ambient_occlusion": "Ortam oklüzyonu",
"navbar.assistant": "Asistan",
"navbar.custom.add_slot": "{slot} ekle",
"navbar.custom.always": "Her zaman görünür",
"navbar.custom.available": "{available} · çubuğa sürükleyin veya Ekle'ye basın",
"navbar.custom.buttons": "Düğmeler",
"navbar.custom.compact": "Kompakt",
"navbar.custom.count": "16 yuvadan {count} tanesi",
"navbar.custom.customise": "Gezinme çubuğunu özelleştir…",
"navbar.custom.design": "Tasarım",
"navbar.custom.duplicate": "Bu yuva zaten çubukta.",
"navbar.custom.fade": "Soldur",
"navbar.custom.full": "Başka bir yuva eklemek için bir yuvayı kaldırın.",
"navbar.custom.hidden_design": "Tasarımda gizli",
"navbar.custom.hidden_render": "Render'da gizli",
"navbar.custom.hide": "Gezinme çubuğunu gizle",
"navbar.custom.hide_idle": "Üzerine gelinceye kadar gizle",
"navbar.custom.icon_only": "Yalnızca simge",
"navbar.custom.icon_value": "Simge ve değer",
"navbar.custom.icons": "Simgeler",
"navbar.custom.idle": "Boştayken",
"navbar.custom.intro": "3B görünümün altındaki çubukta hangi denetimlerin ve hangi sırayla olacağını seçin. Bir yuvayı taşımak için sürükleyin, kaldırmak için çubuğun dışına sürükleyin.",
"navbar.custom.labels": "Simgeler ve etiketler",
"navbar.custom.left": "Sola taşı",
"navbar.custom.position": "Konum",
"navbar.custom.position_centre": "Orta",
"navbar.custom.position_left": "Sol",
"navbar.custom.position_right": "Sağ",
"navbar.custom.preview_as": "Şu şekilde önizle",
"navbar.custom.regular": "Normal",
"navbar.custom.remove": "Kaldır",
"navbar.custom.remove_bar": "Çubuktan kaldır",
"navbar.custom.render": "Render",
"navbar.custom.reset": "Gezinme çubuğunu sıfırla",
"navbar.custom.reset_default": "Varsayılana sıfırla",
"navbar.custom.right": "Sağa taşı",
"navbar.custom.select": "Yuva seçilmedi. Taşımak, kaldırmak veya görünümünü değiştirmek için çubukta bir yuva seçin.",
"navbar.custom.separators_full": "Çubukta zaten dört ayırıcı var.",
"navbar.custom.show": "Gezinme çubuğunu göster",
"navbar.custom.shows": "Gösterim",
"navbar.custom.size": "Boyut",
"navbar.custom.stale": "Çubuk değişti. Yuvayı yeniden seçin.",
"navbar.custom.title": "Gezinme çubuğu",
"navbar.custom.unknown": "Bu yuva kullanılamıyor.",
"navbar.description.ambient_occlusion": "Derinlik katmak için kıvrımları ve köşeleri koyulaştırır.",
"navbar.description.display": "Görünüm ayarlarını barındırır: grafik hazır ayarı, ızgara, zemin gölgesi, ortam oklüzyonu ve projeksiyon.",
"navbar.description.fit": "Seçimi çerçeveler; hiçbir şey seçili değilse tüm modeli.",
"navbar.description.grid": "Zemin ızgarasını gösterir veya gizler.",
"navbar.description.ground_shadow": "Modelin altındaki gölgeyi gösterir veya gizler.",
"navbar.description.home": "Tüm modelin izometrik görünümüne döner.",
"navbar.description.look_at": "Görünümü seçili yüze, düzleme veya açık eskize doğru çevirir.",
"navbar.description.orbit": "Görünümü modelin etrafında döndürür.",
"navbar.description.pan": "Görünümü yana, yukarı veya aşağı kaydırır.",
"navbar.description.projection": "Ortografik ve perspektif görünümler arasında geçiş yapar.",
"navbar.description.separator": "Komşu yuvaları gruplayan ince bir çizgi.",
"navbar.description.spin": "Siz tıklayana veya bir tuşa basana kadar görünümü döndürmeye devam eder.",
"navbar.description.visual_style": "Modelin nasıl çizileceğini değiştirir: gölgeli, tel kafes veya gizli kenarlarla.",
"navbar.description.zoom": "Görünümü modele yaklaştırır veya uzaklaştırır.",
"navbar.display": "Görüntü",
"navbar.fit": "Sığdır",
"navbar.graphics": "Grafik",
"navbar.grid": "Izgara",
"navbar.ground_shadow": "Zemin gölgesi",
"navbar.home": "Ana görünüm",
"navbar.later": "Sonra",
"navbar.look_at": "Bak",
"navbar.more": "Daha fazla",
"navbar.orbit": "Yörünge",
"navbar.orthographic": "Ortografik",
"navbar.pan": "Kaydır",
"navbar.perspective": "Perspektif",
"navbar.preset": "Hazır ayar",
"navbar.projection": "Projeksiyon",
"navbar.projection_heading": "Projeksiyon",
"navbar.separator": "Ayırıcı",
"navbar.show": "Göster",
"navbar.spin": "Sürekli döndür",
"navbar.style.shaded": "Gölgeli",
"navbar.style.shaded_with_edges": "Kenarlı gölgeli",
"navbar.style.shaded_with_hidden_edges": "Gizli kenarlı gölgeli",
"navbar.style.wireframe": "Tel kafes",
"navbar.translucent": "Yarı saydam",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "Görsel stil",
"navbar.zoom": "Yakınlaştır",
"needs two joints": "iki bağlantı gerektirir",
"network.allow_once": "Bir kez izin ver",
"network.always_allow": "Bu sunucuya her zaman izin ver",
@@ -1406,6 +1541,11 @@
"no picture": "resim yok",
"none": "yok",
"parts.automatic_name": "otomatik",
"parts.dimension.d": "Nominal çap",
"parts.dimension.height": "Yükseklik",
"parts.dimension.pitch": "Adım",
"parts.dimension.thickness": "Kalınlık",
"parts.dimension.width": "Genişlik",
"pattern.alignment_2": "Hizalama 2",
"pattern.alignment_hint": "Adet, orijinali içerir. Ortala, kopyaları iki yana dağıtır; çift adetlerde yönü ters çevirme, fazladan kopyanın hangi tarafta olacağını belirler.",
"pattern.direction_1": "Yön 1",
@@ -1432,6 +1572,10 @@
"prefs.assistant": "Asistan",
"prefs.axes": "Eksenler",
"prefs.axis": "Eksen",
"prefs.bodies_folders": "Gövde klasörleri",
"prefs.bodies_folders_always": "Her zaman",
"prefs.bodies_folders_never": "Hiçbir zaman",
"prefs.bodies_folders_several": "Yalnızca birden çok gövde",
"prefs.bottom": "Alt",
"prefs.browser": "Tarayıcı",
"prefs.built_in": "Yerleşik",
@@ -1456,6 +1600,10 @@
"prefs.design_note": "Yeni tasarımların neyle başladığı. Açık tasarımlar kendi ayarlarını korur.",
"prefs.devices": "3B fare",
"prefs.dialog_buttons": "Diyalog düğmeleri",
"prefs.dialogs": "Diyaloglar",
"prefs.dialogs_edge": "Görünümün kenarında",
"prefs.dialogs_left_column": "Sol sütunda",
"prefs.dialogs_note": "Komut diyaloglarının açılacağı yer: görünümün kenarına yerleşik veya tarayıcının ve Geçmiş'in yerine sol sütunda; bunlar diyalog kapanınca eskisi gibi geri gelir.",
"prefs.display": "Görüntü",
"prefs.edges": "Kenarlar ve gölgeleme",
"prefs.extend": "Uzat",
@@ -1515,6 +1663,8 @@
"prefs.opaque": "Opak",
"prefs.orbit_snap": "Bir eksene hizalamak için döndürme sırasında Shift tuşunu basılı tutun.",
"prefs.orientation": "Yönelim",
"prefs.origin_plane_names": "Orijin düzlemi adları",
"prefs.origin_plane_names_note": "Tarayıcıda, diyaloglarda ve listelerde gösterilen adlar. Z yukarı olmak üzere {top} XY, {front} XZ ve {right} YZ'dir. Komutlar, betikler ve kayıtlı tasarımlar XY, XZ ve YZ adlarını korur.",
"prefs.overall_speed": "Genel hız",
"prefs.placement": "Yerleşim",
"prefs.prefer_free_sketch_points": "Noktalar örtüştüğünde hareketli eskiz noktalarını tercih et",
@@ -1528,6 +1678,8 @@
"prefs.saving": "Otomatik kayıt ve kurtarma",
"prefs.scale_note": "Pencerede ayrıca Ctrl + / Ctrl −. Düğmeler %100'de 28 px.",
"prefs.scale_text": "Ölçek ve metin",
"prefs.search": "Ayarlarda ara",
"prefs.search_empty": "Eşleşen ayar yok",
"prefs.select": "Seçim",
"prefs.select_one_item": "Bir öğe seçin",
"prefs.selecting": "Seçme",
@@ -1625,6 +1777,7 @@
"render.aging_target_search": "Gövde adlarını filtrele",
"render.aging_upward": "Yukarı bakan birikim",
"render.all_controls_help": "Tüm geçerli kontrollerin yoğun incelemesi. Bölüm sayfaları, temel isteği değiştirmeden odaklı düzenleme sağlar.",
"render.all_shots_label": "Tüm Çekimler",
"render.appearance_physics_separate": "Görsel görünüm yoğunluk, termal veri veya diğer mühendislik özelliklerini atamaz.",
"render.availability_native": "Yerli kompozisyon; uygulamadan önce inceleyin",
"render.availability_projection": "Desteklenen yansıtma; kapsama ve atlamalara bakın",
@@ -1779,10 +1932,13 @@
"render.effects_reset_lens": "Mercek efektlerini sıfırla",
"render.effects_seed": "Desen tohumu",
"render.export_display": "Dışa aktar: görüntü PNG",
"render.export_image_label": "Görüntüyü Dışa Aktar",
"render.export_linear": "Dışa aktar: ham doğrusal EXR",
"render.exr_pending": "GPU ham doğrusal EXR'ı saklayabilir. Sıkıştırma, çok katmanlı görüntüler ve yardımcı render geçişleri kullanılamamaya devam ediyor.",
"render.film_grain": "Fotoğrafik gren",
"render.fit": "Ürünü sığdır",
"render.fixed_camera": "Kamera",
"render.fixed_world": "Dünya",
"render.flare_ghosts": "Kaynak başına hayalet halka",
"render.flare_halo": "Flare halesi",
"render.flare_streak": "Anamorfik tarzı çizgi",
@@ -1809,6 +1965,12 @@
"render.hdr_primaries_srgb": "Renk alanı: sRGB/D65",
"render.hdr_primaries_undeclared": "Kaynak renk alanını beyan etmiyor; işleyici renk gereksinimlerini inceleyin.",
"render.hdr_resource_missing": "Bu tasarımda kaydedilen HDR kaynağı eksik.",
"render.heading_batch": "TOPLU",
"render.heading_frame": "ÇERÇEVE",
"render.heading_lens": "MERCEK",
"render.heading_results": "SONUÇLAR",
"render.heading_shots": "ÇEKİMLER",
"render.hide_shots_label": "Çekim şeridini gizle",
"render.image_advanced": "Gelişmiş GPU kontrolleri",
"render.image_cancelled": "Render iptal edildi",
"render.image_cancelling": "İptal ediliyor",
@@ -1840,6 +2002,7 @@
"render.image_width": "Genişlik",
"render.include_rig_cards": "Pasif kartları ve bayrakları dahil et",
"render.inspect_scene": "Yakalanan sahne özetini yenile",
"render.inspector": "Denetçi",
"render.keep_editing": "Düzenlemeye devam et",
"render.layer_down": "Aşağı taşı",
"render.layer_enabled": "Katman etkin",
@@ -1908,6 +2071,8 @@
"render.library_unfavorite": "Sık kullanılanlardan kaldır",
"render.library_uniform_ack": "Uzamsal veya gelişmiş efektler olmadan tek biçimli yaklaşımı kullan",
"render.library_usable": "Çalıştırılabilir yansıtmalar",
"render.light_anchor_pending": "Işık koordinat çerçevesini değiştirmek henüz desteklenmiyor.",
"render.lights_fixed_to": "Işıklar şuna sabit",
"render.linear_help": "Giderme, pozlama, ton eşleme, filtreler ve arka plandan önce 32 bit float RGBA ana görüntüyü saklar. Doğrusal sRGB/D65; kapsama ile ön çarpımlı. Ek bellek açıkça kabul edilir. Sıkıştırma veya ek geçiş yoktur.",
"render.linear_retain": "Ham doğrusal EXR'ı sakla",
"render.linear_unavailable": "Seçilen tamamlanmış karede saklanmış EXR yok. Render'dan önce saklamayı etkinleştirin; eski bir PNG ham ışınımı geri getiremez.",
@@ -1993,6 +2158,7 @@
"render.output_over_budget": "İstenen görüntü, seçilen kaynak sınırını aşıyor. Uygun bir boyut veya profil açıkça seçin; otomatik düşürme yapılmaz.",
"render.output_ratio_refused": "Bağlı boyut, bu yöntemin boyut sınırını aşıyor. Önceki boyut korunur; oranı kilitten çıkarın veya daha küçük bir değer seçin.",
"render.output_swap_orientation": "Genişlik ve yüksekliği değiştir",
"render.output_tools_inspector": "Boyutu ve biçimi Çıktı denetçisinde düzenleyin.",
"render.page_aging": "Yaşlanma ve kirlenme",
"render.page_all": "Tüm kontroller",
"render.page_appearance": "Görünüm",
@@ -2004,6 +2170,7 @@
"render.page_lighting": "Aydınlatma",
"render.page_output": "Çıktı",
"render.page_scene": "Sahne",
"render.paint_label": "Boya",
"render.passive_stage": "Zemin ve pasif sahne",
"render.passive_stage_help": "Sonlu pasif paneller yalnızca render görüntülerine aittir. CAD gövdesi veya kütle eklemezler. Uygulamadan sonra yerleşim sabittir; ürün sınırlarıyla kesişen reddedilir. CPU dağınık sekme aydınlatması sağlamaz.",
"render.perspective": "Perspektif kamera",
@@ -2019,6 +2186,13 @@
"render.physical_prepare_plan": "Oluşturma planını hazırla (uygulamaz)",
"render.physical_separate": "Görünüm, malzeme kimliği değildir. Bunlar kaynaklı referanslardır, sertifikalı etkin özellikler değildir. Mevcut kütle, mühendislik malzemeleri ve optikler değişmez.",
"render.physical_unknown": "Sayısal aday belirlenmemiş. Kademe, formülasyon veya yapı belirtilmelidir; bilinmez, sıfır değildir.",
"render.pick_body": "Gövde",
"render.pick_component": "Bileşen",
"render.pick_face": "Yüz",
"render.pick_help": "Gövde, Yüz veya Bileşen seçin. Temizlemek için boş alana tıklayın; Shift veya Ctrl ekler ya da seçimi tersine çevirir. Vurgular yalnızca canlı ürün görünümünde görünür.",
"render.pick_label": "Seç",
"render.pick_up_label": "Al",
"render.pick_waiting": "Ürün seçimi henüz desteklenmiyor.",
"render.post_contrast": "Kontrast",
"render.post_gain_b": "Mavi kazancı",
"render.post_gain_g": "Yeşil kazancı",
@@ -2031,6 +2205,7 @@
"render.preview": "Yerleşik önizleme",
"render.preview_help": "Harmanlanmış saydamlıkla raster görüntü. Kırılma, HDRI ve son render henüz kullanılamıyor.",
"render.preview_image_settings_help": "Canlı Önizleme, sabit stüdyo aydınlatmasını korur. Pozlama ve görüntü aydınlatması, Kontrol veya Başlat sırasında görüntü işine uygulanır.",
"render.preview_lighting_help": "Canlı önizleme yalnızca doğrudan ışığı gösterir, gölge göstermez.",
"render.preview_retry": "Canlı önizlemeyi yeniden dene",
"render.preview_unavailable_help": "Canlı önizleme kullanılamıyor. Kaydedilmiş kurulumlar ve görüntü işi kontrolleri erişilebilir kalır. Sahneyi değiştirin veya açıkça yeniden deneyin; reddedilen sahne her karede yeniden kurulmaz.",
"render.preview_upload": "Canlı önizleme tepe noktası yükü",
@@ -2044,8 +2219,10 @@
"render.radial_distortion": "Radyal bozulma",
"render.regrade_action": "Ham ana görüntüyü yeniden derecelendir (giderme yok)",
"render.regrade_help": "Bu sunum kontrollerini kullanarak seçilen tamamlanmış ham ana görüntüden ayrı bir PNG oluşturur. Işın izlemez, yakalanan boyutu/kamerayı/ışıkları değiştirmez veya EXR'ın üzerine yazmaz. Giderme yeniden uygulanmaz: ham ana görüntüler onun kılavuzlarını saklamaz. Türev, aynı iş kontrollerinden dışa aktarılabilir kalır.",
"render.regrade_label": "Yeniden derecelendir",
"render.reload_settings": "Kaydedilmiş ayarları yükle",
"render.replace_ground": "Mevcut sahnenin değiştirilmesini onayla",
"render.replace_label": "Değiştir",
"render.replace_saved_surface": "Bu hedef için mevcut kaydedilmiş bağlamın yerini al",
"render.restore_camera": "Kaydedilmiş kamerayı yükle",
"render.result_actual_help": "Ekran pikseli başına bir görüntü pikseli.",
@@ -2091,6 +2268,7 @@
"render.sampling_title": "Uyarlanabilir ve geçiş örnekleme",
"render.save_continue": "Kaydet ve devam et",
"render.save_setup": "Kurulumu kaydet",
"render.save_shot": "Çekimi Kaydet",
"render.saved_maps_runtime_conflict": "Kaydedilmiş yüzey bağlamları, geçici optik geçersiz kılmalar veya kaydedilmemiş HDR ile karıştırılamaz. HDR'ı kaydedin veya geçici girdileri açıkça kaldırın.",
"render.saved_surface_remove": "Kaydedilmiş bağlamı kaldır",
"render.saved_surfaces": "Kaydedilmiş yüzey bağlamları",
@@ -2110,6 +2288,9 @@
"render.setup_runtime_unsupported": "Bu tam iş henüz kaydedilemez: haritalar veya sahne-gövde bağlamları içeriyor. Taşınabilir bir kurulum kaydetmeden önce o geçici girdileri kaldırın.",
"render.setup_save_missing": "Komut tamamlandıktan sonra kaydedilmiş render yapılandırması bulunamadı.",
"render.sharpening": "Detay keskinleştirme",
"render.shell_tab_appearance": "RENDER GÖRÜNÜMÜ",
"render.shell_tab_camera": "RENDER KAMERASI",
"render.shell_tab_scene": "RENDER SAHNESİ",
"render.shot_duplicate": "Kaydedilmiş çekimi çoğalt",
"render.shot_manager": "Kaydedilmiş çekimler",
"render.shot_new_name": "Yeni çekim adı",
@@ -2118,11 +2299,19 @@
"render.shot_remove_title": "Kaydedilmiş çekim kaldırılsın mı?",
"render.shot_rename": "Kaydedilmiş çekimi yeniden adlandır",
"render.shot_saved_only": "Önce geçerli taslağı kaydedin. Çoğalt ve yeniden adlandır, tam kaydedilmiş seçenekleri ve kaynak referanslarını korur.",
"render.show_shots_label": "Çekim şeridini göster",
"render.sky_ground": "Zemin · doğrusal RGB",
"render.sky_horizon": "Ufuk · doğrusal RGB",
"render.sky_zenith": "Tepe · doğrusal RGB",
"render.soft_focus": "Yumuşak odak",
"render.stage_frame": "Çerçeve",
"render.stage_light": "Işık",
"render.stage_look": "Görünüm",
"render.stage_orthographic": "Ortografik",
"render.stage_output": "Çıktı",
"render.stage_panel_count": "Kaydedilmiş paneller",
"render.stage_preview_note": "Entegre önizleme · doğrudan ışık",
"render.strip_label": "Şerit",
"render.studio_add_area": "Alan ışığı ekle",
"render.studio_ambient": "Sabit ortam ışınımı",
"render.studio_ambient_rgb": "Sabit ortam ışınımı (doğrusal RGB)",
@@ -2179,6 +2368,12 @@
"render.volume_max": "En fazla sınırlar · dünya mm",
"render.volume_min": "En az sınırlar · dünya mm",
"render.volume_title": "Sınırlı homojen hacim",
"render.wait_batch": "henüz desteklenmiyor: kayıtlı çekimlerin render kuyruğu",
"render.wait_compare": "henüz desteklenmiyor: saklanan görüntü karşılaştırması",
"render.wait_paint": "henüz desteklenmiyor: ürün seçimi ve görünüm boyama",
"render.wait_pick_up": "henüz desteklenmiyor: ürün seçimi ve görünüm örnekleme",
"render.wait_replace": "henüz desteklenmiyor: bir görünümün tüm kullanımlarını değiştirme",
"render.wait_solo": "henüz desteklenmiyor: ışık görünürlüğü ve solo denetimleri",
"sample.bracket.about": "2 mm sac metal kuralına göre kenar flanşları ve bir kenet içeren taban flanşı",
"sample.bracket.name": "Sac metal köşebent",
"sample.enclosure.about": "Dudak, vida göbekleri, dayanak ve geçmeli bağlantı içeren, içi boşaltılmış blok",
@@ -2270,6 +2465,7 @@
"timeline.delete_after_marker_one": "Geçmiş İşaretçisinden Sonra 1 Özelliği Sil",
"timeline.delete_after_marker_other": "Geçmiş İşaretçisinden Sonra {count} Özelliği Sil",
"timeline.delete_folders_tip": "Özelliklerini ve iç içe klasörlerini geçmişte tut",
"timeline.delete_folders_with_features_tip": "Klasörleri, içlerindeki her özellikle ve iç içe klasörleriyle birlikte sil",
"timeline.delete_many": "{count} Seçili Özelliği Sil",
"timeline.feature_error": "Hata: {message}",
"timeline.feature_hint": "Düzenlemek için çift tıklayın · sıralamak için sürükleyin · daha fazlası için sağ tıklayın",
@@ -2279,6 +2475,7 @@
"timeline.move_to_group": "Özellikleri klasöre taşı",
"timeline.rename_group": "Özellik klasörünü yeniden adlandır",
"timeline.reorder_many": "Özellikleri yeniden sırala",
"timeline.suppress_folders_tip": "Klasörlerdeki ve iç içe klasörlerindeki her özelliği bastır veya bastırmayı kaldır",
"timeline.ungroup": "Özellik klasörünü kaldır",
"to the face": "yüze kadar",
"to the next face": "sonraki yüze kadar",
@@ -2289,7 +2486,11 @@
"toolbar.render_camera": "KAMERA",
"toolbar.render_environment": "ORTAM",
"toolbar.render_lighting": "AYDINLATMA",
"toolbar.render_lights": "IŞIKLAR",
"toolbar.render_result": "SONUÇ",
"toolbar.render_scene": "SAHNE",
"toolbar.render_stage": "PLATO",
"toolbar.render_studio": "STÜDYO",
"trace.points": "Yol boyunca {count} nokta",
"trace.stopped_by_contact": "Örnek {sample} noktasında biter: {a}, {b} içinden geçecek",
"trace.stopped_by_loop": "Örnek {sample} noktasında biter: {joint} üzerinden geçen döngü daha fazla kapanamaz",
@@ -2468,6 +2669,7 @@
"ui.agent_chat_import_failed": "{name}: içe aktarma başarısız oldu: {error}",
"ui.agent_chat_intro": "Zaten kullandığınız bir kodlama ajanıyla veya seçtiğiniz bir model uç noktasıyla sohbet edin. Ajan, SolidCraft'ın araçlarıyla açık tasarım üzerinde çalışır: Değişiklikleri hemen görünür ve mesaj başına tek adımda geri alınabilir. Sormadan neleri yapabileceğini Ayarlar > AI altında belirlersiniz.",
"ui.agent_chat_key_in_env": "anahtar ayarlı",
"ui.agent_chat_last_missing": "En son kullanılan ajan ({agent}) artık kullanılamıyor. Bir ajan seçin, ardından Yeniden dene'ye basın.",
"ui.agent_chat_left": "Sol",
"ui.agent_chat_limit": "Ajan, bir mesaj için {limit} değişiklik sınırına ulaştı. Devam etmesi için başka bir mesaj gönderin.",
"ui.agent_chat_login_found": "oturum bulundu",
@@ -2514,6 +2716,7 @@
"ui.agent_chat_remove": "Sıradan kaldır",
"ui.agent_chat_remove_file": "Bu iletiden çıkar",
"ui.agent_chat_remove_imported": "Bu iletiden çıkar; parça tasarımda kalır (Geri al onu kaldırır)",
"ui.agent_chat_retry": "Yeniden dene",
"ui.agent_chat_right": "Sağ",
"ui.agent_chat_save": "Kaydet",
"ui.agent_chat_send": "Gönder",
@@ -2526,6 +2729,7 @@
"ui.agent_chat_state_auth": "Oturum açılması gerekiyor",
"ui.agent_chat_state_busy": "Çalışıyor…",
"ui.agent_chat_state_exited": "Ajan sonlandı",
"ui.agent_chat_state_failed": "Bağlantı başarısız",
"ui.agent_chat_state_off": "Bağlı değil",
"ui.agent_chat_state_ready": "Hazır",
"ui.agent_chat_state_starting": "Başlatılıyor…",
@@ -2829,6 +3033,7 @@
"ui.fully_constrained": "Tam kısıtlı",
"ui.function": "Fonksiyon",
"ui.general": "Genel",
"ui.gpu_memory_lowered": "Ekran kartının belleği doldu: görünüm daha düşük kalitede çiziliyor.",
"ui.graphics": "Grafik",
"ui.graphics_custom": "Özel",
"ui.graphics_performance": "Performans",
@@ -2908,6 +3113,7 @@
"ui.heading_utilities": "ARAÇLAR",
"ui.heading_utility": "YARDIMCI ARAÇLAR",
"ui.heading_weldments": "KAYNAK",
"ui.height": "Yükseklik",
"ui.help": "Yardım",
"ui.hide": "Gizle",
"ui.hideAxes": "Eksenleri gizle",
@@ -2950,6 +3156,7 @@
"ui.language": "Dil",
"ui.layout_compact": "Kompakt",
"ui.layout_floating": "Kayan",
"ui.length": "Uzunluk",
"ui.length_decimals": "Uzunluk ondalık basamakları",
"ui.light": "Açık",
"ui.line": "Çizgi",
@@ -3048,6 +3255,7 @@
"ui.pinToShortcuts": "Kısayollara sabitle",
"ui.pinToToolbar": "Araç çubuğuna sabitle",
"ui.pipe": "Boru",
"ui.pitch": "Adım",
"ui.placement": "Yerleşim",
"ui.placement_handles": "Yerleşim tutamaçları",
"ui.placement_handles_tip": "Bir Dayama, Kabarıklık veya Kilit Geçme önizlemesindeki tutamaçlar: işaretçiyi model üzerinde hareket ettirmek için sürükleyin, halkasıyla döndürün",
@@ -3099,6 +3307,7 @@
"ui.render": "Render",
"ui.renderer": "Çizim motoru",
"ui.repeat": "Tekrarla",
"ui.repeat_nothing": "Henüz tekrarlanacak bir şey yok: önce bir araç veya diyalog başlatın.",
"ui.replace_with_link_done": "Kopyalar artık bağlı tasarımın yerleşimleri.",
"ui.report_a_bug": "Hata bildir",
"ui.reset": "Sıfırla",
@@ -3254,6 +3463,7 @@
"ui.visual_shaded_with_edges": "Kenarlarla gölgeli",
"ui.visual_style": "Görsel stil",
"ui.visual_wireframe": "Tel kafes",
"ui.width": "Genişlik",
"ui.window_system": "Pencere sistemi",
"ui.window_system_auto": "Otomatik",
"ui.window_system_wayland": "Wayland",
@@ -3321,5 +3531,6 @@
"web.open_link": "Bağlı tasarım açılsın mı?",
"web.open_link_confirm": "Kaydedilmemiş değişiklikler var. Bağlı tasarım yeni bir sekmede açılsın mı?",
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ seç · Enter / Tab tamamla · Esc kapat",
"↑ ↓ choose · Enter applies what you typed · Esc dismiss": "↑ ↓ seçin · Enter yazdığınızı uygular · Esc kapatır"
"↑ ↓ choose · Enter applies what you typed · Esc dismiss": "↑ ↓ seçin · Enter yazdığınızı uygular · Esc kapatır",
"⌘Enter continues on GitHub.": "⌘Enter ile GitHub'da devam edilir."
}
+11
View File
@@ -1382,7 +1382,9 @@
"nav.free_orbit.label": "Вільне обертання",
"nav.free_orbit.snap_help": "Mouse and 3D mouse rotate through both poles and preserve roll. Hold Shift during an orbit drag to snap the view direction and roll.",
"nav.fusion.help": "Середня панорамує, Shift+середня обертає, права обертає",
"nav.hfss.help": "Alt+ліва панорамує, Shift+Alt+ліва масштабує, Ctrl+ліва з порожнього місця обертає",
"nav.inventor.help": "Середня панорамує, Shift+середня обертає, Ctrl+середня масштабує, права обертає",
"nav.maya.help": "Alt+ліва обертає, Alt+середня панорамує, Alt+права масштабує; середня також панорамує",
"nav.openscad.help": "Ліва обертає по порожньому місцю, Shift+ліва виділяє рамкою, геометрію ескізу перетягують для редагування; права або середня панорамує, Shift+права або Shift+середня масштабує",
"nav.perspective.sketch": "Sketch editing uses orthographic view. Finish the sketch to switch perspective.",
"nav.solidworks.help": "Середня обертає, Ctrl+середня панорамує, Shift+середня масштабує, права обертає",
@@ -1406,6 +1408,11 @@
"no picture": "немає зображення",
"none": "немає",
"parts.automatic_name": "автоматично",
"parts.dimension.d": "Номінальний діаметр",
"parts.dimension.height": "Висота",
"parts.dimension.pitch": "Крок",
"parts.dimension.thickness": "Товщина",
"parts.dimension.width": "Ширина",
"pattern.alignment_2": "Вирівнювання 2",
"pattern.alignment_hint": "Кількість включає оригінал. Центрування розподіляє копії з обох боків; за парної кількості зміна напрямку визначає бік із додатковою копією.",
"pattern.direction_1": "Напрямок 1",
@@ -2906,6 +2913,7 @@
"ui.heading_utilities": "УТИЛІТИ",
"ui.heading_utility": "УТИЛІТА",
"ui.heading_weldments": "ЗВАРЮВАННЯ",
"ui.height": "Висота",
"ui.help": "Довідка",
"ui.hide": "Приховати",
"ui.hideAxes": "Приховати осі",
@@ -2948,6 +2956,7 @@
"ui.language": "Мова",
"ui.layout_compact": "Компактне",
"ui.layout_floating": "Плаваюче",
"ui.length": "Довжина",
"ui.length_decimals": "Знаки після коми для довжин",
"ui.light": "Світла",
"ui.line": "Пряма",
@@ -3046,6 +3055,7 @@
"ui.pinToShortcuts": "Закріпити в комбінаціях клавіш",
"ui.pinToToolbar": "Закріпити на панелі інструментів",
"ui.pipe": "Труба",
"ui.pitch": "Крок",
"ui.placement": "Розміщення",
"ui.placement_handles": "Placement handles",
"ui.placement_handles_tip": "Handles on the preview of a Rest, Boss or Snap Fit: drag the marker to move it across the model, turn it by its ring",
@@ -3252,6 +3262,7 @@
"ui.visual_shaded_with_edges": "Затінений із ребрами",
"ui.visual_style": "Стиль відображення",
"ui.visual_wireframe": "Каркас",
"ui.width": "Ширина",
"ui.window_system": "Window system",
"ui.window_system_auto": "Automatic",
"ui.window_system_wayland": "Wayland",
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(quy tắc đang dùng)",
"0 turns it off": "0: tắt tính năng này",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Mở bản nháp GitHub bên dưới, sau đó dán báo cáo đã sao chép vào bộ nhớ tạm.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Mở bản nháp GitHub bên dưới. Tiêu đề và báo cáo sẽ được tự động điền.",
@@ -51,16 +52,20 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "Hãy áp dụng vật liệu bề mặt trước. Tệp xuất sẽ gồm các vật liệu bề mặt đã gán và vật liệu được tạo trong thiết kế này.",
"Arc length": "Chiều dài cung tròn",
"Area": "Diện tích",
"As Picked": "Theo lựa chọn",
"As-Built": "Như đã lắp",
"Assign Rule": "Gán quy tắc",
"Attachment": "Mối liên kết",
"BLEND SURFACE": "MẶT NỐI MƯỢT",
"BOUNDARY SURFACE": "BỀ MẶT BIÊN DẠNG",
"BROWSER": "CÂY ĐỐI TƯỢNG",
"Ball": "Cầu",
"Bar": "Thép thanh",
"Base Center": "Tâm đáy",
"Base Height": "Chiều cao đế",
"Bend": "Góc uốn",
"Bend Edges": "Cạnh uốn gập",
"Bend Line": "Đường uốn",
"Bend Line Position": "Vị trí đường chấn",
"Bend Position": "Vị trí chấn",
"Bend Radius": "Bán kính chấn uốn",
@@ -72,6 +77,7 @@
"Body (last if none)": "Khối (mặc định lấy khối cuối nếu để trống)",
"Body to split": "Khối cần phân tách",
"Body, or faces to take out": "Khối, hoặc các mặt cần loại bỏ",
"Both": "Cả hai",
"Bottom Left": "Dưới cùng bên trái",
"Bottom Middle": "Dưới cùng ở giữa",
"Bottom Right": "Dưới cùng bên phải",
@@ -103,6 +109,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "Chọn một mặt phẳng mới. Hình học và kích thước phác thảo được giữ nguyên trong hệ tọa độ 2D.",
"Choose…": "Chọn…",
"Circle center": "Tâm đường tròn",
"Circle or sphere": "Đường tròn hoặc khối cầu",
"Circular": "Tròn",
"Circumference": "Chu vi",
"Clockwise": "Theo chiều kim đồng hồ",
@@ -119,6 +126,7 @@
"Config Table": "Bảng cấu hình",
"Configuration": "Cấu hình",
"Configuration rules": "Quy tắc cấu hình",
"Constant radius": "Bán kính không đổi",
"Contact": "Tiếp xúc",
"Contact Sets": "Tập hợp tiếp xúc",
"Contact sets": "Tập hợp tiếp xúc",
@@ -154,7 +162,9 @@
"Custom": "Tùy chỉnh",
"Customize Toolbar": "Tùy biến thanh công cụ",
"Customize…": "Tùy chỉnh…",
"Cylindrical": "Trụ",
"Cylindrical face": "Mặt trụ",
"Deboss": "Dập chìm (Deboss)",
"Delete": "Xóa",
"Delete Folders and Features…": "Xóa thư mục cùng các tính năng…",
"Delete Selected Features…": "Xóa các tính năng đã chọn…",
@@ -186,6 +196,7 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Kéo để xoay gờ đỡ theo từng bước 5°. Giữ phím Alt hoặc Ctrl để xoay tự do.",
"Drive Joint": "Dẫn động khớp nối",
"Duration": "Thời lượng",
"Edge": "Cạnh",
"Edges": "Các cạnh",
"Edit": "Sửa",
"Edit Profile Sketch": "Chỉnh sửa phác thảo biên dạng",
@@ -194,6 +205,7 @@
"End Radius": "Bán kính kết thúc",
"End bulge": "Độ phình cuối",
"End continuity": "Độ liên tục cuối",
"Equal Distance": "Khoảng cách bằng nhau",
"Expand": "Mở rộng",
"Expected result (optional)": "Kết quả mong muốn (tùy chọn)",
"Explode": "Phân rã",
@@ -221,6 +233,8 @@
"Faces": "Các bề mặt",
"Faces / edges / vertices": "Bề mặt / Cạnh / Đỉnh",
"Faces to split": "Các mặt cần phân tách",
"Faces/Body": "Bề mặt/Thân",
"Factor must be a positive number": "Hệ số phải là một số dương",
"Fastener": "Chi tiết kẹp chặt",
"Favorites": "Yêu thích",
"Favourite": "Yêu thích",
@@ -230,9 +244,12 @@
"Filter…": "Bộ lọc…",
"Find in Browser": "Tìm trong cây đối tượng",
"Finish": "Hoàn tất",
"First edge": "Cạnh thứ nhất",
"First plane": "Mặt phẳng thứ nhất",
"First point": "Điểm thứ nhất",
"Fit and G2 corners require Constant radius.": "Kiểu khớp và góc bo G2 yêu cầu Bán kính không đổi.",
"Fixed Face": "Mặt cố định",
"Flange Gap": "Khe hở mép gập",
"Flange thickness": "Độ dày cánh (flange)",
"Flanges": "Gờ viền (Flanges)",
"Flat Pattern": "Bản khai triển phẳng",
@@ -240,8 +257,10 @@
"Follow camera (Look At sketches)": "Đi theo camera (Nhìn vuông góc phác thảo)",
"Follow the camera (Look At sketches)": "Đi theo camera (Nhìn vuông góc phác thảo)",
"Font": "Phông chữ",
"Free Move": "Di chuyển tự do",
"From": "Điểm bắt đầu",
"From Bodies": "Từ thân khối",
"From Snap": "Từ điểm bắt",
"From edges": "Từ các cạnh",
"Full Length": "Toàn bộ chiều dài",
"Full thread depth": "Toàn bộ chiều sâu ren",
@@ -253,10 +272,13 @@
"Halo under sketch curves": "Vầng sáng dưới đường cong phác thảo",
"Height": "Chiều cao",
"Height From": "Chiều cao tính từ",
"Hem Gap": "Khe hở mép viền",
"Hidden edges": "Nét khuất",
"History layout": "Bố cục lịch sử",
"History names": "Tên trong lịch sử",
"Hole (optional)": "Lỗ (tùy chọn)",
"Hole Depth": "Độ sâu lỗ",
"Hole Diameter": "Đường kính lỗ",
"Holes": "Lỗ",
"Holes (edges on them)": "Lỗ (các cạnh trên lỗ)",
"Home view": "Góc nhìn chuẩn (Home)",
@@ -279,12 +301,16 @@
"Issue title": "Tiêu đề vấn đề",
"Items": "Các mục",
"JOINTS": "KHỚP NỐI",
"Joint 1": "Khớp 1",
"Joint 2": "Khớp 2",
"Joint Origin1": "Gốc khớp nối 1",
"K Factor": "Hệ số K",
"Keep (points on it)": "Giữ lại (phía có các điểm)",
"Keep Tools": "Giữ lại công cụ cắt",
"Keep of the other surface": "Giữ phần của bề mặt kia",
"Key a joint's value at this step": "Khóa giá trị khớp nối tại bước này",
"Keys": "Khóa / Phím",
"Knife Edge": "Cạnh sắc",
"L-Angle": "Thép góc chữ L",
"LIBRARY": "THƯ VIỆN",
"LINKS": "LIÊN KẾT",
@@ -297,9 +323,11 @@
"Letter Spacing": "Khoảng cách chữ",
"Library": "Thư viện",
"Library file": "Tệp thư viện",
"Library response is missing": "Thiếu phản hồi từ thư viện",
"Limits": "Giới hạn",
"Line Spacing": "Khoảng cách dòng",
"Line Type": "Kiểu đường",
"Line on plane": "Đường thẳng trên mặt phẳng",
"Lines": "Các đoạn thẳng",
"Listing the installed fonts…": "Đang liệt kê các phông chữ đã cài đặt…",
"Load library": "Tải thư viện",
@@ -319,11 +347,14 @@
"Material Outside": "Vật liệu bên ngoài",
"Material copied. Existing body assignments are unchanged.": "Đã sao chép vật liệu. Các gán vật liệu cho khối hiện có không đổi.",
"Max": "Tối đa",
"Max Thickness": "Độ dày tối đa",
"Maximum": "Tối đa",
"Mesh body": "Khối lưới (Mesh)",
"Mid Radius": "Bán kính giữa",
"Middle double-click": "Nhấp đúp chuột giữa",
"Min": "Tối thiểu",
"Min Draft": "Độ côn tối thiểu",
"Min Thickness": "Độ dày tối thiểu",
"Minimum": "Tối thiểu",
"Mirror Plane": "Mặt phẳng đối xứng",
"Mitre": "Góc vát chéo (Mitre)",
@@ -343,6 +374,7 @@
"Name": "Tên",
"Name on import": "Tên khi nhập",
"Nearest": "Gần nhất",
"Neutral plane": "Mặt phẳng trung hòa",
"New": "Mới",
"New Comp.": "Chi tiết mới",
"New Sketch": "Phác thảo mới",
@@ -353,6 +385,7 @@
"No matching appearances": "Không có màu sắc/vật liệu phù hợp",
"No matching physical materials.": "Không tìm thấy vật liệu vật lý phù hợp.",
"No visible bodies or sketches to export.": "Không có thân khối hoặc phác thảo hiển thị nào để xuất.",
"Nominal Radius": "Bán kính danh định",
"Nominal diameter": "Đường kính danh nghĩa",
"None": "Không có",
"Not available yet": "Chưa khả dụng",
@@ -381,22 +414,28 @@
"Overall length": "Chiều dài tổng thể",
"Param. Graph": "Đồ thị tham số",
"Parameter": "Tham số",
"Part length must be greater than zero and at most 2000 mm": "Chiều dài chi tiết phải lớn hơn 0 và tối đa 2000 mm",
"Parts": "Chi tiết",
"Pass through": "Đi xuyên qua",
"Path": "Đường dẫn",
"Pattern": "Mảng",
"Per Edge": "Theo từng cạnh",
"Physical material definitions": "Định nghĩa vật liệu vật lý",
"Pick a part size": "Chọn một kích thước chi tiết",
"Pick the tool bodies": "Chọn các thân khối làm công cụ cắt",
"Picked": "Đã chọn",
"Picked point": "Điểm đã chọn",
"Pin-slot": "Chốt-rãnh",
"Pitch": "Bước ren",
"Pivot": "Điểm tựa xoay / Trục quay",
"Place at the origin instead": "Đặt tại gốc tọa độ",
"Planar": "Phẳng",
"Plastic Rules": "Quy tắc nhựa",
"Play the joint's motion in the view": "Mô phỏng chuyển động khớp nối trong vùng nhìn",
"Playback": "Phát lại",
"Plot": "Vẽ đồ thị",
"Point on line": "Điểm trên đường thẳng",
"Point on plane": "Điểm trên mặt phẳng",
"Position": "Vị trí",
"Position (0 to 1)": "Vị trí (0 đến 1)",
"Position (G0)": "Vị trí liên tục (G0)",
@@ -409,6 +448,7 @@
"Profiles or curves": "Các biên dạng hoặc đường cong",
"Profiles/Curves": "Biên dạng / Đường cong",
"Quantity": "Số lượng",
"Quantity must be at least 2": "Số lượng phải từ 2 trở lên",
"RECENT": "GẦN ĐÂY",
"REFERENCE": "THAM CHIẾU",
"RULED SURFACE": "MẶT KẺ (RULED SURFACE)",
@@ -422,6 +462,8 @@
"Rectangular": "Hình chữ nhật",
"Rectangular Tube": "Thép hộp chữ nhật",
"Reference face": "Bề mặt tham chiếu",
"Relief Depth": "Độ sâu rãnh thoát",
"Relief Width": "Chiều rộng rãnh thoát",
"Remove Tools": "Loại bỏ công cụ cắt",
"Remove condition": "Xóa điều kiện",
"Remove from Folder": "Loại khỏi thư mục",
@@ -450,6 +492,7 @@
"Restore this studio's tools": "Khôi phục các công cụ của studio này",
"Result": "Kết quả",
"Retake screenshot": "Chụp lại màn hình",
"Reveal Height": "Chiều cao bậc",
"Reverse": "Đảo chiều",
"Reverse Direction": "Đảo ngược hướng",
"Revert": "Hoàn nguyên",
@@ -458,12 +501,15 @@
"Revert Position": "Hoàn nguyên vị trí",
"Review the report and screenshot before opening GitHub.": "Xem lại báo cáo và ảnh chụp màn hình trước khi mở GitHub.",
"Review your report on GitHub and click Submit new issue to publish it.": "Kiểm tra lại báo cáo của bạn trên GitHub và nhấp 'Submit new issue' để phát hành.",
"Revolute": "Xoay",
"Rib Length": "Chiều dài gân tăng cứng",
"Rib Offset": "Độ lệch gân tăng cứng",
"Rib Thickness": "Độ dày gân tăng cứng",
"Ribs": "Gân tăng cứng",
"Right Middle": "Ở giữa bên phải",
"Rigid": "Cứng",
"Rim Edge": "Cạnh mép vành",
"Rim face": "Mặt vành",
"Ring of tools on the right button": "Vòng tròn công cụ khi giữ chuột phải",
"Roll Back Here": "Lùi lịch sử về đây",
"Roll History Marker Here": "Cuộn mốc lịch sử tới đây",
@@ -488,16 +534,28 @@
"Search": "Tìm kiếm",
"Search commands": "Tìm kiếm lệnh",
"Search this library": "Tìm trong thư viện này",
"Second edge": "Cạnh thứ hai",
"Second plane": "Mặt phẳng thứ hai",
"Second point": "Điểm thứ hai",
"Section": "Mặt cắt",
"Section (optional)": "Mặt cắt (tùy chọn)",
"Section position": "Vị trí mặt cắt",
"Sections (one sketch each)": "Các mặt cắt (mỗi mặt cắt một phác thảo)",
"Select Other": "Chọn đối tượng khác",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "Chọn đối tượng khác: giữ nút chuột trái đứng yên trên mô hình (hoặc nhấp chuột phải › Chọn đối tượng khác…) để liệt kê mọi đối tượng dưới con trỏ; nhấp lại vào cùng vị trí đó để chọn đối tượng kế tiếp. Nhấp đúp chuột giữa để về Góc nhìn chuẩn (Tùy chọn cài đặt › Điều hướng).",
"Select Same Look": "Chọn cùng diện mạo",
"Select bodies (a face picks its body)": "Chọn thân khối (chọn một mặt sẽ chọn cả thân khối)",
"Select bodies or faces instead": "Chọn thân khối hoặc bề mặt thay thế",
"Select edges": "Chọn các cạnh",
"Select points of the sketch being edited": "Chọn các điểm của phác thảo đang chỉnh sửa",
"Select the centre the pattern turns around first": "Hãy chọn tâm mà mảng xoay quanh trước",
"Select the curves to offset first": "Hãy chọn các đường cong cần offset trước",
"Select the mirror line": "Chọn đường đối xứng",
"Select the sketch curves or points to mirror first": "Hãy chọn các đường cong hoặc điểm phác thảo cần đối xứng trước",
"Select the sketch curves or points to move first": "Hãy chọn các đường cong hoặc điểm phác thảo cần di chuyển trước",
"Select the sketch curves or points to pattern first": "Hãy chọn các đường cong hoặc điểm phác thảo cần tạo mảng trước",
"Select the sketch curves or points to scale first": "Hãy chọn các đường cong hoặc điểm phác thảo cần thay đổi tỷ lệ trước",
"Select the sketch curves or points to transform first": "Hãy chọn các đường cong hoặc điểm phác thảo cần biến đổi trước",
"Selection filter": "Bộ lọc chọn đối tượng",
"Semantic faces share their appearance across instances.": "Các bề mặt ngữ nghĩa dùng chung màu sắc bề mặt giữa các bản thể.",
"Send your report on GitHub": "Gửi báo cáo của bạn trên GitHub",
@@ -517,9 +575,12 @@
"Sketch geometry and profiles": "Hình học và biên dạng phác thảo",
"Sketch plane has no body-face attachment.": "Mặt phẳng phác thảo không có liên kết với bề mặt thân khối.",
"Sketch points": "Điểm phác thảo",
"Slider": "Trượt",
"Slot width": "Bề rộng rãnh then",
"Snap to face and edge centres": "Bắt vào tâm mặt và tâm cạnh",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft đã đóng trước khi các thiết kế này được lưu. Bạn có thể mở bản tự động lưu gần nhất của chúng.",
"Spacing 2 must be a non-zero number": "Khoảng cách 2 phải là một số khác 0",
"Spacing must be a non-zero number": "Khoảng cách phải là một số khác 0",
"Specialise": "Chuyên biệt hóa",
"Speed": "Tốc độ",
"Splitting tool": "Công cụ cắt chia",
@@ -530,6 +591,7 @@
"Start angle": "Góc bắt đầu",
"Start bulge": "Độ phình đầu",
"Start continuity": "Độ liên tục đầu",
"Stationary Side": "Phía cố định",
"Step": "Bước",
"Steps": "Các bước",
"Steps to reproduce (optional)": "Các bước tái hiện (tùy chọn)",
@@ -544,6 +606,7 @@
"Suppressed": "Bị tạm nén",
"Surface": "Bề mặt",
"Surface, or faces to turn over": "Mặt cong, hoặc các mặt cần lật hướng",
"Surfaces": "Các bề mặt",
"Swap Ends": "Hoán đổi hai đầu",
"TRIM": "CẮT XÉN",
"Tangent": "Tiếp tuyến",
@@ -554,24 +617,34 @@
"Tap drill diameter": "Đường kính mũi khoan taro",
"Target": "Mục tiêu",
"Target Body": "Khối mục tiêu",
"Target Face (optional)": "Mặt đích (tùy chọn)",
"Tear": "Xé rách mép chấn",
"Technical details": "Chi tiết kỹ thuật",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "Phác thảo nét đứt là đường dẫn mặt phẳng đã lưu. Hãy chọn một bề mặt mới để sửa lại liên kết.",
"The design changed. Reopen Change Part Size for the component.": "Thiết kế đã thay đổi. Hãy mở lại Change Part Size cho thành phần này.",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "Hướng phải là một trục hoặc một đường cong phác thảo thẳng nằm trong mặt phẳng phác thảo",
"The mirror line cannot also be mirrored": "Đường đối xứng không thể đồng thời được lấy đối xứng",
"The mirror line must be a straight curve of this sketch, not an origin axis": "Đường đối xứng phải là một đường cong thẳng của phác thảo này, không phải trục gốc",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "Bản thể tác giả đã lưu bị thiếu. Hãy chọn một vị trí tác giả hợp lệ trước khi gán lại.",
"Then": "Thì",
"These features will be deleted:": "Các tính năng sau sẽ bị xóa:",
"These features will fail:": "Các tính năng này sẽ bị lỗi:",
"Thickness Outside": "Độ dày hướng ra ngoài",
"Thickness Variation": "Biến thiên độ dày",
"Thin": "Thành mỏng",
"Thin Extrude": "Đùn thành mỏng",
"Third plane": "Mặt phẳng thứ ba",
"Third point": "Điểm thứ ba",
"This child is shared. Deleting it removes it from every copy of its parent.": "Đối tượng con này được dùng chung. Việc xóa nó sẽ xóa khỏi mọi bản sao của đối tượng cha.",
"This child is shared. Position changes apply to every copy of its parent.": "Đối tượng con này được dùng chung. Thay đổi vị trí sẽ áp dụng cho mọi bản sao của đối tượng cha.",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "Bề mặt này không thể tạo liên kết bền vững. Hãy chọn bề mặt khác hoặc sử dụng mặt phẳng cố định.",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "Ảnh này chưa được đính kèm vào GitHub. Vui lòng sao chép hoặc lưu ảnh, sau đó đính kèm lên GitHub.",
"Thread depth": "Chiều sâu ren",
"Thread diameter": "Đường kính ren",
"Through point": "Qua điểm",
"To": "Đến",
"To Offset": "Tới khoảng dời (Offset)",
"To Snap": "Đến điểm bắt",
"To edges": "Đến các cạnh",
"Toe radius": "Bán kính mép cánh",
"Tolerance": "Dung sai",
@@ -585,6 +658,7 @@
"Trimming tool (plane, face or curves)": "Công cụ cắt (mặt phẳng, bề mặt hoặc đường cong)",
"Turn off section analysis before exporting the view.": "Tắt phân tích mặt cắt trước khi xuất khung nhìn.",
"Type": "Kiểu",
"Type a distance or an angle to move by": "Nhập khoảng cách hoặc góc để di chuyển",
"UNTRIM": "HỦY CẮT TỈA (UNTRIM)",
"Unit": "Đơn vị",
"Unsuppress": "Kích hoạt lại (Unsuppress)",
@@ -629,6 +703,17 @@
"Z angle": "Góc Z",
"Z distance": "Khoảng cách Z",
"Zebra": "Sọc vằn",
"`joint` must be an id or a name": "`joint` phải là một id hoặc một tên",
"`params` must be an object": "`params` phải là một đối tượng",
"`values` must be a list": "`values` phải là một danh sách",
"a chamfer needs a corner of exactly two lines": "vát cạnh cần một góc gồm đúng hai đường thẳng",
"a file operation is in progress": "một thao tác tệp đang được thực hiện",
"a picked curve is no longer in a sketch": "một đường cong đã chọn không còn nằm trong phác thảo nào",
"a picked curve's sketch has not been solved": "phác thảo của một đường cong đã chọn chưa được giải",
"a picked edge has no points": "một cạnh đã chọn không có điểm nào",
"a picked edge is gone": "một cạnh đã chọn không còn nữa",
"a picked edge's body is gone": "thân của một cạnh đã chọn không còn nữa",
"add a key for a joint first": "hãy thêm một khóa cho khớp trước",
"ai.connected_toast": "SolidCraft hiện đã sẵn sàng trong {clients}. Khởi động lại ứng dụng để sử dụng (Cài đặt > Trợ lý ảo).",
"ai.prefs.allow_control": "Cho phép AI agent kết nối (kênh điều khiển / MCP)",
"ai.prefs.allow_control_note": "Mở kênh điều khiển chỉ trên máy tính này (127.0.0.1, cổng 27878 hoặc cổng trống tiếp theo). Chương trình kết nối phải xuất trình mã token bảo mật chỉ tài khoản người dùng của bạn đọc được, được tạo mới mỗi lần khởi động. Có hiệu lực vào lần khởi động tiếp theo của SolidCraft. Khi tắt: không lắng nghe trừ khi bạn bật.",
@@ -669,6 +754,7 @@
"appearance.pbr_opaque": "PBR không trong suốt",
"appearance.roughness": "Độ nhám bề mặt",
"appearance.surface_response": "Phản hồi bề mặt",
"bom.group_children": "Chi tiết con trong hàng của chi tiết cha",
"browser.body_name": "Thân khối{number}",
"browser.calibrate_title": "Hiệu chuẩn: {name}",
"browser.capture_many": "{count} chi tiết đã được di chuyển nhưng vị trí chưa được ghi lại.",
@@ -679,6 +765,8 @@
"browser.move_title": "Di chuyển: {name}",
"browser.parameters": "Bảng tham số ({count})",
"browser.precision": "Độ chính xác: {precision}",
"browser.sketch_attachment_lost": "{name} (mất liên kết)",
"browser.sketch_editing": "{name} (đang sửa)",
"browser.sketch_name": "Phác thảo{number}",
"browser.units": "Đơn vị: {units}",
"cam.flat": "Bề mặt phẳng",
@@ -688,7 +776,13 @@
"cam.roller": "Con lăn cam",
"cam.roller_pick": "Con lăn cam (tùy chọn)",
"cam.tip_pick": "Đầu tiếp xúc cam (tùy chọn)",
"choose a profile": "chọn một biên dạng",
"choose the cam's and the follower's joints": "chọn khớp của cam và khớp của cần đẩy",
"choose the joints to couple": "chọn các khớp cần ghép nối",
"click a plane or planar face": "nhấp vào một mặt phẳng hoặc bề mặt phẳng",
"click sketch curves": "nhấp vào các đường cong phác thảo",
"cmd.appearance_assign": "Vẻ ngoài / Màu sắc",
"cmd.appearance_chain": "Chuỗi diện mạo",
"cmd.appearance_library": "Thư viện màu sắc bề mặt",
"cmd.appearance_list": "Danh sách màu sắc bề mặt",
"cmd.appearance_paint": "Tô diện mạo",
@@ -1073,6 +1167,9 @@
"cmd.timeline_roll_to": "Cuộn mốc lịch sử",
"cmd.timeline_rollback": "Di chuyển con trỏ lịch sử thiết kế",
"cmd.timeline_suppress": "Tạm nén tính năng",
"cmd.view.render_browser": "Trình duyệt kết xuất",
"cmd.view.render_dock": "Di chuyển neo kết xuất",
"cmd.view.render_focus": "Chế độ xem tập trung kết xuất",
"cmd.view_ambient_occlusion": "Đổ bóng che khuất môi trường (AO)",
"cmd.view_apply": "Áp dụng góc nhìn đã lưu",
"cmd.view_back": "Góc nhìn phía sau",
@@ -1183,6 +1280,8 @@
"dxf.progress.write": "Đang ghi tệp DXF (5/5)",
"dxf.tolerance": "Dung sai đường cong",
"dxf.tolerance_help": "Chỉ áp dụng cho các thân khối và phác thảo hiển thị. Đường cong sử dụng các đoạn thẳng. Dung sai nhỏ hơn cho đường cong mịn hơn nhưng tốn nhiều thời gian và bộ nhớ hơn.",
"each rail's curves must be in one sketch": "các đường cong của mỗi đường dẫn hướng phải nằm trong cùng một phác thảo",
"feature computation ended without a result": "việc tính toán đặc trưng kết thúc mà không có kết quả",
"file.open.drawing_filter": "Thiết kế, tệp CAD, lưới đa giác và bản vẽ",
"file_load.built": "Đã dựng được: {built} trên {total} tính năng.",
"file_load.converting": "Đang chuyển đổi khối đặc {done} trên {total}",
@@ -1344,6 +1443,8 @@
"keymap.command_id": "Mã lệnh",
"keymap.empty": "Không có lệnh phù hợp",
"keymap.use_anyway": "Vẫn dùng {key} tại đây",
"label.move_to_left_side": "Chuyển sang bên trái",
"label.move_to_right_side": "Chuyển sang bên phải",
"manage.appearance_hint": "Chọn một kiểu hiển thị cho phần đã chọn, hoặc kéo một mẫu màu thả lên thân khối hay bề mặt.",
"manage.assign_hint": "Chọn các thân khối và chọn quy tắc thiết kế nhựa cho chúng.",
"manage.config_hint": "Sửa các hàng, cột và quy tắc cấu hình, rồi kích hoạt hoặc xem trước một hàng.",
@@ -1428,7 +1529,9 @@
"nav.free_orbit_upright.help": "Kéo chuột sang ngang sẽ xoay mô hình quanh trục thẳng đứng của không gian; kéo lên và xuống sẽ nghiêng qua đỉnh mà không bị giới hạn.",
"nav.free_orbit_upright.label": "Xoay quanh trục thẳng đứng",
"nav.fusion.help": "Kéo chuột giữa để trượt, Shift + chuột giữa để xoay, kéo chuột phải để xoay",
"nav.hfss.help": "Alt+kéo chuột trái để trượt, Shift+Alt+chuột trái để thu phóng, Ctrl+kéo chuột trái từ vùng trống để xoay",
"nav.inventor.help": "Kéo chuột giữa để trượt, Shift + chuột giữa để xoay, Ctrl + chuột giữa để thu phóng, kéo chuột phải để xoay",
"nav.maya.help": "Alt+kéo chuột trái để xoay, Alt+chuột giữa để trượt, Alt+chuột phải để thu phóng; kéo chuột giữa cũng trượt",
"nav.openscad.help": "Kéo chuột trái trên vùng trống để xoay, Shift + chuột trái để quét chọn vùng, kéo hình học phác thảo để chỉnh sửa; kéo chuột phải hoặc chuột giữa để trượt, Shift + kéo chuột phải hoặc chuột giữa để thu phóng",
"nav.perspective.sketch": "Chế độ chỉnh sửa phác thảo sử dụng góc nhìn trực giao. Hãy hoàn tất phác thảo để chuyển sang góc nhìn phối cảnh.",
"nav.solidworks.help": "Kéo chuột giữa để xoay, Ctrl + chuột giữa để trượt, Shift + chuột giữa để thu phóng, kéo chuột phải để xoay",
@@ -1439,6 +1542,93 @@
"nav.touchpad.pan": "Dời góc nhìn (giữ Shift và di chuyển; không cần nhấn chuột)",
"nav.touchpad.scroll": "Bàn rê cảm ứng dùng thao tác cuộn dọc để thu phóng. Cài đặt dời góc nhìn bằng hai ngón tay được giữ cho các cấu hình khác.",
"nav.touchpad.zoom": "Thu phóng (cuộn dọc hoặc chụm ngón tay)",
"navbar.agent_chat": "Bảng trò chuyện của trợ lý",
"navbar.agent_cursor": "Hiện con trỏ tác tử",
"navbar.ambient_occlusion": "Đổ bóng che khuất môi trường (AO)",
"navbar.assistant": "Trợ lý",
"navbar.custom.add_slot": "Thêm {slot}",
"navbar.custom.always": "Luôn hiện",
"navbar.custom.available": "{available} · kéo vào thanh hoặc nhấn Thêm",
"navbar.custom.buttons": "Nút",
"navbar.custom.compact": "Gọn",
"navbar.custom.count": "{count}/16 ô",
"navbar.custom.customise": "Tùy chỉnh thanh điều hướng…",
"navbar.custom.design": "Thiết kế",
"navbar.custom.duplicate": "Ô này đã có trên thanh.",
"navbar.custom.fade": "Mờ dần",
"navbar.custom.full": "Hãy xóa một ô để thêm ô khác.",
"navbar.custom.hidden_design": "Ẩn trong Thiết kế",
"navbar.custom.hidden_render": "Ẩn trong Kết xuất",
"navbar.custom.hide": "Ẩn thanh điều hướng",
"navbar.custom.hide_idle": "Ẩn cho đến khi rê chuột",
"navbar.custom.icon_only": "Chỉ biểu tượng",
"navbar.custom.icon_value": "Biểu tượng và giá trị",
"navbar.custom.icons": "Biểu tượng",
"navbar.custom.idle": "Khi không dùng",
"navbar.custom.intro": "Chọn các điều khiển trên thanh ở cuối khung nhìn 3D và thứ tự của chúng. Kéo một ô để di chuyển, hoặc kéo ra khỏi thanh để xóa.",
"navbar.custom.labels": "Biểu tượng và nhãn",
"navbar.custom.left": "Chuyển sang trái",
"navbar.custom.position": "Vị trí",
"navbar.custom.position_centre": "Giữa",
"navbar.custom.position_left": "Trái",
"navbar.custom.position_right": "Phải",
"navbar.custom.preview_as": "Xem trước ở chế độ",
"navbar.custom.regular": "Thường",
"navbar.custom.remove": "Xóa",
"navbar.custom.remove_bar": "Xóa khỏi thanh",
"navbar.custom.render": "Kết xuất",
"navbar.custom.reset": "Đặt lại thanh điều hướng",
"navbar.custom.reset_default": "Đặt lại mặc định",
"navbar.custom.right": "Chuyển sang phải",
"navbar.custom.select": "Chưa chọn ô nào. Hãy chọn một ô trên thanh để di chuyển, xóa hoặc đổi cách hiển thị.",
"navbar.custom.separators_full": "Thanh đã có bốn dải phân cách.",
"navbar.custom.show": "Hiện thanh điều hướng",
"navbar.custom.shows": "Hiển thị",
"navbar.custom.size": "Kích thước",
"navbar.custom.stale": "Thanh đã thay đổi. Hãy chọn lại ô.",
"navbar.custom.title": "Thanh điều hướng",
"navbar.custom.unknown": "Ô này không khả dụng.",
"navbar.description.ambient_occlusion": "Làm tối các nếp gấp và góc để tạo chiều sâu.",
"navbar.description.display": "Chứa các cài đặt hiển thị: mẫu đồ họa, lưới, bóng đổ mặt sàn, đổ bóng che khuất môi trường và phép chiếu.",
"navbar.description.fit": "Đưa vùng chọn vào khung nhìn, hoặc toàn bộ mô hình nếu chưa chọn gì.",
"navbar.description.grid": "Hiện hoặc ẩn lưới mặt sàn.",
"navbar.description.ground_shadow": "Hiện hoặc ẩn bóng bên dưới mô hình.",
"navbar.description.home": "Quay về góc nhìn đẳng cự của toàn bộ mô hình.",
"navbar.description.look_at": "Xoay góc nhìn về phía mặt, mặt phẳng hoặc bản phác đang mở đã chọn.",
"navbar.description.orbit": "Xoay góc nhìn quanh mô hình.",
"navbar.description.pan": "Trượt góc nhìn sang ngang, lên hoặc xuống.",
"navbar.description.projection": "Chuyển giữa chế độ trực giao và phối cảnh.",
"navbar.description.separator": "Một đường mảnh nhóm các ô liền kề.",
"navbar.description.spin": "Giữ cho góc nhìn tiếp tục xoay cho đến khi bạn nhấp chuột hoặc nhấn phím.",
"navbar.description.visual_style": "Đổi cách vẽ mô hình: tô bóng, khung dây hoặc có cạnh ẩn.",
"navbar.description.zoom": "Đưa góc nhìn lại gần hoặc ra xa mô hình.",
"navbar.display": "Hiển thị",
"navbar.fit": "Vừa khung nhìn",
"navbar.graphics": "Đồ họa",
"navbar.grid": "Lưới tọa độ",
"navbar.ground_shadow": "Bóng đổ mặt sàn",
"navbar.home": "Góc nhìn chuẩn",
"navbar.later": "Sau",
"navbar.look_at": "Nhìn vào",
"navbar.more": "Thêm",
"navbar.orbit": "Xoay góc nhìn",
"navbar.orthographic": "Trực giao",
"navbar.pan": "Trượt góc nhìn",
"navbar.perspective": "Phối cảnh",
"navbar.preset": "Mẫu thiết lập sẵn",
"navbar.projection": "Phép chiếu",
"navbar.projection_heading": "Phép chiếu",
"navbar.separator": "Dải phân cách",
"navbar.show": "Hiển thị",
"navbar.spin": "Xoay liên tục",
"navbar.style.shaded": "Tô bóng",
"navbar.style.shaded_with_edges": "Tô bóng có cạnh",
"navbar.style.shaded_with_hidden_edges": "Tô bóng có cạnh ẩn",
"navbar.style.wireframe": "Khung dây",
"navbar.translucent": "Bán trong suốt",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "Kiểu hiển thị trực quan",
"navbar.zoom": "Thu phóng",
"needs two joints": "cần hai khớp nối",
"network.allow_once": "Cho phép một lần",
"network.always_allow": "Luôn cho phép máy chủ này",
@@ -1449,9 +1639,34 @@
"no hole": "không có lỗ",
"no interference": "không có giao thoa",
"no joint that moves yet": "chưa có khớp nối nào có thể chuyển động",
"no motion study yet": "chưa có nghiên cứu chuyển động",
"no picture": "không có ảnh",
"no such joint": "không có khớp này",
"none": "không có",
"not a move": "không phải một phép di chuyển",
"not a number": "không phải là số",
"open a sketch first": "hãy mở một phác thảo trước",
"parts.automatic_name": "tự động",
"parts.dimension.across_flats": "Cỡ cờ lê",
"parts.dimension.bore": "Đường kính lỗ",
"parts.dimension.d": "Đường kính danh nghĩa",
"parts.dimension.head_diameter": "Đường kính đầu",
"parts.dimension.head_height": "Chiều cao đầu",
"parts.dimension.height": "Chiều cao",
"parts.dimension.inner": "Đường kính trong",
"parts.dimension.outer": "Đường kính ngoài",
"parts.dimension.pitch": "Bước ren",
"parts.dimension.socket": "Cỡ lục giác",
"parts.dimension.socket_depth": "Độ sâu lục giác",
"parts.dimension.thickness": "Độ dày",
"parts.dimension.width": "Bề rộng",
"parts.family.bearing": "Ổ bi cầu rãnh sâu (bao ngoài)",
"parts.family.dowel_pin": "Chốt trụ",
"parts.family.hex_bolt": "Bu lông đầu lục giác",
"parts.family.hex_nut": "Đai ốc lục giác",
"parts.family.set_screw": "Vít trí lục giác chìm, đầu bằng",
"parts.family.socket_head_cap_screw": "Bu lông lục giác chìm đầu trụ",
"parts.family.washer": "Vòng đệm phẳng",
"pattern.alignment_2": "Căn chỉnh 2",
"pattern.alignment_hint": "Số lượng bao gồm cả bản gốc. Căn giữa sẽ cân bằng các bản sao; Đổi hướng sẽ chọn phía bổ sung cho tổng số chẵn.",
"pattern.direction_1": "Hướng 1",
@@ -1467,9 +1682,25 @@
"perf.ui_time": "Thời gian giao diện",
"perf.viewport": "Khung nhìn",
"perf.worst": "Tệ nhất",
"pick a body or some of its faces": "chọn một thân hoặc một số mặt của thân",
"pick a hole to seat it, or OK places it at the origin": "chọn một lỗ để lắp đặt, hoặc nhấn OK để đặt tại gốc tọa độ",
"pick a planar face": "chọn một mặt phẳng",
"pick a plane or a face as the tool": "chọn một mặt phẳng hoặc một mặt làm dụng cụ",
"pick a size": "chọn một kích thước",
"pick edges of a body": "chọn các cạnh của một thân",
"pick edges of one body": "chọn các cạnh của cùng một thân",
"pick edges of the holes to remove": "chọn các cạnh của những lỗ cần loại bỏ",
"pick faces of one body": "chọn các mặt của cùng một thân",
"pick faces to offset": "chọn các mặt cần offset",
"pick lines of one sketch": "chọn các đường thẳng của cùng một phác thảo",
"pick one or two vertices, edges or faces": "chọn một hoặc hai đỉnh, cạnh hoặc bề mặt",
"pick one plane or face as the tool, or sketch curves": "chọn một mặt phẳng hoặc một mặt làm dụng cụ, hoặc chọn các đường cong phác thảo",
"pick sections in two or more sketches": "chọn các mặt cắt trong hai phác thảo trở lên",
"pick sketch curves or edges": "chọn các đường cong phác thảo hoặc các cạnh",
"pick the face to untrim": "chọn mặt cần hủy cắt tỉa",
"pick the path": "chọn đường dẫn",
"pick what to keep": "chọn phần cần giữ lại",
"pick what to keep of the other surface": "chọn phần cần giữ lại của bề mặt còn lại",
"prefs.add_item": "Thêm mục",
"prefs.alt_frees_manipulators": "Phím Alt / Option cũng giải phóng mũi tên thao tác",
"prefs.anti_aliasing_amd_dx12": "Khử răng cưa sử dụng mức 1× vì kiểm tra khởi động không vẽ được hình ảnh với đa lấy mẫu và đã vượt qua ở mức 1×. Bạn có thể chọn cài đặt khác ở trên; hãy khởi động lại để áp dụng nếu kiểm tra vượt qua.",
@@ -1837,6 +2068,64 @@
"render.effects_help": "Kết hợp các phong cách màu sắc có thứ tự và hiệu ứng ống kính không gian ảnh. Kết xuất và chỉnh màu lại bản gốc thô dùng chung các cài đặt đã lưu. Tệp EXR thô giữ nguyên. Đây là các điều khiển nghệ thuật độc lập, không phải mô phỏng ống kính hiệu chuẩn hay phim có thương hiệu.",
"render.effects_reset_lens": "Đặt lại hiệu ứng ống kính",
"render.effects_seed": "Hạt giống hoa văn",
"render.emitted_axis": "Trục phát",
"render.error_area_samples": "area_samples phải là 1, 4, 16 hoặc 64",
"render.error_binding_allocation": "không thể dành chỗ cho liên kết vật liệu",
"render.error_body_bound": "xem trước sản phẩm vượt quá giới hạn thân đã ghi",
"render.error_checkpoint_dimensions": "kích thước điểm kiểm tra khác với yêu cầu đã ghi",
"render.error_decode_budget": "tràn ngân sách giải mã ảnh",
"render.error_denoise_setting": "cài đặt khử nhiễu gốc không hợp lệ",
"render.error_display_dimensions": "kích thước hiển thị ảnh không hợp lệ",
"render.error_display_fit": "hiển thị ảnh không thể vừa thiết bị này",
"render.error_display_height": "tràn chiều cao hiển thị",
"render.error_display_width": "tràn chiều rộng hiển thị",
"render.error_duplicate_face": "diện mạo mặt sản phẩm bị trùng",
"render.error_export_document": "tài liệu xuất kết xuất đã đổi trong lúc chọn đích",
"render.error_face_cap": "xem trước sản phẩm vượt quá hạn mức chấp nhận diện mạo mặt",
"render.error_finish_gesture": "hãy hoàn tất thao tác dựng mô hình trước khi xem trước",
"render.error_finish_operation": "hãy hoàn tất thao tác dựng mô hình hiện tại trước khi vào Kết xuất",
"render.error_fixed_preview": "xem trước studio cố định yêu cầu phơi sáng 0, xoay môi trường 0 và cường độ 1",
"render.error_geometry_size": "tràn kích thước hình học sản phẩm",
"render.error_glass_recipe": "công thức kính không xác định",
"render.error_gpu_preview": "Xem trước sản phẩm bằng GPU không khả dụng trên máy chủ này. Các thiết lập đã lưu vẫn dùng được.",
"render.error_gpu_samples": "số mẫu GPU không được hỗ trợ",
"render.error_image_dimensions": "kích thước ảnh kết xuất không khớp với công việc của nó",
"render.error_image_profile": "ảnh kết xuất vượt quá hồ sơ tài nguyên đã ghi",
"render.error_interactive_command": "lệnh Kết xuất tương tác chưa được gán",
"render.error_job_action": "không phải hành động công việc ảnh tương tác",
"render.error_job_identity": "danh tính công việc kết xuất không hợp lệ: {error}",
"render.error_library_reply": "phản hồi thư viện kết xuất không hợp lệ",
"render.error_material_binding": "thiếu liên kết vật liệu",
"render.error_no_completed_image": "kết xuất chưa có ảnh hoàn tất",
"render.error_no_geometry": "không có hình học sản phẩm",
"render.error_no_scene": "không có cảnh sản phẩm",
"render.error_opacity": "độ đục diện mạo sản phẩm không hợp lệ",
"render.error_pbr_opacity": "PBR đục yêu cầu độ đục 1",
"render.error_physical_glass": "công thức đã chọn không phải kính vật lý",
"render.error_preview_device": "xem trước sản phẩm cần thiết bị đã cài có bộ đệm độ sâu",
"render.error_product_triangle": "tam giác sản phẩm không hợp lệ",
"render.error_provisional_identity": "danh tính kết xuất tạm hoặc số mẫu không hợp lệ",
"render.error_quality_bounds": "phép chiếu chất lượng vượt quá giới hạn gốc",
"render.error_quality_method": "phép chiếu chất lượng yêu cầu cùng phương pháp GPU tường minh",
"render.error_quality_projection": "phép chiếu chất lượng gốc không hợp lệ",
"render.error_regrade_identity": "danh tính chỉnh lại màu không hợp lệ: {error}",
"render.error_scene_bodies": "thiếu các thân của cảnh kết xuất",
"render.error_scene_body_limit": "cảnh kết xuất vượt quá giới hạn thân",
"render.error_scene_identity": "danh tính cảnh kết xuất không hợp lệ",
"render.error_setup_panicked": "Thiết lập dò đường đi của tia bằng GPU bị lỗi nghiêm trọng",
"render.error_setup_stopped": "tiến trình thiết lập dừng mà không trả về máy chủ",
"render.error_setup_worker": "không thể khởi động tiến trình thiết lập: {error}",
"render.error_source_preview": "xem trước nguồn vượt quá giới hạn byte",
"render.error_surface_normals": "PBR yêu cầu pháp tuyến bề mặt khác không",
"render.error_surface_reply": "phản hồi bề mặt tác giả không hợp lệ",
"render.error_triangle_bound": "xem trước sản phẩm vượt quá giới hạn nguồn tám triệu tam giác",
"render.error_triangle_count": "tràn số tam giác sản phẩm",
"render.error_upload_slot": "khe tải lên xem trước sản phẩm không khả dụng",
"render.error_vertex_allocation": "cấp phát đỉnh xem trước sản phẩm thất bại",
"render.error_vertex_envelope": "xem trước sản phẩm vượt quá giới hạn dữ liệu đỉnh {limit} MiB; hình học không được đơn giản hóa",
"render.error_vertex_packing": "cách đóng gói xem trước sản phẩm khác dữ liệu đỉnh đã chấp nhận",
"render.error_visible_solid": "Hãy tạo một khối đặc hiển thị trong Thiết kế để xem trước ở đây.",
"render.exit_focus": "Thoát tập trung",
"render.export_display": "Xuất: ảnh PNG hiển thị",
"render.export_image_label": "Xuất ảnh",
"render.export_linear": "Xuất: ảnh EXR tuyến tính thô",
@@ -1850,6 +2139,7 @@
"render.flare_streak": "Vệt sáng phong cách biến dạng (Anamorphic)",
"render.flare_strength": "Cường độ vệt lóe điểm sáng",
"render.flare_threshold": "Ngưỡng lóe sáng tuyến tính cảnh",
"render.fold_browser": "Gập Trình duyệt",
"render.gpu_depth": "Độ sâu đường truyền tia tối đa",
"render.gpu_options_help": "Số mẫu, độ sâu, hạt giống và độ phơi sáng được lưu cùng thiết lập này. Chỉ lưu phương thức tạo ảnh đang hoạt động.",
"render.gpu_path_failed": "Bộ dò đường truyền tia GPU không khả dụng",
@@ -1907,11 +2197,13 @@
"render.image_use_largest": "Sử dụng kích thước lớn nhất theo tỷ lệ này:",
"render.image_width": "Bề rộng",
"render.include_rig_cards": "Bao gồm tấm hắt sáng và tấm chắn sáng thụ động",
"render.inner_half_angle": "Nửa góc trong",
"render.inspect_scene": "Làm mới tóm tắt cảnh đã ghi nhận",
"render.inspector": "Bảng thuộc tính",
"render.keep_editing": "Tiếp tục chỉnh sửa",
"render.layer_down": "Chuyển xuống",
"render.layer_enabled": "Bật lớp này",
"render.layer_off_suffix": " (tắt)",
"render.layer_remove": "Xóa lớp",
"render.layer_strength": "Cường độ lớp",
"render.layer_up": "Chuyển lên",
@@ -2059,6 +2351,7 @@
"render.optics_save": "Lưu cài đặt quang học này vào thiết lập",
"render.optics_saved": "Các mục tiêu quang học đã lưu",
"render.optics_saved_help": "Định danh chính xác về định nghĩa, tính năng và thực thể được duy trì sau khi mở lại ngoại tuyến. Từ chối các mục tiêu bị thiếu/thay thế/ẩn; vật liệu kỹ thuật không đổi. Hãy lưu hoặc hủy các chỉnh sửa số trước khi xóa mục tiêu đã lưu.",
"render.outer_half_angle": "Nửa góc ngoài",
"render.output_format_status": "PNG là hình ảnh hiển thị hoàn chỉnh chính xác. EXR tùy chọn trên GPU giữ lại suất bức xạ FLOAT32 tuyến tính cảnh thô trước các bộ lọc hiển thị. Xuất không bao giờ thay thế bằng bộ nhớ đệm xem trước hoặc tác vụ khác.",
"render.output_lock_ratio": "Khóa tỷ lệ khung hình",
"render.output_over_budget": "Hình ảnh yêu cầu vượt quá giới hạn tài nguyên đã chọn. Hãy chủ động chọn kích thước hoặc cấu hình tương thích; không tự động hạ cấp chất lượng.",
@@ -2092,7 +2385,10 @@
"render.physical_prepare_plan": "Chuẩn bị kế hoạch tạo (không áp dụng)",
"render.physical_separate": "Diện mạo không phải là định danh vật liệu. Đây là các tham chiếu có nguồn gốc, không phải đặc tính hiệu dụng được chứng nhận. Khối lượng, vật liệu kỹ thuật và quang học hiện có giữ nguyên.",
"render.physical_unknown": "Chưa xác định ứng viên số học. Phải chỉ định mác, công thức hoặc cấu tạo; chưa rõ không có nghĩa là bằng 0.",
"render.pick_body": "Thân",
"render.pick_component": "Thành phần",
"render.pick_face": "Mặt",
"render.pick_help": "Chọn Thân, Mặt hoặc Thành phần. Bấm vào chỗ trống để bỏ chọn; Shift hoặc Ctrl để thêm hoặc đảo. Phần tô sáng chỉ hiện ở chế độ xem sản phẩm trực tiếp.",
"render.pick_label": "Chọn",
"render.pick_up_label": "Lấy",
"render.pick_waiting": "Chưa hỗ trợ chọn sản phẩm.",
@@ -2114,6 +2410,12 @@
"render.preview_upload": "Dung lượng đỉnh xem trước trực tiếp",
"render.preview_upload_help": "Số byte đỉnh xem trước chính xác, không phải tổng bộ nhớ GPU hay tiến trình. Hình học không bị đơn giản hóa. Các tác vụ hình ảnh dùng kiểm tra tiếp nhận và ánh sáng riêng.",
"render.progressive_image_summary": "PNG xem trước · PBR và thủy tinh · mẫu lũy tiến",
"render.property_conditions": "Điều kiện: {value}",
"render.property_fallback": "thuộc tính",
"render.property_qualifier": "Bộ định tính: {value}",
"render.property_source": "Nguồn: {id} - {locator}",
"render.property_uncertainty": "Độ bất định: {value}",
"render.property_unknown": "không rõ",
"render.quality_ack": "Xác nhận phép chiếu định mức cố định và các mục lược bỏ",
"render.quality_apply": "Sử dụng định mức lấy mẫu cố định này",
"render.quality_projection_help": "Các thiết lập sẵn Q bao gồm các yêu cầu tương lai. Hành động này chỉ chiếu định mức mẫu PNG cố định được hỗ trợ và lược bỏ rõ ràng việc dừng thích ứng, đầu ra tuyến tính thô và các giới hạn truyền dẫn độc lập.",
@@ -2129,6 +2431,7 @@
"render.replace_saved_surface": "Thay thế liên kết đã lưu hiện có cho mục tiêu này",
"render.restore_camera": "Khôi phục camera đã lưu",
"render.result_actual_help": "Một pixel hình ảnh tương ứng một pixel màn hình hiển thị.",
"render.result_actual_size": "100%",
"render.result_capture": "Phiên bản đã ghi nhận",
"render.result_current": "Phiên bản mô hình đã ghi nhận là phiên bản hiện tại.",
"render.result_empty": "Chưa có hình ảnh nào hoàn thành. Hãy kiểm tra cài đặt rồi bắt đầu kết xuất.",
@@ -2203,10 +2506,14 @@
"render.shot_rename": "Đổi tên khung hình đã lưu",
"render.shot_saved_only": "Hãy lưu bản nháp hiện tại trước. Nhân bản và đổi tên sẽ giữ nguyên các tùy chọn đã lưu và tham chiếu tài nguyên chính xác.",
"render.show_shots_label": "Hiện dải cảnh chụp",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Mặt đất · RGB tuyến tính",
"render.sky_horizon": "Đường chân trời · RGB tuyến tính",
"render.sky_zenith": "Thiên đỉnh · RGB tuyến tính",
"render.soft_focus": "Lấy nét mềm (Soft focus)",
"render.spot_cone": "Chóp đèn rọi",
"render.stage_frame": "Khung",
"render.stage_light": "Ánh sáng",
"render.stage_look": "Giao diện",
@@ -2257,9 +2564,45 @@
"render.subsurface_enable": "Bước đi ngẫu nhiên tán xạ bên trong",
"render.subsurface_help": "Chỉ dành cho chất điện môi kín. Hệ số tán xạ và hấp thụ RGB là các hệ số riêng biệt trên mỗi mm. Tia sáng tán xạ bên trong hình học thực tế, sau đó khúc xạ hoặc phản xạ tại ranh giới. Hãy tắt bóng đổ thẳng, khử nhiễu bề mặt và thể tích bên ngoài; dùng một phân tầng Fresnel. Đây không phải bộ đổ bóng khuếch tán, lưới mật độ hay vật liệu đo đạc. Môi trường đậm đặc có thể cần nhiều mẫu và độ sâu tia lớn hơn.",
"render.subsurface_rate": "Tần suất va chạm tán xạ",
"render.tone_aces_fitted": "ACES khớp",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "Thủy tinh GPU hỗ trợ các môi trường rời rạc đã xác thực. Không cung cấp môi trường lồng nhau không giới hạn hay ước tính truyền dẫn không nhiễu.",
"render.transmission_strata": "Số phân tầng Fresnel có điều kiện",
"render.transmission_strata_help": "Giá trị 1 giữ nguyên chuỗi ban đầu. Giá trị 2 hoặc 4 phân tầng hóa lựa chọn phản xạ/truyền qua đầu tiên của thủy tinh theo định luật Snell và hấp thụ không đổi. Thêm đường truyền tia sẽ tốn nhiều tính toán hơn; đây không phải tính năng khử nhiễu, hỗ trợ môi trường lồng nhau hay đảm bảo tăng tốc kết xuất.",
"render.tree_add_light": "Thêm đèn",
"render.tree_add_shot": "Thêm cảnh chụp",
"render.tree_browser": "Trình duyệt kết xuất",
"render.tree_by_look": "Theo diện mạo",
"render.tree_by_object": "Theo đối tượng",
"render.tree_constant": "Môi trường hằng định",
"render.tree_default": "Mặc định",
"render.tree_directional": "Định hướng",
"render.tree_environment": "Môi trường",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} mặt",
"render.tree_face_one": "{count} mặt",
"render.tree_fixed_studio": "Studio cố định",
"render.tree_hdr": "HDR",
"render.tree_lights": "Đèn",
"render.tree_lights_pending": "Chưa có lệnh đèn có tên.",
"render.tree_mixed": "Hỗn hợp",
"render.tree_more": "Thêm {count}",
"render.tree_mute": "Tắt đèn",
"render.tree_no_environment": "Không có môi trường",
"render.tree_objects": "Đối tượng",
"render.tree_output": "Đầu ra",
"render.tree_point": "Điểm",
"render.tree_rectangle": "Hình chữ nhật",
"render.tree_search": "Tìm đối tượng",
"render.tree_selection": "Vùng chọn kết xuất",
"render.tree_shots": "Cảnh chụp",
"render.tree_sky": "Bầu trời",
"render.tree_solo": "Chỉ hiện một đèn",
"render.tree_spot": "Đèn rọi",
"render.tree_sun": "Mặt trời",
"render.tree_switch": "Chuyển",
"render.tree_user_one": "{count} đối tượng",
"render.tree_users": "{count} đối tượng",
"render.unavailable_preview": "Thiết lập này yêu cầu cấu hình xem trước hiện không khả dụng.",
"render.unsaved": "Các thay đổi xem trước chưa lưu",
"render.use_preview": "Sử dụng xem trước tích hợp",
@@ -2303,6 +2646,26 @@
"search.try": "Nhập tên lệnh, một tính năng trong thiết kế này hoặc một tham số. Để chạy lệnh kèm giá trị, hãy nhập mã lệnh và một đối tượng JSON: {example}",
"search.valid": "Hợp lệ",
"section.off_hint": "Chưa chọn mặt phẳng: nhấn OK sẽ tắt mặt cắt.",
"select a direction (an axis, a sketch line or a straight edge) first": "hãy chọn một hướng (một trục, một đường thẳng phác thảo hoặc một cạnh thẳng) trước",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "chọn một hướng (một trục, một đường thẳng phác thảo hoặc một cạnh thẳng) để biên dạng đi theo",
"select a point on a component": "chọn một điểm trên một thành phần",
"select a profile, edges or sketch lines first": "hãy chọn một biên dạng, các cạnh hoặc các đường thẳng phác thảo trước",
"select an axis": "chọn một trục",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "hãy chọn một trục, một cạnh thẳng hoặc cạnh tròn, hoặc một mặt trụ, mặt nón hay mặt xuyến trước",
"select bodies first": "hãy chọn các thân trước",
"select corner points, or the two lines of one corner": "chọn các điểm góc, hoặc hai đường thẳng của một góc",
"select one corner point, or the two lines of one corner": "chọn một điểm góc, hoặc hai đường thẳng của một góc",
"select sheet edges first": "hãy chọn các cạnh của tấm trước",
"select the bend line (a sketch line) first": "hãy chọn đường gập (một đường thẳng phác thảo) trước",
"select the cam's profile (a sketch profile or the cam's edges)": "chọn biên dạng của cam (một biên dạng phác thảo hoặc các cạnh của cam)",
"select the corner to cut first": "hãy chọn góc cần cắt trước",
"select the corners to round first": "hãy chọn các góc cần bo tròn trước",
"select the fixed face first (a plate's large face)": "hãy chọn mặt cố định trước (mặt lớn của một tấm)",
"select the frame sketch's lines first": "hãy chọn các đường thẳng của phác thảo khung trước",
"select the path (sketch lines across the edge)": "chọn đường dẫn (các đường thẳng phác thảo dọc qua cạnh)",
"select the rim face first": "hãy chọn mặt viền trước",
"select the sheet edge first": "hãy chọn cạnh của tấm trước",
"select two components": "chọn hai thành phần",
"set by the sketch's lines": "xác định bởi các đường của phác thảo",
"settings.display_quality_note": "Mức độ chi tiết cao hơn giúp hiển thị các mặt cong và cạnh mượt mà hơn nhưng tốn nhiều thời gian tạo lưới hơn. Thiết lập này chỉ thay đổi vùng nhìn, không ảnh hưởng đến thiết kế hay dữ liệu xuất tệp.",
"settings.frame_rate_details_note": "Bổ sung biểu đồ thời gian các khung hình gần nhất xếp chồng số tam giác đã vẽ, biểu đồ phân bố thời gian khung hình và nội dung GPU đã vẽ. Bấm vào tốc độ khung hình trên khung nhìn để ẩn/hiện.",
@@ -2320,17 +2683,23 @@
"settings.window_system_details": "Chi tiết",
"settings.window_system_note_now": "Áp dụng sau khi khởi động lại. Hiện tại: {now}.",
"settings.window_system_wayland_limited": "Một số tính năng bị giới hạn trên Wayland gốc.",
"sheet.flange_type_base": "Cơ sở",
"sheet.flange_type_contour": "Đường viền",
"sheet.flange_type_edge": "Cạnh",
"sheet.no_body": "chưa có khối tấm kim loại: hãy bắt đầu bằng Cánh gập > Cơ sở (Base), hoặc chuyển một tấm phẳng thành tấm kim loại bằng lệnh 'Chuyển thành tấm kim loại' (chọn mặt phẳng lớn của nó)",
"shortcut.json_error": "tham số phải là JSON: {error}",
"shortcut.no_command": "không có lệnh `{id}`; văn bản trước JSON phải là mã lệnh",
"shortcut.pin": "Ghim lên đầu hộp S",
"shortcut.unpin": "Bỏ ghim",
"sketch is missing": "thiếu phác thảo",
"sketch.degrees_of_freedom": "{count} bậc tự do",
"sketch.dof_left": "Còn {count} bậc tự do",
"sketch.dof_left_one": "Còn {count} bậc tự do",
"sketch.draw_curves": "Vẽ dưới dạng {linetype}",
"sketch.make_selection": "Chuyển đổi vùng chọn sang {linetype}",
"sketch.open_ends": "Đầu hở: {count}",
"sketch.status_conflict": "ràng buộc xung đột",
"sketch.status_fully_constrained": "ràng buộc hoàn toàn",
"sketch.untied_ends": "Chưa khóa: {count}",
"sketch_panel.attached": "Gắn vào {body} / {path}",
"sketch_panel.author": "Vị trí gốc: {path}",
@@ -2357,7 +2726,24 @@
"sketch_text.path_hint": "Đường cong phác thảo mà văn bản chạy theo: nhấp vào đây, sau đó chọn đường cong",
"sketch_text.use_font_file": "Sử dụng tệp phông chữ {path}",
"solid": "khối đặc",
"the angle must be a number": "góc phải là một số",
"the curves must be in one sketch": "các đường cong phải nằm trong cùng một phác thảo",
"the direction must be an axis, a sketch line or a straight edge": "hướng phải là một trục, một đường thẳng phác thảo hoặc một cạnh thẳng",
"the duration must be a number of seconds, 0.001 or more": "thời lượng phải là một số giây, từ 0,001 trở lên",
"the line's sketch is gone": "phác thảo của đường thẳng không còn nữa",
"the lines must be in one sketch": "các đường thẳng phải nằm trong cùng một phác thảo",
"the lines must be in one sketch, not the section's": "các đường thẳng phải nằm trong cùng một phác thảo, không phải phác thảo của mặt cắt",
"the parts library is empty": "thư viện chi tiết đang trống",
"the parts library is not available": "thư viện chi tiết tiêu chuẩn hiện không khả dụng",
"the path curves must be in one other sketch": "các đường cong của đường dẫn phải nằm trong cùng một phác thảo khác",
"the path's sketch is gone": "phác thảo của đường dẫn không còn nữa",
"the position must be a number": "vị trí phải là một số",
"the preview failed": "xem trước không thành công",
"the profiles and curves must be in one sketch": "các biên dạng và đường cong phải nằm trong cùng một phác thảo",
"the reference face must be on the edges' body": "mặt tham chiếu phải thuộc thân của các cạnh",
"the scale must be above 0": "tỷ lệ phải lớn hơn 0",
"the section's profiles must be in one sketch": "các biên dạng của mặt cắt phải nằm trong cùng một phác thảo",
"the two origins are on the same component": "hai gốc tọa độ nằm trên cùng một thành phần",
"thread.automatic_size": "Kích thước tự động",
"thread.designation": "Ký hiệu ren",
"thread.direction": "Chiều ren",
@@ -2397,6 +2783,7 @@
"trace.points": "{count} điểm dọc theo đường dẫn",
"trace.stopped_by_contact": "Kết thúc tại mẫu {sample}: {a} sẽ xuyên qua {b}",
"trace.stopped_by_loop": "Kết thúc tại mẫu {sample}: vòng lặp qua {joint} không thể khép kín thêm được nữa",
"trim by sketch curves, or by one plane or face": "cắt tỉa bằng các đường cong phác thảo, hoặc bằng một mặt phẳng hay một mặt",
"ui.1_degree_of_freedom": "1 bậc tự do",
"ui.3d_mouse_axes_reassigned": "Các trục được gán lại trong Tùy chọn, và điều đó vẫn áp dụng cùng với hiệu chuẩn này.",
"ui.3d_mouse_button": "Nút {number}",
@@ -2873,6 +3260,8 @@
"ui.design_properties.revision": "Lần sửa đổi (Revision)",
"ui.diameter": "Đường kính",
"ui.dimension": "Kích thước",
"ui.direct_interaction": "Tương tác trực tiếp",
"ui.direct_interaction_note": "Thao tác trực tiếp trên mô hình trong khung nhìn. Nhấn vào một mặt phẳng hoặc biên dạng rồi kéo: lên trên là đùn, xuống vào thân là cắt, di chuyển sang ngang đặt bước nhảy",
"ui.direction": "Hướng",
"ui.display_quality": "Chất lượng hiển thị",
"ui.display_quality_coarse": "Thô (Nhanh)",
@@ -2896,6 +3285,7 @@
"ui.editJointLimits": "Chỉnh sửa giới hạn khớp nối",
"ui.edit_section_analysis": "Chỉnh sửa phân tích mặt cắt",
"ui.ellipse": "Hình elip",
"ui.emboss_wrap_note": "Các biên dạng đường trực giao tiếp xúc với một hình trụ được hỗ trợ sẽ tự động quấn. Chọn một thành để chọn mục tiêu.",
"ui.end_radius": "Bán kính kết thúc",
"ui.end_scale": "Tỷ lệ đầu cuối",
"ui.entities": "Các thực thể",
@@ -2968,6 +3358,7 @@
"ui.heading_extrude": "ĐÙN KHỐI",
"ui.heading_fillet": "BO TRÒN",
"ui.heading_finish_sketch": "HOÀN TẤT PHÁC THẢO",
"ui.heading_form": "TẠO HÌNH",
"ui.heading_front": "HÌNH CHIẾU ĐỨNG",
"ui.heading_hole": "TẠO LỖ",
"ui.heading_home": "GÓC NHÌN CHUẨN",
@@ -3016,6 +3407,7 @@
"ui.heading_utilities": "TIỆN ÍCH",
"ui.heading_utility": "TIỆN ÍCH",
"ui.heading_weldments": "KẾT CẤU HÀN",
"ui.height": "Chiều cao",
"ui.help": "Trợ giúp",
"ui.hide": "Ẩn",
"ui.hideAxes": "Ẩn Các trục",
@@ -3053,11 +3445,14 @@
"ui.intersect": "Giao nhau",
"ui.isolate": "Cô lập đối tượng",
"ui.join": "Nối liền",
"ui.joint_play": "▶ Phát",
"ui.joint_stop": "■ Dừng",
"ui.joints": "Các khớp nối",
"ui.keyboard_shortcuts": "Phím tắt bàn phím",
"ui.language": "Ngôn ngữ (Language)",
"ui.layout_compact": "Gọn",
"ui.layout_floating": "Nổi",
"ui.length": "Chiều dài",
"ui.length_decimals": "Số chữ số thập phân cho chiều dài",
"ui.light": "Sáng",
"ui.line": "Đoạn thẳng",
@@ -3069,6 +3464,7 @@
"ui.loft": "Vuốt nối biên dạng (Loft)",
"ui.look_at": "Nhìn trực diện",
"ui.look_at_anim_desc": "Góc nhìn theo trục, Nhìn thẳng, Chuẩn và Vừa vặn",
"ui.major_radius": "Bán kính lớn",
"ui.manipulator_free_alt": "Kéo tự do bộ thao tác cũng bằng Alt/Option",
"ui.manipulator_free_alt_tip": "Bật: Alt/Option hoặc Ctrl/Cmd trên các mũi tên đùn / gizmo sẽ tắt bước nhảy giá trị. Tắt: chỉ Ctrl/Cmd.",
"ui.manufacture": "Gia công chế tạo",
@@ -3098,8 +3494,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "3MF kèm thẻ bề mặt",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "Bán kính nhỏ",
"ui.mirror": "Lấy đối xứng",
"ui.mirror_line": "Đường đối xứng",
"ui.modifiers_either": "{first} hoặc {second}",
"ui.move": "Di chuyển",
"ui.multiple": "Nhiều đối tượng",
"ui.named_views": "Các góc nhìn đã đặt tên",
@@ -3156,6 +3554,7 @@
"ui.pinToShortcuts": "Ghim vào phím tắt",
"ui.pinToToolbar": "Ghim vào thanh công cụ",
"ui.pipe": "Ống",
"ui.pitch": "Bước xoắn",
"ui.placement": "Vị trí đặt",
"ui.placement_handles": "Tay nắm định vị",
"ui.placement_handles_tip": "Tay nắm trên hình xem trước của Gờ đỡ, Vấu lồi hoặc Khớp cài: kéo điểm đánh dấu để di chuyển trên mô hình, xoay bằng vòng xoay",
@@ -3218,6 +3617,7 @@
"ui.reverse_horizontal_pan_direction": "Đảo chiều di chuyển góc nhìn ngang",
"ui.reverse_horizontal_pan_tip": "Cuộn hai ngón tay theo phương ngang và con lăn phụ sẽ di chuyển góc nhìn theo chiều ngược lại",
"ui.reverse_zoom_direction": "Đảo chiều thu phóng",
"ui.revolutions": "Số vòng",
"ui.revolve": "Xoay tròn tạo khối",
"ui.ribbon_exit": "Thoát",
"ui.ribbon_labels": "Hiển thị văn bản bên dưới biểu tượng dải băng",
@@ -3234,6 +3634,7 @@
"ui.scale": "Thay đổi tỷ lệ",
"ui.second_rail": "Đường ray dẫn hướng thứ hai",
"ui.section_analysis": "Phân tích mặt cắt",
"ui.section_size": "Kích thước mặt cắt",
"ui.select": "Chọn",
"ui.selectOther": "Chọn đối tượng khác…",
"ui.selectTangentChain": "Chọn chuỗi tiếp tuyến",
@@ -3305,6 +3706,7 @@
"ui.start_page": "Trang bắt đầu",
"ui.step_values": "Tăng giảm giá trị bằng phím mũi tên và con lăn chuột",
"ui.step_values_tip": "Trong ô nhập giá trị đang gõ, phím Lên/Xuống và con lăn chuột trên ô sẽ tăng giảm số thuần túy 1 đơn vị (Shift: 10, Alt: 0.1). Biểu thức toán học được giữ nguyên như đã nhập.",
"ui.stitch_tolerance_hint": "chặt",
"ui.stretch": "Kéo giãn",
"ui.supersampling": "Khử răng cưa SSAA",
"ui.supersampling_adaptive": "Chỉ khi góc nhìn đứng yên",
@@ -3335,6 +3737,8 @@
"ui.to_object": "Tới đối tượng",
"ui.tool_direction": "Hướng công cụ",
"ui.top": "Trên (Hình chiếu bằng)",
"ui.top_diameter": "Đường kính đỉnh",
"ui.top_radius": "Bán kính đỉnh",
"ui.torus": "Hình xuyến",
"ui.total_angle": "Góc tổng thể",
"ui.trackpad_pan_tip": "Thao tác vuốt bàn rê giúp dời góc nhìn (khi tắt: sẽ thu phóng như con lăn); con lăn chuột thu phóng, con lăn ngón cái dời góc nhìn sang hai bên, thao tác chụm ngón tay luôn thu phóng",
@@ -3363,6 +3767,7 @@
"ui.visual_shaded_with_edges": "Tô bóng kèm hiển thị cạnh",
"ui.visual_style": "Kiểu hiển thị trực quan",
"ui.visual_wireframe": "Khung dây (Wireframe)",
"ui.width": "Bề rộng",
"ui.window_system": "Hệ thống cửa sổ",
"ui.window_system_auto": "Tự động",
"ui.window_system_wayland": "Wayland",
@@ -3423,6 +3828,9 @@
"update.up_to_date": "SolidCraft đã được cập nhật bản mới nhất.",
"update.update_now": "Cập nhật ngay",
"update.you_have": "Bạn đang dùng phiên bản {version}.",
"use a positive nominal diameter and a pitch smaller than it": "dùng đường kính danh nghĩa dương và bước ren nhỏ hơn đường kính đó",
"values must be finite numbers": "các giá trị phải là số hữu hạn",
"values must be numbers or expressions": "các giá trị phải là số hoặc biểu thức",
"view.auto_ortho_faces": "Phối cảnh khi xoay quỹ đạo, trực giao khi nhìn trực diện mặt",
"web.files.insert_drawings_hint": "Tệp CAD, lưới đa giác, DXF hoặc SVG vào thiết kế đang mở",
"web.files.insert_stored_drawings_hint": "Vào thiết kế đang mở (tệp CAD, lưới đa giác, DXF, SVG)",
+1095 -1
View File
File diff suppressed because it is too large Load Diff
+408
View File
@@ -1,4 +1,5 @@
{
"(active rule)": "(当前规则)",
"0 turns it off": "0 表示关闭",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. 点击下方按钮打开 GitHub 草稿,然后粘贴已复制到剪贴板的报告。",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. 点击下方按钮打开 GitHub 草稿。标题和报告将自动填入。",
@@ -51,16 +52,20 @@
"Apply your appearance first. Exports assigned appearances and materials created in this design.": "请先应用外观。导出已指定的外观和在此设计中创建的材质。",
"Arc length": "弧长",
"Area": "面积",
"As Picked": "按选取",
"As-Built": "现有位置",
"Assign Rule": "分配规则",
"Attachment": "附着",
"BLEND SURFACE": "混合曲面",
"BOUNDARY SURFACE": "边界曲面",
"BROWSER": "浏览器",
"Ball": "球",
"Bar": "扁钢",
"Base Center": "底面中心",
"Base Height": "底座高度",
"Bend": "折弯角度",
"Bend Edges": "折弯边",
"Bend Line": "折弯线",
"Bend Line Position": "弯折线位置",
"Bend Position": "折弯位置",
"Bend Radius": "折弯半径",
@@ -72,6 +77,7 @@
"Body (last if none)": "实体(未指定时为最后一个)",
"Body to split": "要分割的实体",
"Body, or faces to take out": "实体,或要移除的面",
"Both": "两侧",
"Bottom Left": "左下",
"Bottom Middle": "下中",
"Bottom Right": "右下",
@@ -103,6 +109,7 @@
"Choose a new plane. Sketch geometry and dimensions stay unchanged in its two-dimensional coordinates.": "选择一个新平面。草图几何和尺寸在其二维坐标中保持不变。",
"Choose…": "选择…",
"Circle center": "圆心",
"Circle or sphere": "圆或球",
"Circular": "圆周",
"Circumference": "周长",
"Clockwise": "顺时针",
@@ -119,6 +126,7 @@
"Config Table": "配置表",
"Configuration": "配置",
"Configuration rules": "配置规则",
"Constant radius": "等半径",
"Contact": "接触",
"Contact Sets": "接触集",
"Contact sets": "接触集",
@@ -154,7 +162,9 @@
"Custom": "自定义",
"Customize Toolbar": "自定义工具栏",
"Customize…": "自定义…",
"Cylindrical": "圆柱",
"Cylindrical face": "圆柱面",
"Deboss": "凹印",
"Delete": "删除",
"Delete Folders and Features…": "删除文件夹及其特征…",
"Delete Selected Features…": "删除所选特征…",
@@ -186,6 +196,7 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "拖动以 5° 为步长旋转垫块。按住 Alt 或 Ctrl 可自由旋转。",
"Drive Joint": "驱动接头",
"Duration": "时长",
"Edge": "边",
"Edges": "边",
"Edit": "编辑",
"Edit Profile Sketch": "编辑轮廓草图",
@@ -194,6 +205,7 @@
"End Radius": "结束半径",
"End bulge": "终止鼓度",
"End continuity": "终止连续性",
"Equal Distance": "等距离",
"Expand": "展开",
"Expected result (optional)": "预期结果(可选)",
"Explode": "爆炸",
@@ -221,6 +233,8 @@
"Faces": "面",
"Faces / edges / vertices": "面 / 边 / 顶点",
"Faces to split": "要分割的面",
"Faces/Body": "面/实体",
"Factor must be a positive number": "系数必须是正数",
"Fastener": "紧固件",
"Favorites": "收藏",
"Favourite": "收藏",
@@ -230,9 +244,12 @@
"Filter…": "筛选…",
"Find in Browser": "在浏览器中查找",
"Finish": "完成",
"First edge": "第一条边",
"First plane": "第一个平面",
"First point": "第一点",
"Fit and G2 corners require Constant radius.": "拟合和 G2 拐角需要 Constant radius。",
"Fixed Face": "固定面",
"Flange Gap": "法兰间隙",
"Flange thickness": "翼缘厚度",
"Flanges": "法兰",
"Flat Pattern": "展开图",
@@ -240,8 +257,10 @@
"Follow camera (Look At sketches)": "跟随相机(注视草图)",
"Follow the camera (Look At sketches)": "跟随相机(注视草图)",
"Font": "字体",
"Free Move": "自由移动",
"From": "起点",
"From Bodies": "从实体创建",
"From Snap": "起始捕捉",
"From edges": "起始边",
"Full Length": "全长",
"Full thread depth": "完整螺纹深度",
@@ -253,10 +272,13 @@
"Halo under sketch curves": "在草图曲线下方显示光晕",
"Height": "高度",
"Height From": "高度基准",
"Hem Gap": "卷边间隙",
"Hidden edges": "隐藏线",
"History layout": "历史布局",
"History names": "历史名称",
"Hole (optional)": "孔(可选)",
"Hole Depth": "孔深",
"Hole Diameter": "孔径",
"Holes": "孔",
"Holes (edges on them)": "孔(孔上的边)",
"Home view": "主视图",
@@ -279,12 +301,16 @@
"Issue title": "Issue 标题",
"Items": "项目",
"JOINTS": "关节",
"Joint 1": "接头 1",
"Joint 2": "接头 2",
"Joint Origin1": "接头原点1",
"K Factor": "K 因子",
"Keep (points on it)": "保留(其上的点)",
"Keep Tools": "保留工具",
"Keep of the other surface": "另一曲面保留的部分",
"Key a joint's value at this step": "在此步骤为接头值设置关键帧",
"Keys": "关键帧",
"Knife Edge": "刀口",
"L-Angle": "角钢",
"LIBRARY": "库",
"LINKS": "链接",
@@ -297,9 +323,11 @@
"Letter Spacing": "字间距",
"Library": "零件库",
"Library file": "库文件",
"Library response is missing": "缺少零件库的响应",
"Limits": "限制",
"Line Spacing": "行间距",
"Line Type": "线型",
"Line on plane": "直线在平面上",
"Lines": "直线",
"Listing the installed fonts…": "正在列出已安装字体…",
"Load library": "加载库",
@@ -319,11 +347,14 @@
"Material Outside": "材料在外",
"Material copied. Existing body assignments are unchanged.": "材质已复制。现有实体指定保持不变。",
"Max": "最大",
"Max Thickness": "最大厚度",
"Maximum": "最大",
"Mesh body": "网格实体",
"Mid Radius": "中间半径",
"Middle double-click": "中键双击",
"Min": "最小",
"Min Draft": "最小拔模",
"Min Thickness": "最小厚度",
"Minimum": "最小",
"Mirror Plane": "镜像平面",
"Mitre": "斜接",
@@ -343,6 +374,7 @@
"Name": "名称",
"Name on import": "导入名称",
"Nearest": "最近",
"Neutral plane": "中性面",
"New": "新建",
"New Comp.": "新建组件",
"New Sketch": "新建草图",
@@ -353,6 +385,7 @@
"No matching appearances": "没有匹配的外观",
"No matching physical materials.": "没有匹配的物理材质。",
"No visible bodies or sketches to export.": "没有可导出的可见实体或草图。",
"Nominal Radius": "公称半径",
"Nominal diameter": "公称直径",
"None": "无",
"Not available yet": "暂不可用",
@@ -381,22 +414,28 @@
"Overall length": "总长",
"Param. Graph": "参数图",
"Parameter": "参数",
"Part length must be greater than zero and at most 2000 mm": "零件长度必须大于零且不超过 2000 mm",
"Parts": "零件",
"Pass through": "通过点",
"Path": "路径",
"Pattern": "阵列",
"Per Edge": "每条边",
"Physical material definitions": "物理材质定义",
"Pick a part size": "请选择零件尺寸",
"Pick the tool bodies": "选择工具实体",
"Picked": "所选",
"Picked point": "选取的点",
"Pin-slot": "销槽",
"Pitch": "螺距",
"Pivot": "枢轴",
"Place at the origin instead": "改为放置在原点",
"Planar": "平面",
"Plastic Rules": "塑料规则",
"Play the joint's motion in the view": "在视图中播放接头运动",
"Playback": "播放",
"Plot": "图表",
"Point on line": "点在直线上",
"Point on plane": "点在平面上",
"Position": "位置",
"Position (0 to 1)": "位置(0 到 1)",
"Position (G0)": "位置 (G0)",
@@ -409,6 +448,7 @@
"Profiles or curves": "轮廓或曲线",
"Profiles/Curves": "轮廓/曲线",
"Quantity": "数量",
"Quantity must be at least 2": "数量至少为 2",
"RECENT": "最近使用",
"REFERENCE": "参考",
"RULED SURFACE": "直纹曲面",
@@ -422,6 +462,8 @@
"Rectangular": "矩形",
"Rectangular Tube": "矩形管",
"Reference face": "参考面",
"Relief Depth": "止裂槽深度",
"Relief Width": "止裂槽宽度",
"Remove Tools": "移除工具",
"Remove condition": "删除条件",
"Remove from Folder": "从文件夹中移除",
@@ -450,6 +492,7 @@
"Restore this studio's tools": "恢复此工作室的工具",
"Result": "结果",
"Retake screenshot": "重新截图",
"Reveal Height": "台阶高度",
"Reverse": "反向",
"Reverse Direction": "反向",
"Revert": "还原",
@@ -458,12 +501,15 @@
"Revert Position": "恢复位置",
"Review the report and screenshot before opening GitHub.": "打开 GitHub 前请审阅报告和截图。",
"Review your report on GitHub and click Submit new issue to publish it.": "请在GitHub中检查报告,然后点击Submit new issue发布。",
"Revolute": "旋转",
"Rib Length": "筋板长度",
"Rib Offset": "筋板偏移",
"Rib Thickness": "筋板厚度",
"Ribs": "筋板",
"Right Middle": "右中",
"Rigid": "刚性",
"Rim Edge": "轮缘边",
"Rim face": "边缘面",
"Ring of tools on the right button": "右键工具环",
"Roll Back Here": "回滚到此处",
"Roll History Marker Here": "将历史标记滚动到此处",
@@ -488,16 +534,28 @@
"Search": "搜索",
"Search commands": "搜索命令",
"Search this library": "搜索此库",
"Second edge": "第二条边",
"Second plane": "第二个平面",
"Second point": "第二点",
"Section": "剖面",
"Section (optional)": "截面(可选)",
"Section position": "截面位置",
"Sections (one sketch each)": "截面(每个一个草图)",
"Select Other": "选择其他",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "“选择其他”:在模型上按住左键(或右键单击 › 选择其他…)列出光标下的所有对象;在同一位置再次单击可选择该处的下一个对象。双击中键转到主视图(首选项 › 导航)。",
"Select Same Look": "选择相同外观",
"Select bodies (a face picks its body)": "选择实体(单击面即选择其所属实体)",
"Select bodies or faces instead": "改为选择实体或面",
"Select edges": "选择边",
"Select points of the sketch being edited": "请选择正在编辑的草图中的点",
"Select the centre the pattern turns around first": "请先选择阵列旋转所绕的中心",
"Select the curves to offset first": "请先选择要偏移的曲线",
"Select the mirror line": "请选择镜像线",
"Select the sketch curves or points to mirror first": "请先选择要镜像的草图曲线或点",
"Select the sketch curves or points to move first": "请先选择要移动的草图曲线或点",
"Select the sketch curves or points to pattern first": "请先选择要阵列的草图曲线或点",
"Select the sketch curves or points to scale first": "请先选择要缩放的草图曲线或点",
"Select the sketch curves or points to transform first": "请先选择要变换的草图曲线或点",
"Selection filter": "选择筛选",
"Semantic faces share their appearance across instances.": "语义面在各实例间共享外观。",
"Send your report on GitHub": "在 GitHub 上发送报告",
@@ -517,9 +575,12 @@
"Sketch geometry and profiles": "草图几何和轮廓",
"Sketch plane has no body-face attachment.": "草图平面没有实体面附着。",
"Sketch points": "草图点",
"Slider": "滑块",
"Slot width": "槽宽",
"Snap to face and edge centres": "捕捉到面和边的中心",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft 在这些设计保存前已关闭。可以打开它们的上次自动保存。",
"Spacing 2 must be a non-zero number": "间距 2 必须是非零数字",
"Spacing must be a non-zero number": "间距必须是非零数字",
"Specialise": "专用操作",
"Speed": "速度",
"Splitting tool": "分割工具",
@@ -530,6 +591,7 @@
"Start angle": "起始角度",
"Start bulge": "起始鼓度",
"Start continuity": "起始连续性",
"Stationary Side": "固定侧",
"Step": "步骤",
"Steps": "步数",
"Steps to reproduce (optional)": "重现步骤(可选)",
@@ -544,6 +606,7 @@
"Suppressed": "已抑制",
"Surface": "曲面",
"Surface, or faces to turn over": "曲面,或要翻转的面",
"Surfaces": "曲面",
"Swap Ends": "交换端点",
"TRIM": "修剪",
"Tangent": "相切",
@@ -554,24 +617,34 @@
"Tap drill diameter": "攻丝底孔直径",
"Target": "目标",
"Target Body": "目标实体",
"Target Face (optional)": "目标面(可选)",
"Tear": "撕裂",
"Technical details": "技术详情",
"The dashed sketch is a saved plane guide. Select a new face to repair the attachment.": "虚线草图是已保存的平面引导。选择一个新面以修复附着。",
"The design changed. Reopen Change Part Size for the component.": "设计已更改。请为该组件重新打开“更改零件尺寸”。",
"The direction must be an axis or a straight sketch curve that lies in the sketch plane": "方向必须是轴,或位于草图平面内的直线草图曲线",
"The mirror line cannot also be mirrored": "镜像线本身不能再被镜像",
"The mirror line must be a straight curve of this sketch, not an origin axis": "镜像线必须是此草图中的直线曲线,不能是原点轴",
"The saved author occurrence is missing. Select a valid author placement before rebinding.": "保存的作者实例缺失。重新绑定前请选择有效的作者放置。",
"Then": "操作",
"These features will be deleted:": "以下特征将被删除:",
"These features will fail:": "以下特征将失败:",
"Thickness Outside": "外侧厚度",
"Thickness Variation": "厚度变化",
"Thin": "薄壁",
"Thin Extrude": "薄壁拉伸",
"Third plane": "第三个平面",
"Third point": "第三点",
"This child is shared. Deleting it removes it from every copy of its parent.": "此子项是共享的。删除它会从其父项的每个副本中移除。",
"This child is shared. Position changes apply to every copy of its parent.": "此子项是共享的。位置更改会应用到其父项的每个副本。",
"This face cannot provide a durable attachment. Choose another face or explicitly use a fixed plane.": "此面无法提供持久附着。请选择其他面或显式使用固定平面。",
"This image is not attached to GitHub yet. Copy or save it, then attach it on GitHub.": "此图片尚未附加到GitHub。请复制或保存图片,然后在GitHub中附加。",
"Thread depth": "螺纹深度",
"Thread diameter": "螺纹直径",
"Through point": "通过点",
"To": "终点",
"To Offset": "偏移",
"To Snap": "目标捕捉",
"To edges": "终止边",
"Toe radius": "肢端圆角半径",
"Tolerance": "公差",
@@ -585,6 +658,7 @@
"Trimming tool (plane, face or curves)": "修剪工具(平面、面或曲线)",
"Turn off section analysis before exporting the view.": "请关闭截面分析后再导出视图。",
"Type": "类型",
"Type a distance or an angle to move by": "请输入要移动的距离或角度",
"UNTRIM": "取消修剪",
"Unit": "单位",
"Unsuppress": "取消抑制",
@@ -629,6 +703,17 @@
"Z angle": "Z 角度",
"Z distance": "Z 距离",
"Zebra": "斑马纹",
"`joint` must be an id or a name": "“joint”必须是编号或名称",
"`params` must be an object": "“params”必须是对象",
"`values` must be a list": "“values”必须是列表",
"a chamfer needs a corner of exactly two lines": "倒角需要恰好由两条直线构成的角",
"a file operation is in progress": "正在进行文件操作",
"a picked curve is no longer in a sketch": "所选曲线已不在任何草图中",
"a picked curve's sketch has not been solved": "所选曲线所在的草图尚未求解",
"a picked edge has no points": "所选边没有点",
"a picked edge is gone": "所选边已不存在",
"a picked edge's body is gone": "所选边所属的实体已不存在",
"add a key for a joint first": "请先为接头添加关键帧",
"ai.connected_toast": "SolidCraft 现已可在 {clients} 中使用。请重启它们(设置 > 助手)。",
"ai.prefs.allow_control": "允许 AI 代理连接(控制通道 / MCP)",
"ai.prefs.allow_control_note": "仅在本机开放控制通道(127.0.0.1,端口 27878 或下一个空闲端口)。连接的程序还必须出示一个每次启动时新生成、只有你的用户账户能读取的秘密令牌。下次启动 SolidCraft 时生效。关闭:除非用 --control 启动,否则不监听任何端口。",
@@ -669,6 +754,7 @@
"appearance.pbr_opaque": "不透明 PBR",
"appearance.roughness": "粗糙度",
"appearance.surface_response": "表面响应",
"bom.group_children": "子零件并入所属零件的行",
"browser.body_name": "实体{number}",
"browser.calibrate_title": "校准:{name}",
"browser.capture_many": "{count} 个组件已移动,但尚未捕获其位置。",
@@ -679,6 +765,8 @@
"browser.move_title": "移动:{name}",
"browser.parameters": "参数 ({count})",
"browser.precision": "精度: {precision}",
"browser.sketch_attachment_lost": "{name} (附着丢失)",
"browser.sketch_editing": "{name} (编辑中)",
"browser.sketch_name": "草图{number}",
"browser.units": "单位: {units}",
"cam.flat": "平底",
@@ -688,7 +776,13 @@
"cam.roller": "滚子",
"cam.roller_pick": "滚子(可选)",
"cam.tip_pick": "尖端(可选)",
"choose a profile": "请选择轮廓",
"choose the cam's and the follower's joints": "请选择凸轮和从动件的接头",
"choose the joints to couple": "请选择要耦合的接头",
"click a plane or planar face": "单击平面或平整面",
"click sketch curves": "单击草图曲线",
"cmd.appearance_assign": "外观",
"cmd.appearance_chain": "外观来源",
"cmd.appearance_library": "外观库",
"cmd.appearance_list": "列出外观",
"cmd.appearance_paint": "涂抹外观",
@@ -1073,6 +1167,9 @@
"cmd.timeline_roll_to": "滚动历史标记",
"cmd.timeline_rollback": "移动时间线标记",
"cmd.timeline_suppress": "抑制特征",
"cmd.view.render_browser": "渲染浏览器",
"cmd.view.render_dock": "移动渲染停靠面板",
"cmd.view.render_focus": "渲染专注视图",
"cmd.view_ambient_occlusion": "环境光遮蔽",
"cmd.view_apply": "还原命名视图",
"cmd.view_back": "后视图",
@@ -1183,6 +1280,8 @@
"dxf.progress.write": "正在写入 DXF (5/5)",
"dxf.tolerance": "曲线公差",
"dxf.tolerance_help": "仅导出可见实体和显示的草图。曲线使用直线段近似。公差越小,曲线越精细,但需要更多时间和内存。",
"each rail's curves must be in one sketch": "每条导轨的曲线必须位于同一个草图中",
"feature computation ended without a result": "特征计算结束时没有返回结果",
"file.open.drawing_filter": "设计、CAD 文件、网格和图纸",
"file_load.built": "已构建:{built}/{total} 个特征。",
"file_load.converting": "正在转换实体 {done}/{total}",
@@ -1344,6 +1443,8 @@
"keymap.command_id": "命令 ID",
"keymap.empty": "没有匹配的命令",
"keymap.use_anyway": "仍在此处使用 {key}",
"label.move_to_left_side": "移到左侧",
"label.move_to_right_side": "移到右侧",
"manage.appearance_hint": "为所选对象选择外观,或将色样拖到实体或面上。",
"manage.assign_hint": "选择实体并指定其塑料设计规则。",
"manage.config_hint": "编辑配置行、列和规则,然后激活或预览某一行。",
@@ -1428,7 +1529,9 @@
"nav.free_orbit_upright.help": "左右拖动鼠标时模型绕世界竖直轴旋转;上下拖动可不受限制地越过顶部倾斜。",
"nav.free_orbit_upright.label": "绕竖直轴旋转",
"nav.fusion.help": "中键拖动平移,Shift+中键拖动旋转,右键拖动旋转",
"nav.hfss.help": "Alt+左键拖动平移,Shift+Alt+左键拖动缩放,在空白处 Ctrl+左键拖动旋转",
"nav.inventor.help": "中键拖动平移,Shift+中键拖动旋转,Ctrl+中键拖动缩放,右键拖动旋转",
"nav.maya.help": "Alt+左键拖动旋转,Alt+中键拖动平移,Alt+右键拖动缩放;中键拖动也可平移",
"nav.openscad.help": "在空白处左键拖动旋转,Shift+左键拖动框选,拖动草图几何可编辑;右键或中键拖动平移,Shift+右键或 Shift+中键拖动缩放",
"nav.perspective.sketch": "编辑草图时使用正交视图。完成草图后才能切换透视。",
"nav.solidworks.help": "中键拖动旋转,Ctrl+中键拖动平移,Shift+中键拖动缩放,右键拖动旋转",
@@ -1439,6 +1542,93 @@
"nav.touchpad.pan": "平移(按住 Shift 并移动,无需鼠标按钮)",
"nav.touchpad.scroll": "触控板使用垂直滚动进行缩放。双指平移设置将保留供其他预设使用。",
"nav.touchpad.zoom": "缩放(垂直滚动或双指捏合)",
"navbar.agent_chat": "助手聊天面板",
"navbar.agent_cursor": "显示智能体光标",
"navbar.ambient_occlusion": "环境光遮蔽",
"navbar.assistant": "助手",
"navbar.custom.add_slot": "添加{slot}",
"navbar.custom.always": "始终显示",
"navbar.custom.available": "{available} · 拖到栏上,或点击添加",
"navbar.custom.buttons": "按钮",
"navbar.custom.compact": "紧凑",
"navbar.custom.count": "{count} / 16 个槽位",
"navbar.custom.customise": "自定义导航栏…",
"navbar.custom.design": "设计",
"navbar.custom.duplicate": "此槽位已在栏上。",
"navbar.custom.fade": "淡化",
"navbar.custom.full": "请先移除一个槽位以添加其他槽位。",
"navbar.custom.hidden_design": "在设计中隐藏",
"navbar.custom.hidden_render": "在渲染中隐藏",
"navbar.custom.hide": "隐藏导航栏",
"navbar.custom.hide_idle": "悬停时显示",
"navbar.custom.icon_only": "仅图标",
"navbar.custom.icon_value": "图标和值",
"navbar.custom.icons": "图标",
"navbar.custom.idle": "空闲时",
"navbar.custom.intro": "选择3D视图底部导航栏中的控件及其顺序。拖动槽位可移动,拖出栏外可移除。",
"navbar.custom.labels": "图标和标签",
"navbar.custom.left": "左移",
"navbar.custom.position": "位置",
"navbar.custom.position_centre": "居中",
"navbar.custom.position_left": "左",
"navbar.custom.position_right": "右",
"navbar.custom.preview_as": "预览为",
"navbar.custom.regular": "常规",
"navbar.custom.remove": "移除",
"navbar.custom.remove_bar": "从栏中移除",
"navbar.custom.render": "渲染",
"navbar.custom.reset": "重置导航栏",
"navbar.custom.reset_default": "恢复默认",
"navbar.custom.right": "右移",
"navbar.custom.select": "未选择槽位。选择栏上的槽位即可移动、移除或更改其外观。",
"navbar.custom.separators_full": "导航栏已有4个分隔线。",
"navbar.custom.show": "显示导航栏",
"navbar.custom.shows": "显示内容",
"navbar.custom.size": "大小",
"navbar.custom.stale": "导航栏已更改。请重新选择槽位。",
"navbar.custom.title": "导航栏",
"navbar.custom.unknown": "此槽位不可用。",
"navbar.description.ambient_occlusion": "加深凹槽和角落的阴影,增加深度感。",
"navbar.description.display": "设置图形预设、网格、地面阴影、环境光遮蔽和投影。",
"navbar.description.fit": "完整显示所选对象;未选择时显示整个模型。",
"navbar.description.grid": "显示或隐藏地面网格。",
"navbar.description.ground_shadow": "显示或隐藏模型下方的阴影。",
"navbar.description.home": "返回显示整个模型的等轴测视图。",
"navbar.description.look_at": "使视图正对所选面、平面或打开的草图。",
"navbar.description.orbit": "围绕模型旋转视图。",
"navbar.description.pan": "向左右或上下平移视图。",
"navbar.description.projection": "切换正交视图和透视视图。",
"navbar.description.separator": "用于分组相邻槽位的细分隔线。",
"navbar.description.spin": "持续旋转视图,直到点击或按键停止。",
"navbar.description.visual_style": "切换着色、线框或带隐藏边线等模型绘制方式。",
"navbar.description.zoom": "将视图拉近或远离模型。",
"navbar.display": "显示",
"navbar.fit": "适合视图",
"navbar.graphics": "图形",
"navbar.grid": "网格",
"navbar.ground_shadow": "地面阴影",
"navbar.home": "主视图",
"navbar.later": "稍后提供",
"navbar.look_at": "正视",
"navbar.more": "更多",
"navbar.orbit": "环绕",
"navbar.orthographic": "正交",
"navbar.pan": "平移",
"navbar.perspective": "透视",
"navbar.preset": "预设",
"navbar.projection": "透视投影",
"navbar.projection_heading": "投影",
"navbar.separator": "分隔线",
"navbar.show": "显示",
"navbar.spin": "连续环绕",
"navbar.style.shaded": "着色",
"navbar.style.shaded_with_edges": "带边线着色",
"navbar.style.shaded_with_hidden_edges": "带隐藏边线着色",
"navbar.style.wireframe": "线框",
"navbar.translucent": "半透明",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "视觉样式",
"navbar.zoom": "缩放",
"needs two joints": "需要两个接头",
"network.allow_once": "仅允许一次",
"network.always_allow": "始终允许此服务器",
@@ -1449,9 +1639,34 @@
"no hole": "无孔",
"no interference": "无干涉",
"no joint that moves yet": "尚无运动接头",
"no motion study yet": "尚无运动分析",
"no picture": "无图片",
"no such joint": "没有这个接头",
"none": "无",
"not a move": "不是移动",
"not a number": "不是数字",
"open a sketch first": "请先打开一个草图",
"parts.automatic_name": "自动",
"parts.dimension.across_flats": "对边宽度",
"parts.dimension.bore": "内径",
"parts.dimension.d": "公称直径",
"parts.dimension.head_diameter": "头部直径",
"parts.dimension.head_height": "头部高度",
"parts.dimension.height": "高度",
"parts.dimension.inner": "内径",
"parts.dimension.outer": "外径",
"parts.dimension.pitch": "螺距",
"parts.dimension.socket": "内六角对边",
"parts.dimension.socket_depth": "内六角深度",
"parts.dimension.thickness": "厚度",
"parts.dimension.width": "宽度",
"parts.family.bearing": "深沟球轴承(外形)",
"parts.family.dowel_pin": "圆柱销",
"parts.family.hex_bolt": "六角头螺栓",
"parts.family.hex_nut": "六角螺母",
"parts.family.set_screw": "内六角平端紧定螺钉",
"parts.family.socket_head_cap_screw": "内六角圆柱头螺钉",
"parts.family.washer": "平垫圈",
"pattern.alignment_2": "对齐 2",
"pattern.alignment_hint": "数量包含原始图形。居中时副本分布在两侧;数量为偶数时,反转可切换多一个副本的一侧。",
"pattern.direction_1": "方向 1",
@@ -1467,9 +1682,25 @@
"perf.ui_time": "界面耗时",
"perf.viewport": "视图",
"perf.worst": "最差",
"pick a body or some of its faces": "请选择一个实体或它的若干个面",
"pick a hole to seat it, or OK places it at the origin": "选择一个孔放置,或单击确定放置在原点",
"pick a planar face": "请选择一个平面",
"pick a plane or a face as the tool": "请选择一个平面或一个面作为工具",
"pick a size": "请选择尺寸",
"pick edges of a body": "请选择实体的边",
"pick edges of one body": "请选择同一个实体的边",
"pick edges of the holes to remove": "请选择要移除的孔的边",
"pick faces of one body": "请选择同一个实体的面",
"pick faces to offset": "请选择要偏移的面",
"pick lines of one sketch": "请选择同一个草图的直线",
"pick one or two vertices, edges or faces": "选择一个或两个顶点、边或面",
"pick one plane or face as the tool, or sketch curves": "请选择一个平面或一个面作为工具,或选择草图曲线",
"pick sections in two or more sketches": "请选择位于两个或更多草图中的截面",
"pick sketch curves or edges": "请选择草图曲线或边",
"pick the face to untrim": "请选择要取消修剪的面",
"pick the path": "选择路径",
"pick what to keep": "请选择要保留的部分",
"pick what to keep of the other surface": "请选择另一个曲面上要保留的部分",
"prefs.add_item": "添加项目",
"prefs.alt_frees_manipulators": "Alt / Option 也可自由拖动操纵器箭头",
"prefs.anti_aliasing_amd_dx12": "由于启动检查在启用多重采样时未绘制任何内容,而在1×时通过了检查,抗锯齿已设为1×。您可以在上方选择其他设置;重启后若检查通过,该设置将生效。",
@@ -1837,6 +2068,64 @@
"render.effects_help": "组合有序颜色风格和图像空间镜头效果。渲染和原始母版重新调整使用相同保存设置。原始 EXR 保持不变。这些是原创艺术控制,不是校准镜头或品牌胶片仿真。",
"render.effects_reset_lens": "重置镜头效果",
"render.effects_seed": "图案种子",
"render.emitted_axis": "发射轴",
"render.error_area_samples": "area_samples 必须为 1、4、16 或 64",
"render.error_binding_allocation": "无法分配材质绑定",
"render.error_body_bound": "产品预览超出捕获实体数上限",
"render.error_checkpoint_dimensions": "检查点尺寸与捕获的请求不同",
"render.error_decode_budget": "图像解码预算溢出",
"render.error_denoise_setting": "原生降噪设置无效",
"render.error_display_dimensions": "图像显示尺寸无效",
"render.error_display_fit": "图像显示无法适配此设备",
"render.error_display_height": "显示高度溢出",
"render.error_display_width": "显示宽度溢出",
"render.error_duplicate_face": "产品面外观重复",
"render.error_export_document": "选择目标位置时渲染导出文档已更改",
"render.error_face_cap": "产品预览超出面外观数量上限",
"render.error_finish_gesture": "请先完成建模操作再预览",
"render.error_finish_operation": "请先完成当前建模操作再进入渲染",
"render.error_fixed_preview": "固定工作室预览要求曝光为 0、环境旋转为 0、强度为 1",
"render.error_geometry_size": "产品几何数据大小溢出",
"render.error_glass_recipe": "未知的玻璃配方",
"render.error_gpu_preview": "此主机不支持 GPU 产品预览。已保存的设置仍可使用。",
"render.error_gpu_samples": "不支持的 GPU 采样数",
"render.error_image_dimensions": "渲染图像尺寸与任务不匹配",
"render.error_image_profile": "渲染图像超出捕获的资源配置",
"render.error_interactive_command": "未绑定的交互式渲染命令",
"render.error_job_action": "不是交互式图像任务操作",
"render.error_job_identity": "渲染任务标识无效:{error}",
"render.error_library_reply": "渲染库响应无效",
"render.error_material_binding": "缺少材质绑定",
"render.error_no_completed_image": "没有已完成的渲染图像",
"render.error_no_geometry": "没有产品几何形状",
"render.error_no_scene": "没有产品场景",
"render.error_opacity": "产品外观不透明度无效",
"render.error_pbr_opacity": "不透明 PBR 要求不透明度为 1",
"render.error_physical_glass": "所选配方不是物理玻璃",
"render.error_preview_device": "产品预览需要带深度缓冲区的设备",
"render.error_product_triangle": "产品三角形无效",
"render.error_provisional_identity": "临时渲染标识或采样数无效",
"render.error_quality_bounds": "质量映射超出原生限制",
"render.error_quality_method": "质量映射要求相同的显式 GPU 方法",
"render.error_quality_projection": "原生质量映射无效",
"render.error_regrade_identity": "重新调色标识无效:{error}",
"render.error_scene_bodies": "缺少渲染场景实体",
"render.error_scene_body_limit": "渲染场景超出实体数上限",
"render.error_scene_identity": "渲染场景标识无效",
"render.error_setup_panicked": "GPU 路径追踪器初始化异常",
"render.error_setup_stopped": "初始化任务停止且未返回主机",
"render.error_setup_worker": "无法启动初始化任务:{error}",
"render.error_source_preview": "源预览超出字节数上限",
"render.error_surface_normals": "PBR 要求非零表面法线",
"render.error_surface_reply": "已创作表面响应无效",
"render.error_triangle_bound": "产品预览超出源数据八百万三角形上限",
"render.error_triangle_count": "产品三角形数溢出",
"render.error_upload_slot": "产品预览上传槽不可用",
"render.error_vertex_allocation": "产品预览顶点内存分配失败",
"render.error_vertex_envelope": "产品预览超出 {limit} MiB 顶点数据上限;未简化几何形状",
"render.error_vertex_packing": "产品预览打包与允许的顶点数据不符",
"render.error_visible_solid": "请在设计中创建可见实体以在此预览。",
"render.exit_focus": "退出专注视图",
"render.export_display": "导出:显示 PNG",
"render.export_image_label": "导出图像",
"render.export_linear": "导出:原始线性 EXR",
@@ -1850,6 +2139,7 @@
"render.flare_streak": "变形镜头风格光条",
"render.flare_strength": "高光耀斑强度",
"render.flare_threshold": "场景线性耀斑阈值",
"render.fold_browser": "折叠浏览器",
"render.gpu_depth": "最大路径深度",
"render.gpu_options_help": "采样数、深度、种子和曝光会随此配置保存。仅保存当前图像方法。",
"render.gpu_path_failed": "GPU 路径追踪器不可用",
@@ -1907,11 +2197,13 @@
"render.image_use_largest": "使用此宽高比下的最大尺寸:",
"render.image_width": "宽度",
"render.include_rig_cards": "包含被动反光板和遮光板",
"render.inner_half_angle": "内半角",
"render.inspect_scene": "刷新捕获的场景摘要",
"render.inspector": "检查器",
"render.keep_editing": "继续编辑",
"render.layer_down": "下移",
"render.layer_enabled": "启用此层",
"render.layer_off_suffix": "(关闭)",
"render.layer_remove": "删除层",
"render.layer_strength": "层强度",
"render.layer_up": "上移",
@@ -2059,6 +2351,7 @@
"render.optics_save": "将此光学设置保存到场景",
"render.optics_saved": "已保存光学目标",
"render.optics_saved_help": "定义、特征及实例的确切标识在离线重开后保留。拒绝缺失、替换或隐藏的目标;工程材料保持不变。移除目标前先保存或放弃数值编辑。",
"render.outer_half_angle": "外半角",
"render.output_format_status": "PNG 是完成的显示图像。可选 GPU EXR 保留显示滤镜前的原始线性 FLOAT32 辐亮度;导出不会替换成预览缓存或其他任务。",
"render.output_lock_ratio": "锁定宽高比",
"render.output_over_budget": "请求图像超出所选资源范围;请明确选择兼容尺寸或配置,不会自动降级。",
@@ -2092,7 +2385,10 @@
"render.physical_prepare_plan": "准备创建计划(不应用)",
"render.physical_separate": "外观不等于材料识别。这些是有来源的参考,不是经认证的等效属性。现有质量、工程材料和光学设置保持不变。",
"render.physical_unknown": "尚未确定数值候选资料。必须指定牌号、配方或构造;未知不等于零。",
"render.pick_body": "实体",
"render.pick_component": "组件",
"render.pick_face": "面",
"render.pick_help": "选择实体、面或组件。单击空白处清除选择;Shift 或 Ctrl 可添加或切换选择。高亮仅显示在实时产品视图中。",
"render.pick_label": "拾取",
"render.pick_up_label": "拾取",
"render.pick_waiting": "暂不支持产品拾取。",
@@ -2114,6 +2410,12 @@
"render.preview_upload": "实时预览顶点数据量",
"render.preview_upload_help": "这是精确的预览顶点字节数,不是 GPU 或进程总内存;几何不会简化。图像任务使用各自的准入检查和照明。",
"render.progressive_image_summary": "预览 PNG · 不透明 PBR · 渐进采样",
"render.property_conditions": "条件:{value}",
"render.property_fallback": "属性",
"render.property_qualifier": "限定条件:{value}",
"render.property_source": "来源:{id} - {locator}",
"render.property_uncertainty": "不确定度:{value}",
"render.property_unknown": "未知",
"render.quality_ack": "确认固定预算映射和省略项",
"render.quality_apply": "使用此固定采样预算",
"render.quality_projection_help": "Q 预设包含未来需求。此操作仅映射受支持的固定样本 PNG 预算,明确省略自适应停止、原始线性输出和独立透射限制。",
@@ -2129,6 +2431,7 @@
"render.replace_saved_surface": "替换此目标已有的保存绑定",
"render.restore_camera": "恢复已保存相机",
"render.result_actual_help": "一个图像像素对应一个屏幕像素。",
"render.result_actual_size": "100%",
"render.result_capture": "捕获版本",
"render.result_current": "捕获的模型版本为当前版本。",
"render.result_empty": "尚无已完成的图像。请检查设置,然后开始渲染。",
@@ -2203,10 +2506,14 @@
"render.shot_rename": "重命名已保存镜头",
"render.shot_saved_only": "请先保存当前草稿;复制和重命名会保留精确的保存选项与资源引用。",
"render.show_shots_label": "显示镜头条",
"render.size_4k_uhd": "4K 超高清",
"render.size_full_hd": "全高清",
"render.size_hd": "HD",
"render.sky_ground": "地面 · 线性 RGB",
"render.sky_horizon": "地平线 · 线性 RGB",
"render.sky_zenith": "天顶 · 线性 RGB",
"render.soft_focus": "柔焦",
"render.spot_cone": "聚光锥",
"render.stage_frame": "构图",
"render.stage_light": "照明",
"render.stage_look": "外观",
@@ -2257,9 +2564,45 @@
"render.subsurface_enable": "内部散射随机游走",
"render.subsurface_help": "仅适用于封闭介质。散射和RGB吸收使用独立的每毫米系数。路径在实际几何内部散射,并在边界折射或反射。关闭直线透射阴影、表面降噪和外部体积;使用一个菲涅耳分层。这不是扩散着色器、密度网格或实测材料。高密度可能需要更多样本和路径深度。",
"render.subsurface_rate": "散射碰撞率",
"render.tone_aces_fitted": "ACES 拟合",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "GPU 玻璃支持经过验证且互不相交的介质;不支持任意嵌套介质,也不提供无噪声透射估计器。",
"render.transmission_strata": "条件菲涅耳分层数",
"render.transmission_strata_help": "1保留原始序列。2或4条子路径对首次玻璃反射或透射选择进行分层,不改变斯涅尔定律和吸收规律。更多路径增加计算量;这不是降噪、嵌套介质支持或加速保证。",
"render.tree_add_light": "添加灯光",
"render.tree_add_shot": "添加镜头",
"render.tree_browser": "渲染浏览器",
"render.tree_by_look": "按外观",
"render.tree_by_object": "按对象",
"render.tree_constant": "恒定环境光",
"render.tree_default": "默认",
"render.tree_directional": "平行光",
"render.tree_environment": "环境",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} 个面",
"render.tree_face_one": "{count} 个面",
"render.tree_fixed_studio": "固定工作室",
"render.tree_hdr": "HDR",
"render.tree_lights": "灯光",
"render.tree_lights_pending": "命名灯光命令尚不可用。",
"render.tree_mixed": "混合",
"render.tree_more": "另有 {count} 个",
"render.tree_mute": "静音灯光",
"render.tree_no_environment": "无环境",
"render.tree_objects": "对象",
"render.tree_output": "输出",
"render.tree_point": "点光源",
"render.tree_rectangle": "矩形光",
"render.tree_search": "搜索对象",
"render.tree_selection": "渲染选择",
"render.tree_shots": "镜头",
"render.tree_sky": "天空",
"render.tree_solo": "独显灯光",
"render.tree_spot": "聚光灯",
"render.tree_sun": "太阳",
"render.tree_switch": "切换",
"render.tree_user_one": "{count} 个对象",
"render.tree_users": "{count} 个对象",
"render.unavailable_preview": "此设置请求了不可用的预览配置。",
"render.unsaved": "未保存的预览更改",
"render.use_preview": "使用集成预览",
@@ -2303,6 +2646,26 @@
"search.try": "输入命令名称、此设计中的特征或参数。要带值运行命令,请输入其ID和JSON对象:{example}",
"search.valid": "有效",
"section.off_hint": "未选择平面:按“确定”将移除剖面。",
"select a direction (an axis, a sketch line or a straight edge) first": "请先选择方向(轴、草图直线或直边)",
"select a direction (an axis, a sketch line or a straight edge) for the profile to follow": "请选择轮廓所沿的方向(轴、草图直线或直边)",
"select a point on a component": "选择组件上的一个点",
"select a profile, edges or sketch lines first": "请先选择轮廓、边或草图直线",
"select an axis": "请选择一个轴",
"select an axis, a straight or circular edge, or a cylinder, cone or torus face first": "请先选择轴、直边或圆边,或圆柱面、圆锥面或圆环面",
"select bodies first": "请先选择实体",
"select corner points, or the two lines of one corner": "请选择角点,或同一个角的两条直线",
"select one corner point, or the two lines of one corner": "请选择一个角点,或同一个角的两条直线",
"select sheet edges first": "请先选择钣金边",
"select the bend line (a sketch line) first": "请先选择折弯线(草图直线)",
"select the cam's profile (a sketch profile or the cam's edges)": "请选择凸轮的轮廓(草图轮廓或凸轮的边)",
"select the corner to cut first": "请先选择要切除的角",
"select the corners to round first": "请先选择要倒圆的角",
"select the fixed face first (a plate's large face)": "请先选择固定面(板的大面)",
"select the frame sketch's lines first": "请先选择框架草图的直线",
"select the path (sketch lines across the edge)": "请选择路径(横跨边的草图直线)",
"select the rim face first": "请先选择边缘面",
"select the sheet edge first": "请先选择钣金边",
"select two components": "请选择两个组件",
"set by the sketch's lines": "由草图的线条决定",
"settings.display_quality_note": "仅影响显示,不影响设计和导出。",
"settings.frame_rate_details_note": "添加最近各帧耗时的图表(叠加绘制的三角形数)、帧耗时直方图以及 GPU 绘制的内容。点击视图中的帧率可显示或隐藏。",
@@ -2320,17 +2683,23 @@
"settings.window_system_details": "详情",
"settings.window_system_note_now": "重启后生效。当前:{now}。",
"settings.window_system_wayland_limited": "在原生 Wayland 下部分功能受限。",
"sheet.flange_type_base": "基体",
"sheet.flange_type_contour": "轮廓",
"sheet.flange_type_edge": "边线",
"sheet.no_body": "没有钣金实体:请使用法兰 > Base 创建,或使用转换为钣金将板材转换为钣金(选择其较大的平面)。",
"shortcut.json_error": "参数必须采用 JSON 格式:{error}",
"shortcut.no_command": "没有命令 `{id}`;JSON 前的文本必须是命令 ID",
"shortcut.pin": "固定到 S 框顶部",
"shortcut.unpin": "取消固定",
"sketch is missing": "草图不存在",
"sketch.degrees_of_freedom": "{count} 个自由度",
"sketch.dof_left": "剩余 {count} 个自由度",
"sketch.dof_left_one": "剩余 {count} 个自由度",
"sketch.draw_curves": "绘制为 {linetype}",
"sketch.make_selection": "将选择转换为 {linetype}",
"sketch.open_ends": "开放 {count}",
"sketch.status_conflict": "约束冲突",
"sketch.status_fully_constrained": "完全约束",
"sketch.untied_ends": "未约束 {count}",
"sketch_panel.attached": "附着到 {body} / {path}",
"sketch_panel.author": "创建时的放置:{path}",
@@ -2357,7 +2726,24 @@
"sketch_text.path_hint": "文字所跟随的草图曲线:先单击此处,再选择曲线",
"sketch_text.use_font_file": "使用字体文件 {path}",
"solid": "实心",
"the angle must be a number": "角度必须是数字",
"the curves must be in one sketch": "曲线必须位于同一个草图中",
"the direction must be an axis, a sketch line or a straight edge": "方向必须是轴、草图直线或直边",
"the duration must be a number of seconds, 0.001 or more": "时长必须是不小于 0.001 的秒数",
"the line's sketch is gone": "该直线所在的草图已不存在",
"the lines must be in one sketch": "直线必须位于同一个草图中",
"the lines must be in one sketch, not the section's": "直线必须位于同一个草图中,且不能是截面所在的草图",
"the parts library is empty": "零件库是空的",
"the parts library is not available": "零件库不可用",
"the path curves must be in one other sketch": "路径曲线必须位于同一个另外的草图中",
"the path's sketch is gone": "路径所在的草图已不存在",
"the position must be a number": "位置必须是数字",
"the preview failed": "预览失败",
"the profiles and curves must be in one sketch": "轮廓和曲线必须位于同一个草图中",
"the reference face must be on the edges' body": "参考面必须位于这些边所属的实体上",
"the scale must be above 0": "缩放比例必须大于 0",
"the section's profiles must be in one sketch": "截面的轮廓必须位于同一个草图中",
"the two origins are on the same component": "这两个原点位于同一个组件上",
"thread.automatic_size": "自动尺寸",
"thread.designation": "螺纹标记",
"thread.direction": "螺纹方向",
@@ -2397,6 +2783,7 @@
"trace.points": "路径上的 {count} 个点",
"trace.stopped_by_contact": "在采样 {sample} 处结束:{a} 会穿过 {b}",
"trace.stopped_by_loop": "在采样 {sample} 处结束:经过 {joint} 的环路无法再闭合",
"trim by sketch curves, or by one plane or face": "请用草图曲线修剪,或用一个平面或面修剪",
"ui.1_degree_of_freedom": "1 个自由度",
"ui.3d_mouse_axes_reassigned": "轴已在偏好设置中重新分配,在此次校准之上仍然生效。",
"ui.3d_mouse_button": "按钮 {number}",
@@ -2873,6 +3260,8 @@
"ui.design_properties.revision": "版本",
"ui.diameter": "直径",
"ui.dimension": "尺寸",
"ui.direct_interaction": "直接交互",
"ui.direct_interaction_note": "在视口中直接处理模型。按住平面或轮廓并拖动:向上为拉伸,向下进入实体为切除,横向移动设置步长",
"ui.direction": "方向",
"ui.display_quality": "显示质量",
"ui.display_quality_coarse": "粗糙",
@@ -2896,6 +3285,7 @@
"ui.editJointLimits": "编辑接头限制",
"ui.edit_section_analysis": "编辑截面分析",
"ui.ellipse": "椭圆",
"ui.emboss_wrap_note": "与受支持圆柱相切的正交线轮廓会自动缠绕。选择一个壁以指定目标。",
"ui.end_radius": "结束半径",
"ui.end_scale": "末端缩放",
"ui.entities": "实体",
@@ -2968,6 +3358,7 @@
"ui.heading_extrude": "拉伸",
"ui.heading_fillet": "圆角",
"ui.heading_finish_sketch": "完成草图",
"ui.heading_form": "造型",
"ui.heading_front": "前视",
"ui.heading_hole": "孔",
"ui.heading_home": "主页",
@@ -3016,6 +3407,7 @@
"ui.heading_utilities": "工具",
"ui.heading_utility": "实用工具",
"ui.heading_weldments": "焊件",
"ui.height": "高度",
"ui.help": "帮助",
"ui.hide": "隐藏",
"ui.hideAxes": "隐藏轴",
@@ -3053,11 +3445,14 @@
"ui.intersect": "相交",
"ui.isolate": "隔离",
"ui.join": "连接",
"ui.joint_play": "▶ 播放",
"ui.joint_stop": "■ 停止",
"ui.joints": "关节",
"ui.keyboard_shortcuts": "键盘快捷键",
"ui.language": "语言",
"ui.layout_compact": "紧凑",
"ui.layout_floating": "浮动",
"ui.length": "长度",
"ui.length_decimals": "长度小数位",
"ui.light": "浅色",
"ui.line": "直线",
@@ -3069,6 +3464,7 @@
"ui.loft": "放样",
"ui.look_at": "朝向",
"ui.look_at_anim_desc": "轴视图、注视、主视图与适合窗口",
"ui.major_radius": "大半径",
"ui.manipulator_free_alt": "操纵器自由拖动也适用于 Alt/Option",
"ui.manipulator_free_alt_tip": "开:在拉伸/小控件箭头上按 Alt/Option 或 Ctrl/Cmd 可关闭数值捕捉。关:仅 Ctrl/Cmd。",
"ui.manufacture": "制造",
@@ -3098,8 +3494,10 @@
"ui.mesh_format_3mf": "3MF",
"ui.mesh_format_3mf_tagged": "带面标签的 3MF",
"ui.mesh_format_stl": "STL",
"ui.minor_radius": "小半径",
"ui.mirror": "镜像",
"ui.mirror_line": "镜像线",
"ui.modifiers_either": "{first} 或 {second}",
"ui.move": "移动",
"ui.multiple": "多个",
"ui.named_views": "命名视图",
@@ -3156,6 +3554,7 @@
"ui.pinToShortcuts": "固定到快捷方式",
"ui.pinToToolbar": "固定到工具栏",
"ui.pipe": "管道",
"ui.pitch": "螺距",
"ui.placement": "放置",
"ui.placement_handles": "放置手柄",
"ui.placement_handles_tip": "垫块、凸台或卡扣预览上的手柄:拖动标记在模型上移动,用转环旋转",
@@ -3218,6 +3617,7 @@
"ui.reverse_horizontal_pan_direction": "反转水平平移方向",
"ui.reverse_horizontal_pan_tip": "水平双指滚动和拇指滚轮向相反方向平移",
"ui.reverse_zoom_direction": "反转缩放方向",
"ui.revolutions": "圈数",
"ui.revolve": "旋转",
"ui.ribbon_exit": "退出",
"ui.ribbon_labels": "显示功能区图标下的文字",
@@ -3234,6 +3634,7 @@
"ui.scale": "缩放",
"ui.second_rail": "第二导轨",
"ui.section_analysis": "截面分析",
"ui.section_size": "截面尺寸",
"ui.select": "选择",
"ui.selectOther": "选择其他…",
"ui.selectTangentChain": "选择相切链",
@@ -3305,6 +3706,7 @@
"ui.start_page": "起始页",
"ui.step_values": "使用方向键和滚轮调整数值",
"ui.step_values_tip": "在正在输入的数值框中,上下方向键和框上的鼠标滚轮可将数字增减 1(Shift:10,Alt:0.1)。表达式保持不变。",
"ui.stitch_tolerance_hint": "严格",
"ui.stretch": "伸展",
"ui.supersampling": "超级采样 (SSAA)",
"ui.supersampling_adaptive": "仅在视图静止时",
@@ -3335,6 +3737,8 @@
"ui.to_object": "到对象",
"ui.tool_direction": "刀具方向",
"ui.top": "上视",
"ui.top_diameter": "顶部直径",
"ui.top_radius": "顶部半径",
"ui.torus": "圆环体",
"ui.total_angle": "总角度",
"ui.trackpad_pan_tip": "双指滚动平移;Fusion 预设下,Shift + 双指滚动旋转视图。关闭时滚动缩放。鼠标滚轮和双指捏合缩放,拇指滚轮横向平移。",
@@ -3363,6 +3767,7 @@
"ui.visual_shaded_with_edges": "带边着色",
"ui.visual_style": "视觉样式",
"ui.visual_wireframe": "线框",
"ui.width": "宽度",
"ui.window_system": "窗口系统",
"ui.window_system_auto": "自动",
"ui.window_system_wayland": "Wayland",
@@ -3423,6 +3828,9 @@
"update.up_to_date": "SolidCraft 已是最新版本。",
"update.update_now": "立即更新",
"update.you_have": "当前版本为 {version}。",
"use a positive nominal diameter and a pitch smaller than it": "请使用正的公称直径,且螺距小于公称直径",
"values must be finite numbers": "值必须是有限数字",
"values must be numbers or expressions": "值必须是数字或表达式",
"view.auto_ortho_faces": "旋转时透视,正对表面时正交",
"web.files.insert_drawings_hint": "将 CAD 文件、网格、DXF 或 SVG 插入当前设计",
"web.files.insert_stored_drawings_hint": "插入当前设计(CAD 文件、网格、DXF、SVG)",
+17
View File
@@ -8,6 +8,15 @@ const fn icon_primary(rgb: [u8; 3]) -> Color32 {
impl Tokens {
pub const fn light() -> Tokens {
Tokens {
nav_hover: Color32::from_rgb(233, 237, 242),
nav_press: Color32::from_rgb(220, 226, 234),
nav_dim: Color32::from_rgb(136, 149, 167),
nav_viewport: Color32::from_rgb(238, 241, 245),
nav_tip: Color32::from_rgb(27, 36, 48),
nav_tip_ink: Color32::from_rgb(255, 255, 255),
nav_tip_key_border: Color32::from_rgba_unmultiplied_const(128, 140, 160, 153),
nav_field: Color32::from_rgb(255, 255, 255),
borders: crate::theme::Borders::LEGACY,
icon_palette: None,
file_dim: Color32::from_rgb(58, 70, 86),
@@ -314,6 +323,14 @@ impl Tokens {
t.render_ink = Color32::from_rgb(224, 116, 174);
t.render_soft = Color32::from_rgb(64, 35, 54);
t.tab_on_fill_dark = Color32::BLACK;
t.nav_hover = Color32::from_rgb(58, 65, 80);
t.nav_press = Color32::from_rgb(70, 78, 96);
t.nav_dim = Color32::from_rgb(124, 135, 154);
t.nav_viewport = Color32::from_rgb(38, 43, 53);
t.nav_tip = Color32::from_rgb(238, 241, 245);
t.nav_tip_ink = Color32::from_rgb(27, 36, 48);
t.nav_tip_key_border = Color32::from_rgba_unmultiplied_const(128, 140, 160, 153);
t.nav_field = Color32::from_rgb(47, 52, 62);
t.dialog_body = Color32::from_rgb(39, 43, 52);
t.dialog_footer = Color32::from_rgb(47, 52, 62);
t.dialog_rule = Color32::from_rgb(53, 59, 71);
+8
View File
@@ -101,6 +101,14 @@
"mesh_fill": "#ffffff",
"mesh_ink": "#ffffff",
"mesh_soft": "#000000",
"nav_dim": "#ffffff",
"nav_field": "#000000",
"nav_hover": "#000000",
"nav_press": "#ffffff",
"nav_tip": "#ffffff",
"nav_tip_ink": "#000000",
"nav_tip_key_border": "#000000",
"nav_viewport": "#000000",
"on_accent": "#000000",
"origin_plane": "#000000",
"origin_plane_edge": "#ffffff",
+8
View File
@@ -101,6 +101,14 @@
"mesh_fill": "#000000",
"mesh_ink": "#000000",
"mesh_soft": "#ffffff",
"nav_dim": "#000000",
"nav_field": "#ffffff",
"nav_hover": "#ffffff",
"nav_press": "#000000",
"nav_tip": "#000000",
"nav_tip_ink": "#ffffff",
"nav_tip_key_border": "#ffffff",
"nav_viewport": "#ffffff",
"on_accent": "#ffffff",
"origin_plane": "#ffffff",
"origin_plane_edge": "#000000",
+8
View File
@@ -101,6 +101,14 @@
"mesh_fill": "#55ff55",
"mesh_ink": "#55ff55",
"mesh_soft": "#000000",
"nav_dim": "#55ffff",
"nav_field": "#000000",
"nav_hover": "#aa00aa",
"nav_press": "#ff55ff",
"nav_tip": "#ffffff",
"nav_tip_ink": "#000000",
"nav_tip_key_border": "#55ffff",
"nav_viewport": "#000000",
"on_accent": "#000000",
"origin_plane": "#55ffff20",
"origin_plane_edge": "#55ffff80",
+348 -20
View File
@@ -3,7 +3,7 @@
//! a component's over the physical material's look; a body with none of these keeps the colour
//! it was imported with.
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};
use solidcraft_geom::Vec3;
@@ -129,6 +129,95 @@ impl Appearances {
pub fn is_empty(&self) -> bool {
self.bodies.is_empty() && self.faces.is_empty() && self.components.is_empty()
}
/// Bound bulk appearance operations, including designs read from untrusted files.
pub fn check_budget(&self) -> crate::Result<()> {
if self.bodies.len().saturating_add(self.faces.len()).saturating_add(self.components.len()) > 100_000 {
return Err(crate::DocError::Invalid("at most 100000 appearance overrides can be processed".into()));
}
Ok(())
}
/// Build a replacement without changing the source. Equality includes the label and
/// every optical value. Physical-material defaults are deliberately outside this scope.
/// `None` means no change, allowing callers to preserve history and revision.
pub fn replacing(&self, from: &Look, to: &Look, scope: Option<&AppearanceScope>) -> crate::Result<Option<(Self, usize)>> {
self.check_budget()?;
for look in [from, to] {
if !look.opacity.is_finite() || !(0.0..=1.0).contains(&look.opacity) {
return Err(crate::DocError::Invalid("opacity must be finite and in 0..1".into()));
}
look.opaque_surface()?;
}
if from == to {
return Ok(None);
}
let body_in_scope = |body: &str| scope.is_none_or(|s| s.bodies.contains(body));
let component_in_scope = |id: &u64| scope.is_none_or(|s| s.components.contains(id));
let count = self.bodies.iter().filter(|(body, look)| body_in_scope(body) && *look == from).count()
+ self.faces.iter().filter(|face| body_in_scope(&face.body) && &face.look == from).count()
+ self.components.iter().filter(|(id, look)| component_in_scope(id) && *look == from).count();
if count == 0 {
return Ok(None);
}
let mut replaced = self.clone();
for (body, look) in &mut replaced.bodies {
if body_in_scope(body) && look == from {
*look = to.clone();
}
}
for face in &mut replaced.faces {
if body_in_scope(&face.body) && &face.look == from {
face.look = to.clone();
}
}
for (id, look) in &mut replaced.components {
if component_in_scope(id) && look == from {
*look = to.clone();
}
}
Ok(Some((replaced, count)))
}
}
/// Exact override containers for replacement. A body includes its face overrides;
/// a component selects its own override, independently of the bodies it owns.
#[derive(Clone, Debug, Default)]
pub struct AppearanceScope {
pub bodies: BTreeSet<String>,
pub components: BTreeSet<u64>,
}
/// A target in an evaluated model. Face indices are those of `model.faces`.
#[derive(Clone, Copy, Debug)]
pub enum AppearanceTarget<'a> {
Body(&'a str),
Face { body: &'a str, face: usize },
Component(u64),
}
/// The four override steps, in descending precedence. Imported paint is a display
/// fallback, not an override or physical material, and is not a fifth step.
#[derive(Clone, Debug, PartialEq)]
pub struct AppearanceChain {
pub face: Option<Look>,
pub body: Option<Look>,
pub component: Option<Look>,
pub material: Option<Look>,
}
impl AppearanceChain {
pub fn steps(&self) -> [(&'static str, Option<&Look>); 4] {
[("face", self.face.as_ref()), ("body", self.body.as_ref()), ("component", self.component.as_ref()), ("material", self.material.as_ref())]
}
pub fn active(&self) -> Option<&'static str> {
self.steps().into_iter().find_map(|(step, look)| look.map(|_| step))
}
pub fn resolved(&self) -> Option<&Look> {
self.steps().into_iter().find_map(|(_, look)| look)
}
}
/// The built-in appearance library: (name, colour, opacity).
@@ -161,15 +250,96 @@ pub fn material_look(material: &str) -> Option<Look> {
}
impl Document {
/// Read the same precedence used by body and face display resolution. Components
/// have no material assignment of their own: the material step is present only
/// when their directly owned bodies all have the same material look. Empty or
/// mixed components have no material step. Root is not an assignable component.
pub fn appearance_chain(&self, state: &crate::ModelState, target: AppearanceTarget<'_>) -> crate::Result<AppearanceChain> {
self.appearances.check_budget()?;
match target {
AppearanceTarget::Body(name) | AppearanceTarget::Face { body: name, .. } => {
let body = state.body(name).ok_or_else(|| crate::DocError::Invalid(format!("no body `{name}`")))?;
let mut chain = self.body_appearance_chain(body.definition_name(), self.model_body_component(body));
if let AppearanceTarget::Face { face, .. } = target {
if face >= body.body.face_count() {
return Err(crate::DocError::Invalid("unknown face index".into()));
}
let mut overrides = Vec::new();
self.apply_face_overrides(body, &mut overrides);
chain.face = overrides.into_iter().find_map(|(index, look)| (index == face).then_some(look));
}
Ok(chain)
}
AppearanceTarget::Component(id) => {
if id == 0 || !self.components.iter().any(|c| c.id == id) {
return Err(crate::DocError::Invalid("unknown or root component".into()));
}
if state.bodies.len() > 100_000 {
return Err(crate::DocError::Invalid("too many bodies to read a component appearance chain".into()));
}
// Legacy ownership can refer to a feature. Index it once, rather
// than scanning the timeline for each body of a large component.
let features: BTreeMap<_, _> = self.features.iter().rev().map(|f| (f.id, f.component)).collect();
let owner = |b: &&crate::ModelBody| {
if b.transferred || b.source_name.is_some() {
b.component
} else {
self.body_components.get(&b.name).copied().or_else(|| features.get(&b.feature).copied()).unwrap_or(0)
}
};
let mut materials = state
.bodies
.iter()
.filter(|b| owner(b) == id)
.map(|b| self.materials.get(b.definition_name()).and_then(|m| self.material_look(m)));
let material = materials.next().flatten().filter(|first| materials.all(|look| look.as_ref() == Some(first)));
Ok(AppearanceChain { face: None, body: None, component: self.appearances.components.get(&id).cloned(), material })
}
}
}
fn body_appearance_chain(&self, name: &str, component: u64) -> AppearanceChain {
AppearanceChain {
face: None,
body: self.appearances.bodies.get(name).cloned(),
component: (component != 0).then(|| self.appearances.components.get(&component).cloned()).flatten(),
material: self.materials.get(name).and_then(|material| self.material_look(material)),
}
}
/// Resolve a picked face through the same appearance chain used by the viewport.
pub fn model_face_look(&self, body: &crate::ModelBody, face: usize) -> Option<Look> {
self.face_colors(body).into_iter().find(|(index, _)| *index == face).map(|(_, look)| look).or_else(|| self.model_display_look(body))
}
/// Body appearance including the imported fallback used by `body_color`.
pub fn model_display_look(&self, body: &crate::ModelBody) -> Option<Look> {
self.model_body_look(body).or_else(|| {
let color = body.body.color().or_else(|| body.imported.as_ref().and_then(|p| p.color))?;
Some(Look::custom(color.map(|v| (v.clamp(0.0, 1.0) * 255.0).round() as u8), self.model_body_opacity(body)))
})
}
/// Distinct appearances used by an object, including its face overrides. `None` is
/// the unassigned/imported body appearance. Repeated faces count as one object user.
pub fn model_used_looks(&self, body: &crate::ModelBody) -> Vec<Option<Look>> {
let faces = self.face_colors(body);
let mut looks = Vec::new();
if faces.len() < body.body.face_count() || faces.is_empty() {
looks.push(self.model_display_look(body));
}
for (_, look) in faces {
let look = Some(look);
if !looks.contains(&look) {
looks.push(look);
}
}
looks
}
/// Shared definition appearance for a computed occurrence body.
pub fn model_body_look(&self, body: &crate::ModelBody) -> Option<Look> {
let name = body.definition_name();
self.appearances
.bodies
.get(name)
.cloned()
.or_else(|| self.appearances.components.get(&self.model_body_component(body)).cloned())
.or_else(|| self.materials.get(name).and_then(|material| self.material_look(material)))
self.body_appearance_chain(body.definition_name(), self.model_body_component(body)).resolved().cloned()
}
/// Effective body opacity, including paint carried from an imported body.
pub fn model_body_opacity(&self, body: &crate::ModelBody) -> f64 {
@@ -182,15 +352,7 @@ impl Document {
/// A body's look (without face appearances): its own, else its component's, else its
/// material's.
pub fn body_look(&self, name: &str, feature: u64) -> Option<Look> {
self.appearances
.bodies
.get(name)
.cloned()
.or_else(|| {
let c = self.body_component(name, feature);
(c != 0).then(|| self.appearances.components.get(&c).cloned()).flatten()
})
.or_else(|| self.materials.get(name).and_then(|m| self.material_look(m)))
self.body_appearance_chain(name, self.body_component(name, feature)).resolved().cloned()
}
/// Face appearances on a body: (point on the face, look).
@@ -201,9 +363,19 @@ impl Document {
/// The faces of a body with appearances of their own: (B-rep face index, look). A later
/// assignment to the same face wins.
pub fn face_colors(&self, b: &crate::ModelBody) -> Vec<(usize, Look)> {
let mut out = self.imported_face_colors(b);
for (index, look) in self.authored_face_colors(b) {
out.retain(|(old, _)| *old != index);
out.push((index, look));
}
out
}
/// Imported paint alone, after applying body-appearance precedence.
pub(crate) fn imported_face_colors(&self, b: &crate::ModelBody) -> Vec<(usize, Look)> {
// An assigned body appearance replaces imported paint; design face appearances still win.
let to8 = |x: f32| (x.clamp(0.0, 1.0) * 255.0).round() as u8;
let mut out: Vec<(usize, Look)> = if self.appearances.bodies.contains_key(b.definition_name()) {
if self.appearances.bodies.contains_key(b.definition_name()) {
Vec::new()
} else {
match b.body.paint() {
@@ -219,7 +391,18 @@ impl Document {
None => Vec::new(),
},
}
};
}
}
/// Design-authored face overrides, without imported STEP paint. Linked designs carry
/// these independently so an inherited body look does not hide their face overrides.
pub fn authored_face_colors(&self, b: &crate::ModelBody) -> Vec<(usize, Look)> {
let mut out = Vec::new();
self.apply_face_overrides(b, &mut out);
out
}
fn apply_face_overrides(&self, b: &crate::ModelBody, out: &mut Vec<(usize, Look)>) {
for f in self.appearances.faces.iter().filter(|f| f.body == b.definition_name()) {
let (p, look) = (crate::apply_point(&b.source_transform, f.point), f.look.clone());
if f.strict_name {
@@ -259,7 +442,6 @@ impl Document {
out.push((i, look));
}
}
out
}
}
@@ -385,6 +567,28 @@ mod tests {
assert!(restored.iter().all(|(face, look)| *look == if *face == 0 { face_look.clone() } else { Look::custom([255, 0, 0], 0.5) }));
}
#[test]
fn linked_paint_retains_imported_faces_without_baking_authored_overrides() {
let mut state = crate::ModelState::default();
state.bodies.push(imported_box());
let body = &state.bodies[0];
let mut doc = Document::default();
doc.appearances.faces.push(FaceLook {
body: body.name.clone(),
point: Vec3::ZERO,
look: Look::custom([0, 255, 0], 1.0),
name: Some(crate::naming::face_names(body)[0].clone()),
strict_name: false,
certificate: None,
});
let exported = doc.painted(&state);
assert!(exported.bodies[0].body.paint().unwrap().faces.iter().any(|face| face.color == [0., 1., 0.]));
let linked = doc.painted_for_link(&state);
let faces = &linked.bodies[0].body.paint().unwrap().faces;
assert_eq!(faces.len(), body.body.faces(0.01).unwrap().len());
assert!(faces.iter().all(|face| face.color == [1., 0., 0.] && face.opacity == 0.5));
}
#[test]
fn body_appearance_overrides_imported_face_paint() {
check_imported_appearance_precedence(&imported_box());
@@ -400,6 +604,130 @@ mod tests {
check_imported_appearance_precedence(&body);
}
fn chain_fixture() -> (Document, crate::ModelState) {
let mut doc = Document::new("Appearance chain");
doc.components.push(crate::Component { id: 1, name: "Part".into(), ..Default::default() });
doc.body_components.insert("B".into(), 1);
let mut state = crate::ModelState::default();
state.bodies.push(crate::ModelBody::new("B".into(), solidcraft_kernel::box_solid(Vec3::ZERO, Vec3::new(10., 10., 10.)).unwrap(), 1));
(doc, state)
}
#[test]
fn appearance_chain_agrees_with_display_and_definition_identity() {
let (mut doc, mut state) = chain_fixture();
let body_look = library("ABS - Red").unwrap();
let face_look = library("Steel - Satin PBR").unwrap();
doc.appearances.bodies.insert("B".into(), body_look.clone());
doc.appearances.components.insert(1, library("ABS - Blue").unwrap());
doc.materials.insert("B".into(), "Brass".into());
let body = &state.bodies[0];
let spot = crate::naming::face_spots(body)[0].unwrap().point;
let face_name = crate::naming::face_names(body)[0].clone();
doc.appearances.faces.push(FaceLook {
body: "B".into(),
point: spot,
look: face_look.clone(),
name: Some(face_name),
strict_name: false,
certificate: None,
});
let chain = doc.appearance_chain(&state, AppearanceTarget::Face { body: "B", face: 0 }).unwrap();
assert_eq!(chain.active(), Some("face"));
assert_eq!(chain.resolved(), Some(&face_look));
assert_eq!(doc.model_face_look(body, 0).as_ref(), chain.resolved());
let chain = doc.appearance_chain(&state, AppearanceTarget::Body("B")).unwrap();
assert_eq!(chain.active(), Some("body"));
assert_eq!(doc.model_body_look(body).as_ref(), chain.resolved());
assert_eq!(doc.body_look("B", 1).as_ref(), chain.resolved());
assert_eq!(chain.component.as_ref().unwrap().name, "ABS - Blue");
assert_eq!(chain.material.as_ref().unwrap().name, "Brass");
// A computed placement resolves the definition's assignments, not its label.
state.bodies[0].name = "Occurrence/B".into();
state.bodies[0].source_name = Some("B".into());
state.bodies[0].component = 1;
let chain = doc.appearance_chain(&state, AppearanceTarget::Body("Occurrence/B")).unwrap();
assert_eq!(chain.body, Some(body_look));
assert_eq!(chain.material.as_ref().unwrap().name, "Brass");
assert!(doc.appearance_chain(&state, AppearanceTarget::Face { body: "Occurrence/B", face: usize::MAX }).is_err());
assert!(doc.appearance_chain(&state, AppearanceTarget::Body("missing")).is_err());
}
#[test]
fn appearance_chain_component_material_is_common_or_absent_and_imports_stay_fallbacks() {
let (mut doc, mut state) = chain_fixture();
state.bodies[0].imported = Some(std::sync::Arc::new(ImportedLook { color: Some([0.2, 0.4, 0.6]), ..Default::default() }));
let body = doc.appearance_chain(&state, AppearanceTarget::Body("B")).unwrap();
assert_eq!(body.active(), None);
assert!(doc.model_display_look(&state.bodies[0]).is_some());
doc.materials.insert("B".into(), "Brass".into());
assert_eq!(doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap().active(), Some("material"));
let mut second = state.bodies[0].clone();
second.name = "C".into();
doc.body_components.insert("C".into(), 1);
state.bodies.push(second);
assert_eq!(doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap().active(), None);
doc.materials.insert("C".into(), "Brass".into());
assert_eq!(doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap().active(), Some("material"));
doc.materials.insert("C".into(), "Steel".into());
assert_eq!(doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap().material, None);
doc.appearances.components.insert(1, library("ABS - Blue").unwrap());
assert_eq!(doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap().active(), Some("component"));
state.bodies.clear();
assert_eq!(doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap().material, None);
assert!(doc.appearance_chain(&state, AppearanceTarget::Component(0)).is_err());
assert!(doc.appearance_chain(&state, AppearanceTarget::Component(99)).is_err());
}
#[test]
fn appearance_replacement_validates_values_and_design_budget_without_mutation() {
let from = library("ABS - Red").unwrap();
let to = library("ABS - Blue").unwrap();
let mut appearances = Appearances::default();
appearances.bodies.insert("B".into(), from.clone());
for opacity in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY, -1., 2.] {
let mut invalid = to.clone();
invalid.opacity = opacity;
assert!(appearances.replacing(&from, &invalid, None).is_err());
assert!(appearances.replacing(&invalid, &to, None).is_err());
assert_eq!(appearances.bodies["B"], from);
}
let mut invalid = library("Steel - Satin PBR").unwrap();
invalid.opacity = 0.5;
assert!(appearances.replacing(&from, &invalid, None).is_err());
let (changed, count) = appearances.replacing(&from, &to, None).unwrap().unwrap();
assert_eq!(count, 1);
assert_eq!(changed.bodies["B"], to);
assert_eq!(appearances.bodies["B"], from);
assert!(appearances.replacing(&from, &from, None).unwrap().is_none());
for i in 0..100_000 {
appearances.components.insert(i, from.clone());
}
assert!(appearances.replacing(&from, &to, None).is_err());
let (mut doc, state) = chain_fixture();
doc.appearances = appearances;
assert!(doc.appearance_chain(&state, AppearanceTarget::Body("B")).is_err());
}
#[test]
fn appearance_chain_of_ten_thousand_body_component_has_four_steps() {
let (mut doc, mut state) = chain_fixture();
let mut body = state.bodies[0].clone();
body.source_name = Some("B".into());
body.component = 1;
state.bodies = (0..10_000)
.map(|i| {
let mut b = body.clone();
b.name = format!("Placed {i}");
b
})
.collect();
doc.materials.insert("B".into(), "Brass".into());
let chain = doc.appearance_chain(&state, AppearanceTarget::Component(1)).unwrap();
assert_eq!(chain.steps().len(), 4);
assert_eq!(chain.active(), Some("material"));
}
#[test]
fn library_and_materials() {
assert_eq!(library("abs - red").map(|l| l.color), Some([196, 40, 40]));
+43 -6
View File
@@ -2617,13 +2617,42 @@ pub struct StandardPart {
/// A component whose contents come from another design file (Insert Design): where that file
/// is, and the Import feature in the component that holds its bodies (Update Links replaces
/// them; Break Link keeps them and forgets the file).
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct DesignLink {
/// The design file: relative to this design's folder once this design is saved, else as
/// given (`/` separates folders).
pub path: String,
/// The Import feature holding the linked design's bodies.
pub feature: u64,
/// Last inherited values, by Import body slot. Differing assembly assignments are
/// local overrides and survive a source update. Older links start with no baseline.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub inherited: Vec<LinkedBodyProperties>,
}
/// The values last inherited by a linked body, not another editable material library.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct LinkedBodyProperties {
pub material: String,
/// SHA-256 of the inherited custom definition, for equality only. The complete
/// engineering card stays in user_materials, not duplicated once per linked body.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub material_fingerprint: Option<String>,
/// Explicit body/component look only: material fallback must remain a fallback.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub appearance: Option<crate::appearance::Look>,
/// Last inherited authored face overrides. None marks links saved before face
/// inheritance; Some(empty) records that the source has no authored face overrides.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub faces: Option<Vec<crate::appearance::FaceLook>>,
}
impl LinkedBodyProperties {
pub fn fingerprint(material: &UserMaterial) -> Result<String> {
use sha2::{Digest, Sha256};
let bytes = serde_json::to_vec(material).map_err(|e| DocError::Invalid(e.to_string()))?;
Ok(format!("{:x}", Sha256::digest(bytes)))
}
}
/// A name the design's counter hands out (`Body1`).
@@ -3131,14 +3160,22 @@ impl Document {
/// The model with each body carrying the colour, opacity and face colours it is shown with
/// (for export).
pub fn painted(&self, state: &crate::ModelState) -> crate::ModelState {
self.painted_with_faces(state, true)
}
/// Linked designs carry authored face overrides as editable properties. Their STEP
/// geometry keeps imported paint, without baking a second copy of those overrides.
pub fn painted_for_link(&self, state: &crate::ModelState) -> crate::ModelState {
self.painted_with_faces(state, false)
}
fn painted_with_faces(&self, state: &crate::ModelState, authored_faces: bool) -> crate::ModelState {
let mut st = state.clone();
for b in &mut st.bodies {
let c = self.body_color(b);
let faces: Vec<solidcraft_kernel::FacePaint> = self
.face_colors(b)
.into_iter()
.map(|(face, l)| solidcraft_kernel::FacePaint { face, color: l.rgb(), opacity: l.opacity as f32 })
.collect();
let face_colors = if authored_faces { self.face_colors(b) } else { self.imported_face_colors(b) };
let faces: Vec<solidcraft_kernel::FacePaint> =
face_colors.into_iter().map(|(face, l)| solidcraft_kernel::FacePaint { face, color: l.rgb(), opacity: l.opacity as f32 }).collect();
let opacity = self.model_body_opacity(b) as f32;
let paint = solidcraft_kernel::Paint { opacity, faces };
if c != b.body.color() || b.body.paint() != Some(&paint) {
+1 -1
View File
@@ -2332,7 +2332,7 @@ impl Model {
}
Err(e) => Some(e.to_string().trim_start_matches("the operation failed: ").to_string()),
};
if !self.no_cache {
if !self.no_cache && !watched.cancelled() {
let e = CachedEval {
error: error.clone(),
warning: warning.clone(),
@@ -0,0 +1,8 @@
//! Linked components retain the last inherited physical material, explicit body look and
//! authored face overrides by imported body slot. Face baselines are optional: an older
//! link is read again on Update Links while preserving local assignments. Authored face
//! overrides stay separate from imported STEP paint, including under a body appearance.
//! Source-only property edits can then update the link while
//! differing local assignments survive. Older links have no baseline: existing assignments
//! are preserved and missing ones can be recovered on Update Links. The last release
//! refuses the newer design format instead of silently discarding these baselines.
+7
View File
@@ -173,6 +173,13 @@ pub(crate) fn begin(total: usize) -> Evaluation {
}
impl Evaluation {
/// Whether the watcher asked to stop. A feature cut short then (a STEP import that stopped
/// part way) failed only because of it: its result must not be kept for the same inputs, as
/// the evaluation cache is shared with the model a preview was copied from (#7167).
pub(crate) fn cancelled(&self) -> bool {
CURRENT.with(|c| c.borrow().as_ref().is_some_and(|cur| cur.progress.is_cancelled()))
}
/// Feature `index` is next. True when the watcher asked to stop: skip it.
pub(crate) fn step(&self, index: usize) -> bool {
CURRENT.with(|c| {
+128
View File
@@ -0,0 +1,128 @@
//! Read the shared document appearance chain and replace exact saved overrides.
use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet};
use serde_json::{Value, json};
use solidcraft_doc::appearance::{AppearanceScope, AppearanceTarget, Look};
use crate::params::bad;
use crate::{Result, Session};
const MAX_TARGETS: usize = 10_000;
fn name<'a>(cmd: &str, value: &'a Value) -> Result<&'a str> {
value.as_str().filter(|s| !s.is_empty() && s.len() <= 4096).ok_or_else(|| bad(cmd, "target name must have 1..4096 bytes"))
}
fn component(s: &Session, cmd: &str, value: &Value) -> Result<u64> {
let key = match value {
Value::String(_) => name(cmd, value)?.to_string(),
Value::Number(_) => value.as_u64().ok_or_else(|| bad(cmd, "component must be a name or unsigned id"))?.to_string(),
_ => return Err(bad(cmd, "component must be a name or unsigned id")),
};
s.doc.find_component(&key).filter(|id| *id != 0).ok_or_else(|| bad(cmd, "unknown or root component"))
}
pub(super) fn chain(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "appearance.chain";
let target = p.get("target").and_then(Value::as_object).ok_or_else(|| bad(cmd, "give one target object"))?;
let target = match (target.get("body"), target.get("face"), target.get("component")) {
(Some(body), None, None) if target.len() == 1 => AppearanceTarget::Body(name(cmd, body)?),
(Some(body), Some(face), None) if target.len() == 2 => AppearanceTarget::Face {
body: name(cmd, body)?,
face: face.as_u64().and_then(|f| usize::try_from(f).ok()).ok_or_else(|| bad(cmd, "face must be a zero-based unsigned index"))?,
},
(None, None, Some(id)) if target.len() == 1 => AppearanceTarget::Component(component(s, cmd, id)?),
_ => return Err(bad(cmd, "target must be {body}, {body, face}, or {component}")),
};
let chain = s.doc.appearance_chain(&s.model.state(), target).map_err(|e| bad(cmd, e.to_string()))?;
Ok(json!({
"steps": chain.steps().into_iter().map(|(step, look)| json!({"step":step,"look":look.map(super::look_json)})).collect::<Vec<_>>(),
"active": chain.active(),
}))
}
/// A saved in-design look's label is inert; a string explicitly selects a library
/// recipe. Reuse assignment's optical parsing rather than a second preset resolver.
fn look(cmd: &str, value: &Value) -> Result<Look> {
let params = match value {
Value::String(_) => Cow::Owned(json!({"appearance":name(cmd, value)?})),
Value::Object(_) => Cow::Borrowed(value),
_ => return Err(bad(cmd, "from and to must be library names or look objects")),
};
if let Some(opacity) = params.get("opacity")
&& opacity.as_f64().filter(|o| o.is_finite() && (0.0..=1.0).contains(o)).is_none()
{
return Err(bad(cmd, "opacity must be a finite number in 0..1"));
}
if let Some(appearance) = params.get("appearance") {
name(cmd, appearance)?;
}
super::appearance_look(cmd, &params)?.ok_or_else(|| bad(cmd, "from and to require a look; use appearance.assign to clear"))
}
fn scope(s: &Session, cmd: &str, value: &Value) -> Result<AppearanceScope> {
let object = value
.as_object()
.filter(|o| !o.is_empty() && o.keys().all(|k| matches!(k.as_str(), "bodies" | "components")))
.ok_or_else(|| bad(cmd, "scope must contain bodies and/or components lists"))?;
let list =
|key: &str| -> Result<&Vec<Value>> { object.get(key).and_then(Value::as_array).ok_or_else(|| bad(cmd, "scope targets must be lists")) };
let mut count = 0usize;
for key in object.keys() {
count = count.saturating_add(list(key)?.len());
if count > MAX_TARGETS {
return Err(bad(cmd, "scope has more than 10000 targets"));
}
}
let mut scope = AppearanceScope::default();
if object.contains_key("bodies") {
let state = s.model.state();
let bodies: BTreeSet<_> = state.bodies.iter().map(|b| b.name.as_str()).collect();
for body in list("bodies")? {
let body = name(cmd, body)?;
if !bodies.contains(body) {
return Err(bad(cmd, "unknown body in scope"));
}
scope.bodies.insert(body.into());
}
}
if object.contains_key("components") {
// Build indexes once: 10000 repeated component targets must not scan a
// 10000-component design once per target.
let ids: BTreeSet<_> = s.doc.components.iter().map(|c| c.id).collect();
let names: BTreeMap<_, _> = s.doc.components.iter().rev().map(|c| (c.name.as_str(), c.id)).collect();
for target in list("components")? {
let id = match target {
Value::String(_) => {
let key = name(cmd, target)?;
key.parse::<u64>().ok().filter(|id| ids.contains(id)).or_else(|| names.get(key).copied())
}
Value::Number(_) => target.as_u64().filter(|id| ids.contains(id)),
_ => None,
}
.filter(|id| *id != 0)
.ok_or_else(|| bad(cmd, "unknown component in scope"))?;
scope.components.insert(id);
}
}
Ok(scope)
}
pub(super) fn replace(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "appearance.replace";
s.doc.appearances.check_budget().map_err(|e| bad(cmd, e.to_string()))?;
let from = look(cmd, p.get("from").ok_or_else(|| bad(cmd, "from is required"))?)?;
let to = look(cmd, p.get("to").ok_or_else(|| bad(cmd, "to is required"))?)?;
let scope = p.get("scope").map(|v| scope(s, cmd, v)).transpose()?;
// Every validation and allocation completes before obtaining a mutable document.
let replacement = s.doc.appearances.replacing(&from, &to, scope.as_ref()).map_err(|e| bad(cmd, e.to_string()))?;
let count = if let Some((appearances, count)) = replacement {
s.doc_mut().appearances = appearances;
count
} else {
0
};
Ok(json!({"count": count}))
}
+10 -4
View File
@@ -56,7 +56,7 @@ pub static COMMANDS: &[CommandSpec] = &[
Display only: open/closed rows are not saved in the design and are not an undo step → open, open_by_default, closed_by_default",
),
CommandSpec::new("browser.collapse_all", "Collapse All", collapse_all).icon("folder").noundo().params(
"path?: [occurrence ids]; component?: id; omit both for the whole tree (the design row stays open so the first level remains visible). \
"path?: [occurrence ids]; component?: id; omit both for the whole tree. The row it starts from (the design row for the whole tree) stays open, so its first level remains visible. \
Display only; not an undo step → open, open_by_default, closed_by_default",
),
];
@@ -562,8 +562,14 @@ fn fold_tree(s: &mut Session, p: &Value, open: bool, cmd: &str) -> Result<Value>
FoldScope::Tree => walk_fold(s, &[], true, &mut keys, cmd)?,
FoldScope::Occurrence(path) => walk_fold(s, path, false, &mut keys, cmd)?,
}
if !open && matches!(scope, FoldScope::Tree) {
keys.open.remove("c0");
if !open {
// Collapse All folds what is under the clicked row; the row itself stays open.
let own = match &scope {
FoldScope::Tree => "c0".to_string(),
FoldScope::Component(id) => format!("c{id}"),
FoldScope::Occurrence(path) => occurrence_fold_key(path),
};
keys.open.remove(&own);
}
if keys.open.len().saturating_add(keys.closed.len()) > MAX_FOLD_KEYS {
return Err(bad(cmd, "expand/collapse exceeds 10000 browser rows"));
@@ -1993,7 +1999,7 @@ mod tests {
let below = run(&mut s, "browser.collapse_all", json!({"path": [occ]}));
let open = strs(&below, "open_by_default");
assert!(open.contains(&format!("o:{occ}")), "{open:?}");
assert!(!open.contains(&format!("o:{occ}")), "the clicked row stays open: {open:?}");
assert!(!open.contains(&"c0/bodies".into()), "{open:?}");
assert!(strs(&below, "closed_by_default").iter().all(|k| !k.starts_with("c0") && k != "origin"), "{below}");
+5 -3
View File
@@ -17,7 +17,7 @@ use serde_json::{Value, json};
use solidcraft_doc::{DesignLink, Document, FeatureKind, ModelBody, ModelState};
use solidcraft_geom::Vec3;
use super::{absolute, component_key, resolve, session_bodies, stored};
use super::{absolute, component_key, inherit_properties, resolve, session_bodies, stored};
use crate::params::{bad, str_};
use crate::{EngineError, Result, Session};
@@ -566,7 +566,7 @@ pub(super) fn extract(s: &mut Session, p: &Value) -> Result<Value> {
// This design: the component's history becomes an Import feature of the new design's bodies
let shown = file.display().to_string();
let (_, sf, faces, _) = session_bodies(&part, &shown)?;
let (_, sf, faces, _, properties) = session_bodies(&part, &shown)?;
// The link has a body per piece: a body in pieces keeps its name on the first
let mut solids: Vec<String> = Vec::new();
for b in part.world_state().bodies.iter().filter(|b| !b.body.is_mesh()) {
@@ -592,12 +592,14 @@ pub(super) fn extract(s: &mut Session, p: &Value) -> Result<Value> {
f.link_faces = faces;
}
let path = stored(s.path.as_deref(), &file);
s.doc_mut().links.insert(comp, DesignLink { path: file.to_string_lossy().into_owned(), feature: id });
s.doc_mut().links.insert(comp, DesignLink { path: file.to_string_lossy().into_owned(), feature: id, inherited: Vec::new() });
s.refresh();
rename_joint_faces(s, &state, id, &sc.own);
if let Some(e) = s.model.result(id).and_then(|r| r.error.clone()) {
return Err(EngineError::Other(e));
}
inherit_properties(s, comp, &properties)?;
s.refresh();
let mut warnings = sf.warnings;
warnings.extend(before.check(s, CMD, &sc.name)?);
let copies = copies_of(s, comp)?;
+303 -27
View File
@@ -13,7 +13,7 @@ use std::path::{Path, PathBuf};
use std::sync::Mutex;
use serde_json::{Value, json};
use solidcraft_doc::{DesignLink, Document, FeatureKind};
use solidcraft_doc::{DesignLink, Document, FeatureKind, LinkedBodyProperties, UserMaterial};
use super::CommandSpec;
use super::design_link::{absolute, resolve, stored};
@@ -88,11 +88,20 @@ pub fn resolve_design_links(doc: &mut Document, from: Option<&str>) {
/// The bodies of a linked design: its name, the Import feature that holds them and the names
/// the design gives their faces (`Feature::link_faces`), with the source's design properties.
type Linked = (String, solidcraft_io::StepFeature, Vec<Vec<String>>, solidcraft_doc::Metadata);
type Linked = (String, solidcraft_io::StepFeature, Vec<Vec<String>>, solidcraft_doc::Metadata, Vec<SourceProperties>);
#[derive(Clone)]
struct SourceProperties {
material: String,
definition: Option<UserMaterial>,
appearance: Option<solidcraft_doc::appearance::Look>,
/// Resolved authored overrides, by the face index in this imported body.
faces: Vec<(usize, solidcraft_doc::appearance::Look)>,
}
/// What a linked file last gave, by the file: digests of its bytes, of the STEP text it gave and
/// of its face names, and that read's warnings. Update Links evaluates a file again only when its
/// bytes or the linked bodies changed since (#5606). Bounded, oldest first out.
/// of its face names, and that read's warnings and source properties. Update Links evaluates
/// a file again only when its bytes or the linked bodies changed since (#5606). Bounded, oldest first out.
static READS: Mutex<Vec<LinkRead>> = Mutex::new(Vec::new());
const READS_SIZE: usize = 256;
@@ -102,6 +111,7 @@ struct LinkRead {
step: u64,
faces: u64,
warnings: Vec<String>,
properties: Vec<SourceProperties>,
}
#[cfg(test)]
@@ -116,15 +126,18 @@ fn digest<T: Hash + ?Sized>(value: &T) -> u64 {
h.finish()
}
/// The warnings of the last read of `file`, when it had these bytes and gave the STEP text
/// Warnings and source properties of the last read of `file`, when it had these bytes and gave the STEP text
/// `step` and the face names `faces`: the bodies it gives are the ones the link holds.
fn unchanged_read(file: &Path, bytes: u64, step: u64, faces: u64) -> Option<Vec<String>> {
fn unchanged_read(file: &Path, bytes: u64, step: u64, faces: u64) -> Option<(Vec<String>, Vec<SourceProperties>)> {
let file = absolute(file);
let reads = READS.lock().ok()?;
reads.iter().find(|r| r.file == file && r.bytes == bytes && r.step == step && r.faces == faces).map(|r| r.warnings.clone())
reads
.iter()
.find(|r| r.file == file && r.bytes == bytes && r.step == step && r.faces == faces)
.map(|r| (r.warnings.clone(), r.properties.clone()))
}
fn remember_read(file: &Path, bytes: u64, feature: &solidcraft_io::StepFeature, faces: &[Vec<String>]) {
fn remember_read(file: &Path, bytes: u64, feature: &solidcraft_io::StepFeature, faces: &[Vec<String>], properties: &[SourceProperties]) {
let FeatureKind::Import { step, .. } = &feature.kind else { return };
let file = absolute(file);
let Ok(mut reads) = READS.lock() else { return };
@@ -132,7 +145,14 @@ fn remember_read(file: &Path, bytes: u64, feature: &solidcraft_io::StepFeature,
if reads.len() >= READS_SIZE {
reads.remove(0);
}
reads.push(LinkRead { file, bytes, step: digest(step.as_bytes()), faces: digest(faces), warnings: feature.warnings.clone() });
reads.push(LinkRead {
file,
bytes,
step: digest(step.as_bytes()),
faces: digest(faces),
warnings: feature.warnings.clone(),
properties: properties.to_vec(),
});
}
/// The bytes of the design at `file`, which must not be the design saved at `own`.
@@ -168,9 +188,9 @@ fn design_bodies(file: &Path, bytes: &[u8]) -> Result<Linked> {
} else {
(solidcraft_io::read_design(bytes).map_err(fail)?, None)
};
let (name, feature, faces, metadata) = session_bodies(&Session::opened_at(doc, saved.as_ref(), Some(&shown)), &shown)?;
remember_read(file, digest(bytes), &feature, &faces);
Ok((name, feature, faces, metadata))
let (name, feature, faces, metadata, properties) = session_bodies(&Session::opened_at(doc, saved.as_ref(), Some(&shown)), &shown)?;
remember_read(file, digest(bytes), &feature, &faces, &properties);
Ok((name, feature, faces, metadata, properties))
}
/// The solid bodies of `part`, the design saved as `shown`, as an Import feature.
@@ -184,7 +204,7 @@ fn session_bodies(part: &Session, shown: &str) -> Result<Linked> {
if solids.is_empty() {
return Err(EngineError::Other(format!("{shown}: the design has no solid bodies to link")));
}
let step = solidcraft_io::export(&part.doc.painted(&world), &solids, solidcraft_io::Format::Step, &name)
let step = solidcraft_io::export(&part.doc.painted_for_link(&world), &solids, solidcraft_io::Format::Step, &name)
.map_err(|e| EngineError::Other(format!("{shown}: {e}")))?;
let mut feature = solidcraft_io::step_import_feature(&step, shown).map_err(|e| EngineError::Other(format!("{shown}: {e}")))?;
if world.bodies.len() > solids.len() {
@@ -193,7 +213,239 @@ fn session_bodies(part: &Session, shown: &str) -> Result<Linked> {
// The STEP text keeps no face names: carry the design's own, so references into the linked
// bodies follow them as they do inside the design (#3330).
let faces = solidcraft_doc::naming::carried_face_names(&world, &feature.import.bodies);
Ok((name, feature, faces, part.doc.metadata.clone()))
let properties = feature
.import
.bodies
.iter()
.zip(&faces)
.map(|(read, carried)| {
// STEP can split a source body into several lumps. Match its carried source
// face names rather than assuming source and imported body orders agree.
let source = world
.bodies
.iter()
.find(|b| b.name == read.name)
.or_else(|| {
world
.bodies
.iter()
.filter(|b| !b.body.is_mesh())
.filter_map(|b| {
let names = solidcraft_doc::naming::face_names(b);
let count = carried.iter().filter(|n| !n.is_empty() && names.contains(n)).count();
(count > 0).then_some((count, b))
})
.max_by_key(|(count, _)| *count)
.map(|(_, b)| b)
})
.ok_or_else(|| EngineError::Other(format!("{shown}: cannot match linked body {} to its source properties", read.name)))?;
let key = source.definition_name();
let material = part.doc.body_material(key);
let definition = if solidcraft_doc::material_density(&material).is_none() { part.doc.user_material(&material).cloned() } else { None };
let appearance = part
.doc
.appearances
.bodies
.get(key)
.cloned()
.or_else(|| part.doc.appearances.components.get(&part.doc.model_body_component(source)).cloned());
let names = solidcraft_doc::naming::face_names(source);
let authored: std::collections::BTreeMap<_, _> = part
.doc
.authored_face_colors(source)
.into_iter()
.filter_map(|(index, look)| names.get(index).map(|name| (name.clone(), look)))
.collect();
let faces = carried.iter().enumerate().filter_map(|(index, name)| authored.get(name).map(|look| (index, look.clone()))).collect();
Ok(SourceProperties { material, definition, appearance, faces })
})
.collect::<Result<Vec<_>>>()?;
Ok((name, feature, faces, part.doc.metadata.clone(), properties))
}
fn material_fingerprint(doc: &Document, material: &str) -> Result<Option<String>> {
if solidcraft_doc::material_density(material).is_some() {
return Ok(None);
}
doc.user_material(material).map(LinkedBodyProperties::fingerprint).transpose().map_err(|e| EngineError::Other(e.to_string()))
}
/// Copy a design-owned definition without changing a same-named assembly material.
fn inherit_material(doc: &mut Document, source: &SourceProperties, previous: Option<&str>) -> Result<String> {
let Some(definition) = &source.definition else { return Ok(source.material.clone()) };
for existing in &doc.user_materials {
// Equal density/optics do not make differently named materials interchangeable.
// A previous disambiguated copy can be reused on subsequent source updates.
if !existing.name.eq_ignore_ascii_case(&definition.name) && previous != Some(existing.name.as_str()) {
continue;
}
let mut candidate = definition.clone();
candidate.name.clone_from(&existing.name);
if &candidate == existing {
return Ok(existing.name.clone());
}
}
if doc.user_materials.len() >= solidcraft_doc::MAX_USER_MATERIALS {
return Err(EngineError::Other("cannot inherit linked material: this design already has 1000 custom materials".into()));
}
let mut copy = definition.clone();
if doc.material_name(&copy.name).is_some() {
let base: String = copy.name.chars().take(64).collect();
let name = (1..=solidcraft_doc::MAX_USER_MATERIALS + 1)
.map(|i| format!("{base} (linked {i})"))
.find(|name| doc.material_name(name).is_none())
.ok_or_else(|| EngineError::Other("cannot name the linked material".into()))?;
copy.name = name;
}
let name = copy.name.clone();
doc.user_materials.push(copy);
Ok(name)
}
/// Replace only unchanged inherited face assignments. A locally edited, added or removed
/// override remains local, independently for each face. Resolve names on the evaluated Import,
/// not source feature IDs or face order from the source's model.
fn inherit_faces(
s: &mut Session,
name: &str,
source: &SourceProperties,
previous: Option<&LinkedBodyProperties>,
) -> (Vec<solidcraft_doc::appearance::FaceLook>, bool) {
use solidcraft_doc::appearance::FaceLook;
let previous = previous.and_then(|p| p.faces.as_deref()).unwrap_or_default();
if source.faces.is_empty() && previous.is_empty() {
return (Vec::new(), false);
}
let state = s.model.state();
let Some(body) = state.body(name) else { return (Vec::new(), false) };
let names = solidcraft_doc::naming::face_names(body);
// A stable named assignment needs no new geometric point. Keep its position in
// the appearance list and avoid tessellating on unchanged cached reads.
if previous.len() == source.faces.len()
&& previous.iter().all(|old| old.body == name && s.doc.appearances.faces.contains(old))
&& source.faces.iter().all(|(index, look)| {
names.get(*index).is_some_and(|name| previous.iter().any(|old| old.name.as_ref() == Some(name) && old.look == *look))
})
{
return (previous.to_vec(), false);
}
let before = s.doc.appearances.faces.clone();
let mut local = before.clone();
let mut inherited = Vec::new();
let mut replaced = Vec::new();
let mut blocked = std::collections::BTreeSet::new();
for old in previous {
let mut old = old.clone();
old.body = name.into();
if let Some(index) = local.iter().position(|face| *face == old) {
local.remove(index);
replaced.push(old);
} else {
if let Some(name) = &old.name {
blocked.extend(solidcraft_doc::naming::faces_with_stem(body, name));
}
// Remember an explicit local removal too, including after save/reopen.
inherited.push(old);
}
}
s.doc_mut().appearances.faces = local;
blocked.extend(s.doc.authored_face_colors(body).into_iter().map(|(index, _)| index));
let spots = if source.faces.is_empty() { Vec::new() } else { solidcraft_doc::naming::face_spots(body) };
let mut assignments = Vec::new();
for (index, look) in &source.faces {
if blocked.contains(index) {
// An appended local override can coexist with the old inherited entry.
// Keep that baseline as a tombstone if the local override is later removed.
if let Some(old) = names.get(*index).and_then(|name| previous.iter().find(|old| old.name.as_ref() == Some(name))) {
let mut old = old.clone();
old.body = name.into();
if !inherited.contains(&old) {
inherited.push(old);
}
}
continue;
}
let Some(face_name) = names.get(*index).filter(|name| !name.is_empty()) else { continue };
let Some(spot) = spots.get(*index).and_then(|spot| *spot) else { continue };
let face = FaceLook {
body: name.into(),
point: spot.point,
look: look.clone(),
name: Some(face_name.clone()),
strict_name: false,
certificate: None,
};
assignments.push(face.clone());
inherited.push(face);
}
// Replace inherited entries in place; leave all local and other bodies' entries
// in their original order, including multiple overrides on the same face.
let mut after = Vec::new();
for old in &before {
if replaced.contains(old) {
if let Some(index) = assignments.iter().position(|face| face.body == old.body && face.name == old.name) {
after.push(assignments.remove(index));
}
} else {
after.push(old.clone());
}
}
after.extend(assignments);
let changed = after != before;
s.doc_mut().appearances.faces = after;
(inherited, changed)
}
/// Apply properties after evaluation has resolved body-name collisions. Last inherited
/// values are kept independently for material and appearance, so overriding one does not
/// stop updates of the other. Session::execute makes this part of the command's undo step.
fn inherit_properties(s: &mut Session, component: u64, sources: &[SourceProperties]) -> Result<bool> {
let Some(link) = s.doc.links.get(&component).cloned() else { return Ok(false) };
let state = s.model.state();
let names: Vec<String> = state.bodies.iter().filter(|b| b.feature == link.feature).map(|b| b.name.clone()).collect();
let slots = s.doc.feature(link.feature).map(|f| f.body_name_slots(names.len())).unwrap_or_default();
let mut inherited = link.inherited.clone();
inherited.resize(sources.len(), LinkedBodyProperties::default());
let mut changed = false;
for (name, slot) in names.iter().zip(slots) {
let Some(source) = sources.get(slot) else { continue };
let old = link.inherited.get(slot);
let current_definition = material_fingerprint(&s.doc, &s.doc.body_material(name))?;
let may_change_material = match old {
Some(old) => s.doc.materials.get(name) == Some(&old.material) && current_definition == old.material_fingerprint,
None => !s.doc.materials.contains_key(name),
};
let mut next = old.cloned().unwrap_or_default();
if may_change_material {
let material = inherit_material(s.doc_mut(), source, old.map(|old| old.material.as_str()))?;
changed |= s.doc.materials.get(name) != Some(&material);
s.doc_mut().materials.insert(name.clone(), material.clone());
next.material_fingerprint = material_fingerprint(&s.doc, &material)?;
next.material = material;
}
if s.doc.appearances.bodies.get(name) == old.and_then(|old| old.appearance.as_ref()) {
changed |= s.doc.appearances.bodies.get(name) != source.appearance.as_ref();
match &source.appearance {
Some(look) => {
s.doc_mut().appearances.bodies.insert(name.clone(), look.clone());
}
None => {
s.doc_mut().appearances.bodies.remove(name);
}
}
next.appearance.clone_from(&source.appearance);
}
let (faces, face_changed) = inherit_faces(s, name, source, old);
next.faces = Some(faces);
changed |= face_changed;
if let Some(snapshot) = inherited.get_mut(slot) {
*snapshot = next;
}
}
if let Some(link) = s.doc_mut().links.get_mut(&component) {
link.inherited = inherited;
}
Ok(changed)
}
fn component_key(s: &Session, p: &Value, key: &str, cmd: &str) -> Result<u64> {
@@ -225,7 +477,7 @@ fn insert_design(s: &mut Session, p: &Value) -> Result<Value> {
return super::component::copy_occurrence(s, &json!({"component": component, "parent": parent, "translate": translate}));
}
}
let (design_name, sf, faces, metadata) = linked_bodies(&file, s.path.as_deref())?;
let (design_name, sf, faces, metadata, properties) = linked_bodies(&file, s.path.as_deref())?;
let name = str_(p, "name").filter(|n| !n.trim().is_empty()).map(str::to_string).unwrap_or(design_name);
let mut create = json!({"name": name, "activate": false});
// Clipboard insertion uses reuse even for the first paste, which must stay movable.
@@ -252,11 +504,13 @@ fn insert_design(s: &mut Session, p: &Value) -> Result<Value> {
o.transform[3] = [translate.x, translate.y, translate.z, 1.0];
}
let path = stored(s.path.as_deref(), &file);
s.doc_mut().links.insert(comp, DesignLink { path: file.to_string_lossy().into_owned(), feature: id });
s.doc_mut().links.insert(comp, DesignLink { path: file.to_string_lossy().into_owned(), feature: id, inherited: Vec::new() });
s.refresh();
if let Some(e) = s.model.result(id).and_then(|r| r.error.clone()) {
return Err(EngineError::Other(e));
}
inherit_properties(s, comp, &properties)?;
s.refresh();
let st = s.model.state();
let bodies: Vec<&str> = st.bodies.iter().filter(|b| b.feature == id).map(|b| b.name.as_str()).collect();
Ok(
@@ -294,18 +548,34 @@ fn update_links(s: &mut Session, p: &Value) -> Result<Value> {
link_refused(s.path.as_deref(), &link.path).map_err(|e| bad(cmd, format!("{cname}: {e}")))?;
let file = resolve(s.path.as_deref(), &link.path);
let bytes = read_link(&file, s.path.as_deref()).map_err(|e| bad(cmd, format!("{cname}: {e}")))?;
let kept_faces = s.doc.feature(link.feature).map(|f| digest(f.link_faces.as_slice()));
if let Some(known) = kept_faces.and_then(|faces| unchanged_read(&file, digest(bytes.as_slice()), digest(old.as_bytes()), faces)) {
// A link that has not recorded the properties it inherited (made before they were) is read again.
let kept_faces = s
.doc
.feature(link.feature)
.filter(|_| !link.inherited.is_empty() && link.inherited.iter().all(|p| p.faces.is_some()))
.map(|f| digest(f.link_faces.as_slice()));
if let Some((known, properties)) = kept_faces.and_then(|faces| unchanged_read(&file, digest(bytes.as_slice()), digest(old.as_bytes()), faces))
{
warnings.extend(known);
unchanged.push(cname);
// Another component or session may have evaluated this source first. Its
// cached geometry says nothing about this link's inherited properties.
if inherit_properties(s, comp, &properties)? {
updated.push(cname)
} else {
unchanged.push(cname)
}
continue;
}
let (_, sf, faces, _) = design_bodies(&file, &bytes).map_err(|e| bad(cmd, format!("{cname}: {e}")))?;
let (_, sf, faces, _, properties) = design_bodies(&file, &bytes).map_err(|e| bad(cmd, format!("{cname}: {e}")))?;
warnings.extend(sf.warnings.iter().cloned());
let same = matches!(&sf.kind, FeatureKind::Import { step, .. } if *step == old);
let kept = s.doc.feature(link.feature).map(|f| &f.link_faces);
if same && kept == Some(&faces) {
unchanged.push(cname);
if inherit_properties(s, comp, &properties)? {
updated.push(cname)
} else {
unchanged.push(cname)
}
continue;
}
// The same bodies, their faces named for the first time (a link made before names were
@@ -329,6 +599,8 @@ fn update_links(s: &mut Session, p: &Value) -> Result<Value> {
// A link made before the design's face names were kept gets them here.
f.link_faces = faces;
}
s.refresh();
let changed = inherit_properties(s, comp, &properties)? || changed;
if changed { updated.push(cname) } else { unchanged.push(cname) }
}
solidcraft_doc::progress::item(None);
@@ -381,7 +653,7 @@ fn relink(s: &mut Session, p: &Value) -> Result<Value> {
}
// Read/evaluate the candidate before changing anything. Session::execute owns the single
// undo step and restores both the document and evaluated state on any later failure.
let (_, sf, faces, _) = linked_bodies(&file, s.path.as_deref()).map_err(|e| bad(cmd, e.to_string()))?;
let (_, sf, faces, _, properties) = linked_bodies(&file, s.path.as_deref()).map_err(|e| bad(cmd, e.to_string()))?;
let geometry_changed = match (s.doc.feature(link.feature).map(|f| &f.kind), &sf.kind) {
(Some(FeatureKind::Import { step: old, .. }), FeatureKind::Import { step, .. }) => old != step,
_ => true,
@@ -404,11 +676,13 @@ fn relink(s: &mut Session, p: &Value) -> Result<Value> {
f.kind = sf.kind;
f.link_faces = faces;
}
s.doc_mut().links.insert(comp, DesignLink { path: file.to_string_lossy().into_owned(), feature: link.feature });
s.doc_mut().links.insert(comp, DesignLink { path: file.to_string_lossy().into_owned(), ..link.clone() });
s.refresh();
if let Some(error) = s.model.result(link.feature).and_then(|r| r.error.clone()) {
return Err(bad(cmd, error));
}
inherit_properties(s, comp, &properties)?;
s.refresh();
// Report the solver's diagnostics. A resolved joint can still describe the wrong
// connection after a source edit; the reminder above does not depend on solve errors.
let sol = solidcraft_doc::joints::solve(&s.doc, &s.model.state());
@@ -840,7 +1114,7 @@ mod tests {
std::fs::copy(&part, dir.join("parts").join("NUL.solidcraft")).unwrap();
let before = volume(&mut a);
for link in crafted.iter().chain(&devices) {
a.doc_mut().links.insert(comp, DesignLink { path: link.to_string(), feature });
a.doc_mut().links.insert(comp, DesignLink { path: link.to_string(), feature, ..Default::default() });
let calls = solidcraft_io::vfs::file_calls();
let listed = run(&mut a, "component.links", json!({}));
let entry = &listed["links"][0];
@@ -858,7 +1132,7 @@ mod tests {
// Allowed (Allow once, a preference, …), the same link is read as any other.
#[cfg(unix)]
{
a.doc_mut().links.insert(comp, DesignLink { path: crafted[0].to_string(), feature });
a.doc_mut().links.insert(comp, DesignLink { path: crafted[0].to_string(), feature, ..Default::default() });
solidcraft_io::vfs::allowing_hosts(&["EVIL.example".to_string()], || {
let listed = run(&mut a, "component.links", json!({}));
assert_eq!(listed["links"][0]["found"], true, "{listed}");
@@ -868,7 +1142,7 @@ mod tests {
}
// A local link, relative or absolute, is found and read as before.
for local in ["parts/plate.solidcraft".to_string(), part.to_string_lossy().to_string()] {
a.doc_mut().links.insert(comp, DesignLink { path: local.clone(), feature });
a.doc_mut().links.insert(comp, DesignLink { path: local.clone(), feature, ..Default::default() });
assert_eq!(run(&mut a, "component.links", json!({}))["links"][0]["found"], true, "{local}");
assert_eq!(run(&mut a, "component.update_links", json!({}))["unchanged"], json!(["plate"]), "{local}");
}
@@ -888,7 +1162,9 @@ mod tests {
fn every_link_path_goes_through_the_design_path_rule() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let code = |file: &str| {
let text = std::fs::read_to_string(root.join(file)).unwrap();
// Windows Git checkouts can use CRLF. Locate the test module in either
// representation, rather than mistaking its fixture file calls for product code.
let text = std::fs::read_to_string(root.join(file)).unwrap().replace("\r\n", "\n");
// The code before its test module.
text.split("\n#[cfg(test)]\n#[allow(clippy::unwrap_used").next().unwrap_or("").to_string()
};
@@ -24,6 +24,121 @@ fn volume(s: &mut Session) -> f64 {
run(s, "inspect.measure", json!({}))["total"]["volume_mm3"].as_f64().unwrap()
}
fn properties_part(path: &Path, material: &str, density: Option<f64>, color: [u8; 3]) -> Session {
let mut s = Session::default();
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 10, "body_name": "Cube"}));
if let Some(density) = density {
s.doc_mut().user_materials.push(solidcraft_doc::UserMaterial { name: material.into(), density, appearance: None, physical_card: None });
}
run(&mut s, "material.assign", json!({"bodies": ["Cube"], "material": material}));
s.doc_mut().appearances.bodies.insert("Cube".into(), solidcraft_doc::appearance::Look::custom(color, 0.4));
run(&mut s, "file.save", json!({"path": path}));
s
}
fn assert_link_properties(s: &mut Session, component: u64, material: &str, mass: f64, color: [u8; 3]) {
let p = run(s, "component.properties", json!({"component": component}));
assert_eq!(p["bodies"][0]["material"], material, "{p}");
assert!((p["total"]["mass_g"].as_f64().unwrap() - mass).abs() < 1e-6, "{p}");
let state = s.model.state();
let b = state.bodies.iter().find(|b| b.component == component).unwrap();
let look = s.doc.model_body_look(b).unwrap();
assert_eq!(look.color, color);
assert!((s.doc.model_body_opacity(b) - 0.4).abs() < 1e-9);
}
#[test]
fn linked_design_properties_keep_material_and_appearance_after_insert_and_reload() {
let dir = folder("properties-insert");
let file = dir.join("source.solidcraft");
properties_part(&file, "Steel", None, [12, 34, 56]);
let mut s = Session::default();
// The assembly already owns this body name; properties must follow the new name.
run(&mut s, "solid.box", json!({"length": 1, "width": 1, "height": 1, "body_name": "Cube"}));
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
assert_link_properties(&mut s, c, "Steel", 7.85, [12, 34, 56]);
assert_eq!(s.doc.body_material("Cube"), "Default");
let assembly = dir.join("assembly.solidcraft");
run(&mut s, "file.save", json!({"path": assembly}));
let mut cold = Session::default();
run(&mut cold, "doc.open", json!({"path": assembly}));
assert_link_properties(&mut cold, c, "Steel", 7.85, [12, 34, 56]);
run(&mut cold, "component.insert_design", json!({"path": file, "reuse": true}));
assert_eq!(cold.doc.links.len(), 1);
assert_link_properties(&mut cold, c, "Steel", 7.85, [12, 34, 56]);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_follow_source_only_edits_and_keep_local_overrides() {
let dir = folder("properties-update");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Steel", None, [12, 34, 56]);
let mut s = Session::default();
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
run(&mut part, "material.assign", json!({"bodies": ["Cube"], "material": "Aluminum"}));
part.doc_mut().appearances.bodies.insert("Cube".into(), solidcraft_doc::appearance::Look::custom([80, 90, 100], 0.4));
run(&mut part, "file.save", json!({}));
assert_eq!(run(&mut s, "component.update_links", json!({}))["updated"].as_array().unwrap().len(), 1);
assert_link_properties(&mut s, c, "Aluminum", 2.7, [80, 90, 100]);
run(&mut s, "edit.undo", json!({}));
assert_link_properties(&mut s, c, "Steel", 7.85, [12, 34, 56]);
run(&mut s, "edit.redo", json!({}));
assert_link_properties(&mut s, c, "Aluminum", 2.7, [80, 90, 100]);
run(&mut s, "material.assign", json!({"bodies": ["Cube"], "material": "Brass"}));
s.doc_mut().appearances.bodies.insert("Cube".into(), solidcraft_doc::appearance::Look::custom([1, 2, 3], 0.4));
run(&mut part, "material.assign", json!({"bodies": ["Cube"], "material": "Steel"}));
run(&mut part, "file.save", json!({}));
run(&mut s, "component.update_links", json!({}));
assert_link_properties(&mut s, c, "Brass", solidcraft_doc::material_density("Brass").unwrap(), [1, 2, 3]);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_do_not_replace_conflicting_custom_materials() {
let dir = folder("properties-custom");
let file = dir.join("source.solidcraft");
properties_part(&file, "Custom alloy", Some(4.2), [12, 34, 56]);
let mut s = Session::default();
s.doc_mut().user_materials.push(solidcraft_doc::UserMaterial {
name: "Custom alloy".into(),
density: 9.0,
appearance: None,
physical_card: None,
});
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
let p = run(&mut s, "component.properties", json!({"component": c}));
let assigned = p["bodies"][0]["material"].as_str().unwrap();
assert_ne!(assigned, "Custom alloy");
assert!((p["total"]["mass_g"].as_f64().unwrap() - 4.2).abs() < 1e-6, "{p}");
assert_eq!(s.doc.material_density("Custom alloy"), Some(9.0));
assert_eq!(s.doc.user_materials.len(), 2);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_keep_distinct_names_for_equal_material_properties() {
let dir = folder("properties-equal-density");
let file = dir.join("source.solidcraft");
properties_part(&file, "Source alloy", Some(4.2), [12, 34, 56]);
let mut s = Session::default();
s.doc_mut().user_materials.push(solidcraft_doc::UserMaterial {
name: "Different alloy".into(),
density: 4.2,
appearance: None,
physical_card: None,
});
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
assert_link_properties(&mut s, c, "Source alloy", 4.2, [12, 34, 56]);
let count = s.doc.user_materials.len();
for _ in 0..2 {
assert_eq!(run(&mut s, "component.update_links", json!({}))["unchanged"].as_array().unwrap().len(), 1);
assert_eq!(s.doc.user_materials.len(), count);
}
assert_eq!(s.doc.user_material("Different alloy").unwrap().density, 4.2);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn reused_design_insertion_is_free_even_before_a_link_exists() {
let dir = folder("reuse-grounding");
@@ -46,6 +161,272 @@ fn reused_design_insertion_is_free_even_before_a_link_exists() {
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_update_density_without_geometry_and_keep_edited_cards() {
let dir = folder("properties-density");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Custom alloy", Some(4.2), [12, 34, 56]);
let mut s = Session::default();
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
part.doc_mut().user_materials[0].density = 4.8;
run(&mut part, "file.save", json!({}));
assert_eq!(run(&mut s, "component.update_links", json!({}))["updated"].as_array().unwrap().len(), 1);
let p = run(&mut s, "component.properties", json!({"component": c}));
assert!((p["total"]["mass_g"].as_f64().unwrap() - 4.8).abs() < 1e-6, "{p}");
let name = p["bodies"][0]["material"].as_str().unwrap().to_string();
let count = s.doc.user_materials.len();
for _ in 0..2 {
assert_eq!(run(&mut s, "component.update_links", json!({}))["unchanged"].as_array().unwrap().len(), 1);
assert_eq!(s.doc.user_materials.len(), count, "unchanged source does not duplicate a disambiguated material");
}
s.doc_mut().user_materials.iter_mut().find(|m| m.name == name).unwrap().density = 6.0;
part.doc_mut().user_materials[0].density = 5.0;
run(&mut part, "file.save", json!({}));
run(&mut s, "component.update_links", json!({}));
assert_link_properties(&mut s, c, &name, 6.0, [12, 34, 56]);
let assembly = dir.join("assembly.solidcraft");
run(&mut s, "file.save", json!({"path": assembly}));
let mut cold = Session::default();
run(&mut cold, "doc.open", json!({"path": assembly}));
assert_link_properties(&mut cold, c, &name, 6.0, [12, 34, 56]);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_keep_opaque_pbr_and_face_color_after_reload() {
use solidcraft_doc::appearance::{FaceLook, Look};
use solidcraft_geom::Vec3;
let dir = folder("properties-optics");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Steel", None, [12, 34, 56]);
let mut look = Look::custom([12, 34, 56], 1.0);
look.pbr = Some(solidcraft_doc::pbr_appearance::PbrParameters::new(0.8, 0.23, 1.5).unwrap());
part.doc_mut().appearances.bodies.insert("Cube".into(), look.clone());
let top = Vec3::new(5.0, 5.0, 10.0);
part.doc_mut().appearances.faces.push(FaceLook {
body: "Cube".into(),
point: top,
look: Look::custom([190, 20, 30], 0.65),
name: None,
strict_name: false,
certificate: None,
});
run(&mut part, "file.save", json!({}));
let mut s = Session::default();
run(&mut s, "solid.box", json!({"length": 1, "width": 1, "height": 1, "body_name": "Cube"}));
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
assert!(!s.doc.appearances.faces.iter().any(|face| face.body == "Cube"), "the assembly's existing body keeps its appearance");
let check = |s: &Session| {
let state = s.model.state();
let body = state.bodies.iter().find(|b| b.component == c).unwrap();
assert_eq!(s.doc.model_body_look(body), Some(look.clone()));
let face = solidcraft_doc::appearance::face_index_at(body, top).unwrap();
let face_looks = s.doc.face_colors(body);
let face_look = &face_looks.iter().find(|(f, _)| *f == face).unwrap().1;
assert_eq!(face_look.color, [190, 20, 30]);
assert!((face_look.opacity - 0.65).abs() < 1e-6);
};
check(&s);
let assembly = dir.join("assembly.solidcraft");
run(&mut s, "file.save", json!({"path": assembly}));
let mut cold = Session::default();
run(&mut cold, "doc.open", json!({"path": assembly}));
check(&cold);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_face_overrides_update_independently_and_preserve_local_edits_and_removals() {
use solidcraft_doc::appearance::{FaceLook, Look};
use solidcraft_geom::Vec3;
let dir = folder("properties-faces");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Steel", None, [12, 34, 56]);
let top = Vec3::new(5.0, 5.0, 10.0);
let side = Vec3::new(10.0, 5.0, 5.0);
for (point, color) in [(top, [190, 20, 30]), (side, [20, 190, 30])] {
part.doc_mut().appearances.faces.push(FaceLook {
body: "Cube".into(),
point,
look: Look::custom(color, 1.0),
name: None,
strict_name: false,
certificate: None,
});
}
run(&mut part, "file.save", json!({}));
let mut s = Session::default();
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
let color = |s: &Session, point| {
let state = s.model.state();
let body = state.bodies.iter().find(|b| b.component == c).unwrap();
let index = solidcraft_doc::appearance::face_index_at(body, point).unwrap();
s.doc.face_colors(body).into_iter().find(|(face, _)| *face == index).map(|(_, look)| look.color)
};
assert_eq!(color(&s, top), Some([190, 20, 30]));
assert_eq!(color(&s, side), Some([20, 190, 30]));
part.doc_mut().appearances.faces[0].look = Look::custom([30, 40, 200], 1.0);
part.doc_mut().appearances.faces.pop();
run(&mut part, "file.save", json!({}));
run(&mut s, "component.update_links", json!({}));
assert_eq!(color(&s, top), Some([30, 40, 200]));
assert_eq!(color(&s, side), None, "a removed source override reveals the body's look");
run(&mut s, "edit.undo", json!({}));
assert_eq!(color(&s, side), Some([20, 190, 30]));
run(&mut s, "edit.redo", json!({}));
assert_eq!(color(&s, side), None);
let mut local = s.doc.appearances.faces[0].clone();
local.look = Look::custom([200, 180, 30], 1.0);
s.doc_mut().appearances.faces.push(local);
let assembly = dir.join("assembly.solidcraft");
run(&mut s, "file.save", json!({"path": assembly}));
let mut cold = Session::default();
run(&mut cold, "doc.open", json!({"path": assembly}));
part.doc_mut().appearances.faces[0].look = Look::custom([40, 50, 60], 1.0);
run(&mut part, "file.save", json!({}));
run(&mut cold, "component.update_links", json!({}));
assert_eq!(color(&cold, top), Some([200, 180, 30]), "a local face edit survives a source edit after reopening");
cold.doc_mut().appearances.faces.clear();
part.doc_mut().appearances.faces[0].look = Look::custom([60, 70, 80], 1.0);
run(&mut part, "file.save", json!({}));
run(&mut cold, "component.update_links", json!({}));
assert_eq!(color(&cold, top), None, "an explicit local removal is not restored by a source update");
// A link saved by the earlier material-only implementation must be read again,
// even when the file read cache already knows the current source bytes.
cold.doc_mut().links.get_mut(&c).unwrap().inherited[0].faces = None;
run(&mut cold, "component.update_links", json!({}));
assert_eq!(color(&cold, top), Some([60, 70, 80]));
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_properties_update_every_component_and_session_sharing_a_cached_source() {
let dir = folder("properties-shared-read");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Source alloy", Some(4.2), [12, 34, 56]);
let mut s = Session::default();
let a = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
let b = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
let mut other = Session::default();
let c = run(&mut other, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
part.doc_mut().user_materials[0].density = 4.8;
run(&mut part, "file.save", json!({}));
let updated = run(&mut s, "component.update_links", json!({}));
assert_eq!(updated["updated"].as_array().unwrap().len(), 2, "{updated}");
for component in [a, b] {
let p = run(&mut s, "component.properties", json!({"component": component}));
assert!((p["total"]["mass_g"].as_f64().unwrap() - 4.8).abs() < 1e-6, "{p}");
}
run(&mut other, "component.update_links", json!({}));
let p = run(&mut other, "component.properties", json!({"component": c}));
assert!((p["total"]["mass_g"].as_f64().unwrap() - 4.8).abs() < 1e-6, "{p}");
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_face_removal_without_a_body_look_does_not_reveal_baked_source_paint() {
use solidcraft_doc::appearance::{FaceLook, Look};
let dir = folder("properties-unpainted-body");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Steel", None, [12, 34, 56]);
part.doc_mut().appearances.bodies.clear();
part.doc_mut().appearances.faces.push(FaceLook {
body: "Cube".into(),
point: solidcraft_geom::Vec3::new(5.0, 5.0, 10.0),
look: Look::custom([190, 20, 30], 0.65),
name: None,
strict_name: false,
certificate: None,
});
run(&mut part, "file.save", json!({}));
let mut s = Session::default();
run(&mut s, "component.insert_design", json!({"path": file}));
assert_eq!(s.doc.face_colors(&s.model.state().bodies[0]).len(), 1);
assert!(s.doc.appearances.bodies.is_empty());
s.doc_mut().appearances.faces.clear();
assert!(s.doc.face_colors(&s.model.state().bodies[0]).is_empty(), "local removal must reveal the body's material, not duplicate STEP paint");
part.doc_mut().appearances.faces[0].look = Look::custom([20, 190, 30], 0.8);
run(&mut part, "file.save", json!({}));
run(&mut s, "component.update_links", json!({}));
assert!(s.doc.face_colors(&s.model.state().bodies[0]).is_empty(), "source edits must preserve the local removal");
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn unchanged_linked_face_overrides_do_not_reorder_assignments_or_report_updates() {
use solidcraft_doc::appearance::{FaceLook, Look};
let dir = folder("properties-face-cache");
let file = dir.join("source.solidcraft");
let mut part = properties_part(&file, "Steel", None, [12, 34, 56]);
part.doc_mut().appearances.faces.push(FaceLook {
body: "Cube".into(),
point: solidcraft_geom::Vec3::new(5.0, 5.0, 10.0),
look: Look::custom([190, 20, 30], 0.65),
name: None,
strict_name: false,
certificate: None,
});
run(&mut part, "file.save", json!({}));
let mut s = Session::default();
for _ in 0..2 {
run(&mut s, "component.insert_design", json!({"path": file}));
}
let before = s.doc.clone();
for _ in 0..2 {
let result = run(&mut s, "component.update_links", json!({}));
assert!(result["updated"].as_array().unwrap().is_empty(), "{result}");
assert_eq!(result["unchanged"].as_array().unwrap().len(), 2, "{result}");
assert_eq!(s.doc, before, "unchanged links preserve assignment order and inherited baselines");
}
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_survive_save_as_and_relink_with_undo() {
let dir = folder("properties-relink");
let first = dir.join("first.solidcraft");
let second = dir.join("second.solidcraft");
properties_part(&first, "Steel", None, [12, 34, 56]);
properties_part(&second, "Aluminum", None, [80, 90, 100]);
let mut s = Session::default();
let c = run(&mut s, "component.insert_design", json!({"path": first}))["component"].as_u64().unwrap();
let baseline = s.doc.links[&c].inherited.clone();
let assembly = dir.join("assembly.solidcraft");
run(&mut s, "file.save", json!({"path": assembly}));
let saved_as = dir.join("saved-as.solidcraft");
run(&mut s, "file.save", json!({"path": saved_as}));
let mut cold = Session::default();
run(&mut cold, "doc.open", json!({"path": saved_as}));
assert_eq!(cold.doc.links[&c].inherited, baseline);
run(&mut cold, "component.relink", json!({"component": c, "path": second}));
assert_link_properties(&mut cold, c, "Aluminum", 2.7, [80, 90, 100]);
run(&mut cold, "edit.undo", json!({}));
assert_link_properties(&mut cold, c, "Steel", 7.85, [12, 34, 56]);
run(&mut cold, "edit.redo", json!({}));
assert_link_properties(&mut cold, c, "Aluminum", 2.7, [80, 90, 100]);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn linked_design_properties_repair_old_links_without_overwriting_assignments() {
let dir = folder("properties-legacy");
let file = dir.join("source.solidcraft");
properties_part(&file, "Steel", None, [12, 34, 56]);
let mut s = Session::default();
let c = run(&mut s, "component.insert_design", json!({"path": file}))["component"].as_u64().unwrap();
s.doc_mut().links.get_mut(&c).unwrap().inherited.clear();
s.doc_mut().materials.remove("Cube");
s.doc_mut().appearances.bodies.remove("Cube");
run(&mut s, "component.update_links", json!({}));
assert_link_properties(&mut s, c, "Steel", 7.85, [12, 34, 56]);
s.doc_mut().links.get_mut(&c).unwrap().inherited.clear();
run(&mut s, "material.assign", json!({"bodies": ["Cube"], "material": "Brass"}));
s.doc_mut().appearances.bodies.insert("Cube".into(), solidcraft_doc::appearance::Look::custom([1, 2, 3], 0.4));
run(&mut s, "component.update_links", json!({}));
assert_link_properties(&mut s, c, "Brass", solidcraft_doc::material_density("Brass").unwrap(), [1, 2, 3]);
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn relink_repairs_a_moved_source_for_every_instance_in_one_undo_step() {
let dir = folder("moved");
+2 -2
View File
@@ -68,7 +68,7 @@ pub(super) fn resolve(design: Option<&str>, link: &str) -> PathBuf {
/// The links of `doc` stored for a design saved at `to` instead of at `from`.
pub(super) fn rebased(doc: &Document, from: Option<&str>, to: &str) -> std::collections::BTreeMap<u64, DesignLink> {
doc.links.iter().map(|(c, l)| (*c, DesignLink { path: stored(Some(to), &resolve(from, &l.path)), feature: l.feature })).collect()
doc.links.iter().map(|(c, l)| (*c, DesignLink { path: stored(Some(to), &resolve(from, &l.path)), ..l.clone() })).collect()
}
#[cfg(test)]
@@ -90,7 +90,7 @@ mod tests {
let unsaved = stored(None, &part);
assert!(Path::new(&unsaved).is_absolute(), "{unsaved}");
let mut doc = Document::default();
doc.links.insert(7, DesignLink { path: unsaved, feature: 3 });
doc.links.insert(7, DesignLink { path: unsaved, feature: 3, ..Default::default() });
let moved = rebased(&doc, None, &design);
assert_eq!(moved.get(&7).map(|l| l.path.as_str()), Some("../parts/plate.solidcraft"));
let beside = root.join("parts").join("asm.solidcraft").to_string_lossy().into_owned();
+55
View File
@@ -80,7 +80,11 @@ pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("select.set", "Select", select_set).icon("select")
.noundo()
.params("items: [{type: body|edge|face|feature|sketch_curve|sketch_point|profile, …}], add?: bool"),
CommandSpec::new("select.filter", "Selection filter", select_filter).icon("select").noundo().doc_only()
.params("mode: body|face|component → validated UI pick granularity; headless echo only, no document edits or undo"),
CommandSpec::new("select.clear", "Clear Selection", select_clear).icon("select").noundo(),
CommandSpec::new("select.same_look", "Select Same Look", select_same_look).icon("select").noundo().doc_only()
.params("body?: world body name, face?: face index; defaults to the current body/face selection → selects objects using the resolved appearance"),
];
fn undo(s: &mut Session, _p: &Value) -> Result<Value> {
@@ -1199,6 +1203,57 @@ fn select_set(s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({"selected": s.selection.len()}))
}
fn select_filter(_s: &mut Session, p: &Value) -> Result<Value> {
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct Request {
mode: String,
}
let request: Request = serde_json::from_value(p.clone()).map_err(|e| bad("select.filter", e.to_string()))?;
if !matches!(request.mode.as_str(), "body" | "face" | "component") {
return Err(bad("select.filter", "mode must be body, face or component"));
}
Ok(json!({"mode": request.mode}))
}
fn select_same_look(s: &mut Session, p: &Value) -> Result<Value> {
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct Request {
body: Option<String>,
face: Option<usize>,
}
let request: Request = serde_json::from_value(p.clone()).map_err(|e| bad("select.same_look", e.to_string()))?;
let selected = s.selection.last();
let name = request
.body
.as_deref()
.or(match selected {
Some(Sel::Body { name }) => Some(name.as_str()),
Some(Sel::Face { body, .. }) => Some(body.as_str()),
_ => None,
})
.ok_or_else(|| bad("select.same_look", "select an object or face"))?;
let state = s.world_state();
let body = state.body(name).ok_or_else(|| bad("select.same_look", "unknown object"))?;
let face = request.face.or(match selected {
Some(Sel::Face { body, index, .. }) if request.body.is_none() && body == name => Some(*index),
_ => None,
});
if let Some(face) = face
&& face >= body.body.face_count()
{
return Err(bad("select.same_look", "unknown face"));
}
let look = face.map_or_else(|| s.doc.model_display_look(body), |face| s.doc.model_face_look(body, face));
let items: Vec<_> =
state.bodies.iter().filter(|b| s.doc.model_used_looks(b).contains(&look)).take(10_001).map(|b| Sel::Body { name: b.name.clone() }).collect();
if items.len() > 10_000 {
return Err(bad("select.same_look", "too many objects"));
}
select_set(s, &json!({"items":items}))
}
fn select_clear(s: &mut Session, _p: &Value) -> Result<Value> {
s.selection.clear();
s.revision += 1;
+38
View File
@@ -1244,3 +1244,41 @@ fn a_reorder_keeps_the_model_it_was_checked_on() {
fresh.evaluate(&s.doc);
assert_eq!(fresh.state().bodies.len(), bodies(&s));
}
#[test]
fn select_same_look_uses_resolved_looks_without_document_history_edits_and_refuses_hostile_input() {
let mut s = Session::default();
for (name, x) in [("A", 0), ("B", 20), ("C", 40)] {
run(&mut s, "solid.box", json!({"corner":[x,0,0],"length":10,"width":10,"height":10,"body_name":name}));
}
run(&mut s, "appearance.assign", json!({"bodies":["A","B"],"appearance":"ABS - Red"}));
run(&mut s, "appearance.assign", json!({"bodies":["C"],"appearance":"ABS - Blue"}));
run(&mut s, "appearance.assign", json!({"body":"C","faces":[[40,5,5]],"appearance":"ABS - Red"}));
let doc = s.doc.clone();
let history = (s.undo.len(), s.redo.len(), s.evaluations);
run(&mut s, "select.same_look", json!({"body":"A"}));
assert_eq!(s.selection.len(), 3);
let point = solidcraft_geom::Vec3::new(40.0, 5.0, 5.0);
let face = solidcraft_doc::appearance::face_index_at(s.world_state().body("C").unwrap(), point).unwrap();
run(&mut s, "select.set", json!({"items":[Sel::Face {body:"C".into(),index:face,point}]}));
run(&mut s, "select.same_look", json!({}));
assert_eq!(s.selection.len(), 3);
run(&mut s, "select.same_look", json!({"body":"C"}));
assert_eq!(s.selection, [Sel::Body { name: "C".into() }]);
let selected = s.selection.clone();
// Session treats null parameters as the command's empty/default object.
run(&mut s, "select.same_look", Value::Null);
for params in [
json!([]),
json!({"body":"missing"}),
json!({"body":"A","face":u64::MAX}),
json!({"body":"A","face":-1}),
json!({"body":1}),
json!({"body":"A","extra":true}),
] {
assert!(s.execute("select.same_look", &params).is_err(), "{params}");
assert_eq!(s.selection, selected);
}
assert!(std::sync::Arc::ptr_eq(&doc, &s.doc));
assert_eq!(history, (s.undo.len(), s.redo.len(), s.evaluations));
}
+80 -64
View File
@@ -12,6 +12,9 @@ use super::CommandSpec;
use crate::params::{bad, bool_, str_, string_list};
use crate::{EngineError, Result, Session};
#[path = "appearance_chain.rs"]
mod appearance_chain;
pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("inspect.colored_components", "Enable Component Colors", colored_components)
.at("SOLID", "INSPECT").icon("colored_components").noundo()
@@ -46,6 +49,12 @@ pub static COMMANDS: &[CommandSpec] = &[
appearance?: library name or stable starter.* ID (appearance.library) | color: \"#rrggbb\" or [r, g, b] (0–255), opacity? (0–1, default 1); \
name?: inert copied look label (requires color, mutually exclusive with appearance); pbr?: {metallic:0..1, roughness:0.045..1, dielectric_ior:1..3} (requires color/appearance and opacity 1); a starter ID or registered starter name resolves its recipe before color overrides; omitted pbr retains that response and pbr: null explicitly clears it. Unavailable glass recipes refuse through either selector. Other custom labels with an explicit color retain legacy scalar behavior. Neither appearance nor color (or color: null): clear, so the face follows its body, the body its component, the component its material",
),
CommandSpec::new("appearance.chain", "Appearance Chain", appearance_chain::chain).icon("inspect").noundo().params(
"target: {body: name} | {body: name, face: zero-based model.faces index} | {component: name or id}. Returns steps [{step: face|body|component|material, look: {name,color,opacity,pbr?} or null}] in precedence order and active (step or null). Component material is the common default look of its directly owned bodies, null if mixed/empty. Imported paint is a display fallback outside the four steps. Read-only; no dialogs",
),
CommandSpec::new("appearance.replace", "Replace Appearance", appearance_chain::replace).icon("appearance").params(
"from: library name | saved look {name,color,opacity,pbr?} (copy appearance.list in_design); to: library name | assignment look {appearance? | color, name?, opacity?, pbr?} (appearance.assign rules; no clear). Matches the full look including name and PBR. scope?: {bodies?: [names], components?: [names or ids]}, at most 10000 targets; body scope includes face overrides, component scope selects only the component override. Omitted scope means all overrides, including hidden/suppressed ones; physical defaults are unchanged. Duplicate targets count once. Returns count of rewritten overrides; zero adds no history. One undo step, atomic; no dialogs. Designs above 100000 overrides refuse",
),
CommandSpec::new("appearance.library", "Appearance Library", appearance_library).icon("library")
.noundo()
.params("→ 20 legacy scalar appearances, six opaque PBR finishes and 40 starter recipes with IDs, categories, provenance, requirements and availability; six starter glass recipes are unavailable"),
@@ -474,71 +483,9 @@ pub(super) fn color_param(v: &Value) -> Option<[u8; 3]> {
}
pub(super) fn appearance(s: &mut Session, p: &Value) -> Result<Value> {
use solidcraft_doc::appearance::{FaceLook, Look, library};
use solidcraft_doc::appearance::FaceLook;
let cmd = "appearance.assign";
// A saved label is data, not a request to resolve a recipe. Keep the explicit
// appearance selector separate so an owned look may have any recipe's ID as its name.
let copied_name = match p.get("name") {
None | Some(Value::Null) => None,
Some(Value::String(name)) if !name.is_empty() && name.chars().count() <= 128 && !name.chars().any(char::is_control) => Some(name),
_ => return Err(bad(cmd, "`name` must be a nonempty label of at most 128 characters without controls")),
};
if copied_name.is_some() && (p.get("color").is_none_or(Value::is_null) || p.get("appearance").is_some_and(|value| !value.is_null())) {
return Err(bad(cmd, "`name` requires an explicit color and cannot be combined with `appearance`"));
}
// Both the stable ID and a registered display name explicitly select a recipe.
// Copied labels use `name`, so color overrides cannot bypass unsupported optics.
let preset = str_(p, "appearance").and_then(solidcraft_doc::appearance_pack::find);
let mut look: Option<Look> = if let Some(preset) = preset {
// Refuse unsupported optics before any color/PBR/opacity override.
let mut look = preset.opaque_look().map_err(|e| bad(cmd, e.to_string()))?;
if let Some(color) = p.get("color").filter(|v| !v.is_null()) {
look.color = color_param(color).ok_or_else(|| bad(cmd, "invalid preset color override"))?;
}
if let Some(opacity) = p.get("opacity").and_then(Value::as_f64).filter(|x| x.is_finite()) {
look.opacity = opacity.clamp(0.0, 1.0);
}
Some(look)
} else {
match (str_(p, "appearance"), p.get("color")) {
// A colour with a name: that colour, called that (a name not in the library is fine).
(Some(n), Some(v)) if !v.is_null() => {
let c = color_param(v).ok_or_else(|| bad(cmd, "`color` must be \"#rrggbb\" or [r, g, b] with values 0–255"))?;
let o = p.get("opacity").and_then(Value::as_f64).filter(|x| x.is_finite()).unwrap_or(1.0);
let mut l = Look::custom(c, o);
l.name = n.chars().take(128).collect();
Some(l)
}
(Some(n), _) => {
let mut l = if let Some(preset) = solidcraft_doc::appearance_pack::find(n) {
preset.opaque_look().map_err(|e| bad(cmd, e.to_string()))?
} else {
library(n).ok_or_else(|| bad(cmd, format!("no appearance `{n}` in the library (appearance.library)")))?
};
if let Some(o) = p.get("opacity").and_then(Value::as_f64).filter(|x| x.is_finite()) {
l.opacity = o.clamp(0.0, 1.0);
}
Some(l)
}
(None, None | Some(Value::Null)) => None,
(None, Some(v)) => {
let c = color_param(v).ok_or_else(|| bad(cmd, "`color` must be \"#rrggbb\" or [r, g, b] with values 0–255"))?;
let o = match p.get("opacity") {
Some(o) => o.as_f64().filter(|x| x.is_finite() && (0.0..=1.0).contains(x)).ok_or_else(|| bad(cmd, "`opacity` must be 0…1"))?,
None => 1.0,
};
Some(Look::custom(c, o))
}
}
};
if let Some(l) = &mut look {
if let Some(name) = copied_name {
l.name = name.clone();
}
attach_pbr(cmd, p, l)?;
} else if p.get("pbr").is_some_and(|v| !v.is_null()) {
return Err(bad(cmd, "`pbr` requires a color or appearance"));
}
let look = appearance_look(cmd, p)?;
let bodies = string_list(p, "bodies");
let st = s.model.state();
if bodies.iter().any(|b| st.body(b).is_none()) {
@@ -642,6 +589,75 @@ pub(super) fn appearance(s: &mut Session, p: &Value) -> Result<Value> {
}))
}
/// Shared look parser for assignment and atomic replacement.
pub(super) fn appearance_look(cmd: &str, p: &Value) -> Result<Option<solidcraft_doc::appearance::Look>> {
use solidcraft_doc::appearance::{Look, library};
// A saved label is data, not a request to resolve a recipe. Keep the explicit
// appearance selector separate so an owned look may have any recipe's ID as its name.
let copied_name = match p.get("name") {
None | Some(Value::Null) => None,
Some(Value::String(name)) if !name.is_empty() && name.chars().count() <= 128 && !name.chars().any(char::is_control) => Some(name),
_ => return Err(bad(cmd, "`name` must be a nonempty label of at most 128 characters without controls")),
};
if copied_name.is_some() && (p.get("color").is_none_or(Value::is_null) || p.get("appearance").is_some_and(|value| !value.is_null())) {
return Err(bad(cmd, "`name` requires an explicit color and cannot be combined with `appearance`"));
}
// Both the stable ID and a registered display name explicitly select a recipe.
// Copied labels use `name`, so color overrides cannot bypass unsupported optics.
let preset = str_(p, "appearance").and_then(solidcraft_doc::appearance_pack::find);
let mut look: Option<Look> = if let Some(preset) = preset {
// Refuse unsupported optics before any color/PBR/opacity override.
let mut look = preset.opaque_look().map_err(|e| bad(cmd, e.to_string()))?;
if let Some(color) = p.get("color").filter(|v| !v.is_null()) {
look.color = color_param(color).ok_or_else(|| bad(cmd, "invalid preset color override"))?;
}
if let Some(opacity) = p.get("opacity").and_then(Value::as_f64).filter(|x| x.is_finite()) {
look.opacity = opacity.clamp(0.0, 1.0);
}
Some(look)
} else {
match (str_(p, "appearance"), p.get("color")) {
// A colour with a name: that colour, called that (a name not in the library is fine).
(Some(n), Some(v)) if !v.is_null() => {
let c = color_param(v).ok_or_else(|| bad(cmd, "`color` must be \"#rrggbb\" or [r, g, b] with values 0–255"))?;
let o = p.get("opacity").and_then(Value::as_f64).filter(|x| x.is_finite()).unwrap_or(1.0);
let mut l = Look::custom(c, o);
l.name = n.chars().take(128).collect();
Some(l)
}
(Some(n), _) => {
let mut l = if let Some(preset) = solidcraft_doc::appearance_pack::find(n) {
preset.opaque_look().map_err(|e| bad(cmd, e.to_string()))?
} else {
library(n).ok_or_else(|| bad(cmd, format!("no appearance `{n}` in the library (appearance.library)")))?
};
if let Some(o) = p.get("opacity").and_then(Value::as_f64).filter(|x| x.is_finite()) {
l.opacity = o.clamp(0.0, 1.0);
}
Some(l)
}
(None, None | Some(Value::Null)) => None,
(None, Some(v)) => {
let c = color_param(v).ok_or_else(|| bad(cmd, "`color` must be \"#rrggbb\" or [r, g, b] with values 0–255"))?;
let o = match p.get("opacity") {
Some(o) => o.as_f64().filter(|x| x.is_finite() && (0.0..=1.0).contains(x)).ok_or_else(|| bad(cmd, "`opacity` must be 0…1"))?,
None => 1.0,
};
Some(Look::custom(c, o))
}
}
};
if let Some(l) = &mut look {
if let Some(name) = copied_name {
l.name = name.clone();
}
attach_pbr(cmd, p, l)?;
} else if p.get("pbr").is_some_and(|v| !v.is_null()) {
return Err(bad(cmd, "`pbr` requires a color or appearance"));
}
Ok(look)
}
fn dist_to(b: &solidcraft_doc::ModelBody, p: solidcraft_geom::Vec3) -> f64 {
let bb = b.mesh().bounds();
let c = solidcraft_geom::Vec3::new(p.x.clamp(bb.min.x, bb.max.x), p.y.clamp(bb.min.y, bb.max.y), p.z.clamp(bb.min.z, bb.max.z));
+97 -11
View File
@@ -14,7 +14,7 @@ use solidcraft_geom::{Aabb3, Vec3};
use super::contact_sweep::{ContactGeometry, Member};
use super::{drive_with_contact, joint_id, keyed, occurrences, path_world, study_index, traced_point, values_at};
use crate::params::{bad, bool_};
use crate::params::{bad, bool_, num};
use crate::{EngineError, Result, Session};
pub const PLOT_DOC: &str = "study: id|name; joints?: [id|name] (default: every joint that moves); occurrence? and point? (a point \
@@ -30,10 +30,12 @@ pub const PLOT_DOC: &str = "study: id|name; joints?: [id|name] (default: every j
pub const INTERFERENCE_DOC: &str = "study: id|name; occurrences?: [ids or names] (two or more, checked against each other; \
default every occurrence), with against?: [ids or names] (then each of `occurrences` is checked only against these, such \
as an arm against the parts it must miss), or contact_sets?: true (the pairs of the design's contact sets); samples? \
(2…1000, default the study's steps + 1) → collisions: [{a, b, first_step, last_step, steps: [[from, to]…] (the step ranges where they overlap), \
(2…1000, default the study's steps + 1); budget_s?: seconds (above 0, at most 86400; default a fixed work budget): the \
time the check may take instead, looked at between samples, for a mechanism such as a gear train that needs longer → collisions: [{a, b, first_step, last_step, steps: [[from, to]…] (the step ranges where they overlap), \
depth_mm (how far into each other, the most at deepest_step), volume_mm3 (their overlap there; null when it was not \
cheap to work out)}], clear, \
pairs (checked), samples (taken), truncated (the work budget ran out; checked_to: the last step checked), stopped_at, \
cheap to work out)}], clear (every sample checked and none collide; never while truncated), \
pairs (checked), samples (taken), truncated (the work budget, or budget_s, ran out; checked_to: the last step checked), budget_s \
(when given), stopped_at, \
stopped_by_loop. The study plays as motion.play plays it but contact sets do not stop it, on a copy (the design is not \
changed). Parts are tested at the samples only: one that passes wholly through another between two samples is missed";
@@ -43,6 +45,8 @@ const MAX_SAMPLES: usize = 1000;
const MAX_SERIES: usize = 256;
/// Most collision work over a whole study (see `ContactGeometry::hits`).
const MAX_WORK: usize = 500_000_000;
/// Longest time an interference check may be given (`budget_s`): a day, as `inspect.interference`.
const MAX_BUDGET_S: f64 = 86_400.0;
/// Most colliding pairs whose overlap volume is worked out, and most body booleans that takes.
const MAX_VOLUMES: usize = 16;
const MAX_BOOLEANS: usize = 64;
@@ -359,21 +363,42 @@ pub(super) fn checked_pairs(s: &Session, p: &Value, cmd: &str) -> Result<Contact
pub(super) fn interference(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "motion.interference";
let seconds = match p.get("budget_s") {
None | Some(Value::Null) => None,
Some(_) => match num(p, "budget_s") {
Some(v) if v > 0.0 && v <= MAX_BUDGET_S => Some(v),
_ => return Err(bad(cmd, format!("`budget_s` must be a number of seconds above 0, at most {MAX_BUDGET_S}"))),
},
};
interference_within(s, p, MAX_WORK, seconds)
}
/// `motion.interference` with at most `budget` collision work (see `ContactGeometry::hits`), or,
/// given `seconds`, with that time instead: the work is then not counted against a budget, and
/// the time is looked at before each sample, so the last one may run past it (#7855).
fn interference_within(s: &mut Session, p: &Value, budget: usize, seconds: Option<f64>) -> Result<Value> {
let cmd = "motion.interference";
let deadline = seconds.and_then(|v| std::time::Duration::try_from_secs_f64(v).ok()).and_then(|d| web_time::Instant::now().checked_add(d));
let budget = if deadline.is_some() { usize::MAX } else { budget };
let m = s.doc.assembly.studies.get(study_index(s, p, cmd)?).cloned().ok_or_else(|| bad(cmd, "study"))?;
let n = samples(p, &m, 2, cmd)?;
let geometry = checked_pairs(s, p, cmd)?;
let mut found: BTreeMap<(u64, u64), Collision> = BTreeMap::new();
let (mut work, mut checked, mut truncated) = (0usize, 0usize, false);
let stop = play(s, &m, n, false, |t, k| {
// Placing the meshes is work too, also where nothing comes near.
work = work.saturating_add(geometry.vertex_count());
if work > MAX_WORK {
if deadline.is_some_and(|d| web_time::Instant::now() >= d) {
truncated = true;
return Ok(false);
}
let hits: Vec<(Member, Member, f64)> = match geometry.hits(t, &mut work, MAX_WORK, true) {
// Placing the meshes is work too, also where nothing comes near.
work = work.saturating_add(geometry.vertex_count());
if work > budget {
truncated = true;
return Ok(false);
}
let hits: Vec<(Member, Member, f64)> = match geometry.hits(t, &mut work, budget, true) {
Ok(h) => h,
Err(_) if work > MAX_WORK => {
Err(_) if work > budget => {
truncated = true;
return Ok(false);
}
@@ -401,7 +426,13 @@ pub(super) fn interference(s: &mut Session, p: &Value) -> Result<Value> {
})?;
// Nothing checked is not clear.
if truncated && checked == 0 {
return Err(bad(cmd, "the check ran out of its work budget before its first step: check fewer parts (occurrences, against)"));
return Err(bad(
cmd,
match seconds {
Some(_) => "the check ran out of its budget_s before its first step: give it more time or check fewer parts (occurrences, against)",
None => "the check ran out of its work budget before its first step: check fewer parts (occurrences, against) or give it a budget_s",
},
));
}
let mut list: Vec<(&(u64, u64), &Collision)> = found.iter().collect();
list.sort_by_key(|(_, c)| c.samples.first().copied().unwrap_or(usize::MAX));
@@ -417,11 +448,16 @@ pub(super) fn interference(s: &mut Session, p: &Value) -> Result<Value> {
"depth_mm": c.depth, "deepest_step": step_of(&m, c.deepest, n), "volume_mm3": volume})
})
.collect();
let mut out = json!({"study": m.name, "steps": m.steps, "clear": collisions.is_empty(), "collisions": collisions,
// A check cut short says nothing about the steps it did not reach, so it is not clear (#7855).
let clear = collisions.is_empty() && !truncated;
let mut out = json!({"study": m.name, "steps": m.steps, "clear": clear, "collisions": collisions,
"pairs": geometry.pair_count(), "samples": checked, "truncated": truncated});
if truncated {
out["checked_to"] = json!(checked.checked_sub(1).map(|k| step_of(&m, k, n)));
}
if let Some(v) = seconds {
out["budget_s"] = json!(v);
}
out["stopped_at"] = stop["stopped_at"].clone();
out["stopped_by_loop"] = stop["stopped_by_loop"].clone();
Ok(out)
@@ -431,6 +467,56 @@ pub(super) fn interference(s: &mut Session, p: &Value) -> Result<Value> {
mod tests {
use super::*;
fn run(s: &mut Session, id: &str, p: Value) -> Value {
s.execute(id, &p).unwrap_or_else(|e| panic!("{id} {p}: {e}"))
}
/// Cube B (x 20…30) slides from 10 mm away until it touches A (x 0…10) over the 15 steps of
/// study "Push": nothing ever overlaps.
fn touching() -> Session {
let mut s = Session::default();
for (name, x) in [("A", 0), ("B", 20)] {
run(&mut s, "component.activate", json!({"component": "root"}));
run(&mut s, "component.create", json!({"name": name}));
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 10, "corner": [x, 0, 0]}));
}
run(&mut s, "component.activate", json!({"component": "root"}));
let a = s.doc.find_component("A").and_then(|c| s.doc.occurrence_of(c)).map(|o| o.id).unwrap_or(0);
run(&mut s, "occurrence.ground", json!({"occurrence": a, "grounded": true}));
run(&mut s, "joint.create", json!({"type": "slider", "a": {"face": [10, 5, 5]}, "b": {"face": [20, 5, 5]}, "name": "Rail"}));
run(&mut s, "joint.drive", json!({"joint": "Rail", "value": 10}));
run(&mut s, "motion.study", json!({"name": "Push", "steps": 15, "keys": [{"joint": "Rail", "points": [[0, 10], [15, 0]]}]}));
s
}
/// #7855: a check its work budget cuts short is not clear, though nothing collided in the
/// steps it reached.
#[test]
fn a_check_cut_short_is_not_clear() {
let mut s = touching();
let p = json!({"study": "Push"});
let full = run(&mut s, "motion.interference", p.clone());
assert!(full["clear"] == true && full["truncated"] == false && full["samples"] == 16, "{full}");
assert!(full.get("budget_s").is_none(), "{full}");
// The least work that checks a first step stops long before the last.
let cut = (0..31).find_map(|i| interference_within(&mut s, &p, 1usize << i, None).ok()).unwrap_or_default();
assert!(cut["truncated"] == true && cut["samples"].as_u64().is_some_and(|n| (1..16).contains(&n)), "{cut}");
assert!(cut["collisions"] == json!([]) && cut["clear"] == false, "{cut}");
}
/// #7855: given `budget_s`, the time is the budget, not the work: the smallest work budget,
/// which stops a check before its first step, no longer stops it.
#[test]
fn a_time_budget_takes_the_place_of_the_work_budget() {
let mut s = touching();
let p = json!({"study": "Push"});
assert!(interference_within(&mut s, &p, 1, None).is_err(), "one unit of work checks no step");
let timed = interference_within(&mut s, &p, 1, Some(600.0)).unwrap_or_default();
assert!(timed["clear"] == true && timed["truncated"] == false && timed["samples"] == 16, "{timed}");
let r = run(&mut s, "motion.interference", json!({"study": "Push", "budget_s": 600}));
assert!(r["clear"] == true && r["samples"] == 16 && r["budget_s"] == 600.0, "{r}");
}
/// The differences are exact for a quadratic: its velocity and acceleration everywhere,
/// the ends too.
#[test]
@@ -201,6 +201,10 @@ fn motion_analysis_refuses_what_it_cannot_do() {
("motion.interference", json!({"study": "Push", "occurrences": ["A"]})),
("motion.interference", json!({"study": "Push", "occurrences": ["A", "B"], "contact_sets": true})),
("motion.interference", json!({"study": "Push", "contact_sets": true})),
("motion.interference", json!({"study": "Push", "budget_s": 0})),
("motion.interference", json!({"study": "Push", "budget_s": -1})),
("motion.interference", json!({"study": "Push", "budget_s": 1e9})),
("motion.interference", json!({"study": "Push", "budget_s": "soon"})),
];
for (cmd, p) in refused {
assert!(s.execute(cmd, &p).is_err(), "{cmd} {p}");
@@ -637,3 +637,223 @@ fn starter_names_and_ids_share_admission_before_all_overrides() {
}
}
}
fn chain_read(s: &mut Session, target: serde_json::Value) -> serde_json::Value {
s.execute("appearance.chain", &json!({"target":target})).unwrap()
}
#[test]
fn appearance_chain_and_from_material_preserve_mass_and_all_four_steps() {
let mut s = Session::default();
s.execute("component.create", &json!({"name":"Part"})).unwrap();
s.execute("solid.box", &json!({"body_name":"Specimen","length":10,"width":20,"height":5})).unwrap();
s.execute("material.create", &json!({"name":"Substrate","density_g_cm3":2.3,"appearance":"Steel - Satin PBR"})).unwrap();
s.execute("material.assign", &json!({"bodies":["Specimen"],"material":"Substrate"})).unwrap();
let mass = s.execute("component.properties", &json!({})).unwrap();
let physical = s.doc.user_materials.clone();
let face = s.execute("model.faces", &json!({"body":"Specimen"})).unwrap()["faces"]
.as_array()
.unwrap()
.iter()
.find(|f| f["point"][2] == 5.0)
.unwrap()["index"]
.clone();
let target = json!({"body":"Specimen","face":face});
s.execute("appearance.assign", &json!({"components":["Part"],"appearance":"ABS - Blue"})).unwrap();
s.execute("appearance.assign", &json!({"bodies":["Specimen"],"color":"#abcdef","opacity":0.5})).unwrap();
s.execute("appearance.assign", &json!({"body":"Specimen","faces":[[5,10,5]],"appearance":"Copper - Clean PBR"})).unwrap();
let history = (s.undo.len(), s.redo.len(), s.revision);
let doc = s.doc.clone();
let chain = chain_read(&mut s, target.clone());
assert_eq!(chain["active"], "face");
assert_eq!(
chain["steps"].as_array().unwrap().iter().map(|s| s["step"].as_str().unwrap()).collect::<Vec<_>>(),
["face", "body", "component", "material"]
);
assert_eq!(chain["steps"][0]["look"]["name"], "Copper - Clean PBR");
assert_eq!(chain["steps"][1]["look"]["opacity"], 0.5);
assert_eq!(chain["steps"][2]["look"]["name"], "ABS - Blue");
assert_eq!(chain["steps"][3]["look"]["pbr"]["metallic"], 1.0);
assert!(Arc::ptr_eq(&doc, &s.doc));
assert_eq!((s.undo.len(), s.redo.len(), s.revision), history);
assert_eq!(chain_read(&mut s, json!({"body":"Specimen"}))["active"], "body");
assert_eq!(chain_read(&mut s, json!({"component":"Part"}))["active"], "component");
// The existing clear form walks down the same chain, one edit at a time.
s.execute("appearance.assign", &json!({"body":"Specimen","faces":[[6,11,5]],"color":null})).unwrap();
assert_eq!(chain_read(&mut s, target.clone())["active"], "body");
s.execute("appearance.assign", &json!({"bodies":["Specimen"],"color":null})).unwrap();
assert_eq!(chain_read(&mut s, target.clone())["active"], "component");
s.execute("appearance.assign", &json!({"components":["Part"]})).unwrap();
for t in [target.clone(), json!({"body":"Specimen"}), json!({"component":"Part"})] {
assert_eq!(chain_read(&mut s, t)["active"], "material");
}
// Clearing each target independently also restores material when no lower override exists.
for assign in [json!({"bodies":["Specimen"]}), json!({"components":["Part"]}), json!({"body":"Specimen","faces":[[5,10,5]]})] {
let mut painted = assign.clone();
painted["appearance"] = json!("ABS - Red");
s.execute("appearance.assign", &painted).unwrap();
s.execute("appearance.assign", &assign).unwrap();
assert_eq!(chain_read(&mut s, target.clone())["active"], "material");
assert_eq!(s.execute("component.properties", &json!({})).unwrap(), mass);
}
assert_eq!(s.doc.user_materials, physical);
let state = s.model.state();
let body = state.body("Specimen").unwrap();
assert_eq!(s.doc.model_face_look(body, face.as_u64().unwrap() as usize), s.doc.model_display_look(body));
let mut reopened = Session::new(crate::doc::Document::from_json(&s.doc.to_json()).unwrap());
assert_eq!(chain_read(&mut reopened, target.clone()), chain_read(&mut s, target));
}
#[test]
fn appearance_replace_is_exact_atomic_one_undo_and_survives_reopen() {
let mut s = Session::default();
s.execute("component.create", &json!({"name":"Part"})).unwrap();
s.execute("solid.box", &json!({"body_name":"Specimen","length":10,"width":20,"height":5})).unwrap();
s.execute("material.create", &json!({"name":"Substrate","density_g_cm3":2.3,"appearance":"Steel - Satin PBR"})).unwrap();
s.execute("material.assign", &json!({"bodies":["Specimen"],"material":"Substrate"})).unwrap();
s.execute(
"appearance.assign",
&json!({"bodies":["Specimen"],"components":["Part"],"body":"Specimen","faces":[[5,10,5]],"appearance":"Steel - Satin PBR"}),
)
.unwrap();
// Same label and color, different optical values: full equality must distinguish it.
let mut scalar = s.doc.appearances.bodies["Specimen"].clone();
scalar.pbr = None;
s.doc_mut().appearances.bodies.insert("Suppressed fixture".into(), scalar.clone());
let mass = s.execute("component.properties", &json!({})).unwrap();
let scene = product_scene::extract(&s).unwrap();
let before = s.doc.clone();
let history = s.undo.len();
let listed = s.execute("appearance.list", &json!({})).unwrap();
let from = listed["in_design"].as_array().unwrap().iter().find(|l| l.get("pbr").is_some()).unwrap().clone();
let params = json!({"from":from,"to":"Copper - Clean PBR"});
assert_eq!(s.execute("appearance.replace", &params).unwrap()["count"], 3);
assert_eq!(s.undo.len(), history + 1);
assert_eq!(s.doc.appearances.bodies["Suppressed fixture"], scalar);
assert_eq!(s.doc.user_materials, before.user_materials);
assert_eq!(s.doc.materials, before.materials);
assert_eq!(s.doc.features, before.features);
assert_eq!(s.doc.occurrences, before.occurrences);
assert_eq!(s.execute("component.properties", &json!({})).unwrap(), mass);
let after_scene = product_scene::extract(&s).unwrap();
assert!(Arc::ptr_eq(&scene.meshes[0].mesh, &after_scene.meshes[0].mesh));
let after = s.doc.appearances.clone();
s.execute("edit.undo", &json!({})).unwrap();
assert_eq!(s.doc.appearances, before.appearances);
s.execute("edit.redo", &json!({})).unwrap();
assert_eq!(s.doc.appearances, after);
let reopened = Session::new(crate::doc::Document::from_json(&s.doc.to_json()).unwrap());
assert_eq!(reopened.doc.appearances, after);
let snapshot = s.doc.clone();
let history = (s.undo.len(), s.redo.len(), s.revision);
assert_eq!(s.execute("appearance.replace", &params).unwrap()["count"], 0);
assert_eq!(s.execute("appearance.replace", &json!({"from":"Copper - Clean PBR","to":"Copper - Clean PBR"})).unwrap()["count"], 0);
assert!(Arc::ptr_eq(&snapshot, &s.doc));
assert_eq!((s.undo.len(), s.redo.len(), s.revision), history);
}
#[test]
fn appearance_replace_scope_deduplicates_and_does_not_expand_component_targets() {
let mut s = Session::default();
s.execute("component.create", &json!({"name":"Part"})).unwrap();
s.execute("solid.box", &json!({"body_name":"Specimen","length":10,"width":20,"height":5})).unwrap();
let part = s.doc.find_component("Part").unwrap();
let assign = json!({"bodies":["Specimen"],"components":["Part"],"body":"Specimen","faces":[[5,10,5]],"appearance":"ABS - Red"});
s.execute("appearance.assign", &assign).unwrap();
let history = s.undo.len();
assert_eq!(
s.execute(
"appearance.replace",
&json!({"from":"ABS - Red","to":{"color":"#123456","opacity":0.4},"scope":{"bodies":["Specimen","Specimen"]}})
)
.unwrap()["count"],
2
);
assert_eq!(s.undo.len(), history + 1);
assert_eq!(s.doc.appearances.components[&part].name, "ABS - Red");
assert_eq!(
s.execute("appearance.replace", &json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"components":[part,"Part",part.to_string()]}}))
.unwrap()["count"],
1
);
assert_eq!(s.doc.appearances.bodies["Specimen"].color, [18, 52, 86]);
// Empty scope is an explicit no-op, and a no-op preserves an existing redo entry.
s.execute("edit.undo", &json!({})).unwrap();
let doc = s.doc.clone();
let history = (s.undo.len(), s.redo.len(), s.revision);
assert_eq!(s.execute("appearance.replace", &json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"bodies":[]}})).unwrap()["count"], 0);
assert!(Arc::ptr_eq(&doc, &s.doc));
assert_eq!((s.undo.len(), s.redo.len(), s.revision), history);
}
#[test]
fn appearance_chain_and_replace_hostile_inputs_refuse_atomically() {
let mut s = fixture();
s.execute("appearance.assign", &json!({"bodies":["Specimen"],"appearance":"ABS - Red"})).unwrap();
let doc = s.doc.clone();
let history = (s.undo.len(), s.redo.len(), s.revision);
for target in [
json!({}),
json!({"body":"missing"}),
json!({"component":"missing"}),
json!({"component":0}),
json!({"body":"Specimen","face":u64::MAX}),
json!({"body":"Specimen","face":-1}),
json!({"body":"Specimen","component":1}),
json!({"body":["Specimen"]}),
json!({"body":"Specimen","face":null}),
] {
assert!(s.execute("appearance.chain", &json!({"target":target})).is_err());
}
for value in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
// JSON has no nonfinite numbers: serde_json encodes these as null.
for look in [
json!({"color":[value,0,0]}),
json!({"color":"#ffffff","opacity":value}),
json!({"color":"#ffffff","pbr":{"metallic":value,"roughness":0.3,"dielectric_ior":1.5}}),
] {
for field in ["from", "to"] {
let mut params = json!({"from":"ABS - Red","to":"ABS - Blue"});
params[field] = look.clone();
assert!(s.execute("appearance.replace", &params).is_err());
}
}
}
for params in [
json!({"from":"ABS - Red","to":null}),
json!({"from":"unknown","to":"ABS - Blue"}),
json!({"from":"ABS - Red","to":{"color":[256,0,0]}}),
json!({"from":"ABS - Red","to":{"appearance":"ABS - Blue","opacity":2}}),
json!({"from":"ABS - Red","to":{"appearance":"starter.glass.clear-soda-lime","color":"#ffffff","pbr":null}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"bodies":["Specimen","missing"]}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"components":["missing"]}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"bodies":["Specimen"],"components":[false]}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"bodies":vec!["Specimen";10_001]}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"bodies":vec!["Specimen";5001],"components":vec!["missing";5000]}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"bodies":"Specimen"}}),
json!({"from":"ABS - Red","to":"ABS - Blue","scope":{"faces":[]}}),
] {
assert!(s.execute("appearance.replace", &params).is_err(), "{params}");
assert!(Arc::ptr_eq(&doc, &s.doc));
assert_eq!((s.undo.len(), s.redo.len(), s.revision), history);
}
}
#[test]
fn appearance_chain_and_replace_process_ten_thousand_entries_with_bounded_output() {
let mut s = fixture();
let look = crate::doc::appearance::library("ABS - Red").unwrap();
for i in 0..10_000 {
// Suppressed definition overrides are still uses and must be replaced.
s.doc_mut().appearances.bodies.insert(format!("Dormant {i}"), look.clone());
}
let chain = chain_read(&mut s, json!({"body":"Specimen"}));
assert_eq!(chain["steps"].as_array().unwrap().len(), 4);
assert!(chain["active"].is_null());
assert_eq!(s.execute("appearance.replace", &json!({"from":"ABS - Red","to":"ABS - Blue"})).unwrap(), json!({"count":10_000}));
assert!(s.doc.appearances.bodies.values().all(|l| l.name == "ABS - Blue"));
assert_eq!(
s.execute("appearance.replace", &json!({"from":"ABS - Blue","to":"ABS - Red","scope":{"bodies":vec!["Specimen";10_000]}})).unwrap()["count"],
0
);
}
-1
View File
@@ -17,7 +17,6 @@ macro_rules! waiting {
pub static COMMANDS: &[CommandSpec] = &[
waiting!("appearance.paint", "Paint Appearance", "RENDER APPEARANCE", "APPEARANCE", "appearance", "product picking and appearance painting"),
waiting!("appearance.pick_up", "Pick Up Appearance", "RENDER APPEARANCE", "APPEARANCE", "select", "product picking and appearance sampling"),
waiting!("appearance.replace", "Replace Appearance", "RENDER APPEARANCE", "APPEARANCE", "appearance", "replacing all uses of an appearance"),
waiting!("render.lights.solo", "Solo Light", "RENDER SCENE", "LIGHTS", "render_scene", "light visibility and solo controls"),
waiting!("render.compare", "Compare Images", "RENDER", "RESULT", "compare", "retained image comparison"),
waiting!("render.batch", "Render All Shots", "RENDER", "BATCH", "render_image", "the saved-shot render queue"),
+4 -2
View File
@@ -16,7 +16,7 @@ pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("canvas.decal", "Decal", add_decal)
.at("SKETCH", "INSERT")
.icon("decal")
.params("path | data; face: [x,y,z] on a planar face (the image is centred there); width?: mm; angle?: deg; opacity?: (default 1)"),
.params("path | data; face: [x,y,z] on a planar face (the image is centred there), or the picked face as sketch.create's plane takes it ({face, body, index, path?}); width?: mm; angle?: deg; opacity?: (default 1)"),
CommandSpec::new("canvas.edit", "Edit Canvas", edit_canvas).at("SKETCH", "INSERT").icon("canvas").params("canvas: id or name; center?, width?, angle?: deg, opacity?, flip?, visible?, name?"),
CommandSpec::new("canvas.calibrate", "Calibrate Canvas", calibrate).icon("measure")
.params("canvas: id or name; a, b: two points on the canvas plane [x,y]; distance: their true distance (mm): scales the image about a"),
@@ -88,9 +88,11 @@ fn add_canvas(s: &mut Session, p: &Value) -> Result<Value> {
fn add_decal(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "canvas.decal";
let face = p.get("face").cloned().ok_or_else(|| bad(cmd, "`face` must be a point [x,y,z] on a planar face"))?;
// A picked face as `sketch.create` takes it ({face, body, index, path?}) is used as it is.
let plane = if face.get("face").is_some() { face } else { json!({"face": face}) };
let mut q = p.clone();
if let Some(o) = q.as_object_mut() {
o.insert("plane".into(), json!({"face": face}));
o.insert("plane".into(), plane);
}
make(s, &q, cmd, true)
}
+217
View File
@@ -4,8 +4,32 @@ use solidcraft_render::{Camera, StandardView};
use super::CommandSpec;
use crate::params::{bad, num, req_vec2, req_vec3, vec3};
use crate::schema::view_navigation::{RenderBrowser, RenderFocus};
use crate::schema::{TypedContract, output_schema_for};
use crate::{Result, Sel, Session};
const FOCUS_CONTRACT: TypedContract<RenderFocus> = TypedContract::new();
const BROWSER_CONTRACT: TypedContract<RenderBrowserRequest> = TypedContract::new();
// Both existing request forms share the Browser command and its published schema.
#[derive(serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
#[serde(untagged)]
enum RenderBrowserRequest {
Open(RenderBrowser),
Controls(RenderBrowserControls),
}
#[derive(serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
struct RenderBrowserControls {
#[serde(skip_serializing_if = "Option::is_none")]
by_look: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
search: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
query: Option<String>,
}
pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("view.fit", "Fit", fit)
.icon("fit").key("F6").noundo().doc_only().params("no parameters → frame the active canvas or selection; display only"),
@@ -23,12 +47,28 @@ CommandSpec::new("view.ground_shadow", "Ground shadow", ground_shadow)
.icon("style").noundo().doc_only().params("on?: bool (omitted: toggle) → on?; show the ground shadow"),
CommandSpec::new("view.navigation_bar", "Navigation bar", navigation_bar)
.icon("pan").noundo().doc_only().params("visible?: bool (omitted: toggle) → visible?; show the navigation bar (window setting)"),
CommandSpec::new("view.render_focus", "Render Focus View", crate::checked!("view.render_focus", render_focus))
.icon("render_scene").noundo().doc_only()
.contract(&FOCUS_CONTRACT).output(output_schema_for::<RenderFocus>)
.params("on: bool → {on}; per-window UI state, never saved in the design; headless validation only"),
CommandSpec::new("view.render_browser", "Render Browser", crate::checked!("view.render_browser", render_browser))
.icon("list").noundo().doc_only()
.contract(&BROWSER_CONTRACT).output(output_schema_for::<RenderBrowserRequest>)
.params("open: bool; or by_look?: bool; search?: bool; query?: string (up to 1024 bytes) → validated transient Browser controls; never edits the design or opens a dialog"),
CommandSpec::new("view.render_select", "Render selection", render_select)
.icon("select").noundo().doc_only()
.params("kind: nothing|environment|light|shot|output; id?: bounded nonempty string for light/shot → validated transient Browser focus; never edits the design or opens a dialog"),
CommandSpec::new("view.render_stage", "Render Stage", render_stage)
.icon("render_scene").noundo().doc_only()
.params("stage: look|light|frame|output → {stage}; per-document UI state, never edits or evaluates the design; headless validation only"),
CommandSpec::new("view.shots_strip", "Shots Strip", shots_strip)
.at("RENDER CAMERA", "SHOTS").icon("camera").noundo().doc_only()
.params("visible: bool → {visible}; Render Shots strip UI preference. Headless echo only, no document edits or undo"),
CommandSpec::new("view.render_dock", "Move Render Dock", crate::checked!("view.render_dock", render_dock))
.at("RENDER", "SCENE").icon("settings").noundo().doc_only()
.contract(&RENDER_DOCK_CONTRACT)
.output(crate::schema::output_schema_for::<crate::schema::view_navigation::RenderDock>)
.params("panel: inspector|browser; side: left|right → {panel, side}; Render dock UI preference; headless echo only, no document edits or undo"),
CommandSpec::new("view.layout", "Workspace layout", layout)
.icon("settings").noundo().doc_only().params("mode: floating|compact → validated workspace layout; display only, never opens a dialog"),
CommandSpec::new("view.history_layout", "History layout", history_layout)
@@ -210,6 +250,53 @@ fn navigation_bar(_s: &mut Session, p: &Value) -> Result<Value> {
view_toggle(p, "view.navigation_bar", "visible")
}
fn render_focus(_s: &mut Session, p: &Value) -> Result<Value> {
let request: RenderFocus = serde_json::from_value(p.clone()).map_err(|e| bad("view.render_focus", e.to_string()))?;
Ok(json!(request))
}
fn render_select(s: &mut Session, p: &Value) -> Result<Value> {
#[derive(serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
struct Request {
kind: String,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
}
let request: Request = serde_json::from_value(p.clone()).map_err(|e| bad("view.render_select", e.to_string()))?;
let identified = matches!(request.kind.as_str(), "light" | "shot");
if !matches!(request.kind.as_str(), "nothing" | "environment" | "light" | "shot" | "output")
|| identified != request.id.is_some()
|| request.id.as_ref().is_some_and(|id| id.trim().is_empty() || id.len() > 1024)
{
return Err(bad("view.render_select", "expected a Browser kind and an id only for light or shot"));
}
let result = serde_json::to_value(request).map_err(|e| bad("view.render_select", e.to_string()))?;
if !s.selection.is_empty() {
s.selection.clear();
s.revision += 1;
}
Ok(result)
}
fn render_browser(_s: &mut Session, p: &Value) -> Result<Value> {
if !p.is_object() {
return Err(bad("view.render_browser", "expected an object with Browser controls"));
}
if p.get("open").is_some() {
let request: RenderBrowser = serde_json::from_value(p.clone()).map_err(|e| bad("view.render_browser", e.to_string()))?;
return Ok(json!(request));
}
let request: RenderBrowserControls = serde_json::from_value(p.clone()).map_err(|e| bad("view.render_browser", e.to_string()))?;
if request.by_look.is_none() && request.search.is_none() && request.query.is_none() {
return Err(bad("view.render_browser", "expected at least one Browser control"));
}
if request.query.as_ref().is_some_and(|q| q.len() > 1024) {
return Err(bad("query", "expected at most 1024 bytes"));
}
serde_json::to_value(request).map_err(|e| bad("view.render_browser", e.to_string()))
}
fn render_stage(_s: &mut Session, p: &Value) -> Result<Value> {
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
@@ -223,6 +310,14 @@ fn render_stage(_s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({"stage":request.stage}))
}
const RENDER_DOCK_CONTRACT: crate::schema::TypedContract<crate::schema::view_navigation::RenderDock> = crate::schema::TypedContract::new();
fn render_dock(_s: &mut Session, p: &Value) -> Result<Value> {
let request: crate::schema::view_navigation::RenderDock =
serde_json::from_value(p.clone()).map_err(|e| bad("view.render_dock", e.to_string()))?;
serde_json::to_value(request).map_err(|e| bad("view.render_dock", e.to_string()))
}
fn shots_strip(_s: &mut Session, p: &Value) -> Result<Value> {
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
@@ -872,6 +967,38 @@ fn workspace_layout_validates_modes_without_mutating_the_design() {
assert!(session.undo.is_empty());
}
#[cfg(test)]
#[test]
fn render_workspace_focus_and_browser_validate_without_side_effects() {
let mut session = Session { camera: Some(Camera::default()), ..Default::default() };
let camera = session.camera;
let document = session.doc.clone();
let before = (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty());
for (id, field) in [("view.render_focus", "on"), ("view.render_browser", "open")] {
let command = crate::find_command(id).unwrap();
assert!(command.contract.is_some() && command.output.is_some());
for on in [true, false] {
let request = json!({field:on});
assert_eq!(session.execute(id, &request).unwrap(), request);
}
for params in [
Value::Null,
json!([]),
json!({}),
json!({field:null}),
json!({field:"true"}),
json!({field:1e300}),
json!({field:[]}),
json!({field:true,"unknown":false}),
] {
assert!(session.execute(id, &params).is_err(), "{id}: {params}");
}
}
assert!(std::sync::Arc::ptr_eq(&document, &session.doc));
assert_eq!(session.camera, camera);
assert_eq!(before, (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty()));
}
#[cfg(test)]
#[test]
fn render_workspace_shots_strip_is_a_validated_headless_preference_request() {
@@ -919,3 +1046,93 @@ fn render_workspace_stage_validates_without_document_changes_or_evaluation() {
assert!(std::sync::Arc::ptr_eq(&document, &session.doc));
assert_eq!(before, (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty()));
}
#[cfg(test)]
#[test]
fn render_workspace_dock_validates_without_mutation() {
let mut session = Session::default();
session.execute("solid.box", &json!({"length":10,"width":10,"height":10})).unwrap();
session.execute("edit.undo", &json!({})).unwrap();
let document = session.doc.clone();
let before = (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty(), session.camera);
for panel in ["inspector", "browser"] {
for side in ["left", "right"] {
let params = json!({"panel":panel,"side":side});
assert_eq!(session.execute("view.render_dock", &params).unwrap(), params);
}
}
for params in [
Value::Null,
json!([]),
json!({}),
json!({"panel":"inspector"}),
json!({"side":"left"}),
json!({"panel":true,"side":"left"}),
json!({"panel":"inspector","side":null}),
json!({"panel":"inspector","side":1e300}),
json!({"panel":"other","side":"left"}),
json!({"panel":"inspector","side":"top"}),
json!({"panel":"browser","side":"left","unknown":true}),
] {
assert!(session.execute("view.render_dock", &params).is_err(), "{params}");
}
assert!(std::sync::Arc::ptr_eq(&document, &session.doc));
assert_eq!(before, (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty(), session.camera));
}
#[cfg(test)]
#[test]
fn render_browser_focus_validates_without_document_changes_or_evaluation() {
let mut session = Session::default();
let doc = session.doc.clone();
let before = (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty());
for request in [
json!({"kind":"nothing"}),
json!({"kind":"environment"}),
json!({"kind":"light","id":"sun:0"}),
json!({"kind":"shot","id":"Hero"}),
json!({"kind":"output"}),
] {
assert_eq!(session.execute("view.render_select", &request).unwrap(), request);
}
for request in [
Value::Null,
json!([]),
json!({}),
json!({"kind":"object"}),
json!({"kind":"shot"}),
json!({"kind":"light","id":1}),
json!({"kind":"light","id":" "}),
json!({"kind":"shot","id":"x".repeat(1025)}),
json!({"kind":"output","id":"extra"}),
json!({"kind":"environment","extra":true}),
] {
assert!(session.execute("view.render_select", &request).is_err(), "{request}");
}
assert!(std::sync::Arc::ptr_eq(&doc, &session.doc));
assert_eq!(before, (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty()));
}
#[cfg(test)]
#[test]
fn render_browser_controls_validate_without_document_changes_or_evaluation() {
let mut session = Session::default();
let document = session.doc.clone();
let before = (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty());
for request in [json!({"by_look":true}), json!({"search":true,"query":"Copper"}), json!({"query":""})] {
assert_eq!(session.execute("view.render_browser", &request).unwrap(), request);
}
for request in [
Value::Null,
json!([]),
json!({}),
json!({"by_look":null}),
json!({"by_look":1}),
json!({"search":null,"extra":true}),
json!({"query":"x".repeat(1025)}),
] {
assert!(session.execute("view.render_browser", &request).is_err());
}
assert!(std::sync::Arc::ptr_eq(&document, &session.doc));
assert_eq!(before, (session.undo.len(), session.redo.len(), session.revision, session.evaluations, session.is_dirty()));
}
+1
View File
@@ -58,6 +58,7 @@ pub mod edit;
pub mod features;
pub mod inspect;
pub mod sketch_constraints;
pub mod view_navigation;
pub use check::{Contract, Issue, ParamCheck, TypedContract, input_schema_for, output_schema_for, run_checked, run_checked_as};
pub use types::*;
@@ -0,0 +1,38 @@
//! Render shell requests. The UI applies validated echoes without design edits.
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct RenderDock {
pub panel: RenderPanel,
pub side: DockSide,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum RenderPanel {
Inspector,
Browser,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum DockSide {
Left,
Right,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct RenderFocus {
/// Hide the Render docks while retaining their layout and the current camera.
pub on: bool,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct RenderBrowser {
/// Open the floating Browser card in a narrow Render window.
pub open: bool,
}
@@ -78,3 +78,37 @@ fn cancelled_import_stops_and_leaves_the_design_alone() {
assert!(done < total, "stopped part way ({done} of {total})");
let _ = std::fs::remove_file(path);
}
/// A preview cancelled while it imports again (#7167) keeps no "cancelled" result: the scratch
/// session shares the evaluation cache with the design, which then evaluates the same inputs and
/// imports in full.
#[test]
fn a_cancelled_preview_import_leaves_no_failure_in_the_shared_cache() {
let path = step_file("preview", 300);
let mut s = Session::default();
s.execute("solid.box", &json!({"length": 10, "width": 10, "height": 10, "body_name": "first"})).unwrap();
s.execute("file.insert_step", &json!({"path": path})).unwrap();
let import = s.doc.features.iter().position(|f| matches!(f.kind, FeatureKind::Import { .. })).unwrap();
// A new length for the box: the import after it is evaluated again on new inputs.
let redefine =
json!({"feature": s.doc.features[0].id, "command": "solid.box", "params": {"length": 20, "width": 10, "height": 10, "body_name": "first"}});
let mut scratch = s.scratch();
let progress = Arc::new(Progress::default());
let canceller = {
let progress = progress.clone();
std::thread::spawn(move || {
while progress.work().is_none() {
std::thread::yield_now();
}
progress.cancel();
})
};
let _ = solidcraft_doc::progress::watch(progress.clone(), || scratch.execute("timeline.redefine", &redefine));
canceller.join().unwrap();
let (_, done, total) = progress.work().unwrap();
assert!(done < total, "the preview's import stopped part way ({done} of {total})");
s.execute("timeline.redefine", &redefine).unwrap();
let result = &s.model.results[import];
assert!(result.error.is_none() && !result.skipped, "the design imports in full: {:?}", result.error);
let _ = std::fs::remove_file(path);
}
+18 -7
View File
@@ -231,6 +231,7 @@ fn send_to_slicer_needs_a_slicer_and_bodies() {
}
/// The chosen-programs list is process-wide: tests that set it take turns.
#[cfg(unix)]
static CHOSEN_PROGRAMS: std::sync::Mutex<()> = std::sync::Mutex::new(());
/// `file.save_mesh` with a `slicer` writes where the caller said and hands that file over, by the
@@ -437,7 +438,10 @@ fn send_to_slicer_writes_3mf_and_starts_the_program_with_it() {
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
let (script, seen) = (dir.join("fake-slicer"), dir.join("seen"));
std::fs::write(&script, format!("#!/bin/sh\necho \"$@\" > {}\n", seen.display())).unwrap();
// Publish the acknowledgement only after writing it: cleanup must wait for every launch.
let writing = dir.join("writing");
std::fs::write(&script, format!("#!/bin/sh\nprintf '%s\\n' \"$@\" > '{}'\nmv '{}' '{}'\n", writing.display(), writing.display(), seen.display()))
.unwrap();
std::fs::set_permissions(&script, std::fs::Permissions::from_mode(0o755)).unwrap();
run(&mut s, "select.set", json!({"items":[{"type":"body","name":"Mesh"}]}));
// A program nobody chose is refused; once it is among the user's chosen ones it starts.
@@ -452,19 +456,26 @@ fn send_to_slicer_writes_3mf_and_starts_the_program_with_it() {
assert_eq!(r["format"], "3mf");
let file = r["path"].as_str().unwrap().to_string();
assert!(std::fs::read(&file).unwrap().starts_with(b"PK"));
for _ in 0..100 {
if seen.exists() && std::fs::metadata(&seen).unwrap().len() > 0 {
break;
let await_launch = |expected: &str| {
for _ in 0..100 {
if seen.exists() {
assert_eq!(std::fs::read_to_string(&seen).unwrap().trim(), expected);
std::fs::remove_file(&seen).unwrap();
return;
}
std::thread::sleep(std::time::Duration::from_millis(50));
}
std::thread::sleep(std::time::Duration::from_millis(50));
}
assert_eq!(std::fs::read_to_string(&seen).unwrap().trim(), file);
panic!("fake slicer did not acknowledge {expected}");
};
await_launch(&file);
// Sending the same bodies again replaces the file; the same name in the same private folder.
let again = s.execute("file.send_to_slicer", &json!({"slicer": script})).unwrap();
assert_eq!((again["path"].as_str(), again["numbered"].as_bool()), (Some(file.as_str()), Some(false)));
await_launch(&file);
let stl = s.execute("file.send_to_slicer", &json!({"slicer": script, "format": "stl"})).unwrap();
assert!(stl["path"].as_str().unwrap().ends_with(".stl"));
assert_ne!(stl["path"], r["path"]);
await_launch(stl["path"].as_str().unwrap());
crate::slicers::set_chosen_programs(&[]);
std::fs::remove_dir_all(std::path::Path::new(&file).parent().unwrap()).unwrap();
std::fs::remove_dir_all(dir).unwrap();
+2 -1
View File
@@ -3242,6 +3242,7 @@ impl Renderer {
if cb.product {
res.product.take(device, queue, &res.uniform, &res.uniform_bgl, cb.key, &cb.slot, None, false);
res.product.sort_glass(queue, cb.back);
res.highlight.take(device, queue, &res.uniform, &res.uniform_bgl, cb.hl_key, &cb.hl_slot, None, false);
queue.write_buffer(&res.uniform, 0, &uniform_bytes(cb, cb.size_px[0], cb.size_px[1], res.linear_out, res.target.reversed_depth()));
// The product picture goes through the window's pass too: offscreen when the targets
// differ or it is drawn smaller, else straight into the window's pass.
@@ -3434,7 +3435,7 @@ impl Renderer {
}
};
let (m, sk, h, pv) = if cb.product {
(&res.product, &res.empty, &res.empty, &res.empty)
(&res.product, &res.empty, &res.highlight, &res.empty)
} else if cb.pv_hide {
(&res.model, &res.sketch, &res.highlight, &res.empty)
} else {
+1 -1
View File
@@ -115,7 +115,7 @@ pub fn show(app: &mut SolveApp, ctx: &egui::Context) {
});
d.by_definition = grouping == 1;
ui.separator();
crate::ui_kit::checkbox(ui, "Sub-parts in their part's row", &mut d.group_children);
crate::ui_kit::checkbox(ui, crate::i18n::tr("bom.group_children"), &mut d.group_children);
if was != (d.top, d.by_definition, d.group_children) {
d.picked = None;
}
+198 -282
View File
@@ -64,7 +64,6 @@ pub(crate) fn reveal_body(app: &mut SolveApp, body: &str) {
#[path = "browser_model_tests.rs"]
mod model_tests;
use crate::icons::glyphs::badge;
use std::collections::BTreeSet;
use egui::{Color32, FontId, Pos2, Rect, Sense, Stroke, pos2, vec2};
@@ -75,7 +74,7 @@ use solidcraft_engine::doc::FeatureKind;
use crate::context_menu::{Item, Target};
use crate::theme::Tokens;
use crate::{SolveApp, icons};
use crate::SolveApp;
thread_local! {
/// The rows drawn this frame: (label, row, fold arrow area, open). For automation
@@ -446,220 +445,31 @@ pub fn group_action(app: &mut SolveApp, action: &str, p: &Value) {
// Drawing
// ---------------------------------------------------------------------------------------------
const ROW_H: f32 = crate::ui_kit::TREE_ROW_HEIGHT;
/// The floating card's inner margin: the header highlight sits this far from the card's top, left
/// and right edges, so its corners are concentric with the card's.
const CARD_INSET: f32 = 4.0;
const HEADER_H: f32 = 26.0;
const INDENT: f32 = 14.0;
/// Opacity of a dimmed row's icon (a hidden body, sketch, origin item, …).
const DIM_ICON_OPACITY: f32 = 0.4;
use crate::ui_kit::RowResp;
fn row_rect(ui: &egui::Ui) -> Rect {
Rect::from_min_size(ui.cursor().min, vec2(ui.available_width(), ROW_H))
crate::ui_kit::tree_row_rect(ui, &Row { compact: compact_tree(ui), ..Default::default() })
}
/// One row's look.
#[derive(Default)]
pub(crate) struct Row<'a> {
pub(crate) depth: usize,
/// Some(open) for rows that fold.
pub(crate) fold: Option<bool>,
/// Some(visible) for rows with an eye.
pub(crate) eye: Option<bool>,
pub(crate) icon: &'a str,
pub(crate) label: &'a str,
/// The label is a name someone gave (a body, sketch, component, …): it is shown as typed,
/// not translated when it happens to match a UI label.
pub(crate) name: bool,
pub(crate) selected: bool,
pub(crate) dim: bool,
pub(crate) color: Option<Color32>,
/// Component rows: is it the active one?
pub(crate) radio: Option<bool>,
/// Trailing badges: "lock", "pin".
pub(crate) badges: &'a [&'a str],
/// A button at the row's right end: (icon, tooltip label), e.g. a feature's profile sketch.
pub(crate) action: Option<(&'a str, &'a str)>,
/// Lit by the selection or the 3D view's pointer: the item's own row, or a row leading to it.
pub(crate) mark: Mark,
pub(crate) use crate::ui_kit::{Mark, Row};
fn compact_tree(ui: &egui::Ui) -> bool {
ui.ctx().data(|d| d.get_temp::<bool>(egui::Id::new("sc_compact_tree"))).unwrap_or(false)
}
/// How a row relates to what the selection and the 3D view's pointer light.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum Mark {
#[default]
None,
/// A row a lit item is inside (its component, placement, folder or group): a faint bar.
Branch,
/// A lit item's own row: a solid bar, and the hover colour unless it is selected.
Here,
}
/// What happened on a row.
#[derive(Default)]
pub(crate) struct RowResp {
pub(crate) rect: Option<Rect>,
pub(crate) clicked: bool,
pub(crate) double: bool,
pub(crate) secondary: Option<Pos2>,
pub(crate) fold: bool,
pub(crate) eye: bool,
pub(crate) radio: bool,
/// The row's [`Row::action`] button was clicked.
pub(crate) action: bool,
pub(crate) hovered: bool,
/// The row's response (drag and drop).
pub(crate) resp: Option<egui::Response>,
/// The press began on the fold arrow, eye or radio (not a drag of the row).
pub(crate) on_control: bool,
}
pub(crate) fn draw_row(ui: &mut egui::Ui, id: egui::Id, row: &Row) -> RowResp {
let t = Tokens::get();
// Rows scrolled out of view only take their space: no widgets, no painting.
let r = row_rect(ui);
if !ui.is_rect_visible(r) {
ui.allocate_space(r.size());
return RowResp { rect: Some(r), ..Default::default() };
}
// A stable id per row (not the layout position), so a press and its release stay on the
// same row while rows above open or close.
let (r, _) = ui.allocate_exact_size(vec2(ui.available_width(), ROW_H), Sense::hover());
let resp = ui.interact(r, id, Sense::click_and_drag());
// While something is dragged (an appearance swatch, drawn under the pointer) `hovered` is
// off; the row under the pointer still counts, so a drop lands on it.
let dragged_over = egui::DragAndDrop::has_any_payload(ui.ctx()) && ui.input(|i| i.pointer.hover_pos()).is_some_and(|p| r.contains(p));
let mut out = RowResp { rect: Some(r), hovered: resp.hovered() || dragged_over, ..Default::default() };
if row.selected {
ui.painter().rect_filled(r, t.radius_sm.saturating_sub(1), crate::theme::TabAccent::current(ui.ctx()).soft);
} else if resp.hovered() || row.mark == Mark::Here {
ui.painter().rect_filled(r, t.radius_sm.saturating_sub(1), t.hover);
}
// A lit item (selected, or under the pointer in the 3D view): a bar down the left of its row,
// and a fainter, thinner one on each row leading to it, so the bars trace its branch.
let bar = match row.mark {
Mark::None => None,
Mark::Branch => Some((2.0, t.accent.gamma_multiply(0.4))),
Mark::Here => Some((3.0, t.accent)),
};
if let Some((w, colour)) = bar {
ui.painter().rect_filled(Rect::from_min_size(r.left_top() + vec2(0.0, 2.0), vec2(w, r.height() - 4.0)), t.radius_sm / 4, colour);
}
let mut x = r.left() + 2.0 + row.depth as f32 * INDENT;
let cy = r.center().y;
// The row is one widget: where a click lands decides what it does (the fold arrow with
// padding, the eye, the radio, or the row itself), so a click on the arrow never also
// selects the row or starts a drag.
let fold_r = Rect::from_min_max(pos2(x - 4.0, r.top()), pos2(x + 15.0, r.bottom()));
let eye_r = Rect::from_center_size(pos2(x + 14.0 + 8.0, cy), vec2(19.0, r.height()));
let radio_r = Rect::from_center_size(pos2(x + 32.0 + 6.0, cy), vec2(15.0, r.height()));
// The label follows the fold arrow, eye, radio and icon (drawn below in that order). It is
// laid out first, so the action button can sit right after the name and read as the row's.
let label_x = x + 14.0 + 18.0 + if row.radio.is_some() { 15.0 } else { 0.0 } + if row.icon.is_empty() { 0.0 } else { 21.0 };
let col =
if row.selected { crate::theme::TabAccent::current(ui.ctx()).ink } else { row.color.unwrap_or(if row.dim { t.text_dim } else { t.text }) };
let label_display = if row.name { crate::i18n::tr_name(row.label) } else { crate::i18n::tr_dyn(row.label) };
let font = if row.selected { crate::fonts::semibold(t.font_label) } else { FontId::proportional(t.font_label) };
// The label stops before the action, the badges and the card's edge; a longer name ends in
// an ellipsis and its full text is in the tooltip.
let badges_width = row.badges.len() as f32 * 15.0;
let action_width = if row.action.is_some() { 22.0 } else { 0.0 };
let room = (r.right() - 4.0 - badges_width - action_width - label_x).max(0.0);
let mut job = egui::text::LayoutJob::simple(label_display.to_string(), font, col, room);
job.wrap.max_rows = 1;
job.wrap.break_anywhere = true;
job.wrap.overflow_character = Some('\u{2026}');
let galley = ui.painter().layout_job(job);
let lw = galley.size().x;
let elided = galley.elided;
let action_r = Rect::from_min_size(pos2(label_x + lw + 2.0, r.top()), vec2(20.0, r.height()));
let at = |p: Pos2| -> u8 {
if row.action.is_some() && action_r.contains(p) {
4
} else if row.fold.is_some() && fold_r.contains(p) {
1
} else if row.eye.is_some() && eye_r.contains(p) {
2
} else if row.radio.is_some() && radio_r.contains(p) {
3
} else {
0
}
};
DRAWN.with(|d| d.borrow_mut().push((row.label.to_string(), r, row.fold.map(|_| fold_r), row.fold)));
let press_on = ui.input(|i| i.pointer.press_origin()).map_or(0, at);
let click_on = resp.interact_pointer_pos().map_or(0, at);
let hover_on = resp.hover_pos().map_or(0, at);
// Fold arrow.
if let Some(open) = row.fold {
crate::ui_kit::disclosure(ui.painter(), pos2(x + 6.0, cy), open, if hover_on == 1 { t.text } else { t.text_dim });
out.fold = resp.clicked() && click_on == 1;
crate::scenario::publish_handle(&format!("fold:{}", row.label), fold_r.center());
}
x += 14.0;
// Eye.
if let Some(vis) = row.eye {
let er = Rect::from_center_size(pos2(x + 8.0, cy), vec2(15.0, 15.0));
// Hidden or faded rows keep main's dimming, with the rounded suppression asset.
icons::paint_icon(ui.painter(), er, if vis { "eye" } else { "suppress" }, if vis && !row.dim { 0.85 } else { DIM_ICON_OPACITY });
out.eye = resp.clicked() && click_on == 2;
crate::scenario::publish_handle(&format!("eye:{}", row.label), er.center());
}
x += 18.0;
// Activation radio (components).
if let Some(active) = row.radio {
let rc = pos2(x + 6.0, cy);
ui.painter().circle_stroke(rc, 5.0, Stroke::new(1.2, if active { t.accent } else { t.text_dim }));
if active {
ui.painter().circle_filled(rc, 2.8, t.accent);
}
out.radio = resp.clicked() && click_on == 3;
x += 15.0;
}
if !row.icon.is_empty() {
let ir = Rect::from_min_size(pos2(x, cy - 8.0), vec2(16.0, 16.0));
// Icons are full-colour images (a tint colour only sets their opacity): a hidden or
// faded row draws its icon faint, like its label.
icons::paint_icon(ui.painter(), ir, row.icon, if row.dim { DIM_ICON_OPACITY } else { 1.0 });
x += 21.0;
}
crate::scenario::publish_rect(&format!("row_label:{}", row.label), Rect::from_min_size(pos2(x, cy - galley.size().y / 2.0), galley.size()));
ui.painter().with_clip_rect(ui.painter().clip_rect().intersect(r)).galley(pos2(x, cy - galley.size().y / 2.0), galley, col);
let mut bx = (x + lw + 6.0 + action_width).min(r.right() - 16.0);
for b in row.badges {
let br = Rect::from_center_size(pos2(bx + 6.0, cy), vec2(12.0, 12.0));
badge(ui.painter(), br, b, t.text_dim);
bx += 15.0;
}
if let Some((icon, _)) = row.action {
if hover_on == 4 {
ui.painter().rect_filled(action_r.shrink2(vec2(1.0, 3.0)), t.radius_sm.saturating_sub(1), t.hover);
}
let ir = Rect::from_center_size(action_r.center(), vec2(14.0, 14.0));
icons::paint_icon(ui.painter(), ir, icon, if hover_on == 4 { 1.0 } else { 0.6 });
out.action = resp.clicked() && click_on == 4;
crate::scenario::publish_handle(&format!("action:{}", row.label), action_r.center());
}
crate::scenario::publish_handle(&format!("row:{}", row.label), r.center());
let tip = match hover_on {
1 => Some(if row.fold == Some(true) { crate::i18n::tr("ui.collapse") } else { crate::i18n::tr("ui.expand") }),
2 => Some(if row.eye == Some(true) { crate::i18n::tr("ui.hide") } else { crate::i18n::tr("ui.show") }),
3 => Some(if row.radio == Some(true) { crate::i18n::tr("ui.active_component") } else { crate::i18n::tr("ui.activate") }),
4 => row.action.map(|(_, tip)| crate::i18n::tr_label(tip)),
_ => None,
};
let resp = match tip {
Some(t) => resp.on_hover_text(t),
None if elided => resp.on_hover_text(label_display.to_string()),
None => resp,
};
out.on_control = press_on != 0;
out.clicked = resp.clicked() && click_on == 0;
out.double = resp.double_clicked() && click_on == 0;
out.resp = Some(resp.clone());
if resp.secondary_clicked() {
out.secondary = resp.interact_pointer_pos().or(Some(r.left_bottom()));
pub(crate) fn draw_row(ui: &mut egui::Ui, id: egui::Id, row: &Row<'_>) -> RowResp {
let compact = compact_tree(ui);
let out = crate::ui_kit::tree_row(ui, id, &Row { compact, ..*row });
if let Some(r) = out.rect.filter(|r| ui.is_rect_visible(*r)) {
let x = r.left() + if compact { Tokens::get().space_8 } else { 2.0 } + row.depth as f32 * INDENT;
let fold = row.fold.map(|_| Rect::from_min_max(pos2(x - 4.0, r.top()), pos2(x + 15.0, r.bottom())));
DRAWN.with(|d| d.borrow_mut().push((row.label.to_string(), r, fold, row.fold)));
}
out
}
@@ -1067,30 +877,70 @@ pub fn browser(app: &mut SolveApp, ui: &mut egui::Ui) {
fn render_card(app: &mut SolveApp, ui: &mut egui::Ui, acts: &mut Actions) {
let bounds = crate::shell::panel_bounds(app, ui.available_rect_before_wrap());
let narrow = bounds.width() < 800.0;
crate::shell::register_panel(app, "render:browser:show", None, None);
if narrow && !app.shell.render_browser_open {
app.shell.browser = None;
crate::shell::register_panel(app, "render:browser", None, None);
crate::render_ui::dock_chip(app, ui, "render:browser:show", "ui.browser_title", "view.render_browser", json!({"open":true}));
return;
}
let mut side = app.preferences.render_browser_side.clone();
let mut width = app.preferences.render_browser_width;
let title = app.tr("ui.browser_title").to_string();
let content = crate::ui_kit::Panel::workspace(
let title = app.tr("render.page_scene").to_string();
let labels = [app.tr("render.tree_by_object").to_string(), app.tr("render.tree_by_look").to_string()];
let search_label = app.tr("render.tree_search").to_string();
let mut lens = usize::from(app.render_workspace.view.by_look);
let mut search_clicked = false;
let content = crate::ui_kit::Panel::workspace_with_header(
ui,
crate::ui_kit::WorkspaceOptions { id: "render:browser", title: &title, icon: "list", bounds, fill_height: true },
crate::ui_kit::WorkspaceOptions {
id: "render:browser",
title: &title,
icon: "list",
bounds,
fill_height: true,
compact: crate::render_ui::compact(app, bounds.width()),
},
&mut side,
&mut width,
true,
|ui, options| {
search_clicked =
crate::ui_kit::tree_header(ui, options.title, &mut lens, &labels.iter().map(String::as_str).collect::<Vec<_>>(), &search_label);
},
|ui| {
if narrow {
let hide = crate::ui_kit::button(ui, app.tr("render.fold_browser"), crate::ui_kit::Button::Normal);
crate::scenario::publish_target("render:browser:hide", hide.rect);
if hide.clicked() {
let _ = app.run("view.render_browser", json!({"open":false}));
}
}
ui.ctx().data_mut(|d| d.insert_temp(egui::Id::new("sc_compact_tree"), true));
browser_contents(app, ui, acts, true);
ui.ctx().data_mut(|d| d.remove::<bool>(egui::Id::new("sc_compact_tree")));
},
);
app.preferences.render_browser_width = width;
if app.preferences.render_browser_side != side {
app.preferences.render_inspector_side = if side == "left" { "right" } else { "left" }.into();
if (lens == 1) != app.render_workspace.view.by_look {
let _ = app.run("view.render_browser", json!({"by_look":lens == 1}));
}
if search_clicked {
let _ = app.run("view.render_browser", json!({"search":!app.render_workspace.view.search_objects}));
}
app.preferences.render_browser_width = width;
let requested =
content.as_ref().and_then(|c| c.inner.1).map(str::to_string).or_else(|| (app.preferences.render_browser_side != side).then(|| side.clone()));
if let Some(side) = requested {
let _ = app.run("view.render_dock", serde_json::json!({"panel":"browser","side":side}));
}
app.preferences.render_browser_side = side.clone();
let rect = content.map(|c| c.response.rect);
app.shell.browser = rect;
crate::shell::register_panel(
app,
"render:browser",
rect,
Some(if side == "left" { crate::ui_kit::Edge::Left } else { crate::ui_kit::Edge::Right }),
if narrow { None } else { Some(if side == "left" { crate::ui_kit::Edge::Left } else { crate::ui_kit::Edge::Right }) },
);
if let Some(rect) = rect {
crate::scenario::publish_rect("browser:card", rect);
@@ -1153,8 +1003,10 @@ fn browser_contents(app: &mut SolveApp, ui: &mut egui::Ui, acts: &mut Actions, c
if crate::render_workspace::browser_mode(app, ui) {
return;
}
t.secondary_hline(ui.painter(), ui.max_rect().x_range(), ui.cursor().top() + 1.0, t.toolbar.lerp_to_gamma(t.border, 0.5));
ui.add_space(t.space_3);
if !render {
t.secondary_hline(ui.painter(), ui.max_rect().x_range(), ui.cursor().top() + 1.0, t.toolbar.lerp_to_gamma(t.border, 0.5));
ui.add_space(t.space_3);
}
if collapsible && !stacked {
browser_rows_hugging(app, ui, acts);
} else {
@@ -1288,7 +1140,15 @@ fn rows_scrolling(app: &mut SolveApp, ui: &mut egui::Ui, acts: &mut Actions, shr
.scroll_source(egui::scroll_area::ScrollSource { scroll_bar: true, mouse_wheel: true, ..egui::scroll_area::ScrollSource::NONE })
.show(ui, |ui| {
ui.spacing_mut().item_spacing.y = 0.0;
component_rows(app, ui, 0, 0, acts, &mut cache);
if crate::render_workspace::active(app) {
crate::render_workspace::scene::sections(app, ui);
if !crate::render_workspace::scene::objects(app, ui, &mut acts.hover_bodies, &mut acts.hovered) {
component_rows(app, ui, 0, 1, acts, &mut cache);
}
crate::render_workspace::scene::output(app, ui);
} else {
component_rows(app, ui, 0, 0, acts, &mut cache);
}
});
// The row was reached and scrolled to, or isn't in the tree (a body a later feature removes):
// either way the reveal is done.
@@ -1381,6 +1241,15 @@ fn component_rows_inner(
cache: &mut cache::Cache,
root: &mut cache::Node,
) {
if id == 0 && crate::render_workspace::active(app) {
let Some(slot) = root.folders.first_mut() else { return };
let data = slot.get_or_insert_with(|| cache.folder(app, id, None, "bodies"));
folder_rows_at(app, ui, id, None, "bodies", depth.saturating_sub(1), acts, data);
for path in &root.children {
occurrence_rows(app, ui, path, depth, acts, cache);
}
return;
}
let key = &root.key;
let reveal = app.tree.reveal.clone();
if let Some(body) = reveal.as_ref() {
@@ -1397,6 +1266,7 @@ fn component_rows_inner(
let faded = app.session.active_component != 0 && !app.session.doc.component_within(id, app.session.active_component) && !active;
let name = &root.name;
let badges: &[&str] = if root.grounded { &["pin"] } else { &[] };
let appearance = crate::render_workspace::scene::decoration(app, bodies);
let row = Row {
depth,
fold: Some(open),
@@ -1408,6 +1278,9 @@ fn component_rows_inner(
dim: faded,
radio: Some(active),
badges,
swatch: appearance.swatch,
secondary: &appearance.name,
count: &appearance.count,
// The design holds everything the tree lists.
mark: if id == 0 && acts.lit.any() { Mark::Branch } else { Mark::None },
..Default::default()
@@ -1467,19 +1340,25 @@ fn component_rows_inner(
return;
}
let d = depth + 1;
if id == 0 {
if id == 0 && !crate::render_workspace::active(app) {
doc_settings(app, ui, d);
named_view_rows(app, ui, d, acts);
origin_rows(app, ui, d, acts);
canvas_rows(app, ui, d, acts);
analysis_rows(app, ui, d, acts);
}
let render = crate::render_workspace::active(app);
for (slot, folder) in root.folders.iter_mut().zip(["bodies", "sketches", "construction"]) {
if render && folder != "bodies" {
continue;
}
let data = slot.get_or_insert_with(|| cache.folder(app, id, None, folder));
folder_rows_at(app, ui, id, None, folder, d, acts, data);
}
features::rows(app, ui, id, &[], d, acts);
if id == 0 {
if !render {
features::rows(app, ui, id, &[], d, acts);
}
if id == 0 && !render {
crate::dialogs_assembly::browser_joints(app, ui, d);
}
for path in &root.children {
@@ -1537,6 +1416,12 @@ fn occurrence_rows_inner(
let faded = app.session.active_occurrence_path.as_ref().is_some_and(|p| !path.starts_with(p) && !p.starts_with(path));
let badges: &[&str] = if placement.grounded { &["pin"] } else { &[] };
app.tree.remember(key);
let appearance = if crate::render_workspace::active(app) {
let bodies = placement.hover_bodies.get_or_insert_with(|| app.session.occurrence_bodies(path, true).unwrap_or_default());
crate::render_workspace::scene::decoration(app, bodies)
} else {
crate::render_workspace::scene::Decoration::default()
};
let r = draw_row(
ui,
ui.id().with(key),
@@ -1546,6 +1431,9 @@ fn occurrence_rows_inner(
eye: Some(own_visible),
icon: "component",
label: &placement.label,
swatch: appearance.swatch,
secondary: &appearance.name,
count: &appearance.count,
name: true,
selected,
// A cut component is faded until Paste moves it.
@@ -1609,11 +1497,17 @@ fn occurrence_rows_inner(
if !open {
return;
}
let render = crate::render_workspace::active(app);
for (slot, folder) in placement.folders.iter_mut().zip(["bodies", "sketches", "construction"]) {
if render && folder != "bodies" {
continue;
}
let data = slot.get_or_insert_with(|| cache.folder(app, placement.component, Some(path), folder));
folder_rows_at(app, ui, placement.component, Some(path), folder, depth + 1, acts, data);
}
features::rows(app, ui, placement.component, path, depth + 1, acts);
if !render {
features::rows(app, ui, placement.component, path, depth + 1, acts);
}
if path.len() < 64 {
for child in &placement.children {
occurrence_rows(app, ui, child, depth + 1, acts, cache);
@@ -2138,9 +2032,9 @@ impl Entry {
thing: Thing::Sketch(f.id),
patterns: crate::sketch_pattern_tree::has_patterns(app, f.id).then(|| format!("s:{}/patterns", f.id)),
label: if lost {
format!("{} (attachment lost)", f.name)
crate::i18n::format("browser.sketch_attachment_lost", &[("name", &crate::i18n::tr_name(&f.name))])
} else if active {
format!("{} (editing)", f.name)
crate::i18n::format("browser.sketch_editing", &[("name", &crate::i18n::tr_name(&f.name))])
} else {
f.name.clone()
},
@@ -2342,7 +2236,8 @@ fn folder_rows_at(
}
// A folded folder draws no row: its groups and items move up into its place, and their own
// eyes, hover and drops do its jobs. It is always open, as nothing could open it again.
let folded = folder == "bodies" && bodies_folded(app, comp, prefix, data.entries().count());
let render = crate::render_workspace::active(app);
let folded = !render && folder == "bodies" && bodies_folded(app, comp, prefix, data.entries().count());
let open = folded || is_open(app, key, true);
let inner = if folded { depth } else { depth + 1 };
// The folder's eye is its own: hiding it hides its items without changing theirs, and its
@@ -2350,75 +2245,89 @@ fn folder_rows_at(
// hidden, whatever their own eyes say.
let shown = !app.session.folder_hidden(key);
let folder_faded = !shown || path.is_some_and(|p| !app.session.occurrence_visible(p));
let r = if folded {
RowResp::default()
} else {
draw_row(
ui,
ui.id().with(key),
&Row {
depth,
fold: Some(open),
eye: Some(shown),
icon: "folder",
label: folder_label(folder),
dim: folder_faded,
mark: acts.lit.branch(app, data.entries()),
..Default::default()
},
)
};
if r.fold {
toggle(app, key, true);
} else if r.clicked {
// The Bodies label is the whole set while a command is asking for bodies. The arrow
// still folds it. With no such command, the label folds, as it always has.
let names: Vec<String> = data.entries().flat_map(|e| e.bodies.clone()).collect();
if !offer_bodies(app, &names, Take::Toggle) {
if !render {
let r = if folded {
RowResp::default()
} else {
draw_row(
ui,
ui.id().with(key),
&Row {
depth,
fold: Some(open),
eye: Some(shown),
icon: "folder",
label: folder_label(folder),
dim: folder_faded,
mark: acts.lit.branch(app, data.entries()),
..Default::default()
},
)
};
if r.fold {
toggle(app, key, true);
} else if r.clicked {
// The Bodies label is the whole set while a command is asking for bodies. The arrow
// still folds it. With no such command, the label folds, as it always has.
let names: Vec<String> = data.entries().flat_map(|e| e.bodies.clone()).collect();
if !offer_bodies(app, &names, Take::Toggle) {
toggle(app, key, true);
}
}
if r.eye {
toggle_folder(app, key);
}
if r.hovered {
acts.hover(data.entries().flat_map(|e| &e.bodies));
}
if let Some(p) = r.secondary {
acts.menu = Some((p, Target::Folder { component: comp, folder: fstatic.to_string(), scope: prefix.to_owned() }));
}
// Dropping on the folder row takes items out of their groups, to the end. Bodies or sketches
// from another component's folder move into this component, as a drop on its row does
// (#3270: the Bodies folder looked like the place to drop a body, and took nothing).
if let Some(resp) = &r.resp
&& let Some(d) = drop_target(ui, resp, |d: &Drag| d.folder == fstatic && (d.comp == comp || d.folder != "construction"), DropMark::Box)
{
acts.drop = Some(if d.comp == comp {
DropAction::Move { comp, folder: fstatic, keys: d.keys.clone(), group: None, before: None }
} else {
DropAction::Component { to: comp, folder: d.folder, keys: d.keys.clone() }
});
}
if !open {
return;
}
}
if r.eye {
toggle_folder(app, key);
}
if r.hovered {
acts.hover(data.entries().flat_map(|e| &e.bodies));
}
if let Some(p) = r.secondary {
acts.menu = Some((p, Target::Folder { component: comp, folder: fstatic.to_string(), scope: prefix.to_owned() }));
}
// Dropping on the folder row takes items out of their groups, to the end. Bodies or sketches
// from another component's folder move into this component, as a drop on its row does
// (#3270: the Bodies folder looked like the place to drop a body, and took nothing).
if let Some(resp) = &r.resp
&& let Some(d) = drop_target(ui, resp, |d: &Drag| d.folder == fstatic && (d.comp == comp || d.folder != "construction"), DropMark::Box)
{
acts.drop = Some(if d.comp == comp {
DropAction::Move { comp, folder: fstatic, keys: d.keys.clone(), group: None, before: None }
} else {
DropAction::Component { to: comp, folder: d.folder, keys: d.keys.clone() }
});
}
if !open {
return;
}
let loose_keys = &data.loose_keys;
if render {
for e in &data.loose {
entry_row(app, ui, comp, path, fstatic, e, depth + 1, None, loose_keys, folder_faded, acts);
}
}
for group in &data.groups {
let (id, items, gkey) = (group.id, &group.items, &group.key);
let gopen = is_open(app, gkey, true);
let gshown = !app.session.folder_hidden(gkey);
let group_faded = folder_faded || !gshown;
let label = if render {
app.session.doc.browser_groups.iter().find(|g| g.id == id).map_or(group.label.as_str(), |g| g.name.as_str())
} else {
&group.label
};
let count = if render && !gopen { crate::i18n::format("render.tree_more", &[("count", &items.len().to_string())]) } else { String::new() };
let r = draw_row(
ui,
ui.id().with(gkey),
&Row {
depth: inner,
fold: Some(gopen),
eye: Some(gshown),
icon: "folder",
label: &group.label,
eye: (!render || gopen).then_some(gshown),
icon: if render { "" } else { "folder" },
label,
name: true,
dim: group_faded,
dim: group_faded || (render && !gopen),
count: &count,
mark: acts.lit.branch(app, items),
..Default::default()
},
@@ -2451,8 +2360,10 @@ fn folder_rows_at(
}
}
}
for e in &data.loose {
entry_row(app, ui, comp, path, fstatic, e, inner, None, loose_keys, folder_faded, acts);
if !render {
for e in &data.loose {
entry_row(app, ui, comp, path, fstatic, e, inner, None, loose_keys, folder_faded, acts);
}
}
}
@@ -2508,11 +2419,16 @@ fn entry_row(
parent_hidden: bool,
acts: &mut Actions,
) {
let appearance = crate::render_workspace::scene::decoration(app, &e.bodies);
if crate::render_workspace::active(app) && !crate::render_workspace::scene::matches_query(app, &e.label, &appearance.name) {
return;
}
app.tree.remember(&e.row_key);
let pattern_key = e.patterns.as_deref();
let patterns_open = pattern_key.is_some_and(|key| is_open(app, key, true));
let rect = row_rect(ui);
if !ui.is_rect_visible(rect) && !patterns_open && !(folder == "bodies" && app.tree.reveal.as_deref() == Some(e.key.as_str())) {
let revealed = folder == "bodies" && app.tree.reveal.as_ref().is_some_and(|b| e.row_key.strip_prefix("b:") == Some(b.as_str()));
if !ui.is_rect_visible(rect) && !patterns_open && !revealed {
ui.allocate_space(rect.size());
return;
}
@@ -2537,6 +2453,9 @@ fn entry_row(
// A cut body is faded until Paste moves it.
dim: !e.visible || parent_hidden || (folder == "bodies" && app.cut_bodies.contains(&e.key)),
color: e.color,
swatch: appearance.swatch,
secondary: &appearance.name,
count: &appearance.count,
badges,
mark,
..Default::default()
@@ -2559,10 +2478,7 @@ fn entry_row(
}
if r.double && folder == "sketches" {
if let Ok(id) = e.key.parse() {
if let Some(path) = path {
let _ = app.run("component.activate", json!({"component": comp,"occurrence":path.last(),"path":path}));
}
app.edit_sketch(id);
app.edit_sketch_in(id, path.map(|path| (comp, path)));
}
} else if r.clicked {
let shift = ui.input(|i| i.modifiers.shift);
+32
View File
@@ -402,6 +402,38 @@ mod tests {
}
}
#[test]
fn browser_find_reveals_a_placed_body_whose_row_is_off_screen() {
let mut h = Harness::new();
let component = h.app.run("component.create", json!({"name":"Part"})).unwrap();
h.app.run("solid.box", json!({"length":10,"width":10,"height":10,"body_name":"Plate"})).unwrap();
h.app.run("component.activate", json!({"component":0})).unwrap();
let first = component["occurrence"].as_u64().unwrap();
// Enough placements that the last one's row sits below the Browser's visible height.
let mut last = first;
for i in 1..=80 {
last = h.app.run("occurrence.copy", json!({"occurrence":first,"translate":[20.0 * f64::from(i),0,0]})).unwrap()["occurrence"]
.as_u64()
.unwrap();
}
h.app.run("browser.collapse_all", json!({})).unwrap();
h.frames(2);
let world_body = h.app.session.occurrence_bodies(&[last], false).unwrap()[0].clone();
// A later placement's body has its own world name; the row's label stays the local one.
assert_ne!(world_body, "Plate");
let plate_rows = || drawn_rows().into_iter().filter(|(label, ..)| label == "Plate").count();
assert_eq!(plate_rows(), 0, "the body starts off screen and collapsed");
find_in_browser(&mut h.app, face(&world_body));
// The row is off screen, so the reveal only gives it a rect to scroll to; the scroll then
// animates over several frames until the row is on screen and drawn.
let arrived = (0..240).any(|_| {
h.frames(1);
plate_rows() == 1
});
assert!(arrived, "the off-screen placed body row was never scrolled into view");
assert_eq!(h.app.session.selection, [Sel::Body { name: world_body }]);
}
#[test]
fn browser_feature_imported_source_ids_never_reveal_an_unrelated_native_feature() {
struct Source(std::path::PathBuf);
+36
View File
@@ -196,6 +196,31 @@ fn construction_rows_include_points_and_axes() {
assert!(super::entries(&h.app, 0, "construction").is_empty());
}
#[test]
fn render_browser_swatch_resolves_face_body_component_then_physical_material() {
let (mut h, component, _) = fixture();
crate::render_workspace::enter(&mut h.app, true).unwrap();
let swatch = |h: &crate::scenario::Harness| crate::render_workspace::scene::decoration(&h.app, &["Body1".into()]);
h.app.run("material.assign", json!({"bodies":["Body1"],"material":"Brass"})).unwrap();
assert_eq!(swatch(&h).name, "Brass");
h.app.run("appearance.assign", json!({"components":[component.to_string()],"appearance":"ABS - Red"})).unwrap();
assert_eq!(swatch(&h).name, "ABS - Red");
h.app.run("appearance.assign", json!({"bodies":["Body1"],"appearance":"ABS - Blue"})).unwrap();
assert_eq!(swatch(&h).name, "ABS - Blue");
let point = solidcraft_engine::geom::Vec3::new(0.0, 5.0, 5.0);
h.app.run("appearance.assign", json!({"body":"Body1","faces":[point],"appearance":"ABS - Red"})).unwrap();
let state = h.app.session.world_state();
let body = state.body("Body1").unwrap();
let face = solidcraft_engine::doc::appearance::face_index_at(body, point).unwrap();
h.app.run("select.set", json!({"items":[Sel::Face{body:"Body1".into(),index:face,point}]})).unwrap();
let resolved = swatch(&h);
assert_eq!(resolved.name, "ABS - Red");
assert_eq!(resolved.swatch, Some(egui::Color32::from_rgb(196, 40, 40)));
assert_eq!(resolved.count, "1 face");
h.app.run("select.clear", json!({})).unwrap();
assert_eq!(swatch(&h).name, "ABS - Blue");
}
fn body_names(app: &crate::SolveApp) -> Vec<String> {
app.dialog
.as_ref()
@@ -384,3 +409,14 @@ fn browser_rows_still_fold_or_select_when_move_copy_is_not_open() {
click(&mut h, "row:Bodies");
assert!(h.app.tree.collapsed.contains("c0/bodies"));
}
/// The sketch being edited is marked in the user's language, not with an English "(editing)",
/// and its default name reads as the browser shows it elsewhere.
#[test]
fn the_edited_sketch_is_marked_in_the_users_language() {
let mut h = crate::scenario::Harness::new();
h.app.run("sketch.create", json!({"plane":"XY","name":"Sketch1"})).unwrap();
let _japanese = crate::i18n::scope("ja");
let rows = super::entries(&h.app, 0, "sketches");
assert_eq!(rows.iter().map(|r| r.label.as_str()).collect::<Vec<_>>(), ["スケッチ1 (編集中)"]);
}
@@ -280,6 +280,7 @@ fn groups(t: &Tokens) -> Vec<Group> {
group("card text", &[("form_ink", t.form_ink), ("form_error", t.form_error)], &[("dialog_body", t.dialog_body)]),
group("card hints", &[("form_dim", t.form_dim)], &[("dialog_body", t.dialog_body)]),
group("card primary", &[("form_primary", t.form_primary)], &[("dialog_body", t.dialog_body)]),
group("navigation status", &[("form_primary", t.form_primary), ("warning", t.warning)], &[("dialog_body", t.dialog_body)]),
// Validation is identified by its words as well as colour. Measure both the
// ink and badge surfaces against the corresponding failure states.
group(
@@ -377,6 +378,14 @@ const SHADED: [&str; 2] = ["analysis.draft", "analysis.access"];
/// Tokens no colour vision mode needs to keep apart, and why. A new token fails
/// `every_token_is_measured_or_carries_no_meaning` until it is in a group above or here.
const NO_MEANING: &[(&str, &str)] = &[
("nav_hover", "neutral hover surface; placement and pointer feedback identify the control"),
("nav_press", "neutral pressed/open surface; interaction and menu presence identify the state"),
("nav_dim", "neutral secondary ink; the Later label identifies the unavailable option"),
("nav_field", "neutral control surface, not a semantic category"),
("nav_tip", "neutral tooltip surface, not a semantic category"),
("nav_tip_ink", "neutral tooltip text; words identify the control and value"),
("nav_tip_key_border", "neutral keycap outline; its key label carries the meaning"),
("nav_viewport", "neutral preview-stage background, not model or status colour"),
("borders.primary", "structural chrome: hierarchy uses width, pattern and placement, not hue"),
("borders.secondary", "structural chrome: hierarchy uses width, pattern and placement, not hue"),
("borders.secondary_dotted", "structural chrome: hierarchy uses width, pattern and placement, not hue"),
+47 -1
View File
@@ -359,6 +359,14 @@ pub fn radial_items(app: &SolveApp) -> Vec<Item> {
pub fn items(app: &SolveApp, target: &Target) -> Vec<Item> {
let mut v = match target {
Target::Viewport => viewport_items(app),
Target::Body { name } if crate::render_workspace::active(app) => vec![
cmd(app, "select.set", "Select").with(json!({"items":[Sel::Body {name:name.clone()}]})),
cmd(app, "select.same_look", "Select Same Look").with(json!({"body":name})),
Item::sep(),
act("ui.isolate", "Isolate", "body").with(json!({"bodies":[name]})),
act(if app.session.visibility.hidden_bodies.contains(name) { "ui.show" } else { "ui.hide" }, "Show/Hide", "eye")
.with(json!({"bodies":[name]})),
],
Target::Body { name } => body_items(app, std::slice::from_ref(name), true),
Target::Sketch { id } => sketch_items(app, *id),
Target::Feature { id } => feature_items(app, *id),
@@ -398,7 +406,31 @@ pub fn items(app: &SolveApp, target: &Target) -> Vec<Item> {
.collect(),
Target::NamedView { name } => crate::browser::view_items(app, name),
};
v.extend(crate::browser::folded_folder_items(app, target));
if !crate::render_workspace::active(app) {
v.extend(crate::browser::folded_folder_items(app, target));
}
if crate::render_workspace::active(app) {
let (bodies, selection) = match target {
Target::Component { id } => {
let bodies = component_bodies(app, *id);
let selection: Vec<Sel> = bodies.iter().map(|name| Sel::Body { name: name.clone() }).collect();
(bodies, selection)
}
Target::Occurrence { path } => {
(app.session.occurrence_bodies(path, true).unwrap_or_default(), vec![Sel::Occurrence { path: path.clone() }])
}
_ => (Vec::new(), Vec::new()),
};
if let Some(body) = bodies.first() {
v.insert(0, cmd(app, "select.set", "Select").with(json!({"items":selection})));
v.insert(
1,
cmd(app, "select.same_look", "Select Same Look")
.with(json!({"body":body}))
.on(crate::render_workspace::scene::same_look(app, &bodies)),
);
}
}
// Several items of the folder selected: they can be grouped.
if let Some(p) = crate::browser::selection_group(app, target) {
v.push(Item::sep());
@@ -408,6 +440,14 @@ pub fn items(app: &SolveApp, target: &Target) -> Vec<Item> {
if item.id != "ui.appearance" {
continue;
}
// A selected browser body keeps the selection for the editor and its quick choices.
// A row outside the selection still targets only the body that was right-clicked.
if let Target::Body { name } = target {
let bodies = sel_bodies(app);
if bodies.contains(name) {
item.params = Some(json!({"bodies": bodies}));
}
}
let original = item.clone();
let params = item.params.clone().unwrap_or_else(|| {
let faces: Vec<_> = app
@@ -1082,6 +1122,12 @@ fn sketch_entity_items(app: &SolveApp) -> Vec<Item> {
v.push(act("ui.paste", "Paste", "paste").key("Ctrl+V").on(app.session.sketch_clipboard.is_some()));
v.push(act("ui.delete", "Delete", "delete").key("Del"));
v.push(cmd(app, "sketch.dimension", "Sketch Dimension").with(json!({ "entities": ents })).on(ents.len() <= 2));
// One arc alone: Sketch Dimension gives its radius, this its length along the curve (#6039).
if let [arc] = ents.as_slice()
&& ss.sketch.curve_index(arc).and_then(|i| ss.sketch.curves.get(i)).is_some_and(|c| matches!(c.kind, CurveKind::Arc { .. }))
{
v.push(cmd(app, "sketch.dimension", "Arc Length Dimension").with(json!({ "entities": [arc], "type": "arc_length" })));
}
let mut c = Vec::new();
let n = ents.len();
let (l, r, p) = (lines.len(), rounds.len(), points.len());
+23
View File
@@ -26,6 +26,8 @@ use crate::viewport::Hit;
#[path = "dialogs_dense.rs"]
mod dense;
#[cfg(test)]
pub(crate) use dense::primitive_label;
const SELECT_ONLY: &[Scope] = &[Scope::Selection, Scope::FeaturePreview];
const SELECT_MANIP: &[Scope] = &[Scope::Selection, Scope::Manipulator, Scope::FeaturePreview];
@@ -6382,6 +6384,27 @@ mod awaiting_selection_tests {
assert_eq!(d.error.as_deref(), Some("select a plane first"));
assert!(crate::scenario::handle_at("dialog:create_issue").is_none(), "no Create Issue for a missing pick");
}
/// A missing-pick hint reads in the user's language: the dialogs return it as English text,
/// and the dialog translates it as it shows it.
#[test]
fn missing_pick_hints_read_in_the_users_language() {
for (command, english) in [
("solid.move", "select bodies first"),
("sheet.flange", "select a profile, edges or sketch lines first"),
("plastic.lip", "select the rim face first"),
] {
let mut h = crate::scenario::Harness::new();
h.step(&serde_json::json!({"start":command})).unwrap();
h.frames(2);
h.step(&serde_json::json!({"key":"Enter"})).unwrap();
h.frames(2);
assert_eq!(h.app.dialog.as_ref().and_then(|d| d.error.as_deref()), Some(english), "{command}");
let _japanese = crate::i18n::scope("ja");
let shown = super::shown_error(english);
assert!(shown != english && !shown.is_ascii(), "{command} shows {shown:?}");
}
}
}
#[cfg(test)]
+103 -6
View File
@@ -255,6 +255,42 @@ form_case!(shell, "solid.shell", ["Thickness", "Direction"]);
form_case!(draft, "solid.draft", ["Angle"]);
form_case!(mirror, "solid.mirror", ["Operation"]);
/// The Motion Study's and Motion Trace's hints read in the user's language: the dialogs drew them
/// as they got them, in English.
#[test]
fn motion_dialog_hints_are_translated() {
fn texts(shape: &egui::Shape, out: &mut Vec<String>) {
match shape {
egui::Shape::Text(text) => out.push(text.galley.job.text.clone()),
egui::Shape::Vec(shapes) => shapes.iter().for_each(|shape| texts(shape, out)),
_ => {}
}
}
let mut h = fixture();
h.app.preferences.language = "ja".into();
let _japanese = crate::i18n::scope("ja");
for (command, english) in [("motion.study", "add a key for a joint first"), ("motion.trace", "select a point on a component")] {
let mut d = Dialog::for_command(&h.app, command).unwrap();
let mut painted = Vec::new();
for _ in 0..2 {
let mut out = h.ctx.run_ui(
egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, vec2(320.0, 1600.0))), ..Default::default() },
|ui| {
ui.set_width(264.0);
ui_kit::scope(ui, |ui| {
rows(&mut h.app, &h.ctx, &mut d, ui);
});
},
);
out.textures_delta.clear();
painted.clear();
out.shapes.iter().for_each(|shape| texts(&shape.shape, &mut painted));
}
assert!(!painted.iter().any(|p| p == english), "{command} paints {english:?} in Japanese");
assert!(painted.iter().any(|p| p == crate::i18n::tr_label(english)), "{command} paints {painted:?}");
}
}
fn mirror_preselection() -> (Harness, Vec<Sel>) {
let mut h = Harness::new();
h.app.run("sketch.create", json!({"plane":"XY","name":"Sketch1"})).unwrap();
@@ -366,12 +402,12 @@ form_case!(pipe, "solid.pipe", ["Diameter", "Wall", "Operation"]);
form_case!(stock, "solid.bounding_solid", ["Margin"]);
form_case!(frame_member, "frame.member", ["All Lines", "Anchor", "Angle", "Mirror", "Name"]);
form_case!(thread, "solid.thread", ["Profile", "Size", "Pitch", "Designation"]);
form_case!(primitive_box, "solid.box", ["length", "width", "height", "Operation"]);
form_case!(cylinder, "solid.cylinder", ["diameter", "height", "Operation"]);
form_case!(sphere, "solid.sphere", ["diameter", "Operation"]);
form_case!(torus, "solid.torus", ["major", "minor", "Operation"]);
form_case!(cone, "solid.cone", ["diameter", "top_diameter", "height", "Operation"]);
form_case!(coil, "solid.coil", ["diameter", "revolutions", "pitch", "section_size", "Operation"]);
form_case!(primitive_box, "solid.box", ["ui.length", "ui.width", "ui.height", "Operation"]);
form_case!(cylinder, "solid.cylinder", ["ui.diameter", "ui.height", "Operation"]);
form_case!(sphere, "solid.sphere", ["ui.diameter", "Operation"]);
form_case!(torus, "solid.torus", ["ui.major_radius", "ui.minor_radius", "Operation"]);
form_case!(cone, "solid.cone", ["ui.diameter", "ui.top_diameter", "ui.height", "Operation"]);
form_case!(coil, "solid.coil", ["ui.diameter", "ui.revolutions", "ui.pitch", "ui.section_size", "Operation"]);
form_case!(combine, "solid.combine", ["Operation"]);
form_case!(surface_extrude, "surface.extrude", ["Distance", "Direction"]);
form_case!(surface_revolve, "surface.revolve", ["Angle", "Direction"]);
@@ -421,6 +457,47 @@ fn registry_dialog_inventory_has_no_unclassified_feature_forms() {
}
}
/// Texts these dialogs draw themselves read in the user's language: the joints' Play button, the
/// Motion Study's Loop, the Stitch tolerance hint, the Flange type and the Emboss note.
#[test]
fn hand_drawn_dialog_texts_are_translated() {
fn texts(shape: &egui::Shape, out: &mut Vec<String>) {
match shape {
egui::Shape::Text(text) => out.push(text.galley.job.text.clone()),
egui::Shape::Vec(shapes) => shapes.iter().for_each(|shape| texts(shape, out)),
_ => {}
}
}
let mut h = fixture();
h.app.preferences.language = "ja".into();
let _japanese = crate::i18n::scope("ja");
for (command, english) in [
("joint.gear", "▶ Play"),
("motion.study", "Loop"),
("surface.stitch", "tight"),
("sheet.flange", "Base"),
("solid.emboss", "Orthogonal line profiles tangent to one supported cylinder wrap automatically. Pick a wall to choose a target."),
] {
let mut d = Dialog::for_command(&h.app, command).unwrap();
let mut painted = Vec::new();
for _ in 0..2 {
let mut out = h.ctx.run_ui(
egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, vec2(320.0, 1600.0))), ..Default::default() },
|ui| {
ui.set_width(264.0);
ui_kit::scope(ui, |ui| {
rows(&mut h.app, &h.ctx, &mut d, ui);
});
},
);
out.textures_delta.clear();
painted.clear();
out.shapes.iter().for_each(|shape| texts(&shape.shape, &mut painted));
}
assert!(!painted.iter().any(|p| p == english), "{command} paints {english:?} in Japanese: {painted:?}");
}
}
#[test]
fn revolve_layout_fixture_builds_a_valid_solid() {
let mut h = fixture();
@@ -934,3 +1011,23 @@ fn extrude_builds_the_one_region_clicked_where_the_face_outline_cuts_a_profile()
assert!(((volume - before) - area * 5.0).abs() < 5e-3 * area * 5.0, "x = {x}: {volume} - {before} vs {}", area * 5.0);
}
}
/// Every selection field of every command's dialog is labelled with a message the catalogs carry,
/// so it reads in the user's language ("First edge", "Second point" read English everywhere when
/// they were missing).
#[test]
fn every_selection_field_label_is_translated() {
let h = fixture();
let _japanese = crate::i18n::scope("ja");
let mut missing = std::collections::BTreeSet::new();
for spec in solidcraft_engine::command_specs() {
let Some(d) = Dialog::for_command(&h.app, spec.id) else { continue };
for input in &d.inputs {
let label = input.label.trim();
if label.chars().any(|c| c.is_ascii_alphabetic()) && crate::i18n::tr_label(label) == label {
missing.insert(format!("{}: {label}", spec.id));
}
}
}
assert!(missing.is_empty(), "selection fields without a message: {missing:#?}");
}
+15 -4
View File
@@ -59,6 +59,16 @@ const TYPE_LABELS: [&str; 13] = [
"Point on line",
"Line on plane",
];
/// A joint type's label, as the Type box lists it ("Pin-slot", "Point on plane").
pub(crate) fn kind_label(kind: JointKind) -> &'static str {
TYPES.iter().position(|t| JointKind::parse(t) == Some(kind)).and_then(|i| TYPE_LABELS.get(i)).copied().unwrap_or("")
}
/// A joint as the joint lists name it: its name, and its type in the user's language.
pub(crate) fn joint_choice(name: &str, kind: JointKind) -> String {
format!("{name} ({})", crate::i18n::tr_label(kind_label(kind)))
}
/// What a joint origin input accepts (snaps on faces, edges and vertices).
pub const SNAPS: u16 = FACES | EDGES | VERTICES;
/// Commands whose effect is where occurrences sit (previewed on the placed model).
@@ -580,8 +590,10 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Asm, inputs: &mut [Se
let kind = f.joint_kind();
if kind != JointKind::Rigid {
form_row(ui, "Animate", |ui| {
let label = if f.animate { "■ Stop" } else { "▶ Play" };
if crate::ui_kit::button(ui, label, crate::ui_kit::Button::Normal).on_hover_text("Play the joint's motion in the view").clicked()
let label = crate::i18n::tr(if f.animate { "ui.joint_stop" } else { "ui.joint_play" });
if crate::ui_kit::button(ui, label, crate::ui_kit::Button::Normal)
.on_hover_text(crate::i18n::tr_label("Play the joint's motion in the view"))
.clicked()
{
f.animate = !f.animate;
}
@@ -640,8 +652,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Asm, inputs: &mut [Se
}
return false;
}
let labels: Vec<String> =
list.iter().filter_map(|i| s.doc.assembly.joints.get(*i)).map(|j| format!("{} ({:?})", j.name, j.kind)).collect();
let labels: Vec<String> = list.iter().filter_map(|i| s.doc.assembly.joints.get(*i)).map(|j| joint_choice(&j.name, j.kind)).collect();
let refs: Vec<&str> = labels.iter().map(String::as_str).collect();
// On a rigid joint the box shows none of the joints that move until one is chosen.
let mut pos = list.iter().position(|i| i == joint).unwrap_or(list.len());
+2 -2
View File
@@ -46,7 +46,7 @@ pub struct CamForm {
/// Joints of a kind: (id, label).
fn joints_of(s: &Session, kinds: &[JointKind]) -> Vec<(u64, String)> {
s.doc.assembly.joints.iter().filter(|j| kinds.contains(&j.kind)).map(|j| (j.id, format!("{} ({:?})", j.name, j.kind))).collect()
s.doc.assembly.joints.iter().filter(|j| kinds.contains(&j.kind)).map(|j| (j.id, crate::dialogs_assembly::joint_choice(&j.name, j.kind))).collect()
}
pub fn start(app: &SolveApp) -> (Asm, Vec<SelInput>) {
@@ -133,7 +133,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, f: &mut CamForm, inputs: &[Se
}
crate::ui_kit::options(ui, "cam_options", &mut [("Other side", &mut f.flip)]);
form_row(ui, "Animate", |ui| {
let label = if f.animate { "■ Stop" } else { "▶ Play" };
let label = crate::i18n::tr(if f.animate { "ui.joint_stop" } else { "ui.joint_play" });
let r = crate::ui_kit::button(ui, label, crate::ui_kit::Button::Normal)
.on_hover_text(crate::i18n::tr_label("Play the joint's motion in the view"));
crate::scenario::publish_handle("dialog:Animate", r.rect.center());
+2 -2
View File
@@ -46,7 +46,7 @@ fn joints_that(s: &Session, turn: bool) -> Vec<(u64, String)> {
.joints
.iter()
.filter(|j| (0..j.kind.dofs().len()).any(|i| j.kind.is_angle(i) == turn))
.map(|j| (j.id, format!("{} ({:?})", j.name, j.kind)))
.map(|j| (j.id, crate::dialogs_assembly::joint_choice(&j.name, j.kind)))
.collect()
}
@@ -206,7 +206,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, f: &mut CouplingForm, inputs:
ui.label(RichText::new(shown.unwrap_or_else(|| "-".into())).color(t.text_dim));
});
form_row(ui, "Animate", |ui| {
let label = if f.animate { "■ Stop" } else { "▶ Play" };
let label = crate::i18n::tr(if f.animate { "ui.joint_stop" } else { "ui.joint_play" });
let r = crate::ui_kit::button(ui, label, crate::ui_kit::Button::Normal)
.on_hover_text(crate::i18n::tr_label("Play the joint's motion in the view"));
crate::scenario::publish_handle("dialog:Animate", r.rect.center());
+22 -5
View File
@@ -575,6 +575,26 @@ fn extra_options(ui: &mut egui::Ui, id: &str, extra: &mut serde_json::Map<String
}
}
/// The message a primitive's size field is labelled with, by its parameter name: "Section size",
/// not `section_size`.
pub(crate) fn primitive_label(key: &str) -> &str {
match key {
"length" => "ui.length",
"width" => "ui.width",
"height" => "ui.height",
"diameter" => "ui.diameter",
"radius" => "ui.radius",
"top_diameter" => "ui.top_diameter",
"top_radius" => "ui.top_radius",
"major" => "ui.major_radius",
"minor" => "ui.minor_radius",
"revolutions" => "ui.revolutions",
"pitch" => "ui.pitch",
"section_size" => "ui.section_size",
_ => key,
}
}
/// The coil's section, where the section sits on the diameter, the way it turns and where it
/// starts (#3862). A default stays out of the parameters, so OK on an unchanged edit keeps the coil.
fn coil_rows(ui: &mut egui::Ui, extra: &mut serde_json::Map<String, Value>) -> bool {
@@ -712,10 +732,7 @@ fn additional_rows(app: &mut SolveApp, d: &mut Dialog, ui: &mut egui::Ui) -> boo
ui_kit::segmented(ui, &mut i, &["Emboss", "Deboss"], Default::default());
*deboss = i == 1;
});
ui.add(
egui::Label::new("Orthogonal line profiles tangent to one supported cylinder wrap automatically. Pick a wall to choose a target.")
.wrap(),
);
ui.add(egui::Label::new(crate::i18n::tr("ui.emboss_wrap_note")).wrap());
}
Kind::Align { flip } => {
// Where on the picked face or edge to snap: as picked (a face turns to meet
@@ -799,7 +816,7 @@ fn additional_rows(app: &mut SolveApp, d: &mut Dialog, ui: &mut egui::Ui) -> boo
if from_sketch && (*k == "diameter" || *k == "section_size") {
continue;
}
enter |= expr_row(ui, k, v);
enter |= expr_row(ui, primitive_label(k), v);
}
if *cmd == "solid.coil" {
enter |= coil_rows(ui, &mut d.extra);
+6 -6
View File
@@ -456,7 +456,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
let list = app.session.execute("contact.list", &json!({})).unwrap_or(Value::Null);
form_row(ui, "Contact", |ui| {
let mut on = list.get("enabled").and_then(Value::as_bool).unwrap_or(false);
if crate::ui_kit::checkbox(ui, "enabled", &mut on).changed() {
if crate::ui_kit::checkbox(ui, crate::i18n::tr_label("Enabled"), &mut on).changed() {
let _ = app.run("contact.enable_sets", json!({ "enabled": on }));
}
});
@@ -490,9 +490,9 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
let hits = c.get("collisions").and_then(Value::as_array).cloned().unwrap_or_default();
crate::ui_kit::section(ui, "contact_collisions", "Collisions", true, |ui| {
if let Some(e) = c.get("error").and_then(Value::as_str) {
ui.label(RichText::new(e).color(t.error));
ui.label(RichText::new(crate::i18n::tr_label(e)).color(t.error));
} else if hits.is_empty() {
ui.label(RichText::new("none").color(t.text_dim));
ui.label(RichText::new(crate::i18n::tr_label("none")).color(t.text_dim));
} else {
ui.vertical(|ui| {
for h in hits {
@@ -530,7 +530,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
}
if let Some(e) = error {
ui.vertical(|ui| {
ui.label(RichText::new(e.as_str()).color(t.error));
ui.label(RichText::new(crate::i18n::tr_label(e)).color(t.error));
});
}
}
@@ -599,7 +599,7 @@ fn motion_study_rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs:
*playing = false;
}
ui.add_space(t.space_6);
crate::ui_kit::checkbox(ui, "Loop", looping);
crate::ui_kit::checkbox(ui, crate::i18n::tr_label("Loop"), looping);
let names: Vec<String> = SPEEDS.iter().map(|x| format!("{x}×")).collect();
let refs: Vec<&str> = names.iter().map(String::as_str).collect();
ui.allocate_ui(vec2(t.form_label_width, t.control_height), |ui| combo(ui, "ms_speed", &refs, speed));
@@ -737,7 +737,7 @@ fn motion_study_rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs:
}
if let Some(e) = error {
ui.vertical(|ui| {
ui.label(RichText::new(e.as_str()).color(t.text_dim));
ui.label(RichText::new(crate::i18n::tr_label(e)).color(t.text_dim));
});
}
enter
+2 -2
View File
@@ -317,7 +317,7 @@ fn collision_rows(
}
Some(Err(e)) => {
ui.vertical(|ui| {
ui.add(egui::Label::new(RichText::new(e.as_str()).color(t.error)).wrap());
ui.add(egui::Label::new(RichText::new(crate::i18n::tr_label(e)).color(t.error)).wrap());
});
}
None => {}
@@ -385,7 +385,7 @@ fn plot_rows(
});
}
Some(Err(e)) => {
ui.add(egui::Label::new(RichText::new(e.as_str()).color(t.text_dim)).wrap());
ui.add(egui::Label::new(RichText::new(crate::i18n::tr_label(e)).color(t.text_dim)).wrap());
}
None => {}
});
+1 -1
View File
@@ -170,7 +170,7 @@ pub fn open(app: &mut SolveApp, component: u64) {
pub fn rows(app: &SolveApp, ui: &mut egui::Ui, k: &mut Resize) -> bool {
row(ui, "Type", |ui| {
ui.add(egui::Label::new(format!("{} ({})", k.family.name, k.family.standard)).wrap());
ui.add(egui::Label::new(format!("{} ({})", crate::dialogs_parts::family_name(&k.family), k.family.standard)).wrap());
});
let sizes: Vec<&str> = k.family.sizes.iter().map(|s| s.0.as_str()).collect();
choice_row(ui, "Size", "part_resize_size", &mut k.size, &sizes);
+69 -3
View File
@@ -50,6 +50,16 @@ pub fn families(v: &Value) -> Vec<Family> {
.collect()
}
/// A family's name in the user's language, by its id in the library: the library's own (English)
/// name for a family the catalogs don't know.
pub(crate) fn family_name(f: &Family) -> String {
let id = format!("parts.family.{}", f.id);
match crate::i18n::tr(&id) {
shown if shown == id => f.name.clone(),
shown => shown.to_string(),
}
}
#[derive(Clone, Debug)]
pub struct Pt {
pub family: usize,
@@ -129,7 +139,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Pt, inputs: &[SelInpu
return false;
}
let names: Vec<String> =
lib.iter().map(|f| if f.standard.is_empty() { f.name.clone() } else { format!("{} ({})", f.name, f.standard) }).collect();
lib.iter().map(|f| if f.standard.is_empty() { family_name(f) } else { format!("{} ({})", family_name(f), f.standard) }).collect();
let refs: Vec<&str> = names.iter().map(String::as_str).collect();
let before = k.family;
choice_row(ui, "Type", "pt_family", &mut k.family, &refs);
@@ -150,7 +160,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Pt, inputs: &[SelInpu
k.length = i.checked_sub(1);
});
}
text_row(ui, "Name", &mut k.name, "automatic");
text_row(ui, "Name", &mut k.name, crate::i18n::tr("parts.automatic_name"));
// The part, and its table values.
let key = (k.family, k.size, k.length);
let tex_id = egui::Id::new("sc_part_picture");
@@ -179,7 +189,8 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Pt, inputs: &[SelInpu
&& let Some(o) = row.as_object()
{
for (key, v) in o.iter().filter(|(key, _)| key.as_str() != "size") {
form_row(ui, &key.replace('_', " "), |ui| {
let label = dimension_label(key).map_or_else(|| key.replace('_', " "), str::to_string);
form_row(ui, &label, |ui| {
crate::ui_kit::text(
ui,
&v.as_f64().map(|x| crate::prefs::show_mm(app, x, 1)).unwrap_or_else(|| v.to_string()),
@@ -212,6 +223,27 @@ pub fn commands(app: &SolveApp, k: &Pt, inputs: &[SelInput]) -> Result<Vec<(Stri
Ok(vec![(id.into(), p)])
}
/// The message a size's dimension is labelled with, by its key in the library: "Head height",
/// not `head_height`. A key the library adds later shows as it is until it has one here.
fn dimension_label(key: &str) -> Option<&'static str> {
Some(match key {
"across_flats" => "parts.dimension.across_flats",
"bore" => "parts.dimension.bore",
"d" => "parts.dimension.d",
"head_diameter" => "parts.dimension.head_diameter",
"head_height" => "parts.dimension.head_height",
"height" => "parts.dimension.height",
"inner" => "parts.dimension.inner",
"outer" => "parts.dimension.outer",
"pitch" => "parts.dimension.pitch",
"socket" => "parts.dimension.socket",
"socket_depth" => "parts.dimension.socket_depth",
"thickness" => "parts.dimension.thickness",
"width" => "parts.dimension.width",
_ => return None,
})
}
#[cfg(test)]
mod tests {
use super::*;
@@ -234,6 +266,20 @@ mod tests {
assert!(l[1].lengths.is_none());
}
/// The library's families are named in the user's language, and a family the catalogs
/// don't know keeps the library's name.
#[test]
fn family_names_follow_the_language() {
let l = families(&solidcraft_engine::Session::default().execute("parts.library", &json!({})).unwrap());
assert!(l.len() >= 7, "{}", l.len());
let _german = crate::i18n::scope("de");
for f in &l {
assert_ne!(family_name(f), f.name, "{}", f.id);
}
let unknown = Family { id: "spring".into(), name: "Spring".into(), standard: String::new(), sizes: vec![], lengths: None };
assert_eq!(family_name(&unknown), "Spring");
}
/// A hole pick seats the part (`at`); without one it goes to the origin along Z.
#[test]
fn insert_params_for_picks() {
@@ -249,4 +295,24 @@ mod tests {
assert!(p.get("length").is_none());
assert!(insert_params(&[], &k, None).is_err());
}
/// Every dimension the library gives for a size is labelled in words, in each family.
#[test]
fn every_library_dimension_has_a_label_in_words() {
let mut s = solidcraft_engine::Session::default();
let l = families(&s.execute("parts.library", &json!({})).unwrap());
assert!(l.len() >= 7, "{}", l.len());
for f in &l {
for (size, row) in &f.sizes {
for key in row.as_object().into_iter().flat_map(|o| o.keys()).filter(|k| k.as_str() != "size") {
let label = dimension_label(key).map(crate::i18n::tr);
assert!(
label.is_some_and(|l| l.starts_with(char::is_uppercase) && !l.contains('_') && !l.starts_with("parts.")),
"{} {size}: {key} is labelled {label:?}",
f.name
);
}
}
}
}
}
+3 -2
View File
@@ -23,7 +23,8 @@ const PERFORATION_LABELS: [&str; 2] = ["ui.perforate_staggered", "ui.perforate_s
const FOLD_POSITIONS: [&str; 4] = ["centerline", "start", "end", "mould"];
const FOLD_POSITION_LABELS: [&str; 4] = ["Centerline", "Start of Bend", "End of Bend", "Outside Mould Line"];
const FLANGE_TYPES: [&str; 3] = ["Base", "Edge", "Contour"];
/// The flange types' messages, by the type's index (Base, Edge, Contour).
const FLANGE_TYPES: [&str; 3] = ["sheet.flange_type_base", "sheet.flange_type_edge", "sheet.flange_type_contour"];
const POSITIONS: [&str; 5] = ["inside", "outside", "middle", "material_outside", "tangent"];
const POSITION_LABELS: [&str; 5] = ["Inside", "Outside", "Middle", "Material Outside", "Tangent to Edge"];
/// Where an edge flange's height is measured from (`height_from`; the first is the default).
@@ -242,7 +243,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Sm, inputs: &mut [Sel
Sm::Flange { ty, height, angle, radius, position, height_from, flip, distance, reverse, rule, own, relief, relief_size, then } => {
*ty = flange_type(inputs);
form_row(ui, "Type", |ui| {
ui.label(FLANGE_TYPES.get(*ty).copied().unwrap_or(""));
ui.label(FLANGE_TYPES.get(*ty).copied().map(crate::i18n::tr).unwrap_or(""));
});
match *ty {
1 => {
+20
View File
@@ -1322,3 +1322,23 @@ fn perforate_edit_restores_dimensions_pattern_and_target() {
assert_eq!(params[key], value, "{key} is restored");
}
}
#[test]
fn flat_pattern_navigation_slots_hide_orbit_controls_and_keep_fit_home() {
let ctx = crate::fonts::test_context();
let mut app = flat_app("fusion", crate::shell::LayoutMode::Floating);
app.preferences.navigation_bar = serde_json::from_value(json!({
"slots":["orbit","spin","look_at","projection","visual_style","pan","zoom","fit","home","display"]
}))
.unwrap();
let mut time = 0.0;
crate::scenario::clear_handles();
frame(&mut app, &ctx, &mut time, egui::Modifiers::NONE, vec![]);
assert_eq!(crate::navigation_bar::canvas_caps(&app), crate::navigation::NavCaps { orbit: false, pick: false });
for slot in ["orbit", "spin", "look_at", "projection", "visual_style"] {
assert!(crate::scenario::handle_at(&format!("nav:slot:{slot}")).is_none(), "{slot}");
}
for slot in ["pan", "zoom", "fit", "home", "display"] {
assert!(crate::scenario::handle_at(&format!("nav:slot:{slot}")).is_some(), "{slot}");
}
}
+1 -1
View File
@@ -225,7 +225,7 @@ pub fn rows(ui: &mut egui::Ui, k: &mut Surf) -> bool {
let mut enter = false;
match k {
Surf::Stitch { tolerance } => {
enter |= hint_row(ui, "Tolerance", tolerance, "tight");
enter |= hint_row(ui, "Tolerance", tolerance, crate::i18n::tr("ui.stitch_tolerance_hint"));
}
Surf::Thicken { thickness, symmetric, operation } => {
enter |= expr_row(ui, "Thickness", thickness);
+1 -1
View File
@@ -196,7 +196,7 @@ pub fn rows(app: &mut crate::SolveApp, ui: &mut egui::Ui, f: &mut TraceForm, inp
Some(why) => (why, t.warning),
None => (crate::i18n::format("trace.points", &[("count", &v["samples"].to_string())]), t.text_dim),
},
Err(e) => (e.clone(), t.text_dim),
Err(e) => (crate::i18n::tr_label(e).to_string(), t.text_dim),
};
form_row(ui, "", |ui| {
ui.add(egui::Label::new(RichText::new(text).color(colour)).wrap());
+3
View File
@@ -27,6 +27,7 @@ pub struct DocSlot {
pre_sketch_marker: Option<Option<usize>>,
pub(crate) pending_feature_edit: Option<crate::feature_edit::PendingFeatureEdit>,
pre_sketch_cam: Option<crate::PreSketchView>,
pre_sketch_component: Option<crate::PreSketchComponent>,
view: DocView,
occurrence_move: Option<crate::browser::OccMove>,
agent_chat: crate::agent_chat::AgentChat,
@@ -55,6 +56,7 @@ impl DocSlot {
pre_sketch_marker: None,
pending_feature_edit: None,
pre_sketch_cam: None,
pre_sketch_component: None,
view: DocView::default(),
occurrence_move: None,
agent_chat: Default::default(),
@@ -148,6 +150,7 @@ fn swap_in(app: &mut SolveApp, mut slot: DocSlot) -> DocSlot {
pre_sketch_marker: std::mem::replace(&mut app.pre_sketch_marker, slot.pre_sketch_marker),
pending_feature_edit: std::mem::replace(&mut app.pending_feature_edit, slot.pending_feature_edit),
pre_sketch_cam: std::mem::replace(&mut app.pre_sketch_cam, slot.pre_sketch_cam),
pre_sketch_component: std::mem::replace(&mut app.pre_sketch_component, slot.pre_sketch_component),
view: take_view(app),
occurrence_move: std::mem::replace(&mut app.tree.occurrence_move, slot.occurrence_move),
agent_chat: slot.agent_chat,
+1 -1
View File
@@ -279,7 +279,7 @@ fn update_links_and_open_linked_design_ask_before_a_network_location() {
let comp = h.app.run("component.insert_design", json!({"path": part})).unwrap()["component"].as_u64().unwrap();
h.app.run("file.save", json!({"path": case})).unwrap();
let feature = h.app.session.doc.links[&comp].feature;
h.app.session.doc_mut().links.insert(comp, solidcraft_engine::doc::DesignLink { path: crafted.into(), feature });
h.app.session.doc_mut().links.insert(comp, solidcraft_engine::doc::DesignLink { path: crafted.into(), feature, ..Default::default() });
save_part(8.0);
let until_idle = |h: &mut crate::scenario::Harness| {
let began = std::time::Instant::now();
+31
View File
@@ -473,4 +473,35 @@ mod tests {
let n = doc.canvas_plane(&vals, canvas).unwrap().normal();
assert!(n.z.abs() > 0.99, "the canvas lies on {n:?}, not on XY");
}
/// A canvas and a decal clicked onto a face of a design with many curved faces land on it.
/// The click sent only the point, and the engine's search of every face of every body for it
/// gave up ("face capture work limit exceeded"), as on an imported trophy of nine bodies.
#[test]
fn a_canvas_and_a_decal_clicked_onto_a_face_of_a_large_design_land_on_it() {
let mut h = crate::scenario::Harness::new();
h.app.run("solid.box", json!({"length": 200, "width": 120, "height": 40, "corner": [20, 20, 0]})).unwrap();
for i in 0..8 {
let center = [60 + 45 * (i % 4), 50 + 60 * (i / 4), 60];
h.app.run("solid.torus", json!({"major": 30, "minor": 8, "center": center, "operation": "new_body"})).unwrap();
}
for command in ["canvas.insert", "canvas.decal"] {
for step in [
json!({"make_image": "pic.png"}),
json!({"choose_file": "pic.png"}),
json!({"call": "ui.view", "params": {"view": "iso"}}),
json!({"start": command}),
json!({"click": {"world": [30, 30, 40]}}),
] {
h.step(&step).unwrap();
}
}
let doc = &h.app.session.doc;
assert_eq!(doc.canvases.len(), 2, "both images are placed");
let (vals, _) = doc.param_values();
for canvas in &doc.canvases {
let plane = doc.canvas_plane(&vals, canvas).unwrap();
assert!(plane.normal().z.abs() > 0.99 && (plane.origin.z - 40.0).abs() < 1e-6, "{} lies on {plane:?}", canvas.name);
}
}
}

Some files were not shown because too many files have changed in this diff Show More