Compare commits

..

83 Commits

Author SHA1 Message Date
selune 0cbf328bab chore: preserve reviewed X4-exact-nano source proposal and provenance 2026-10-31 04:37:43 +01:00
selune 3559964792 archive: conditional X3 SPLINE acceptance preserving rmorgans prerequisites (unrun) 2026-10-31 03:20:37 +01:00
selune dfb0b3e113 archive: preserve reviewed eleven-path X1 source reconciliation (unresolved lock, unrun) 2026-10-31 01:13:00 +01:00
selune cd39f96d33 archive: preserve reviewed X1 two-file reconciliation on frozen main (unrun source) 2026-10-31 00:59:27 +01:00
selune 67cbfe941e wip(drawings): preserve explicit PDF widths following the owner contract 2026-10-31 00:06:11 +01:00
selune 45286e0489 wip(drawings): preserve F0 checked font-plan sources and original acceptance 2026-10-30 23:33:09 +01:00
selune 5f127aceb0 wip(drawings): preserve additive B1 width and many-page reference source 2026-10-30 22:14:51 +01:00
selune e717739735 wip(drawings): preserve B1 text-plan scaffold and 13 original unrun cases 2026-10-30 20:44:35 +01:00
selune 28d90fae50 fix(drawings): preserve reviewed caller-local circle compatibility proposal 2026-10-30 15:06:40 +01:00
selune 7b18fd5c0f Preserve P2 B1 adaptation analysis and unit-neutral arc diagnostic 2026-10-30 10:30:14 +01:00
selune 992466e76a Preserve unintegrated W10 same-units half-turn converter and PDF reproducer proposals 2026-10-30 10:12:41 +01:00
selune c46fd3acd4 Preserve W21 NoPictures parity and repeatability source proposal 2026-10-30 08:30:35 +01:00
lillith 7d66a4d0ab Clarify Drawings preservation manifest and published index hash
Source preservation only. The manifest now records the actual published index README rather than the initial selection note, and states its pre-Git-normalization hash scope. Original product proposals are unchanged. The canonical index links all branch checkpoints; validation and owner handoffs remain pending.
2026-10-29 11:00:46 +01:00
lillith 0b3bc6e968 Preserve remaining Drawings original source proposals and canonical code index
Canonical preservation of W10, W21, X4 and supporting W38 source proposals. Sources remain deliberately unregistered and unexecuted, with real bases and alternatives documented in proposals/drawings/README.md. Existing contributor claims and PRs remain authoritative; this is not a merge-ready integration candidate.
2026-10-29 10:57:57 +01:00
lillith d8e7a8690a fix(dxf): keep counter and copy tests compatible with strict Clippy
Use fresh local mutable counter values instead of mutable references to
constants. Enumerate the ten original copied shapes after asserting their
independent fixture count. Preserve all production code, numeric expected
values, refusals and the other tests. No lint suppression or ignored tests.

The prior 6b39ee36 attempt stopped at test-target Clippy, before native
test builds/runs and wasm. Both test-only hunks were independently reviewed;
normal formatting passed without changing bytes. New results are pending.
2026-10-29 03:17:21 +01:00
lillith 6b39ee3686 fix(dxf): resolve strict Clippy findings without weakening checks
Remove an unused private Interval helper and collapse the copied-vertex
guard to an equivalent let-chain with identical evaluation order and error.
Preserve all 28 geometry and 10 bounds tests, limits and assertions.

The prior a7f3c78b development attempt stopped at Clippy; IO/engine tests
and wasm were not reached. Both corrective hunks were source-reviewed,
and normal formatting passed. Tests for this new source remain unrun.
2026-10-29 02:59:05 +01:00
lillith a7f3c78b07 feat(dxf): add bounded bulged paths and layered text import (WIP #5319 #5320)
Add the reviewed minimal X1 bulged-path producer, conservative bounds,
ordered layered bulge reader, ELLIPSE/TEXT imports and two original
cross-feature cases. Preserve legacy entry points; retain the two explicit
source-supported fixture migrations, not a blanket assertion relaxation.

Include the three original owner corrections from #8534 to unblock wasm,
without adopting later main or transferring upstream validation.

Normal cargo fmt --all passed. 223 declarations in the nine IO files
(333 including 110 unchanged UI/web declarations) are not test results.
This WIP has not been compiled or run; full CI and caller migration remain.
Earlier-source native passes do not qualify this candidate.

Co-authored-by: Ray <raykholo@users.noreply.github.com>
2026-10-29 02:39:19 +01:00
lillith 471e17f50e feat(dxf): preserve layer-zero imports and nine TEXT alignments (WIP #5319 #5320)
Add explicit alignment production and bounds callbacks, immutable layer-zero
initialization/import, and a reviewed fix retaining its metadata through copies.
Preserve the existing POINT and real writer-reader roundtrip foundation.

156 test declarations across four modules, including 26 additions against the
published parent; this source has NOT been formatted, compiled or run. Separate
source reviews do not qualify runtime. The older-source X2 gate remains separate.
2026-10-28 23:29:45 +01:00
lillith 1891344e07 feat(dxf): preserve POINT and original round-trip acceptance (WIP #5320)
Source-only reviewed four-file increment. 18 added test declarations, not executed. Published at the user's request; current X2 validation continues on unchanged older source.
2026-10-28 22:54:24 +01:00
lillith 1e176d8503 feat(dxf): preserve partial layered reader WIP (#5320)
Stacked on the owned X2 model. Includes 52 declared tests, not executed. Legacy projection and the remaining importer contract are pending; not ready for merge.
2026-10-28 21:57:39 +01:00
lillith fac0043543 feat(dxf): preserve owned file model and shared writer WIP (#5319)
Publish the reviewed partial implementation at the user's request while the corrected normal full gate is running. Not ready or fully validated.
2026-10-28 21:57:39 +01:00
lillith 119c40c814 claim: #5319 2026-10-28 19:37:38 +01:00
github-actions[bot] fe3fb381b1 Regenerate generated files and fold pending files [skip ci] 2026-10-28 18:21:33 +00:00
github-actions[bot] 0778d24801 Regenerate generated files and fold pending files [skip ci] 2026-10-28 18:14:57 +00:00
PaddleStroke 79f53a0999 Sketch dimensions in their own colour in every theme (#7861) (#8124)
* claim: #7861

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

* Sketch dimensions in a colour of their own in every theme (#7861)

Dimension lines, arrows and values were drawn in the same near-black or
near-white as fully constrained sketch curves, so they were hard to tell
apart in a busy sketch. Every theme now sets its own dimension colours:
plum on Light, orchid on Dark, and a hue from each built-in theme's own
palette. Colour vision tests measure them against the curves, the
construction lines and the conflict red, and a new test holds every
shipped theme to readable, distinct dimension colours.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 16:23:47 +00:00
froglemonade2 dba3a226f6 Closing from the background brings the window forward to ask about unsaved changes (#7783) (#7784)
* Closing from the background: the window comes forward to ask about unsaved changes

Right-click › Close on the taskbar while another app had the focus showed the
"save changes?" prompt in a window that stayed behind, so the close seemed to do
nothing. When the close stops at the prompt, the window now asks for the focus
(unminimizing it first) and for the user's attention, which is what native
Wayland offers (xdg-activation) and marks the taskbar entry where the system
refuses the focus. A window already in focus is left alone.

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

* X11: ask the window manager to raise the window as a user action

winit's Focus asks as an application, which KWin's focus-stealing prevention
refuses for a window last used before the switch away: it raised nothing and,
since the attention request was then skipped, did not even mark the taskbar.
On X11 send _NET_ACTIVE_WINDOW with source 2 (a direct user action) through
x11rb, which restores a minimized window too; native Wayland keeps the
attention request. Moves the logic into come_forward.rs.

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

* Come forward once the taskbar menu is gone, without flicker

KWin raised the window, then the taskbar's closing context menu handed the
focus back to the previous app 2 to 11 ms later, so the window only came
forward some of the time; asking again made it flicker. Ask 120 ms after the
close instead, and again only when the focus is taken back within 50 ms of a
request (a slow menu) or never came. A later switch away is the user's own and
the window stays behind.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 16:09:25 +00:00
cronos b72165fd30 Sketch: show temporary centre and midpoint alignment guides (#7903)
* Sketch: show center and midpoint alignment guides

Add transient per-viewport horizontal and vertical guides with a sketch preference. Related tests, native UI, WASM and supplementary Linux checks pass. Full CI remains blocked by unchanged Windows engine dead-code Clippy errors.

* Sketch: complete alignment-guide translations

* Tests: compile chosen-program mutex only on Unix
2026-10-28 16:07:05 +00:00
Frank 8e26fe9388 Measure: number the two picks in the view (#6020) (#6021)
* claim: #6020

* Measure: number the two picks in the view (#6020)

"1" and "2" beside the measured line's ends, as the panel lists the
picks, each just past its end so it stays off the line and its length.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-28 16:05:22 +00:00
semmelrinde c8c9534022 Create Sketch: the grid previews the origin plane under the pointer (#6975) (#7404)
* claim: #6975

* Create Sketch: the grid previews the plane under the pointer (#6975)

While Create Sketch waits for its plane, the grid now lies on the origin or
construction plane under the pointer, so the sketch's plane shows before
the click. A plane's browser row under the pointer lights that plane in the
view, and previews it the same way.

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

* Create Sketch: the planes at the top of the History preview too (#6975)

main now draws the Origin rows at the top of the vertical History as well
(history_rows). Hovering a plane there lights it like its row in the browser:
the plane is handed over the same way the hovered bodies are.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:58:33 +00:00
Christian Hammacher aae2c5e417 Assemblies: edit a linked component in place, with the assembly around it (#7672) (#7819)
* Links: update linked designs that changed while the assembly's tab was away

A design coming back to its tab compares the modification time and size of its linked
design files with what they were when it went to the background, and runs Update Links
on the worker thread for those that changed: saved in another tab, another window or by
a checkout. Preference update_changed_links (Design, Linked designs) turns it off.

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

* Docs: the assembly guide says linked designs update when their tab returns

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

* Links: Vietnamese strings, now that vi is a complete catalog

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

* Links: remember what each design last read, so an update that fails is tried again

A design's linked files are now recorded as the design last read them: when Update Links reads a
link without an error, or when the link is first seen. Coming back to the tab reads again what
differs, one link per run, so a file that cannot be read holds up no other and is tried again
the next time, and a part changed while the assembly was shown is taken up on its next return.
Closing several tabs together reads nothing on the way, and the web build, which keeps no file
times, looks at nothing.

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

* Links: no read during a save-changes prompt, records for adopted designs and missing files

A tab shown to answer "save changes?" reads no link before its save, and Cancel there or on a
batch lets the tab left in front read what it skipped. A design opened in place of the blank one
records its links at once, a link whose file is missing is recorded as missing so it is read when
the file comes back, and a read queued for a design that is no longer shown by the time it starts
is dropped. More changed links than can wait at once are read on the next return.

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

* Assemblies: edit a linked component in place, with the assembly around it

Activating a linked component opens the design it comes from in a tab of its own, with the
rest of the assembly drawn faded around it where the component sits, so the part's own history,
browser and commands are at hand. Finish Editing in the browser saves the part, goes back to the
assembly and closes the part's tab when the edit opened it; coming back to the assembly updates
the changed link (or Finish Editing runs Update Links when that is turned off). Update Links in
the part also reads the assembly's links again, off the window thread, and redraws the assembly
around the part; a result for an assembly changed meanwhile is dropped with a message.

The part is an ordinary tab, so saving, autosave, recovery, closing and quitting treat it as any
other design. The model scene's ghost triangles are now drawn (only the preview's were).
Preference edit_linked_in_place turns it off. Builds on the update of changed links when an
assembly's tab returns.

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

* Edit in place: a double-click opens it, Activate only activates

A double-click on a linked component edits it in place, in the browser as on a face in the
view (around the placement clicked), and the component's menu gets Edit in Place. Activate and
the browser's radio button make it the active component as they always did, so a linked
component can still be activated without opening its design.

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

* Double-click on a component's face: edit a linked one in place, activate any other

A double-click on a face in the view activates the component the body belongs to, at that
placement, as a double-click on its row does; a linked one is edited in place. Bodies of the
design itself or of the active component are left alone, and so is a double-click with a
modifier. One preference, double_click_components, covers both gestures.

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

* Edit in place: fixes from review

An edit whose part never opens is forgotten instead of starting on a later open of the same
file, and the web build starts the edit after its synchronous open. Finish Editing goes on only
for a save into the linked file and in the part's own tab, waits for a "changed on disk"
answer, and says so when the part was saved elsewhere. Showing the assembly no longer drops a
refresh, which now records the links it read so coming back reads nothing twice. The faded
assembly is worked out once per picture, a bad mesh index skips its whole triangle, and the
last two status texts come from the catalogs.

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

* Edit in place: Finish Editing on the MODEL tab and the mouse's back button

Finish Editing is a command now, component.finish_edit, with its schemas: the app window
answers it, anywhere else nothing changes, as with view.fit. While a linked design is edited in
place the MODEL tab ends with a FINISH EDITING panel, pinned at the right as FINISH SKETCH is,
with a new left-arrow icon; the browser keeps only the line naming the assembly. The mouse's
back button, or a keyboard's Back key, finishes too unless a dialog, tool or sketch is open.
The assembly guide describes editing in place.

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

* Edit in place: fixes from the second review

Saving the assembly waits while it reads its links for the part
Finish Editing waits for dialogs, tools, sketches and prompts open in the part, also when run as a command
The assembly reads the edited part explicitly when it does not check its links on its own
The FINISH EDITING panel cannot be customized
A tab opened by an edit stays that edit's to close when the part is entered again
The mouse's back button finishes editing; the keyboard's only while no text field has focus
Refreshing the assembly keeps its selection and active component

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

* Edit in place: fixes from the third review

component.finish_edit run as a command opens nothing and answers with an error when it cannot finish; engine.batch and engine.script refuse it
A double-click or Edit in Place while a dialog, tool or sketch is open in the assembly keeps it open
What changes in the assembly while it reads its links without changing its document stays: picks, activation, components dragged but not captured
Showing the assembly while it reads its links starts no second read
A new or opened design in the part's tab ends the edit
Finish Editing keeps the part's tab open while its agent chat runs

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

* Edit in place: Update Links run as a command in the part refreshes the assembly too

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

* Edit in place: the ribbon button reads Finish Edit, as Finish Sketch does

A bare "Finish" took the catalogs' surface-finish translation (German "Oberfläche").

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

* Edit in place: fixes from the fourth review

Finish Edit waits while the part's agent is in the middle of its turn, instead of keeping the tab of any chat open
A part saved while its assembly refreshes is read again when the edit finishes: the refresh records the files as it found them
A double-click on a linked component while something is open in the assembly says so instead of activating it
Commands are recognised in any spelling the engine takes, so engine.batch and engine.script cannot slip Finish Edit through
Update Links run as a command refreshes the assembly from the control channel only, not for the app's own reads
Moves of components the refresh removed are not carried over, and a refusal is one message
The command description and the guide say that the command does not save the part

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

* Edit in place: the command is Finish Edit, as Finish Sketch is

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

* Edit in place: a command to start it, and fixes from the full review

Added component.edit_in_place {component, path?}: the double-click and Edit in Place in the menu run it, and as a command it asks nothing, so a network location not allowed yet or a design open elsewhere makes it fail instead
Finish Edit asked by the part's own agent finishes once that agent's turn ends; the button still waits for the turn
The parameters and design properties panels, with text typed and not applied yet, hold up entering and finishing an edit
A refresh is not taken up under an undo, a queued command or a feature still being computed in the assembly
Refusals say what holds them up (a refresh, a file being read or written) instead of nothing
The browser strip names the assembly that is refreshing, not any assembly
The schema description says the command does not save the part
Korean strings for every new message

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

* Edit in place: fixes from the second full review

The MCP batch tool refuses component.edit_in_place and component.finish_edit as steps instead of sending them one by one
Edit in Place asked while the assembly's agent is in its turn opens the part once the turn ends; a double-click then is refused rather than stopping the agent
Both commands answer queued: true when they wait for the agent's turn, and stopping the agent forgets what it queued
An undo, a queued command or a delete check running in the design holds up entering and finishing an edit
A refresh redraws every edit of the assembly, the parts in other tabs too
In an assembly never saved, a double-click activates the linked component as before
The control and MCP docs list the new batch and script refusals, and the commands list every way they fail

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

* Edit in place: fixes from the third full review

The MCP batch tool refuses the two commands however a step names them, an execute step too
A queued Edit in Place is checked fully when asked for, a second one is refused, and both queued requests wait for what runs in the design instead of being dropped
Disconnecting the agent forgets what it queued, as stopping it does

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

* Edit in place: help text for the Finish Edit button

main now requires help for every toolbar command (#7134), and Finish Edit
is one. Written in every language the branch's catalog carries.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:57:44 +00:00
Ajmal Musthafa 2cc6615c2d Enhance two-tangent circle tool: add default radius handling and improve interaction hints (#8116) 2026-10-28 15:57:06 +00:00
Homero Thompson 9c5b3beb73 geom: cover inside_loop and segments_meet in the fill predicates (#6162)
Add unit tests for fill.rs's two ray-casting predicates, which
fill_general.rs relies on to decide which parts of a surface a loop
covers: a point inside/outside a square and an L-shaped (non-convex)
loop, documenting how inside_loop resolves points on an edge or
vertex; and segments that cross, stay apart, touch at an endpoint,
or are collinear with and without overlap for segments_meet.

Closes #38

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-28 15:49:30 +00:00
CamWight 14acdc2a6d Render: one sRGB transfer function (#7161) (#7162)
* Render: one sRGB transfer function, geom::srgb, for the hand-written copies (#7161)

Twelve places wrote the sRGB encode or decode formula out by hand (doc's glass
recipe, engine's render library, glTF import, the PNG film, photographic and
presentation output, the ray tracer's image, the stage, the surface decoder,
texture normalisation and the theme's contrast check). They now call
solidcraft_geom::srgb: encode/decode on 0..1 values, encode8/decode8 for 8-bit
codes. render::surface::srgb8_to_linear stays as a re-export, so its callers
are unchanged.

Same results: the module's tests compare it bit for bit with the formula as the
callers wrote it, over all 256 codes and a dense sweep of linear values plus
the knees, out-of-range values, infinities and NaN, for each way the callers
clamped (after encoding, before it, or not at all), and decoded values either
side of the decode knee, where no 8-bit code falls.

One change: glTF import encoded in f32. Over every f32 in 0..1, 218 of
1,065,353,217 values sit on a rounding tie that f32 got wrong and now give the
neighbouring code (f64 gives the nearer one).

Left as they are: render/job/image.rs (replaced by exact tables in its own
change), the tests and the starter-pack validator that keep their own copy as
an independent reference, and the WGSL shaders (they can't call Rust).

Fixes #7161

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

* Tests: the sRGB codes of five callers that had no test of their output (#7161)

The glass swatch, a library surface applied as a plain appearance, glTF's
fallback for a colour channel that isn't a number, a stage panel and an empty
pixel in presentation output each get an assertion with their sRGB codes worked
out by hand. A planted wrong conversion at each is now caught by that test.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:48:56 +00:00
semmelrinde bcb67cc2ec Mirror and Pattern: a body feature reopens with Bodies and its Operation (#8207) (#8298)
Editing a body Mirror from the history showed Object Type Features (the dialog starts from
the timeline selection, the Mirror itself, which turns pattern objects into features) and
dropped its saved Join. The editor now sets the objects back to Bodies for a body Mirror or
Pattern and restores the Mirror's combine.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:38:41 +00:00
Jasper van Loenen a8e5bfca73 Fix BOM table being too narrow (#8113) (#8144)
* claim: 8113

* Bill of Materials: size columns to their contents, Description fills the rest (#8113)
2026-10-28 15:28:55 +00:00
raykholo b68d42e5ec Theme: paste a theme into the Import tile (#8226) (#8227)
* claim: #8226

* Theme: paste a theme into the Import tile (#8226)

Ctrl/Cmd+V on Preferences > Interface imports a copied theme file, the tile's
menu offers Paste theme, and a theme file dropped on the tile imports instead
of opening as a design. Pasted text that is not a theme keeps its usual
meaning. The tile reads "file or paste".

* Theme paste: the new strings in Arabic, Hebrew and Vietnamese too (#8226)
2026-10-28 15:28:48 +00:00
github-actions[bot] 1ca2c5299c Regenerate generated files and fold pending files [skip ci] 2026-10-28 17:46:27 +00:00
github-actions[bot] 7d652d0e1f Regenerate generated files and fold pending files [skip ci] 2026-10-28 17:39:36 +00:00
semmelrinde 5f98396460 Dutch: translate the Render workspace's 733 messages (batch 2) (#8283)
* Dutch: translate the Render workspace's 706 messages (batch 2)

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

* Dutch: the 27 Render messages main gained since (the Appearances panel)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:28:41 +00:00
Badger B bffa846a55 Add German translations, batch 3 (#7237) (#8285)
* Add German translations, batch 3 (#7237)

* Use "Ansatz" for boss in German (#7237)

* Fix article for "Ansatz" (#7237)
2026-10-28 15:28:35 +00:00
semmelrinde 62da9deb29 Hungarian: translate the Render workspace's 733 messages (batch 2) (#8286)
* Hungarian: translate the Render workspace's 706 messages (batch 2)

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

* Hungarian: the 27 Render messages main gained since (the Appearances panel)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:28:28 +00:00
semmelrinde d17bc410a9 Galician: translate the Render workspace's 733 messages (batch 2) (#8292)
* Galician: translate the Render workspace's 706 messages (batch 2)

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

* Galician: the 27 Render messages main gained since (the Appearances panel)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:28:21 +00:00
semmelrinde fe210ece6d Malay: translate the Render workspace's 733 messages (batch 2) (#8299)
* Malay: translate the Render workspace's 706 messages (batch 2)

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

* Malay: the 27 Render messages main gained since (the Appearances panel)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:28:06 +00:00
semmelrinde e8d214716d Norwegian Bokmål: translate the Render workspace's 733 messages (batch 2) (#8300)
* Norwegian Bokmål: translate the Render workspace's 706 messages (batch 2)

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

* Norwegian Bokmål: the 27 Render messages main gained since (the Appearances panel)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:27:59 +00:00
P'tite Tête a4d1b5b6a9 Viewport: fewer ambient occlusion samples while the view moves (#7165) (#7214)
* feat: Fewer ambient occlusion samples while the view moves (#7165)

- Draw AO with 8 samples while the view moves, 32 once it has held still for 0.25 s
- Share the settle tracking with adaptive supersampling and repaint when it settles
- ui.screenshot waits for the full-quality frame (at most half a second)
- Test the sample choice, the uniform slot, and ghosting at both counts

* fix: Set the AO sample count in the scale test frame

- scale_tests.rs, new on main, builds a gpu::Frame without ao_samples
- Use AO_SAMPLES, as the other still-frame builders do

---------

Co-authored-by: P'tite Tête <asso@ptitetete.com>
2026-10-28 15:05:34 +00:00
semmelrinde 8589cdfb84 Ukrainian: translate the catalog entries that held English, and the missing ones (#8073)
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:05:02 +00:00
dudedagger42 4a34a258e1 Logo: an option to draw it in the theme's accent (#8133)
* Logo: an option to draw it in the theme's accent

Preferences > Interface > Logo: Theme's colours (the default, as before) or
Accent, three shades of the theme's accent. ui.prefs logo_accent.

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

* Logo: US spelling for the option's label, as upstream's English catalog uses

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

* Translations for the new options in the five complete catalogs (ar, he, ja, vi, zh)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:04:53 +00:00
Herperlerpicus 3a951bc8c3 Sketch: dimension new shapes as drawn (squashed onto current main) (#5987)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:57:54 +00:00
HiroKenEz 4fa051c9fc View angles: an optional readout under the orientation gizmo and a command to set them (#6032) (#6249)
* claim: #6032

* View angles: an optional readout under the orientation gizmo and a command to set them (#6032)

View > View angles (also Preferences > Graphics, or view.angle_readout) shows the
view's pitch, yaw and roll in degrees and Ortho/Persp under the axis view or cube,
updated live; off by default. Clicking the readout opens a small card to type
exact angles, which runs view.apply.

The angles are the camera's own (Camera::view_angles / with_view_angles), about
the up axis: yaw is the heading of the line of sight (Front 0, Left 90, Right -90,
Back 180), pitch the eye's elevation (Top 90, Bottom -90), and a positive roll
turns the model clockwise. view.apply documents this convention and now refuses a
pitch past +/-pi/2.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:49:47 +00:00
Homero Thompson 31d6873f7d OBJ export: the body colours travel with the file (#4451) (#6693)
* claim: #4451

* fix(#4451): the body colours travel with the OBJ file

An OBJ export left the colours of the design behind: the mesh file named no
material, so every body arrived in the reader's default grey. The export now
writes a material library (.mtl) next to the mesh file, with a material per
body, and the mesh file names that library with mtllib and picks the material
of each body with usemtl. Every path is checked before anything is written,
the library goes first and the mesh file last, so a mesh file never names a
library that is not there. Only the colour of the body travels: the colours of
single faces and the transparency of a body stay out, as a face colour needs
material groups inside one object. The export that writes one file stays
material-free, so it never names a library it does not write.
2026-10-28 14:44:32 +00:00
github-actions[bot] 545232be37 Regenerate generated files and fold pending files [skip ci] 2026-10-28 17:08:18 +00:00
Nathan Dane c1dee61482 Render shots: strip with thumbnails, Update and Revert for camera changes (#6430) 2026-10-28 12:59:40 -04:00
github-actions[bot] ad182057b9 Regenerate generated files and fold pending files [skip ci] 2026-10-28 16:53:13 +00:00
github-actions[bot] bfe7792592 Regenerate generated files and fold pending files [skip ci] 2026-10-28 16:44:05 +00:00
semmelrinde be2deb8c6f Create Sketch: a face of a combined Mirror's copy keeps its own attachment (#5779) (#8278)
A mirror's or pattern's copy of a face carries its seed's construction certificate, and on a
combined body that certificate finds the seed's face. Capturing an attachment never checked
that the certificate finds the picked face, so a sketch on the mirrored half sat on the
original. The capture now falls back to the face's exact history name when the certificate
names another face, as docs/face-attachments.md describes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:44:32 +00:00
PaddleStroke cecb1d8b66 Naming: a long history of one body no longer overflows the stack on reorder (#7587) (#8159)
* claim: #7587

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

* Naming: name a long history of one body from the oldest up (#7587)

A body's face names are worked out from the names of the body it was made
from, recursively. After a few hundred features in a row whose names
nothing asked for, reordering or moving an earlier feature re-evaluated
them all and the first name lookup (a fillet at the end) recursed once per
feature, overflowing the 1 MB window-thread stack on Windows. Name every
16th earlier version oldest first so no lookup recurses through more than
16 of them; the names are the same.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:43:42 +00:00
semmelrinde 427bd730f0 Title bar: a longer version moves Report a bug left instead of covering it (#5621) (#8280)
The version right of Report a bug had a fixed 60 points, enough for v0.25.1 but not for a
release candidate such as v0.21.0-rc.1, whose text was painted over the button. The bar now
measures the version and reserves its width plus a gap, never less than before. The extra
width comes only from the document tabs' spare room: where they would keep less than one tab,
the version is hidden, as on a narrow bar.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:33:25 +00:00
PaddleStroke 10b8faeba3 Windows: an export over a file another program holds briefly waits for it, up to 2 s (#8104) (#8125)
* claim: #8104

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

* Windows: an export over a file another program holds briefly waits for it, up to 2 s (#8104)

write_atomic replaces the target with one rename. Windows refuses that rename
(os error 5 or 32) while another program, such as an antivirus or indexer
scanning a file written a moment earlier, has the file open without delete
sharing. The retry gave up after 127 ms of waiting, which a scan under load
outlasts, so render.export and library.export over an existing file failed
with "Access is denied".

The retry now keeps doubling its wait up to 250 ms, about 2 s in all. If the
file is still held after that, the error says the file is in use by another
program, followed by the system's own message. The old file stays whole
throughout, as before.

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

* Saving over a read-only file fails at once, and says why Windows refused

Access denied (os error 5) is also what Windows gives for a read-only or
ACL-denied target, which waiting does not fix. A read-only target is now
refused without the 2 s wait, with "the file is read-only". Any other refusal
that outlasts the wait says another program may have the file open or it is
read-only, followed by the system's own message.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:32:20 +00:00
Dane Doubell 649ab0ef91 Sketch dimension: a slot's two caps measure the centre-to-centre distance (#7464) (#7488)
* Sketch dimension: a slot's two caps measure the overall length (#7464)

* Sketch dimension: slot caps need tangent sides, not just shared lines (#7464)

* Sketch dimension: slot caps measure the centre-to-centre distance (#7464)

---------

Co-authored-by: Dane Doubell <2853036+danedoubell@users.noreply.github.com>
2026-10-28 14:23:48 +00:00
PaddleStroke 8be7bb0201 Insert design: file names get the dialog's width (#8097) (#8122)
* claim: #8097

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

* Insert design: file names get the width the size and actions leave (#8097)

The web app's "Files in this browser" window listed stored files in an egui
Grid sized from cell content: the wide action buttons took most of the fixed
window width, the name and size columns were cut, and the rest was empty.

Add ui_kit::name_list on the kit's table grid: the name column takes the
width the other columns leave, the other columns are as wide as their widest
cell (measured as drawn, a changed measurement discards the frame), and a
name is cut with an ellipsis and its full text on hover only when it does
not fit. The window is a little wider (still capped at the browser width).

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:23:31 +00:00
Lars Jansen 67d5051792 Ribbon: keep the SKETCH tab shown outside a sketch (#7904) (#7906)
* claim: #7904

* feat(ui): keep the Sketch tab shown outside a sketch; its drawing tools start one (#7904)
2026-10-28 14:14:08 +00:00
Homero Thompson 7e8f87dc57 Extrude: a face shared by two bodies is resolved in the active occurrence (#419) (#6469)
* claim: #419

* fix(#419): a face shared by two bodies is resolved in the active occurrence
2026-10-28 14:13:45 +00:00
Colin Faulkingham 84016f036e Redefine: the reply reports the features it rebuilt (#5694) (#8244)
* claim: #5694

* Redefine: the reply reports the features it rebuilt (#5694)

timeline.redefine builds the edited feature and the features after it in its trial session;
the session's own evaluation then only takes those results from what the trial kept, so the
reply reported that second evaluation and read as "nothing was rebuilt" although the geometry
changed. Report the trial's rebuild, plus anything the session still had to compute itself, as
timeline.edit reports the same change; `restored` keeps counting only genuine reuse of earlier
results.

Tests: redefining_reports_the_features_it_rebuilt fails before the change with
{"feature": 2, "recomputed": 0, "restored": 2} and passes after it;
redefining_computes_the_later_features_once still guards the single computation (the reply
doubles if the kept results are lost).
2026-10-28 14:02:44 +00:00
raykholo 5f90d06452 Preferences: reverse vertical pan direction (#5240) (#5454)
* claim: #5240

* Preferences: reverse vertical pan direction (#5240)

Add "Reverse vertical pan direction" beside the horizontal setting in
Preferences > Navigation. pan_reverse_y defaults off, so older settings
files load unchanged, and flips the vertical part of two-finger pan on
every canvas through navigation::handle, independent of the horizontal
setting. Labels in en, ja, zh, de, and ko.

* Reverse vertical pan: strings as a pending locale file, with Arabic, Hebrew and Vietnamese

* Control protocol: pan_reverse_y in the sorted ui.prefs list (#5240)
2026-10-28 13:59:38 +00:00
Colin Faulkingham 27772ddba1 Keep command dialogs above Browser and History (#8174) (#8203)
* claim: #8174

* fix(ui): keep command dialogs above workspace panels (#8174)
2026-10-28 13:59:28 +00:00
semmelrinde e1b49238ba Italian: translate the Render workspace's 733 messages (batch 2) (#8250)
* Italian: translate the Render workspace's 706 messages (batch 2)

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

* Italian: the 27 Render messages main gained since (the Appearances panel)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:58:52 +00:00
github-actions[bot] ba35509ca0 Regenerate generated files and fold pending files [skip ci] 2026-10-28 16:12:44 +00:00
github-actions[bot] 32f11961e9 Regenerate generated files and fold pending files [skip ci] 2026-10-28 16:06:14 +00:00
semmelrinde 4dda001210 Traditional Chinese: translate the Render workspace's 706 messages (batch 2) (#8272)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:58:23 +00:00
semmelrinde f49d5c2f29 Indonesian: translate the Render workspace's 706 messages (batch 2) (#8271)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:58:13 +00:00
github-actions[bot] afde0f8073 Regenerate generated files and fold pending files [skip ci] 2026-10-28 15:32:53 +00:00
Nathan Dane 2897d3b22e Render library: Appearances card with a sphere grid, scopes, favourites and recents (#6429) 2026-10-28 13:41:24 +00:00
bherbruck 9bcb2ffe68 Drawings: first landing from the drawings branch (#8249)
* Drawing sheets: sizes, the ISO 5457 border and its marks (#3875) (#5108)

* Drawing sheets: sizes and the ISO 5457 border (#3875)

A sheet is a paper size and an orientation: ISO A0 to A5, Letter, Legal,
ANSI A to F, architectural A to E1, or a custom size (finite, above 0 and
at most 5,000 mm a side), landscape by default and either way for every
size.

A border profile is the rule for its border, and layout() works it out
for a sheet: the frame inside the margins, and the reference fields with
their labels. The ISO profile has a 20 mm filing margin on the left and
10 mm elsewhere, a 0.7 mm frame, fields of 50 mm out from the centre
lines with the corner fields taking what's left, rows lettered from the
top without I and O (AA, AB and on past Z), columns numbered from the
left, and an A4 sheet labelled on its top and right only. A profile can
divide the frame equally instead, or have no grid.

The records sit in geom, next to the section records, so saving,
rendering and export can all use them. Nothing is saved or drawn yet:
there is no command and no format change. Margins that leave no drawing
space, values that aren't finite, fields outside 1 to 1000 mm, more than
200 equal fields and unknown JSON fields are refused.

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

* Drawing sheets: ISO 5457's centring and trimming marks (#3875)

A drawing border profile now also holds the grid reference border and the
centring and trimming marks, either of which can be left out. The ISO
profile follows ISO 5457:1999 (read in its identical adoption,
IS 10711:2001):
- the grid reference border 5 mm outside the drawing border on every
  side, with the field labels between the two;
- four centring marks on the sheet's centre lines, from the grid
  reference border to 10 mm inside the drawing border;
- at each corner a trimming mark of two overlapping 10 x 5 mm
  rectangles, in the margin outside the grid reference border.

The labelled sides are now a rule worked out for each sheet: ISO 5457's
(the top and right of A4, all four sides of the others) or fixed sides.
So one profile labels every size correctly. validate() checks what
doesn't depend on the sheet, for when a profile is read; layout() calls
it, then checks the rest against the sheet.

Refused:
- a grid reference border that isn't finite, is negative or is wider
  than a margin;
- a centring mark that isn't above 0, would reach past the sheet's
  centre lines, or is on a drawing border those lines miss;
- a trimming mark that isn't above 0, is wider than it is long, is
  wider than the margin left outside the grid reference border, or is
  longer than half the sheet's shorter side.

The grid rule's JSON is now externally tagged ("none",
{"from_centre": {"field_mm": 50}}), as the sheet size is, so an unknown
field is refused in every form; the internally tagged "none" ignored
one. Nothing is saved yet, so the shape change costs nothing.

The names follow the glossary, and ISO 5457's "drawing sheets": the
module is drawing_sheet (was sheet, which means sheet metal elsewhere
here), DrawingBorderProfile and SheetLayout (were BorderProfile and
BorderLayout), sheet_border and drawing_border (were paper and frame),
and Sheet::size_mm (was paper_mm). The first part of S1 is still a draft,
so the renames are made here rather than in a commit of their own.

The extra centring marks ISO 5457 asks for on sheets larger than A0
aren't here yet. Still nothing is saved or drawn.

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

* Drawing sheets: a lighter built-in border, the filing margin a choice (#3875)

Cameron's decisions after seeing the sheet in the app, 2026-10-23:
- No trimming marks in the built-in profile: the filled corner blocks
  take a lot of ink. trimming_mark_mm stays, so a profile can still ask
  for them.
- Centring marks stop at the drawing border: from the grid reference
  border to the drawing border, never into the drawing area (on A4 they
  crossed the tables). centring_mark_mm keeps its meaning, how far a
  mark reaches inside the drawing border, and now takes 0, the built-in
  value, as grid_border_mm already takes 0 for "on the drawing border".
  A mark of no length (a reach of 0 with no grid reference border) is
  refused.
- Margins of 10 mm all round. ISO 5457's 20 mm filing margin on the
  left, for drawings that get bound, is a named choice: filing_margin,
  off when not given. On, it stands in for margins.left_mm, which is
  kept, and still checked, for when it's off again. The 20 mm is
  FILING_MARGIN_MM, and validate() and layout() both take the margins
  from one helper, laid_out_margins().

A3 landscape is now 400 x 277 at (10, 10), with eight 50 mm columns.
With the filing margin it is 390 x 277 at (20, 10) again, the same as a
20 mm left margin set by hand. A profile with all three choices on
(ISO 5457's full border) lays out exactly as the built-in profile did
before, and the tests keep the old hand values for it.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing W23a workshop plate oracle fixtures (#4950) (#4962)

* test(oracle): reviewer-aligned parameterized workshop plate fixtures (#4950)

Independent analytic W23 expected values and seven verified models,
including four R10 corners and the 2 mm tangent top chamfer.
Document accepted Drawing states and commit regenerated docs/oracle.md
from successful workflow run #29 (90/90 pass).

* fix(oracle): correct W23 chamfer centroid and clarify drawing session ownership

* Paper scene: plain records of what is drawn on a sheet (#4890 A1) (#5513)

geom::paper holds what a sheet shows as plain data: groups of strokes and fills, each group tagged
with the object that drew it (an opaque id) and its kind, with one validation pass over a bounded
record count. Seg2's checks and the coordinate rule move into profile.rs so section and paper share
them, and drawing_sheet takes its side and line limits from paper, so each limit is written once.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing sheets: centring marks across the whole margin (#3875) (#5554)

The built-in sheet's centring marks now run from the trimmed sheet's edge to the drawing border.
From the grid reference border, as before, a mark was the same length as a grid field mark, and on
A3 it sat on one (the sheet's centre falls on a field edge), so it no longer read as a mark once the
grid reference border's outline is left out (Cameron, after the prototype on #3875).

- DrawingBorderProfile.centring_mark_start: sheet_edge (the built-in's, and when not given) or
  grid_border (ISO 5457's figure 5); ISO's full border in the tests asks for grid_border.
- A mark still needs a length: one that stops on the drawing border needs room outside it on the
  side it starts from, every margin for sheet_edge, the grid reference border for grid_border.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing sheets: no centring or trimming mark longer than the largest sheet's side (#3875) (#6410)

A border profile capped every length at 5000 mm (the largest sheet's side) but two: a
centring mark's reach inside the drawing border and a trimming mark's length. A file could
give either a huge whole number, such as 18446744073709551615. The read's number check passes
whole numbers, so the profile took it as 1.8e19 mm, and saving wrote it as a decimal the next
read refused: a drawing that saved but didn't open again. K2's fuzz test of drawing files
(#3890) found it.

Both now take the cap the margins have, `MAX_SIDE_MM`, in `validate`, so the file is refused
when it's read. Layout's own checks against the sheet are unchanged, so a 5000 mm mark still
validates and is refused only on a sheet too small for it.

Tests: the hostile-profile test refuses 5000.000001 mm and 1.8e19 mm for each mark, and takes
5000 mm on its own; 4 planted faults (each cap removed or made one short) are all caught.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Bill of materials types: phantom, reference, purchased and inseparable (#3874) (#5107)

* Bill of materials types: phantom, reference, purchased and inseparable (#3874)

A component's bill of materials type is a part property (`bom_type` in its metadata, set with
component.metadata.set and read by component.metadata, as part_number is), so older releases
keep it and no format change is needed. It isn't a design property: the Design Properties
dialog doesn't list it and document.metadata.set refuses it. A word this build doesn't know
reads as normal and is kept.

assembly.bom counts by type: a phantom has no row and what it holds counts where it is placed,
in the same rows as the same parts there; a reference counts nowhere, and nothing inside it
does; purchased and inseparable components are one row, and in parts only an inseparable
component's purchased parts are listed too. Rows of one part number but different types are
different rows. Rows and children carry bom_type. With no types set the rows are as before.

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

* Glossary: bill of materials and bill of materials type (#3874)

The bill of materials types are a new idea, so the glossary gets their
term, with the five types, and "normal" gets its fourth meaning in the
table of words with more than one meaning.

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

* Bill of materials types: a plain line for each (#3874)

The guide's table and the glossary entry say what each type is for in
plain words: something you make, something just to group, something to
use as a reference, something you buy, something made as one piece.
The names stay the five standard ones.

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

* Bill of materials: kits fold together only when their contents' types match (#3874)

With group_children, two kits with one part number share a row when what they hold reads the
same. That reading (kit_key) compared each child by part number and count, but not by its bill
of materials type, though rows themselves are told apart by type. So a kit holding a made bolt
and a kit holding a bought one, both KIT, folded into one KIT x2 row listing the first kit's
bolt twice: the other type was lost, and which one depended on creation order. 0xlillith found
it in review of #5107.

kit_key now includes each child's type. Equal part number, type and contents still fold.

Test: two KIT kits each holding a BOLT fold into one row of two; once one bolt is purchased they
are two rows, each listing its own bolt. Planted fault (the type left out of the key): caught.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing files: a drawing saved as a container or as plain JSON, never read as a design (#3890) (#7098)

* File format families: drawings share the design format's versioning (#3890)

The format code works for a family of files: its own tag, its own numbers and
its own folder of change files, with one reading of a file's format, one
refusal of a file a newer build saved and one upgrade for every family. Designs
(solidcraft/N) are one family and keep everything they had: FORMAT and FORMATS
are as they were, and pending_names, format_string, version_of and read mean
what they did. Drawings (solidcraft-drawing/N) are the other, with format 1 as
their first record and each later change one file in
crates/doc/src/drawing/format/pending/, as design changes are. Nothing saved
changes.

A design tag never reads as a drawing's or the other way round, and a file that
names no format is a design from before format strings, never a drawing. Every
refusal names its family; a design's read word for word as before. A design
listing a pending change this build doesn't have is now refused as a newer
build's before its content is checked, as a newer number already was, so a
newer build's fields never read as damage. The list reader is
take_names(v, key, noun), the shape #4811 uses for its own list.

For the maintainer, the release step changes: scripts/fold-format-pending.sh
now folds every family that crates/doc/build.rs lists (FAMILIES), each into
its own next number: designs into crates/doc/src/format/v<N>/ as before,
drawings into crates/doc/src/drawing/format/v<N>/ from 2. With nothing pending
in a family it says so and moves nothing. Its test folds a drawing change into
v2 beside the design changes. docs/releasing.md, CONTRIBUTING.md and AGENTS.md say so.

build.rs lists each family's changes from its own folder, each folder's
versions contiguous from its own base.

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

* Drawing record: format 1 of the drawing family (#3890)

A drawing is now a record of its own (crates/doc/src/drawing.rs): its name,
the designs it draws (sources: an id and the design file's path, relative to
the drawing's folder as a linked design's is), its properties under the design
metadata's rules, its units (each design's own, or one length unit of the
expression unit table), its content language (a BCP 47 tag) and its sheets.
A sheet holds its paper, a copy of its drawing border's profile, the
resolution its pictures are rendered at (300 dpi unless it says, 25 to 2400),
the component it documents and whether it is left out of the sheet count or
of printing. This is format 1 of the drawing family; each later kind of
record adds one file in crates/doc/src/drawing/format/pending/.

The rules: one id counter for every object, raised above the largest id when
a file is read and never rewound; every reference is an id that must resolve,
or the file is damaged and refused, never patched; 1 to 1,000 sheets, at most
64 sources, names of 1 to 256 bytes, paths of 1 to 4,096 bytes without NUL.
The same drawing always saves as the same bytes.

Drawing::from_json reads at most 16 MiB of text, then runs the family's format
check, the number check, the upgrade, the typed record (unknown fields refused
everywhere) and Drawing::validate. The number check is now one function every
family calls, Family::check_numbers, told which field holds other tools' data;
a design's refusals read as before.

Nothing saves or opens a drawing yet: the container is the next step.

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

* Drawing ids: random and collision-free from format 1 (#3890)

A drawing's objects now take random ids, the form jyviko chose on #3890 from
#1017: no counter, so objects added on two branches never share an id and
never edit one line. The allocator is one module for drawings now and designs
later (#626 Phase 3), crates/doc/src/ids.rs: an IdSource gives nonzero u64s by
splitmix64 from a seed, each checked against the ids in use and drawn again
when it is one, or when it is 0. A run never draws a number twice, so at most
one draw per id in use comes before a free one, and a seeded run over a file
the same seed made still gets a new id. IdSource::seeded gives the same ids
for tests and replays; IdSource::from_entropy seeds a session from the
standard library's hash keys, the time and a count, with no new dependency.

In a file an id is 13 characters of Crockford base32, lowercase
(0000000000001 to fzzzzzzzzzzzz): ids::encode writes it and ids::decode reads
only that spelling, case-sensitive, so an id has one form to search for.
Anything else, 0 included, makes the drawing damaged. The drawing loses
next_id (a file that holds one is refused), and Drawing::new and allocate_id
take the IdSource. Messages name ids as the file writes them. The component a
sheet documents stays its design's own number until designs move over.

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

* Drawing record: a drawing too large to reopen isn't saved (#3890)

from_json reads at most MAX_DRAWING_BYTES (16 MiB), but to_json had no limit. Other tools'
properties are kept as they came, and indenting them can grow a drawing read in at about 4 MB
past 16 MiB (two million zeros in one array), so the next read refused what the save had just
written. 0xlillith found it in review of #3891.

to_json now returns a Result and refuses JSON longer than a read takes ("drawing too large to
save (at most 16 MiB)"), so every drawing saved opens again. Nothing writes drawing files yet, so
the error reaches the future file writer before it publishes anything.

Test: that case is refused, and a smaller compact drawing saves and reopens unchanged.

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

* Drawing files: a drawing saved as a container or as plain JSON, never read as a design (#3890)

K3 of the drawing storage plan (W11.2): the file a drawing is saved in. Nothing writes one from a
command yet; opening and saving come with K5.

- A drawing container is a design container holding `drawing.json` (Deflate, as `document.json`)
  in place of `document.json`, and `container.json` says so:
  {"content": "drawing", "format": "solidcraft-container/1"}. A design's `container.json` is as it
  was, with no `content`. The plain JSON form is the drawing's own text. Both give the same bytes
  every save, so a drawing can live in version control as text.
- `io::file_kind` tells a design from a drawing by `container.json` or by the JSON's format. The
  design reader refuses a drawing ("this file is a SolidCraft drawing, not a design: open it as a
  drawing") and the drawing reader a design; plain JSON only asks when it isn't a design, so
  reading a design costs nothing more. A container's content this build doesn't know, or a drawing
  container that also holds a design's `document.json`, is refused.
- `read_drawing` (bytes, either form), `read_drawing_file` (one seekable handle, the design
  reader's checks) and `write_drawing_container`; `DRAWING_EXT` (`scdwg`) and
  `is_drawing_path` beside the design's.
- The container writer's set-up and finish, the file opening and the container sniffing move into
  one function each, which designs and drawings both use. The container's own checks (budgets,
  entries, the ZIP directory) are the design container's, word for word.

Tests: a drawing round-trips through both forms byte for byte, and the container holds exactly
`container.json` and `drawing.json`; `file_kind` on both forms of both kinds; each reader refuses
the other's file; unknown content, a stray `document.json`, a missing drawing, an unknown
container version and a damaged drawing refused; both forms from disk, and a directory refused;
mutation fuzz of both forms (an error or a drawing, never a panic).

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Paper scene: SVG of a sheet, its lines, arcs, cubics and fills (#4890 A3a) (#7032)

The first export of a paper scene, as SVG first (jyviko and 0xlillith on #4890), from the research
in the plan's §16. A3b adds ellipses, hyperbolas and Béziers above degree 3, which this refuses as
"not supported yet".

- `geom::paper::Prepared`: writers read a scene through `Scene::prepare`, which checks it first, so
  none reads one unchecked. Clipping goes there too, once (A8).
- `geom::paper::arc_pieces`: an arc's ends in pieces of at most a quarter turn, the last its own end.
  A half turn drawn from its ends is ill-conditioned: rounded to the nanometre (six decimals of a millimetre) its
  centre moves up to 1e-2 mm, where a quarter turn's stays under 1e-6 mm.
- `io::paper::paper_svg`: one user unit a millimetre, the size in mm on the root; y flipped by
  writing the height less y, so the file's numbers are page coordinates and an anticlockwise arc
  has sweep flag 0; lines `L`, arcs `A` (never large-arc), cubics `C`, parabolas `Q`; fills
  black and even-odd; one path per item; groups as `data-object` and `data-kind` (object ids can't
  be XML ids). No background, so cutters see only the marks.
- Numbers are whole nanometres (six decimals of a millimetre): no exponent, no "-0", the same bytes every time. They are the
  writer's own state too, so a joint is written once and a closed path ends exactly on its first
  point. Numbers are written straight onto the document, with no text made per number. A width
  under half a nanometre is written as one, and a piece too short for the grid is merged into the
  next, both counted in the report; a path's last piece has no next, so it is kept however short
  (unless it has no length). Output over 64 MiB is refused.

Tests: the A3 drawing border's whole document; quarter, 270°, clockwise and whole-turn arcs, and a
circle of two halves giving the same four quarters; the quarter-turn boundary both sides; cubics and
parabolas, and the conics refused; the number format; a closed path whose start and end round
apart; a sliver merged; an open path's short last line and arc kept, and one of no length dropped; read back through our own SVG reader (lines exactly, the arc as an arc);
the scene's JSON mutated into the writer (never a panic).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing W17a: view definitions as data (#4816) (#4817)

* claim: #4816

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

* Drawing views as data: named views, scales and the map onto paper (#4816, W17a P1)

What a drawing view is, before anything draws it (geom::drawing_view):
- NamedView: the six principal views and the isometric views from the four upper corners, each
  an exact basis (a Plane whose normal points back at the viewer), never taken from a camera,
  whose pitch clamp would tilt a top view, with no -0 to write out; `iso` reads as the
  front-right one.
- basis_looking: any other view from its direction, an up and an origin (paper x = direction x up,
  paper y = x x direction), refusing a zero direction, an up along it, or an origin that isn't
  finite or within 1e12 mm. W07's
  {direction, up, origin} view reads through it.
- Scale: paper : model as two positive numbers, read and written as "1:2", from 1:100000 to
  1000:1; Scale::fit picks the largest ISO 5455 preset (50:1 to 1:10000) at which a view fits a
  space (W07's "fits the page" default), compared as size x paper <= room x model so an exact
  fit at a reduction isn't lost to rounding.
- ViewFrame: a view's basis, scale and place on paper, the point of its plane at `centre`
  landing at `position_mm`. Its paper map moves the view's curves and their accuracy onto
  paper (paper error = scale x model error); `boundary` maps a box of its plane onto paper from
  its four corners.

In geom, where Seg2 lives:
- Similarity2 and Seg2::similar (new): scale, turn and shift a segment exactly, an arc staying an
  arc. Similarity2::new refuses a scale that isn't above 0 and works the turn out once, not per
  point;
- Seg2::map_controls: a segment's control points mapped by any function. It was doc's
  sheet::map_controls; its four callers in doc use the method now, unchanged.

CurveAccuracy::scaled gives a curve's accuracy at another scale.

Tests: each named view's basis and viewer side, and the same bases from a direction and up; a 50 mm cube in every principal view at 1:1 and
1:2, and in isometric (edges 50 x sqrt(2/3), outline 50 x sqrt(2)); the view's centre on its
position (W07's 100 x 20 front view on A3 at 2:1); scales read, written and refused; the fitted
scale, an exact fit at 1:5 and ISO's smallest; no -0 in any named view's axes; an origin refused by
its own message; hostile bases, centres and positions; every segment kind moved by a similarity,
and the similarities refused; scaled accuracy.

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

* Drawing views: the bottom view pinned, square near parallel, bounded scales and boxes (#4816)

From DevonHope's review of #4817:
- The tests pin all six principal views exactly. The direction-and-up test uses literal ups,
  so a bottom view turned half round now fails it.
- basis_looking squares x to the direction before normalising. Near the 1e-9 threshold the
  normal was up to 8.8e-9 rad off; now it is about 1e-16.
- Scale::fit fits nothing for a size or room that is negative or not finite. A size of 0 still
  sets no limit that way.
- Each side of a scale is 1e-6 to 1e6, so a scale writes at most 49 characters.
- ViewFrame::boundary returns a Result. It refuses a box that is inside out or not finite on
  paper, instead of dropping a corner.
- paper_map, boundary and seg_to_paper say which coordinates they take.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing W18 S2: title blocks as data (#3875) (#3877)

* Title blocks: what a cell shows and where its text goes (#3875)

geom::cell holds a title-block cell's content: parts of text and fields
(component, drawing, sheet, revision or prompt, by key, with an optional
unit and decimals kept as written for the resolver to check), at most 64
parts and 4096 bytes of text, with no control character but a line break.
Beside it are a resolved value (live, overridden and drifted, or missing,
with "-" for each part that couldn't be read and why), an override with
the value it replaced, and the projection a drawing's views use (first or
third angle), which the title block's symbol will read.

A fit warns and never cuts: a count of characters, not bytes, with its own
count for text in Chinese, Japanese, Korean or Yi characters.

The cell text rule places a label and a value: the label's baseline 1 mm
plus its cap height below the cell's top, the value box under it inset by
1 mm, one line centred in the box, and wrapped or several lines down from
its top at the font's pitch, with a warning when the last falls below the
box. Wrapping by width, width warnings and glyphs a font lacks need the
text measured, so they wait for the paper scene's text.

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

* Title blocks: definitions and their place on a sheet (#3875)

geom::title_block holds a title block's definition: its size (1 to 1000
mm a side), its outline and cell line widths, and up to 64 cells. Each cell
has a snake-case name of its own, a rectangle measured from the block's
lower-right corner, an optional one-line label with its cap height, and a
value: text from cell content, with its cap height, alignment and fit, or
the projection symbol, which reads the drawing's projection and is never
fixed in the block.

validate() checks a definition on its own, as when one is read: cells
inside the block and not overlapping (touching is fine), label and value
cap heights that fit, and the content's own limits. layout() puts the
block on the drawing border's lower-right corner of a sheet, refusing one
that doesn't fit, and gives each cell's rectangle, its label's place and
its value box by the cell text rule. On A3 landscape a 180 x 54 mm block
runs from (230, 10) to (410, 64); it fits A5 landscape and every larger
sheet, but not A5 upright.

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

* Cell text: a value box lies within the paper's coordinates (#3875)

place_lines took any finite, ordered value box, but centring one far out (min x 1e308, max x
1.1e308) overflows: the anchor came back infinite, with no warning. 0xlillith found it in review
of #3877.

The paper scene already bounds every coordinate it holds by MAX_COORDINATE_MM (twenty times
the longest sheet side). That limit is now public, and place_lines keeps its box inside it, so
its anchor is always finite: one rule for what a paper coordinate may be.

Tests: the hostile-box test refuses both overflow cases from the review and a box just past the
limit on each side, and places lines in a box the size of the whole paper limit. The fuzz test's
numbers now include values past the limit (1.1e5, ±1e308).

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

* Title blocks: padding from the lines' inner edges, one label rule, nothing unread (#3875)

A cell's text is padded from the inner edge of its lines: each side of a cell moves in by half
the line drawn on it (the outline's on the block's edges, a cell line's inside), so a wide
outline never covers the text. Before, the padding ran from the line's centre.

The label's one-line rule lives with the cell text rules (`cell::check_label`), where parts
lists will find it. The cell types nothing read yet (`Override`, `Resolved`, `State`,
`Problem`, `Reason` and `MISSING`) wait for the resolver that will read them.

The tests check the exact thresholds inside the lines (a label that leaves no room, a value
that just fits), pick each of the lines, alignment and wrapping on their own so every
combination comes up, and lay fuzzed blocks out on every standard sheet, either way, with and
without the filing margin.

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

* Title blocks: the drawing border's line, descenders, room where the block sits (#3875)

From DevonHope's review of #3877:
- Each cell's lines are clamped to the inner edge of the drawing border's line. That line runs
  along the block's right and bottom edges, and along any other edge it reaches, as when the
  block fills the border. Aabb2::intersection, the 2D twin of Aabb3's, does the clamping.
- layout checks each cell's room again where the block sits (place_cells, which validate runs
  at the origin), so rounding at the real corner can't turn a cell inside out.
- The cell text rule counts descenders, at 3/10 of the cap height (ISO 3098's lettering B).
  They may reach into the padding under a value box, never past it to a line. place_lines
  warns Height when they would, and validate asks it whether one line fits.
- The module doc no longer links to a private function.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Drawing W06a: exact orthographic hidden lines for the analytic subset (#2455) (#2457)

* Drawing W06a: exact orthographic hidden lines for the analytic subset (#2455)

crates/geom/src/hlr (L0): prepare once per body, then hidden_lines for a
scene of placed bodies. Edges and face silhouettes are projected from their
exact curves, split where projections cross, and each piece is classified by
rays toward the viewer against the trimmed faces: visible, hidden or
explicitly uncertain, never guessed. Planes, cylinders, cones, spheres and
tori are supported whether stored as analytic records, revolutions or spline
patches; freeform faces are reported and make what they could hide
uncertain. Screen geometry is Seg2 with the W01a accuracy vocabulary: exact
lines and conic arcs where the projection is exact, bounded chords
otherwise. docs/drawing-hlr.md holds the contract and its limits.

* geom/hlr: handle the brep records main gained in #3093

Main's exact model storage (#3093) added Curve::SurfaceIntersection,
Surface::PlaneThrough and Surface::PlacedRevolution, and the HLR matches on
the records no longer compiled. A plane through three points is a plane: it
is trimmed and intersected as one, and a box stored that way draws the same
bits as one with axis-stored planes. The procedural intersection curve and
the placed revolution (whose affine placement may scale it unevenly) are
refused by prepare as not supported yet, until the kernel adapter handles
them. The records' positions move with the body's centre like the others.

* geom/hlr: pad plane faces' boxes, so a plane record off by rounding still hides

Plane faces took the box of their boundary chords unpadded, flat along the
normal. When the plane record and its edges disagree by rounding (a unit cube's
top plane one ulp above its edges, a 100 mm cube's 1e-11), the ray toward the
viewer reached the plane just outside that box, the slab test culled the hit,
and the back edges came out Visible with no doubt. Every face's box is now
padded by 1e-6 of its size, as curved faces' boxes already were. Reported by
DevonHope on #2457.

* geom/hlr: limits from review: trim samples, scene extent, crossing pairs, surface groups

From DevonHope's review of #2457:
- Options::trim_samples must be 1 to MAX_TRIM_SAMPLES (4096).
- Placed bodies must stay within MAX_COORDINATE (1e12 mm, as section and brep
  bound stored numbers). Placements 1e200 apart made the scene's size infinite
  and every tolerance taken from it with it, so everything came out Visible.
- The crossing search counts its candidate pairs before it starts and meets
  each pair only in the first grid cell the two segments share, instead of
  keeping a set of the pairs met, which could outgrow wasm's 4 GB before the
  500 million pair budget tripped. The same pairs in the same order.
- prepare groups faces on one quadric or torus by comparing each face with
  the faces of its kind whose size agrees to the tolerance (sorted), not with
  every face; at most 50 million comparisons. prepare_cancellable polls a
  cancel callback between edges, faces and comparisons.

* geom/hlr: boundary chords on a grid, and no fine pass over coincident curved chords

The cost items of DevonHope's review of #2457:
- Every ray hit asked how far it lies from its face's boundary by scanning all
  of the face's chords (4096 per circle; a plate's face with 256 holes has
  about a million). The chords are now bucketed on a uniform grid over the
  boundary's box, cells at least as long as the longest chord, and the test
  looks only at the cells around the point. It finds exactly the chords the
  scan finds.
- Chords of two curved curves that lie on each other end to end (aligned holes
  seen along their axes) were cut into 16 by 16 pieces and intersected, to
  find crossings that are only noise within the curves' tolerance. They are
  now skipped; visibility changes where a coincident run starts or ends, and
  chords that only partly overlap still find those.
- Fixtures: a plate with holes, coaxial cylinders seen along their axis, and
  300 placements.

* geom/hlr: pad boxes by the body's coordinates too; coincident chords only to rounding

Review of the previous commits found two holes:
- The padding grew with the face's size, but rounding grows with where the body
  was modelled: a 0.001 mm cube 1e7 mm out, its top plane one step (1.9e-9 mm)
  above its edges, still had its hit culled. The pad now adds 1e-12 of the
  body's offset.
- Two chords were taken for coincident when their ends lay within each other's
  sag, which in a coarse scene can hide real crossings: an arc can bulge across
  a line 1 mm off its chord twice. Only chords that coincide to rounding are
  skipped now; identical projections, the costly case, still are.

* geom/hlr: coincident curves meeting at shared sample points do not cross

Timing the review's scenes showed that skipping coincident chords was not
enough: chords of two coincident curves also touch end to end at every sample
point they share, and each touch was a crossing to refine and split at. 64
coaxial cylinders seen along their axis gave 8.3 million crossings (19 s), 64
cylinders one behind another along the line of sight 4.2 million (214 s;
before these commits the crossing budget refused it). A touch at a shared
sample point is now dropped when the two curves also coincide, to rounding, on
both sides of it. Where a coincident run starts or ends one side differs, and
the touch is kept.

* geom/hlr: the own-face margin allows for rounding where a body was modelled

The far 0.001 mm cube of the previous commit showed a second effect of records
rounded at large coordinates: its top plane, one ulp (1.9e-9 mm) above its
edges, hid the top edges themselves, because a ray leaving an edge met its own
face 3.2e-9 mm along, past the own-face margin of 1e-6 of the face (1.4e-9).
The margin now also covers 1e-14 of the body's offset (about 45 ulps of its
coordinates), which only matters for parts far smaller than their distance
from the origin.

* geom/hlr: no parity test for a hit on the boundary, where it is uncertain anyway

* docs/drawing-hlr: the fixtures of the review's second round

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>

---------

Co-authored-by: CamWight <91156642+CamWight@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Benny1496 <163034806+Benny1496@users.noreply.github.com>
Co-authored-by: Mateusz Sych <151755914+SychPL@users.noreply.github.com>
Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-28 13:31:16 +00:00
Ahmad Khan 6af571eb40 Flat Pattern: show the whole flat size (#7495) (#7496)
* claim: #7495

* Flat Pattern: show the whole flat size (#7495)

Each side of the flat size and the thickness get their own row (Flat size X, Flat size Y,
Thickness), so the panel's width no longer cuts the value off after its first side.

* Flat Pattern: the flat size labels in Arabic, Hebrew and Vietnamese (#7495)
2026-10-28 13:25:09 +00:00
ermanyop-stack a5f472c23e Prevent angular drags from collapsing construction geometry (#8148) (#8160)
* Reject newly collapsed angular reference lines (#8148)

Reject angular solutions that collapse a reference relative to its input length. Cover constrained drags and already-short references. Engine replay and full CI validation remain in progress.

* Cover live and non-live angular drags (#8148)

Adds a replay of #8148 for live and non-live drags. The integration test compiles locally, but the Windows GNU test executable exits with STATUS_ACCESS_VIOLATION before running tests, including with --list/--help. Kept in the draft PR pending validation on a working native runner.
2026-10-28 12:44:16 +00:00
semmelrinde 34efb90489 Romanian: translate 946 messages the catalog was missing (batch 1) (#8193)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:44:10 +00:00
Tarik Sijerčić f060702676 i18n: add Bosnian, Croatian and Serbian interface languages (#7813)
* i18n: add Bosnian (bs), Croatian (hr) and Serbian (sr) catalogs

Full translations of all English messages, the pending ones included,
kept in step with one shared terminology:

- Bosnian (Bosanski): ijekavian, Latin script.
- Croatian (Hrvatski): ijekavian, Latin script, Croatian standard terms
  (točka, kut, brid, ploha, značajka, spremi, izbornik, sučelje).
- Serbian (Српски): ekavian, Cyrillic script; brand and file names,
  acronyms, units, key names and placeholders stay in Latin.

The Browser panel is "Stablo modela" so it is never confused with a web
browser, and the History panel is the timeline ("Vremenska traka"), not
the undo history, per the glossary.

Registers the three catalogs, adds them to the new-language test, a
pending attribution file, and a terminology note in docs/localization.md.

* i18n(bs, hr, sr): translate the 195 messages added on main since the catalogs were made

Covers the navigation bar customisation, the render stage, the new
command help texts and the Assistant start-up preferences, so the three
catalogs again carry every English message.
2026-10-28 12:38:27 +00:00
Homero Thompson d6b1d03695 Browser: an exact body name wins over a case-only sketch match (#6967) (#7004)
* claim: #6967

* Browser: an exact body name wins over a case-only sketch match (#6967)
2026-10-28 12:22:27 +00:00
Mateusz Sych e181015fd1 MCP save: a folder the agent opened or saved a design in stays in scope (#7181) (#7216)
* claim: #7181

* MCP save: a folder the agent opened or saved a design in stays in scope (#7181)

The agent's default folders held the open design's folder only while that
design stayed open there, so after a new design, an opened STEP file or a
save-as elsewhere a save beside the earlier design was refused, while the
same save through the control port worked.

The MCP server now keeps, for the rest of its run, the folder of every
design file a call opened or saved (open, save, and doc.open, file.save,
file.save_as through execute or batch, path given in full) and, headless,
of every design open in its session. Such a call only succeeded because the
folder was already in scope, so naming a path adds nothing. The folders get
the open design folder's terms (inside home or temp, not hidden, hidden
entries unreachable), at most 16. Bridged, they go to the app as
design_folders, which it judges the same way.

The save tool description and docs/mcp.md say how to add a folder with
--allow-path.

* MCP scope: a design's folder is the folder its file resolves to (#7181)

A link in another folder to a design inside the agent's folders passes the
scope check, which follows it, but its own folder was what got remembered
(and, for the open design, what counted while it was open). Take the folder
of the file as the check resolves it.

* Control test: a hidden file the export format accepts (#7181)

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-28 12:22:20 +00:00
Homero Thompson 387e86729c Sketch: the rounded rectangle completes from a vertex like the plain one (#7878) (#7943)
* claim: #7878

* Sketch: the rounded rectangle completes from a vertex start point (#7878)
2026-10-28 12:20:46 +00:00
Dahak Builds 64ff25f380 Fix sketch drag breaking midpoint-constrained line solver (#7635) (#7810)
* claim: #7635

* Keep the drag cursor on the manifold of an ill-conditioned sketch (#7635)

A construction line collapsed to zero length makes its angle row's entries
on that line ~1e7 while the same row's entries on the measured line are ~1.
Dragging an endpoint of the midpoint-pinned line then failed two ways: the
null-space rank analysis, which scaled rows only, hid the small (physically
meaningful) entries below its pivot tolerance and let the measured line
rotate freely; and the cursor's refinement, which demanded a TOL-tight
correction the ill-conditioned system cannot deliver, gave up entirely and
let the drag leave an unsolvable step placed - breaking the perpendicular
and angle constraints.

Equilibrate the null-space Jacobian on both sides (columns by their largest
entry, then rows) so one row's entries share a scale, and let the cursor
keep working from a pose the solver itself calls solved (residual below
ACCEPT) when refinement stalls above TOL, accepting corrected trials at the
same tolerance the final validation uses.

---------

Co-authored-by: Dahak Builds <dahakbuilds@users.noreply.github.com>
2026-10-28 12:20:40 +00:00
Jomguy2 1dba7f7f04 Agent chat: OpenCode Go preset with per-model endpoints (#6111)
* agent chat: OpenCode Go preset with per-model endpoints

One preset (https://opencode.ai/zen/go/v1) covers every Go model: each
model is routed to its endpoint family (chat completions, responses,
messages, Gemini), always with the x-opencode-session header Go
requires. Unknown models fall through protocols when Go names the
mismatch; the conversation and tools translate per protocol.

* agent chat: keep Go reasoning metadata, route all listed models (#5656)

* fix agent chat Go endpoints to documented inference routes

* style: collapse long assert in Go routing test (cargo fmt)

* refactor: share Go tool/args helpers, table-driven protocol routing (no behavior change)

* refactor: share GoCallAccum across Go reply parsers (no behavior change)

* refactor: share part/call extractors across Go history converters (no behavior change)

* refactor: share post_to envelope between post and go_post (no behavior change)

* refactor: pass system note into go_responses_input, drop history clone (no behavior change)

* refactor: lazy Gemini name map, shared go_tools, named tool-call cap (no behavior change)

* refactor: share shaped-tool wrapper across Go tool converters (no behavior change)

* fix: set request_timeout_s in Go test setups for rebased main (no behavior change)

* fix: expect ToolsAvailable first in tool-loop tests (matches new event order)

* simplify: reuse tool_arguments, drop restater comments (no behavior change)

---------

Co-authored-by: Julius <julius@localhost>
Co-authored-by: Jom_g <jom_g@users.noreply.github.com>
Co-authored-by: HoloPort <holoport@localhost>
2026-10-28 12:20:19 +00:00
N3MI-DG 7d9b28e20d Context menu: only the row under the pointer stays highlighted while a flyout closes (#8065) (#8066)
* claim: #8065

* Context menu: only the row under the pointer stays highlighted while a flyout closes (#8065)

A row that owns a flyout kept its highlight for the whole of the flyout's
closing delay, so the row the pointer had settled on lit up alongside it.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-10-28 12:19:51 +00:00
439 changed files with 110920 additions and 2187 deletions
+5
View File
@@ -597,6 +597,11 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
| 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 |
| assets/locales/bs.json | Tarik Sijercic (tsijercic1) | Original Bosnian translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
| assets/locales/hr.json | Tarik Sijercic (tsijercic1) | Original Croatian translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
| assets/locales/sr.json | Tarik Sijercic (tsijercic1) | Original Serbian (ekavian, Cyrillic) translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/finish_edit.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| `assets/locales/pending/sketch-tracking-guides.json` | SolidCraft contributors | Original alignment-guide preference labels and help text | MIT OR Apache-2.0 |
## Code adapted from sibling projects
+3 -1
View File
@@ -268,7 +268,9 @@ a conflict. `crates/doc/src/format/pending/README.md` has an example.
**At release time** the maintainer runs `scripts/fold-format-pending.sh`, which moves the pending
files into `crates/doc/src/format/v<N>/` and fixes that number for good (see
[docs/releasing.md](docs/releasing.md)). Never add a file to a `v<N>/` folder afterwards.
[docs/releasing.md](docs/releasing.md)). Never add a file to a `v<N>/` folder afterwards. Drawings
follow the same rules with their own numbers, from 1, in `crates/doc/src/drawing/format/` (see its
`pending/README.md`), and the same script folds them.
## Lists many changes add to
Generated
+1
View File
@@ -4238,6 +4238,7 @@ dependencies = [
"ureq",
"windows-sys 0.61.2",
"winit",
"x11rb",
]
[[package]]
+1 -2
View File
@@ -131,8 +131,7 @@ 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. 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.
documented licences and attribution.
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
@@ -1,36 +0,0 @@
# 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).
+1 -1
View File
@@ -653,7 +653,7 @@ fn cmd_mcp(args: &[String]) -> Result<(), String> {
if let Some(s) = &scope {
let roots: Vec<String> = s.roots().iter().map(|r| r.display().to_string()).collect();
eprintln!(
"solidcraft mcp: files limited to {} and the open design's folder (--allow-path DIR adds one, --allow-any-path lifts the limit)",
"solidcraft mcp: files limited to {} and the folders of designs opened or saved here (--allow-path DIR adds one, --allow-any-path lifts the limit)",
roots.join(", ")
);
let design_dir = flag(args, "--in")
+6 -2
View File
@@ -40,6 +40,8 @@ pub enum Intent {
Open,
/// Add its bodies to the open design (STEP, 3MF, STL).
Insert,
/// Import it as a theme: it was dropped on Preferences' Import tile (#8226).
Theme,
}
/// A stored design, as the file panel lists it.
@@ -615,13 +617,15 @@ fn choose_file(accept: &str) -> Result<js_sys::Promise, String> {
}
/// Read files dropped on the page.
pub fn take_drops(files: &Rc<Files>, raw: &mut egui::RawInput) {
/// `theme`: the pointer is over Preferences' Import tile, so the files are themes.
pub fn take_drops(files: &Rc<Files>, raw: &mut egui::RawInput, theme: bool) {
let intent = if theme { Intent::Theme } else { Intent::Insert };
for f in std::mem::take(&mut raw.dropped_files) {
let files = files.clone();
spawn_local(async move {
let name = f.path().file_name().map(|n| n.to_string_lossy().to_string()).unwrap_or_else(|| "dropped".into());
match f.bytes_async().await {
Ok(b) => files.arrive(name, b, Intent::Insert),
Ok(b) => files.arrive(name, b, intent),
Err(e) => files.say(format!("{name}: {e}"), true),
}
});
+59 -52
View File
@@ -271,6 +271,10 @@ mod web {
!companion
});
for (name, bytes, intent) in incoming {
if intent == Intent::Theme {
solidcraft_ui_egui::prefs::import_theme_bytes(&mut self.app, bytes);
continue;
}
let design = solidcraft_engine::io::is_design_path(&name);
let path = if design && intent == Intent::Open {
// A design from the computer is kept in the browser (a copy), so Save works.
@@ -287,7 +291,7 @@ mod web {
};
match intent {
Intent::Open => self.app.open_path(&path),
Intent::Insert => self.app.drop_path(&path),
Intent::Insert | Intent::Theme => self.app.drop_path(&path),
}
self.files.panel.set(false);
}
@@ -353,7 +357,8 @@ mod web {
}
let mut act: Option<(&'static str, String)> = None;
let closed = solidcraft_ui_egui::ui_kit::Window::new(egui::Id::new("sc_browser_files"), "folder", "Files in this browser")
.cards(3.0)
// Room for long names; the kit still caps the window at the browser's width.
.cards(4.0)
.show_body(ctx, |ui| {
ui.horizontal(|ui| {
if ui_kit::button(ui, "Open from computer…", ui_kit::Button::Normal).clicked() {
@@ -381,61 +386,62 @@ mod web {
return;
}
let entries = self.files.entries.borrow().clone();
if entries.is_empty() {
ui.label("Designs you save appear here. They stay in this browser.");
}
egui::ScrollArea::vertical().max_height(360.0).show(ui, |ui| {
egui::Grid::new("opfs_files").num_columns(3).spacing([12.0, 6.0]).show(ui, |ui| {
// The name takes the width the size and the actions leave (#8097).
let empty = "Designs you save appear here. They stay in this browser.";
ui_kit::name_list(ui, "opfs_files", &["Name", "Size", "Actions"], empty, |list| {
for e in &entries {
match &mut self.renaming {
Some((from, to)) if *from == e.name => {
let r = ui_kit::cell_editor(ui, ui.make_persistent_id(("stored_file_name", from.as_str())), to, "", false);
if std::mem::take(&mut self.rename_focus) {
r.request_focus();
}
if r.lost_focus() {
act = Some(if ui.input(|i| i.key_pressed(egui::Key::Enter)) {
("rename", to.clone())
} else {
("rename_cancel", String::new())
});
list.row(&e.name, |row| {
match &mut self.renaming {
Some((from, to)) if *from == e.name => row.cell(|ui| {
let r =
ui_kit::cell_editor(ui, ui.make_persistent_id(("stored_file_name", from.as_str())), to, "", false);
if std::mem::take(&mut self.rename_focus) {
r.request_focus();
}
if r.lost_focus() {
act = Some(if ui.input(|i| i.key_pressed(egui::Key::Enter)) {
("rename", to.clone())
} else {
("rename_cancel", String::new())
});
}
}),
_ => {
row.name(&e.name);
}
}
_ => {
ui.label(&e.name);
}
}
ui.label(format!("{:.1} KB", e.size as f64 / 1024.0));
ui.horizontal(|ui| {
if ui_kit::button(ui, "Open", ui_kit::Button::Small).clicked() {
act = Some(("open", e.name.clone()));
}
let design = solidcraft_engine::io::is_design_path(&e.name);
if !design
&& ui_kit::button(ui, "Insert", ui_kit::Button::Small)
.on_hover_text(solidcraft_ui_egui::i18n::tr("web.files.insert_stored_drawings_hint"))
row.cell(|ui| ui.label(format!("{:.1} KB", e.size as f64 / 1024.0)));
row.cell(|ui| {
if ui_kit::button(ui, "Open", ui_kit::Button::Small).clicked() {
act = Some(("open", e.name.clone()));
}
let design = solidcraft_engine::io::is_design_path(&e.name);
if !design
&& ui_kit::button(ui, "Insert", ui_kit::Button::Small)
.on_hover_text(solidcraft_ui_egui::i18n::tr("web.files.insert_stored_drawings_hint"))
.clicked()
{
act = Some(("insert", e.name.clone()));
}
if ui_kit::button(ui, "Rename", ui_kit::Button::Small).clicked() {
self.renaming = Some((e.name.clone(), e.name.clone()));
self.rename_focus = true;
}
if ui_kit::button(ui, "Save to computer…", ui_kit::Button::Small)
.on_hover_text("A copy in a file you choose; the stored design stays here")
.clicked()
{
act = Some(("insert", e.name.clone()));
}
if ui_kit::button(ui, "Rename", ui_kit::Button::Small).clicked() {
self.renaming = Some((e.name.clone(), e.name.clone()));
self.rename_focus = true;
}
if ui_kit::button(ui, "Save to computer…", ui_kit::Button::Small)
.on_hover_text("A copy in a file you choose; the stored design stays here")
.clicked()
{
act = Some(("save_copy", e.name.clone()));
}
if ui_kit::button(ui, "Download", ui_kit::Button::Small).clicked() {
act = Some(("download", e.name.clone()));
}
if ui_kit::button(ui, "Delete", ui_kit::Button::Small).clicked() {
act = Some(("delete", e.name.clone()));
}
{
act = Some(("save_copy", e.name.clone()));
}
if ui_kit::button(ui, "Download", ui_kit::Button::Small).clicked() {
act = Some(("download", e.name.clone()));
}
if ui_kit::button(ui, "Delete", ui_kit::Button::Small).clicked() {
act = Some(("delete", e.name.clone()));
}
});
});
ui.end_row();
}
});
});
@@ -630,7 +636,8 @@ mod web {
ctx.request_repaint_after(delay);
}
if self.launch.persists() {
files::take_drops(&self.files, raw);
let theme = solidcraft_ui_egui::prefs::theme_drop_target(&self.app, ctx);
files::take_drops(&self.files, raw, theme);
} else {
raw.dropped_files.clear();
}
+5
View File
@@ -96,6 +96,11 @@ libc = "0.2"
[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
winit = { version = "0.30", default-features = false, features = ["x11"] }
# Bringing the window forward on X11 when a close asks about unsaved designs (src/come_forward.rs):
# the window's id, and the window manager request winit doesn't send (MIT OR Apache-2.0; both
# already in the tree through eframe and winit).
raw-window-handle = "0.6"
x11rb = { version = "0.13", default-features = false }
[build-dependencies]
embed-resource = "3.0.11"
+234
View File
@@ -0,0 +1,234 @@
//! Bringing the window forward when a close stops at "save changes?".
//!
//! A close from the taskbar or a window switcher reaches the window while another app has the
//! focus. The prompt it opens is only seen once the window comes forward, so the window asks for
//! the focus then. A window the user is already in is left alone.
//!
//! winit's Focus asks as an application, which a window manager with focus-stealing prevention
//! (KWin's default) refuses for a window used before the switch away: it only marks the taskbar
//! entry. On X11 the request is sent again with the source EWMH gives "direct user actions"
//! (`_NET_ACTIVE_WINDOW`, source 2), which is what this is: the prompt is the rest of the user's
//! close. Native Wayland has no way for a window to raise itself, so there the attention request
//! (xdg-activation) lets the compositor raise it or mark its taskbar entry.
//!
//! When: not at once. KWin raises the window, then the taskbar's closing context menu hands the
//! focus back to the app that had it, a few milliseconds later, and the window would flicker
//! forward and back. So the window asks once the menu is gone, `FIRST_AFTER` the close. It asks
//! again only if the focus is taken back right after it came (a slow menu) or never came; a later
//! switch is the user's own, and the window stays where the user put it.
use std::time::{Duration, Instant};
/// From the close to the first request: past the taskbar menu's focus hand-back (2 to 11 ms on
/// KDE Plasma 6), too short to notice.
const FIRST_AFTER: Duration = Duration::from_millis(120);
/// After the first request, how long the window asks again when it loses the focus: short of
/// anything the user does next.
const KEEP_ASKING: Duration = Duration::from_millis(400);
/// The least time between two requests.
const AGAIN_AFTER: Duration = Duration::from_millis(100);
/// Focus lost this soon after a request was taken back by the taskbar menu; later, by the user.
const TAKEN_BACK_WITHIN: Duration = Duration::from_millis(50);
/// The window coming forward after a close that asks about unsaved designs.
#[derive(Default)]
pub struct ComeForward {
/// The first request and the end of asking; `None`: not asking.
window: Option<(Instant, Instant)>,
/// The last request.
last: Option<Instant>,
/// The window has had the focus since the last request.
held: bool,
}
/// What a frame does while the window is coming forward.
#[derive(Debug, PartialEq)]
enum Step {
/// Ask for the focus now.
Ask,
/// Look again after this long.
Wait(Duration),
/// Done asking.
Done,
}
impl ComeForward {
/// A close stopped at the prompt: ask for the focus shortly.
pub fn start(&mut self, now: Instant) {
let first = now + FIRST_AFTER;
self.window = Some((first, first + KEEP_ASKING));
self.last = None;
self.held = false;
}
/// Every frame: ask once the taskbar menu is gone, and again while the focus is taken back.
pub fn tick(&mut self, ctx: &egui::Context, frame: &eframe::Frame) {
if self.window.is_none() {
return;
}
let (focused, minimized) = ctx.input(|i| (i.viewport().focused, i.viewport().minimized));
// The app may be idle: a frame to look again.
match self.step(Instant::now(), focused) {
Step::Ask => {
bring(ctx, frame, minimized);
ctx.request_repaint_after(AGAIN_AFTER);
}
Step::Wait(after) => ctx.request_repaint_after(after),
Step::Done => {}
}
}
fn step(&mut self, now: Instant, focused: Option<bool>) -> Step {
let Some((first, until)) = self.window else { return Step::Done };
if now >= until {
self.window = None;
return Step::Done;
}
if now < first {
return Step::Wait(first - now);
}
let Some(last) = self.last else {
if focused == Some(true) {
// The user went back to the window already.
self.window = None;
return Step::Done;
}
self.last = Some(now);
return Step::Ask;
};
if focused == Some(true) {
self.held = true;
return Step::Wait(until - now);
}
if self.held {
if now.duration_since(last) >= TAKEN_BACK_WITHIN {
// The user switched away: leave the window there.
self.window = None;
return Step::Done;
}
self.held = false;
}
let next = last + AGAIN_AFTER;
if now < next {
return Step::Wait(next - now);
}
self.last = Some(now);
Step::Ask
}
}
/// Ask for the focus once.
fn bring(ctx: &egui::Context, frame: &eframe::Frame, minimized: Option<bool>) {
#[cfg(all(unix, not(target_os = "macos")))]
let raised = match x11_activate(frame) {
Ok(sent) => sent,
Err(e) => {
log::warn!("bringing the window forward through X11: {e}");
false
}
};
#[cfg(not(all(unix, not(target_os = "macos"))))]
let raised = {
let _ = frame;
false
};
for c in commands(minimized, raised) {
ctx.send_viewport_cmd(c);
}
}
/// The viewport commands for a window in the background; `raised`: the X11 request went out,
/// which also restores a minimized window.
fn commands(minimized: Option<bool>, raised: bool) -> Vec<egui::ViewportCommand> {
if raised {
return vec![egui::ViewportCommand::Focus];
}
let mut commands = Vec::new();
if minimized == Some(true) {
commands.push(egui::ViewportCommand::Minimized(false));
}
commands.push(egui::ViewportCommand::Focus);
commands.push(egui::ViewportCommand::RequestUserAttention(egui::UserAttentionType::Informational));
commands
}
/// Ask the X11 window manager to activate the window as a user action. `Ok(false)`: the window
/// isn't an X11 window (native Wayland).
#[cfg(all(unix, not(target_os = "macos")))]
fn x11_activate(frame: &eframe::Frame) -> Result<bool, String> {
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
use x11rb::connection::Connection;
use x11rb::protocol::xproto::{ClientMessageEvent, ConnectionExt, EventMask};
let handle = frame.window_handle().map_err(|e| e.to_string())?;
let window = match handle.as_raw() {
RawWindowHandle::Xlib(h) => u32::try_from(h.window).map_err(|e| e.to_string())?,
RawWindowHandle::Xcb(h) => h.window.get(),
_ => return Ok(false),
};
// A connection of its own: winit's isn't reachable, and a close that asks is rare.
let (conn, screen) = x11rb::connect(None).map_err(|e| e.to_string())?;
let root = conn.setup().roots.get(screen).ok_or("no X11 screen")?.root;
let atom = conn.intern_atom(false, b"_NET_ACTIVE_WINDOW").map_err(|e| e.to_string())?.reply().map_err(|e| e.to_string())?.atom;
// Source 2: a direct user action; the time is the server's current time.
let event = ClientMessageEvent::new(32, window, atom, [2, x11rb::CURRENT_TIME, 0, 0, 0]);
conn.send_event(false, root, EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY, event).map_err(|e| e.to_string())?;
conn.flush().map_err(|e| e.to_string())?;
Ok(true)
}
#[cfg(test)]
mod tests {
use super::{AGAIN_AFTER, ComeForward, FIRST_AFTER, KEEP_ASKING, Step};
use eframe::egui::{UserAttentionType, ViewportCommand as C};
use std::time::{Duration, Instant};
/// The first request waits until the taskbar menu has handed the focus back. The window asks
/// again when the focus is taken back right after it came, or never came, no more often than
/// every `AGAIN_AFTER` and only for `KEEP_ASKING`; a later switch away is the user's.
#[test]
fn the_window_asks_once_the_taskbar_menu_is_gone() {
let t0 = Instant::now();
let ms = |n: u64| Duration::from_millis(n);
let at = |n: u64| t0 + ms(n);
let (first, again, keep) = (FIRST_AFTER.as_millis() as u64, AGAIN_AFTER.as_millis() as u64, KEEP_ASKING.as_millis() as u64);
let mut f = ComeForward::default();
assert_eq!(f.step(t0, Some(false)), Step::Done, "not started");
f.start(t0);
assert_eq!(f.step(t0, Some(false)), Step::Wait(FIRST_AFTER), "the menu is still closing");
assert_eq!(f.step(at(5), Some(false)), Step::Wait(ms(first - 5)));
assert_eq!(f.step(at(first), Some(false)), Step::Ask);
assert_eq!(f.step(at(first + 3), Some(true)), Step::Wait(ms(keep - 3)), "raised");
// A slow menu takes the focus back 10 ms later: ask again, not before AGAIN_AFTER.
assert_eq!(f.step(at(first + 10), Some(false)), Step::Wait(ms(again - 10)));
assert_eq!(f.step(at(first + again), Some(false)), Step::Ask);
assert_eq!(f.step(at(first + again + 3), Some(true)), Step::Wait(ms(keep - again - 3)));
// The user clicks another app 200 ms later: the window stays behind.
assert_eq!(f.step(at(first + again + 200), Some(false)), Step::Done);
assert_eq!(f.step(at(first + again + 300), Some(false)), Step::Done);
// Never raised (the request was refused): ask again every AGAIN_AFTER, for KEEP_ASKING.
f.start(t0);
assert_eq!(f.step(at(first), None), Step::Ask, "unknown focus counts as out of focus");
assert_eq!(f.step(at(first + again), Some(false)), Step::Ask);
assert_eq!(f.step(at(first + keep), Some(false)), Step::Done);
// Back in the window before the first request: nothing to do.
f.start(t0);
assert_eq!(f.step(at(first), Some(true)), Step::Done);
}
/// Without the X11 request: focus, and the attention mark where focus is refused; a minimized
/// window is restored first.
#[test]
fn a_window_closed_from_the_background_comes_forward() {
let forward = [C::Focus, C::RequestUserAttention(UserAttentionType::Informational)];
assert_eq!(super::commands(Some(false), false), forward);
assert_eq!(super::commands(None, false), forward, "unknown counts as not minimized");
let minimized = super::commands(Some(true), false);
assert_eq!(minimized.first(), Some(&C::Minimized(false)));
assert_eq!(minimized.get(1..), Some(&forward[..]));
// The window manager took the X11 request: nothing left to mark.
assert_eq!(super::commands(Some(true), true), [C::Focus]);
}
}
+10
View File
@@ -20,6 +20,7 @@
#[cfg(not(target_os = "macos"))]
#[path = "../../../assets/icons/app/shared/source/app_icon.rs"]
mod app_icon;
mod come_forward;
mod control_server;
mod device_lost;
#[cfg(target_os = "windows")]
@@ -84,6 +85,8 @@ struct App {
frames: u32,
/// Started over the control channel: the window doesn't ask for the foreground.
take_focus_unwanted: bool,
/// Coming forward after a close that asks about unsaved designs.
come_forward: come_forward::ComeForward,
/// The graphics device: lost, it can't draw again (`App::watch_device`, #4172).
gpu: Option<LostWatch>,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
@@ -139,7 +142,13 @@ impl eframe::App for App {
if ctx.input(|i| i.viewport().close_requested()) && !self.solve.quit_requested {
ctx.send_viewport_cmd(egui::ViewportCommand::CancelClose);
solidcraft_ui_egui::documents::request_quit(&mut self.solve);
// Closed from the taskbar or a window switcher while another app had the focus: the
// "save changes?" prompt is only seen once the window comes forward.
if !self.solve.quit_requested {
self.come_forward.start(std::time::Instant::now());
}
}
self.come_forward.tick(ctx, _frame);
#[cfg(target_os = "macos")]
for f in if self.solve.file_picker_busy() { Vec::new() } else { open_documents::take() } {
self.solve.open_path_async(&f);
@@ -1060,6 +1069,7 @@ fn main() -> eframe::Result {
starting,
frames: 0,
take_focus_unwanted: control_port.is_some(),
come_forward: come_forward::ComeForward::default(),
gpu,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
space_mouse,
@@ -105,6 +105,7 @@ eye false
fastener false
fillet false
finish false
finish_edit false
fit false
fit_section false
flange false
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Finish Edit</title>
<path d="M50 32L14 32M25 21L14 32L25 43" fill="none" stroke="#236ead" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 237 B

+88
View File
@@ -38,6 +38,7 @@
"All open designs": "كل التصاميم المفتوحة",
"Allowed expressions, separated by semicolons": "التعابير المسموح بها، مفصولة بفواصل منقوطة",
"Also deletes": "يحذف أيضًا",
"Also place them from the origin (fully constrained)": "وضعها أيضًا انطلاقًا من نقطة الأصل (مقيّدة بالكامل)",
"Anchor": "نقطة الإرساء",
"Angle 2": "الزاوية 2",
"Angle Display": "عرض الزاوية",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "تظهر هنا التصاميم التي تفتحها أو تحفظها.",
"Determined by To Object. Choose Angle to edit the angular extent.": "يحدده خيار «إلى كائن». اختر «زاوية» لتعديل الامتداد الزاوي.",
"Diameter": "القطر",
"Dimension new shapes": "إضافة أبعاد للأشكال الجديدة",
"Direction": "الاتجاه",
"Discard": "تجاهل",
"Distance": "المسافة",
@@ -196,6 +198,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "اسحب لتدوير المسند بخطوات 5°. اضغط Alt أو Ctrl لتدويره بحرية.",
"Drive Joint": "تحريك المفصل",
"Duration": "المدة",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "يحصل كل شكل جديد أيضًا على أبعاد من نقطة أصل الرسم حتى لا يبقى فيه شيء حر. لا يحصل الشكل المتصل مسبقًا بنقطة الأصل أو بهندسة موضوعة على أي منها.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "يحصل كل شكل ترسمه على جميع أبعاده بالمقاسات التي رسمتها (القيم المكتوبة لها الأولوية). يُستبعد المقاس الذي يحدده الرسم مسبقًا.",
"Edge": "حافة",
"Edges": "الحواف",
"Edit": "تعديل",
@@ -254,6 +258,8 @@
"Flanges": "الحواف المثنية",
"Flat Pattern": "النمط المسطح",
"Flat size": "الحجم المسطّح",
"Flat size X": "الحجم المسطّح X",
"Flat size Y": "الحجم المسطّح Y",
"Follow camera (Look At sketches)": "تتبّع الكاميرا (النظر إلى الرسومات)",
"Follow the camera (Look At sketches)": "تتبّع الكاميرا (النظر إلى الرسومات)",
"Font": "الخط",
@@ -812,7 +818,9 @@
"cmd.component_create": "مكوّن جديد",
"cmd.component_cycle_color": "تدوير لون المكوّن",
"cmd.component_delete": "حذف المكوّن",
"cmd.component_edit_in_place": "تحرير في المكان",
"cmd.component_extract": "استخراج إلى ملف",
"cmd.component_finish_edit": "إنهاء التحرير",
"cmd.component_from_bodies": "إنشاء مكوّنات من الأجسام",
"cmd.component_insert_design": "إدراج تصميم",
"cmd.component_links": "قائمة الروابط",
@@ -1171,6 +1179,7 @@
"cmd.view.render_dock": "نقل لوحة التصيير",
"cmd.view.render_focus": "عرض تركيز التصيير",
"cmd.view_ambient_occlusion": "الإظلال المحيطي",
"cmd.view_angle_readout": "زوايا العرض",
"cmd.view_apply": "استعادة عرض مسمّى",
"cmd.view_back": "العرض الخلفي",
"cmd.view_bottom": "العرض السفلي",
@@ -1305,6 +1314,7 @@
"help.appearance.assign": "يمنح الأجسام أو الأوجه أو المكونات المحددة لونًا أو مظهر مادة، من دون تغيير وزنها. استخدمه للتمييز بين القطع أو لمعاينة التشطيب.",
"help.attributions": "الإسنادات (ATTRIBUTION.md)",
"help.build": "الإصدار {version} · الإيداع {commit} · بُني في {date}",
"help.component.finish_edit": "يحفظ الجزء الذي تحرّره في مكانه، ويعود إلى تجميعه ويحدّث التجميع منه. استخدمه عند الانتهاء من تغييراتك على الجزء المرتبط.",
"help.connect_note": "أعد تشغيل كل مساعد لتحميل خادم SolidCraft. نُسخ كل ملف احتياطيًا بامتداد .bak قبل تغييره.",
"help.connect_title": "ربط مساعدي الذكاء الاصطناعي",
"help.face.delete": "يحذف الأوجه المحددة ويترك الأوجه المجاورة تسد الفجوة، أو يترك الفتحة مفتوحة كسطح. استخدمه لإزالة حافة مقوّسة أو ثقب أو نتوء يعترض الطريق.",
@@ -1782,8 +1792,12 @@
"prefs.layout_note": "المضغوط يثبّت اللوحات على حواف النافذة. شفافية المستعرض متاحة في الوضع العائم. غيّر جهة المساعد من صفحة المساعد.",
"prefs.left": "يسار",
"prefs.left_click": "نقر أيسر",
"prefs.linked_designs": "التصاميم المرتبطة",
"prefs.live_input": "الإدخال المباشر",
"prefs.live_preview": "المعاينة المباشرة",
"prefs.logo": "الشعار",
"prefs.logo_accent": "لون التمييز",
"prefs.logo_theme": "ألوان السمة",
"prefs.minutes": "دقائق",
"prefs.minutes_suffix": " دقيقة",
"prefs.mouse": "الفأرة ولوحة اللمس",
@@ -1832,6 +1846,10 @@
"prefs.sketch_selection": "الرسم والتحديد",
"prefs.sketch_selection_heading": "الرسم والتحديد",
"prefs.sketch_selection_note": "كيف تلتقط الرسومات وكيف تحدد النقرات.",
"prefs.sketch_tab_always": "إبقاء تبويب الرسم ظاهرًا",
"prefs.sketch_tab_always_note": "يبقى تبويب الرسم في الشريط بعد تبويب النموذج مباشرة حتى عندما لا يكون أي رسم مفتوحًا. عندها تبدأ أدوات الرسم فيه رسمًا على المستوي أو الوجه المحدد، أو على المستوي الذي تختاره بعد ذلك، وتكون الأداة جاهزة فيه.",
"prefs.sketch_tracking_guides": "أدلة محاذاة المراكز ونقاط المنتصف",
"prefs.sketch_tracking_guides_note": "مرّر المؤشر فوق مركز دائرة أو نقطة منتصف حافة مستقيمة، ثم حرّكه أفقيًا أو عموديًا لإظهار دليل منقّط مؤقت.",
"prefs.sketching": "الرسم",
"prefs.snap_drawing_note": "أثناء الرسم أو سحب نقطة في الرسم.",
"prefs.source": "المصدر",
@@ -1844,12 +1862,16 @@
"prefs.supersampling_brief": "يرسم العرض بحجم أكبر ثم يصغّره: حاد جدًا لكنه أثقل.",
"prefs.tab_accent_note": "لون التمييز يتبع التبويب النشط",
"prefs.theme_file": "ملف السمة",
"prefs.theme_file_or_paste": "ملف أو لصق",
"prefs.theme_follow": "اتباع ملف سمة",
"prefs.theme_follow_error": "لم يُطبّق: {error}. تبقى آخر سمة سليمة مفعّلة.",
"prefs.theme_follow_launch": "يُتّبع لهذه الجلسة فقط (--theme-file)؛ يُعاد تحميله كلما أعادت أداة أخرى كتابته.",
"prefs.theme_follow_note": "يُعاد تحميله كلما أعادت أداة أخرى كتابته. اختيار سمة يوقف اتباعه.",
"prefs.theme_follow_off": "إيقاف",
"prefs.theme_follow_stop": "إيقاف الاتباع",
"prefs.theme_import_hint": "انقر لاختيار ملف سمة، أو أفلت ملفًا هنا، أو اضغط Ctrl+V (Cmd+V على Mac) بعد نسخ سمة",
"prefs.theme_paste": "لصق السمة",
"prefs.theme_paste_none": "لا تحتوي الحافظة على سمة SolidCraft",
"prefs.timeline_half_hour": "−30 دقيقة",
"prefs.timeline_now": "الآن",
"prefs.timeline_quarter_hour": "−15",
@@ -1916,6 +1938,7 @@
"render.all_controls_help": "فحص مكثف لكل عناصر التحكم الحالية. صفحات الأقسام توفر تحريرًا مركّزًا دون تغيير الطلب الأساسي.",
"render.all_shots_label": "كل اللقطات",
"render.appearance_physics_separate": "المظهر المرئي لا يعيّن الكثافة ولا البيانات الحرارية ولا أي خصائص هندسية أخرى.",
"render.appearances": "المظاهر",
"render.availability_native": "تركيب أصلي؛ راجعه قبل التطبيق",
"render.availability_projection": "إسقاط مدعوم؛ راجع النطاق وما أُغفل",
"render.availability_reference": "بيانات مرجعية؛ ليست تعيينًا تلقائيًا",
@@ -1970,6 +1993,10 @@
"render.camera_set": "تعيين كاميرا التصيير",
"render.camera_target": "موضع الهدف · mm",
"render.camera_yaw": "الانعطاف",
"render.category_metal": "معدن",
"render.category_paint": "طلاء",
"render.category_plastic": "بلاستيك",
"render.category_wood": "خشب",
"render.chromatic_offset": "إزاحة لونية عند الحواف",
"render.clear_stage": "إزالة المنصة المحفوظة",
"render.copy_request": "نسخ JSON",
@@ -2069,6 +2096,7 @@
"render.effects_reset_lens": "إعادة ضبط تأثيرات العدسة",
"render.effects_seed": "بذرة النمط",
"render.emitted_axis": "المحور المنبعث",
"render.environment_tiles_require_raytrace": "تتطلب البيئات تتبّع الأشعة على المعالج أو بطاقة الرسومات. اخترْه في محرر المخرجات.",
"render.error_area_samples": "يجب أن تكون area_samples 1 أو 4 أو 16 أو 64",
"render.error_binding_allocation": "تعذّر حجز ربط المادة",
"render.error_body_bound": "معاينة المنتج تتجاوز حد الأجسام الملتقطة",
@@ -2140,6 +2168,8 @@
"render.flare_strength": "شدة وهج الإضاءات العالية",
"render.flare_threshold": "عتبة الوهج الخطية للمشهد",
"render.fold_browser": "طيّ المتصفح",
"render.frame_presets": "إعدادات مسبقة للإطار",
"render.frame_presets_pending": "تصل مع محرر اللقطة",
"render.gpu_depth": "أقصى عمق للمسار",
"render.gpu_options_help": "تُحفظ العيّنات والعمق والبذرة والتعريض مع هذا الإعداد. تُحفظ طريقة الصورة النشطة فقط.",
"render.gpu_path_failed": "متتبع المسارات على GPU غير متاح",
@@ -2211,8 +2241,12 @@
"render.lens_effects_title": "مستوحى من العدسات والتصوير",
"render.library_all": "الفهرس",
"render.library_all_states": "كل حالات التوفر",
"render.library_appearance_available": "مظهر متاح",
"render.library_applicable": "الموارد القابلة للتطبيق",
"render.library_applied": "طُبّق إسقاط المورد. افحص طلب التصيير الكامل قبل البدء.",
"render.library_apply_appearance": "تطبيق المظهر",
"render.library_apply_hdr": "الحفظ مع بيئة HDR هذه",
"render.library_apply_hint": "انقر للتطبيق · اسحب إلى النموذج",
"render.library_apply_maps": "استخدام خرائط سطح GPU المُعدّة",
"render.library_apply_studio": "حفظ إسقاط الاستوديو المُعدّ",
"render.library_apply_uniform": "تطبيق مظهر معتم موحّد",
@@ -2228,15 +2262,23 @@
"render.library_extent": "امتداد الموضوع",
"render.library_favorite": "إضافة إلى المفضلة",
"render.library_favorites": "المفضلة",
"render.library_filters": "الفهرس والتوفر",
"render.library_grid": "شبكة",
"render.library_hdr": "بيئات HDR المدمجة",
"render.library_hdr_help": "يضمّن HDR الأصلي في الإعداد المحفوظ. يُحوَّل أصل خط الطول المُعدّ صراحةً؛ ولا حاجة إلى ملف خارجي بعد الحفظ.",
"render.library_in_design": "في التصميم",
"render.library_inspect_only": "اختر للفحص؛ لا يُطبّق شيء تلقائيًا. المفضلة والسجل الحديث يخصّان جلسة المستند المفتوحة هذه.",
"render.library_ior": "معامل الانكسار",
"render.library_light_concepts": "مفاهيم الإضاءة",
"render.library_list": "قائمة",
"render.library_maps_help": "يمكن حفظ الخرائط المدمجة بمصادر مثبّتة وتعيين محلي للتواجدات. تبقى التجاوزات البصرية المؤقتة وضعًا منفصلًا.",
"render.library_material_concepts": "مفاهيم المواد",
"render.library_metallic": "معدنية",
"render.library_native_scenes": "الاستوديوهات الأصلية",
"render.library_next": "الصفحة التالية",
"render.library_omitted": "غير مضمّن",
"render.library_opacity": "العتامة",
"render.library_other": "مظاهر أخرى",
"render.library_physical_profiles": "ملفات المراجع الفيزيائية",
"render.library_previous": "الصفحة السابقة",
"render.library_quality_concepts": "مواصفات الجودة",
@@ -2246,6 +2288,7 @@
"render.library_results": "الموارد المطابقة",
"render.library_rig_help": "لاءم مرة واحدة عند مركز صريح وامتداد فيزيائي. الأطقم الكاملة تتضمن بطاقات سلبية؛ وتظل موانع المعايرة ترفض. يُفحص خلوص محافظ بين الباعثات والبطاقات قبل الحفظ.",
"render.library_rigs": "أطقم الإضاءة المُعدّة",
"render.library_roughness": "الخشونة",
"render.library_save_maps": "حفظ الخرائط في هذا الإعداد",
"render.library_scene_bounds": "استخدام حدود المشهد الملتقطة",
"render.library_scenes": "مواصفات المشاهد",
@@ -2269,6 +2312,7 @@
"render.library_unfavorite": "إزالة من المفضلة",
"render.library_uniform_ack": "استخدام التقريب الموحّد دون تأثيرات مكانية أو متقدمة",
"render.library_usable": "إسقاطات قابلة للتنفيذ",
"render.library_users": "المستخدمون",
"render.light_anchor_pending": "تغيير نظام إحداثيات الضوء غير مدعوم بعد.",
"render.lights_fixed_to": "الأضواء مثبّتة على",
"render.linear_help": "يحتفظ بنسخة أصلية RGBA بفاصلة عائمة 32 بت قبل إزالة التشويش والتعريض وتخطيط الدرجات والمرشحات والخلفية. sRGB/D65 خطي؛ مضروب مسبقًا في التغطية. تُقبل الذاكرة الإضافية صراحةً. بدون ضغط أو تمريرات إضافية.",
@@ -2487,6 +2531,7 @@
"render.scene_review": "الحل والمراجعة",
"render.scene_review_help": "راجع التركيب الأصلي الكامل قبل التطبيق. لا تُستبدل مواصفات SCENE المتقدمة غير المربوطة.",
"render.scene_scope_details": "نطاق التركيب",
"render.search_appearances": "ابحث في {count} مظهرًا",
"render.setup_legacy_environment": "يستخدم هذا الإعداد الأقدم دورانًا أو شدة قديمة للبيئة. يُحتفظ بتلك القيم؛ حوّلها صراحةً قبل حفظ مهمة صورة كاملة.",
"render.setup_name": "اسم الإعداد",
"render.setup_numeric_help": "يسجّل الحفظ طريقة الصورة النشطة وكل إعداداتها الرقمية. إعادة التحميل أو اختيار إعداد آخر يستبدل هذه المسودة؛ واستعد الكاميرا بشكل منفصل.",
@@ -2505,10 +2550,19 @@
"render.shot_remove_title": "إزالة اللقطة المحفوظة؟",
"render.shot_rename": "إعادة تسمية اللقطة المحفوظة",
"render.shot_saved_only": "احفظ المسودة الحالية أولًا. التكرار وإعادة التسمية يحافظان على الخيارات المحفوظة ومراجع الموارد بالضبط.",
"render.shots_camera_changed": "تغيّرت الكاميرا منذ حفظ هذه اللقطة",
"render.shots_name_help": "أدخل اسمًا فريدًا للقطة الحالية.",
"render.shots_no_result": "لا يوجد تصيير بعد",
"render.shots_result": "التصيير {number} · {width} × {height}",
"render.shots_revert": "استرجاع",
"render.shots_save": "حفظ اللقطة",
"render.shots_update": "تحديث اللقطة",
"render.show_shots_label": "إظهار شريط اللقطات",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "إعدادات الحجم المسبقة",
"render.size_presets_pending": "تصل مع محرر المخرجات",
"render.sky_ground": "الأرض · RGB خطي",
"render.sky_horizon": "الأفق · RGB خطي",
"render.sky_zenith": "السمت · RGB خطي",
@@ -2559,8 +2613,10 @@
"render.studio_sky_help": "تدرج سماء أصلي للإضاءة؛ وليس نموذجًا جويًا معايَرًا.",
"render.studio_sun": "الشمس",
"render.studio_sun_radius": "نصف القطر الزاوي",
"render.studio_tiles_require_gpu": "تتطلب الاستوديوهات تتبّع المسار على بطاقة الرسومات. اخترْ GPU في محرر المخرجات.",
"render.studio_title": "استوديو التصيير",
"render.studio_tone_map": "تخطيط الدرجات",
"render.studios_environments": "الاستوديوهات والبيئات",
"render.subsurface_enable": "مسار عشوائي للتشتت الداخلي",
"render.subsurface_help": "للعوازل المغلقة فقط. التشتت وامتصاص RGB معاملان منفصلان لكل mm. تتشتت المسارات داخل الهندسة الفعلية، ثم تنكسر أو تنعكس عند الحد. عطّل نفاذ الظل المستقيم وإزالة تشويش السطح والحجم الخارجي؛ واستخدم طبقة فرينل واحدة. ليس مظلل انتشار ولا شبكة كثافة ولا مادة مقيسة. الأوساط الكثيفة قد تحتاج مزيدًا من العيّنات وعمق المسار.",
"render.subsurface_rate": "معدل اصطدامات التشتت",
@@ -2668,6 +2724,7 @@
"select two components": "حدد مكوّنين اثنين",
"set by the sketch's lines": "تحدده خطوط الرسم",
"settings.display_quality_note": "المستويات الأدق ترسم الأوجه والحواف المنحنية بنعومة أكبر وتستغرق وقتًا أطول لإنشاء الشبكة. يتغير العرض فقط، لا التصميم ولا الملفات المصدّرة.",
"settings.double_click_components": "انقر نقرًا مزدوجًا على مكوّن لتنشيطه، أو لتحرير مكوّن مرتبط في مكانه",
"settings.frame_rate_details_note": "يضيف رسمًا لأزمنة الإطارات الأخيرة مع المثلثات المرسومة فوقه، ومدرّجًا تكراريًا لأزمنة الإطارات، وما رسمته وحدة GPU. انقر معدل الإطارات في العرض لإظهارها أو إخفائها.",
"settings.frame_rate_note": "يعرض الإطارات في الثانية في الزاوية اليمنى السفلية من العرض. أثناء تفعيله يُعاد رسم العرض باستمرار.",
"settings.measure_axis_distances": "إظهار المسافات على X/Y/Z",
@@ -2680,6 +2737,7 @@
"settings.reset_intro": "هذه الإعدادات لا تعمل على هذا الحاسوب وكانت ستمنع SolidCraft من البدء، لذا غُيّرت:",
"settings.reset_title": "تم تغيير الإعدادات",
"settings.supersampling_note": "يرسم العرض بدقة أعلى ثم يصفّيه: حواف وخطوط وشبكة أنعم على الشاشات الأقل من 4K. يكلّف وقتًا من معالج الرسوميات: نحو 2.25× من البكسلات عند 1.5× و4× عند 2×.",
"settings.update_changed_links": "تحديث التصاميم المرتبطة التي تغيّرت عند العودة إلى علامة التبويب",
"settings.window_system_details": "التفاصيل",
"settings.window_system_note_now": "يُطبَّق بعد إعادة التشغيل. الحالي: {now}.",
"settings.window_system_wayland_limited": "بعض الميزات محدودة على Wayland الأصلي.",
@@ -3283,6 +3341,24 @@
"ui.easyprint_uploading": "جارٍ الرفع إلى Printables…",
"ui.edit": "تعديل",
"ui.editJointLimits": "تعديل حدود المفصل",
"ui.edit_in_place": "تحرير في المكان",
"ui.edit_in_place_after_turn": "ينتهي التحرير عند انتهاء دور الوكيل",
"ui.edit_in_place_agent_busy": "لا يزال الوكيل يعمل في هذا التصميم؛ حاول مرة أخرى بعد انتهاء دوره",
"ui.edit_in_place_already_queued": "هناك تحرير ينتظر بالفعل انتهاء دور الوكيل",
"ui.edit_in_place_assembly_closed": "{name} لم يعد مفتوحًا",
"ui.edit_in_place_banner": "تحرير داخل {name}",
"ui.edit_in_place_busy": "أنهِ ما هو مفتوح أو ألغِه أولاً",
"ui.edit_in_place_none": "لا يُحرَّر أي تصميم مرتبط في مكانه",
"ui.edit_in_place_not_saved": "في الجزء تغييرات غير محفوظة؛ احفظه لإنهاء التحرير",
"ui.edit_in_place_open_elsewhere": "{name} مفتوح في نسخة أخرى من SolidCraft",
"ui.edit_in_place_opens_after_turn": "يُفتح الجزء عند انتهاء دور الوكيل",
"ui.edit_in_place_refresh_dropped": "تغيّر التجميع أثناء تحديث الروابط؛ شغّله مرة أخرى",
"ui.edit_in_place_refresh_stopped": "توقّف تحديث الروابط قبل أن ينتهي",
"ui.edit_in_place_refreshing": "جارٍ تحديث الروابط في {name}…",
"ui.edit_in_place_save_first": "احفظ التجميع أولاً: يُعثر على تصاميمه المرتبطة انطلاقًا من ملفه",
"ui.edit_in_place_save_waits": "يجري تحديث الروابط في {name}؛ احفظه بعد انتهائه",
"ui.edit_in_place_saved_elsewhere": "حُفظ الجزء في ملف آخر؛ ما زال التجميع مرتبطًا بـ {name}",
"ui.edit_in_place_wait": "انتظر حتى ينتهي ما يجري في التصميم",
"ui.edit_section_analysis": "تعديل تحليل المقطع",
"ui.ellipse": "قطع ناقص",
"ui.emboss_wrap_note": "تلتف ملامح الخطوط المتعامدة المماسة لأسطوانة مدعومة تلقائيًا. اختر جدارًا لتحديد الهدف.",
@@ -3357,6 +3433,7 @@
"ui.heading_edit": "تعديل",
"ui.heading_extrude": "بثق",
"ui.heading_fillet": "تقويس",
"ui.heading_finish_editing": "إنهاء التحرير",
"ui.heading_finish_sketch": "إنهاء الرسم",
"ui.heading_form": "تشكيل",
"ui.heading_front": "أمام",
@@ -3616,6 +3693,8 @@
"ui.restore_defaults": "استعادة الافتراضيات",
"ui.reverse_horizontal_pan_direction": "عكس اتجاه الإزاحة الأفقية",
"ui.reverse_horizontal_pan_tip": "التمرير الأفقي بإصبعين وعجلة الإبهام يزيحان في الاتجاه المعاكس",
"ui.reverse_vertical_pan_direction": "عكس اتجاه التحريك الرأسي",
"ui.reverse_vertical_pan_tip": "التمرير الرأسي بإصبعين يحرّك العرض في الاتجاه المعاكس",
"ui.reverse_zoom_direction": "عكس اتجاه التكبير",
"ui.revolutions": "عدد اللفات",
"ui.revolve": "دوران",
@@ -3761,6 +3840,15 @@
"ui.updateToCurrentView": "التحديث إلى العرض الحالي",
"ui.upload": "رفع",
"ui.vertical_constraint": "قيد رأسي",
"ui.view_angles": "زوايا العرض",
"ui.view_angles_convention": "درجات حول المحور العلوي. الانعراج 0° هو العرض الأمامي، و90° الأيسر، و−90° الأيمن، و180° الخلفي؛ الانحدار 90° هو العرض العلوي؛ والدوران الموجب يدير النموذج على الشاشة باتجاه عقارب الساعة.",
"ui.view_angles_help": "يعرض زوايا الانحدار والانعراج والدوران للعرض بالدرجات ونوع الإسقاط أسفل أداة الاتجاه. انقر على القراءة لكتابة زوايا دقيقة.",
"ui.view_angles_ortho": "متعامد",
"ui.view_angles_persp": "منظور",
"ui.view_angles_pitch": "الانحدار",
"ui.view_angles_readout": "الانحدار {pitch} · الانعراج {yaw} · الدوران {roll}",
"ui.view_angles_roll": "الدوران",
"ui.view_angles_yaw": "الانعراج",
"ui.view_centre": "مركز العرض",
"ui.viewport_theme_follow": "اتباع السمة",
"ui.visual_shaded_hidden_edges": "مظلل مع الحواف المخفية",
File diff suppressed because it is too large Load Diff
+4
View File
@@ -37,6 +37,7 @@
"All open designs": "Všechny otevřené návrhy",
"Allowed expressions, separated by semicolons": "Povolené výrazy oddělené středníkem",
"Also deletes": "Smaže také",
"Also place them from the origin (fully constrained)": "Také je umístit od počátku (plně zavazbené)",
"Anchor": "Kotva",
"Angle 2": "Úhel 2",
"Angle Display": "Zobrazení úhlu",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Zde se zobrazí návrhy, které otevřete nebo uložíte.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Určeno volbou K objektu. Pro úpravu úhlového rozsahu zvolte Úhel.",
"Diameter": "Průměr",
"Dimension new shapes": "Kótovat nové tvary",
"Direction": "Směr",
"Discard": "Zahodit",
"Distance": "Vzdálenost",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Přetažením otáčíte opěrku po krocích 5°. Podržením Alt nebo Ctrl ji otočíte volně.",
"Drive Joint": "Pohánět kloub",
"Duration": "Doba trvání",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Každý nový tvar se také okótuje od počátku skici, dokud v něm nic nezůstane volné. Tvar již připojený k počátku nebo k umístěné geometrii nedostane nic.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Každý nakreslený tvar dostane všechny své kóty v nakreslených velikostech (zadané hodnoty mají přednost). Velikost, kterou už skica určuje, se vynechá.",
"Edges": "Hrany",
"Edit": "Upravit",
"Edit Profile Sketch": "Upravit náčrt profilu",
+11
View File
@@ -33,6 +33,7 @@
"All open designs": "Alle åbne designs",
"Allowed expressions, separated by semicolons": "Tilladte udtryk adskilt af semikolon",
"Also deletes": "Sletter også",
"Also place them from the origin (fully constrained)": "Placer dem også fra origo (fuldt fastlåst)",
"Anchor": "Forankring",
"Angle 2": "Vinkel 2",
"Animate": "Animér",
@@ -158,6 +159,7 @@
"Designs you open or save appear here.": "Designs, du åbner eller gemmer, vises her.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Bestemmes af Til objekt. Vælg Vinkel for at ændre vinkeludstrækningen.",
"Diameter": "Diameter",
"Dimension new shapes": "Mål nye figurer",
"Direction": "Retning",
"Discard": "Kassér",
"Distance": "Afstand",
@@ -169,6 +171,8 @@
"Drag to move the hole; click to remove it": "Træk for at flytte hullet; klik for at fjerne det",
"Drive Joint": "Bevæg led",
"Duration": "Varighed",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Hver ny figur får også mål fra skitsens origo, indtil intet af den er frit. En figur, der allerede er knyttet til origo eller til placeret geometri, får ingen.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Hver figur, du tegner, får alle sine mål i de størrelser, du tegnede (indtastede værdier vinder). En størrelse, som skitsen allerede fastlægger, udelades.",
"Edges": "Kanter",
"Edit": "Redigér",
"Edit Profile Sketch": "Redigér profilskitse",
@@ -1395,6 +1399,13 @@
"render.return_design": "Tilbage til Design",
"render.save_setup": "Gem opsætning",
"render.setup_name": "Opsætningsnavn",
"render.shots_camera_changed": "Kameraet er ændret, siden denne optagelse blev gemt",
"render.shots_name_help": "Indtast et unikt navn til den aktuelle optagelse.",
"render.shots_no_result": "Ingen rendering endnu",
"render.shots_result": "Rendering {number} · {width} × {height}",
"render.shots_revert": "Gendan",
"render.shots_save": "Gem optagelse",
"render.shots_update": "Opdater optagelse",
"render.unavailable_preview": "Denne opsætning bruger en type forhåndsvisning, der ikke er tilgængelig.",
"render.unsaved": "Ændringer i forhåndsvisning er ikke gemt",
"render.use_preview": "Brug integreret forhåndsvisning",
+216 -2
View File
@@ -38,6 +38,7 @@
"All open designs": "Alle geöffneten Designs",
"Allowed expressions, separated by semicolons": "Zulässige Ausdrücke, durch Semikolons getrennt",
"Also deletes": "Löscht auch",
"Also place them from the origin (fully constrained)": "Auch vom Ursprung aus platzieren (vollständig bestimmt)",
"Anchor": "Anker",
"Angle 2": "Winkel 2",
"Angle Display": "Winkelanzeige",
@@ -179,6 +180,7 @@
"Designs you open or save appear here.": "Designs, die Sie öffnen oder speichern, erscheinen hier.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Bestimmt durch Bis Objekt. Wählen Sie Winkel, um den Winkelbereich zu bearbeiten.",
"Diameter": "Durchmesser",
"Dimension new shapes": "Neue Formen bemaßen",
"Direction": "Richtung",
"Discard": "Verwerfen",
"Distance": "Abstand",
@@ -187,9 +189,16 @@
"Don't ask again": "Nicht mehr fragen",
"Double-click to rename": "Double-click to rename",
"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": "Doppelklick mit der mittleren Taste in der Ansicht: Home (Startansicht, zeigt alles Sichtbare), Einpassen (Sichtbares einpassen, Ausrichtung beibehalten) oder nichts",
"Drag to move the boss across the model. It snaps to sketch points on the face.": "Ziehen, um den Ansatz über das Modell zu verschieben. Er rastet an Skizzenpunkten auf der Fläche ein.",
"Drag to move the hole; click to remove it": "Ziehen, um die Bohrung zu verschieben; anklicken, um sie zu entfernen",
"Drag to move the rest across the model. It snaps to sketch points on the face.": "Ziehen, um die Auflage über das Modell zu verschieben. Sie rastet an Skizzenpunkten auf der Fläche ein.",
"Drag to move the snap fit across the model. It snaps to sketch points on the face.": "Ziehen, um die Rastverbindung über das Modell zu verschieben. Sie rastet an Skizzenpunkten auf der Fläche ein.",
"Drag to point the catch in another direction.": "Ziehen, um den Rasthaken anders auszurichten.",
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Ziehen, um die Auflage in 5°-Schritten zu drehen. Alt oder Strg gedrückt halten, um sie stufenlos zu drehen.",
"Drive Joint": "Gelenk antreiben",
"Duration": "Dauer",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Jede neue Form wird zusätzlich vom Skizzenursprung aus bemaßt, bis nichts mehr frei ist. Eine Form, die schon am Ursprung oder an platzierter Geometrie hängt, erhält keine.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Jede gezeichnete Form erhält alle ihre Bemaßungen in den gezeichneten Größen (eingegebene Werte haben Vorrang). Eine Größe, die die Skizze bereits festlegt, wird ausgelassen.",
"Edge": "Kante",
"Edges": "Kanten",
"Edit": "Bearbeiten",
@@ -472,6 +481,8 @@
"Rename Feature": "Merkmal umbenennen",
"Rename Folder": "Ordner umbenennen",
"Render Stage": "Renderphase",
"Reopen designs": "Designs erneut öffnen",
"Reopen the designs that were open when SolidCraft was last closed": "Die Designs erneut öffnen, die beim letzten Beenden von SolidCraft geöffnet waren",
"Replace existing library file": "Vorhandene Bibliotheksdatei ersetzen",
"Report a bug — review a screenshot and open a GitHub draft": "Fehler melden — Screenshot prüfen und einen GitHub-Entwurf öffnen",
"Report text copied. Paste it into GitHub and submit your report there.": "Berichtstext kopiert. Fügen Sie ihn auf GitHub ein und reichen Sie den Bericht dort ein.",
@@ -713,6 +724,8 @@
"ai.prefs.background_commands": "Agentenbefehle im Hintergrund ausführen",
"ai.prefs.connect_apps": "SolidCraft für KI-Apps auf diesem Computer verfügbar machen",
"ai.prefs.connect_apps_note": "Trägt SolidCraft beim Start als MCP-Server in die auf diesem Computer gefundenen KI-Apps ein (OpenCode, Claude Desktop, Claude Code, Cursor, Codex, Gemini CLI, Copilot CLI, Windsurf, Zed, VS Code), damit ein Agent es ohne Einrichtung nutzen kann. Nur der Eintrag „solidcraft“ wird hinzugefügt oder sein Pfad aktualisiert; ein von Ihnen geänderter Eintrag bleibt unberührt, und die Datei wird vorher gesichert. Aus: Die hinzugefügten Einträge werden entfernt. Hilfe > KI-Assistenten verbinden… erledigt das von Hand.",
"ai.prefs.connect_at_start": "Zuletzt verwendeten Agenten beim Start von SolidCraft verbinden",
"ai.prefs.connect_at_start_note": "Verbindet beim Start von SolidCraft automatisch den zuletzt verwendeten Agenten (oder den Standardagenten) im Hintergrund, damit er für den Chat bereitsteht. Diese Funktion ist deaktiviert, wenn SolidCraft mit --control gestartet wird. Kann keine Verbindung hergestellt werden, zeigt der Assistent „Verbindung fehlgeschlagen“ und eine Schaltfläche zum erneuten Verbindungsversuch an.",
"ai.prefs.follow_camera": "Kamera zu Skizzen drehen",
"ai.prefs.follow_camera_off": "Die automatische Kameraführung ist aus.",
"ai.prefs.follow_camera_on": "Die Kamera dreht sich zu Skizzen, die der Agent erstellt.",
@@ -720,6 +733,8 @@
"ai.prefs.make_default": "Standardmäßig verwenden",
"ai.prefs.no_agents": "Noch keine Agenten. Fügen Sie einen Agenten hinzu oder aktualisieren Sie, um installierte Agenten zu finden.",
"ai.prefs.no_saved_approvals": "Keine gespeicherten Freigaben.",
"ai.prefs.open_at_start": "Assistentenbereich beim Start von SolidCraft öffnen",
"ai.prefs.open_at_start_note": "Öffnet beim Start von SolidCraft automatisch den Assistentenbereich oder dessen separates Fenster. Diese Funktion ist deaktiviert, wenn SolidCraft mit --control gestartet wird.",
"ai.prefs.override_all_warning": "Dieser Agent darf das Design ohne Rückfrage speichern, überschreiben, exportieren oder ersetzen.",
"ai.prefs.permission_all": "Alles erlauben",
"ai.prefs.permission_all_summary": "Verfügbare SolidCraft-Werkzeuge werden ohne Rückfrage ausgeführt.",
@@ -796,10 +811,13 @@
"cmd.component_break_link": "Verknüpfung trennen",
"cmd.component_capture_position": "Position erfassen",
"cmd.component_copies": "Identische Kopien finden",
"cmd.component_copy_bodies": "Körper einfügen",
"cmd.component_create": "Neue Komponente",
"cmd.component_cycle_color": "Komponentenfarbe wechseln",
"cmd.component_delete": "Komponente löschen",
"cmd.component_edit_in_place": "An Ort und Stelle bearbeiten",
"cmd.component_extract": "In Datei extrahieren",
"cmd.component_finish_edit": "Bearbeitung beenden",
"cmd.component_from_bodies": "Komponenten aus Körpern erstellen",
"cmd.component_insert_design": "Konstruktion einfügen",
"cmd.component_links": "Verknüpfungen auflisten",
@@ -877,6 +895,7 @@
"cmd.file_insert_step": "STEP einfügen",
"cmd.file_open_in_easyprint": "Mit EasyPrint öffnen",
"cmd.file_save_mesh": "Als Netz speichern",
"cmd.file_send_to_slicer": "An Slicer senden",
"cmd.file_slicers": "Installierte Slicer",
"cmd.frame_member": "Rahmenelement",
"cmd.frame_profile_insert": "Profil einfügen",
@@ -948,6 +967,7 @@
"cmd.occurrence_ground": "Festsetzen",
"cmd.occurrence_move": "Instanz verschieben",
"cmd.occurrence_properties": "Physikalische Eigenschaften der Instanz",
"cmd.occurrence_reparent": "In andere Komponente verschieben",
"cmd.parameters_add": "Benutzerparameter hinzufügen",
"cmd.parameters_change": "Parameter ändern",
"cmd.parameters_comment": "Parameter kommentieren",
@@ -966,7 +986,7 @@
"cmd.parts_library": "Standardbauteile",
"cmd.parts_resize": "Bauteilgröße ändern",
"cmd.plastic_assign_rule": "Kunststoffregel zuweisen",
"cmd.plastic_boss": "Erhöhung",
"cmd.plastic_boss": "Ansatz",
"cmd.plastic_lip": "Lippe",
"cmd.plastic_manage_rules": "Kunststoffregeln verwalten",
"cmd.plastic_rest": "Auflage",
@@ -1030,6 +1050,7 @@
"cmd.sheet_refold": "Wieder falten",
"cmd.sheet_rules": "Blechregeln auflisten",
"cmd.sheet_unfold": "Entfalten",
"cmd.sketch_arc3d": "3D-Bogen",
"cmd.sketch_arc_center_point": "Mittelpunkt-Kreisbogen",
"cmd.sketch_arc_tangent": "Tangentialbogen",
"cmd.sketch_arc_three_point": "3-Punkt-Kreisbogen",
@@ -1058,6 +1079,7 @@
"cmd.sketch_drag": "Skizzengeometrie ziehen",
"cmd.sketch_drag_end": "Skizzen-Ziehen beenden",
"cmd.sketch_draw_dimensioned": "Skizzengeometrie mit Maßen zeichnen",
"cmd.sketch_drawing_bounds": "Zeichnungsgröße",
"cmd.sketch_edit": "Skizze bearbeiten",
"cmd.sketch_edit_text": "Text bearbeiten",
"cmd.sketch_export_dxf": "Als DXF speichern",
@@ -1154,22 +1176,31 @@
"cmd.view.render_dock": "Render-Panel verschieben",
"cmd.view.render_focus": "Render-Fokusansicht",
"cmd.view_ambient_occlusion": "Umgebungsverdeckung",
"cmd.view_angle_readout": "Ansichtswinkel",
"cmd.view_apply": "Benannte Ansicht wiederherstellen",
"cmd.view_back": "Rückansicht",
"cmd.view_bottom": "Untersicht",
"cmd.view_delete": "Benannte Ansicht löschen",
"cmd.view_fit": "Ansicht einpassen",
"cmd.view_front": "Vorderansicht",
"cmd.view_graphics_preset": "Grafikprofil",
"cmd.view_grid": "Raster",
"cmd.view_ground_shadow": "Bodenschatten",
"cmd.view_home": "Startansicht",
"cmd.view_isometric": "Isometrische Ansicht",
"cmd.view_left": "Linke Seitenansicht",
"cmd.view_list": "Benannte Ansichten auflisten",
"cmd.view_navigate": "Ansicht navigieren",
"cmd.view_navigation_bar": "Navigationsleiste",
"cmd.view_normal_to": "Senkrecht zur Auswahl",
"cmd.view_rename": "Benannte Ansicht umbenennen",
"cmd.view_right": "Rechte Seitenansicht",
"cmd.view_save": "Neue benannte Ansicht",
"cmd.view_shots_strip": "Aufnahmenleiste",
"cmd.view_spin": "Ansicht kontinuierlich drehen",
"cmd.view_tool": "Navigationswerkzeug",
"cmd.view_top": "Draufsicht",
"cmd.view_visual_style": "Darstellungsstil",
"color.copy": "Klicken, um Farbwerte zu kopieren",
"color.edit": "Klicken, um Farbe zu bearbeiten",
"color.gamma": "Farbwerte im Gammaraum 0-255 anzeigen",
@@ -1239,6 +1270,7 @@
"document.save_changes": "Änderungen in {name} speichern?",
"document.save_copy": "Kopie speichern…",
"document.unsaved_changes": "{name} enthält ungespeicherte Änderungen. Wenn Sie nicht speichern, gehen sie verloren.",
"drive.rigid": "{joint} ist ein starres Gelenk. Es hält die verbundenen Teile fest zusammen und ermöglicht daher keine Bewegung. Um die Teile beweglich zu machen, ändern Sie den Gelenktyp unter „Gelenk bearbeiten“: Drehgelenk für Drehbewegungen, Schubgelenk für lineare Bewegungen oder Zylindergelenk für beides.",
"drive.stopped_by_contact": "Angehalten bei {value}: {a} würde {b} durchdringen",
"drive.stopped_by_loop": "Angehalten bei {value}: die Schleife über {joint} lässt sich nicht weiter schließen",
"drive.unconnected": "Bewegt nichts: {part} ist mit nichts Festgesetztem verbunden",
@@ -1278,6 +1310,7 @@
"help.apache": "Apache-Lizenz 2.0",
"help.attributions": "Quellenangaben (ATTRIBUTION.md)",
"help.build": "Version {version} · Commit {commit} · erstellt am {date}",
"help.component.finish_edit": "Speichert das an Ort und Stelle bearbeitete Teil, kehrt zu seiner Baugruppe zurück und aktualisiert die Baugruppe daraus. Verwenden Sie es, wenn Ihre Änderungen am verknüpften Teil fertig sind.",
"help.connect_note": "Starten Sie jeden Assistenten neu, damit er den SolidCraft-Server lädt. Jede Datei wurde vor der Änderung als .bak gesichert.",
"help.connect_title": "KI-Assistenten verbinden",
"help.font_details": "Die Oberfläche verwendet die integrierten Schriftarten von egui (Ubuntu Light und Hack unter der Ubuntu Font Licence und der MIT/Bitstream-Vera-Lizenz; Noto Emoji und die Emoji-Symbolschrift unter OFL und MIT). Skizzentext verwendet Liberation Sans (SIL OFL 1.1). Das optionale Schriftpaket craft-fonts von The Crafting Apps (BIZ UDPGothic, Shippori Mincho, BIZ UDMincho, Noto Sans CJK SC, Noto Sans Arabic; SIL OFL 1.1) ist nicht in SolidCraft-Builds enthalten.",
@@ -1298,6 +1331,26 @@
"help.solid.shell": "Höhlt einen Körper aus, lässt Wände in der eingestellten Dicke stehen und kann gewählte Flächen öffnen. Für Kästen, Deckel und andere dünnwandige Teile.",
"help.solid.sweep": "Führt ein Skizzenprofil entlang eines Pfads und erzeugt so einen Körper. Für Rohre, Schienen, Griffe und alle Teile mit gleichbleibendem Querschnitt entlang einer Kurve.",
"help.third_party": "Drittanbieterlizenzen",
"hole_presets.confirm_delete": "Löschen bestätigen",
"hole_presets.delete": "Löschen",
"hole_presets.delete_prompt": "Möchten Sie diese persönliche Vorlage wirklich löschen? Bereits vorhandene Bohrungen bleiben unverändert.",
"hole_presets.full": "Die persönliche Vorlagenbibliothek enthält bereits 64 Vorlagen.",
"hole_presets.invalid_name": "Geben Sie einen kurzen Namen ohne Zeilenumbrüche oder Steuerzeichen ein.",
"hole_presets.invalid_parameters": "Vervollständigen Sie die Bohrungsparameter mit gültigen Ausdrücken angemessener Länge.",
"hole_presets.missing": "Die ausgewählte Vorlage ist nicht mehr verfügbar.",
"hole_presets.name": "Vorlagenname",
"hole_presets.name_exists": "Eine Vorlage mit diesem Namen existiert bereits. Wählen Sie einen anderen Namen.",
"hole_presets.name_hint": "Eindeutigen Namen eingeben",
"hole_presets.overwrite": "Änderungen in der ausgewählten Vorlage speichern",
"hole_presets.preset": "Vorlage",
"hole_presets.recall": "Vorlage laden",
"hole_presets.rename": "Umbenennen",
"hole_presets.save": "Als neue Vorlage speichern",
"hole_presets.scope": "In Ihrem Profil gespeichert und für alle Projekte verfügbar.",
"hole_presets.select": "Vorlage auswählen",
"hole_presets.title": "Persönliche Vorlagen",
"hole_presets.unsupported_options": "Diese Vorlage enthält Gewindeoptionen, die in dieser Version nicht geladen werden können.",
"hole_presets.unsupported_overwrite": "Diese Vorlage enthält Optionen, die nicht sicher überschrieben werden können.",
"home.back": "Zurück zu {name}",
"home.crashes": "Absturzberichte",
"home.design_workspace": "Entwurf",
@@ -1568,6 +1621,10 @@
"navbar.visual_style": "Darstellung",
"navbar.zoom": "Zoomen",
"needs two joints": "benötigt zwei Gelenke",
"network.allow_once": "Einmalig erlauben",
"network.always_allow": "Diesen Server immer erlauben",
"network.prompt_detail": "Dieses Design verweist auf eine Datei auf dem Netzwerkcomputer {host}. Beim Öffnen wird eine Verbindung zu diesem Computer hergestellt. Dabei werden möglicherweise Ihre Windows-Anmeldedaten an ihn übermittelt. Erlauben Sie den Zugriff nur auf Server, denen Sie vertrauen.",
"network.prompt_title": "Netzwerkzugriff",
"new configuration": "neue Konfiguration",
"new parameter": "new parameter",
"no hole": "keine Bohrung",
@@ -1606,6 +1663,16 @@
"pattern.direction_1": "Richtung 1",
"pattern.direction_2": "Richtung 2",
"pattern.flip_direction": "Richtung umkehren",
"perf.click_for_details": "Für Details klicken: Frametime-Diagramm, Histogramm und Darstellung der GPU-Ausgabe",
"perf.draw_calls": "Draw Calls",
"perf.line_segments": "Liniensegmente",
"perf.low_1": "1-%-Tiefstwert",
"perf.renderer": "Renderer",
"perf.scene_build": "Szenenaufbau",
"perf.triangles": "Dreiecke",
"perf.ui_time": "UI-Zeit",
"perf.viewport": "Ansichtsfenster",
"perf.worst": "schlechtester Wert",
"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",
@@ -1622,30 +1689,110 @@
"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 the path": "Pfad auswählen",
"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.add_item": "Element hinzufügen",
"prefs.alt_frees_manipulators": "Alt / Option schaltet auch an Manipulatorpfeilen das Einrasten ab",
"prefs.anti_aliasing_amd_dx12": "Die Kantenglättung verwendet 1×, da der Starttest mit Multisampling keine Ausgabe erzeugt hat, während der Test mit 1× erfolgreich war. Sie können oben eine andere Einstellung wählen. Starten Sie SolidCraft neu, damit die Änderung übernommen wird, sofern der Test erfolgreich ist.",
"prefs.anti_aliasing_note": "Glättet gezackte Kanten.",
"prefs.applies_on_restart": "Wird nach einem Neustart übernommen",
"prefs.assistant": "Assistent",
"prefs.axes": "Achsen",
"prefs.axis": "Achse",
"prefs.bodies_folders": "Körperordner",
"prefs.bodies_folders_always": "Immer",
"prefs.bodies_folders_never": "Nie",
"prefs.bodies_folders_several": "Nur bei mehreren Körpern",
"prefs.bottom": "Unten",
"prefs.browser": "Browser",
"prefs.built_in": "Integriert",
"prefs.button_left": "Ziehen mit der linken Maustaste",
"prefs.button_middle": "Ziehen mit der mittleren Maustaste",
"prefs.button_right": "Ziehen mit der rechten Maustaste",
"prefs.choose_font": "Schriftdatei auswählen…",
"prefs.click": "Klicken",
"prefs.contact_shading": "Weiche Kontaktschattierung",
"prefs.contact_shading_note": "Erzeugt weiche Schatten an Stellen, an denen sich Bauteile nahekommen.",
"prefs.context_menu": "Kontextmenü",
"prefs.context_menu_ring": "Kontextmenü · Gedrückt halten, um das Radialmenü zu öffnen",
"prefs.cpu": "CPU (Software)",
"prefs.crash_reports": "Absturzberichte öffnen…",
"prefs.crash_reports_note": "Die Berichte bleiben auf diesem Computer. Sie enthalten das Design und die Befehle, mit denen sich das Problem reproduzieren lässt.",
"prefs.ctrl_cmd": "Strg / Cmd",
"prefs.curved_surfaces": "Gekrümmte Flächen",
"prefs.curves": "Gekrümmte Flächen",
"prefs.dead_zone_note": "Der schraffierte Bereich kennzeichnet die Totzone. Bewegungen innerhalb dieses Bereichs werden ignoriert.",
"prefs.default": "Standard",
"prefs.design": "Design-Vorgaben",
"prefs.design_note": "Legt fest, mit welchen Einstellungen neue Designs beginnen. Bereits geöffnete Designs behalten ihre eigenen Einstellungen.",
"prefs.devices": "3D-Maus",
"prefs.dialog_buttons": "Dialogschaltflächen",
"prefs.dialogs": "Dialoge",
"prefs.dialogs_edge": "Am Rand der Ansicht",
"prefs.dialogs_left_column": "In der linken Spalte",
"prefs.dialogs_note": "Wo Befehlsdialoge öffnen: am Rand der Ansicht angedockt oder in der linken Spalte anstelle von Browser und Verlauf, die beim Schließen des Dialogs wie zuvor zurückkehren.",
"prefs.display": "Anzeige",
"prefs.edges": "Kanten und Schattierung",
"prefs.extend": "Erweitern",
"prefs.extra_navigation": "Mit Strg und gedrückter linker Maustaste auf einer freien Fläche drehen. Leertaste gedrückt halten, um die Ansicht zu verschieben.",
"prefs.follows_os": "Wie im Betriebssystem",
"prefs.font": "Schrift",
"prefs.font_fallback": "Zeichen, die in der ausgewählten Schrift fehlen, werden mit der integrierten Ersatzschrift dargestellt. So werden keine Beschriftungen als leere Kästchen angezeigt.",
"prefs.font_sample": "Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich · Ø12,50 mm · 45,0° · 0123456789",
"prefs.font_unreadable": "Die ausgewählte Schriftdatei konnte nicht gelesen werden.",
"prefs.general": "Allgemein",
"prefs.general_note": "Sprache, Speichern und Updates.",
"prefs.gesture_orbit": "Ansicht drehen",
"prefs.gesture_pan": "Ansicht verschieben",
"prefs.gesture_zoom": "Ansicht zoomen",
"prefs.graphics": "Grafik",
"prefs.graphics_card": "Grafikkarte",
"prefs.graphics_card_auto": "Automatisch",
"prefs.graphics_card_missing": "Die gespeicherte Grafikkarte ist nicht verfügbar. Stattdessen wird „Automatisch“ verwendet.",
"prefs.graphics_card_restart": "Diese Einstellung wird nach einem Neustart von SolidCraft wirksam. Die Umgebungsvariable WGPU_ADAPTER_NAME hat Vorrang vor dieser Auswahl.",
"prefs.graphics_note": "Wägen Sie Leistung und Darstellungsqualität gegeneinander ab. Jede Option veranschaulicht ihre Wirkung anhand eines Beispiels.",
"prefs.graphics_presets_note": "Mit den Profilen werden die unten aufgeführten Optionen gemeinsam eingestellt.",
"prefs.history": "Verlauf",
"prefs.history_origin_bodies": "Ursprung und Körper oben zeigen",
"prefs.history_origin_bodies_note": "Der Verlauf links oder unter dem Browser beginnt mit dem Körper-Ordner der aktiven Komponente und dem Ursprung, mit Augen und Menüs wie im Browser. Der Verlauf unten bleibt unverändert.",
"prefs.history_sketches": "Skizzen",
"prefs.history_sketches_in_order": "In Erstellungsreihenfolge",
"prefs.history_sketches_note": "Wenn „Skizzen“ auf „Unter dem zugehörigen Feature“ eingestellt ist, wird jede Skizze im linken Verlauf eine Ebene unter dem ersten daraus erstellten Feature angezeigt, sofern der Bereich breit genug für die Namen ist. Die Timeline unten zeigt weiterhin die Reihenfolge, in der die Elemente erstellt wurden.",
"prefs.history_sketches_under_feature": "Unter dem zugehörigen Feature",
"prefs.hold_stop_snapping": "Gedrückt halten, um das Einrasten zu deaktivieren",
"prefs.icons_only": "Nur Symbole",
"prefs.imported_file": "Importierte Datei",
"prefs.input": "Eingabe",
"prefs.interface": "Oberfläche",
"prefs.interface_language": "Oberflächensprache",
"prefs.interface_note": "Legt das Erscheinungsbild von SolidCraft und die Anordnung seiner Bereiche fest.",
"prefs.interval_minutes": "{n} min",
"prefs.labels": "Beschriftungen",
"prefs.layout": "Layout",
"prefs.layout_note": "Im Layout „Kompakt“ werden Bereiche an den Fensterrändern angedockt. Transparenz für den Browser ist nur im Layout „Schwebend“ verfügbar. Die Position des Assistenten ändern Sie auf der Seite „Assistent“.",
"prefs.left": "Links",
"prefs.left_click": "Linksklick",
"prefs.linked_designs": "Verknüpfte Designs",
"prefs.minutes_suffix": " min",
"prefs.origin_plane_names": "Namen der Ursprungsebenen",
"prefs.origin_plane_names_note": "Namen in Browser, Dialogen und Listen. {top} ist XY, {front} ist XZ und {right} ist YZ, mit Z nach oben. Befehle, Skripte und gespeicherte Konstruktionen behalten XY, XZ und YZ.",
"prefs.search": "Einstellungen suchen",
"prefs.search_empty": "Keine passenden Einstellungen",
"prefs.sketch_tab_always": "Registerkarte Skizze immer zeigen",
"prefs.sketch_tab_always_note": "Die Registerkarte Skizze bleibt im Menüband direkt nach Modell, auch wenn keine Skizze offen ist. Ihre Zeichenwerkzeuge beginnen dann eine Skizze auf der ausgewählten Ebene oder Fläche oder auf der Ebene, die Sie als Nächstes wählen, und das Werkzeug ist darin bereit.",
"prefs.sketch_tracking_guides": "Ausrichtungshilfen für Mittelpunkte",
"prefs.sketch_tracking_guides_note": "Den Mauszeiger über einen Kreismittelpunkt oder eine Kantenmitte bewegen und dann waagerecht oder senkrecht bewegen, um eine temporäre gepunktete Hilfslinie anzuzeigen.",
"prefs.theme_file_or_paste": "Datei oder Einfügen",
"prefs.theme_follow": "Einer Designdatei folgen",
"prefs.theme_follow_error": "Nicht angewendet: {error}. Das letzte gültige Design bleibt aktiv.",
"prefs.theme_follow_launch": "Nur für diesen Start (--theme-file); wird neu geladen, sobald ein anderes Werkzeug die Datei überschreibt.",
"prefs.theme_follow_note": "Wird neu geladen, sobald ein anderes Werkzeug die Datei überschreibt. Die Auswahl eines Designs beendet das Folgen.",
"prefs.theme_follow_off": "Aus",
"prefs.theme_follow_stop": "Nicht mehr folgen",
"prefs.theme_import_hint": "Klicken, um eine Designdatei zu wählen, eine hierher ziehen oder mit kopiertem Design Strg+V (Cmd+V auf dem Mac) drücken",
"prefs.theme_paste": "Design einfügen",
"prefs.theme_paste_none": "Die Zwischenablage enthält kein SolidCraft-Design",
"properties.title": "Eigenschaften: {name}",
"recovery.days_ago": "vor {count} Tagen",
"recovery.detail": "{file} · {features} Merkmale · automatisch gespeichert {when}",
@@ -1655,6 +1802,7 @@
"recovery.never_saved": "nie gespeichert",
"render.add_ground": "Add fitted ground to setup",
"render.all_shots_label": "Alle Aufnahmen",
"render.appearances": "Erscheinungsbilder",
"render.background": "Szenenhintergrund",
"render.bloom_enable": "Darstellungs-Bloom",
"render.bloom_help": "Kreativer Ausgabeglanz aus linearen Glanzlichtern mit drei normierten Durchläufen. Radius in Ausgabepixeln; Addition vor sRGB. Keine Linsen-, Volumen- oder Konvergenzsimulation. Das rohe EXR bleibt unverändert.",
@@ -1664,6 +1812,10 @@
"render.bloom_threshold": "Linearer Glanzlichtschwellwert",
"render.camera_pitch": "Kameraneigung",
"render.camera_set": "Render-Kamera einstellen",
"render.category_metal": "Metall",
"render.category_paint": "Lack",
"render.category_plastic": "Kunststoff",
"render.category_wood": "Holz",
"render.clear_stage": "Remove saved stage",
"render.cpu_budget": "CPU-Ressourcenprofil",
"render.cpu_budget_bodies": "Körperobergrenze",
@@ -1677,6 +1829,7 @@
"render.cpu_budget_triangles": "Dreiecksobergrenze",
"render.cpu_budget_workstation": "Workstation (komplexe Szenen)",
"render.emitted_axis": "Abstrahlachse",
"render.environment_tiles_require_raytrace": "Umgebungen benötigen CPU- oder GPU-Raytracing. Im Ausgabeeditor wählen.",
"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",
@@ -1740,6 +1893,8 @@
"render.fixed_camera": "Kamera",
"render.fixed_world": "Welt",
"render.fold_browser": "Browser einklappen",
"render.frame_presets": "Bildvorlagen",
"render.frame_presets_pending": "Kommt mit dem Aufnahmeeditor",
"render.heading_batch": "Stapel",
"render.heading_frame": "Bildrahmen",
"render.heading_lens": "Objektiv",
@@ -1772,8 +1927,12 @@
"render.inner_half_angle": "Innerer Halbwinkel",
"render.inspector": "Inspektor",
"render.layer_off_suffix": " (aus)",
"render.library_appearance_available": "Verfügbares Erscheinungsbild",
"render.library_applicable": "Passende Ressourcen",
"render.library_applied": "Ressourcenvariante angewendet. Vollständigen Renderauftrag vor dem Start prüfen.",
"render.library_apply_appearance": "Erscheinungsbild anwenden",
"render.library_apply_hdr": "Mit dieser HDR-Umgebung speichern",
"render.library_apply_hint": "Klicken zum Anwenden · auf das Modell ziehen",
"render.library_apply_maps": "Erstellte GPU-Oberflächenmaps verwenden",
"render.library_apply_studio": "Erstellte Studiovariante speichern",
"render.library_apply_uniform": "Einheitliches opakes Aussehen anwenden",
@@ -1783,12 +1942,21 @@
"render.library_emitters_only_ack": "Nur Strahler verwenden; dokumentierte passive Karten auslassen",
"render.library_environment_concepts": "Umgebungskonzepte",
"render.library_extent": "Objektausdehnung",
"render.library_filters": "Katalog und Verfügbarkeit",
"render.library_grid": "Raster",
"render.library_hdr": "Integrierte HDR-Umgebungen",
"render.library_hdr_help": "Bettet das originale HDR in die gespeicherte Einstellung ein. Der Längengradursprung wird ausdrücklich umgerechnet; nach dem Speichern ist keine externe Datei nötig.",
"render.library_in_design": "Im Design",
"render.library_inspect_only": "Zum Prüfen wählen · Im Inspektor anwenden",
"render.library_ior": "Brechungsindex",
"render.library_light_concepts": "Beleuchtungskonzepte",
"render.library_list": "Liste",
"render.library_maps_help": "Built-in maps can be saved with pinned sources and local occurrence mapping. Temporary optical overrides remain a separate mode.",
"render.library_material_concepts": "Materialkonzepte",
"render.library_metallic": "Metallisch",
"render.library_next": "Nächste Seite",
"render.library_opacity": "Deckkraft",
"render.library_other": "Weitere Erscheinungsbilder",
"render.library_physical_profiles": "Physical reference profiles",
"render.library_previous": "Vorherige Seite",
"render.library_quality_concepts": "Qualitätsspezifikationen",
@@ -1797,6 +1965,7 @@
"render.library_results": "Passende Ressourcen",
"render.library_rig_help": "Fit once at an explicit center and physical extent. Complete rigs include passive cards; calibration blockers still refuse. Conservative emitter/card clearance is checked before saving.",
"render.library_rigs": "Erstellte Lichtaufbauten",
"render.library_roughness": "Rauheit",
"render.library_save_maps": "Save maps to this setup",
"render.library_scene_bounds": "Erfasste Szenengrenzen verwenden",
"render.library_scenes": "Szenenspezifikationen",
@@ -1807,6 +1976,7 @@
"render.library_target": "Zielkörper",
"render.library_title": "Render-Ressourcenbibliothek",
"render.library_uniform_ack": "Einheitliche Näherung ohne räumliche oder erweiterte Effekte verwenden",
"render.library_users": "Verwendungen",
"render.light_anchor_pending": "Das Koordinatensystem der Lichter kann noch nicht geändert werden.",
"render.lights_fixed_to": "Lichter gebunden an",
"render.material_color_replace": "Basismap ersetzt Körperfarbe",
@@ -1884,14 +2054,24 @@
"render.saved_surface_remove": "Remove saved binding",
"render.saved_surfaces": "Saved surface bindings",
"render.saved_surfaces_help": "Pinned built-in maps follow the selected occurrence in local millimeters. A replaced or missing target is an error, never an automatic reassignment.",
"render.search_appearances": "{count} Erscheinungsbilder durchsuchen",
"render.setup_name": "Name des Setups",
"render.shell_tab_appearance": "Aussehen",
"render.shell_tab_camera": "Kamera",
"render.shell_tab_scene": "SZENE",
"render.shots_camera_changed": "Die Kamera wurde seit dem Speichern dieser Aufnahme geändert",
"render.shots_name_help": "Geben Sie einen eindeutigen Namen für die aktuelle Aufnahme ein.",
"render.shots_no_result": "Noch kein Renderbild",
"render.shots_result": "Rendering {number} · {width} × {height}",
"render.shots_revert": "Zurücksetzen",
"render.shots_save": "Aufnahme speichern",
"render.shots_update": "Aufnahme aktualisieren",
"render.show_shots_label": "Aufnahmenleiste einblenden",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "Größenvorlagen",
"render.size_presets_pending": "Kommt mit dem Ausgabeeditor",
"render.spot_cone": "Spotkegel",
"render.stage_frame": "Bildausschnitt",
"render.stage_light": "Licht",
@@ -1901,6 +2081,8 @@
"render.stage_panel_count": "Saved panels",
"render.stage_preview_note": "Integrierte Vorschau · direktes Licht",
"render.strip_label": "Leiste",
"render.studio_tiles_require_gpu": "Studios benötigen GPU-Pfadverfolgung. Im Ausgabeeditor GPU wählen.",
"render.studios_environments": "Studios und Umgebungen",
"render.tone_aces_fitted": "ACES angepasst",
"render.tone_reinhard": "Reinhard",
"render.tree_add_light": "Licht hinzufügen",
@@ -1954,7 +2136,7 @@
"sample.flange.name": "Schraubflansch",
"sample.hinge.about": "Zwei Komponenten und ein Drehgelenk, auf 60° angetrieben",
"sample.hinge.name": "Scharnierbaugruppe",
"sample.plate.about": "Parametrische Platte mit Vollrundungen, Bohrungen und einer aufgebohrten Erhöhung",
"sample.plate.about": "Parametrische Platte mit Vollrundungen, Bohrungen und einem aufgebohrten Ansatz",
"sample.plate.name": "Beispielplatte",
"sample.vents.about": "Langlöcher in einem Rechteckmuster: Zeilen, Spalten und Abstand sind Parameter",
"sample.vents.name": "Lüftungsplatte",
@@ -1992,6 +2174,7 @@
"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.double_click_components": "Doppelklick auf eine Komponente aktiviert sie oder bearbeitet eine verknüpfte an Ort und Stelle",
"settings.frame_rate_note": "Zeigt die Bilder pro Sekunde unten rechts in der Ansicht.",
"settings.measure_axis_distances": "X/Y/Z-Maße anzeigen",
"settings.measure_axis_distances_help": "Bei geöffneter Messung die Abstände entlang der Weltachsen zusätzlich zum Gesamtabstand anzeigen.",
@@ -2003,6 +2186,7 @@
"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×.",
"settings.update_changed_links": "Geänderte verknüpfte Designs aktualisieren, wenn ein Tab wieder angezeigt wird",
"sheet.flange_type_base": "Basislasche",
"sheet.flange_type_contour": "Konturlasche",
"sheet.flange_type_edge": "Kantenlasche",
@@ -2536,6 +2720,24 @@
"ui.easyprint_uploading": "Wird zu Printables hochgeladen …",
"ui.edit": "Bearbeiten",
"ui.editJointLimits": "Gelenkgrenzen bearbeiten",
"ui.edit_in_place": "An Ort und Stelle bearbeiten",
"ui.edit_in_place_after_turn": "Die Bearbeitung endet, sobald der Agent seine Antwort beendet hat",
"ui.edit_in_place_agent_busy": "Der Agent arbeitet noch in diesem Design; erneut versuchen, sobald er seine Antwort beendet hat",
"ui.edit_in_place_already_queued": "Eine Bearbeitung wartet bereits auf das Ende der Antwort des Agenten",
"ui.edit_in_place_assembly_closed": "{name} ist nicht mehr geöffnet",
"ui.edit_in_place_banner": "Bearbeitung in {name}",
"ui.edit_in_place_busy": "Zuerst abschließen oder abbrechen, was offen ist",
"ui.edit_in_place_none": "Es wird kein verknüpftes Design an Ort und Stelle bearbeitet",
"ui.edit_in_place_not_saved": "Das Teil hat ungespeicherte Änderungen; zum Beenden der Bearbeitung speichern",
"ui.edit_in_place_open_elsewhere": "{name} ist in einem anderen SolidCraft geöffnet",
"ui.edit_in_place_opens_after_turn": "Das Teil öffnet sich, sobald der Agent seine Antwort beendet hat",
"ui.edit_in_place_refresh_dropped": "Die Baugruppe wurde während der Aktualisierung der Verknüpfungen geändert; bitte erneut ausführen",
"ui.edit_in_place_refresh_stopped": "Die Aktualisierung der Verknüpfungen wurde vorzeitig beendet",
"ui.edit_in_place_refreshing": "Verknüpfungen in {name} werden aktualisiert…",
"ui.edit_in_place_save_first": "Zuerst die Baugruppe speichern: ihre verknüpften Designs werden von ihrer Datei aus gefunden",
"ui.edit_in_place_save_waits": "In {name} werden die Verknüpfungen aktualisiert; danach speichern",
"ui.edit_in_place_saved_elsewhere": "Das Teil wurde in eine andere Datei gespeichert; die Baugruppe verknüpft weiterhin {name}",
"ui.edit_in_place_wait": "Warten, bis abgeschlossen ist, was im Design läuft",
"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.",
@@ -2607,6 +2809,7 @@
"ui.heading_edit": "BEARBEITEN",
"ui.heading_extrude": "EXTRUDIEREN",
"ui.heading_fillet": "VOLLRUNDUNG",
"ui.heading_finish_editing": "BEARBEITUNG BEENDEN",
"ui.heading_finish_sketch": "SKIZZE BEENDEN",
"ui.heading_form": "FORM",
"ui.heading_front": "VORNE",
@@ -2838,6 +3041,8 @@
"ui.restore_defaults": "Standardeinstellungen wiederherstellen",
"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_vertical_pan_direction": "Vertikale Schwenkrichtung umkehren",
"ui.reverse_vertical_pan_tip": "Vertikales Zwei-Finger-Scrollen schwenkt in die andere Richtung",
"ui.reverse_zoom_direction": "Zoomrichtung umkehren",
"ui.revolutions": "Windungen",
"ui.revolve": "Drehen",
@@ -2965,6 +3170,15 @@
"ui.up_axis_note": "Welche Achse in den Ansichten nach oben zeigt (Achsenansicht, Home, Ansehen). Designs bleiben unverändert.",
"ui.updateToCurrentView": "Auf aktuelle Ansicht aktualisieren",
"ui.upload": "Hochladen",
"ui.view_angles": "Ansichtswinkel",
"ui.view_angles_convention": "Grad um die Hochachse. Gieren 0° ist die Vorderansicht, 90° links, −90° rechts, 180° die Rückansicht; Nicken 90° ist die Draufsicht; ein positives Rollen dreht das Modell im Uhrzeigersinn.",
"ui.view_angles_help": "Zeigt Nick-, Gier- und Rollwinkel der Ansicht in Grad sowie die Projektion unter dem Orientierungs-Gizmo. Klicken Sie auf die Anzeige, um genaue Winkel einzugeben.",
"ui.view_angles_ortho": "Ortho",
"ui.view_angles_persp": "Persp",
"ui.view_angles_pitch": "Nicken",
"ui.view_angles_readout": "Nicken {pitch} · Gieren {yaw} · Rollen {roll}",
"ui.view_angles_roll": "Rollen",
"ui.view_angles_yaw": "Gieren",
"ui.view_centre": "Ansichtszentrum",
"ui.viewport_theme_follow": "Dem Design folgen",
"ui.visual_shaded_hidden_edges": "Schattiert mit verdeckten Kanten",
+2
View File
@@ -17,6 +17,8 @@
"cmd.sketch_slot_center_point": "Centre Point Slot",
"cmd.sketch_slot_center_to_center": "Centre to Centre Slot",
"pattern.alignment_hint": "Counts include the original. Centre balances copies; Flip chooses the extra side for even totals.",
"prefs.sketch_tracking_guides": "Centre and midpoint alignment guides",
"prefs.sketch_tracking_guides_note": "Hover over a circle centre or straight-edge midpoint, then move horizontally or vertically to show a temporary dotted guide.",
"prefs.theme_follow": "Follow a theme file",
"prefs.theme_follow_error": "Not applied: {error}. The last good theme stays on.",
"prefs.theme_follow_launch": "Followed for this run only (--theme-file); reloaded whenever another tool rewrites it.",
+88
View File
@@ -38,6 +38,7 @@
"All open designs": "All open designs",
"Allowed expressions, separated by semicolons": "Allowed expressions, separated by semicolons",
"Also deletes": "Also deletes",
"Also place them from the origin (fully constrained)": "Also place them from the origin (fully constrained)",
"Anchor": "Anchor",
"Angle 2": "Angle 2",
"Angle Display": "Angle Display",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "Designs you open or save appear here.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Determined by To Object. Choose Angle to edit the angular extent.",
"Diameter": "Diameter",
"Dimension new shapes": "Dimension new shapes",
"Direction": "Direction",
"Discard": "Discard",
"Distance": "Distance",
@@ -196,6 +198,8 @@
"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",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.",
"Edge": "Edge",
"Edges": "Edges",
"Edit": "Edit",
@@ -254,6 +258,8 @@
"Flanges": "Flanges",
"Flat Pattern": "Flat Pattern",
"Flat size": "Flat size",
"Flat size X": "Flat size X",
"Flat size Y": "Flat size Y",
"Follow camera (Look At sketches)": "Follow camera (Look At sketches)",
"Follow the camera (Look At sketches)": "Follow the camera (Look At sketches)",
"Font": "Font",
@@ -812,7 +818,9 @@
"cmd.component_create": "New Component",
"cmd.component_cycle_color": "Cycle Component Color",
"cmd.component_delete": "Delete Component",
"cmd.component_edit_in_place": "Edit in Place",
"cmd.component_extract": "Extract to File",
"cmd.component_finish_edit": "Finish Edit",
"cmd.component_from_bodies": "Create Components from Bodies",
"cmd.component_insert_design": "Insert Design",
"cmd.component_links": "List Links",
@@ -1171,6 +1179,7 @@
"cmd.view.render_dock": "Move Render Dock",
"cmd.view.render_focus": "Render Focus View",
"cmd.view_ambient_occlusion": "Ambient Occlusion",
"cmd.view_angle_readout": "View Angles",
"cmd.view_apply": "Restore Named View",
"cmd.view_back": "Back View",
"cmd.view_bottom": "Bottom View",
@@ -1305,6 +1314,7 @@
"help.appearance.assign": "Gives the selected bodies, faces or components a colour or a material look, without changing their weight. Use it to tell parts apart or to preview a finish.",
"help.attributions": "Attributions (ATTRIBUTION.md)",
"help.build": "Version {version} · commit {commit} · built {date}",
"help.component.finish_edit": "Saves the part you are editing in place, returns to its assembly and updates the assembly from it. Use it when your changes to the linked part are done.",
"help.connect_note": "Restart each assistant to load the SolidCraft server. Each file was backed up as .bak before it changed.",
"help.connect_title": "Connect AI assistants",
"help.face.delete": "Removes the selected faces and lets the neighbouring faces close the gap, or leaves the gap open as a surface. Use it to take off a rounded edge, a hole or a boss that is in the way.",
@@ -1782,8 +1792,12 @@
"prefs.layout_note": "Compact docks panels to the window edges. Browser translucency is available in Floating. Change the Assistant side on the Assistant page.",
"prefs.left": "Left",
"prefs.left_click": "Left click",
"prefs.linked_designs": "Linked designs",
"prefs.live_input": "Live input",
"prefs.live_preview": "Live preview",
"prefs.logo": "Logo",
"prefs.logo_accent": "Accent",
"prefs.logo_theme": "Theme's colors",
"prefs.minutes": "minutes",
"prefs.minutes_suffix": " min",
"prefs.mouse": "Mouse and trackpad",
@@ -1832,6 +1846,10 @@
"prefs.sketch_selection": "Sketch & selection",
"prefs.sketch_selection_heading": "Sketch and selection",
"prefs.sketch_selection_note": "How sketches snap and how clicks select.",
"prefs.sketch_tab_always": "Keep the Sketch tab shown",
"prefs.sketch_tab_always_note": "The Sketch tab stays in the ribbon, right after Model, while no sketch is open. Its drawing tools then start a sketch on the selected plane or face, or on the plane you pick next, with the tool ready in it.",
"prefs.sketch_tracking_guides": "Center and midpoint alignment guides",
"prefs.sketch_tracking_guides_note": "Hover over a circle center or straight-edge midpoint, then move horizontally or vertically to show a temporary dotted guide.",
"prefs.sketching": "Sketching",
"prefs.snap_drawing_note": "While drawing or dragging a sketch point.",
"prefs.source": "Source",
@@ -1844,12 +1862,16 @@
"prefs.supersampling_brief": "Draws the view larger and filters it down: very crisp, and heavier.",
"prefs.tab_accent_note": "The accent follows the active tab",
"prefs.theme_file": "theme file",
"prefs.theme_file_or_paste": "file or paste",
"prefs.theme_follow": "Follow a theme file",
"prefs.theme_follow_error": "Not applied: {error}. The last good theme stays on.",
"prefs.theme_follow_launch": "Followed for this run only (--theme-file); reloaded whenever another tool rewrites it.",
"prefs.theme_follow_note": "Reloaded whenever another tool rewrites it. Choosing a theme stops following it.",
"prefs.theme_follow_off": "Off",
"prefs.theme_follow_stop": "Stop following",
"prefs.theme_import_hint": "Click to choose a theme file, drop one here, or press Ctrl+V (Cmd+V on a Mac) with a theme copied",
"prefs.theme_paste": "Paste theme",
"prefs.theme_paste_none": "The clipboard holds no SolidCraft theme",
"prefs.timeline_half_hour": "−30 min",
"prefs.timeline_now": "now",
"prefs.timeline_quarter_hour": "−15",
@@ -1916,6 +1938,7 @@
"render.all_controls_help": "Dense inspection of all current controls. Section pages provide focused editing without changing the underlying request.",
"render.all_shots_label": "All Shots",
"render.appearance_physics_separate": "Visual appearance does not assign density, thermal data or other engineering properties.",
"render.appearances": "Appearances",
"render.availability_native": "Native composition; review before applying",
"render.availability_projection": "Supported projection; see scope and omissions",
"render.availability_reference": "Reference data; not an automatic assignment",
@@ -1970,6 +1993,10 @@
"render.camera_set": "Set Render Camera",
"render.camera_target": "Target position · mm",
"render.camera_yaw": "Yaw",
"render.category_metal": "Metal",
"render.category_paint": "Paint",
"render.category_plastic": "Plastic",
"render.category_wood": "Wood",
"render.chromatic_offset": "Chromatic edge offset",
"render.clear_stage": "Remove saved stage",
"render.copy_request": "Copy JSON",
@@ -2069,6 +2096,7 @@
"render.effects_reset_lens": "Reset lens effects",
"render.effects_seed": "Pattern seed",
"render.emitted_axis": "Emitted axis",
"render.environment_tiles_require_raytrace": "Environments require CPU or GPU ray tracing. Select it in the Output editor.",
"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",
@@ -2140,6 +2168,8 @@
"render.flare_strength": "Highlight flare strength",
"render.flare_threshold": "Scene-linear flare threshold",
"render.fold_browser": "Fold Browser",
"render.frame_presets": "Frame presets",
"render.frame_presets_pending": "Arrives with the Shot editor",
"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",
@@ -2211,8 +2241,12 @@
"render.lens_effects_title": "Lens-inspired & photographic",
"render.library_all": "Catalog",
"render.library_all_states": "All availability states",
"render.library_appearance_available": "Available appearance",
"render.library_applicable": "Applicable resources",
"render.library_applied": "Resource projection applied. Check the complete render request before starting.",
"render.library_apply_appearance": "Apply appearance",
"render.library_apply_hdr": "Save with this HDR environment",
"render.library_apply_hint": "Click to apply · drag onto the model",
"render.library_apply_maps": "Use authored GPU surface maps",
"render.library_apply_studio": "Save authored studio projection",
"render.library_apply_uniform": "Apply uniform opaque appearance",
@@ -2228,15 +2262,23 @@
"render.library_extent": "Subject extent",
"render.library_favorite": "Add favorite",
"render.library_favorites": "Favorites",
"render.library_filters": "Catalog and availability",
"render.library_grid": "Grid",
"render.library_hdr": "Built-in HDR environments",
"render.library_hdr_help": "Embeds the original HDR in the saved setup. The authored longitude origin is converted explicitly; no external file is needed after saving.",
"render.library_in_design": "In Design",
"render.library_inspect_only": "Select to inspect; nothing is applied automatically. Favorites and recent history belong to this open document session.",
"render.library_ior": "IOR",
"render.library_light_concepts": "Lighting concepts",
"render.library_list": "List",
"render.library_maps_help": "Built-in maps can be saved with pinned sources and local occurrence mapping. Temporary optical overrides remain a separate mode.",
"render.library_material_concepts": "Material concepts",
"render.library_metallic": "Metallic",
"render.library_native_scenes": "Native studios",
"render.library_next": "Next page",
"render.library_omitted": "Not included",
"render.library_opacity": "Opacity",
"render.library_other": "Other appearances",
"render.library_physical_profiles": "Physical reference profiles",
"render.library_previous": "Previous page",
"render.library_quality_concepts": "Quality specifications",
@@ -2246,6 +2288,7 @@
"render.library_results": "Matching resources",
"render.library_rig_help": "Fit once at an explicit center and physical extent. Complete rigs include passive cards; calibration blockers still refuse. Conservative emitter/card clearance is checked before saving.",
"render.library_rigs": "Authored lighting rigs",
"render.library_roughness": "Roughness",
"render.library_save_maps": "Save maps to this setup",
"render.library_scene_bounds": "Use captured scene bounds",
"render.library_scenes": "Scene specifications",
@@ -2269,6 +2312,7 @@
"render.library_unfavorite": "Remove favorite",
"render.library_uniform_ack": "Use the uniform approximation without spatial or advanced effects",
"render.library_usable": "Executable projections",
"render.library_users": "Users",
"render.light_anchor_pending": "Changing the light coordinate frame is not supported yet.",
"render.lights_fixed_to": "Lights fixed to",
"render.linear_help": "Keeps a 32-bit float RGBA master before denoising, exposure, tone mapping, filters and backdrop. Linear sRGB/D65; coverage-premultiplied. Additional memory is admitted explicitly. No compression or extra passes.",
@@ -2487,6 +2531,7 @@
"render.scene_review": "Resolve and review",
"render.scene_review_help": "Review the complete native composition before applying. Unbound advanced SCENE specifications are not substituted.",
"render.scene_scope_details": "Composition scope",
"render.search_appearances": "Search {count} appearances",
"render.setup_legacy_environment": "This older setup uses legacy environment rotation or intensity. Those values are retained; convert them explicitly before saving a full image job.",
"render.setup_name": "Setup name",
"render.setup_numeric_help": "Save records the active image method and all its numeric settings. Reload or choosing another setup replaces this draft; restore the camera separately.",
@@ -2505,10 +2550,19 @@
"render.shot_remove_title": "Remove saved shot?",
"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.shots_camera_changed": "Camera changed since this shot was saved",
"render.shots_name_help": "Enter a unique name for the current shot.",
"render.shots_no_result": "No render yet",
"render.shots_result": "Render {number} · {width} × {height}",
"render.shots_revert": "Revert",
"render.shots_save": "Save Shot",
"render.shots_update": "Update shot",
"render.show_shots_label": "Show Shots strip",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "Size presets",
"render.size_presets_pending": "Arrives with the Output editor",
"render.sky_ground": "Ground · linear RGB",
"render.sky_horizon": "Horizon · linear RGB",
"render.sky_zenith": "Zenith · linear RGB",
@@ -2559,8 +2613,10 @@
"render.studio_sky_help": "Original sky gradient for lighting; not a calibrated atmospheric model.",
"render.studio_sun": "Sun",
"render.studio_sun_radius": "Angular radius",
"render.studio_tiles_require_gpu": "Studios require GPU path tracing. Select GPU in the Output editor.",
"render.studio_title": "Render studio",
"render.studio_tone_map": "Tone mapping",
"render.studios_environments": "Studios and Environments",
"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",
@@ -2668,6 +2724,7 @@
"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.double_click_components": "Double-click a component to activate it, or to edit a linked one in place",
"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.",
"settings.frame_rate_note": "Shows frames per second in the view's bottom-right corner.",
"settings.measure_axis_distances": "Show X/Y/Z distances",
@@ -2680,6 +2737,7 @@
"settings.reset_intro": "These settings don't work on this computer and would keep SolidCraft from starting, so they were changed:",
"settings.reset_title": "Settings were changed",
"settings.supersampling_note": "Draws the view at a higher resolution and filters it down: smoother edges, lines and grid on screens below 4K. It costs GPU time: about 2.25× the pixels at 1.5× and 4× at 2×.",
"settings.update_changed_links": "Update changed linked designs when a tab comes back",
"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.",
@@ -3283,6 +3341,24 @@
"ui.easyprint_uploading": "Uploading to Printables…",
"ui.edit": "Edit",
"ui.editJointLimits": "Edit Joint Limits",
"ui.edit_in_place": "Edit in Place",
"ui.edit_in_place_after_turn": "The edit finishes when the agent's turn ends",
"ui.edit_in_place_agent_busy": "The agent is still working in this design; try again once its turn is done",
"ui.edit_in_place_already_queued": "An edit already waits for the end of the agent's turn",
"ui.edit_in_place_assembly_closed": "{name} is no longer open",
"ui.edit_in_place_banner": "Editing in {name}",
"ui.edit_in_place_busy": "Finish or cancel what is open first",
"ui.edit_in_place_none": "No linked design is edited in place",
"ui.edit_in_place_not_saved": "The part has changes that are not saved; save it to finish editing",
"ui.edit_in_place_open_elsewhere": "{name} is open in another SolidCraft",
"ui.edit_in_place_opens_after_turn": "The part opens when the agent's turn ends",
"ui.edit_in_place_refresh_dropped": "The assembly changed while Update Links ran; run it again",
"ui.edit_in_place_refresh_stopped": "Update Links stopped before it was done",
"ui.edit_in_place_refreshing": "Updating links in {name}…",
"ui.edit_in_place_save_first": "Save the assembly first: its linked designs are found from its file",
"ui.edit_in_place_save_waits": "Update Links is running in {name}; save it once it is done",
"ui.edit_in_place_saved_elsewhere": "The part was saved to another file; the assembly still links {name}",
"ui.edit_in_place_wait": "Wait until what is running in the design is done",
"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.",
@@ -3357,6 +3433,7 @@
"ui.heading_edit": "EDIT",
"ui.heading_extrude": "EXTRUDE",
"ui.heading_fillet": "FILLET",
"ui.heading_finish_editing": "FINISH EDITING",
"ui.heading_finish_sketch": "FINISH SKETCH",
"ui.heading_form": "FORM",
"ui.heading_front": "FRONT",
@@ -3616,6 +3693,8 @@
"ui.restore_defaults": "Restore Defaults",
"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_vertical_pan_direction": "Reverse vertical pan direction",
"ui.reverse_vertical_pan_tip": "Vertical two-finger scrolling pans the other way",
"ui.reverse_zoom_direction": "Reverse zoom direction",
"ui.revolutions": "Revolutions",
"ui.revolve": "Revolve",
@@ -3761,6 +3840,15 @@
"ui.updateToCurrentView": "Update to Current View",
"ui.upload": "Upload",
"ui.vertical_constraint": "Vertical Constraint",
"ui.view_angles": "View angles",
"ui.view_angles_convention": "Degrees about the up axis. Yaw 0° is the Front view, 90° Left, −90° Right, 180° Back; pitch 90° is the Top view; a positive roll turns the model clockwise.",
"ui.view_angles_help": "Shows the view's pitch, yaw and roll in degrees and its projection under the orientation gizmo. Click the readout to type exact angles.",
"ui.view_angles_ortho": "Ortho",
"ui.view_angles_persp": "Persp",
"ui.view_angles_pitch": "Pitch",
"ui.view_angles_readout": "Pitch {pitch} · Yaw {yaw} · Roll {roll}",
"ui.view_angles_roll": "Roll",
"ui.view_angles_yaw": "Yaw",
"ui.view_centre": "View centre",
"ui.viewport_theme_follow": "Follow theme",
"ui.visual_shaded_hidden_edges": "Shaded with hidden edges",
+4
View File
@@ -27,6 +27,7 @@
"All open designs": "Todos los diseños abiertos",
"Allowed expressions, separated by semicolons": "Expresiones permitidas, separadas por punto y coma",
"Also deletes": "También elimina",
"Also place them from the origin (fully constrained)": "Situarlas también desde el origen (totalmente restringidas)",
"Angle 2": "Ángulo 2",
"Animate": "Animar",
"Appearance name": "Nombre de apariencia",
@@ -124,6 +125,7 @@
"Dependents": "Dependientes",
"Designs you open or save appear here.": "Aquí aparecen los diseños que abras o guardes.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Determinado por «Hasta objeto». Elige «Ángulo» para modificar la extensión angular.",
"Dimension new shapes": "Acotar las formas nuevas",
"Direction": "Dirección",
"Discard": "Descartar",
"Do not export hidden edges": "No exportar aristas ocultas",
@@ -132,6 +134,8 @@
"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",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Cada forma nueva también se acota desde el origen del croquis hasta que no quede nada libre. Una forma ya unida al origen o a geometría situada no recibe ninguna.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Cada forma que dibujas recibe todas sus cotas con los tamaños dibujados (los valores escritos tienen prioridad). Se omite un tamaño que el croquis ya fija.",
"Edge": "Arista",
"Edges": "Aristas",
"Edit": "Editar",
+4
View File
@@ -36,6 +36,7 @@
"All open designs": "Toutes les conceptions ouvertes",
"Allowed expressions, separated by semicolons": "Expressions autorisées, séparées par des points-virgules",
"Also deletes": "Supprime aussi",
"Also place them from the origin (fully constrained)": "Les placer aussi depuis l'origine (entièrement contraintes)",
"Anchor": "Ancrage",
"Angle 2": "Angle 2",
"Angle Display": "Affichage de l'angle",
@@ -175,6 +176,7 @@
"Designs you open or save appear here.": "Les conceptions que vous ouvrez ou enregistrez apparaissent ici.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Déterminé par Jusqu'à l'objet. Choisir Angle pour modifier l'étendue angulaire.",
"Diameter": "Diamètre",
"Dimension new shapes": "Coter les nouvelles formes",
"Direction": "Direction",
"Discard": "Abandonner",
"Distance": "Distance",
@@ -186,6 +188,8 @@
"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",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Chaque nouvelle forme est aussi cotée depuis l'origine de l'esquisse jusqu'à ce que rien ne reste libre. Une forme déjà liée à l'origine ou à une géométrie placée n'en reçoit aucune.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Chaque forme dessinée reçoit toutes ses cotes aux tailles dessinées (les valeurs saisies l'emportent). Une taille déjà fixée par l'esquisse est omise.",
"Edge": "Arête",
"Edges": "Arêtes",
"Edit": "Modifier",
+710
View File
@@ -37,6 +37,7 @@
"All open designs": "Todos os deseños abertos",
"Allowed expressions, separated by semicolons": "Expresións permitidas, separadas por punto e coma",
"Also deletes": "Tamén elimina",
"Also place them from the origin (fully constrained)": "Situalas tamén desde a orixe (totalmente restrinxidas)",
"Anchor": "Áncora",
"Angle 2": "Ángulo 2",
"Angle Display": "Visualización do ángulo",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Os deseños que abras ou gardes aparecen aquí.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Determinado por Ata o obxecto. Escolle Ángulo para editar a extensión angular.",
"Diameter": "Diámetro",
"Dimension new shapes": "Cotar as formas novas",
"Direction": "Dirección",
"Discard": "Descartar",
"Distance": "Distancia",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Arrastra para xirar o apoio en pasos de 5°. Mantén premido Alt ou Ctrl para xiralo libremente.",
"Drive Joint": "Accionar a unión",
"Duration": "Duración",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Cada forma nova tamén se cota desde a orixe do esbozo ata que non quede nada libre. Unha forma xa unida á orixe ou a xeometría situada non recibe ningunha.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Cada forma que debuxas recibe todas as súas cotas cos tamaños debuxados (os valores escritos teñen prioridade). Omítese un tamaño que o esbozo xa fixa.",
"Edges": "Arestas",
"Edit": "Editar",
"Edit Profile Sketch": "Editar o bosquexo do perfil",
@@ -1741,21 +1745,317 @@
"recovery.just_now": "agora mesmo",
"recovery.min_ago": "hai {count} min",
"recovery.never_saved": "nunca gardado",
"render.adaptive_absolute": "Límite inferior de erro RGB absoluto",
"render.adaptive_coverage": "Obxectivo de erro de cobertura",
"render.adaptive_enable": "Asignar mostras con pilotos independentes",
"render.adaptive_help": "Só GPU. As mostras piloto independentes descártanse e despois asígnanse 16 ou máis mostras de produción por píxel ata o valor de Mostras por píxel. A varianza de RGB e de cobertura guía a asignación; pode que se perdan traxectorias raras e que os píxeles limitados sigan con ruído. O informe final conta o traballo real. Sen garantía certificada de ruído nin de tempo.",
"render.adaptive_minimum": "Mostras de produción mínimas",
"render.adaptive_pending": "Están dispoñibles a asignación adaptativa con pilotos independentes na GPU e os estratos de Fresnel condicionais. A converxencia certificada, as garantías de eventos raros e o transporte adaptativo na CPU seguen sen estar dispoñibles.",
"render.adaptive_pilots": "Mostras piloto por píxel",
"render.adaptive_relative": "Obxectivo de erro RGB relativo",
"render.add_ground": "Engadir á configuración un chan axustado",
"render.advanced_material_scope": "Está dispoñible un medio finito e homoxéneo na GPU con límites explícitos. As grellas de densidade, as combinacións aniñadas de vidro e volume, as superficies con dispersión subsuperficial, o desprazamento, o transporte espectral e os conceptos avanzados de material sen vincular seguen sen estar dispoñibles.",
"render.aging_add": "Engadir capa de envellecemento",
"render.aging_airborne": "Po en suspensión / medio participante",
"render.aging_airborne_help": "O po en suspensión é un volume de dispersión finito e homoxéneo independente. Modifica o transporte e o EXR en bruto, non a pila de envellecemento das superficies. As restricións existentes de volume, vidro e redución de ruído seguen sendo explícitas; non se engade ningunha atmosfera automaticamente.",
"render.aging_all_bodies": "Todos os corpos opacos aptos",
"render.aging_chips": "Pintura descascada",
"render.aging_class_any": "Todas as clases de material opaco",
"render.aging_class_dielectric": "Só superficies non metálicas",
"render.aging_class_metal": "Só superficies metálicas",
"render.aging_color": "Cor da capa · sRGB",
"render.aging_coverage": "Cobertura",
"render.aging_dust": "Po depositado",
"render.aging_empty": "Sen capas de envellecemento: as superficies orixinais non cambian.",
"render.aging_fading": "Revestimento desvaído",
"render.aging_grime": "Sucidade e manchas",
"render.aging_help": "Combina ata oito capas ópticas, por orde. A ferruxe e a pátina son aparencias definidas a man, non simulacións de idade nin de corrosión. A escala está en milímetros do mundo. Non se modifica ningunha xeometría, masa nin propiedade de enxeñaría; exclúense o vidro e os escenarios pasivos.",
"render.aging_metallic": "Fracción metálica da capa",
"render.aging_origin": "Orixe do campo · mm do mundo",
"render.aging_patina": "Pátina verde cobre",
"render.aging_refresh_targets": "Inspeccionar os corpos actuais",
"render.aging_roughness": "Rugosidade da capa",
"render.aging_rust": "Ferro oxidado / ferruxe",
"render.aging_scale": "Escala do patrón",
"render.aging_scratches": "Rabuñaduras finas",
"render.aging_target": "Destino e coordenadas",
"render.aging_target_help": "Un destino con nome aínda debe coincidir co seu índice e o seu nome capturados. As máscaras globais están ancoradas ao mundo; non seguen as pezas en movemento. Isto non é nin detección de cavidades nin desgaste real dos bordos. Filtra a lista para chegar a máis corpos.",
"render.aging_target_search": "Filtrar os nomes dos corpos",
"render.aging_upward": "Deposición cara arriba",
"render.all_controls_help": "Inspección densa de todos os controis actuais. As páxinas de sección permiten editar de forma enfocada sen cambiar a solicitude subxacente.",
"render.all_shots_label": "Todas as tomas",
"render.appearance_physics_separate": "A aparencia visual non asigna densidade, datos térmicos nin outras propiedades de enxeñaría.",
"render.availability_native": "Composición nativa; revísaa antes de aplicar",
"render.availability_projection": "Proxección admitida; consulta o alcance e as omisións",
"render.availability_reference": "Datos de referencia; non é unha asignación automática",
"render.backdrop_alpha_conflict": "Escolle este fondo ou a saída en PNG transparente; o motor de renderizado non ignorará ningún dos dous axustes sen avisar.",
"render.backdrop_enable": "Usar fondo en degradado só para a cámara",
"render.backdrop_first": "Cor inicial / central",
"render.backdrop_help": "Este fondo en espazo de pantalla non ilumina, non proxecta sombras, non reflicte nin representa terreo. Exclúese do EXR en bruto. A xeometría, as luces e o contorno HDR seguen sendo independentes.",
"render.backdrop_horizontal": "Degradado horizontal",
"render.backdrop_radial": "Degradado radial",
"render.backdrop_radius": "Raio",
"render.backdrop_second": "Cor final / do bordo",
"render.backdrop_vertical": "Degradado vertical",
"render.backdrop_x": "Centro X",
"render.backdrop_y": "Centro Y",
"render.background": "Fondo da escena",
"render.background_camera_section": "Fondo da cámara · presentación en PNG",
"render.background_completed_frozen": "O resultado mostrado é unha imaxe rematada e conxelada. Editar un fondo non volve pintar ese resultado automaticamente. Usa Recorrección de cor para cambios só da cámara ou Renderizar para un novo escenario físico.",
"render.background_hdr_separate": "Os recursos HDR actuais iluminan as superficies e reflicten nelas; non se mostran automaticamente como panorama detrás do suxeito. Cambiar un degradado non xira nin recolorea a iluminación.",
"render.background_lighting_section": "Iluminación HDR · independente do fondo da cámara",
"render.background_no_alpha_override": "Non se engade un fondo da cámara á saída transparente sen avisar. A recorrección de cor do mestre en bruto usa a cobertura capturada e non volve aplicar a redución de ruído; o EXR de orixe non cambia.",
"render.background_not_light": "A cor de fondo é presentación, non unha fonte de iluminación adicional.",
"render.background_regrade": "Aplicar ao mestre en bruto conservado",
"render.background_stage_occlusion": "Esta toma inclúe xeometría física do escenario. Un chan ou unha parede grandes poden encher o encadre e ocultar un fondo só da cámara. Borra ou redimensiona o escenario de forma deliberada, ou cambia a súa reflectancia física. A recorrección de cor non pode eliminar a xeometría capturada.",
"render.background_workflow": "Escolle o fondo que queres: unha cor ou un degradado só da cámara, un escenario físico que recibe luz ou iluminación HDR. Son independentes. A vista previa en directo é unha vista de modelado; renderiza unha imaxe nova ou corrixe a cor dun mestre conservado para ver o acabado da cámara.",
"render.base_appearance": "Aparencia do corpo editable",
"render.base_apply": "Aplicar a aparencia do corpo",
"render.base_apply_help": "Unha asignación visual desfacible ao corpo exacto revisado. Os estilos específicos de cara e os materiais de enxeñaría existentes seguen separados.",
"render.base_color": "Cor base · sRGB",
"render.base_metallic": "Fracción metálica",
"render.base_opaque_only": "Este editor mantén a semántica de corpo opaco. Usa os controis explícitos de vidro para a transmisión óptica.",
"render.bloom_enable": "Mostrar resplandor",
"render.bloom_help": "Brillo creativo só de saída a partir de realces lineais positivos, esparexido con tres pasadas de caixa normalizadas. O raio está en píxeles de saída. Engádese na luz de visualización lineal antes de sRGB; non é unha lente, un efecto volumétrico nin unha mellora da converxencia. O EXR en bruto non cambia.",
"render.bloom_opaque": "O resplandor require unha saída opaca. O PNG transparente rexéitase; non se aplana sen avisar.",
"render.bloom_radius": "Raio do resplandor",
"render.bloom_strength": "Intensidade do resplandor",
"render.bloom_threshold": "Limiar de realce lineal",
"render.browse_capabilities": "Inspeccionar o catálogo completo de capacidades",
"render.browse_environments": "Explorar contornos HDR orixinais",
"render.browse_native_scenes": "Explorar estudios nativos",
"render.browse_physical": "Inspeccionar referencias físicas",
"render.browse_quality": "Inspeccionar especificacións de calidade",
"render.browse_rigs": "Explorar montaxes de luces deseñadas",
"render.browse_scene_specs": "Explorar especificacións avanzadas de escena",
"render.browse_surfaces": "Explorar superficies deseñadas",
"render.browser_library": "Biblioteca",
"render.browser_model": "Modelo",
"render.camera_distance": "Distancia do punto de vista ao destino",
"render.camera_exact_help": "Milímetros do mundo; os ángulos móstranse en graos e gárdanse en radiáns. A navegación usa a mesma cámara que a ventá gráfica.",
"render.camera_fov": "Campo de visión vertical",
"render.camera_pitch": "Cabeceo da cámara",
"render.camera_roll": "Xirar sobre a vista",
"render.camera_set": "Definir a cámara de renderizado",
"render.camera_target": "Posición do destino · mm",
"render.camera_yaw": "Guiñada",
"render.chromatic_offset": "Desprazamento cromático dos bordos",
"render.clear_stage": "Quitar o escenario gardado",
"render.copy_request": "Copiar JSON",
"render.cpu_aa_help": "Mostras espaciais: máis mostras melloran os bordos e aumentan o tempo de renderizado.",
"render.cpu_area_add": "Engadir luz rectangular da CPU",
"render.cpu_area_editor": "Luces rectangulares da CPU",
"render.cpu_area_editor_help": "Vectores de lado completos en milímetros; o produto vectorial de U por V apunta cara ao lado emisor. Isto difire dos vectores de semiaresta da GPU.",
"render.cpu_area_full_u": "Lado U completo · mm",
"render.cpu_area_full_v": "Lado V completo · mm",
"render.cpu_area_samples": "Mostras de luz de área",
"render.cpu_binding_confirm": "Confirmar este corpo",
"render.cpu_binding_stale": "A escena cambiou. Confirma de novo este destino de reflexo antes de renderizar.",
"render.cpu_body_choose": "Escoller un corpo",
"render.cpu_body_filter": "Filtrar corpos por nome",
"render.cpu_body_filter_more": "Afina o filtro para ver máis corpos.",
"render.cpu_body_missing": "Falta un destino de reflexo, está oculto, é ambiguo ou ten un nome de máis de 128 bytes. Escóllao de novo.",
"render.cpu_budget": "Perfil de recursos da CPU",
"render.cpu_budget_bodies": "Límite de corpos",
"render.cpu_budget_compact": "Compacto (límites antigos)",
"render.cpu_budget_details": "Límites de recursos",
"render.cpu_budget_help": "Escolle explicitamente límites maiores. A resolución e as mostras nunca se reducen automaticamente.",
"render.cpu_budget_memory": "Límite de memoria do traballo",
"render.cpu_budget_not_guarantee": "Son límites de admisión, non unha reserva de RAM nin unha garantía de velocidade. A xeometría, o búfer de imaxe e as vistas previas conservadas comparten o orzamento de memoria; o renderizado segue podendo cancelarse.",
"render.cpu_budget_resize": "O borrador supera este perfil de CPU ou o seu orzamento de mostras de cámara. Acepta explicitamente unhas dimensións menores ou selecciona un perfil maior.",
"render.cpu_budget_studio": "Studio (imaxes grandes)",
"render.cpu_budget_triangles": "Límite de triángulos",
"render.cpu_budget_workstation": "Estación de traballo (escenas pesadas)",
"render.cpu_captured_hdr": "HDR capturado para esta imaxe",
"render.cpu_check_capture_help": "Comprobar e Iniciar verifican o mesmo resumo do ficheiro ou usan o HDR incorporado. Cada imaxe conserva a súa fonte capturada.",
"render.cpu_check_changed": "Os controis ou o modelo cambiaron despois desta comprobación. Comproba de novo antes de renderizar.",
"render.cpu_constant_help": "A radiancia constante é visible para os raios reflectidos ou transmitidos. Non achega iluminación difusa directa.",
"render.cpu_custom_directions": "Substituír o axuste predefinido por luces direccionais personalizadas",
"render.cpu_direction": "Dirección cara á luz (X, Y, Z)",
"render.cpu_directional": "Luz direccional",
"render.cpu_directional_add": "Engadir luz direccional",
"render.cpu_environment": "Contorno da CPU",
"render.cpu_environment_background": "O fondo da imaxe permanece separado da iluminación do contorno.",
"render.cpu_environment_bounds": "A intensidade da CPU debe estar entre 0 e 64, a rotación HDR debe ser finita e estar dentro de ±1.000.000 radiáns, e as mostras HDR deben ser 1, 4, 16 ou 64.",
"render.cpu_environment_constant": "Contorno constante para raios secundarios",
"render.cpu_environment_none": "Sen contorno da CPU",
"render.cpu_environment_samples": "Mostras de iluminación HDR",
"render.cpu_exposure_help": "A exposición da CPU debe estar entre −16 e 16 EV. Unha exposición da GPU fóra dese intervalo consérvase ata que a cambies.",
"render.cpu_fixed": "Imaxe única",
"render.cpu_hdr_help": "Radiance .hdr, panorama 2:1, ata 2048 × 1024 e 16 MiB. A CPU require primarias sRGB/D65 explícitas no ficheiro; rexéitanse as primarias non especificadas e o EXR.",
"render.cpu_hdr_reflection_help": "As reflexións rugosas HDR requiren superficies de corpos e caras totalmente metálicas. Comprobar informa das combinacións non admitidas.",
"render.cpu_key_rim": "Principal e contraluz",
"render.cpu_last_check": "Última comprobación da CPU",
"render.cpu_light_help": "Ata oito luces direccionais. Unha lista personalizada baleira desactívaas; ao seleccionar un axuste predefinido restáuranse as súas luces. As cores son RGB lineal e a intensidade é relativa, non en watts.",
"render.cpu_light_intensity": "Intensidade relativa (0–64)",
"render.cpu_light_minimum": "Distancia mínima para a atenuación",
"render.cpu_light_position": "Posición no mundo (X, Y, Z)",
"render.cpu_light_reference": "Distancia de referencia para a intensidade",
"render.cpu_light_remove": "Quitar luz",
"render.cpu_lighting": "Axuste predefinido de iluminación",
"render.cpu_lights": "Luces da CPU",
"render.cpu_linear_color": "Cor lineal (R, G, B)",
"render.cpu_neutral": "Neutra",
"render.cpu_opaque_required": "O trazado de raios da CPU necesita un fondo opaco. Desmarca Fondo transparente para continuar.",
"render.cpu_options_pending": "Este panel da CPU aínda non pode editar a emisión, os efectos de superficie, o vidro nin a anisotropía. Borra esas opcións da API antes de usalo.",
"render.cpu_point": "Luz puntual",
"render.cpu_point_add": "Engadir luz puntual",
"render.cpu_point_help": "Ata oito luces puntuais, engadidas á iluminación direccional seleccionada. As distancias están en mm; a mínima non pode superar a distancia de referencia.",
"render.cpu_primary_samples": "Mostras de bordo por píxel",
"render.cpu_progressive": "Progresivo da CPU",
"render.cpu_progressive_help": "Acumula o integrador da CPU existente en pasadas dunha mostra primaria. As reflexións seleccionadas requiren unha mostra; as luces de área, os dieléctricos e a anisotropía requiren Imaxe única.",
"render.cpu_progressive_limits": "Como máximo 1.048.576 píxeles e 16.777.216 avaliacións de píxel × mostra. Cambiar as mostras nunca redimensiona a imaxe automaticamente.",
"render.cpu_progressive_seed": "Semente de mostraxe da CPU",
"render.cpu_progressive_spp": "mostras por píxel",
"render.cpu_reflection_add": "Engadir reflexión rugosa",
"render.cpu_reflection_depth": "Profundidade de reflexión (1–8)",
"render.cpu_reflection_empty": "Non hai corpos seleccionados: as reflexións da escena están desactivadas.",
"render.cpu_reflection_help": "Escolle corpos e define Desactivado, Espello ou Rugoso. Rugoso usa a rugosidade de superficie asignada. Máis mostras e rebotes aumentan o tempo; é un transporte especular limitado, non iluminación global.",
"render.cpu_reflection_limit": "Admítense ata 64 corpos reflectidos.",
"render.cpu_reflection_mirror": "Espello",
"render.cpu_reflection_off": "Desactivado",
"render.cpu_reflection_rough": "Rugoso",
"render.cpu_reflection_samples": "Mostras de reflexión (1–64)",
"render.cpu_reflections": "Reflexións da CPU",
"render.cpu_runtime_help": "Os axustes numéricos de luces e contorno gárdanse coa configuración. As reflexións de corpos e os ficheiros HDR seguen sendo temporais. Consérvanse os valores existentes de luz de área e cono de foco.",
"render.cpu_sampling_mode": "Modo de mostraxe da CPU",
"render.cpu_shadows": "Proxectar sombras",
"render.cpu_summary": "Trazado de raios da CPU · reflexións · HDR · luces direccionais e puntuais",
"render.cpu_warm_cool": "Cálida e fría",
"render.diag_bodies": "Corpos visibles",
"render.diag_job_details": "Detalles do traballo capturado",
"render.diag_last_check": "Última comprobación previa",
"render.diag_memory": "Estimación lóxica de admisión",
"render.diag_not_implemented": "Límites explícitos de capacidades",
"render.diag_preflight_details": "Detalles da comprobación previa",
"render.diag_request": "Solicitude actual exacta",
"render.diag_triangles": "Triángulos",
"render.discard_continue": "Descartar o borrador e continuar",
"render.draft_confirm_help": "O borrador de renderizado actual ten edicións sen aplicar. Gárdaas antes de cambiar, descártaas de forma explícita ou segue editando.",
"render.draft_confirm_title": "Conservar os axustes de renderizado editados",
"render.effects_gpu_only": "Estes efectos requiren trazado de camiños na GPU. Cambiar de páxina nunca cambia o motor de render automaticamente.",
"render.effects_help": "Combina estilos de cor ordenados e efectos de lente no espazo da imaxe. O renderizado e a recorrección de cor do mestre en bruto usan os mesmos axustes gardados. O EXR en bruto non cambia. Son controis artísticos orixinais, non emulacións calibradas de lentes nin de película de marca.",
"render.effects_reset_lens": "Restablecer os efectos de lente",
"render.effects_seed": "Semente do patrón",
"render.emitted_axis": "Eixe de emisión",
"render.error_area_samples": "area_samples debe ser 1, 4, 16 ou 64",
"render.error_binding_allocation": "non se puido reservar a vinculación do material",
"render.error_body_bound": "a vista previa do produto supera o límite de corpos capturados",
"render.error_checkpoint_dimensions": "as dimensións do punto de control difiren da solicitude capturada",
"render.error_decode_budget": "desbordamento do orzamento de decodificación da imaxe",
"render.error_denoise_setting": "axuste nativo de eliminación de ruído non válido",
"render.error_display_dimensions": "dimensións de visualización da imaxe non válidas",
"render.error_display_fit": "a visualización da imaxe non cabe neste dispositivo",
"render.error_display_height": "desbordamento da altura de visualización",
"render.error_display_width": "desbordamento da largura de visualización",
"render.error_duplicate_face": "aparencia de cara de produto duplicada",
"render.error_export_document": "O documento de exportación do renderizado cambiou mentres se escollía o destino",
"render.error_face_cap": "a vista previa do produto supera o límite de admisión de aparencias de cara",
"render.error_finish_gesture": "remata o xesto de modelado antes de previsualizar",
"render.error_finish_operation": "remata a operación de modelado actual antes de entrar en Renderizado",
"render.error_fixed_preview": "a vista previa fixa de Studio require exposición 0, rotación do contorno 0 e intensidade 1",
"render.error_geometry_size": "desbordamento do tamaño da xeometría do produto",
"render.error_glass_recipe": "receita de vidro descoñecida",
"render.error_gpu_preview": "A vista previa do produto na GPU non está dispoñible neste equipo. As configuracións gardadas seguen dispoñibles.",
"render.error_gpu_samples": "número de mostras da GPU non admitido",
"render.error_image_dimensions": "as dimensións da imaxe renderizada non coinciden co seu traballo",
"render.error_image_profile": "a imaxe renderizada supera o seu perfil de recursos capturado",
"render.error_interactive_command": "comando interactivo de Renderizado sen vincular",
"render.error_job_action": "non é unha acción interactiva de traballo de imaxe",
"render.error_job_identity": "identidade de traballo de renderizado non válida: {error}",
"render.error_library_reply": "resposta da biblioteca de renderizado non válida",
"render.error_material_binding": "falta a vinculación do material",
"render.error_no_completed_image": "o renderizado non ten ningunha imaxe completada",
"render.error_no_geometry": "sen xeometría de produto",
"render.error_no_scene": "sen escena de produto",
"render.error_opacity": "opacidade de aparencia do produto non válida",
"render.error_pbr_opacity": "o PBR opaco require opacidade 1",
"render.error_physical_glass": "a receita seleccionada non é vidro físico",
"render.error_preview_device": "a vista previa do produto require un dispositivo instalado cun búfer de profundidade",
"render.error_product_triangle": "triángulo de produto non válido",
"render.error_provisional_identity": "identidade de renderizado provisional ou número de mostras non válidos",
"render.error_quality_bounds": "a proxección de calidade supera os límites nativos",
"render.error_quality_method": "a proxección de calidade require o mesmo método explícito da GPU",
"render.error_quality_projection": "proxección de calidade nativa non válida",
"render.error_regrade_identity": "identidade de recorrección de cor non válida: {error}",
"render.error_scene_bodies": "faltan corpos da escena de renderizado",
"render.error_scene_body_limit": "a escena de renderizado supera o seu límite de corpos",
"render.error_scene_identity": "identidade de escena de renderizado non válida",
"render.error_setup_panicked": "a configuración do trazador de camiños da GPU fallou inesperadamente",
"render.error_setup_stopped": "o proceso de configuración detívose sen devolver un anfitrión",
"render.error_setup_worker": "non se puido iniciar o proceso de configuración: {error}",
"render.error_source_preview": "a vista previa da fonte supera o seu límite de bytes",
"render.error_surface_normals": "o PBR require normais de superficie distintas de cero",
"render.error_surface_reply": "resposta de superficie de autor non válida",
"render.error_triangle_bound": "a vista previa do produto supera o seu límite de orixe de oito millóns de triángulos",
"render.error_triangle_count": "desbordamento da contaxe de triángulos do produto",
"render.error_upload_slot": "a ranura de carga da vista previa do produto non está dispoñible",
"render.error_vertex_allocation": "fallou a asignación de vértices da vista previa do produto",
"render.error_vertex_envelope": "a vista previa do produto supera o seu límite de {limit} MiB de carga de vértices; a xeometría non se simplificou",
"render.error_vertex_packing": "o empaquetado da vista previa do produto difire da carga de vértices admitida",
"render.error_visible_solid": "Crea un sólido visible en Deseño para previsualizalo aquí.",
"render.exit_focus": "Saír do foco",
"render.export_display": "Exportar: PNG de visualización",
"render.export_image_label": "Exportar imaxe",
"render.export_linear": "Exportar: EXR lineal en bruto",
"render.exr_pending": "A GPU pode reter o EXR lineal en bruto. A compresión, as imaxes multicapa e as pasadas auxiliares de renderizado seguen sen estar dispoñibles.",
"render.film_grain": "Gran fotográfico",
"render.fit": "Encadrar o produto",
"render.fixed_camera": "Cámara",
"render.fixed_world": "Mundo",
"render.flare_ghosts": "Aneis fantasma por fonte",
"render.flare_halo": "Halo do destello",
"render.flare_streak": "Raia de estilo anamórfico",
"render.flare_strength": "Intensidade do destello dos realces",
"render.flare_threshold": "Limiar do destello lineal da escena",
"render.fold_browser": "Contraer o navegador",
"render.gpu_depth": "Profundidade máxima de traxectoria",
"render.gpu_options_help": "As mostras, a profundidade, a semente e a exposición gárdanse con esta configuración. Só se garda o método de imaxe activo.",
"render.gpu_path_failed": "Trazador de traxectorias na GPU non dispoñible",
"render.gpu_path_first_setup": "A primeira configuración nesta GPU pode tardar varios minutos; mentres tanto, SolidCraft pódese seguir usando. Os inicios posteriores reutilizan os sombreadores compilados onde o controlador os conserva.",
"render.gpu_path_preparing": "Trazador de traxectorias na GPU: compilando os sombreadores…",
"render.gpu_seed": "Semente aleatoria",
"render.gpu_unavailable": "O trazado de traxectorias na GPU non está listo neste dispositivo.",
"render.ground_apply": "Axustar e gardar o chan",
"render.ground_gap": "Folga explícita",
"render.ground_linear_rgb": "Reflectancia difusa · RGB lineal",
"render.ground_margin": "Marxe da extensión do chan",
"render.hdr_details": "Detalles da fonte HDR",
"render.hdr_embedded": "HDR gardado dentro deste deseño",
"render.hdr_embedded_help": "O renderizado usa os bytes incluídos no deseño; xa non fai falta o ficheiro orixinal.",
"render.hdr_file_captured": "Ficheiro HDR comprobado. Ao gardar incorporaranse estes bytes; se o ficheiro cambia, volve comprobalo de forma explícita.",
"render.hdr_inspect": "Comprobar o ficheiro HDR",
"render.hdr_inspect_required": "Selecciona e comproba un ficheiro HDR antes de gardar ou renderizar.",
"render.hdr_primaries_declared": "A fonte declara as súas cores primarias.",
"render.hdr_primaries_srgb": "Cores primarias: sRGB/D65",
"render.hdr_primaries_undeclared": "A fonte non declara as cores primarias; revisa os requisitos de cor do motor de render.",
"render.hdr_resource_missing": "A este deseño fáltalle o recurso HDR gardado.",
"render.heading_batch": "LOTE",
"render.heading_frame": "ENCADRE",
"render.heading_lens": "LENTE",
"render.heading_results": "RESULTADOS",
"render.heading_shots": "TOMAS",
"render.hide_shots_label": "Ocultar a franxa de tomas",
"render.image_advanced": "Controis avanzados da GPU",
"render.image_cancelled": "Render cancelado",
"render.image_cancelling": "Cancelando",
"render.image_completed": "Imaxe lista para exportar",
"render.image_encoding": "Codificando o PNG",
"render.image_export": "Exportar PNG",
"render.image_exposure": "Exposición",
"render.image_failed": "Fallou o render",
"render.image_height": "Altura",
"render.image_help": "Imaxe de previsualización por CPU · PNG · transparencia aproximada",
"render.image_host_missing": "Non hai ningún anfitrión de imaxes instalado.",
"render.image_method": "Método de imaxe",
"render.image_overwrite": "Substituír o ficheiro existente",
"render.image_preparing": "Preparando a imaxe",
"render.image_progressive": "Renderizado progresivo",
"render.image_queued": "Agardando para renderizar",
"render.image_reduce": "Proba cunha imaxe máis pequena ou unha escena máis sinxela.",
"render.image_running": "Renderizando a imaxe",
"render.image_samples": "Mostras por píxel",
"render.image_scene_stale": "Remata o xesto de modelado ou actualiza a escena antes de comprobar ou iniciar unha imaxe.",
"render.image_stale": "Esta imaxe usa a escena capturada antes dos cambios posteriores.",
"render.image_start": "Iniciar o render",
"render.image_supported": "A solicitude de render é compatible; a cola e a memoria comprobaranse de novo ao comezar.",
@@ -1765,20 +2065,430 @@
"render.image_unknown": "Estado do render non dispoñible",
"render.image_use_largest": "Usar o tamaño máis grande con esta proporción:",
"render.image_width": "Largura",
"render.include_rig_cards": "Incluír tarxetas e bandeiras pasivas",
"render.inner_half_angle": "Semiángulo interior",
"render.inspect_scene": "Actualizar o resumo da escena capturada",
"render.inspector": "Inspector",
"render.keep_editing": "Seguir editando",
"render.layer_down": "Mover abaixo",
"render.layer_enabled": "Capa activada",
"render.layer_off_suffix": " (desactivada)",
"render.layer_remove": "Quitar a capa",
"render.layer_strength": "Intensidade da capa",
"render.layer_up": "Mover arriba",
"render.lens_effects_help": "O destello usa ata catro fontes brillantes separadas da imaxe lineal real. Os fantasmas, o halo, as raias, os desprazamentos cromáticos e a distorsión radial son aproximacións artísticas no espazo da imaxe. Os efectos espaciais precisan unha saída opaca; as mostras exteriores prolongan o bordo da imaxe. O gran é determinista. Non se altera a física, o EXR nin a xeometría.",
"render.lens_effects_title": "Inspirado na lente e fotográfico",
"render.library_all": "Catálogo",
"render.library_all_states": "Todos os estados de dispoñibilidade",
"render.library_applied": "Proxección do recurso aplicada. Comproba a solicitude de renderizado completa antes de iniciar.",
"render.library_apply_hdr": "Gardar con este contorno HDR",
"render.library_apply_maps": "Usar os mapas de superficie de autor da GPU",
"render.library_apply_studio": "Gardar a proxección de Studio de autor",
"render.library_apply_uniform": "Aplicar a aparencia opaca uniforme",
"render.library_authored_help": "Os recursos orixinais de autor son ilustrativos, non datos de enxeñaría medidos. Cada acción aplica só a súa proxección indicada.",
"render.library_blocked": "Bloqueado / require calibración",
"render.library_capabilities": "Especificacións de capacidades",
"render.library_center": "Centro da montaxe",
"render.library_clear_search": "Borrar",
"render.library_details": "Especificación e procedencia",
"render.library_emitters_only_ack": "Usar só os emisores; omitir as tarxetas pasivas documentadas",
"render.library_empty": "Non hai recursos coincidentes. Proba con outra consulta ou outro filtro de dispoñibilidade.",
"render.library_environment_concepts": "Conceptos de contorno",
"render.library_extent": "Extensión do suxeito",
"render.library_favorite": "Engadir aos favoritos",
"render.library_favorites": "Favoritos",
"render.library_hdr": "Contornos HDR integrados",
"render.library_hdr_help": "Incorpora o HDR orixinal na configuración gardada. A orixe de lonxitude de autor convértese de forma explícita; despois de gardar non fai falta ningún ficheiro externo.",
"render.library_inspect_only": "Selecciona para inspeccionar; non se aplica nada automaticamente. Os favoritos e o historial recente pertencen a esta sesión do documento aberto.",
"render.library_light_concepts": "Conceptos de iluminación",
"render.library_maps_help": "Os mapas integrados pódense gardar con fontes fixadas e mapeado local de ocorrencias. As substitucións ópticas temporais seguen sendo un modo á parte.",
"render.library_material_concepts": "Conceptos de material",
"render.library_native_scenes": "Studios nativos",
"render.library_next": "Páxina seguinte",
"render.library_omitted": "Non incluído",
"render.library_physical_profiles": "Perfís de referencia física",
"render.library_previous": "Páxina anterior",
"render.library_quality_concepts": "Especificacións de calidade",
"render.library_recent": "Recentes",
"render.library_replace_environment": "Substituír de forma explícita o contorno existente",
"render.library_replace_studio": "Substituír a iluminación, o contorno e o escenario gardados",
"render.library_results": "Recursos coincidentes",
"render.library_rig_help": "Axusta unha vez cun centro e unha extensión física explícitos. As montaxes completas inclúen tarxetas pasivas; os bloqueos de calibración seguen rexeitando. Antes de gardar compróbase a folga conservadora entre emisores e tarxetas.",
"render.library_rigs": "Montaxes de iluminación de autor",
"render.library_save_maps": "Gardar os mapas nesta configuración",
"render.library_scene_bounds": "Usar os límites da escena capturada",
"render.library_scenes": "Especificacións de escena",
"render.library_search": "Buscar na biblioteca",
"render.library_select_hint": "Escolle un recurso na Biblioteca para inspeccionar as súas accións admitidas e as súas limitacións.",
"render.library_selene": "Aparencias opacas SELENE",
"render.library_selene_shots": "Especificacións de tomas SELENE",
"render.library_short_blocked": "Non dispoñible",
"render.library_short_native": "Composición nativa",
"render.library_short_projection": "Proxección admitida",
"render.library_short_reference": "Só referencia",
"render.library_short_specification": "Só especificación",
"render.library_source_preview": "Cargar a vista previa do mapa de orixe",
"render.library_source_preview_help": "Mapa de orixe da cor base de autor. Non é unha vista previa renderizada nin medida do material.",
"render.library_specification_only": "Só especificación: non é un axuste predefinido completo e executable. Os efectos, os recursos e os papeis do suxeito necesarios aínda precisan unha implementación e unha vinculación explícitas.",
"render.library_specs": "Só especificacións",
"render.library_status": "Dispoñibilidade",
"render.library_surfaces": "Superficies PBR orixinais",
"render.library_target": "Corpo de destino",
"render.library_title": "Biblioteca de recursos de renderizado",
"render.library_unfavorite": "Quitar dos favoritos",
"render.library_uniform_ack": "Usar a aproximación uniforme sen efectos espaciais nin avanzados",
"render.library_usable": "Proxeccións executables",
"render.light_anchor_pending": "Aínda non se admite cambiar o sistema de coordenadas da luz.",
"render.lights_fixed_to": "Luces fixadas a",
"render.linear_help": "Conserva un máster RGBA de coma flotante de 32 bits antes da eliminación de ruído, a exposición, o mapeado tonal, os filtros e o telón de fondo. sRGB lineal/D65; premultiplicado pola cobertura. A memoria adicional admítese de forma explícita. Sen compresión nin pasadas adicionais.",
"render.linear_retain": "Conservar o EXR lineal en bruto",
"render.linear_unavailable": "O fotograma completado seleccionado non ten ningún EXR conservado. Activa a conservación antes de renderizar; un PNG anterior non pode recuperar a radiancia en bruto.",
"render.look_add": "Engadir estilo de cor",
"render.look_bleach": "Inspirado no bleach bypass",
"render.look_cool": "Fría",
"render.look_cyanotype": "Inspirado na cianotipia",
"render.look_faded": "Copia desvaída",
"render.look_mono": "Monocromo",
"render.look_sepia": "Sepia",
"render.look_strength": "Intensidade do estilo",
"render.look_teal_orange": "Verde azulado / laranxa",
"render.look_title": "Pila de estilos creativos",
"render.look_warm": "Cálida",
"render.mapping_scale": "Multiplicador de repetición física",
"render.material_absorption": "Absorción R · G · B (por mm)",
"render.material_add": "Engadir ou editar este corpo",
"render.material_assignments": "Asignacións de corpos",
"render.material_binding_enable": "Incluír esta substitución do corpo",
"render.material_box": "Caixa aliñada cos eixes",
"render.material_browse": "Escoller imaxe…",
"render.material_certification": "O vidro pechado usa a distancia xeométrica. A topoloxía, a orientación, a superposición e os límites ópticos compróbanse durante a preparación da GPU; Comprobar só admite a solicitude.",
"render.material_choose_body": "Escoller un corpo da escena",
"render.material_closed": "Malla sólida pechada",
"render.material_coat": "Capa transparente sobre o material base",
"render.material_coat_enable": "Activar a capa transparente",
"render.material_coat_help": "Revestimento dieléctrico ilustrativo sobre a aparencia opaca existente. Con peso cero, a base queda sen cambios.",
"render.material_color_map": "Imaxe da cor base (sRGB)",
"render.material_color_replace": "O mapa base substitúe a cor do corpo",
"render.material_custom": "Óptica ilustrativa personalizada",
"render.material_enable": "Usar estas substitucións de material na GPU",
"render.material_filter": "Filtrar os corpos da escena…",
"render.material_filter_help": "Móstranse ata 128 corpos coincidentes. Afina o filtro para escenas grandes.",
"render.material_glass": "Vidro e absorción óptica",
"render.material_glass_enable": "Usar vidro físico neste corpo",
"render.material_glass_exclusive": "Neste motor de render, o vidro non pode compartir corpo coa capa transparente nin con mapas de execución.",
"render.material_glass_help": "Receitas ilustrativas orixinais. As mostras amosan a transmitancia, non unha vista previa renderizada. A absorción é −ln(transmitancia lineal) / distancia de referencia; o alfa non cambia.",
"render.material_gpu_required": "Estas substitucións de material activas requiren trazado de camiños na GPU. Selecciona a GPU ou desactiva as substitucións antes de Comprobar ou Iniciar.",
"render.material_ior": "Índice de refracción (IOR)",
"render.material_limits": "Como máximo 128 substitucións de corpos, 32 corpos de vidro disxuntos, 64 capas transparentes e 128 vinculacións de textura. Os mapas idénticos comparten almacenamento; os límites reais do dispositivo e da memoria total seguen aplicándose.",
"render.material_map_invalid": "As rutas dos mapas deben ser rutas locais acoutadas; a intensidade da normal debe ser finita e estar entre 0 e 1.",
"render.material_map_required": "Escolle unha imaxe de cor ou unha imaxe normal antes de usar mapas.",
"render.material_maps": "Mapas planares de cor e normais",
"render.material_maps_enable": "Activar mapas para este corpo opaco",
"render.material_maps_help": "PNG/JPEG de ata 1024×1024; 16 MiB codificados en total. U e V son vectores de repetición ortogonais en mm do mundo (máximo 128 repeticións). A cor é sRGB; os datos normais usan OpenGL +Y. Os ficheiros captúranse ao Comprobar/Iniciar.",
"render.material_metallic_map": "Mapa metálico (lineal)",
"render.material_normal_map": "Imaxe normal (OpenGL, +Y)",
"render.material_normal_strength": "Intensidade da normal (0–1)",
"render.material_origin": "Orixe do mapeado X · Y · Z (mm)",
"render.material_refresh": "Actualizar os corpos da escena",
"render.material_refresh_needed": "A escena cambiou. Actualiza a lista de corpos antes de engadir un destino.",
"render.material_remove": "Quitar esta asignación",
"render.material_repeat_u": "Unha repetición en U X · Y · Z (mm)",
"render.material_repeat_v": "Unha repetición en V X · Y · Z (mm)",
"render.material_revalidate": "Validar de novo este corpo",
"render.material_revalidate_needed": "Esta asignación pertence a unha revisión anterior da escena. Valida de novo a identidade exacta do seu corpo antes de renderizar.",
"render.material_roughness": "Rugosidade da capa (0,045–1)",
"render.material_roughness_map": "Mapa de rugosidade (lineal)",
"render.material_shadow": "Transmitir raios de sombra rectos",
"render.material_target_missing": "O ordinal e o nome do corpo xa non coinciden. Quita esta asignación e escolle de novo, de forma explícita, o corpo desexado.",
"render.material_thickness": "Espesor da lámina fina (mm)",
"render.material_thin": "Lámina fina",
"render.material_title": "Materiais de imaxe na GPU",
"render.material_transient": "Substitucións ópticas temporais para esta lapela do documento. Non se gardan no deseño, na configuración de renderizado nin na biblioteca de materiais.",
"render.material_v_up": "A V da textura apunta cara arriba na imaxe",
"render.material_weight": "Peso da capa (0–1)",
"render.method_cpu": "Trazado de raios na CPU",
"render.method_gpu": "Trazado de camiños na GPU",
"render.method_limit_raster": "O ráster usa a vista previa de estudo opaca fixa. Selecciona un método de trazado de raios explícito para os controis ópticos compatibles.",
"render.method_raster": "Ráster na CPU",
"render.navigation_help": "A cámara móvese como en Deseño (Preferencias › Navegación). Gardar configuración rexistra a cámara actual.",
"render.nested_enable": "Dieléctricos aniñados certificados",
"render.nested_help": "Ata 16 capas contedoras; cada pai debe ser convexo e cada fillo debe estar estritamente dentro del. As interseccións, as superficies en contacto, as láminas finas e a transmisión de sombra recta rexéitanse. O estado de cámara no interior segue a xerarquía certificada. Non crea unha superficie líquida nin fusiona contornos CAD en contacto.",
"render.opaque_image_summary": "PNG de previsualización · PBR opaco · transparencia mesturada",
"render.opaque_preview_help": "PBR opaco e cores simples; transparencia mesturada. A refracción, o HDRI e o render final aínda non están dispoñibles.",
"render.optics_remove": "Quitar a óptica gardada",
"render.optics_replace": "Substituír de forma explícita a óptica gardada deste destino",
"render.optics_save": "Gardar esta óptica na configuración",
"render.optics_saved": "Destinos ópticos gardados",
"render.optics_saved_help": "A identidade exacta da definición, da operación e da ocorrencia consérvase ao reabrir sen conexión. Os destinos que faltan, substituídos ou ocultos rexéitanse; os materiais de enxeñaría non cambian. Garda ou descarta as edicións numéricas antes de quitar un destino gardado.",
"render.outer_half_angle": "Semiángulo exterior",
"render.output_format_status": "O PNG é a imaxe de visualización completada exacta. O EXR opcional da GPU conserva a radiancia FLOAT32 lineal da escena en bruto antes dos filtros de visualización. A exportación nunca substitúe a caché da vista previa nin un traballo diferente.",
"render.output_lock_ratio": "Bloquear a proporción de aspecto",
"render.output_over_budget": "A imaxe solicitada supera o límite de recursos seleccionado. Escolle de forma explícita un tamaño ou un perfil compatible; non se aplica ningunha redución automática.",
"render.output_ratio_refused": "A dimensión ligada supera o límite de tamaño deste método. Consérvase o tamaño anterior; desbloquea a proporción ou escolle un valor menor.",
"render.output_swap_orientation": "Intercambiar largura e altura",
"render.output_tools_inspector": "Edita o tamaño e o formato no inspector de Saída.",
"render.page_aging": "Envellecemento e contaminación",
"render.page_all": "Todos os controis",
"render.page_appearance": "Aparencia",
"render.page_background": "Fondos",
"render.page_camera": "Cámara",
"render.page_diagnostics": "Diagnóstico",
"render.page_effects": "Efectos de lente e acabado",
"render.page_environment": "Contorno",
"render.page_lighting": "Iluminación",
"render.page_output": "Saída",
"render.page_scene": "Escena",
"render.paint_label": "Pintura",
"render.passive_stage": "Chan e escenario pasivo",
"render.passive_stage_help": "Os paneis pasivos finitos pertencen só ás imaxes renderizadas. Non engaden corpos CAD nin masa. A colocación queda fixada despois de aplicar; rexéitanse os paneis que intersequen cos límites do produto. A CPU non ofrece iluminación de rebote difusa.",
"render.perspective": "Cámara en perspectiva",
"render.physical_acknowledge": "Entendo que esta referencia parcial require revisar a calidade, o estado e a fonte",
"render.physical_associations": "Candidatos físicos e papeis",
"render.physical_background_help": "Chan e parede pasivos reais, separados do telón de fondo da cámara. O ciclorama usa 24 tiras poligonais; non é unha superficie infinita nin analiticamente suave. Só substitúe o escenario gardado co teu consentimento.",
"render.physical_copy_plan": "Copiar o plan con fontes e omisións",
"render.physical_cyclorama": "Axustar ciclorama poligonal",
"render.physical_floor_wall": "Axustar chan e parede físicos",
"render.physical_material_name": "Nome proposto do material de referencia",
"render.physical_omissions": "Propiedades que non se poden representar na ficha nativa",
"render.physical_plan_only": "Plan de só lectura preparado. Non se creou nin se asignou ningún material. Conserva o seu perfil ampliado e as súas omisións ao revisar a ficha nativa.",
"render.physical_prepare_plan": "Preparar o plan de creación (non se aplica)",
"render.physical_separate": "A aparencia non identifica o material. Son referencias con fonte, non propiedades efectivas certificadas. A masa, os materiais de enxeñaría e a óptica existentes non cambian.",
"render.physical_unknown": "Non se estableceu ningún candidato numérico. Hai que especificar o grao, a formulación ou a construción; descoñecido non é cero.",
"render.pick_body": "Corpo",
"render.pick_component": "Compoñente",
"render.pick_face": "Cara",
"render.pick_help": "Escolle Corpo, Cara ou Compoñente. Fai clic no espazo baleiro para borrar a escolla; Shift ou Ctrl engade ou alterna. Os realces só aparecen na vista de produto en directo.",
"render.pick_label": "Escoller",
"render.pick_up_label": "Coller",
"render.pick_waiting": "A escolla de produto aínda non é compatible.",
"render.post_contrast": "Contraste",
"render.post_gain_b": "Ganancia do azul",
"render.post_gain_g": "Ganancia do verde",
"render.post_gain_r": "Ganancia do vermello",
"render.post_help": "Só para presentación creativa. As ganancias RGB aplícanse antes do mapeado tonal; o contraste, a saturación e a viñeta van despois, en luz lineal de pantalla. Iniciar o renderizado crea mostras de transporte novas. A recorrección de cor usa o máster en bruto conservado que estea seleccionado, sen eliminación de ruído nin raios novos.",
"render.post_reset": "Restablecer os filtros de presentación",
"render.post_saturation": "Saturación",
"render.post_title": "Filtros de presentación",
"render.post_vignette": "Viñeta",
"render.preview": "Previsualización integrada",
"render.preview_help": "Sombreado ráster e transparencia mesturada. A refracción, o HDRI e o render final aínda non están dispoñibles.",
"render.preview_image_settings_help": "A vista previa en directo mantén unha iluminación de estudo fixa. A exposición e a iluminación da imaxe aplícanse á tarefa de imaxe ao usar Comprobar ou Iniciar.",
"render.preview_lighting_help": "A vista previa en directo só mostra luz directa e non hai sombras.",
"render.preview_retry": "Reintentar a vista previa en directo",
"render.preview_unavailable_help": "A vista previa en directo non está dispoñible. As configuracións gardadas e os controis das tarefas de imaxe seguen accesibles. Cambia a escena ou reinténtao explicitamente; unha escena rexeitada non se reconstrúe en cada fotograma.",
"render.preview_upload": "Datos de vértices da vista previa en directo",
"render.preview_upload_help": "Bytes exactos de vértices da vista previa, non a memoria total da GPU nin do proceso. A xeometría non se simplifica. As tarefas de imaxe usan a súa propia admisión e iluminación.",
"render.progressive_image_summary": "PNG de vista previa · PBR e vidro · mostras progresivas",
"render.property_conditions": "Condicións: {value}",
"render.property_fallback": "propiedade",
"render.property_qualifier": "Cualificador: {value}",
"render.property_source": "Fonte: {id} - {locator}",
"render.property_uncertainty": "Incerteza: {value}",
"render.property_unknown": "descoñecido",
"render.quality_ack": "Confirmar a proxección do orzamento fixo e as omisións",
"render.quality_apply": "Usar este orzamento de mostraxe fixo",
"render.quality_projection_help": "Os axustes predefinidos Q inclúen requisitos futuros. Esta acción só proxecta un orzamento compatible de PNG con mostras fixas e omite explicitamente a parada adaptativa, a saída lineal en bruto e os límites de transmisión independentes.",
"render.quality_review": "Revisar o orzamento de mostraxe",
"render.queue_pending": "Nesta interface non hai ningunha cola de produción automática nin motor de renderizado de animacións. As imaxes fixas completadas poden exportarse por separado.",
"render.radial_distortion": "Distorsión radial",
"render.regrade_action": "Corrixir a cor de novo do máster en bruto (sen eliminación de ruído)",
"render.regrade_help": "Crea un PNG separado a partir do máster en bruto completado que está seleccionado, usando estes controis de presentación. Non traza raios, non cambia o tamaño, a cámara nin as luces capturados e non sobrescribe o EXR. A eliminación de ruído non se volve aplicar: os másters en bruto non conservan as súas guías. O derivado segue sendo exportable cos mesmos controis da tarefa.",
"render.regrade_label": "Recorrección de cor",
"render.reload_settings": "Volver cargar os axustes gardados",
"render.replace_ground": "Confirmar a substitución do escenario existente",
"render.replace_label": "Substituír",
"render.replace_saved_surface": "Substituír unha vinculación gardada existente para este destino",
"render.restore_camera": "Restaurar a cámara gardada",
"render.result_actual_help": "Un píxel da imaxe por píxel da pantalla.",
"render.result_actual_size": "100%",
"render.result_capture": "Revisión capturada",
"render.result_current": "A revisión do modelo capturada é a actual.",
"render.result_empty": "Aínda non hai ningunha imaxe completada. Comproba os axustes e inicia un renderizado.",
"render.result_fit": "Axustar a imaxe",
"render.result_job": "Tarefa",
"render.result_navigation": "O desprazamento e o zoom usan as preferencias de Navegación. Espazo + arrastrar desprazan a vista.",
"render.result_open": "Abrir a imaxe completada no lenzo principal.",
"render.result_preview": "Vista previa en directo",
"render.result_provisional": "Imaxe provisional da CPU",
"render.result_provisional_help": "Este punto de control non se pode exportar. Exportar mantén o último resultado completado; cancelar volve a ese resultado.",
"render.result_reduced_display": "A vista previa en pantalla reduciuse ao límite de dispositivo/caché da vista. O PNG conservado e a exportación manteñen a resolución completa; a inspección nativa ao 100% non está dispoñible nesta vista reducida.",
"render.result_retained": "Móstrase a última imaxe completada; un renderizado máis recente non a substituíu.",
"render.result_sequence": "Punto de control",
"render.result_title": "Resultado do renderizado",
"render.return_design": "Volver a Deseño",
"render.review_stale": "Esta revisión está obsoleta. Resólvea ou comproba de novo antes de aplicar.",
"render.ribbon_aging": "Envellecemento",
"render.ribbon_backgrounds": "Fondos",
"render.ribbon_check": "Comprobar",
"render.ribbon_check_help": "Valida o borrador actual exacto que enviará Renderizar. Sen alternativa de motor de renderizado, redimensionamento silencioso nin substitución de recursos.",
"render.ribbon_edit_lights": "Editar luces",
"render.ribbon_effects": "Efectos",
"render.ribbon_environment_help": "A iluminación HDR, os fondos só para a cámara e as superficies físicas do escenario son controis separados, con consentimento explícito para a substitución.",
"render.ribbon_finish_dialog": "Remata primeiro o diálogo de ficheiro ou de confirmación actual.",
"render.ribbon_frame": "Encadrar",
"render.ribbon_hdr_library": "Biblioteca HDR",
"render.ribbon_job_active": "Xa hai un renderizado en curso; cancélao explicitamente antes de iniciar outro.",
"render.ribbon_light_rigs": "Montaxes de luces",
"render.ribbon_lights_help": "Inspecciona montaxes creadas ou edita luces compatibles sen substituír a configuración actual ata que apliques o cambio explicitamente.",
"render.ribbon_materials": "Materiais",
"render.ribbon_materials_help": "Abre o inspector de aparencia compartido e a biblioteca de superficies orixinal. As edicións ópticas nunca cambian en silencio as propiedades de enxeñaría.",
"render.ribbon_no_active_job": "Non hai ningún renderizado activo que cancelar.",
"render.ribbon_no_result": "Completa un renderizado antes de exportar a súa imaxe exacta.",
"render.ribbon_no_saved_camera": "Garda unha toma antes de restaurar a súa cámara.",
"render.ribbon_saved_camera": "Cámara gardada",
"render.ribbon_shots": "Tomas",
"render.ribbon_studios": "Estudios",
"render.ribbon_studios_help": "Explora as composicións de Studio implementadas e revisa as súas substitucións antes de aplicalas. As escenas que só son conceptos seguen etiquetadas.",
"render.ribbon_surface_maps": "Mapas de superficie",
"render.sampling_title": "Mostraxe adaptativa e de transmisión",
"render.save_continue": "Gardar e continuar",
"render.save_setup": "Gardar configuración",
"render.save_shot": "Gardar toma",
"render.saved_maps_runtime_conflict": "As vinculacións de superficie gardadas non se poden combinar con substitucións ópticas temporais nin cun HDR sen gardar. Garda o HDR ou quita explicitamente as entradas temporais.",
"render.saved_surface_remove": "Quitar a vinculación gardada",
"render.saved_surfaces": "Vinculacións de superficie gardadas",
"render.saved_surfaces_help": "Os mapas integrados fixados seguen a instancia seleccionada en milímetros locais. Un destino substituído ou que falta é un erro, nunca unha reasignación automática.",
"render.scene_apply": "Aplicar o Studio revisado",
"render.scene_consent": "Confirmar a substitución da iluminación, o contorno, a exposición e o escenario",
"render.scene_preserved_fields": "Consérvanse a cámara, a mostraxe, as dimensións, as vinculacións ópticas, a xeometría CAD e os materiais de enxeñaría.",
"render.scene_preserves_design": "Compón a iluminación e un escenario pasivo para o suxeito visible. A xeometría, os materiais de enxeñaría e a cámara permanecen á parte.",
"render.scene_replaces": "Substitúe",
"render.scene_review": "Resolver e revisar",
"render.scene_review_help": "Revisa a composición nativa completa antes de aplicala. As especificacións SCENE avanzadas sen vincular non se substitúen por outras.",
"render.scene_scope_details": "Alcance da composición",
"render.setup_legacy_environment": "Esta configuración antiga usa a rotación ou a intensidade do contorno herdadas. Eses valores consérvanse; conviértenos explicitamente antes de gardar unha tarefa de imaxe completa.",
"render.setup_name": "Nome da configuración",
"render.setup_numeric_help": "Gardar rexistra o método de imaxe activo e todos os seus axustes numéricos. Recargar ou escoller outra configuración substitúe este borrador; restaura a cámara por separado.",
"render.setup_offline_help": "Podes editar e gardar este método sen o seu motor de renderizado. Comprobar e Iniciar requiren un host dispoñible.",
"render.setup_runtime_unsupported": "Esta tarefa completa aínda non se pode gardar: contén mapas ou vinculacións a corpos da escena. Quita esas entradas temporais antes de gardar unha configuración portátil.",
"render.setup_save_missing": "Non se atopou a configuración de renderizado gardada despois de completarse o comando.",
"render.sharpening": "Enfoque de detalles",
"render.shell_tab_appearance": "APARENCIA DO RENDERIZADO",
"render.shell_tab_camera": "CÁMARA DO RENDERIZADO",
"render.shell_tab_scene": "ESCENA DO RENDERIZADO",
"render.shot_duplicate": "Duplicar a toma gardada",
"render.shot_manager": "Tomas gardadas",
"render.shot_new_name": "Nome da toma nova",
"render.shot_remove": "Quitar a toma gardada",
"render.shot_remove_help": "Quita só esta configuración gardada. A xeometría de orixe e as imaxes completadas consérvanse; a acción pódese desfacer.",
"render.shot_remove_title": "Quitar a toma gardada?",
"render.shot_rename": "Renomear a toma gardada",
"render.shot_saved_only": "Garda primeiro o borrador actual. Duplicar e renomear conservan exactamente as opcións gardadas e as referencias aos recursos.",
"render.show_shots_label": "Mostrar a banda de tomas",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Chan · RGB lineal",
"render.sky_horizon": "Horizonte · RGB lineal",
"render.sky_zenith": "Cenit · RGB lineal",
"render.soft_focus": "Enfoque suave",
"render.spot_cone": "Cono do foco",
"render.stage_frame": "Encadre",
"render.stage_light": "Luz",
"render.stage_look": "Estilo",
"render.stage_orthographic": "Ortográfica",
"render.stage_output": "Saída",
"render.stage_panel_count": "Paneis gardados",
"render.stage_preview_note": "Vista previa integrada · luz directa",
"render.strip_label": "Tira",
"render.studio_add_area": "Engadir luz de área",
"render.studio_ambient": "Radiancia constante do contorno",
"render.studio_ambient_rgb": "Radiancia constante do contorno (RGB lineal)",
"render.studio_aperture": "Raio da apertura",
"render.studio_area": "Luz de área",
"render.studio_area_help": "Ata catro rectángulos dunha soa cara. As semiarestas ortogonais U e V definen o tamaño; U × V mira cara ao lado iluminado. As coordenadas están en milímetros do espazo do mundo.",
"render.studio_center": "Centro X, Y, Z (mm)",
"render.studio_denoise": "Reducir o ruído na imaxe final",
"render.studio_denoise_help": "Filtro final sensible ás arestas; o detalle fino pode suavizarse. O vidro e as superficies especulares nítidas omiten o filtro.",
"render.studio_direction": "Dirección cara ao sol (X, Y, Z)",
"render.studio_environment": "Contorno",
"render.studio_environment_bounds": "A rotación do contorno debe ser finita e estar dentro de ±1.000.000 radiáns, e a intensidade entre 0 e 100.",
"render.studio_environment_none": "Sen mapa de contorno",
"render.studio_focus": "Distancia de enfoque axial",
"render.studio_half_u": "Semiaresta U (mm)",
"render.studio_half_v": "Semiaresta V (mm)",
"render.studio_hdr": "Ficheiro HDR Radiance",
"render.studio_hdr_browse": "Escoller HDR…",
"render.studio_hdr_help": "Radiance .hdr, panorama 2:1, ata 2048 × 1024. EXR non está dispoñible. A suposición de cor só se aplica cando as primarias non están especificadas.",
"render.studio_hdr_required": "Escolle un ficheiro .hdr local.",
"render.studio_hdr_srgb": "Interpretar as primarias non especificadas como sRGB lineal",
"render.studio_intensity": "Intensidade do contorno",
"render.studio_lens": "Profundidade de campo",
"render.studio_lens_perspective": "A profundidade de campo require unha cámara en perspectiva.",
"render.studio_lighting": "Iluminación de estudio",
"render.studio_lighting_enable": "Usar iluminación de estudio personalizada",
"render.studio_needs_review": "Revisa o método e os axustes",
"render.studio_radiance": "Radiancia RGB lineal",
"render.studio_ready": "Listo para comprobar",
"render.studio_remove_area": "Quitar luz de área",
"render.studio_rotation": "Rotación do contorno",
"render.studio_runtime_help": "Os axustes numéricos do estudio e as fontes HDR comprobadas pódense gardar coa configuración. As substitucións ópticas e de material dos corpos seguen sendo temporais e non cambian as aparencias gardadas.",
"render.studio_saved": "Configuración gardada / cámara actual",
"render.studio_sky": "Ceo artístico",
"render.studio_sky_help": "Gradiente de ceo orixinal para a iluminación; non é un modelo atmosférico calibrado.",
"render.studio_sun": "Sol",
"render.studio_sun_radius": "Raio angular",
"render.studio_title": "Estudio de renderizado",
"render.studio_tone_map": "Mapeado de tons",
"render.subsurface_enable": "Paseo aleatorio de dispersión interior",
"render.subsurface_help": "Só para dieléctricos pechados. A dispersión e a absorción RGB son coeficientes independentes por mm. As traxectorias dispérsanse dentro da xeometría real e despois refractan ou reflicten no límite. Desactiva a transmisión directa das sombras, a redución de ruído da superficie e o volume exterior; usa un só estrato de Fresnel. Non é un sombreador de difusión, unha grella de densidade nin un material medido. Os medios densos poden necesitar máis mostras e máis profundidade de traxectoria.",
"render.subsurface_rate": "Taxa de colisións de dispersión",
"render.tone_aces_fitted": "ACES axustado",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "O vidro na GPU admite medios disxuntos certificados. Non se ofrecen medios aniñados sen restricións nin un estimador de transmisión sen ruído.",
"render.transmission_strata": "Estratos de Fresnel condicionais",
"render.transmission_strata_help": "1 conserva o fluxo orixinal. 2 ou 4 subtraxectorias estratifican a primeira escolla de reflexión/transmisión do vidro, mantendo sen cambios as leis de Snell e de absorción. Máis traxectorias supoñen máis traballo; isto non é redución de ruído, nin compatibilidade con medios aniñados, nin a promesa dun renderizado máis rápido.",
"render.tree_add_light": "Engadir luz",
"render.tree_add_shot": "Engadir toma",
"render.tree_browser": "Navegador de renderizado",
"render.tree_by_look": "Por estilo",
"render.tree_by_object": "Por obxecto",
"render.tree_constant": "Contorno constante",
"render.tree_default": "Predeterminado",
"render.tree_directional": "Direccional",
"render.tree_environment": "Contorno",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} caras",
"render.tree_face_one": "{count} cara",
"render.tree_fixed_studio": "Estudio fixo",
"render.tree_hdr": "HDR",
"render.tree_lights": "Luces",
"render.tree_lights_pending": "Os comandos de luces con nome aínda non están dispoñibles.",
"render.tree_mixed": "Mixto",
"render.tree_more": "{count} máis",
"render.tree_mute": "Silenciar a luz",
"render.tree_no_environment": "Sen contorno",
"render.tree_objects": "Obxectos",
"render.tree_output": "Saída",
"render.tree_point": "Puntual",
"render.tree_rectangle": "Rectángulo",
"render.tree_search": "Buscar obxectos",
"render.tree_selection": "Selección de renderizado",
"render.tree_shots": "Tomas",
"render.tree_sky": "Ceo",
"render.tree_solo": "Luz en solo",
"render.tree_spot": "Foco",
"render.tree_sun": "Sol",
"render.tree_switch": "Cambiar",
"render.tree_user_one": "{count} obxecto",
"render.tree_users": "{count} obxectos",
"render.unavailable_preview": "Esta configuración pide un perfil de previsualización non dispoñible.",
"render.unsaved": "Cambios da previsualización sen gardar",
"render.use_preview": "Usar a previsualización integrada",
"render.volume_albedo": "Albedo de dispersión · RGB lineal",
"render.volume_anisotropy": "Coseno medio da fase",
"render.volume_enable": "Activar o medio participante",
"render.volume_extinction": "Coeficiente de extinción",
"render.volume_help": "Transporte na GPU dentro dunha única caixa finita, con atenuación de Beer e dispersión HG nas traxectorias da cámara e nas indirectas. Usa iluminación explícita de estudio/HDR/ceo, incluída a atenuación das sombras. Un coseno de fase positivo dispersa cara adiante. Hai que desactivar explicitamente os límites do vidro e a redución de ruído da superficie. Unha extinción cero deixa o transporte sen cambios. Non é unha atmosfera lunar física, unha grella de densidade, unha emisión volumétrica, un transporte espectral nin unha propiedade de material certificada.",
"render.volume_max": "Límites máximos · mm do mundo",
"render.volume_min": "Límites mínimos · mm do mundo",
"render.volume_title": "Volume homoxéneo delimitado",
"render.wait_batch": "aínda non se admite: a cola de renderizado das tomas gardadas",
"render.wait_compare": "aínda non se admite: a comparación de imaxes conservadas",
"render.wait_paint": "aínda non se admite: a selección de produtos e a pintura de aparencias",
"render.wait_pick_up": "aínda non se admite: a selección de produtos e a mostraxe de aparencias",
"render.wait_replace": "aínda non se admite: substituír todos os usos dunha aparencia",
"render.wait_solo": "aínda non se admite: a visibilidade das luces e os controis de solo",
"sample.bracket.about": "Pestana base con pestanas de aresta e un dobradillo cunha regra de 2 mm",
"sample.bracket.name": "Escuadra de chapa",
"sample.enclosure.about": "Caixa baleirada cun beizo, saíntes para parafusos, un apoio e un encaixe a presión",
+88
View File
@@ -38,6 +38,7 @@
"All open designs": "כל התכנים הפתוחים",
"Allowed expressions, separated by semicolons": "ביטויים מותרים, מופרדים בנקודה ופסיק",
"Also deletes": "נמחקים גם",
"Also place them from the origin (fully constrained)": "מיקום גם ביחס לראשית (מוגבל לחלוטין)",
"Anchor": "נקודת עיגון",
"Angle 2": "זווית 2",
"Angle Display": "תצוגת זווית",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "תכנים שנפתחים או נשמרים מופיעים כאן.",
"Determined by To Object. Choose Angle to edit the angular extent.": "נקבע לפי \"עד אובייקט\". יש לבחור \"זווית\" כדי לערוך את התחום הזוויתי.",
"Diameter": "קוטר",
"Dimension new shapes": "הוספת מידות לצורות חדשות",
"Direction": "כיוון",
"Discard": "השלכה",
"Distance": "מרחק",
@@ -196,6 +198,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "יש לגרור כדי לסובב את המשען בצעדים של 5°. יש להחזיק Alt או Ctrl לסיבוב חופשי.",
"Drive Joint": "הנעת מפרק",
"Duration": "משך",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "כל צורה חדשה מקבלת גם מידות מראשית הסקיצה עד שלא נשאר בה דבר חופשי. צורה שכבר מחוברת לראשית או לגאומטריה ממוקמת לא מקבלת אף אחת.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "כל צורה שתשרטט תקבל את כל המידות שלה בגדלים ששרטטת (ערכים שהוקלדו קודמים). גודל שהסקיצה כבר קובעת מושמט.",
"Edge": "מקצוע",
"Edges": "מקצועות",
"Edit": "עריכה",
@@ -254,6 +258,8 @@
"Flanges": "אוגנים",
"Flat Pattern": "פריסה",
"Flat size": "מידות הפריסה",
"Flat size X": "מידות הפריסה X",
"Flat size Y": "מידות הפריסה Y",
"Follow camera (Look At sketches)": "מעקב אחר המצלמה (הבטה אל סקיצות)",
"Follow the camera (Look At sketches)": "מעקב אחר המצלמה (הבטה אל סקיצות)",
"Font": "גופן",
@@ -812,7 +818,9 @@
"cmd.component_create": "רכיב חדש",
"cmd.component_cycle_color": "החלפת צבע הרכיב במחזוריות",
"cmd.component_delete": "מחיקת רכיב",
"cmd.component_edit_in_place": "עריכה במקום",
"cmd.component_extract": "חילוץ לקובץ",
"cmd.component_finish_edit": "סיום עריכה",
"cmd.component_from_bodies": "יצירת רכיבים מגופים",
"cmd.component_insert_design": "הוספת תכן",
"cmd.component_links": "רשימת קישורים",
@@ -1171,6 +1179,7 @@
"cmd.view.render_dock": "הזז את עגינת הרינדור",
"cmd.view.render_focus": "תצוגת מיקוד רינדור",
"cmd.view_ambient_occlusion": "הצללה סביבתית",
"cmd.view_angle_readout": "זוויות תצוגה",
"cmd.view_apply": "שחזור תצוגה שמורה",
"cmd.view_back": "תצוגה אחורית",
"cmd.view_bottom": "תצוגה תחתונה",
@@ -1305,6 +1314,7 @@
"help.appearance.assign": "מתן צבע או מראה של חומר לגופים, לפאות או לרכיבים שנבחרו, בלי לשנות את משקלם. מתאים להבחנה בין חלקים או לתצוגה מקדימה של גימור.",
"help.attributions": "ייחוסים (ATTRIBUTION.md)",
"help.build": "גרסה {version} · קומיט {commit} · נבנתה ב־{date}",
"help.component.finish_edit": "שומר את החלק שנערך במקומו, חוזר להרכבה שלו ומעדכן ממנו את ההרכבה. יש להשתמש בו כשהשינויים בחלק המקושר הושלמו.",
"help.connect_note": "יש להפעיל מחדש כל עוזר כדי לטעון את שרת SolidCraft. לכל קובץ נשמר גיבוי בסיומת .bak לפני השינוי.",
"help.connect_title": "חיבור עוזרי בינה מלאכותית",
"help.face.delete": "מחיקת הפאות שנבחרו, כשהפאות השכנות סוגרות את הפער, או השארת הפתח פתוח כמשטח. מתאים להסרת עיגול, חור או בליטה שמפריעים.",
@@ -1782,8 +1792,12 @@
"prefs.layout_note": "הפריסה הדחוסה מצמידה חלוניות לשולי החלון. שקיפות עץ התכן זמינה בפריסה הצפה. את צד העוזר אפשר לשנות בעמוד העוזר.",
"prefs.left": "שמאל",
"prefs.left_click": "לחיצה שמאלית",
"prefs.linked_designs": "תכנים מקושרים",
"prefs.live_input": "קלט חי",
"prefs.live_preview": "תצוגה מקדימה חיה",
"prefs.logo": "לוגו",
"prefs.logo_accent": "צבע הדגשה",
"prefs.logo_theme": "צבעי ערכת הנושא",
"prefs.minutes": "דקות",
"prefs.minutes_suffix": " דק'",
"prefs.mouse": "עכבר ומשטח מגע",
@@ -1832,6 +1846,10 @@
"prefs.sketch_selection": "סקיצה ובחירה",
"prefs.sketch_selection_heading": "סקיצה ובחירה",
"prefs.sketch_selection_note": "איך סקיצות נצמדות ואיך לחיצות בוחרות.",
"prefs.sketch_tab_always": "השארת לשונית הסקיצה מוצגת",
"prefs.sketch_tab_always_note": "לשונית הסקיצה נשארת ברצועה, מיד אחרי מודל, גם כשאין סקיצה פתוחה. כלי השרטוט בה מתחילים אז סקיצה על המישור או הפאה שנבחרו, או על המישור שתבחרו בהמשך, והכלי מוכן בה.",
"prefs.sketch_tracking_guides": "קווי עזר ליישור מרכזים ונקודות אמצע",
"prefs.sketch_tracking_guides_note": "יש לרחף עם הסמן מעל מרכז מעגל או נקודת אמצע של צלע ישרה, ואז להזיז אותו אופקית או אנכית כדי להציג קו עזר מקווקו זמני.",
"prefs.sketching": "שרטוט סקיצות",
"prefs.snap_drawing_note": "בזמן ציור או גרירה של נקודת סקיצה.",
"prefs.source": "מקור",
@@ -1844,12 +1862,16 @@
"prefs.supersampling_brief": "מצייר את המבט גדול יותר ומקטין אותו: חד מאוד, וכבד יותר.",
"prefs.tab_accent_note": "צבע ההדגשה עוקב אחר הלשונית הפעילה",
"prefs.theme_file": "קובץ ערכת נושא",
"prefs.theme_file_or_paste": "קובץ או הדבקה",
"prefs.theme_follow": "מעקב אחר קובץ ערכת נושא",
"prefs.theme_follow_error": "לא הוחל: {error}. ערכת הנושא התקינה האחרונה נשארת פעילה.",
"prefs.theme_follow_launch": "מעקב להפעלה זו בלבד (--theme-file); נטען מחדש בכל פעם שכלי אחר משכתב את הקובץ.",
"prefs.theme_follow_note": "נטען מחדש בכל פעם שכלי אחר משכתב את הקובץ. בחירת ערכת נושא מפסיקה את המעקב.",
"prefs.theme_follow_off": "כבוי",
"prefs.theme_follow_stop": "הפסקת המעקב",
"prefs.theme_import_hint": "לחצו כדי לבחור קובץ ערכת נושא, שחררו קובץ כאן, או הקישו Ctrl+V ‏(Cmd+V ב-Mac) אחרי שהעתקתם ערכת נושא",
"prefs.theme_paste": "הדבקת ערכת נושא",
"prefs.theme_paste_none": "בלוח אין ערכת נושא של SolidCraft",
"prefs.timeline_half_hour": "−30 דק׳",
"prefs.timeline_now": "עכשיו",
"prefs.timeline_quarter_hour": "−15",
@@ -1916,6 +1938,7 @@
"render.all_controls_help": "בדיקה צפופה של כל הפקדים הנוכחיים. דפי המקטעים מאפשרים עריכה ממוקדת בלי לשנות את הבקשה עצמה.",
"render.all_shots_label": "כל הצילומים",
"render.appearance_physics_separate": "המראה החזותי אינו מקצה צפיפות, נתונים תרמיים או תכונות הנדסיות אחרות.",
"render.appearances": "מראות",
"render.availability_native": "קומפוזיציה מקורית; יש לסקור לפני ההחלה",
"render.availability_projection": "השלכה נתמכת; ראו היקף והשמטות",
"render.availability_reference": "נתוני ייחוס; לא הקצאה אוטומטית",
@@ -1970,6 +1993,10 @@
"render.camera_set": "הגדרת מצלמת ההדמיה",
"render.camera_target": "מיקום היעד · mm",
"render.camera_yaw": "סבסוב",
"render.category_metal": "מתכת",
"render.category_paint": "צבע",
"render.category_plastic": "פלסטיק",
"render.category_wood": "עץ",
"render.chromatic_offset": "היסט כרומטי בקצוות",
"render.clear_stage": "הסרת הבמה השמורה",
"render.copy_request": "העתקת JSON",
@@ -2069,6 +2096,7 @@
"render.effects_reset_lens": "איפוס אפקטי העדשה",
"render.effects_seed": "זרע הדוגמה",
"render.emitted_axis": "ציר פליטה",
"render.environment_tiles_require_raytrace": "סביבות דורשות מעקב קרניים במעבד או בכרטיס המסך. בחר זאת בעורך הפלט.",
"render.error_area_samples": "area_samples חייב להיות 1, 4, 16 או 64",
"render.error_binding_allocation": "לא ניתן היה להקצות קישור חומר",
"render.error_body_bound": "תצוגת המוצר חורגת ממגבלת הגופים שנקלטו",
@@ -2140,6 +2168,8 @@
"render.flare_strength": "עוצמת בוהק ההבהרות",
"render.flare_threshold": "סף בוהק ליניארי של הסצנה",
"render.fold_browser": "קפל דפדפן",
"render.frame_presets": "הגדרות מסגרת מוכנות",
"render.frame_presets_pending": "יגיע עם עורך הצילום",
"render.gpu_depth": "עומק מסלול מרבי",
"render.gpu_options_help": "הדגימות, העומק, הזרע והחשיפה נשמרים עם ההגדרה הזאת. נשמרת רק שיטת התמונה הפעילה.",
"render.gpu_path_failed": "מעקב המסלולים ב־GPU אינו זמין",
@@ -2211,8 +2241,12 @@
"render.lens_effects_title": "בהשראת עדשות וצילום",
"render.library_all": "קטלוג",
"render.library_all_states": "כל מצבי הזמינות",
"render.library_appearance_available": "מראה זמין",
"render.library_applicable": "משאבים ישימים",
"render.library_applied": "השלכת המשאב הוחלה. יש לבדוק את בקשת ההדמיה המלאה לפני ההתחלה.",
"render.library_apply_appearance": "החל מראה",
"render.library_apply_hdr": "שמירה עם סביבת HDR זו",
"render.library_apply_hint": "לחץ להחלה · גרור אל המודל",
"render.library_apply_maps": "שימוש במפות משטח GPU מעוצבות",
"render.library_apply_studio": "שמירת השלכת הסטודיו המעוצב",
"render.library_apply_uniform": "החלת מראה אטום אחיד",
@@ -2228,15 +2262,23 @@
"render.library_extent": "היקף הנושא",
"render.library_favorite": "הוספה למועדפים",
"render.library_favorites": "מועדפים",
"render.library_filters": "קטלוג וזמינות",
"render.library_grid": "רשת",
"render.library_hdr": "סביבות HDR מובנות",
"render.library_hdr_help": "מטמיע את ה־HDR המקורי בהגדרה השמורה. ראשית קו האורך המעוצבת מומרת במפורש; אין צורך בקובץ חיצוני אחרי השמירה.",
"render.library_in_design": "בתכנון",
"render.library_inspect_only": "בחירה לבדיקה; דבר אינו מוחל אוטומטית. המועדפים וההיסטוריה האחרונה שייכים להפעלת המסמך הפתוחה הזאת.",
"render.library_ior": "מקדם שבירה",
"render.library_light_concepts": "מושגי תאורה",
"render.library_list": "רשימה",
"render.library_maps_help": "ניתן לשמור מפות מובנות עם מקורות מוצמדים ומיפוי מקומי של מופעים. דריסות אופטיות זמניות נשארות מצב נפרד.",
"render.library_material_concepts": "מושגי חומר",
"render.library_metallic": "מתכתיות",
"render.library_native_scenes": "סטודיו מקוריים",
"render.library_next": "הדף הבא",
"render.library_omitted": "לא נכלל",
"render.library_opacity": "אטימות",
"render.library_other": "מראות אחרים",
"render.library_physical_profiles": "פרופילי ייחוס פיזיקליים",
"render.library_previous": "הדף הקודם",
"render.library_quality_concepts": "מפרטי איכות",
@@ -2246,6 +2288,7 @@
"render.library_results": "משאבים תואמים",
"render.library_rig_help": "התאמה פעם אחת במרכז מפורש ובהיקף פיזיקלי. מערכים מלאים כוללים כרטיסים סבילים; חסמי כיול עדיין דוחים. מרווח שמרני בין פולטים לכרטיסים נבדק לפני השמירה.",
"render.library_rigs": "מערכי תאורה מעוצבים",
"render.library_roughness": "חספוס",
"render.library_save_maps": "שמירת המפות בהגדרה הזאת",
"render.library_scene_bounds": "שימוש בגבולות הסצנה שנלכדו",
"render.library_scenes": "מפרטי סצנה",
@@ -2269,6 +2312,7 @@
"render.library_unfavorite": "הסרה מהמועדפים",
"render.library_uniform_ack": "שימוש בקירוב האחיד ללא אפקטים מרחביים או מתקדמים",
"render.library_usable": "השלכות ניתנות להרצה",
"render.library_users": "משתמשים",
"render.light_anchor_pending": "שינוי מערכת הצירים של האור אינו נתמך עדיין.",
"render.lights_fixed_to": "האורות מקובעים אל",
"render.linear_help": "שומר מאסטר RGBA בנקודה צפה של 32 סיביות לפני הסרת רעש, חשיפה, מיפוי גוונים, מסננים ורקע. sRGB/D65 ליניארי; מוכפל מראש בכיסוי. זיכרון נוסף מאושר במפורש. ללא דחיסה או מעברים נוספים.",
@@ -2487,6 +2531,7 @@
"render.scene_review": "פתרון וסקירה",
"render.scene_review_help": "יש לסקור את הקומפוזיציה המקורית המלאה לפני ההחלה. מפרטי SCENE מתקדמים שאינם מקושרים אינם מוחלפים.",
"render.scene_scope_details": "היקף הקומפוזיציה",
"render.search_appearances": "חפש בין {count} מראות",
"render.setup_legacy_environment": "הגדרה ישנה זו משתמשת בסיבוב או בעוצמה ישנים של הסביבה. הערכים האלה נשמרים; יש להמיר אותם במפורש לפני שמירת משימת תמונה מלאה.",
"render.setup_name": "שם ההגדרה",
"render.setup_numeric_help": "השמירה מתעדת את שיטת התמונה הפעילה ואת כל ההגדרות המספריות שלה. טעינה מחדש או בחירת הגדרה אחרת מחליפה את הטיוטה הזאת; את המצלמה יש לשחזר בנפרד.",
@@ -2505,10 +2550,19 @@
"render.shot_remove_title": "להסיר את הצילום השמור?",
"render.shot_rename": "שינוי שם הצילום השמור",
"render.shot_saved_only": "יש לשמור קודם את הטיוטה הנוכחית. שכפול ושינוי שם שומרים על האפשרויות השמורות ועל הפניות המשאבים במדויק.",
"render.shots_camera_changed": "המצלמה השתנתה מאז שמירת הצילום",
"render.shots_name_help": "הזן שם ייחודי לצילום הנוכחי.",
"render.shots_no_result": "עדיין אין רינדור",
"render.shots_result": "רינדור {number} · {width} × {height}",
"render.shots_revert": "שחזר",
"render.shots_save": "שמור צילום",
"render.shots_update": "עדכן צילום",
"render.show_shots_label": "הצג את סרגל הצילומים",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "הגדרות גודל מוכנות",
"render.size_presets_pending": "יגיע עם עורך הפלט",
"render.sky_ground": "קרקע · RGB ליניארי",
"render.sky_horizon": "אופק · RGB ליניארי",
"render.sky_zenith": "זנית · RGB ליניארי",
@@ -2559,8 +2613,10 @@
"render.studio_sky_help": "מדרג שמיים מקורי לתאורה; לא מודל אטמוספרי מכויל.",
"render.studio_sun": "שמש",
"render.studio_sun_radius": "רדיוס זוויתי",
"render.studio_tiles_require_gpu": "סטודיו דורש מעקב נתיב במעבד הגרפי. בחר GPU בעורך הפלט.",
"render.studio_title": "סטודיו הדמיה",
"render.studio_tone_map": "מיפוי גוונים",
"render.studios_environments": "סטודיו וסביבות",
"render.subsurface_enable": "הילוך אקראי לפיזור פנימי",
"render.subsurface_help": "לדיאלקטרי סגור בלבד. פיזור ובליעת RGB הם מקדמים נפרדים לכל mm. המסלולים מתפזרים בתוך הגאומטריה בפועל, ואז נשברים או מוחזרים בגבול. יש לבטל העברת צל ישרה, הסרת רעש משטחית ונפח חיצוני; ולהשתמש בשכבת פרנל אחת. אינו שיידר דיפוזיה, אינו רשת צפיפות ואינו חומר מדוד. תווך צפוף עשוי לדרוש יותר דגימות ועומק מסלול.",
"render.subsurface_rate": "קצב התנגשויות הפיזור",
@@ -2668,6 +2724,7 @@
"select two components": "יש לבחור שני רכיבים",
"set by the sketch's lines": "נקבע לפי קווי הסקיצה",
"settings.display_quality_note": "ברמות עדינות יותר, פאות ומקצועות מעוקלים מוצגים חלקים יותר ויצירת הרשת אורכת זמן רב יותר. רק אזור התצוגה משתנה, לא התכן ולא קובצי הייצוא.",
"settings.double_click_components": "לחיצה כפולה על רכיב מפעילה אותו, או עורכת רכיב מקושר במקומו",
"settings.frame_rate_details_note": "מוסיף גרף של זמני התמונות האחרונות עם המשולשים שצוירו מעליו, היסטוגרמה של זמני התמונות ואת מה שה־GPU צייר. לחיצה על קצב התמונות בתצוגה מציגה או מסתירה אותם.",
"settings.frame_rate_note": "הצגת מספר הפריימים לשנייה בפינה הימנית התחתונה של התצוגה. כל עוד האפשרות פעילה, התצוגה מצוירת מחדש ברציפות.",
"settings.measure_axis_distances": "הצגת מרחקי X/Y/Z",
@@ -2680,6 +2737,7 @@
"settings.reset_intro": "ההגדרות האלה לא פועלות במחשב הזה והיו מונעות מ־SolidCraft לעלות, ולכן הן שונו:",
"settings.reset_title": "ההגדרות שונו",
"settings.supersampling_note": "התצוגה מצוירת ברזולוציה גבוהה יותר ומסוננת כלפי מטה: מקצוות, קווים ורשת חלקים יותר במסכים שמתחת ל־4K. הדבר צורך זמן GPU: בערך 2.25× פיקסלים ב־1.5×, ו־4× ב־2×.",
"settings.update_changed_links": "עדכון תכנים מקושרים שהשתנו כשלשונית מוצגת שוב",
"settings.window_system_details": "פרטים",
"settings.window_system_note_now": "ייכנס לתוקף אחרי הפעלה מחדש. כעת: {now}.",
"settings.window_system_wayland_limited": "חלק מהתכונות מוגבלות ב־Wayland מקורי.",
@@ -3283,6 +3341,24 @@
"ui.easyprint_uploading": "מעלה ל־Printables…",
"ui.edit": "עריכה",
"ui.editJointLimits": "עריכת גבולות מפרק",
"ui.edit_in_place": "עריכה במקום",
"ui.edit_in_place_after_turn": "העריכה תסתיים כשתור הסוכן יסתיים",
"ui.edit_in_place_agent_busy": "הסוכן עדיין עובד בתכן הזה; יש לנסות שוב כשתורו יסתיים",
"ui.edit_in_place_already_queued": "עריכה כבר ממתינה לסיום תור הסוכן",
"ui.edit_in_place_assembly_closed": "{name} כבר אינו פתוח",
"ui.edit_in_place_banner": "עריכה בתוך {name}",
"ui.edit_in_place_busy": "יש לסיים או לבטל קודם את מה שפתוח",
"ui.edit_in_place_none": "אין תכן מקושר בעריכה במקום",
"ui.edit_in_place_not_saved": "בחלק יש שינויים שלא נשמרו; יש לשמור כדי לסיים את העריכה",
"ui.edit_in_place_open_elsewhere": "{name} פתוח במופע אחר של SolidCraft",
"ui.edit_in_place_opens_after_turn": "החלק ייפתח כשתור הסוכן יסתיים",
"ui.edit_in_place_refresh_dropped": "ההרכבה השתנתה בזמן עדכון הקישורים; יש להריץ שוב",
"ui.edit_in_place_refresh_stopped": "עדכון הקישורים נעצר לפני שהסתיים",
"ui.edit_in_place_refreshing": "מעדכן קישורים ב-{name}…",
"ui.edit_in_place_save_first": "יש לשמור קודם את ההרכבה: התכנים המקושרים שלה נמצאים לפי הקובץ שלה",
"ui.edit_in_place_save_waits": "עדכון הקישורים פועל ב-{name}; יש לשמור לאחר שיסתיים",
"ui.edit_in_place_saved_elsewhere": "החלק נשמר לקובץ אחר; ההרכבה עדיין מקושרת אל {name}",
"ui.edit_in_place_wait": "יש להמתין עד שמה שפועל בתכן יסתיים",
"ui.edit_section_analysis": "עריכת ניתוח חתך",
"ui.ellipse": "אליפסה",
"ui.emboss_wrap_note": "פרופילי קווים ניצבים המשיקים לגליל נתמך נכרכים אוטומטית. יש לבחור דופן כדי לקבוע יעד.",
@@ -3357,6 +3433,7 @@
"ui.heading_edit": "עריכה",
"ui.heading_extrude": "שליפה",
"ui.heading_fillet": "עיגול פינה",
"ui.heading_finish_editing": "סיום עריכה",
"ui.heading_finish_sketch": "סיום סקיצה",
"ui.heading_form": "צורה",
"ui.heading_front": "חזית",
@@ -3616,6 +3693,8 @@
"ui.restore_defaults": "שחזור ברירות המחדל",
"ui.reverse_horizontal_pan_direction": "היפוך כיוון ההזזה האופקית",
"ui.reverse_horizontal_pan_tip": "גלילה אופקית בשתי אצבעות וגלגל האגודל מזיזים את המבט לכיוון ההפוך",
"ui.reverse_vertical_pan_direction": "היפוך כיוון ההזזה האנכית",
"ui.reverse_vertical_pan_tip": "גלילה אנכית בשתי אצבעות מזיזה בכיוון ההפוך",
"ui.reverse_zoom_direction": "היפוך כיוון הזום",
"ui.revolutions": "סיבובים",
"ui.revolve": "סיבוב",
@@ -3761,6 +3840,15 @@
"ui.updateToCurrentView": "עדכון למבט הנוכחי",
"ui.upload": "העלאה",
"ui.vertical_constraint": "אילוץ אנכי",
"ui.view_angles": "זוויות תצוגה",
"ui.view_angles_convention": "מעלות סביב הציר העליון. סבסוב 0° הוא התצוגה הקדמית, 90° שמאלית, −90° ימנית, 180° אחורית; עלרוד 90° הוא התצוגה העליונה; גלגול חיובי מסובב את המודל על המסך עם כיוון השעון.",
"ui.view_angles_help": "מציג מתחת לגיזמו הכיוון את זוויות העלרוד, הסבסוב והגלגול של התצוגה במעלות ואת סוג ההטלה. לחצו על התצוגה כדי להקליד זוויות מדויקות.",
"ui.view_angles_ortho": "אורתוגרפי",
"ui.view_angles_persp": "פרספקטיבה",
"ui.view_angles_pitch": "עלרוד",
"ui.view_angles_readout": "עלרוד {pitch} · סבסוב {yaw} · גלגול {roll}",
"ui.view_angles_roll": "גלגול",
"ui.view_angles_yaw": "סבסוב",
"ui.view_centre": "מרכז המבט",
"ui.viewport_theme_follow": "לפי ערכת הנושא",
"ui.visual_shaded_hidden_edges": "מוצלל עם מקצועות נסתרים",
File diff suppressed because it is too large Load Diff
+710
View File
@@ -37,6 +37,7 @@
"All open designs": "Minden megnyitott terv",
"Allowed expressions, separated by semicolons": "Engedélyezett kifejezések, pontosvesszővel elválasztva",
"Also deletes": "Szintén töröl",
"Also place them from the origin (fully constrained)": "Elhelyezés az origótól is (teljesen kényszerezve)",
"Anchor": "Horgony",
"Angle 2": "2. szög",
"Angle Display": "Szög megjelenítése",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Itt jelennek meg a megnyitott vagy mentett tervek.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Az Objektumig érték határozza meg. A szögtartomány szerkesztéséhez válassza a Szög lehetőséget.",
"Diameter": "Átmérő",
"Dimension new shapes": "Új alakzatok méretezése",
"Direction": "Irány",
"Discard": "Elvetés",
"Distance": "Távolság",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Húzással 5°-os lépésekben forgathatja a támaszt. Szabad forgatáshoz tartsa lenyomva az Alt vagy a Ctrl billentyűt.",
"Drive Joint": "Hajtó csukló",
"Duration": "Időtartam",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Minden új alakzat méretet kap a vázlat origójától is, amíg semmi sem marad szabadon. Az origóhoz vagy elhelyezett geometriához már kötött alakzat nem kap.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Minden megrajzolt alakzat megkapja az összes méretét a rajzolt méretekkel (a beírt értékek elsőbbséget élveznek). A vázlat által már meghatározott méret kimarad.",
"Edges": "Élek",
"Edit": "Szerkesztés",
"Edit Profile Sketch": "Profilvázlat szerkesztése",
@@ -1741,21 +1745,317 @@
"recovery.just_now": "épp most",
"recovery.min_ago": "{count} perce",
"recovery.never_saved": "soha nem mentett",
"render.adaptive_absolute": "Abszolút RGB-hibaküszöb",
"render.adaptive_coverage": "Lefedettségi hiba célértéke",
"render.adaptive_enable": "Minták kiosztása független próbamintákkal",
"render.adaptive_help": "Csak GPU-n. A független próbaminták elvetésre kerülnek, majd a program pixelenként 16 vagy több végleges mintát oszt ki, legfeljebb a „Minták pixelenként” értékig. Az RGB- és a lefedettségi variancia vezérli a kiosztást; a ritka fényutak kimaradhatnak, a korlátra érő pixelek pedig zajosak maradhatnak. A záró jelentés a ténylegesen elvégzett munkát számolja. Nincs szavatolt zaj- vagy időgarancia.",
"render.adaptive_minimum": "Végleges minták minimális száma",
"render.adaptive_pending": "Elérhető a GPU-s, független próbamintás adaptív mintakiosztás és a feltételes Fresnel-rétegzés. A tanúsított konvergencia, a ritka eseményekre vonatkozó garanciák és a CPU-s adaptív fényátvitel továbbra sem érhető el.",
"render.adaptive_pilots": "Próbaminták pixelenként",
"render.adaptive_relative": "Relatív RGB-hiba célértéke",
"render.add_ground": "Illesztett padló hozzáadása a beállításhoz",
"render.advanced_material_scope": "Egy véges, homogén GPU-s közeg érhető el, kifejezett korlátokkal. A sűrűségrácsok, az egymásba ágyazott üveg–térfogat kombinációk, a felszín alatti szóródású felületek, az elmozdítástérkép (displacement), a spektrális fényátvitel és a hozzá nem kötött fejlett anyagfogalmak továbbra sem érhetők el.",
"render.aging_add": "Öregítési réteg hozzáadása",
"render.aging_airborne": "Levegőben szálló por / résztvevő közeg",
"render.aging_airborne_help": "A levegőben szálló por külön, véges, homogén szóró térfogat. A fényátvitelt és a nyers EXR-t módosítja, nem a felületöregítési rétegeket. A meglévő térfogat-, üveg- és zajszűrési korlátozások továbbra is érvényesek; a program nem ad hozzá automatikusan légkört.",
"render.aging_all_bodies": "Minden alkalmas átlátszatlan test",
"render.aging_chips": "Lepattogzott festék",
"render.aging_class_any": "Minden átlátszatlan anyagosztály",
"render.aging_class_dielectric": "Csak nemfémes felületek",
"render.aging_class_metal": "Csak fémes felületek",
"render.aging_color": "Réteg színe · sRGB",
"render.aging_coverage": "Lefedettség",
"render.aging_dust": "Lerakódott por",
"render.aging_empty": "Nincs öregítési réteg: az eredeti felületek változatlanok maradnak.",
"render.aging_fading": "Kifakult bevonat",
"render.aging_grime": "Szennyeződés és foltosodás",
"render.aging_help": "Legfeljebb nyolc optikai réteg kombinálható, sorrendben. A rozsda és a patina szerkesztett megjelenések, nem kor- vagy korróziószimulációk. A léptéket világ-milliméterben kell megadni. A program nem módosít geometriát, tömeget vagy mérnöki tulajdonságot; az üveg és a passzív díszletek ki vannak zárva.",
"render.aging_metallic": "Réteg fémes hányada",
"render.aging_origin": "Mező origója · világ mm",
"render.aging_patina": "Rézzöld patina",
"render.aging_refresh_targets": "Aktuális testek vizsgálata",
"render.aging_roughness": "Réteg érdessége",
"render.aging_rust": "Oxidált vas / rozsda",
"render.aging_scale": "Minta léptéke",
"render.aging_scratches": "Finom karcolások",
"render.aging_target": "Cél és koordináták",
"render.aging_target_help": "A megnevezett célnak továbbra is egyeznie kell a rögzített indexszel és névvel. A globális maszkok a világhoz vannak rögzítve, nem követik a mozgó alkatrészeket. Ez nem üregfelismerés és nem valódi élkopás. További testek eléréséhez szűrje a listát.",
"render.aging_target_search": "Testnevek szűrése",
"render.aging_upward": "Felfelé néző lerakódás",
"render.all_controls_help": "Az összes jelenlegi vezérlő részletes áttekintése. A szakaszoldalak fókuszált szerkesztést tesznek lehetővé, a mögöttes kérés módosítása nélkül.",
"render.all_shots_label": "Összes felvétel",
"render.appearance_physics_separate": "A vizuális megjelenés nem rendel hozzá sűrűséget, hőtani adatot vagy más mérnöki tulajdonságot.",
"render.availability_native": "Natív összeállítás; alkalmazás előtt tekintse át",
"render.availability_projection": "Támogatott vetítés; lásd a hatókört és a kihagyásokat",
"render.availability_reference": "Referenciaadat; nem automatikus hozzárendelés",
"render.backdrop_alpha_conflict": "Válasszon: ez a háttér vagy az átlátszó PNG-kimenet. A renderelő egyik beállítást sem hagyja csendben figyelmen kívül.",
"render.backdrop_enable": "Csak kamerára vonatkozó színátmenetes háttér használata",
"render.backdrop_first": "Kezdő-/középszín",
"render.backdrop_help": "Ez a képernyőtérbeli háttér nem világít, nem vet árnyékot, nem tükröz, és nem jelképez terepet. Ki van zárva a nyers EXR-ből. A geometria, a fényforrások és a HDR-környezet független marad.",
"render.backdrop_horizontal": "Vízszintes színátmenet",
"render.backdrop_radial": "Sugaras színátmenet",
"render.backdrop_radius": "Sugár",
"render.backdrop_second": "Záró-/szélszín",
"render.backdrop_vertical": "Függőleges színátmenet",
"render.backdrop_x": "X középpont",
"render.backdrop_y": "Y középpont",
"render.background": "Jelenet háttere",
"render.background_camera_section": "Kamera háttere · PNG-megjelenítés",
"render.background_completed_frozen": "A megjelenített eredmény egy befagyasztott, elkészült kép. A háttér szerkesztése nem festi újra automatikusan ezt az eredményt. Csak a kamerát érintő változtatásokhoz használja a „Színkorrekció újra” funkciót, új fizikai díszlethez pedig a Renderelést.",
"render.background_hdr_separate": "A jelenlegi HDR-erőforrások megvilágítják a felületeket és tükröződnek rajtuk, de nem jelennek meg automatikusan panorámaként a modell mögött. A színátmenet módosítása nem forgatja el és nem színezi át a megvilágítást.",
"render.background_lighting_section": "HDR-megvilágítás · a kamera hátterétől független",
"render.background_no_alpha_override": "A kamera háttere nem kerül csendben az átlátszó kimenetre. A nyers mesterkép újbóli színkorrekciója a rögzített lefedettséget használja, és nem alkalmaz újra zajszűrést; a forrás EXR változatlan marad.",
"render.background_not_light": "A háttérszín megjelenítési elem, nem további fényforrás.",
"render.background_regrade": "Alkalmazás a megőrzött nyers mesterképen",
"render.background_stage_occlusion": "Ez a felvétel fizikai díszletgeometriát tartalmaz. Egy nagy padló vagy fal kitöltheti a képkockát, és eltakarhatja a csak kamerára vonatkozó hátteret. Törölje vagy méretezze át a díszletet szándékosan, vagy módosítsa a fizikai visszaverőképességét. Az újbóli színkorrekció nem tudja eltávolítani a rögzített geometriát.",
"render.background_workflow": "Válassza ki a kívánt hátteret: csak kamerára vonatkozó szín/színátmenet, fényt fogadó fizikai díszlet vagy HDR-megvilágítás. Ezek egymástól függetlenek. Az élő előnézet modellezési nézet; a kamerás képfeldolgozás megtekintéséhez renderelje újra a képet, vagy végezzen újbóli színkorrekciót egy megőrzött mesterképen.",
"render.base_appearance": "Szerkeszthető testmegjelenés",
"render.base_apply": "Testmegjelenés alkalmazása",
"render.base_apply_help": "Egyetlen visszavonható vizuális hozzárendelés az áttekintett pontos testhez. A meglévő lapspecifikus stílusok és mérnöki anyagok külön maradnak.",
"render.base_color": "Alapszín · sRGB",
"render.base_metallic": "Fémes hányad",
"render.base_opaque_only": "Ez a szerkesztő megőrzi az átlátszatlan test szemantikáját. Az optikai áteresztéshez használja a külön üvegvezérlőket.",
"render.bloom_enable": "Bloom megjelenítése",
"render.bloom_help": "Kreatív, csak a kimenetre vonatkozó fénykisugárzás a pozitív lineáris csúcsfényekből, három normalizált dobozszűrő-menettel szétterítve. A sugár kimeneti pixelben értendő. Lineáris megjelenítési fényhez adódik az sRGB előtt; nem lencsehatás, nem térfogati effektus és nem javítja a konvergenciát. A nyers EXR változatlan.",
"render.bloom_opaque": "A bloomhoz átlátszatlan kimenet szükséges. Az átlátszó PNG-t a program elutasítja, nem lapítja csendben.",
"render.bloom_radius": "Bloom sugara",
"render.bloom_strength": "Bloom erőssége",
"render.bloom_threshold": "Lineáris csúcsfény-küszöb",
"render.browse_capabilities": "Teljes képességkatalógus megtekintése",
"render.browse_environments": "Eredeti HDR-környezetek böngészése",
"render.browse_native_scenes": "Natív stúdiók böngészése",
"render.browse_physical": "Fizikai referenciák megtekintése",
"render.browse_quality": "Minőségi specifikációk megtekintése",
"render.browse_rigs": "Előre elkészített fényfelállások böngészése",
"render.browse_scene_specs": "Speciális jelenetspecifikációk böngészése",
"render.browse_surfaces": "Előre elkészített felületek böngészése",
"render.browser_library": "Könyvtár",
"render.browser_model": "Modell",
"render.camera_distance": "Szem–cél távolság",
"render.camera_exact_help": "Világ-milliméterben; a szögek fokban jelennek meg, és radiánban mentődnek. A navigáció ugyanazt a kamerát használja, mint a nézetablak.",
"render.camera_fov": "Függőleges látószög",
"render.camera_pitch": "Kamera billentése",
"render.camera_roll": "Gördülés",
"render.camera_set": "Renderkamera beállítása",
"render.camera_target": "Célpozíció · mm",
"render.camera_yaw": "Elfordulás",
"render.chromatic_offset": "Kromatikus éleltolás",
"render.clear_stage": "Mentett díszlet eltávolítása",
"render.copy_request": "JSON másolása",
"render.cpu_aa_help": "Térbeli minták: a több minta javítja az éleket, és növeli a renderelési időt.",
"render.cpu_area_add": "Téglalap alakú CPU-fényforrás hozzáadása",
"render.cpu_area_editor": "Téglalap alakú CPU-fényforrások",
"render.cpu_area_editor_help": "Teljes oldalvektorok milliméterben; az U és V vektorszorzata a kibocsátó oldal felé mutat. Ez eltér a GPU félél-vektoraitól.",
"render.cpu_area_full_u": "Teljes U oldal · mm",
"render.cpu_area_full_v": "Teljes V oldal · mm",
"render.cpu_area_samples": "Felületi fényforrás mintái",
"render.cpu_binding_confirm": "Test megerősítése",
"render.cpu_binding_stale": "A jelenet megváltozott. Renderelés előtt erősítse meg újra ezt a tükröződési célt.",
"render.cpu_body_choose": "Válasszon egy testet",
"render.cpu_body_filter": "Testek szűrése név szerint",
"render.cpu_body_filter_more": "Pontosítsa a szűrőt további testek megtekintéséhez.",
"render.cpu_body_missing": "Egy tükröződési cél hiányzik, rejtett, nem egyértelmű, vagy a neve hosszabb 128 bájtnál. Válassza ki újra.",
"render.cpu_budget": "CPU-erőforrásprofil",
"render.cpu_budget_bodies": "Testek felső korlátja",
"render.cpu_budget_compact": "Kompakt (régi korlátok)",
"render.cpu_budget_details": "Erőforráskorlátok",
"render.cpu_budget_help": "Kifejezetten válasszon nagyobb korlátokat. A felbontást és a mintákat a program soha nem csökkenti automatikusan.",
"render.cpu_budget_memory": "Feladat memóriájának felső korlátja",
"render.cpu_budget_not_guarantee": "Ezek befogadási felső korlátok, nem RAM-foglalás vagy sebességgarancia. A geometria, a filmpuffer és a megőrzött előnézetek közös memóriakeretet használnak; a renderelés megszakítható marad.",
"render.cpu_budget_resize": "A piszkozat meghaladja ezt a CPU-profilt vagy a kamera mintakeretét. Fogadjon el kifejezetten kisebb méreteket, vagy válasszon nagyobb profilt.",
"render.cpu_budget_studio": "Studio (nagy képek)",
"render.cpu_budget_triangles": "Háromszögek felső korlátja",
"render.cpu_budget_workstation": "Munkaállomás (nehéz jelenetek)",
"render.cpu_captured_hdr": "Ehhez a képhez rögzített HDR",
"render.cpu_check_capture_help": "Az Ellenőrzés és a Kezdés ugyanazt a fájlkivonatot ellenőrzi, vagy a beágyazott HDR-t használja. Minden kép megtartja a rögzített forrását.",
"render.cpu_check_changed": "A vezérlők vagy a modell az ellenőrzés után megváltoztak. Renderelés előtt ellenőrizze újra.",
"render.cpu_constant_help": "Az állandó sugársűrűség a visszavert vagy áteresztett sugarak számára látható. Nem ad közvetlen diffúz megvilágítást.",
"render.cpu_custom_directions": "Előbeállítás cseréje egyéni irányfényekre",
"render.cpu_direction": "A fény felé mutató irány (X, Y, Z)",
"render.cpu_directional": "Irányfény",
"render.cpu_directional_add": "Irányfény hozzáadása",
"render.cpu_environment": "CPU-környezet",
"render.cpu_environment_background": "A képháttér független a környezeti megvilágítástól.",
"render.cpu_environment_bounds": "A CPU-intenzitás 0–64 között lehet, a HDR-elforgatás véges érték ±1 000 000 radiánon belül, a HDR-minták száma pedig 1, 4, 16 vagy 64.",
"render.cpu_environment_constant": "Állandó környezet a másodlagos sugarakhoz",
"render.cpu_environment_none": "Nincs CPU-környezet",
"render.cpu_environment_samples": "HDR-megvilágítási minták",
"render.cpu_exposure_help": "A CPU-expozíciónak −16 és 16 EV között kell lennie. Az ezen a tartományon kívüli GPU-expozíció megmarad, amíg meg nem változtatja.",
"render.cpu_fixed": "Egyetlen kép",
"render.cpu_hdr_help": "Radiance .hdr, 2:1 arányú panoráma, legfeljebb 2048 × 1024 és 16 MiB. A CPU-hoz a fájlban kifejezetten megadott sRGB/D65 alapszínek kellenek; a nem megadott alapszínek és az EXR nem fogadhatók el.",
"render.cpu_hdr_reflection_help": "A HDR érdes tükröződéséhez teljesen fémes test- és lapfelületek szükségesek. Az Ellenőrzés jelzi a nem támogatott kombinációkat.",
"render.cpu_key_rim": "Főfény és kontúrfény",
"render.cpu_last_check": "Utolsó CPU-ellenőrzés",
"render.cpu_light_help": "Legfeljebb nyolc irányfény. Az üres egyéni lista kikapcsolja őket; egy előbeállítás kiválasztása visszaállítja annak fényeit. A színek lineáris RGB-értékek, az intenzitás pedig relatív, nem watt.",
"render.cpu_light_intensity": "Relatív intenzitás (0–64)",
"render.cpu_light_minimum": "Minimális távolság a csillapításhoz",
"render.cpu_light_position": "Pozíció a világban (X, Y, Z)",
"render.cpu_light_reference": "Referenciatávolság az intenzitáshoz",
"render.cpu_light_remove": "Fény eltávolítása",
"render.cpu_lighting": "Megvilágítási előbeállítás",
"render.cpu_lights": "CPU-fények",
"render.cpu_linear_color": "Lineáris szín (R, G, B)",
"render.cpu_neutral": "Semleges",
"render.cpu_opaque_required": "A CPU-s sugárkövetéshez átlátszatlan háttér kell. A folytatáshoz törölje az Átlátszó háttér jelölését.",
"render.cpu_options_pending": "Ez a CPU-panel még nem tudja szerkeszteni az emissziót, a felületi effekteket, az üveget és az anizotrópiát. Használat előtt törölje ezeket az API-beállításokat.",
"render.cpu_point": "Pontfény",
"render.cpu_point_add": "Pontfény hozzáadása",
"render.cpu_point_help": "Legfeljebb nyolc pontfény, amelyek a kijelölt irányított megvilágításhoz adódnak hozzá. A távolságok mm-ben értendők; a minimum nem haladhatja meg a referenciatávolságot.",
"render.cpu_primary_samples": "Élminták pixelenként",
"render.cpu_progressive": "Progresszív CPU",
"render.cpu_progressive_help": "A meglévő CPU-integrátor eredményeinek felhalmozása egy elsődleges mintából álló menetekben. A kijelölt tükröződésekhez egy minta szükséges; a területi fényekhez, a dielektrikumokhoz és az anizotrópiához az Egyetlen kép mód kell.",
"render.cpu_progressive_limits": "Legfeljebb 1 048 576 képpont és 16 777 216 képpont × minta kiértékelés. A minták módosítása sosem méretezi át automatikusan a képet.",
"render.cpu_progressive_seed": "CPU-mintavételi kezdőérték",
"render.cpu_progressive_spp": "minta pixelenként",
"render.cpu_reflection_add": "Érdes tükröződés hozzáadása",
"render.cpu_reflection_depth": "Tükröződési mélység (1–8)",
"render.cpu_reflection_empty": "Nincs kijelölt test: a jelenet tükröződései ki vannak kapcsolva.",
"render.cpu_reflection_help": "Válassza ki a testeket, és állítsa Ki, Tükör vagy Érdes értékre. Az Érdes a hozzárendelt felületi érdességet használja. A több minta és visszaverődés növeli az időt; ez korlátozott spekuláris fényátvitel, nem globális megvilágítás.",
"render.cpu_reflection_limit": "Legfeljebb 64 tükröző test támogatott.",
"render.cpu_reflection_mirror": "Tükör",
"render.cpu_reflection_off": "Ki",
"render.cpu_reflection_rough": "Érdes",
"render.cpu_reflection_samples": "Tükröződési minták (1–64)",
"render.cpu_reflections": "CPU-tükröződések",
"render.cpu_runtime_help": "A számszerű fény- és környezeti értékek a beállítással együtt mentődnek. A testek tükröződései és a HDR-fájlok ideiglenesek maradnak. A meglévő területi fény- és reflektorkúp-értékek megmaradnak.",
"render.cpu_sampling_mode": "CPU-mintavételi mód",
"render.cpu_shadows": "Árnyékvetés",
"render.cpu_summary": "CPU-s sugárkövetés · tükröződések · HDR · irány- és pontfények",
"render.cpu_warm_cool": "Meleg és hideg",
"render.diag_bodies": "Látható testek",
"render.diag_job_details": "Rögzített feladat részletei",
"render.diag_last_check": "Utolsó előellenőrzés",
"render.diag_memory": "Logikai befogadási becslés",
"render.diag_not_implemented": "Kifejezett képességhatárok",
"render.diag_preflight_details": "Előellenőrzés részletei",
"render.diag_request": "Pontos aktuális kérés",
"render.diag_triangles": "Háromszögek",
"render.discard_continue": "Piszkozat elvetése és folytatás",
"render.draft_confirm_help": "Az aktuális renderpiszkozat nem alkalmazott módosításokat tartalmaz. Mentse őket váltás előtt, vesse el őket kifejezetten, vagy folytassa a szerkesztést.",
"render.draft_confirm_title": "Szerkesztett renderbeállítások megőrzése",
"render.effects_gpu_only": "Ezekhez az effektekhez GPU-s útkövetés szükséges. Az oldal váltása soha nem váltja át automatikusan a renderelőt.",
"render.effects_help": "Kombinálhat sorba rendezett színstílusokat és képtérbeli lencseeffektusokat. A renderelés és a nyers mester újbóli színkorrekciója ugyanazokat a mentett beállításokat használja. A nyers EXR változatlan marad. Ezek eredeti művészi vezérlők, nem kalibrált lencse- vagy márkás filmemulációk.",
"render.effects_reset_lens": "Lencseeffektusok visszaállítása",
"render.effects_seed": "Mintázat kezdőértéke",
"render.emitted_axis": "Kibocsátási tengely",
"render.error_area_samples": "az area_samples értéke 1, 4, 16 vagy 64 lehet",
"render.error_binding_allocation": "nem sikerült lefoglalni az anyagkötést",
"render.error_body_bound": "a termék-előnézet túllépi a rögzített testek korlátját",
"render.error_checkpoint_dimensions": "az ellenőrzőpont méretei eltérnek a rögzített kéréstől",
"render.error_decode_budget": "túlcsordult a képdekódolási keret",
"render.error_denoise_setting": "érvénytelen natív zajszűrési beállítás",
"render.error_display_dimensions": "érvénytelen képmegjelenítési méretek",
"render.error_display_fit": "a képmegjelenítés nem fér el ezen az eszközön",
"render.error_display_height": "túlcsordult a megjelenítési magasság",
"render.error_display_width": "túlcsordult a megjelenítési szélesség",
"render.error_duplicate_face": "ismétlődő terméklap-megjelenés",
"render.error_export_document": "A renderexport dokumentuma megváltozott a célhely kiválasztása közben",
"render.error_face_cap": "a termék-előnézet túllépi a lapmegjelenések befogadási korlátját",
"render.error_finish_gesture": "fejezze be a modellezési mozdulatot az előnézet előtt",
"render.error_finish_operation": "fejezze be az aktuális modellezési műveletet a Renderelésre váltás előtt",
"render.error_fixed_preview": "a rögzített stúdióelőnézethez 0 expozíció, 0 környezeti elforgatás és 1 intenzitás szükséges",
"render.error_geometry_size": "túlcsordult a termékgeometria mérete",
"render.error_glass_recipe": "ismeretlen üvegrecept",
"render.error_gpu_preview": "A GPU-s termék-előnézet nem érhető el ezen a gépen. A mentett beállítások továbbra is elérhetők.",
"render.error_gpu_samples": "nem támogatott GPU-mintaszám",
"render.error_image_dimensions": "a renderkép méretei nem egyeznek a feladatáéval",
"render.error_image_profile": "a renderkép túllépi a rögzített erőforrásprofilt",
"render.error_interactive_command": "hozzá nem rendelt interaktív renderparancs",
"render.error_job_action": "nem interaktív képfeladathoz tartozó művelet",
"render.error_job_identity": "érvénytelen renderfeladat-azonosító: {error}",
"render.error_library_reply": "érvénytelen renderkönyvtár-válasz",
"render.error_material_binding": "hiányzó anyagkötés",
"render.error_no_completed_image": "a rendernek nincs elkészült képe",
"render.error_no_geometry": "nincs termékgeometria",
"render.error_no_scene": "nincs termékjelenet",
"render.error_opacity": "a termékmegjelenés átlátszatlansága érvénytelen",
"render.error_pbr_opacity": "az átlátszatlan PBR-hez 1-es átlátszatlanság szükséges",
"render.error_physical_glass": "a kiválasztott recept nem fizikai üveg",
"render.error_preview_device": "a termék-előnézethez mélységpuffert tartalmazó, telepített eszköz szükséges",
"render.error_product_triangle": "érvénytelen termékháromszög",
"render.error_provisional_identity": "érvénytelen ideiglenes renderazonosító vagy mintaszám",
"render.error_quality_bounds": "a minőségi előrejelzés túllépi a natív határokat",
"render.error_quality_method": "a minőségi előrejelzéshez ugyanaz a kifejezett GPU-módszer szükséges",
"render.error_quality_projection": "érvénytelen natív minőségi előrejelzés",
"render.error_regrade_identity": "érvénytelen újbóli színkorrekció-azonosító: {error}",
"render.error_scene_bodies": "hiányzó renderjelenet-testek",
"render.error_scene_body_limit": "a renderjelenet túllépi a testek számának korlátját",
"render.error_scene_identity": "érvénytelen renderjelenet-azonosító",
"render.error_setup_panicked": "a GPU-s útkövető inicializálása összeomlott",
"render.error_setup_stopped": "az inicializáló szál leállt anélkül, hogy gazdaobjektumot adott volna vissza",
"render.error_setup_worker": "nem sikerült elindítani az inicializáló szálat: {error}",
"render.error_source_preview": "a forrás-előnézet túllépi a bájtkeretét",
"render.error_surface_normals": "a PBR-hez nem nulla felületi normálvektorok szükségesek",
"render.error_surface_reply": "érvénytelen, saját készítésű felületválasz",
"render.error_triangle_bound": "a termék-előnézet túllépi a nyolcmillió háromszöges forráshatárt",
"render.error_triangle_count": "a termék háromszögszámának túlcsordulása",
"render.error_upload_slot": "a termék-előnézet feltöltési helye nem érhető el",
"render.error_vertex_allocation": "a termék-előnézet csúcspont-foglalása sikertelen",
"render.error_vertex_envelope": "a termék-előnézet túllépi a csúcsadatokra megengedett {limit} MiB-os keretet; a geometria nem lett egyszerűsítve",
"render.error_vertex_packing": "a termék-előnézet csomagolása eltér a jóváhagyott csúcsadatoktól",
"render.error_visible_solid": "Hozzon létre látható szilárd testet a Tervezésben, hogy itt előnézetet kapjon.",
"render.exit_focus": "Kilépés a fókuszból",
"render.export_display": "Exportálás: megjelenítési PNG",
"render.export_image_label": "Kép exportálása",
"render.export_linear": "Exportálás: nyers lineáris EXR",
"render.exr_pending": "A GPU meg tudja őrizni a nyers lineáris EXR-t. A tömörítés, a többrétegű képek és a kiegészítő renderelési passzok még nem érhetők el.",
"render.film_grain": "Fényképi szemcsézet",
"render.fit": "Termék illesztése",
"render.fixed_camera": "Kamera",
"render.fixed_world": "Világ",
"render.flare_ghosts": "Szellemgyűrűk forrásonként",
"render.flare_halo": "Lencsefény-udvar",
"render.flare_streak": "Anamorf stílusú csík",
"render.flare_strength": "Fénycsúcsok lencsefény-erőssége",
"render.flare_threshold": "Lencsefény küszöbértéke (jelenet-lineáris)",
"render.fold_browser": "Böngésző összecsukása",
"render.gpu_depth": "Maximális útvonalmélység",
"render.gpu_options_help": "A mintaszám, a mélység, a kezdőérték és az expozíció ezzel a beállítással együtt mentődik. Csak az aktív képalkotási módszer mentődik.",
"render.gpu_path_failed": "A GPU-s útkövető nem érhető el",
"render.gpu_path_first_setup": "Az első beállítás ezen a GPU-n több percig is eltarthat; a SolidCraft közben használható marad. A későbbi indítások újra felhasználják a lefordított shadereket, ha az illesztőprogram megtartja őket.",
"render.gpu_path_preparing": "GPU-s útkövető: shaderek fordítása…",
"render.gpu_seed": "Véletlen kezdőérték",
"render.gpu_unavailable": "A GPU-s útkövetés nem áll készen ezen az eszközön.",
"render.ground_apply": "Padló illesztése és mentése",
"render.ground_gap": "Megadott hézagméret",
"render.ground_linear_rgb": "Diffúz visszaverődés · lineáris RGB",
"render.ground_margin": "Padló kiterjedésének margója",
"render.hdr_details": "HDR-forrás részletei",
"render.hdr_embedded": "Ebbe a tervbe mentett HDR",
"render.hdr_embedded_help": "A renderelés a tervbe foglalt bájtokat használja; az eredeti fájlra már nincs szükség.",
"render.hdr_file_captured": "A HDR-fájl ellenőrizve. A mentés beágyazza ezeket a bájtokat; ha a fájl megváltozik, ellenőrizze újra kifejezetten.",
"render.hdr_inspect": "HDR-fájl ellenőrzése",
"render.hdr_inspect_required": "Mentés vagy renderelés előtt válasszon ki és ellenőrizzen egy HDR-fájlt.",
"render.hdr_primaries_declared": "A forrás megadja a színprimereit.",
"render.hdr_primaries_srgb": "Színprimerek: sRGB/D65",
"render.hdr_primaries_undeclared": "A forrás nem ad meg primereket; ellenőrizze a renderelő színkövetelményeit.",
"render.hdr_resource_missing": "Ebből a tervből hiányzik a mentett HDR-erőforrás.",
"render.heading_batch": "KÖTEGELT",
"render.heading_frame": "KERET",
"render.heading_lens": "OBJEKTÍV",
"render.heading_results": "EREDMÉNYEK",
"render.heading_shots": "FELVÉTELEK",
"render.hide_shots_label": "Felvételsáv elrejtése",
"render.image_advanced": "Speciális GPU-vezérlők",
"render.image_cancelled": "Renderelés megszakítva",
"render.image_cancelling": "Megszakítás",
"render.image_completed": "A kép exportálásra kész",
"render.image_encoding": "PNG kódolása",
"render.image_export": "PNG exportálása",
"render.image_exposure": "Expozíció",
"render.image_failed": "A renderelés sikertelen",
"render.image_height": "Magasság",
"render.image_help": "CPU-előnézeti kép · PNG · hozzávetőleges átlátszóság",
"render.image_host_missing": "Nincs telepítve képgazdaprogram.",
"render.image_method": "Képalkotási módszer",
"render.image_overwrite": "Meglévő fájl cseréje",
"render.image_preparing": "Kép előkészítése",
"render.image_progressive": "Progresszív renderelés",
"render.image_queued": "Várakozás a renderelésre",
"render.image_reduce": "Próbáljon kisebb képet vagy egyszerűbb jelenetet.",
"render.image_running": "Kép renderelése",
"render.image_samples": "Minta pixelenként",
"render.image_scene_stale": "Fejezze be a modellezési műveletet, vagy frissítse a jelenetet, mielőtt képet ellenőrizne vagy indítana.",
"render.image_stale": "Ez a kép a későbbi módosítások előtt rögzített jelenetet használja.",
"render.image_start": "Renderelés indítása",
"render.image_supported": "A renderkérés támogatott; a sort és a memóriakészletet induláskor újra ellenőrzi.",
@@ -1765,20 +2065,430 @@
"render.image_unknown": "A renderelés állapota nem érhető el",
"render.image_use_largest": "A legnagyobb méret használata ennél az oldalaránynál:",
"render.image_width": "Szélesség",
"render.include_rig_cards": "Passzív derítőlapok és fényterelők belefoglalása",
"render.inner_half_angle": "Belső félszög",
"render.inspect_scene": "A rögzített jelenet összefoglalójának frissítése",
"render.inspector": "Vizsgáló",
"render.keep_editing": "Szerkesztés folytatása",
"render.layer_down": "Mozgatás lefelé",
"render.layer_enabled": "Réteg engedélyezve",
"render.layer_off_suffix": " (ki)",
"render.layer_remove": "Réteg eltávolítása",
"render.layer_strength": "Réteg erőssége",
"render.layer_up": "Mozgatás felfelé",
"render.lens_effects_help": "A lencsefény a tényleges lineáris képben legfeljebb négy különálló fényes forrást használ. A szellemképek, az udvar, a csíkok, a kromatikus eltolások és a radiális torzítás művészi, képtérbeli közelítések. A térbeli effektusokhoz átlátszatlan kimenet kell; a képen kívüli minták a kép szélét terjesztik ki. A szemcsézet determinisztikus. Sem a fizika, sem az EXR, sem a geometria nem változik.",
"render.lens_effects_title": "Objektívhatások és fényképi effektek",
"render.library_all": "Katalógus",
"render.library_all_states": "Minden elérhetőségi állapot",
"render.library_applied": "Az erőforrás-vetítés alkalmazva. Indítás előtt ellenőrizze a teljes renderelési kérést.",
"render.library_apply_hdr": "Mentés ezzel a HDR-környezettel",
"render.library_apply_maps": "Saját készítésű GPU-felülettérképek használata",
"render.library_apply_studio": "Saját készítésű stúdióvetítés mentése",
"render.library_apply_uniform": "Egységes, átlátszatlan megjelenés alkalmazása",
"render.library_authored_help": "Az eredeti, saját készítésű erőforrások szemléltető jellegűek, nem mért mérnöki adatok. Minden művelet csak a megnevezett vetítést alkalmazza.",
"render.library_blocked": "Blokkolva / kalibrálást igényel",
"render.library_capabilities": "Képességi specifikációk",
"render.library_center": "Elrendezés középpontja",
"render.library_clear_search": "Törlés",
"render.library_details": "Specifikáció és eredet",
"render.library_emitters_only_ack": "Csak fényforrások használata; a dokumentált passzív derítőlapok kihagyása",
"render.library_empty": "Nincs egyező erőforrás. Próbáljon más keresést vagy elérhetőségi szűrőt.",
"render.library_environment_concepts": "Környezeti koncepciók",
"render.library_extent": "Tárgy kiterjedése",
"render.library_favorite": "Hozzáadás a kedvencekhez",
"render.library_favorites": "Kedvencek",
"render.library_hdr": "Beépített HDR-környezetek",
"render.library_hdr_help": "Az eredeti HDR-t beágyazza a mentett beállításba. A szerzői hosszúsági kezdőpontot kifejezetten átszámítja; mentés után nincs szükség külső fájlra.",
"render.library_inspect_only": "Kijelöléssel megtekinthető; semmi sem alkalmazódik automatikusan. A kedvencek és a legutóbbiak előzményei ehhez a megnyitott dokumentum-munkamenethez tartoznak.",
"render.library_light_concepts": "Világítási koncepciók",
"render.library_maps_help": "A beépített térképek rögzített forrásokkal és helyi példányleképezéssel menthetők. Az ideiglenes optikai felülbírálások külön mód maradnak.",
"render.library_material_concepts": "Anyagkoncepciók",
"render.library_native_scenes": "Natív stúdiók",
"render.library_next": "Következő oldal",
"render.library_omitted": "Nincs belefoglalva",
"render.library_physical_profiles": "Fizikai referenciaprofilok",
"render.library_previous": "Előző oldal",
"render.library_quality_concepts": "Minőségi specifikációk",
"render.library_recent": "Legutóbbiak",
"render.library_replace_environment": "A meglévő környezet kifejezett cseréje",
"render.library_replace_studio": "A mentett világítás, környezet és díszlet cseréje",
"render.library_results": "Egyező erőforrások",
"render.library_rig_help": "Illessze be egyszer, egy megadott középponthoz és fizikai kiterjedéshez. A teljes elrendezések passzív derítőlapokat is tartalmaznak; a kalibrálási akadályok továbbra is elutasítást okoznak. A fényforrások és derítőlapok konzervatív hézagát mentés előtt ellenőrzi.",
"render.library_rigs": "Saját készítésű világítási elrendezések",
"render.library_save_maps": "Térképek mentése ebbe a beállításba",
"render.library_scene_bounds": "A rögzített jelenet határainak használata",
"render.library_scenes": "Jelenetspecifikációk",
"render.library_search": "Keresés a könyvtárban",
"render.library_select_hint": "Válasszon ki egy erőforrást a Könyvtárban a támogatott műveletei és korlátai megtekintéséhez.",
"render.library_selene": "SELENE átlátszatlan megjelenések",
"render.library_selene_shots": "SELENE felvételspecifikációk",
"render.library_short_blocked": "Nem érhető el",
"render.library_short_native": "Natív kompozíció",
"render.library_short_projection": "Támogatott vetítés",
"render.library_short_reference": "Csak referencia",
"render.library_short_specification": "Csak specifikáció",
"render.library_source_preview": "Forrástérkép előnézetének betöltése",
"render.library_source_preview_help": "Saját készítésű alapszín-forrástérkép. Ez nem renderelt vagy mért anyag-előnézet.",
"render.library_specification_only": "Csak specifikáció: nem teljes, futtatható előbeállítás. A szükséges effektek, erőforrások és a tárgy szerepeinek megvalósítását és hozzárendelését még külön el kell végezni.",
"render.library_specs": "Csak specifikációk",
"render.library_status": "Elérhetőség",
"render.library_surfaces": "Saját készítésű PBR-felületek",
"render.library_target": "Céltest",
"render.library_title": "Render-erőforrások könyvtára",
"render.library_unfavorite": "Eltávolítás a kedvencekből",
"render.library_uniform_ack": "Egységes közelítés használata térbeli vagy speciális effektek nélkül",
"render.library_usable": "Futtatható vetületek",
"render.light_anchor_pending": "A fények koordináta-rendszerének módosítása még nem támogatott.",
"render.lights_fixed_to": "Fények rögzítve ehhez",
"render.linear_help": "32 bites lebegőpontos RGBA-mastert őriz meg a zajszűrés, az expozíció, a tónusleképezés, a szűrők és a háttér előtt. Lineáris sRGB/D65; lefedettséggel előreszorzott. A többletmemória csak kifejezett engedéllyel használható. Nincs tömörítés vagy további passz.",
"render.linear_retain": "Nyers lineáris EXR megőrzése",
"render.linear_unavailable": "A kiválasztott befejezett képkockához nincs megőrzött EXR. Renderelés előtt engedélyezze a megőrzést; egy korábbi PNG-ből a nyers sugárzás nem állítható vissza.",
"render.look_add": "Színstílus hozzáadása",
"render.look_bleach": "Bleach bypass ihletésű",
"render.look_cool": "Hideg",
"render.look_cyanotype": "Cianotípia ihletésű",
"render.look_faded": "Kifakult nyomat",
"render.look_mono": "Monokróm",
"render.look_sepia": "Szépia",
"render.look_strength": "Stílus erőssége",
"render.look_teal_orange": "Kékeszöld / narancs",
"render.look_title": "Kreatív stílusrétegek",
"render.look_warm": "Meleg",
"render.mapping_scale": "Fizikai ismétlési szorzó",
"render.material_absorption": "Elnyelés R · G · B (mm-enként)",
"render.material_add": "Hozzáadás vagy szerkesztés ehhez a testhez",
"render.material_assignments": "Testhozzárendelések",
"render.material_binding_enable": "A test felülbírálásának belefoglalása",
"render.material_box": "Tengelyirányú doboz",
"render.material_browse": "Kép kiválasztása…",
"render.material_certification": "A zárt üveg geometriai távolságot használ. A topológiát, az irányítást, az átfedést és az optikai határokat a GPU-előkészítés során ellenőrzi a program; az Ellenőrzés csak a kérést fogadja el.",
"render.material_choose_body": "Válasszon jelenetbeli testet",
"render.material_closed": "Zárt szilárd háló",
"render.material_coat": "Átlátszó fedőlakk az alapanyagon",
"render.material_coat_enable": "Fedőlakk engedélyezése",
"render.material_coat_help": "Szemléltető dielektromos bevonat a meglévő átlátszatlan megjelenés fölött. A nulla súly változatlanul hagyja az alapot.",
"render.material_color_map": "Alapszín-kép (sRGB)",
"render.material_color_replace": "Az alaptérkép lecseréli a test színét",
"render.material_custom": "Egyéni szemléltető optika",
"render.material_enable": "GPU-s anyagfelülbírálások használata",
"render.material_filter": "Jelenettestek szűrése…",
"render.material_filter_help": "Legfeljebb 128 egyező test jelenik meg. Nagy jeleneteknél pontosítsa a szűrőt.",
"render.material_glass": "Üveg és optikai elnyelés",
"render.material_glass_enable": "Fizikai üveg használata ezen a testen",
"render.material_glass_exclusive": "Ebben a renderelőben az üveg nem osztozhat a testen fedőlakkal vagy futásidejű térképekkel.",
"render.material_glass_help": "Saját szemléltető receptek. A mintaszínek az áteresztést mutatják, nem renderelt előnézetet. Az elnyelés −ln(lineáris áteresztés) / referenciatávolság; az alfa változatlan.",
"render.material_gpu_required": "Ezek az aktív anyagfelülbírálások GPU-s útkövetést igényelnek. Az Ellenőrzés vagy a Kezdés előtt válassza a GPU-t, vagy tiltsa le a felülbírálásokat.",
"render.material_ior": "Törésmutató (IOR)",
"render.material_limits": "Legfeljebb 128 testfelülbírálás, 32 különálló üvegtest, 64 lakkréteg és 128 textúra-hozzárendelés. Az azonos térképek közös tárhelyen osztoznak; a tényleges eszköz- és összmemória-korlátok továbbra is érvényesek.",
"render.material_map_invalid": "A térképek útvonalainak korlátozott hosszúságú helyi útvonalaknak kell lenniük; a normálerősségnek végesnek kell lennie, és 0 és 1 között kell esnie.",
"render.material_map_required": "A térképek használata előtt válasszon színképet vagy normálképet.",
"render.material_maps": "Síkvetítésű szín- és normáltérképek",
"render.material_maps_enable": "Térképek engedélyezése ehhez az átlátszatlan testhez",
"render.material_maps_help": "PNG/JPEG legfeljebb 1024×1024 képpont; összesen 16 MiB kódolva. Az U és V egymásra merőleges, világ-mm-ben megadott ismétlési vektorok (legfeljebb 128 ismétlés). A szín sRGB; a normáladatok OpenGL +Y-t használnak. A fájlokat az Ellenőrzés/Kezdés pillanatában olvassa be a program.",
"render.material_metallic_map": "Fémességtérkép (lineáris)",
"render.material_normal_map": "Normálkép (OpenGL, +Y)",
"render.material_normal_strength": "Normál erőssége (0–1)",
"render.material_origin": "Leképezés origója X · Y · Z (mm)",
"render.material_refresh": "Jelenettestek frissítése",
"render.material_refresh_needed": "A jelenet megváltozott. Cél hozzáadása előtt frissítse a testlistát.",
"render.material_remove": "Hozzárendelés eltávolítása",
"render.material_repeat_u": "Egy U-ismétlés X · Y · Z (mm)",
"render.material_repeat_v": "Egy V-ismétlés X · Y · Z (mm)",
"render.material_revalidate": "Test újraellenőrzése",
"render.material_revalidate_needed": "Ez a hozzárendelés a jelenet egy korábbi revíziójához tartozik. Renderelés előtt ellenőrizze újra a test pontos azonosságát.",
"render.material_roughness": "Lakkréteg érdessége (0,045–1)",
"render.material_roughness_map": "Érdességtérkép (lineáris)",
"render.material_shadow": "Egyenes árnyéksugarak átengedése",
"render.material_target_missing": "A test sorszáma és neve már nem egyezik. Távolítsa el ezt a hozzárendelést, és válassza ki újra kifejezetten a kívánt testet.",
"render.material_thickness": "Vékonylemez vastagsága (mm)",
"render.material_thin": "Vékonylemez",
"render.material_title": "GPU-s képalapú anyagok",
"render.material_transient": "Ideiglenes optikai felülbírálások ehhez a dokumentumfülhöz. Nem kerülnek mentésre a tervben, a renderbeállításban vagy az anyagkönyvtárban.",
"render.material_v_up": "A textúra V iránya a képen felfelé mutat",
"render.material_weight": "Lakkréteg súlya (0–1)",
"render.method_cpu": "CPU-s sugárkövetés",
"render.method_gpu": "GPU-s útkövetés",
"render.method_limit_raster": "A raszteres mód a rögzített, átlátszatlan stúdió-előnézetet használja. A támogatott optikai vezérlőkhöz válasszon kifejezetten sugárkövetéses módszert.",
"render.method_raster": "CPU-s raszter",
"render.navigation_help": "A kamera úgy mozog, mint a Tervezésben (Beállítások › Navigáció). A Beállítás mentése rögzíti az aktuális kamerát.",
"render.nested_enable": "Igazolt egymásba ágyazott dielektrikumok",
"render.nested_help": "Legfeljebb 16 tartalmazó réteg; minden szülőnek konvexnek kell lennie, és minden gyermeknek szigorúan benne kell lennie. Metszések, érintkező felületek, vékonylemezek és egyenes árnyékátengedés esetén a kérés elutasításra kerül. A kamera belső állapota az igazolt hierarchiát követi. Nem hoz létre folyadékfelületet, és nem egyesíti az érintkező CAD-határokat.",
"render.opaque_image_summary": "Előnézeti PNG · átlátszatlan PBR · kevert átlátszóság",
"render.opaque_preview_help": "Átlátszatlan PBR és egyszerű színek; kevert átlátszóság. A fénytörés, a HDRI és a végső renderelés még nem érhető el.",
"render.optics_remove": "Mentett optika eltávolítása",
"render.optics_replace": "Ennek a célnak a mentett optikájának kifejezett cseréje",
"render.optics_save": "Optika mentése a beállításba",
"render.optics_saved": "Mentett optikai célok",
"render.optics_saved_help": "A pontos definíció-, elem- és példányazonosság offline újranyitás után is megmarad. A hiányzó, lecserélt vagy rejtett célokat a rendszer elutasítja; a mérnöki anyagok változatlanok maradnak. Mentse vagy vesse el a numerikus módosításokat, mielőtt eltávolít egy mentett célt.",
"render.outer_half_angle": "Külső félszög",
"render.output_format_status": "A PNG a kész megjelenített kép pontos mása. A választható GPU-s EXR a megjelenítési szűrők előtti nyers, jelenetlineáris FLOAT32 sugárzást őrzi meg. Az exportálás sosem helyettesíti az előnézeti gyorsítótárat vagy egy másik feladatot.",
"render.output_lock_ratio": "Képarány zárolása",
"render.output_over_budget": "A kért kép meghaladja a kiválasztott erőforráskeretet. Válasszon kifejezetten megfelelő méretet vagy profilt; automatikus visszaminősítés nem történik.",
"render.output_ratio_refused": "A kapcsolt méret meghaladja ennek a módszernek a mérethatárát. Az előző méret megmarad; oldja fel az arányt, vagy válasszon kisebb értéket.",
"render.output_swap_orientation": "Szélesség és magasság felcserélése",
"render.output_tools_inspector": "A méretet és a formátumot a Kimenet panelen szerkesztheti.",
"render.page_aging": "Öregedés és szennyeződés",
"render.page_all": "Minden vezérlő",
"render.page_appearance": "Megjelenés",
"render.page_background": "Hátterek",
"render.page_camera": "Kamera",
"render.page_diagnostics": "Diagnosztika",
"render.page_effects": "Lencse- és utómunka-effektek",
"render.page_environment": "Környezet",
"render.page_lighting": "Megvilágítás",
"render.page_output": "Kimenet",
"render.page_scene": "Jelenet",
"render.paint_label": "Festék",
"render.passive_stage": "Padló és passzív díszlet",
"render.passive_stage_help": "A véges méretű passzív panelek csak a renderelt képekhez tartoznak. Nem adnak hozzá CAD-testet vagy tömeget. Az elhelyezés alkalmazás után rögzített; ha metszik a termék határait, a program elutasítja. A CPU nem biztosít diffúz, közvetett megvilágítást.",
"render.perspective": "Perspektivikus kamera",
"render.physical_acknowledge": "Tudomásul veszem, hogy ez a részleges referencia az anyagminőség, az állapot és a forrás felülvizsgálatát igényli",
"render.physical_associations": "Fizikai jelöltek és szerepek",
"render.physical_background_help": "Valódi, passzív padló és fal, a kamera hátterétől elkülönítve. A ciklorámához 24 sokszögű sáv tartozik; nem végtelen vagy analitikusan sima felület. A mentett díszletet csak az Ön beleegyezésével cseréli le.",
"render.physical_copy_plan": "Terv másolása forrásokkal és kihagyásokkal",
"render.physical_cyclorama": "Sokszögű cikloráma illesztése",
"render.physical_floor_wall": "Fizikai padló és fal illesztése",
"render.physical_material_name": "Javasolt referenciaanyag-név",
"render.physical_omissions": "A natív kártyán nem ábrázolható tulajdonságok",
"render.physical_plan_only": "Csak olvasható terv elkészítve. Anyag nem jött létre, és nem lett hozzárendelve. A natív kártya áttekintésekor tartsa meg a bővített profilt és a kihagyásokat.",
"render.physical_prepare_plan": "Létrehozási terv előkészítése (nem alkalmazza)",
"render.physical_separate": "A megjelenés nem anyag-azonosítás. Ezek forrással ellátott referenciák, nem igazolt tényleges tulajdonságok. A meglévő tömeg, a mérnöki anyagok és az optika változatlan marad.",
"render.physical_unknown": "Nincs megállapított számértékű jelölt. Meg kell adni az anyagminőséget, az összetételt vagy a felépítést; az ismeretlen nem egyenlő a nullával.",
"render.pick_body": "Test",
"render.pick_component": "Komponens",
"render.pick_face": "Lap",
"render.pick_help": "Válasszon a Test, a Lap és a Komponens közül. Az üres területre kattintva a kijelölés törlődik; a Shift vagy a Ctrl hozzáad, illetve átkapcsol. A kiemelések csak az élő terméknézetben jelennek meg.",
"render.pick_label": "Kijelölés",
"render.pick_up_label": "Átvétel",
"render.pick_waiting": "A termék kijelölése még nem támogatott.",
"render.post_contrast": "Kontraszt",
"render.post_gain_b": "Kék erősítés",
"render.post_gain_g": "Zöld erősítés",
"render.post_gain_r": "Vörös erősítés",
"render.post_help": "Csak kreatív prezentációhoz. Az RGB-erősítések a tónusleképezés előtt érvényesülnek; a kontraszt, a telítettség és a vignetta a megjelenítéshez lineáris fényben követi azokat. A Renderelés indítása új fényterjedési mintákat hoz létre. Az újbóli színkorrekció a kiválasztott, megőrzött nyers mesterképet használja, zajszűrés és új sugarak nélkül.",
"render.post_reset": "Prezentációs szűrők visszaállítása",
"render.post_saturation": "Telítettség",
"render.post_title": "Prezentációs szűrők",
"render.post_vignette": "Vignetta",
"render.preview": "Beépített előnézet",
"render.preview_help": "Raszteres árnyalás és kevert átlátszóság. A fénytörés, a HDRI és a végső renderelés még nem érhető el.",
"render.preview_image_settings_help": "Az élő előnézet rögzített stúdiómegvilágítást használ. Az expozíció és a képmegvilágítás az Ellenőrzéskor vagy az Indításkor érvényesül a képfeladaton.",
"render.preview_lighting_help": "Az élő előnézet csak közvetlen fényt mutat, árnyékok nélkül.",
"render.preview_retry": "Élő előnézet újrapróbálása",
"render.preview_unavailable_help": "Az élő előnézet nem érhető el. A mentett beállítások és a képfeladat vezérlői továbbra is elérhetők. Módosítsa a jelenetet, vagy kifejezetten próbálja újra; az elutasított jelenetet a program nem építi újra minden képkockánál.",
"render.preview_upload": "Élő előnézet csúcspontadatai",
"render.preview_upload_help": "A pontos előnézeti csúcspontbájtok, nem a teljes GPU- vagy folyamatmemória. A geometria nincs egyszerűsítve. A képfeladatok saját befogadási ellenőrzést és megvilágítást használnak.",
"render.progressive_image_summary": "Előnézeti PNG · PBR és üveg · progresszív minták",
"render.property_conditions": "Feltételek: {value}",
"render.property_fallback": "tulajdonság",
"render.property_qualifier": "Minősítő: {value}",
"render.property_source": "Forrás: {id} - {locator}",
"render.property_uncertainty": "Bizonytalanság: {value}",
"render.property_unknown": "ismeretlen",
"render.quality_ack": "A rögzített mintakeret vetületének és a kihagyásoknak a tudomásul vétele",
"render.quality_apply": "Ezen rögzített mintakeret használata",
"render.quality_projection_help": "A Q előbeállítások jövőbeli követelményeket is tartalmaznak. Ez a művelet csak egy támogatott, rögzített mintaszámú PNG-keretet vetít ki, és kifejezetten kihagyja az adaptív leállítást, a nyers lineáris kimenetet és a független transzmissziós korlátokat.",
"render.quality_review": "Mintakeret áttekintése",
"render.queue_pending": "Ebben a felületen nincs automatikus gyártási sor vagy animációs renderelő. A kész állóképek külön exportálhatók.",
"render.radial_distortion": "Radiális torzítás",
"render.regrade_action": "Nyers mesterkép újbóli színkorrekciója (zajszűrés nélkül)",
"render.regrade_help": "Külön PNG-t hoz létre a kiválasztott, kész nyers mesterképből, ezekkel a prezentációs beállításokkal. Nem számít sugarakat, nem módosítja a rögzített méretet, kamerát és fényeket, és nem írja felül az EXR-t. A zajszűrés nem kerül újra alkalmazásra: a nyers mesterképek nem őrzik meg a vezetőpuffereit. A származtatott kép ugyanazokkal a feladatvezérlőkkel exportálható.",
"render.regrade_label": "Újbóli színkorrekció",
"render.reload_settings": "Mentett beállítások újratöltése",
"render.replace_ground": "A meglévő díszlet cseréjének megerősítése",
"render.replace_label": "Csere",
"render.replace_saved_surface": "Az ehhez a célhoz tartozó meglévő mentett kötés cseréje",
"render.restore_camera": "Mentett kamera visszaállítása",
"render.result_actual_help": "Egy képpont jut egy kijelzőképpontra.",
"render.result_actual_size": "100%",
"render.result_capture": "Rögzített revízió",
"render.result_current": "A rögzített modellrevízió aktuális.",
"render.result_empty": "Még nincs kész kép. Ellenőrizze a beállításokat, majd indítsa el a renderelést.",
"render.result_fit": "Kép illesztése",
"render.result_job": "Feladat",
"render.result_navigation": "A pásztázás és a nagyítás a Navigáció beállításait követi. Szóköz + húzás: pásztázás.",
"render.result_open": "A kész kép megnyitása a fő vásznon.",
"render.result_preview": "Élő előnézet",
"render.result_provisional": "Ideiglenes CPU-kép",
"render.result_provisional_help": "Ez az ellenőrzőpont nem exportálható. Az exportálás az utolsó kész eredményt használja; a megszakítás erre az eredményre tér vissza.",
"render.result_reduced_display": "A megjelenített előnézet a nézetablak eszköz- és gyorsítótár-korlátjára van csökkentve. A megőrzött PNG és az exportált kép teljes felbontású marad; ennél a csökkentett nézetnél a natív 100%-os vizsgálat nem érhető el.",
"render.result_retained": "Az utolsó kész kép látható; újabb renderelés még nem váltotta le.",
"render.result_sequence": "Ellenőrzőpont",
"render.result_title": "Renderelési eredmény",
"render.return_design": "Vissza a Tervezéshez",
"render.review_stale": "Ez az áttekintés elavult. Az alkalmazás előtt oldja fel, vagy ellenőrizze újra.",
"render.ribbon_aging": "Öregítés",
"render.ribbon_backgrounds": "Hátterek",
"render.ribbon_check": "Ellenőrzés",
"render.ribbon_check_help": "A Renderelés által elküldendő pontos aktuális tervezet érvényesítése. Nincs tartalék renderelő, csendes átméretezés vagy erőforráscsere.",
"render.ribbon_edit_lights": "Fények szerkesztése",
"render.ribbon_effects": "Effektek",
"render.ribbon_environment_help": "A HDR-megvilágítás, a csak kamera számára látható hátterek és a fizikai díszletfelületek különálló vezérlők, kifejezett csere-jóváhagyással.",
"render.ribbon_finish_dialog": "Először fejezze be az aktuális fájl- vagy megerősítő párbeszédpanelt.",
"render.ribbon_frame": "Keretezés",
"render.ribbon_hdr_library": "HDR-könyvtár",
"render.ribbon_job_active": "Már fut egy renderelés; egy másik indítása előtt kifejezetten szakítsa meg.",
"render.ribbon_light_rigs": "Fényfelállások",
"render.ribbon_lights_help": "A meglévő fényfelállások megtekintése vagy a támogatott fények szerkesztése anélkül, hogy az aktuális beállítás lecserélődne, amíg a módosítást kifejezetten nem alkalmazza.",
"render.ribbon_materials": "Anyagok",
"render.ribbon_materials_help": "Megnyitja a közös megjelenésvizsgálót és az eredeti felületkönyvtárat. Az optikai módosítások soha nem változtatják meg csendben a mérnöki tulajdonságokat.",
"render.ribbon_no_active_job": "Nincs megszakítható aktív renderelés.",
"render.ribbon_no_result": "A kép pontos exportálása előtt fejezzen be egy renderelést.",
"render.ribbon_no_saved_camera": "A kamera visszaállítása előtt mentsen egy felvételt.",
"render.ribbon_saved_camera": "Mentett kamera",
"render.ribbon_shots": "Felvételek",
"render.ribbon_studios": "Stúdiók",
"render.ribbon_studios_help": "A megvalósított stúdiókompozíciók böngészése, és a cseréik áttekintése az alkalmazás előtt. A csak elképzelés szintű jelenetek megjelölve maradnak.",
"render.ribbon_surface_maps": "Felülettérképek",
"render.sampling_title": "Adaptív és transzmissziós mintavételezés",
"render.save_continue": "Mentés és folytatás",
"render.save_setup": "Beállítás mentése",
"render.save_shot": "Felvétel mentése",
"render.saved_maps_runtime_conflict": "A mentett felületkötések nem keverhetők ideiglenes optikai felülírásokkal vagy mentetlen HDR-rel. Mentse el a HDR-t, vagy kifejezetten távolítsa el az ideiglenes bemeneteket.",
"render.saved_surface_remove": "Mentett kötés eltávolítása",
"render.saved_surfaces": "Mentett felületkötések",
"render.saved_surfaces_help": "A rögzített beépített térképek a kiválasztott előfordulást követik, helyi milliméterekben. A lecserélt vagy hiányzó cél hiba, soha nem automatikus újrahozzárendelés.",
"render.scene_apply": "Áttekintett stúdió alkalmazása",
"render.scene_consent": "A megvilágítás, a környezet, az expozíció és a díszlet cseréjének megerősítése",
"render.scene_preserved_fields": "A kamera, a mintavételezés, a méretek, az optikai kötések, a CAD-geometria és a mérnöki anyagok megmaradnak.",
"render.scene_preserves_design": "Megvilágítás és passzív díszlet összeállítása a látható tárgyhoz. A geometria, a mérnöki anyagok és a kamera külön marad.",
"render.scene_replaces": "Lecseréli",
"render.scene_review": "Feloldás és áttekintés",
"render.scene_review_help": "Az alkalmazás előtt tekintse át a teljes natív kompozíciót. A nem kötött, speciális JELENET-specifikációk nem kerülnek helyettesítésre.",
"render.scene_scope_details": "A kompozíció hatóköre",
"render.setup_legacy_environment": "Ez a régebbi beállítás örökölt környezetforgatást vagy -intenzitást használ. Ezek az értékek megmaradnak; teljes képfeladat mentése előtt kifejezetten alakítsa át őket.",
"render.setup_name": "Beállítás neve",
"render.setup_numeric_help": "A Mentés rögzíti az aktív képmódszert és annak összes numerikus beállítását. Az újratöltés vagy másik beállítás választása felülírja ezt a tervezetet; a kamerát külön állítsa vissza.",
"render.setup_offline_help": "Ezt a módszert a renderelője nélkül is szerkesztheti és mentheti. Az Ellenőrzéshez és az Indításhoz elérhető gazdagép szükséges.",
"render.setup_runtime_unsupported": "Ezt a teljes feladatot még nem lehet menteni: térképeket vagy jelenettest-kötéseket tartalmaz. Hordozható beállítás mentése előtt távolítsa el ezeket az ideiglenes bemeneteket.",
"render.setup_save_missing": "A parancs befejezése után a mentett renderkonfiguráció nem található.",
"render.sharpening": "Részletélesítés",
"render.shell_tab_appearance": "RENDERELÉS: MEGJELENÉS",
"render.shell_tab_camera": "RENDERELÉS: KAMERA",
"render.shell_tab_scene": "RENDERELÉS: JELENET",
"render.shot_duplicate": "Mentett felvétel kettőzése",
"render.shot_manager": "Mentett felvételek",
"render.shot_new_name": "Új felvétel neve",
"render.shot_remove": "Mentett felvétel eltávolítása",
"render.shot_remove_help": "Csak ez a mentett beállítás kerül eltávolításra. A forrásgeometria és a kész képek megmaradnak; a művelet visszavonható.",
"render.shot_remove_title": "Eltávolítja a mentett felvételt?",
"render.shot_rename": "Mentett felvétel átnevezése",
"render.shot_saved_only": "Előbb mentse az aktuális tervezetet. A kettőzés és az átnevezés megőrzi a pontos mentett beállításokat és erőforrás-hivatkozásokat.",
"render.show_shots_label": "Felvételsáv megjelenítése",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Talaj · lineáris RGB",
"render.sky_horizon": "Horizont · lineáris RGB",
"render.sky_zenith": "Zenit · lineáris RGB",
"render.soft_focus": "Lágy fókusz",
"render.spot_cone": "Spotfény kúpja",
"render.stage_frame": "Képkivágás",
"render.stage_light": "Fény",
"render.stage_look": "Stílus",
"render.stage_orthographic": "Ortografikus",
"render.stage_output": "Kimenet",
"render.stage_panel_count": "Mentett panelek",
"render.stage_preview_note": "Integrált előnézet · közvetlen fény",
"render.strip_label": "Sáv",
"render.studio_add_area": "Területi fényforrás hozzáadása",
"render.studio_ambient": "Állandó környezeti sugárzás",
"render.studio_ambient_rgb": "Állandó környezeti sugárzás (lineáris RGB)",
"render.studio_aperture": "Rekesznyílás sugara",
"render.studio_area": "Területi fényforrás",
"render.studio_area_help": "Legfeljebb négy egyoldalú téglalap. Az egymásra merőleges U és V félélek határozzák meg a méretet; az U × V a megvilágított oldal felé mutat. A koordináták a világtérben értendők, milliméterben.",
"render.studio_center": "Középpont X, Y, Z (mm)",
"render.studio_denoise": "Zaj csökkentése a kész képen",
"render.studio_denoise_help": "Záró, élérzékeny szűrő; a finom részletek elmosódhatnak. Az üveg és az éles tükröző felületek kikerülik a szűrőt.",
"render.studio_direction": "A Nap felé mutató irány (X, Y, Z)",
"render.studio_environment": "Környezet",
"render.studio_environment_bounds": "A környezet elforgatásának végesnek kell lennie ±1 000 000 radiánon belül, az intenzitásnak pedig 0 és 100 között kell lennie.",
"render.studio_environment_none": "Nincs környezeti térkép",
"render.studio_focus": "Tengelyirányú fókusztávolság",
"render.studio_half_u": "U félél (mm)",
"render.studio_half_v": "V félél (mm)",
"render.studio_hdr": "Radiance HDR-fájl",
"render.studio_hdr_browse": "HDR kiválasztása…",
"render.studio_hdr_help": "Radiance .hdr, 2:1 arányú panoráma, legfeljebb 2048 × 1024. Az EXR nem érhető el. A színfeltevés csak akkor érvényes, ha az alapszínek nincsenek megadva.",
"render.studio_hdr_required": "Válasszon ki egy helyi .hdr fájlt.",
"render.studio_hdr_srgb": "A meg nem adott alapszínek értelmezése lineáris sRGB-ként",
"render.studio_intensity": "Környezet intenzitása",
"render.studio_lens": "Mélységélesség",
"render.studio_lens_perspective": "A mélységélességhez perspektivikus kamera szükséges.",
"render.studio_lighting": "Stúdióvilágítás",
"render.studio_lighting_enable": "Egyéni stúdióvilágítás használata",
"render.studio_needs_review": "Ellenőrizze a módszert és a beállításokat",
"render.studio_radiance": "Lineáris RGB sugárzás",
"render.studio_ready": "Készen áll az ellenőrzésre",
"render.studio_remove_area": "Területi fényforrás eltávolítása",
"render.studio_rotation": "Környezet elforgatása",
"render.studio_runtime_help": "A numerikus stúdióbeállítások és az ellenőrzött HDR-források menthetők a beállítással együtt. A testek optikai és anyagfelülbírálásai ideiglenesek maradnak, és nem módosítják a mentett megjelenéseket.",
"render.studio_saved": "Mentett beállítás / aktuális kamera",
"render.studio_sky": "Művészi égbolt",
"render.studio_sky_help": "Saját égbolt-színátmenet a megvilágításhoz; nem kalibrált légköri modell.",
"render.studio_sun": "Nap",
"render.studio_sun_radius": "Szögsugár",
"render.studio_title": "Renderstúdió",
"render.studio_tone_map": "Tónusleképezés",
"render.subsurface_enable": "Belső szóródás véletlen bolyongással",
"render.subsurface_help": "Csak zárt dielektrikumhoz. A szóródás és az RGB-elnyelés külön, milliméterenkénti együtthatók. A fényutak a tényleges geometrián belül szóródnak, majd a határfelületen megtörnek vagy visszaverődnek. Kapcsolja ki az egyenes árnyékáteresztést, a felületi zajcsökkentést és a külső térfogatot; egy Fresnel-réteget használjon. Nem diffúziós shader, sűrűségrács vagy mért anyag. A sűrű közegekhez több mintára és nagyobb útmélységre lehet szükség.",
"render.subsurface_rate": "Szóródási ütközési gyakoriság",
"render.tone_aces_fitted": "ACES (illesztett)",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "A GPU-s üveg a tanúsított, nem átfedő közegeket támogatja. A korlátozás nélküli egymásba ágyazott közegek és a zajmentes áteresztésbecslő nem érhetők el.",
"render.transmission_strata": "Feltételes Fresnel-rétegek",
"render.transmission_strata_help": "Az 1 az eredeti véletlenszám-sorozatot őrzi meg. A 2 vagy 4 részút rétegezi az első üvegbeli visszaverődés/áteresztés választást, változatlan Snell- és elnyelési törvények mellett. Több út több munkát jelent; ez nem zajcsökkentés, nem egymásba ágyazott közegek támogatása, és nem ígéret gyorsabb renderelésre.",
"render.tree_add_light": "Fényforrás hozzáadása",
"render.tree_add_shot": "Felvétel hozzáadása",
"render.tree_browser": "Renderböngésző",
"render.tree_by_look": "Stílus szerint",
"render.tree_by_object": "Objektum szerint",
"render.tree_constant": "Állandó környezet",
"render.tree_default": "Alapértelmezett",
"render.tree_directional": "Irányított",
"render.tree_environment": "Környezet",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} lap",
"render.tree_face_one": "{count} lap",
"render.tree_fixed_studio": "Rögzített stúdió",
"render.tree_hdr": "HDR",
"render.tree_lights": "Fényforrások",
"render.tree_lights_pending": "A névvel ellátott fényforrás-parancsok még nem érhetők el.",
"render.tree_mixed": "Vegyes",
"render.tree_more": "még {count}",
"render.tree_mute": "Fényforrás némítása",
"render.tree_no_environment": "Nincs környezet",
"render.tree_objects": "Objektumok",
"render.tree_output": "Kimenet",
"render.tree_point": "Pontfény",
"render.tree_rectangle": "Téglalap",
"render.tree_search": "Objektumok keresése",
"render.tree_selection": "Kijelölés renderelése",
"render.tree_shots": "Felvételek",
"render.tree_sky": "Égbolt",
"render.tree_solo": "Szólófény",
"render.tree_spot": "Spotfény",
"render.tree_sun": "Nap",
"render.tree_switch": "Váltás",
"render.tree_user_one": "{count} objektum",
"render.tree_users": "{count} objektum",
"render.unavailable_preview": "Ez a beállítás egy nem elérhető előnézeti profilt kér.",
"render.unsaved": "Nem mentett előnézeti módosítások",
"render.use_preview": "Beépített előnézet használata",
"render.volume_albedo": "Szóródási albedó · lineáris RGB",
"render.volume_anisotropy": "Fázis átlagkoszinusza",
"render.volume_enable": "Résztvevő közeg engedélyezése",
"render.volume_extinction": "Extinkciós együttható",
"render.volume_help": "GPU-s fénytranszport egyetlen véges dobozon belül, Beer-féle gyengítéssel és HG-szóródással a kamera- és közvetett utakon. Kifejezett stúdió-, HDR- és égboltvilágítást használ, az árnyékgyengítést is beleértve. A pozitív fázis-koszinusz előre szór. Az üveghatárokat és a felületi zajcsökkentést külön ki kell kapcsolni. Nulla extinkció esetén a transzport változatlan marad. Nem fizikai holdi légkör, sűrűségrács, térfogati emisszió, spektrális transzport vagy tanúsított anyagjellemző.",
"render.volume_max": "Maximális határok · mm (világ)",
"render.volume_min": "Minimális határok · mm (világ)",
"render.volume_title": "Határolt homogén térfogat",
"render.wait_batch": "még nem támogatott: a mentett felvételek renderelési sora",
"render.wait_compare": "még nem támogatott: megőrzött képek összehasonlítása",
"render.wait_paint": "még nem támogatott: a termék kijelölése és a megjelenés festése",
"render.wait_pick_up": "még nem támogatott: a termék kijelölése és a megjelenés mintavételezése",
"render.wait_replace": "még nem támogatott: egy megjelenés összes előfordulásának lecserélése",
"render.wait_solo": "még nem támogatott: a fényforrások láthatósága és a szólóvezérlők",
"sample.bracket.about": "Alaplap peremekkel és szeggel 2 mm-es szabály szerint",
"sample.bracket.name": "Lemezkonzol",
"sample.enclosure.about": "Héjazott doboz perem, csavardudorok, támasz és pattintós illesztés",
+710
View File
@@ -37,6 +37,7 @@
"All open designs": "Semua desain yang terbuka",
"Allowed expressions, separated by semicolons": "Ekspresi yang diizinkan, dipisahkan titik koma",
"Also deletes": "Juga menghapus",
"Also place them from the origin (fully constrained)": "Tempatkan juga dari titik asal (terkunci penuh)",
"Anchor": "Jangkar",
"Angle 2": "Sudut 2",
"Angle Display": "Tampilan Sudut",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Desain yang Anda buka atau simpan muncul di sini.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Ditentukan oleh To Object. Pilih Angle untuk mengedit rentang sudut.",
"Diameter": "Diameter",
"Dimension new shapes": "Beri dimensi bentuk baru",
"Direction": "Arah",
"Discard": "Buang",
"Distance": "Jarak",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Seret untuk memutar rest dengan langkah 5°. Tahan Alt atau Ctrl untuk memutarnya bebas.",
"Drive Joint": "Gerakkan Sambungan",
"Duration": "Durasi",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Setiap bentuk baru juga diberi dimensi dari titik asal sketsa hingga tidak ada yang bebas. Bentuk yang sudah terhubung ke titik asal atau geometri yang ditempatkan tidak mendapat apa pun.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Setiap bentuk yang Anda gambar mendapat semua dimensinya sesuai ukuran yang digambar (nilai yang diketik diutamakan). Ukuran yang sudah ditetapkan sketsa dilewati.",
"Edges": "Tepi",
"Edit": "Edit",
"Edit Profile Sketch": "Edit Sketsa Profil",
@@ -1701,21 +1705,317 @@
"recovery.just_now": "baru saja",
"recovery.min_ago": "{count} mnt lalu",
"recovery.never_saved": "belum pernah disimpan",
"render.adaptive_absolute": "Batas bawah galat RGB absolut",
"render.adaptive_coverage": "Target galat cakupan",
"render.adaptive_enable": "Alokasikan sampel dengan pilot independen",
"render.adaptive_help": "Hanya GPU. Sampel pilot independen dibuang, lalu 16 sampel produksi atau lebih per piksel dialokasikan hingga Sampel per piksel. Varians RGB dan cakupan memandu alokasi; jalur langka bisa terlewat dan piksel yang dibatasi mungkin tetap noisy. Laporan akhir menghitung kerja yang sebenarnya. Tidak ada jaminan noise atau waktu yang tersertifikasi.",
"render.adaptive_minimum": "Sampel produksi minimum",
"render.adaptive_pending": "Alokasi adaptif pilot independen GPU dan strata Fresnel bersyarat sudah tersedia. Konvergensi tersertifikasi, jaminan kejadian langka, dan transport adaptif CPU masih belum tersedia.",
"render.adaptive_pilots": "Sampel pilot per piksel",
"render.adaptive_relative": "Target galat RGB relatif",
"render.add_ground": "Tambahkan lantai yang pas ke setup",
"render.advanced_material_scope": "Satu medium GPU homogen terbatas tersedia dengan batas eksplisit. Grid kerapatan, kombinasi kaca/volume bersarang, permukaan subsurface, displacement, transport spektral, dan konsep material lanjutan yang tidak terikat belum tersedia.",
"render.aging_add": "Tambah lapisan penuaan",
"render.aging_airborne": "Debu di udara / medium partisipatif",
"render.aging_airborne_help": "Debu di udara adalah volume hamburan homogen terbatas yang terpisah. Ia mengubah transport dan EXR mentah, bukan tumpukan penuaan permukaan. Pembatasan volume/kaca/denoise yang ada tetap eksplisit; tidak ada atmosfer yang ditambahkan otomatis.",
"render.aging_all_bodies": "Semua bodi opak yang memenuhi syarat",
"render.aging_chips": "Cat terkelupas",
"render.aging_class_any": "Semua kelas material opak",
"render.aging_class_dielectric": "Hanya permukaan nonlogam",
"render.aging_class_metal": "Hanya permukaan logam",
"render.aging_color": "Warna lapisan · sRGB",
"render.aging_coverage": "Cakupan",
"render.aging_dust": "Debu yang mengendap",
"render.aging_empty": "Tidak ada lapisan penuaan: permukaan asli tetap tidak berubah.",
"render.aging_fading": "Pelapis pudar",
"render.aging_grime": "Kotoran & noda",
"render.aging_help": "Gabungkan hingga delapan lapisan optik, secara berurutan. Karat dan patina adalah tampilan buatan, bukan simulasi penuaan/korosi. Skala dalam milimeter dunia. Tidak ada geometri, massa, atau properti rekayasa yang diubah; kaca dan panggung pasif dikecualikan.",
"render.aging_metallic": "Fraksi metalik lapisan",
"render.aging_origin": "Origin medan pola · mm dunia",
"render.aging_patina": "Patina hijau tembaga",
"render.aging_refresh_targets": "Periksa bodi saat ini",
"render.aging_roughness": "Kekasaran lapisan",
"render.aging_rust": "Besi teroksidasi / karat",
"render.aging_scale": "Skala pola",
"render.aging_scratches": "Goresan halus",
"render.aging_target": "Target & koordinat",
"render.aging_target_help": "Target bernama harus tetap cocok dengan indeks dan nama yang ditangkap. Mask global terpaku pada dunia; mask tidak mengikuti part yang bergerak. Ini bukan deteksi rongga maupun keausan tepi yang sebenarnya. Filter daftar untuk menjangkau bodi lainnya.",
"render.aging_target_search": "Filter nama bodi",
"render.aging_upward": "Pengendapan menghadap ke atas",
"render.all_controls_help": "Pemeriksaan padat atas semua kontrol saat ini. Halaman bagian menyediakan pengeditan terfokus tanpa mengubah permintaan yang mendasarinya.",
"render.all_shots_label": "Semua Bidikan",
"render.appearance_physics_separate": "Tampilan visual tidak menetapkan massa jenis, data termal, atau properti rekayasa lainnya.",
"render.availability_native": "Komposisi native; tinjau sebelum diterapkan",
"render.availability_projection": "Proyeksi yang didukung; lihat cakupan dan bagian yang dihilangkan",
"render.availability_reference": "Data referensi; bukan penetapan otomatis",
"render.backdrop_alpha_conflict": "Pilih latar belakang ini atau keluaran PNG transparan; renderer tidak akan mengabaikan salah satu pengaturan secara diam-diam.",
"render.backdrop_enable": "Gunakan latar belakang gradasi khusus kamera",
"render.backdrop_first": "Warna awal / tengah",
"render.backdrop_help": "Latar belakang ruang layar ini tidak menerangi, tidak menghasilkan bayangan, tidak memantul, dan tidak mewakili lanskap. Latar ini dikecualikan dari EXR mentah. Geometri, lampu, dan lingkungan HDR tetap independen.",
"render.backdrop_horizontal": "Gradasi horizontal",
"render.backdrop_radial": "Gradasi radial",
"render.backdrop_radius": "Radius",
"render.backdrop_second": "Warna akhir / tepi",
"render.backdrop_vertical": "Gradasi vertikal",
"render.backdrop_x": "Pusat X",
"render.backdrop_y": "Pusat Y",
"render.background": "Latar belakang scene",
"render.background_camera_section": "Latar belakang kamera · presentasi PNG",
"render.background_completed_frozen": "Hasil yang ditampilkan adalah gambar selesai yang dibekukan. Mengedit latar belakang tidak otomatis menggambar ulang hasil itu. Gunakan Koreksi warna ulang untuk perubahan khusus kamera, atau Render untuk panggung fisik yang baru.",
"render.background_hdr_separate": "Sumber daya HDR saat ini menerangi dan memantul pada permukaan; sumber daya itu tidak otomatis ditampilkan sebagai panorama di belakang objek. Mengubah gradasi tidak memutar atau mewarnai ulang pencahayaan.",
"render.background_lighting_section": "Iluminasi HDR · terpisah dari latar belakang kamera",
"render.background_no_alpha_override": "Latar belakang kamera tidak ditambahkan secara diam-diam ke keluaran transparan. Koreksi warna ulang master mentah memakai cakupan yang ditangkap dan tidak menerapkan denoise lagi; EXR sumber tetap tidak berubah.",
"render.background_not_light": "Warna latar belakang adalah presentasi, bukan sumber pencahayaan tambahan.",
"render.background_regrade": "Terapkan ke master mentah yang disimpan",
"render.background_stage_occlusion": "Bidikan ini menyertakan geometri panggung fisik. Lantai atau dinding besar dapat memenuhi bingkai dan menutupi latar belakang khusus kamera. Kosongkan atau ubah ukuran panggung secara sengaja, atau ubah reflektansi fisiknya. Koreksi warna ulang tidak dapat menghapus geometri yang sudah ditangkap.",
"render.background_workflow": "Pilih latar belakang yang dimaksud: warna/gradasi khusus kamera, panggung fisik yang menerima cahaya, atau iluminasi HDR. Ketiganya independen. Pratinjau Langsung adalah tampilan pemodelan; render gambar baru atau lakukan koreksi warna ulang pada master yang disimpan untuk melihat hasil akhir kamera.",
"render.base_appearance": "Tampilan bodi yang dapat diedit",
"render.base_apply": "Terapkan tampilan bodi",
"render.base_apply_help": "Satu penetapan visual yang dapat diurungkan untuk bodi persis yang telah ditinjau. Tampilan khusus muka dan material rekayasa yang ada tetap terpisah.",
"render.base_color": "Warna dasar · sRGB",
"render.base_metallic": "Fraksi metalik",
"render.base_opaque_only": "Editor ini mempertahankan semantik bodi opak. Gunakan kontrol kaca eksplisit untuk transmisi optik.",
"render.bloom_enable": "Tampilkan bloom",
"render.bloom_help": "Cahaya kreatif khusus keluaran dari sorotan linear positif, disebar dengan tiga lintasan kotak ternormalisasi. Radius dalam piksel keluaran. Ditambahkan dalam cahaya tampilan linear sebelum sRGB; bukan lensa, efek volumetrik, atau peningkatan konvergensi. EXR mentah tidak berubah.",
"render.bloom_opaque": "Bloom memerlukan keluaran opak. PNG transparan ditolak, tidak diratakan secara diam-diam.",
"render.bloom_radius": "Radius bloom",
"render.bloom_strength": "Kekuatan bloom",
"render.bloom_threshold": "Ambang sorotan linear",
"render.browse_capabilities": "Periksa katalog kemampuan lengkap",
"render.browse_environments": "Jelajahi lingkungan HDR orisinal",
"render.browse_native_scenes": "Jelajahi studio native",
"render.browse_physical": "Periksa referensi fisik",
"render.browse_quality": "Periksa spesifikasi kualitas",
"render.browse_rigs": "Jelajahi rig lampu buatan",
"render.browse_scene_specs": "Jelajahi spesifikasi adegan lanjutan",
"render.browse_surfaces": "Jelajahi permukaan buatan",
"render.browser_library": "Pustaka",
"render.browser_model": "Model",
"render.camera_distance": "Jarak mata ke target",
"render.camera_exact_help": "Milimeter dunia; sudut ditampilkan dalam derajat dan disimpan sebagai radian. Navigasi memakai kamera yang sama dengan viewport.",
"render.camera_fov": "Bidang pandang vertikal",
"render.camera_pitch": "Pitch kamera",
"render.camera_roll": "Roll",
"render.camera_set": "Atur Kamera Render",
"render.camera_target": "Posisi target · mm",
"render.camera_yaw": "Yaw",
"render.chromatic_offset": "Offset tepi kromatik",
"render.clear_stage": "Hapus panggung tersimpan",
"render.copy_request": "Salin JSON",
"render.cpu_aa_help": "Sampel spasial: lebih banyak sampel memperbaiki tepi dan menambah waktu render.",
"render.cpu_area_add": "Tambah lampu persegi panjang CPU",
"render.cpu_area_editor": "Lampu persegi panjang CPU",
"render.cpu_area_editor_help": "Vektor sisi penuh dalam milimeter; U silang V mengarah ke sisi pemancar. Ini berbeda dari vektor setengah tepi GPU.",
"render.cpu_area_full_u": "Sisi U penuh · mm",
"render.cpu_area_full_v": "Sisi V penuh · mm",
"render.cpu_area_samples": "Sampel lampu area",
"render.cpu_binding_confirm": "Konfirmasi bodi ini",
"render.cpu_binding_stale": "Adegan berubah. Konfirmasi lagi target pantulan ini sebelum merender.",
"render.cpu_body_choose": "Pilih bodi",
"render.cpu_body_filter": "Filter bodi menurut nama",
"render.cpu_body_filter_more": "Perhalus filter untuk melihat lebih banyak bodi.",
"render.cpu_body_missing": "Target pantulan hilang, tersembunyi, ambigu, atau namanya lebih panjang dari 128 byte. Pilih lagi.",
"render.cpu_budget": "Profil sumber daya CPU",
"render.cpu_budget_bodies": "Batas bodi",
"render.cpu_budget_compact": "Ringkas (batas lama)",
"render.cpu_budget_details": "Batas sumber daya",
"render.cpu_budget_help": "Pilih batas yang lebih besar secara eksplisit. Resolusi dan sampel tidak pernah dikurangi otomatis.",
"render.cpu_budget_memory": "Batas memori pekerjaan",
"render.cpu_budget_not_guarantee": "Ini adalah batas penerimaan, bukan reservasi RAM atau jaminan kecepatan. Geometri, film, dan pratinjau yang disimpan berbagi anggaran memori; rendering tetap dapat dibatalkan.",
"render.cpu_budget_resize": "Draf melebihi profil CPU ini atau anggaran sampel kameranya. Terima dimensi yang lebih kecil secara eksplisit atau pilih profil yang lebih besar.",
"render.cpu_budget_studio": "Studio (gambar besar)",
"render.cpu_budget_triangles": "Batas segitiga",
"render.cpu_budget_workstation": "Workstation (adegan berat)",
"render.cpu_captured_hdr": "HDR yang ditangkap untuk gambar ini",
"render.cpu_check_capture_help": "Periksa dan Mulai memverifikasi digest file yang sama atau memakai HDR tersemat. Setiap gambar mempertahankan sumber yang ditangkapnya.",
"render.cpu_check_changed": "Kontrol atau model berubah setelah pemeriksaan ini. Periksa lagi sebelum merender.",
"render.cpu_constant_help": "Radiance konstan terlihat oleh sinar yang dipantulkan atau diteruskan. Radiance ini tidak memberi pencahayaan difus langsung.",
"render.cpu_custom_directions": "Ganti preset dengan lampu arah kustom",
"render.cpu_direction": "Arah menuju lampu (X, Y, Z)",
"render.cpu_directional": "Lampu arah",
"render.cpu_directional_add": "Tambah lampu arah",
"render.cpu_environment": "Lingkungan CPU",
"render.cpu_environment_background": "Latar belakang gambar tetap terpisah dari pencahayaan lingkungan.",
"render.cpu_environment_bounds": "Intensitas CPU harus 0–64, rotasi HDR berhingga dalam ±1.000.000 radian, dan sampel HDR 1, 4, 16 atau 64.",
"render.cpu_environment_constant": "Lingkungan sinar sekunder konstan",
"render.cpu_environment_none": "Tanpa lingkungan CPU",
"render.cpu_environment_samples": "Sampel pencahayaan HDR",
"render.cpu_exposure_help": "Eksposur CPU harus antara −16 dan 16 EV. Eksposur GPU di luar rentang itu dipertahankan sampai Anda mengubahnya.",
"render.cpu_fixed": "Gambar tunggal",
"render.cpu_hdr_help": "Radiance .hdr, panorama 2:1, hingga 2048 × 1024 dan 16 MiB. CPU memerlukan primer sRGB/D65 yang eksplisit di dalam file; primer yang tidak ditentukan dan EXR ditolak.",
"render.cpu_hdr_reflection_help": "Pantulan kasar HDR memerlukan permukaan bodi dan muka yang sepenuhnya metalik. Pemeriksaan melaporkan kombinasi yang tidak didukung.",
"render.cpu_key_rim": "Key dan rim",
"render.cpu_last_check": "Pemeriksaan CPU terakhir",
"render.cpu_light_help": "Hingga delapan lampu arah. Daftar kustom yang kosong mematikannya; memilih preset memulihkan lampunya. Warna berupa RGB linear dan intensitas bersifat relatif, bukan watt.",
"render.cpu_light_intensity": "Intensitas relatif (0–64)",
"render.cpu_light_minimum": "Jarak minimum untuk atenuasi",
"render.cpu_light_position": "Posisi dunia (X, Y, Z)",
"render.cpu_light_reference": "Jarak referensi untuk intensitas",
"render.cpu_light_remove": "Hapus lampu",
"render.cpu_lighting": "Preset pencahayaan",
"render.cpu_lights": "Lampu CPU",
"render.cpu_linear_color": "Warna linear (R, G, B)",
"render.cpu_neutral": "Netral",
"render.cpu_opaque_required": "Ray tracing CPU memerlukan latar belakang opak. Hapus centang Latar belakang transparan untuk melanjutkan.",
"render.cpu_options_pending": "Panel CPU ini belum dapat mengedit emisi, efek permukaan, kaca, atau anisotropi. Bersihkan opsi API tersebut sebelum memakainya.",
"render.cpu_point": "Lampu titik",
"render.cpu_point_add": "Tambah lampu titik",
"render.cpu_point_help": "Hingga delapan lampu titik, ditambahkan ke pencahayaan arah yang dipilih. Jarak dalam mm; minimum tidak boleh melebihi jarak referensi.",
"render.cpu_primary_samples": "Sampel tepi per piksel",
"render.cpu_progressive": "CPU progresif",
"render.cpu_progressive_help": "Akumulasikan integrator CPU yang ada dalam pass berisi satu sampel primer. Pantulan yang dipilih memerlukan satu sampel; lampu area, dielektrik, dan anisotropi memerlukan Gambar tunggal.",
"render.cpu_progressive_limits": "Paling banyak 1.048.576 piksel dan 16.777.216 evaluasi piksel × sampel. Mengubah sampel tidak pernah mengubah ukuran gambar secara otomatis.",
"render.cpu_progressive_seed": "Seed sampling CPU",
"render.cpu_progressive_spp": "sampel per piksel",
"render.cpu_reflection_add": "Tambah pantulan kasar",
"render.cpu_reflection_depth": "Kedalaman pantulan (1–8)",
"render.cpu_reflection_empty": "Tidak ada bodi yang dipilih: pantulan adegan mati.",
"render.cpu_reflection_help": "Pilih bodi lalu atur Mati, Cermin, atau Kasar. Kasar memakai kekasaran permukaan yang ditetapkan. Lebih banyak sampel dan bounce menambah waktu; ini transpor spekular terbatas, bukan iluminasi global.",
"render.cpu_reflection_limit": "Hingga 64 bodi terpantul didukung.",
"render.cpu_reflection_mirror": "Cermin",
"render.cpu_reflection_off": "Mati",
"render.cpu_reflection_rough": "Kasar",
"render.cpu_reflection_samples": "Sampel pantulan (1–64)",
"render.cpu_reflections": "Pantulan CPU",
"render.cpu_runtime_help": "Pengaturan numerik lampu dan lingkungan disimpan bersama setup. Pantulan bodi dan file HDR tetap bersifat sementara. Nilai lampu area dan kerucut spot yang ada dipertahankan.",
"render.cpu_sampling_mode": "Mode sampling CPU",
"render.cpu_shadows": "Buat bayangan",
"render.cpu_summary": "Ray tracing CPU · pantulan · HDR · lampu arah dan titik",
"render.cpu_warm_cool": "Hangat dan dingin",
"render.diag_bodies": "Bodi terlihat",
"render.diag_job_details": "Detail tugas yang ditangkap",
"render.diag_last_check": "Pemeriksaan awal terakhir",
"render.diag_memory": "Estimasi admisi logis",
"render.diag_not_implemented": "Batas kemampuan eksplisit",
"render.diag_preflight_details": "Detail pemeriksaan awal",
"render.diag_request": "Permintaan saat ini yang tepat",
"render.diag_triangles": "Segitiga",
"render.discard_continue": "Buang draf dan lanjutkan",
"render.draft_confirm_help": "Draf render saat ini punya perubahan yang belum diterapkan. Simpan sebelum beralih, buang secara eksplisit, atau lanjutkan mengedit.",
"render.draft_confirm_title": "Pertahankan pengaturan render yang diedit",
"render.effects_gpu_only": "Efek ini memerlukan path tracing GPU. Mengganti halaman tidak pernah mengganti mesin render secara otomatis.",
"render.effects_help": "Gabungkan look warna berurutan dan efek lensa dalam ruang gambar. Render dan koreksi warna ulang master mentah memakai pengaturan tersimpan yang sama. EXR mentah tidak berubah. Ini kontrol artistik orisinal, bukan emulasi lensa terkalibrasi atau film bermerek.",
"render.effects_reset_lens": "Atur ulang efek lensa",
"render.effects_seed": "Seed pola",
"render.emitted_axis": "Sumbu pancaran",
"render.error_area_samples": "area_samples harus 1, 4, 16 atau 64",
"render.error_binding_allocation": "tidak dapat mengalokasikan binding material",
"render.error_body_bound": "pratinjau produk melebihi batas bodi yang ditangkap",
"render.error_checkpoint_dimensions": "dimensi checkpoint berbeda dari permintaan yang ditangkap",
"render.error_decode_budget": "anggaran dekode gambar meluap",
"render.error_denoise_setting": "pengaturan denoise native tidak valid",
"render.error_display_dimensions": "dimensi tampilan gambar tidak valid",
"render.error_display_fit": "tampilan gambar tidak muat di perangkat ini",
"render.error_display_height": "tinggi tampilan meluap",
"render.error_display_width": "lebar tampilan meluap",
"render.error_duplicate_face": "tampilan muka produk duplikat",
"render.error_export_document": "Dokumen ekspor render berubah saat memilih tujuannya",
"render.error_face_cap": "pratinjau produk melebihi batas penerimaan tampilan muka",
"render.error_finish_gesture": "selesaikan gestur pemodelan sebelum melihat pratinjau",
"render.error_finish_operation": "selesaikan operasi pemodelan saat ini sebelum masuk ke Render",
"render.error_fixed_preview": "pratinjau studio tetap memerlukan eksposur 0, rotasi lingkungan 0, dan intensitas 1",
"render.error_geometry_size": "ukuran geometri produk meluap",
"render.error_glass_recipe": "resep kaca tidak dikenal",
"render.error_gpu_preview": "Pratinjau produk GPU tidak tersedia di host ini. Setup tersimpan tetap tersedia.",
"render.error_gpu_samples": "jumlah sampel GPU tidak didukung",
"render.error_image_dimensions": "dimensi gambar render tidak cocok dengan tugasnya",
"render.error_image_profile": "gambar render melebihi profil sumber daya yang ditangkap",
"render.error_interactive_command": "perintah Render interaktif yang tidak terikat",
"render.error_job_action": "bukan aksi tugas gambar interaktif",
"render.error_job_identity": "identitas tugas render tidak valid: {error}",
"render.error_library_reply": "respons pustaka render tidak valid",
"render.error_material_binding": "binding material tidak ada",
"render.error_no_completed_image": "render tidak memiliki gambar yang selesai",
"render.error_no_geometry": "tidak ada geometri produk",
"render.error_no_scene": "tidak ada adegan produk",
"render.error_opacity": "opasitas tampilan produk tidak valid",
"render.error_pbr_opacity": "PBR opak memerlukan opasitas 1",
"render.error_physical_glass": "resep yang dipilih bukan kaca fisik",
"render.error_preview_device": "pratinjau produk memerlukan perangkat terpasang dengan depth buffer",
"render.error_product_triangle": "segitiga produk tidak valid",
"render.error_provisional_identity": "identitas render sementara atau jumlah sampel tidak valid",
"render.error_quality_bounds": "proyeksi kualitas melebihi batas native",
"render.error_quality_method": "proyeksi kualitas memerlukan metode GPU eksplisit yang sama",
"render.error_quality_projection": "proyeksi kualitas native tidak valid",
"render.error_regrade_identity": "identitas koreksi warna ulang tidak valid: {error}",
"render.error_scene_bodies": "bodi adegan render tidak ada",
"render.error_scene_body_limit": "adegan render melebihi batas bodinya",
"render.error_scene_identity": "identitas adegan render tidak valid",
"render.error_setup_panicked": "penyiapan path tracer GPU mengalami panic",
"render.error_setup_stopped": "worker penyiapan berhenti tanpa mengembalikan host",
"render.error_setup_worker": "tidak dapat memulai worker penyiapan: {error}",
"render.error_source_preview": "pratinjau sumber melebihi batas byte",
"render.error_surface_normals": "PBR memerlukan normal permukaan yang bukan nol",
"render.error_surface_reply": "balasan permukaan rancangan tidak valid",
"render.error_triangle_bound": "pratinjau produk melebihi batas sumber delapan juta segitiga",
"render.error_triangle_count": "jumlah segitiga produk meluap",
"render.error_upload_slot": "slot unggah pratinjau produk tidak tersedia",
"render.error_vertex_allocation": "alokasi titik sudut pratinjau produk gagal",
"render.error_vertex_envelope": "pratinjau produk melebihi batas payload titik sudut {limit} MiB; geometri tidak disederhanakan",
"render.error_vertex_packing": "pengemasan pratinjau produk berbeda dari payload titik sudut yang diterima",
"render.error_visible_solid": "Buat solid yang terlihat di Desain untuk melihat pratinjaunya di sini.",
"render.exit_focus": "Keluar dari fokus",
"render.export_display": "Ekspor: PNG tampilan",
"render.export_image_label": "Ekspor Gambar",
"render.export_linear": "Ekspor: EXR linear mentah",
"render.exr_pending": "GPU dapat menyimpan EXR linear mentah. Kompresi, gambar multilayer, dan pass render tambahan belum tersedia.",
"render.film_grain": "Grain fotografis",
"render.fit": "Fit Produk",
"render.fixed_camera": "Kamera",
"render.fixed_world": "Dunia",
"render.flare_ghosts": "Cincin ghost per sumber",
"render.flare_halo": "Halo flare",
"render.flare_streak": "Streak bergaya anamorfik",
"render.flare_strength": "Kekuatan flare sorotan",
"render.flare_threshold": "Ambang flare linear-adegan",
"render.fold_browser": "Lipat Penjelajah",
"render.gpu_depth": "Kedalaman jalur maksimum",
"render.gpu_options_help": "Sampel, kedalaman, seed, dan eksposur disimpan bersama setup ini. Hanya metode gambar yang aktif yang disimpan.",
"render.gpu_path_failed": "GPU path tracer tidak tersedia",
"render.gpu_path_first_setup": "Setup pertama pada GPU ini bisa memakan waktu beberapa menit; SolidCraft tetap dapat dipakai selama itu. Peluncuran berikutnya memakai ulang shader yang sudah dikompilasi jika driver menyimpannya.",
"render.gpu_path_preparing": "GPU path tracer: mengompilasi shader…",
"render.gpu_seed": "Seed acak",
"render.gpu_unavailable": "Path tracing GPU belum siap di perangkat ini.",
"render.ground_apply": "Pasangkan dan simpan lantai",
"render.ground_gap": "Celah kelonggaran eksplisit",
"render.ground_linear_rgb": "Reflektansi difus · RGB linear",
"render.ground_margin": "Margin bentang lantai",
"render.hdr_details": "Detail sumber HDR",
"render.hdr_embedded": "HDR disimpan di dalam desain ini",
"render.hdr_embedded_help": "Render memakai byte yang disertakan dalam desain; file aslinya tidak lagi diperlukan.",
"render.hdr_file_captured": "File HDR sudah diperiksa. Penyimpanan akan menyematkan byte ini; jika file berubah, periksa ulang secara eksplisit.",
"render.hdr_inspect": "Periksa file HDR",
"render.hdr_inspect_required": "Pilih dan periksa file HDR sebelum menyimpan atau merender.",
"render.hdr_primaries_declared": "Sumber menyatakan primer warnanya.",
"render.hdr_primaries_srgb": "Primer warna: sRGB/D65",
"render.hdr_primaries_undeclared": "Sumber tidak menyatakan primer; tinjau persyaratan warna renderer.",
"render.hdr_resource_missing": "Desain ini tidak memiliki sumber daya HDR yang tersimpan.",
"render.heading_batch": "BATCH",
"render.heading_frame": "FRAME",
"render.heading_lens": "LENS",
"render.heading_results": "HASIL",
"render.heading_shots": "BIDIKAN",
"render.hide_shots_label": "Sembunyikan strip Bidikan",
"render.image_advanced": "Kontrol GPU lanjutan",
"render.image_cancelled": "Render dibatalkan",
"render.image_cancelling": "Membatalkan",
"render.image_completed": "Gambar siap diekspor",
"render.image_encoding": "Mengenkode PNG",
"render.image_export": "Ekspor PNG",
"render.image_exposure": "Eksposur",
"render.image_failed": "Render gagal",
"render.image_height": "Tinggi",
"render.image_help": "Gambar pratinjau CPU · PNG · transparansi perkiraan",
"render.image_host_missing": "Tidak ada host gambar yang terpasang.",
"render.image_method": "Metode gambar",
"render.image_overwrite": "Ganti file yang ada",
"render.image_preparing": "Menyiapkan gambar",
"render.image_progressive": "Render progresif",
"render.image_queued": "Menunggu render",
"render.image_reduce": "Coba gambar lebih kecil atau scene lebih sederhana.",
"render.image_running": "Merender gambar",
"render.image_samples": "Sampel per piksel",
"render.image_scene_stale": "Selesaikan gestur pemodelan atau segarkan adegan sebelum memeriksa atau memulai gambar.",
"render.image_stale": "Gambar ini memakai scene yang ditangkap sebelum perubahan berikutnya.",
"render.image_start": "Mulai Render",
"render.image_supported": "Permintaan render didukung; antrean dan kumpulan memori diperiksa lagi saat mulai.",
@@ -1725,20 +2025,430 @@
"render.image_unknown": "Status render tidak tersedia",
"render.image_use_largest": "Gunakan ukuran terbesar pada rasio ini:",
"render.image_width": "Lebar",
"render.include_rig_cards": "Sertakan kartu dan flag pasif",
"render.inner_half_angle": "Setengah sudut dalam",
"render.inspect_scene": "Segarkan ringkasan adegan yang ditangkap",
"render.inspector": "Inspektor",
"render.keep_editing": "Lanjutkan mengedit",
"render.layer_down": "Pindah ke bawah",
"render.layer_enabled": "Lapisan aktif",
"render.layer_off_suffix": " (mati)",
"render.layer_remove": "Hapus lapisan",
"render.layer_strength": "Kekuatan lapisan",
"render.layer_up": "Pindah ke atas",
"render.lens_effects_help": "Flare memakai hingga empat sumber terang terpisah dalam gambar linear yang sebenarnya. Ghost, halo, streak, offset kromatik, dan distorsi radial adalah aproksimasi artistik di ruang gambar. Efek spasial memerlukan keluaran opak; sampel di luar gambar memperluas tepi gambar. Grain bersifat deterministik. Tidak ada fisika, EXR, atau geometri yang diubah.",
"render.lens_effects_title": "Terinspirasi lensa & fotografis",
"render.library_all": "Katalog",
"render.library_all_states": "Semua status ketersediaan",
"render.library_applied": "Proyeksi sumber daya diterapkan. Periksa seluruh permintaan render sebelum memulai.",
"render.library_apply_hdr": "Simpan dengan lingkungan HDR ini",
"render.library_apply_maps": "Gunakan peta permukaan GPU rancangan",
"render.library_apply_studio": "Simpan proyeksi studio rancangan",
"render.library_apply_uniform": "Terapkan tampilan opak seragam",
"render.library_authored_help": "Sumber daya rancangan asli bersifat ilustratif, bukan data rekayasa terukur. Setiap aksi hanya menerapkan proyeksi yang disebutkan.",
"render.library_blocked": "Diblokir / perlu kalibrasi",
"render.library_capabilities": "Spesifikasi kemampuan",
"render.library_center": "Pusat rig",
"render.library_clear_search": "Bersihkan",
"render.library_details": "Spesifikasi dan asal-usul",
"render.library_emitters_only_ack": "Gunakan emitter saja; lewati kartu pasif yang terdokumentasi",
"render.library_empty": "Tidak ada sumber daya yang cocok. Coba kueri atau filter ketersediaan lain.",
"render.library_environment_concepts": "Konsep lingkungan",
"render.library_extent": "Ekstensi subjek",
"render.library_favorite": "Tambah favorit",
"render.library_favorites": "Favorit",
"render.library_hdr": "Lingkungan HDR bawaan",
"render.library_hdr_help": "Menyematkan HDR asli ke dalam setup yang disimpan. Titik asal bujur rancangan dikonversi secara eksplisit; tidak perlu file eksternal setelah disimpan.",
"render.library_inspect_only": "Pilih untuk memeriksa; tidak ada yang diterapkan otomatis. Favorit dan riwayat terbaru milik sesi dokumen yang terbuka ini.",
"render.library_light_concepts": "Konsep pencahayaan",
"render.library_maps_help": "Peta bawaan dapat disimpan dengan sumber tersemat dan pemetaan kemunculan lokal. Penimpaan optik sementara tetap menjadi mode terpisah.",
"render.library_material_concepts": "Konsep material",
"render.library_native_scenes": "Studio asli",
"render.library_next": "Halaman berikutnya",
"render.library_omitted": "Tidak disertakan",
"render.library_physical_profiles": "Profil referensi fisik",
"render.library_previous": "Halaman sebelumnya",
"render.library_quality_concepts": "Spesifikasi kualitas",
"render.library_recent": "Terbaru",
"render.library_replace_environment": "Ganti lingkungan yang ada secara eksplisit",
"render.library_replace_studio": "Ganti pencahayaan, lingkungan, dan panggung yang tersimpan",
"render.library_results": "Sumber daya yang cocok",
"render.library_rig_help": "Pasangkan sekali pada pusat eksplisit dan ekstensi fisik. Rig lengkap menyertakan kartu pasif; penghambat kalibrasi tetap ditolak. Kelonggaran emitter/kartu secara konservatif diperiksa sebelum disimpan.",
"render.library_rigs": "Rig pencahayaan rancangan",
"render.library_save_maps": "Simpan peta ke setup ini",
"render.library_scene_bounds": "Gunakan batas adegan yang ditangkap",
"render.library_scenes": "Spesifikasi adegan",
"render.library_search": "Cari pustaka",
"render.library_select_hint": "Pilih sumber daya di Pustaka untuk memeriksa aksi dan batasan yang didukung.",
"render.library_selene": "Tampilan opak SELENE",
"render.library_selene_shots": "Spesifikasi bidikan SELENE",
"render.library_short_blocked": "Tidak tersedia",
"render.library_short_native": "Komposisi asli",
"render.library_short_projection": "Proyeksi didukung",
"render.library_short_reference": "Hanya referensi",
"render.library_short_specification": "Hanya spesifikasi",
"render.library_source_preview": "Muat pratinjau peta sumber",
"render.library_source_preview_help": "Peta sumber warna dasar rancangan. Ini bukan pratinjau material yang dirender atau terukur.",
"render.library_specification_only": "Hanya spesifikasi: bukan preset lengkap yang dapat dieksekusi. Efek, sumber daya, dan peran subjek yang diperlukan masih perlu implementasi dan binding eksplisit.",
"render.library_specs": "Hanya spesifikasi",
"render.library_status": "Ketersediaan",
"render.library_surfaces": "Permukaan PBR rancangan",
"render.library_target": "Bodi target",
"render.library_title": "Pustaka sumber daya render",
"render.library_unfavorite": "Hapus favorit",
"render.library_uniform_ack": "Gunakan aproksimasi seragam tanpa efek spasial atau lanjutan",
"render.library_usable": "Proyeksi yang dapat dieksekusi",
"render.light_anchor_pending": "Mengubah kerangka koordinat lampu belum didukung.",
"render.lights_fixed_to": "Lampu tetap pada",
"render.linear_help": "Mempertahankan master RGBA float 32-bit sebelum denoising, eksposur, tone mapping, filter, dan latar belakang. sRGB linear/D65; premultiplied terhadap cakupan. Memori tambahan diterima secara eksplisit. Tanpa kompresi atau pass tambahan.",
"render.linear_retain": "Simpan EXR linear mentah",
"render.linear_unavailable": "Bingkai selesai yang dipilih tidak memiliki EXR yang disimpan. Aktifkan penyimpanan sebelum merender; PNG lama tidak dapat memulihkan radiance mentah.",
"render.look_add": "Tambah look warna",
"render.look_bleach": "Terinspirasi bleach-bypass",
"render.look_cool": "Dingin",
"render.look_cyanotype": "Terinspirasi sianotipe",
"render.look_faded": "Cetakan pudar",
"render.look_mono": "Monokrom",
"render.look_sepia": "Sepia",
"render.look_strength": "Kekuatan look",
"render.look_teal_orange": "Teal / oranye",
"render.look_title": "Tumpukan look kreatif",
"render.look_warm": "Hangat",
"render.mapping_scale": "Pengali pengulangan fisik",
"render.material_absorption": "Absorpsi R · G · B (per mm)",
"render.material_add": "Tambah atau edit bodi ini",
"render.material_assignments": "Penetapan bodi",
"render.material_binding_enable": "Sertakan penimpaan bodi ini",
"render.material_box": "Kotak sejajar sumbu",
"render.material_browse": "Pilih gambar…",
"render.material_certification": "Kaca tertutup memakai jarak geometris. Topologi, orientasi, tumpang tindih, dan batas optik diperiksa saat persiapan GPU; Periksa hanya menerima permintaannya.",
"render.material_choose_body": "Pilih bodi adegan",
"render.material_closed": "Mesh solid tertutup",
"render.material_coat": "Clear coat di atas material dasar",
"render.material_coat_enable": "Aktifkan clear coat",
"render.material_coat_help": "Lapisan dielektrik ilustratif di atas tampilan opak yang ada. Bobot nol membiarkan material dasar tidak berubah.",
"render.material_color_map": "Gambar warna dasar (sRGB)",
"render.material_color_replace": "Peta dasar menggantikan warna bodi",
"render.material_custom": "Optik ilustratif kustom",
"render.material_enable": "Gunakan penimpaan material GPU ini",
"render.material_filter": "Filter bodi adegan…",
"render.material_filter_help": "Hingga 128 bodi yang cocok ditampilkan. Persempit filter untuk adegan besar.",
"render.material_glass": "Kaca dan absorpsi optik",
"render.material_glass_enable": "Gunakan kaca fisik pada bodi ini",
"render.material_glass_exclusive": "Kaca tidak dapat berbagi bodi dengan clear coat atau peta runtime di renderer ini.",
"render.material_glass_help": "Resep ilustratif orisinal. Swatch menampilkan transmitansi, bukan pratinjau hasil render. Absorpsi adalah −ln(transmitansi linear) / jarak referensi; alfa tidak berubah.",
"render.material_gpu_required": "Penimpaan material aktif ini memerlukan path tracing GPU. Pilih GPU atau nonaktifkan penimpaan sebelum Periksa atau Mulai.",
"render.material_ior": "Indeks bias (IOR)",
"render.material_limits": "Maksimal 128 penimpaan bodi, 32 bodi kaca terpisah, 64 coat, dan 128 binding tekstur. Peta identik berbagi penyimpanan; batas perangkat dan memori total yang sebenarnya tetap berlaku.",
"render.material_map_invalid": "Jalur peta harus berupa jalur lokal yang terbatas; kekuatan normal harus berhingga dan antara 0 dan 1.",
"render.material_map_required": "Pilih gambar warna atau gambar normal sebelum memakai peta.",
"render.material_maps": "Peta warna dan normal planar",
"render.material_maps_enable": "Aktifkan peta untuk bodi opak ini",
"render.material_maps_help": "PNG/JPEG hingga 1024×1024; total terenkode 16 MiB. U dan V adalah vektor pengulangan ortogonal dalam mm dunia (maksimum 128 pengulangan). Warna dalam sRGB; data normal memakai OpenGL +Y. File ditangkap saat Periksa/Mulai.",
"render.material_metallic_map": "Peta metalik (linear)",
"render.material_normal_map": "Gambar normal (OpenGL, +Y)",
"render.material_normal_strength": "Kekuatan normal (0–1)",
"render.material_origin": "Origin pemetaan X · Y · Z (mm)",
"render.material_refresh": "Segarkan bodi adegan",
"render.material_refresh_needed": "Adegan berubah. Segarkan daftar bodi sebelum menambahkan target.",
"render.material_remove": "Hapus penetapan ini",
"render.material_repeat_u": "Satu pengulangan U X · Y · Z (mm)",
"render.material_repeat_v": "Satu pengulangan V X · Y · Z (mm)",
"render.material_revalidate": "Validasi ulang bodi ini",
"render.material_revalidate_needed": "Penetapan ini milik revisi adegan sebelumnya. Validasi ulang identitas bodi yang persis sebelum merender.",
"render.material_roughness": "Kekasaran coat (0,045–1)",
"render.material_roughness_map": "Peta kekasaran (linear)",
"render.material_shadow": "Teruskan sinar bayangan lurus",
"render.material_target_missing": "Ordinal dan nama bodi tidak lagi cocok. Hapus penetapan ini dan pilih lagi bodi yang dimaksud secara eksplisit.",
"render.material_thickness": "Ketebalan lembaran tipis (mm)",
"render.material_thin": "Lembaran tipis",
"render.material_title": "Material gambar GPU",
"render.material_transient": "Penimpaan optik sementara untuk tab dokumen ini. Tidak disimpan dalam desain, setup render, atau pustaka material.",
"render.material_v_up": "V tekstur mengarah ke atas dalam gambar",
"render.material_weight": "Bobot coat (0–1)",
"render.method_cpu": "Ray tracing CPU",
"render.method_gpu": "Path tracing GPU",
"render.method_limit_raster": "Raster memakai pratinjau studio opak yang tetap. Pilih metode ray tracing secara eksplisit untuk kontrol optik yang didukung.",
"render.method_raster": "Raster CPU",
"render.navigation_help": "Kamera bergerak seperti di Desain (Preferensi › Navigasi). Save Setup merekam kamera saat ini.",
"render.nested_enable": "Dielektrik bersarang tersertifikasi",
"render.nested_help": "Hingga 16 lapisan penampung; setiap induk harus konveks dan setiap anak sepenuhnya berada di dalamnya. Perpotongan, permukaan bersentuhan, lembaran tipis, dan transmisi bayangan lurus ditolak. Status kamera-di-dalam mengikuti hierarki tersertifikasi. Tidak membuat permukaan cairan atau menggabungkan batas CAD yang bersentuhan.",
"render.opaque_image_summary": "Pratinjau PNG · PBR opak · transparansi campuran",
"render.opaque_preview_help": "PBR opak dan warna sederhana; transparansi campuran. Refraksi, HDRI, dan render akhir belum tersedia.",
"render.optics_remove": "Hapus optik tersimpan",
"render.optics_replace": "Ganti optik tersimpan target ini secara eksplisit",
"render.optics_save": "Simpan optik ini ke setup",
"render.optics_saved": "Target optik tersimpan",
"render.optics_saved_help": "Identitas definisi, fitur, dan kemunculan yang persis bertahan saat dibuka kembali secara offline. Target yang hilang/diganti/disembunyikan ditolak; material rekayasa tidak berubah. Simpan atau buang edit numerik sebelum menghapus target tersimpan.",
"render.outer_half_angle": "Setengah sudut luar",
"render.output_format_status": "PNG adalah gambar tampilan selesai yang persis. EXR GPU opsional menyimpan radiance FLOAT32 linear-adegan mentah sebelum filter tampilan. Ekspor tidak pernah menggantikan cache pratinjau atau pekerjaan lain.",
"render.output_lock_ratio": "Kunci rasio aspek",
"render.output_over_budget": "Gambar yang diminta melebihi batas sumber daya yang dipilih. Pilih ukuran atau profil yang kompatibel secara eksplisit; tidak ada penurunan otomatis.",
"render.output_ratio_refused": "Dimensi yang tertaut melebihi batas ukuran metode ini. Ukuran sebelumnya dipertahankan; buka kunci rasio atau pilih nilai yang lebih kecil.",
"render.output_swap_orientation": "Tukar lebar dan tinggi",
"render.output_tools_inspector": "Edit ukuran dan format di Inspektor Keluaran.",
"render.page_aging": "Penuaan & kontaminasi",
"render.page_all": "Semua kontrol",
"render.page_appearance": "Tampilan",
"render.page_background": "Latar belakang",
"render.page_camera": "Kamera",
"render.page_diagnostics": "Diagnostik",
"render.page_effects": "Efek lensa & finishing",
"render.page_environment": "Lingkungan",
"render.page_lighting": "Pencahayaan",
"render.page_output": "Keluaran",
"render.page_scene": "Adegan",
"render.paint_label": "Cat",
"render.passive_stage": "Lantai dan panggung pasif",
"render.passive_stage_help": "Panel pasif berhingga hanya milik gambar yang dirender. Panel ini tidak menambah bodi CAD atau massa. Penempatan menjadi tetap setelah diterapkan; batas produk yang berpotongan ditolak. CPU tidak menyediakan pencahayaan pantulan difus.",
"render.perspective": "Kamera perspektif",
"render.physical_acknowledge": "Saya memahami bahwa referensi parsial ini memerlukan peninjauan grade, kondisi, dan sumber",
"render.physical_associations": "Kandidat dan peran fisik",
"render.physical_background_help": "Lantai dan dinding pasif yang nyata, terpisah dari latar belakang kamera. Cyclorama memakai 24 strip poligonal; ini bukan permukaan tak hingga atau halus secara analitis. Menggantikan panggung tersimpan hanya dengan persetujuan Anda.",
"render.physical_copy_plan": "Salin rencana beserta sumber dan hal yang dihilangkan",
"render.physical_cyclorama": "Pasangkan cyclorama poligonal",
"render.physical_floor_wall": "Pasangkan lantai dan dinding fisik",
"render.physical_material_name": "Nama material referensi yang diusulkan",
"render.physical_omissions": "Properti yang tidak dapat direpresentasikan di kartu native",
"render.physical_plan_only": "Rencana hanya-baca telah disiapkan. Tidak ada material yang dibuat atau ditetapkan. Pertahankan profil yang diperluas dan hal yang dihilangkan saat meninjau kartu native.",
"render.physical_prepare_plan": "Siapkan rencana pembuatan (tidak diterapkan)",
"render.physical_separate": "Tampilan bukan identifikasi material. Ini adalah referensi bersumber, bukan properti efektif tersertifikasi. Massa, material rekayasa, dan optik yang ada tidak berubah.",
"render.physical_unknown": "Belum ada kandidat numerik yang ditetapkan. Grade, formulasi, atau konstruksi harus ditentukan; tidak diketahui bukan berarti nol.",
"render.pick_body": "Bodi",
"render.pick_component": "Komponen",
"render.pick_face": "Muka",
"render.pick_help": "Pilih Bodi, Muka, atau Komponen. Klik ruang kosong untuk membersihkan; Shift atau Ctrl menambah atau mengalihkan. Sorotan hanya muncul di tampilan produk langsung.",
"render.pick_label": "Pilih",
"render.pick_up_label": "Ambil",
"render.pick_waiting": "Pemilihan produk belum didukung.",
"render.post_contrast": "Kontras",
"render.post_gain_b": "Gain biru",
"render.post_gain_g": "Gain hijau",
"render.post_gain_r": "Gain merah",
"render.post_help": "Hanya untuk presentasi kreatif. Gain RGB diterapkan sebelum tone mapping; kontras, saturasi, dan vinyet menyusul dalam cahaya linear tampilan. Mulai Render membuat sampel transport baru. Koreksi warna ulang memakai master mentah tersimpan yang dipilih, tanpa denoise dan tanpa sinar baru.",
"render.post_reset": "Reset filter presentasi",
"render.post_saturation": "Saturasi",
"render.post_title": "Filter presentasi",
"render.post_vignette": "Vinyet",
"render.preview": "Pratinjau terintegrasi",
"render.preview_help": "Shading raster dan transparansi campuran. Refraksi, HDRI, dan render akhir belum tersedia.",
"render.preview_image_settings_help": "Pratinjau Langsung mempertahankan pencahayaan studio yang tetap. Eksposur dan pencahayaan gambar berlaku untuk tugas gambar saat Anda memilih Periksa atau Mulai.",
"render.preview_lighting_help": "Pratinjau langsung hanya menampilkan cahaya langsung dan tanpa bayangan.",
"render.preview_retry": "Coba lagi pratinjau langsung",
"render.preview_unavailable_help": "Pratinjau langsung tidak tersedia. Setup tersimpan dan kontrol tugas gambar tetap dapat diakses. Ubah adegan atau coba lagi secara eksplisit; adegan yang ditolak tidak dibangun ulang di setiap frame.",
"render.preview_upload": "Payload vertex pratinjau langsung",
"render.preview_upload_help": "Byte vertex pratinjau yang persis, bukan total memori GPU atau proses. Geometri tidak disederhanakan. Tugas gambar memakai penerimaan dan pencahayaannya sendiri.",
"render.progressive_image_summary": "PNG pratinjau · PBR dan kaca · sampel progresif",
"render.property_conditions": "Kondisi: {value}",
"render.property_fallback": "properti",
"render.property_qualifier": "Kualifikator: {value}",
"render.property_source": "Sumber: {id} - {locator}",
"render.property_uncertainty": "Ketidakpastian: {value}",
"render.property_unknown": "tidak diketahui",
"render.quality_ack": "Konfirmasi proyeksi anggaran tetap dan hal yang dihilangkan",
"render.quality_apply": "Gunakan anggaran sampling tetap ini",
"render.quality_projection_help": "Preset Q mencakup persyaratan di masa depan. Aksi ini hanya memproyeksikan anggaran PNG dengan sampel tetap yang didukung dan secara eksplisit menghilangkan penghentian adaptif, keluaran linear mentah, dan batas transmisi independen.",
"render.quality_review": "Tinjau anggaran sampling",
"render.queue_pending": "UI ini tidak memiliki antrean produksi otomatis atau renderer animasi. Gambar diam yang sudah selesai tetap dapat diekspor secara terpisah.",
"render.radial_distortion": "Distorsi radial",
"render.regrade_action": "Koreksi warna ulang master mentah (tanpa denoise)",
"render.regrade_help": "Membuat PNG terpisah dari master mentah selesai yang dipilih, memakai kontrol presentasi ini. Tidak menelusuri sinar, tidak mengubah ukuran/kamera/lampu yang ditangkap, dan tidak menimpa EXR. Denoise tidak diterapkan lagi: master mentah tidak menyimpan panduannya. Turunan ini tetap dapat diekspor melalui kontrol tugas yang sama.",
"render.regrade_label": "Koreksi warna ulang",
"render.reload_settings": "Muat Ulang Pengaturan Tersimpan",
"render.replace_ground": "Konfirmasi penggantian panggung yang ada",
"render.replace_label": "Ganti",
"render.replace_saved_surface": "Ganti binding tersimpan yang ada untuk target ini",
"render.restore_camera": "Pulihkan Kamera Tersimpan",
"render.result_actual_help": "Satu piksel gambar per piksel layar.",
"render.result_actual_size": "100%",
"render.result_capture": "Revisi yang ditangkap",
"render.result_current": "Revisi model yang ditangkap adalah yang terbaru.",
"render.result_empty": "Belum ada gambar yang selesai. Periksa pengaturan, lalu mulai render.",
"render.result_fit": "Pas Gambar",
"render.result_job": "Tugas",
"render.result_navigation": "Pan dan zoom memakai preferensi Navigasi. Space + seret untuk menggeser (pan).",
"render.result_open": "Buka gambar yang sudah selesai di kanvas utama.",
"render.result_preview": "Pratinjau Langsung",
"render.result_provisional": "Gambar CPU sementara",
"render.result_provisional_help": "Checkpoint ini tidak dapat diekspor. Ekspor mempertahankan hasil selesai terakhir; pembatalan kembali ke hasil tersebut.",
"render.result_reduced_display": "Pratinjau tampilan dikurangi hingga batas perangkat/cache viewport. PNG yang disimpan dan ekspor tetap beresolusi penuh; inspeksi 100% native tidak tersedia untuk tampilan yang dikurangi ini.",
"render.result_retained": "Menampilkan gambar selesai terakhir; render yang lebih baru belum menggantikannya.",
"render.result_sequence": "Checkpoint",
"render.result_title": "Hasil Render",
"render.return_design": "Kembali ke Desain",
"render.review_stale": "Tinjauan ini sudah usang. Selesaikan atau periksa lagi sebelum menerapkan.",
"render.ribbon_aging": "Penuaan",
"render.ribbon_backgrounds": "Latar Belakang",
"render.ribbon_check": "Periksa",
"render.ribbon_check_help": "Validasi draf terkini yang persis akan dikirim Render. Tanpa fallback renderer, pengubahan ukuran diam-diam, atau penggantian sumber daya.",
"render.ribbon_edit_lights": "Edit Lampu",
"render.ribbon_effects": "Efek",
"render.ribbon_environment_help": "Iluminasi HDR, latar belakang khusus kamera, dan permukaan panggung fisik adalah kontrol terpisah dengan persetujuan penggantian yang eksplisit.",
"render.ribbon_finish_dialog": "Selesaikan dulu dialog file atau konfirmasi yang sedang terbuka.",
"render.ribbon_frame": "Bingkai",
"render.ribbon_hdr_library": "Pustaka HDR",
"render.ribbon_job_active": "Sebuah render sedang berjalan; batalkan secara eksplisit sebelum memulai yang lain.",
"render.ribbon_light_rigs": "Rig Lampu",
"render.ribbon_lights_help": "Periksa rig buatan atau edit lampu yang didukung tanpa mengganti setup saat ini sampai Anda menerapkan perubahan secara eksplisit.",
"render.ribbon_materials": "Material",
"render.ribbon_materials_help": "Buka inspektur Tampilan bersama dan pustaka permukaan orisinal. Pengeditan optik tidak pernah diam-diam mengubah properti rekayasa.",
"render.ribbon_no_active_job": "Tidak ada render aktif yang dapat dibatalkan.",
"render.ribbon_no_result": "Selesaikan sebuah render sebelum mengekspor gambar persisnya.",
"render.ribbon_no_saved_camera": "Simpan bidikan sebelum memulihkan kameranya.",
"render.ribbon_saved_camera": "Kamera Tersimpan",
"render.ribbon_shots": "Bidikan",
"render.ribbon_studios": "Studio",
"render.ribbon_studios_help": "Jelajahi komposisi studio yang sudah diimplementasikan dan tinjau penggantiannya sebelum menerapkan. Adegan yang masih berupa konsep tetap diberi label.",
"render.ribbon_surface_maps": "Peta Permukaan",
"render.sampling_title": "Sampling adaptif dan transmisi",
"render.save_continue": "Simpan dan lanjutkan",
"render.save_setup": "Simpan Setup",
"render.save_shot": "Simpan Bidikan",
"render.saved_maps_runtime_conflict": "Binding permukaan tersimpan tidak dapat dicampur dengan penimpaan optik sementara atau HDR yang belum disimpan. Simpan HDR atau hapus input sementara secara eksplisit.",
"render.saved_surface_remove": "Hapus binding tersimpan",
"render.saved_surfaces": "Binding permukaan tersimpan",
"render.saved_surfaces_help": "Peta bawaan yang disematkan mengikuti kemunculan terpilih dalam milimeter lokal. Target yang diganti atau hilang adalah galat, bukan penugasan ulang otomatis.",
"render.scene_apply": "Terapkan studio yang sudah ditinjau",
"render.scene_consent": "Konfirmasi penggantian pencahayaan, lingkungan, eksposur, dan panggung",
"render.scene_preserved_fields": "Kamera, sampling, dimensi, binding optik, geometri CAD, dan material rekayasa tetap dipertahankan.",
"render.scene_preserves_design": "Susun pencahayaan dan panggung pasif untuk subjek yang terlihat. Geometri, material rekayasa, dan kamera tetap terpisah.",
"render.scene_replaces": "Mengganti",
"render.scene_review": "Proses dan tinjau",
"render.scene_review_help": "Tinjau komposisi native secara lengkap sebelum menerapkan. Spesifikasi SCENE lanjutan yang tidak terikat tidak digantikan.",
"render.scene_scope_details": "Cakupan komposisi",
"render.setup_legacy_environment": "Setup lama ini memakai rotasi atau intensitas lingkungan versi lama. Nilai tersebut dipertahankan; konversikan secara eksplisit sebelum menyimpan tugas gambar penuh.",
"render.setup_name": "Nama setup",
"render.setup_numeric_help": "Simpan merekam metode gambar yang aktif beserta semua pengaturan numeriknya. Memuat ulang atau memilih setup lain menggantikan draf ini; pulihkan kamera secara terpisah.",
"render.setup_offline_help": "Anda dapat mengedit dan menyimpan metode ini tanpa renderer-nya. Periksa dan Mulai memerlukan host yang tersedia.",
"render.setup_runtime_unsupported": "Tugas penuh ini belum dapat disimpan: berisi peta atau binding bodi adegan. Hapus input sementara tersebut sebelum menyimpan setup portabel.",
"render.setup_save_missing": "Konfigurasi render yang disimpan tidak ditemukan setelah perintah selesai.",
"render.sharpening": "Penajaman detail",
"render.shell_tab_appearance": "TAMPILAN RENDER",
"render.shell_tab_camera": "KAMERA RENDER",
"render.shell_tab_scene": "ADEGAN RENDER",
"render.shot_duplicate": "Duplikasi bidikan tersimpan",
"render.shot_manager": "Bidikan tersimpan",
"render.shot_new_name": "Nama bidikan baru",
"render.shot_remove": "Hapus bidikan tersimpan",
"render.shot_remove_help": "Hanya menghapus setup tersimpan ini. Geometri sumber dan gambar yang sudah selesai tetap dipertahankan; aksi ini dapat diurungkan.",
"render.shot_remove_title": "Hapus bidikan tersimpan?",
"render.shot_rename": "Ganti nama bidikan tersimpan",
"render.shot_saved_only": "Simpan draf saat ini terlebih dahulu. Duplikasi dan ganti nama mempertahankan opsi tersimpan dan referensi sumber daya secara persis.",
"render.show_shots_label": "Tampilkan strip Bidikan",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Tanah · RGB linear",
"render.sky_horizon": "Cakrawala · RGB linear",
"render.sky_zenith": "Zenit · RGB linear",
"render.soft_focus": "Fokus lembut",
"render.spot_cone": "Kerucut spot",
"render.stage_frame": "Frame",
"render.stage_light": "Pencahayaan",
"render.stage_look": "Look",
"render.stage_orthographic": "Ortografis",
"render.stage_output": "Keluaran",
"render.stage_panel_count": "Panel tersimpan",
"render.stage_preview_note": "Pratinjau terintegrasi · cahaya langsung",
"render.strip_label": "Strip",
"render.studio_add_area": "Tambah lampu area",
"render.studio_ambient": "Radiance lingkungan konstan",
"render.studio_ambient_rgb": "Radiance lingkungan konstan (RGB linear)",
"render.studio_aperture": "Radius apertur",
"render.studio_area": "Lampu area",
"render.studio_area_help": "Hingga empat persegi panjang satu sisi. Setengah-tepi ortogonal U dan V menentukan ukuran; U × V menghadap sisi yang diterangi. Koordinat dalam milimeter ruang dunia.",
"render.studio_center": "Pusat X, Y, Z (mm)",
"render.studio_denoise": "Kurangi noise pada gambar jadi",
"render.studio_denoise_help": "Filter akhir yang peka tepi; detail halus bisa melunak. Kaca dan permukaan spekular tajam melewati filter.",
"render.studio_direction": "Arah menuju matahari (X, Y, Z)",
"render.studio_environment": "Lingkungan",
"render.studio_environment_bounds": "Rotasi lingkungan harus berhingga dalam ±1.000.000 radian dan intensitas antara 0 dan 100.",
"render.studio_environment_none": "Tanpa peta lingkungan",
"render.studio_focus": "Jarak fokus aksial",
"render.studio_half_u": "Setengah-tepi U (mm)",
"render.studio_half_v": "Setengah-tepi V (mm)",
"render.studio_hdr": "File HDR Radiance",
"render.studio_hdr_browse": "Pilih HDR…",
"render.studio_hdr_help": "Radiance .hdr, panorama 2:1, hingga 2048 × 1024. EXR tidak tersedia. Asumsi warna hanya berlaku saat primer tidak ditentukan.",
"render.studio_hdr_required": "Pilih file .hdr lokal.",
"render.studio_hdr_srgb": "Tafsirkan primer yang tidak ditentukan sebagai sRGB linear",
"render.studio_intensity": "Intensitas lingkungan",
"render.studio_lens": "Kedalaman bidang",
"render.studio_lens_perspective": "Kedalaman bidang memerlukan kamera perspektif.",
"render.studio_lighting": "Pencahayaan studio",
"render.studio_lighting_enable": "Gunakan pencahayaan studio kustom",
"render.studio_needs_review": "Tinjau metode dan pengaturan",
"render.studio_radiance": "Radiance RGB linear",
"render.studio_ready": "Siap diperiksa",
"render.studio_remove_area": "Hapus lampu area",
"render.studio_rotation": "Rotasi lingkungan",
"render.studio_runtime_help": "Pengaturan studio numerik dan sumber HDR yang sudah diperiksa dapat disimpan bersama setup. Penimpaan optik/material bodi tetap sementara dan tidak mengubah tampilan yang tersimpan.",
"render.studio_saved": "Setup tersimpan / kamera saat ini",
"render.studio_sky": "Langit artistik",
"render.studio_sky_help": "Gradasi langit asli untuk pencahayaan; bukan model atmosfer yang dikalibrasi.",
"render.studio_sun": "Matahari",
"render.studio_sun_radius": "Radius sudut",
"render.studio_title": "Studio render",
"render.studio_tone_map": "Tone mapping",
"render.subsurface_enable": "Random walk hamburan interior",
"render.subsurface_help": "Hanya dielektrik tertutup. Hamburan dan absorpsi RGB adalah koefisien per mm yang terpisah. Jalur menghambur di dalam geometri sebenarnya, lalu direfraksi atau dipantulkan pada batas. Nonaktifkan transmisi bayangan lurus, denoise permukaan, dan volume eksterior; gunakan satu strata Fresnel. Bukan shader difusi, grid kerapatan, atau material terukur. Medium padat mungkin memerlukan lebih banyak sampel dan kedalaman jalur.",
"render.subsurface_rate": "Laju tumbukan hamburan",
"render.tone_aces_fitted": "ACES fitted",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "Kaca GPU mendukung medium terpisah yang tersertifikasi. Medium bersarang tanpa batas dan estimator transmisi bebas noise tidak tersedia.",
"render.transmission_strata": "Strata Fresnel bersyarat",
"render.transmission_strata_help": "1 mempertahankan aliran asli. 2 atau 4 subjalur menstratifikasi pilihan pantulan/transmisi kaca pertama dengan hukum Snell dan absorpsi yang tidak berubah. Lebih banyak jalur berarti lebih banyak kerja; ini bukan denoise, dukungan medium bersarang, atau janji render lebih cepat.",
"render.tree_add_light": "Tambah lampu",
"render.tree_add_shot": "Tambah bidikan",
"render.tree_browser": "Penjelajah Render",
"render.tree_by_look": "Menurut look",
"render.tree_by_object": "Menurut objek",
"render.tree_constant": "Lingkungan konstan",
"render.tree_default": "Bawaan",
"render.tree_directional": "Terarah",
"render.tree_environment": "Lingkungan",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} muka",
"render.tree_face_one": "{count} muka",
"render.tree_fixed_studio": "Studio tetap",
"render.tree_hdr": "HDR",
"render.tree_lights": "Lampu",
"render.tree_lights_pending": "Perintah lampu bernama belum tersedia.",
"render.tree_mixed": "Campuran",
"render.tree_more": "{count} lainnya",
"render.tree_mute": "Bisukan lampu",
"render.tree_no_environment": "Tanpa lingkungan",
"render.tree_objects": "Objek",
"render.tree_output": "Keluaran",
"render.tree_point": "Titik",
"render.tree_rectangle": "Persegi panjang",
"render.tree_search": "Cari objek",
"render.tree_selection": "Pilihan render",
"render.tree_shots": "Bidikan",
"render.tree_sky": "Langit",
"render.tree_solo": "Lampu solo",
"render.tree_spot": "Spot",
"render.tree_sun": "Matahari",
"render.tree_switch": "Beralih",
"render.tree_user_one": "{count} objek",
"render.tree_users": "{count} objek",
"render.unavailable_preview": "Setup ini meminta profil pratinjau yang tidak tersedia.",
"render.unsaved": "Perubahan pratinjau belum disimpan",
"render.use_preview": "Gunakan Pratinjau Terintegrasi",
"render.volume_albedo": "Albedo hamburan · RGB linear",
"render.volume_anisotropy": "Kosinus rata-rata fase",
"render.volume_enable": "Aktifkan medium partisipatif",
"render.volume_extinction": "Koefisien ekstingsi",
"render.volume_help": "Transport GPU di dalam satu kotak terbatas, dengan atenuasi Beer dan hamburan HG pada jalur kamera dan tidak langsung. Memakai pencahayaan studio/HDR/langit eksplisit, termasuk atenuasi bayangan. Kosinus fase positif menghambur ke depan. Batas kaca dan denoise permukaan harus dinonaktifkan secara eksplisit. Ekstingsi nol membiarkan transport tidak berubah. Bukan atmosfer bulan fisik, grid kerapatan, emisi volume, transport spektral, atau properti material tersertifikasi.",
"render.volume_max": "Batas maksimum · mm dunia",
"render.volume_min": "Batas minimum · mm dunia",
"render.volume_title": "Volume homogen terbatas",
"render.wait_batch": "belum didukung: antrean render bidikan tersimpan",
"render.wait_compare": "belum didukung: perbandingan gambar yang dipertahankan",
"render.wait_paint": "belum didukung: pemilihan produk dan pengecatan tampilan",
"render.wait_pick_up": "belum didukung: pemilihan produk dan pengambilan sampel tampilan",
"render.wait_replace": "belum didukung: penggantian semua pemakaian suatu tampilan",
"render.wait_solo": "belum didukung: visibilitas lampu dan kontrol solo",
"sample.bracket.about": "Flens dasar dengan flens tepi dan hem pada aturan 2 mm",
"sample.bracket.name": "Braket Pelat Logam",
"sample.enclosure.about": "Kotak shell dengan lip, boss sekrup, rest, dan snap fit",
+710
View File
@@ -38,6 +38,7 @@
"All open designs": "Tutti i progetti aperti",
"Allowed expressions, separated by semicolons": "Espressioni consentite, separate da punti e virgola",
"Also deletes": "Elimina anche",
"Also place them from the origin (fully constrained)": "Posizionale anche dall'origine (completamente vincolate)",
"Anchor": "Ancoraggio",
"Angle 2": "Angolo 2",
"Angle Display": "Visualizzazione dell'angolo",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "I progetti aperti o salvati vengono visualizzati qui.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Determinato da Fino all'oggetto. Scegli Angolo per modificare l'estensione angolare.",
"Diameter": "Diametro",
"Dimension new shapes": "Quota le nuove forme",
"Direction": "Direzione",
"Discard": "Scarta",
"Distance": "Distanza",
@@ -196,6 +198,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Trascina per ruotare l'appoggio a passi di 5°. Tieni premuto Alt o Ctrl per ruotarlo liberamente.",
"Drive Joint": "Aziona giunto",
"Duration": "Durata",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Ogni nuova forma viene quotata anche dall'origine dello schizzo finché nulla resta libero. Una forma già collegata all'origine o a geometria posizionata non ne riceve.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Ogni forma disegnata riceve tutte le sue quote alle dimensioni disegnate (i valori digitati hanno la precedenza). Una dimensione già fissata dallo schizzo viene omessa.",
"Edge": "Spigolo",
"Edges": "Spigoli",
"Edit": "Modifica",
@@ -1746,21 +1750,317 @@
"recovery.just_now": "proprio ora",
"recovery.min_ago": "{count} min fa",
"recovery.never_saved": "mai salvato",
"render.adaptive_absolute": "Soglia minima di errore RGB assoluto",
"render.adaptive_coverage": "Obiettivo di errore di copertura",
"render.adaptive_enable": "Assegna i campioni con piloti indipendenti",
"render.adaptive_help": "Solo GPU. I campioni pilota indipendenti vengono scartati, poi si assegnano 16 o più campioni di produzione per pixel fino a Campioni per pixel. La varianza di RGB e copertura guida l'assegnazione; i percorsi rari possono andare persi e i pixel limitati dal tetto possono restare rumorosi. Il rapporto finale conta il lavoro effettivo. Nessuna garanzia certificata su rumore o tempo.",
"render.adaptive_minimum": "Campioni di produzione minimi",
"render.adaptive_pending": "Sono disponibili l'assegnazione adattiva a piloti indipendenti su GPU e gli strati di Fresnel condizionali. Convergenza certificata, garanzie sugli eventi rari e trasporto adattivo su CPU restano non disponibili.",
"render.adaptive_pilots": "Campioni pilota per pixel",
"render.adaptive_relative": "Obiettivo di errore RGB relativo",
"render.add_ground": "Aggiungi all'impostazione il piano d'appoggio adattato",
"render.advanced_material_scope": "È disponibile un mezzo GPU omogeneo e finito entro limiti espliciti. Griglie di densità, combinazioni annidate di vetro e volume, superfici con scattering sottosuperficiale, displacement, trasporto spettrale e concetti avanzati di materiale non vincolati restano non disponibili.",
"render.aging_add": "Aggiungi strato di invecchiamento",
"render.aging_airborne": "Polvere sospesa / mezzo partecipante",
"render.aging_airborne_help": "La polvere sospesa è un volume di scattering omogeneo e finito, separato dalle superfici. Modifica il trasporto e l'EXR grezzo, non la pila di invecchiamento delle superfici. Le restrizioni esistenti su volume, vetro e riduzione del rumore restano esplicite; non viene aggiunta automaticamente alcuna atmosfera.",
"render.aging_all_bodies": "Tutti i corpi opachi idonei",
"render.aging_chips": "Vernice scheggiata",
"render.aging_class_any": "Tutte le classi di materiali opachi",
"render.aging_class_dielectric": "Solo superfici non metalliche",
"render.aging_class_metal": "Solo superfici metalliche",
"render.aging_color": "Colore dello strato · sRGB",
"render.aging_coverage": "Copertura",
"render.aging_dust": "Polvere depositata",
"render.aging_empty": "Nessuno strato di invecchiamento: le superfici originali restano invariate.",
"render.aging_fading": "Rivestimento sbiadito",
"render.aging_grime": "Sporco e macchie",
"render.aging_help": "Combina fino a otto strati ottici, in ordine. Ruggine e patina sono aspetti artistici, non simulazioni di invecchiamento o corrosione. La scala è in millimetri globali. Nessuna geometria, massa o proprietà ingegneristica viene modificata; vetro e scenografie passive sono esclusi.",
"render.aging_metallic": "Frazione metallica dello strato",
"render.aging_origin": "Origine del campo · mm globali",
"render.aging_patina": "Patina verde rame",
"render.aging_refresh_targets": "Esamina i corpi attuali",
"render.aging_roughness": "Rugosità dello strato",
"render.aging_rust": "Ferro ossidato / ruggine",
"render.aging_scale": "Scala del motivo",
"render.aging_scratches": "Graffi sottili",
"render.aging_target": "Destinazione e coordinate",
"render.aging_target_help": "Una destinazione con nome deve ancora corrispondere all'indice e al nome acquisiti. Le maschere globali sono ancorate al sistema globale e non seguono le parti in movimento. Non sono né un rilevamento delle cavità né una vera usura degli spigoli. Filtra l'elenco per raggiungere altri corpi.",
"render.aging_target_search": "Filtra i nomi dei corpi",
"render.aging_upward": "Deposito sulle superfici rivolte verso l'alto",
"render.all_controls_help": "Ispezione compatta di tutti i controlli attuali. Le pagine delle sezioni consentono una modifica mirata senza cambiare la richiesta sottostante.",
"render.all_shots_label": "Tutte le inquadrature",
"render.appearance_physics_separate": "L'aspetto visivo non assegna densità, dati termici o altre proprietà ingegneristiche.",
"render.availability_native": "Composizione nativa; verifica prima di applicare",
"render.availability_projection": "Proiezione supportata; vedi ambito e omissioni",
"render.availability_reference": "Dati di riferimento; non è un'assegnazione automatica",
"render.backdrop_alpha_conflict": "Scegli questo sfondo oppure l'uscita PNG trasparente; il motore di rendering non ignorerà in silenzio nessuna delle due impostazioni.",
"render.backdrop_enable": "Usa sfondo sfumato solo per la camera",
"render.backdrop_first": "Colore iniziale / centrale",
"render.backdrop_help": "Questo sfondo nello spazio schermo non illumina, non proietta ombre, non riflette e non rappresenta il terreno. È escluso dall'EXR grezzo. Geometria, luci e ambiente HDR restano indipendenti.",
"render.backdrop_horizontal": "Sfumatura orizzontale",
"render.backdrop_radial": "Sfumatura radiale",
"render.backdrop_radius": "Raggio",
"render.backdrop_second": "Colore finale / del bordo",
"render.backdrop_vertical": "Sfumatura verticale",
"render.backdrop_x": "Centro X",
"render.backdrop_y": "Centro Y",
"render.background": "Sfondo della scena",
"render.background_camera_section": "Sfondo della camera · presentazione PNG",
"render.background_completed_frozen": "Il risultato mostrato è un'immagine completata e congelata. La modifica di uno sfondo non ridisegna automaticamente quel risultato. Usa Correzione colore per le modifiche solo della camera oppure Rendering per una nuova scenografia fisica.",
"render.background_hdr_separate": "Le risorse HDR attuali illuminano le superfici e vi si riflettono; non vengono mostrate automaticamente come panorama dietro il soggetto. Modificare una sfumatura non ruota né ricolora l'illuminazione.",
"render.background_lighting_section": "Illuminazione HDR · separata dallo sfondo della camera",
"render.background_no_alpha_override": "Uno sfondo della camera non viene aggiunto in silenzio all'uscita trasparente. La correzione colore del master grezzo usa la copertura acquisita e non riapplica la riduzione del rumore; l'EXR di origine resta invariato.",
"render.background_not_light": "Il colore dello sfondo serve alla presentazione e non è una sorgente luminosa aggiuntiva.",
"render.background_regrade": "Applica al master grezzo conservato",
"render.background_stage_occlusion": "Questa inquadratura include la geometria fisica della scenografia. Un pavimento o una parete grande può riempire l'inquadratura e nascondere uno sfondo solo camera. Cancella o ridimensiona la scenografia di proposito oppure modifica la sua riflettanza fisica. La rielaborazione non può rimuovere la geometria acquisita.",
"render.background_workflow": "Scegli lo sfondo desiderato: un colore o una sfumatura solo camera, una scenografia fisica che riceve luce oppure l'illuminazione HDR. Sono indipendenti. L'anteprima in tempo reale è una vista di modellazione; esegui il rendering di una nuova immagine o rielabora un master conservato per vedere la finitura della camera.",
"render.base_appearance": "Aspetto modificabile del corpo",
"render.base_apply": "Applica l'aspetto del corpo",
"render.base_apply_help": "Un'unica assegnazione visiva annullabile al corpo esatto verificato. Gli aspetti specifici delle facce e i materiali tecnici esistenti restano separati.",
"render.base_color": "Colore di base · sRGB",
"render.base_metallic": "Frazione metallica",
"render.base_opaque_only": "Questo editor mantiene la semantica dei corpi opachi. Per la trasmissione ottica usa i controlli espliciti del vetro.",
"render.bloom_enable": "Bloom di visualizzazione",
"render.bloom_help": "Alone creativo solo in uscita, ricavato dalle alte luci lineari positive e diffuso con tre passate box normalizzate. Il raggio è in pixel di uscita. Viene aggiunto nella luce di visualizzazione lineare prima della conversione sRGB; non è un effetto di lente o volumetrico né un miglioramento della convergenza. L'EXR grezzo resta invariato.",
"render.bloom_opaque": "Il bloom richiede un'uscita opaca. Il PNG trasparente viene rifiutato, non appiattito in silenzio.",
"render.bloom_radius": "Raggio del bloom",
"render.bloom_strength": "Intensità del bloom",
"render.bloom_threshold": "Soglia lineare delle alte luci",
"render.browse_capabilities": "Esamina il catalogo completo delle funzionalità",
"render.browse_environments": "Sfoglia gli ambienti HDR originali",
"render.browse_native_scenes": "Sfoglia gli studi nativi",
"render.browse_physical": "Esamina i riferimenti fisici",
"render.browse_quality": "Esamina le specifiche di qualità",
"render.browse_rigs": "Sfoglia i set di luci predisposti",
"render.browse_scene_specs": "Sfoglia le specifiche avanzate della scena",
"render.browse_surfaces": "Sfoglia le superfici predisposte",
"render.browser_library": "Libreria",
"render.browser_model": "Modello",
"render.camera_distance": "Distanza dall'occhio al punto di mira",
"render.camera_exact_help": "Millimetri nel sistema globale; gli angoli sono mostrati in gradi e salvati in radianti. La navigazione usa la stessa camera della vista 3D.",
"render.camera_fov": "Campo visivo verticale",
"render.camera_pitch": "Beccheggio della camera",
"render.camera_roll": "Rollio",
"render.camera_set": "Imposta camera di rendering",
"render.camera_target": "Posizione del punto di mira · mm",
"render.camera_yaw": "Imbardata",
"render.chromatic_offset": "Scostamento cromatico dei bordi",
"render.clear_stage": "Rimuovi la scenografia salvata",
"render.copy_request": "Copia JSON",
"render.cpu_aa_help": "Campioni spaziali: più campioni migliorano i bordi e aumentano il tempo di rendering.",
"render.cpu_area_add": "Aggiungi luce rettangolare CPU",
"render.cpu_area_editor": "Luci rettangolari CPU",
"render.cpu_area_editor_help": "Vettori dei lati interi in millimetri; il prodotto vettoriale U × V punta verso il lato emittente. Ciò differisce dai vettori di semilato della GPU.",
"render.cpu_area_full_u": "Lato U intero · mm",
"render.cpu_area_full_v": "Lato V intero · mm",
"render.cpu_area_samples": "Campioni delle luci ad area",
"render.cpu_binding_confirm": "Conferma questo corpo",
"render.cpu_binding_stale": "La scena è cambiata. Conferma di nuovo questa destinazione di riflessione prima del rendering.",
"render.cpu_body_choose": "Scegli un corpo",
"render.cpu_body_filter": "Filtra i corpi per nome",
"render.cpu_body_filter_more": "Restringi il filtro per vedere altri corpi.",
"render.cpu_body_missing": "Una destinazione di riflessione è mancante, nascosta, ambigua oppure ha un nome più lungo di 128 byte. Sceglila di nuovo.",
"render.cpu_budget": "Profilo di risorse della CPU",
"render.cpu_budget_bodies": "Limite di corpi",
"render.cpu_budget_compact": "Compatto (limiti precedenti)",
"render.cpu_budget_details": "Limiti delle risorse",
"render.cpu_budget_help": "Scegli esplicitamente limiti più alti. Risoluzione e campioni non vengono mai ridotti automaticamente.",
"render.cpu_budget_memory": "Limite di memoria del lavoro",
"render.cpu_budget_not_guarantee": "Sono limiti di ammissione, non una riserva di RAM né una garanzia di velocità. Geometria, buffer immagine e anteprime conservate condividono il budget di memoria; il rendering può sempre essere annullato.",
"render.cpu_budget_resize": "La bozza supera questo profilo CPU o il suo budget di campioni della camera. Accetta esplicitamente dimensioni inferiori oppure seleziona un profilo più grande.",
"render.cpu_budget_studio": "Studio (immagini grandi)",
"render.cpu_budget_triangles": "Limite di triangoli",
"render.cpu_budget_workstation": "Workstation (scene complesse)",
"render.cpu_captured_hdr": "HDR acquisito per questa immagine",
"render.cpu_check_capture_help": "Verifica e Avvia controllano lo stesso digest del file o usano l'HDR incorporato. Ogni immagine mantiene la propria origine acquisita.",
"render.cpu_check_changed": "I comandi o il modello sono cambiati dopo questa verifica. Verifica di nuovo prima di eseguire il rendering.",
"render.cpu_constant_help": "La radianza costante è visibile ai raggi riflessi o trasmessi. Non fornisce illuminazione diffusa diretta.",
"render.cpu_custom_directions": "Sostituisci la preimpostazione con luci direzionali personalizzate",
"render.cpu_direction": "Direzione verso la luce (X, Y, Z)",
"render.cpu_directional": "Luce direzionale",
"render.cpu_directional_add": "Aggiungi luce direzionale",
"render.cpu_environment": "Ambiente CPU",
"render.cpu_environment_background": "Lo sfondo dell'immagine resta separato dall'illuminazione ambientale.",
"render.cpu_environment_bounds": "L'intensità CPU deve essere compresa tra 0 e 64, la rotazione HDR deve essere finita entro ±1,000,000 radianti e i campioni HDR devono essere 1, 4, 16 o 64.",
"render.cpu_environment_constant": "Ambiente costante per i raggi secondari",
"render.cpu_environment_none": "Nessun ambiente CPU",
"render.cpu_environment_samples": "Campioni di illuminazione HDR",
"render.cpu_exposure_help": "L'esposizione CPU deve essere compresa tra −16 e 16 EV. Un'esposizione GPU fuori da questo intervallo viene mantenuta finché non la modifichi.",
"render.cpu_fixed": "Immagine singola",
"render.cpu_hdr_help": "Radiance .hdr, panorama 2:1, fino a 2048 × 1024 e 16 MiB. La CPU richiede primari sRGB/D65 espliciti nel file; i primari non specificati e i file EXR vengono rifiutati.",
"render.cpu_hdr_reflection_help": "Le riflessioni ruvide HDR richiedono superfici di corpi e facce completamente metalliche. Verifica segnala le combinazioni non supportate.",
"render.cpu_key_rim": "Principale e controluce",
"render.cpu_last_check": "Ultima verifica CPU",
"render.cpu_light_help": "Fino a otto luci direzionali. Un elenco personalizzato vuoto le disattiva; selezionando una preimpostazione si ripristinano le sue luci. I colori sono RGB lineari e l'intensità è relativa, non in watt.",
"render.cpu_light_intensity": "Intensità relativa (0–64)",
"render.cpu_light_minimum": "Distanza minima per l'attenuazione",
"render.cpu_light_position": "Posizione globale (X, Y, Z)",
"render.cpu_light_reference": "Distanza di riferimento per l'intensità",
"render.cpu_light_remove": "Rimuovi luce",
"render.cpu_lighting": "Preimpostazione di illuminazione",
"render.cpu_lights": "Luci CPU",
"render.cpu_linear_color": "Colore lineare (R, G, B)",
"render.cpu_neutral": "Neutra",
"render.cpu_opaque_required": "Il ray tracing su CPU richiede uno sfondo opaco. Deseleziona Sfondo trasparente per continuare.",
"render.cpu_options_pending": "Questo pannello CPU non può ancora modificare emissione, effetti di superficie, vetro o anisotropia. Rimuovi queste opzioni API prima di usarlo.",
"render.cpu_point": "Luce puntiforme",
"render.cpu_point_add": "Aggiungi luce puntiforme",
"render.cpu_point_help": "Fino a otto luci puntiformi, aggiunte all'illuminazione direzionale selezionata. Le distanze sono in mm; il minimo non deve superare la distanza di riferimento.",
"render.cpu_primary_samples": "Campioni dei bordi per pixel",
"render.cpu_progressive": "CPU progressiva",
"render.cpu_progressive_help": "Accumula l'integratore CPU esistente in passate di un campione primario. Le riflessioni selezionate richiedono un solo campione; luci d'area, dielettrici e anisotropia richiedono Immagine singola.",
"render.cpu_progressive_limits": "Al massimo 1,048,576 pixel e 16,777,216 valutazioni pixel × campione. Cambiare i campioni non ridimensiona mai automaticamente l'immagine.",
"render.cpu_progressive_seed": "Seme di campionamento CPU",
"render.cpu_progressive_spp": "campioni per pixel",
"render.cpu_reflection_add": "Aggiungi riflessione ruvida",
"render.cpu_reflection_depth": "Profondità delle riflessioni (1–8)",
"render.cpu_reflection_empty": "Nessun corpo selezionato: le riflessioni della scena sono disattivate.",
"render.cpu_reflection_help": "Scegli i corpi e imposta Disattivato, Specchio o Ruvida. Ruvida usa la rugosità della superficie assegnata. Più campioni e rimbalzi aumentano il tempo; si tratta di trasporto speculare limitato, non di illuminazione globale.",
"render.cpu_reflection_limit": "Sono supportati fino a 64 corpi riflessi.",
"render.cpu_reflection_mirror": "Specchio",
"render.cpu_reflection_off": "Disattivato",
"render.cpu_reflection_rough": "Ruvida",
"render.cpu_reflection_samples": "Campioni di riflessione (1–64)",
"render.cpu_reflections": "Riflessioni CPU",
"render.cpu_runtime_help": "Le impostazioni numeriche di luce e ambiente vengono salvate con l'impostazione. Le riflessioni dei corpi e i file HDR restano temporanei. I valori esistenti di luci d'area e coni degli spot vengono mantenuti.",
"render.cpu_sampling_mode": "Modalità di campionamento CPU",
"render.cpu_shadows": "Proietta ombre",
"render.cpu_summary": "Ray tracing su CPU · riflessioni · HDR · luci direzionali e puntiformi",
"render.cpu_warm_cool": "Calda e fredda",
"render.diag_bodies": "Corpi visibili",
"render.diag_job_details": "Dettagli del lavoro acquisito",
"render.diag_last_check": "Ultimo controllo preliminare",
"render.diag_memory": "Stima logica per l'ammissione",
"render.diag_not_implemented": "Limiti di funzionalità espliciti",
"render.diag_preflight_details": "Dettagli del controllo preliminare",
"render.diag_request": "Richiesta corrente esatta",
"render.diag_triangles": "Triangoli",
"render.discard_continue": "Scarta la bozza e continua",
"render.draft_confirm_help": "La bozza di rendering corrente contiene modifiche non applicate. Salvale prima di cambiare, scartale esplicitamente oppure continua a modificare.",
"render.draft_confirm_title": "Conserva le impostazioni di rendering modificate",
"render.effects_gpu_only": "Questi effetti richiedono il path tracing su GPU. Cambiare pagina non cambia mai automaticamente il motore di rendering.",
"render.effects_help": "Combina look cromatici ordinati ed effetti obiettivo nello spazio immagine. Il rendering e la correzione colore del master grezzo usano le stesse impostazioni salvate. L'EXR grezzo resta invariato. Sono controlli artistici originali, non emulazioni calibrate di obiettivi o di pellicole di marche specifiche.",
"render.effects_reset_lens": "Reimposta effetti obiettivo",
"render.effects_seed": "Seme del motivo",
"render.emitted_axis": "Asse di emissione",
"render.error_area_samples": "area_samples deve essere 1, 4, 16 o 64",
"render.error_binding_allocation": "impossibile riservare l'associazione del materiale",
"render.error_body_bound": "l'anteprima del prodotto supera il limite dei corpi acquisiti",
"render.error_checkpoint_dimensions": "le dimensioni del punto di ripristino differiscono dalla richiesta acquisita",
"render.error_decode_budget": "superato il budget di decodifica dell'immagine",
"render.error_denoise_setting": "impostazione nativa di riduzione del rumore non valida",
"render.error_display_dimensions": "dimensioni di visualizzazione dell'immagine non valide",
"render.error_display_fit": "la visualizzazione dell'immagine supera i limiti di questo dispositivo",
"render.error_display_height": "altezza di visualizzazione fuori limite",
"render.error_display_width": "larghezza di visualizzazione fuori limite",
"render.error_duplicate_face": "aspetto duplicato per una faccia del prodotto",
"render.error_export_document": "Il documento di esportazione del rendering è cambiato durante la scelta della destinazione",
"render.error_face_cap": "l'anteprima del prodotto supera il limite di ammissione degli aspetti delle facce",
"render.error_finish_gesture": "termina il gesto di modellazione prima dell'anteprima",
"render.error_finish_operation": "termina l'operazione di modellazione corrente prima di entrare in Rendering",
"render.error_fixed_preview": "l'anteprima fissa Studio richiede esposizione 0, rotazione dell'ambiente 0 e intensità 1",
"render.error_geometry_size": "dimensione della geometria del prodotto fuori limite",
"render.error_glass_recipe": "ricetta del vetro sconosciuta",
"render.error_gpu_preview": "L'anteprima del prodotto su GPU non è disponibile su questo sistema. Le impostazioni salvate restano disponibili.",
"render.error_gpu_samples": "numero di campioni GPU non supportato",
"render.error_image_dimensions": "le dimensioni dell'immagine di rendering non corrispondono al lavoro",
"render.error_image_profile": "l'immagine di rendering supera il profilo di risorse acquisito",
"render.error_interactive_command": "comando interattivo di Rendering non associato",
"render.error_job_action": "non è un'azione interattiva del lavoro immagine",
"render.error_job_identity": "identità del lavoro di rendering non valida: {error}",
"render.error_library_reply": "risposta della libreria di rendering non valida",
"render.error_material_binding": "associazione del materiale mancante",
"render.error_no_completed_image": "il rendering non ha alcuna immagine completata",
"render.error_no_geometry": "nessuna geometria del prodotto",
"render.error_no_scene": "nessuna scena del prodotto",
"render.error_opacity": "opacità dell'aspetto del prodotto non valida",
"render.error_pbr_opacity": "il PBR opaco richiede opacità 1",
"render.error_physical_glass": "la ricetta selezionata non è un vetro fisico",
"render.error_preview_device": "l'anteprima del prodotto richiede un dispositivo installato con buffer di profondità",
"render.error_product_triangle": "triangolo del prodotto non valido",
"render.error_provisional_identity": "identità o numero di campioni del rendering provvisorio non validi",
"render.error_quality_bounds": "la proiezione della qualità supera i limiti nativi",
"render.error_quality_method": "la proiezione della qualità richiede lo stesso metodo GPU esplicito",
"render.error_quality_projection": "proiezione nativa della qualità non valida",
"render.error_regrade_identity": "identità di correzione colore non valida: {error}",
"render.error_scene_bodies": "corpi della scena di rendering mancanti",
"render.error_scene_body_limit": "la scena di rendering supera il limite di corpi",
"render.error_scene_identity": "identità della scena di rendering non valida",
"render.error_setup_panicked": "la configurazione del path tracer GPU è terminata con un errore interno",
"render.error_setup_stopped": "il thread di configurazione si è arrestato senza restituire un host",
"render.error_setup_worker": "impossibile avviare il thread di configurazione: {error}",
"render.error_source_preview": "l'anteprima di origine supera il limite di byte",
"render.error_surface_normals": "il PBR richiede normali di superficie diverse da zero",
"render.error_surface_reply": "risposta di superficie predisposta non valida",
"render.error_triangle_bound": "l'anteprima del prodotto supera il limite sorgente di otto milioni di triangoli",
"render.error_triangle_count": "overflow del conteggio dei triangoli del prodotto",
"render.error_upload_slot": "slot di caricamento dell'anteprima del prodotto non disponibile",
"render.error_vertex_allocation": "allocazione dei vertici dell'anteprima del prodotto non riuscita",
"render.error_vertex_envelope": "l'anteprima del prodotto supera il limite di {limit} MiB per i dati dei vertici; la geometria non è stata semplificata",
"render.error_vertex_packing": "il packing dell'anteprima del prodotto differisce dai dati dei vertici ammessi",
"render.error_visible_solid": "Crea un solido visibile in Progettazione per vederne qui l'anteprima.",
"render.exit_focus": "Esci dal focus",
"render.export_display": "Esporta: PNG per la visualizzazione",
"render.export_image_label": "Esporta immagine",
"render.export_linear": "Esporta: EXR lineare grezzo",
"render.exr_pending": "La GPU può conservare l'EXR lineare grezzo. Compressione, immagini multilivello e pass di rendering ausiliari restano non disponibili.",
"render.film_grain": "Grana fotografica",
"render.fit": "Inquadra prodotto",
"render.fixed_camera": "Camera",
"render.fixed_world": "Mondo",
"render.flare_ghosts": "Anelli fantasma per sorgente",
"render.flare_halo": "Alone del flare",
"render.flare_streak": "Striatura in stile anamorfico",
"render.flare_strength": "Intensità del flare sulle alte luci",
"render.flare_threshold": "Soglia del flare lineare della scena",
"render.fold_browser": "Comprimi struttura",
"render.gpu_depth": "Profondità massima del percorso",
"render.gpu_options_help": "Campioni, profondità, seed ed esposizione vengono salvati con questa impostazione. Viene salvato solo il metodo di generazione attivo.",
"render.gpu_path_failed": "Path tracer GPU non disponibile",
"render.gpu_path_first_setup": "La prima configurazione su questa GPU può richiedere diversi minuti; nel frattempo SolidCraft resta utilizzabile. Gli avvii successivi riutilizzano gli shader compilati, se il driver li conserva.",
"render.gpu_path_preparing": "Path tracer GPU: compilazione degli shader…",
"render.gpu_seed": "Seed casuale",
"render.gpu_unavailable": "Il path tracing su GPU non è pronto su questo dispositivo.",
"render.ground_apply": "Adatta e salva il pavimento",
"render.ground_gap": "Distanza libera esplicita",
"render.ground_linear_rgb": "Riflettanza diffusa · RGB lineare",
"render.ground_margin": "Margine di estensione del pavimento",
"render.hdr_details": "Dettagli della sorgente HDR",
"render.hdr_embedded": "HDR salvato in questo progetto",
"render.hdr_embedded_help": "Il rendering usa i byte inclusi nel progetto; il file originale non è più necessario.",
"render.hdr_file_captured": "File HDR verificato. Il salvataggio incorporerà questi byte; se il file cambia, verificalo di nuovo esplicitamente.",
"render.hdr_inspect": "Verifica file HDR",
"render.hdr_inspect_required": "Seleziona e verifica un file HDR prima di salvare o eseguire il rendering.",
"render.hdr_primaries_declared": "La sorgente dichiara i propri primari di colore.",
"render.hdr_primaries_srgb": "Primari di colore: sRGB/D65",
"render.hdr_primaries_undeclared": "La sorgente non dichiara i primari; controlla i requisiti di colore del motore di rendering.",
"render.hdr_resource_missing": "In questo progetto manca la risorsa HDR salvata.",
"render.heading_batch": "BATCH",
"render.heading_frame": "FOTOGRAMMA",
"render.heading_lens": "OBIETTIVO",
"render.heading_results": "RISULTATI",
"render.heading_shots": "INQUADRATURE",
"render.hide_shots_label": "Nascondi la barra delle inquadrature",
"render.image_advanced": "Controlli GPU avanzati",
"render.image_cancelled": "Rendering annullato",
"render.image_cancelling": "Annullamento",
"render.image_completed": "Immagine pronta per l'esportazione",
"render.image_encoding": "Codifica PNG",
"render.image_export": "Esporta PNG",
"render.image_exposure": "Esposizione",
"render.image_failed": "Rendering non riuscito",
"render.image_height": "Altezza",
"render.image_help": "Immagine di anteprima CPU · PNG · trasparenza approssimata",
"render.image_host_missing": "Non è installato alcun host per le immagini.",
"render.image_method": "Metodo di generazione dell'immagine",
"render.image_overwrite": "Sostituisci file esistente",
"render.image_preparing": "Preparazione dell'immagine",
"render.image_progressive": "Rendering progressivo",
"render.image_queued": "In attesa di rendering",
"render.image_reduce": "Prova un'immagine più piccola o una scena più semplice.",
"render.image_running": "Rendering dell'immagine",
"render.image_samples": "Campioni per pixel",
"render.image_scene_stale": "Termina l'operazione di modellazione o aggiorna la scena prima di verificare o avviare un'immagine.",
"render.image_stale": "Questa immagine usa la scena acquisita prima delle modifiche successive.",
"render.image_start": "Avvia rendering",
"render.image_supported": "La richiesta di rendering è supportata; la coda e il pool di memoria saranno ricontrollati all'avvio.",
@@ -1770,20 +2070,430 @@
"render.image_unknown": "Stato del rendering non disponibile",
"render.image_use_largest": "Usa le dimensioni massime con queste proporzioni:",
"render.image_width": "Larghezza",
"render.include_rig_cards": "Includi pannelli e bandiere passivi",
"render.inner_half_angle": "Semiangolo interno",
"render.inspect_scene": "Aggiorna il riepilogo della scena acquisita",
"render.inspector": "Ispettore",
"render.keep_editing": "Continua a modificare",
"render.layer_down": "Sposta giù",
"render.layer_enabled": "Livello abilitato",
"render.layer_off_suffix": " (disattivato)",
"render.layer_remove": "Rimuovi livello",
"render.layer_strength": "Intensità del livello",
"render.layer_up": "Sposta su",
"render.lens_effects_help": "Il flare usa fino a quattro sorgenti luminose separate nell'immagine lineare effettiva. Fantasmi, alone, striature, scostamenti cromatici e distorsione radiale sono approssimazioni artistiche nello spazio immagine. Gli effetti spaziali richiedono un output opaco; i campioni esterni estendono il bordo dell'immagine. La grana è deterministica. Non vengono alterati fisica, EXR o geometria.",
"render.lens_effects_title": "Effetti d'obiettivo e fotografici",
"render.library_all": "Catalogo",
"render.library_all_states": "Tutti gli stati di disponibilità",
"render.library_applied": "Proiezione della risorsa applicata. Verifica la richiesta di rendering completa prima di avviare.",
"render.library_apply_hdr": "Salva con questo ambiente HDR",
"render.library_apply_maps": "Usa le mappe di superficie GPU predisposte",
"render.library_apply_studio": "Salva la proiezione dello studio predisposta",
"render.library_apply_uniform": "Applica aspetto opaco uniforme",
"render.library_authored_help": "Le risorse originali predisposte sono illustrative, non dati tecnici misurati. Ogni azione applica solo la proiezione indicata.",
"render.library_blocked": "Bloccato / richiede calibrazione",
"render.library_capabilities": "Specifiche delle funzionalità",
"render.library_center": "Centro del rig",
"render.library_clear_search": "Cancella",
"render.library_details": "Specifiche e provenienza",
"render.library_emitters_only_ack": "Usa solo gli emettitori; ometti i pannelli passivi documentati",
"render.library_empty": "Nessuna risorsa corrispondente. Prova una ricerca o un filtro di disponibilità diversi.",
"render.library_environment_concepts": "Concetti di ambiente",
"render.library_extent": "Estensione del soggetto",
"render.library_favorite": "Aggiungi ai preferiti",
"render.library_favorites": "Preferiti",
"render.library_hdr": "Ambienti HDR integrati",
"render.library_hdr_help": "Incorpora l'HDR originale nell'impostazione salvata. L'origine della longitudine predisposta viene convertita esplicitamente; dopo il salvataggio non serve alcun file esterno.",
"render.library_inspect_only": "Seleziona per esaminare; non viene applicato nulla automaticamente. I preferiti e la cronologia recente appartengono a questa sessione del documento aperto.",
"render.library_light_concepts": "Concetti di illuminazione",
"render.library_maps_help": "Le mappe integrate possono essere salvate con sorgenti fissate e mappatura locale delle occorrenze. Le sostituzioni ottiche temporanee restano una modalità separata.",
"render.library_material_concepts": "Concetti di materiale",
"render.library_native_scenes": "Studi nativi",
"render.library_next": "Pagina successiva",
"render.library_omitted": "Non incluso",
"render.library_physical_profiles": "Profili fisici di riferimento",
"render.library_previous": "Pagina precedente",
"render.library_quality_concepts": "Specifiche di qualità",
"render.library_recent": "Recenti",
"render.library_replace_environment": "Sostituisci esplicitamente l'ambiente esistente",
"render.library_replace_studio": "Sostituisci illuminazione, ambiente e scenografia salvati",
"render.library_results": "Risorse corrispondenti",
"render.library_rig_help": "Adatta una sola volta a un centro e a un'estensione fisica espliciti. I rig completi includono pannelli passivi; i blocchi di calibrazione continuano a rifiutare l'operazione. Prima del salvataggio viene verificata una distanza libera prudenziale tra emettitori e pannelli.",
"render.library_rigs": "Rig di illuminazione predisposti",
"render.library_save_maps": "Salva le mappe in questa impostazione",
"render.library_scene_bounds": "Usa i limiti della scena acquisita",
"render.library_scenes": "Specifiche della scena",
"render.library_search": "Cerca nella libreria",
"render.library_select_hint": "Scegli una risorsa nella Libreria per esaminarne le azioni supportate e i limiti.",
"render.library_selene": "Aspetti opachi SELENE",
"render.library_selene_shots": "Specifiche delle inquadrature SELENE",
"render.library_short_blocked": "Non disponibile",
"render.library_short_native": "Composizione nativa",
"render.library_short_projection": "Proiezione supportata",
"render.library_short_reference": "Solo riferimento",
"render.library_short_specification": "Solo specifica",
"render.library_source_preview": "Carica anteprima della mappa sorgente",
"render.library_source_preview_help": "Mappa sorgente del colore base predisposta. Non è un'anteprima del materiale renderizzata o misurata.",
"render.library_specification_only": "Solo specifica: non è una preimpostazione eseguibile completa. Gli effetti, le risorse e i ruoli dei soggetti richiesti necessitano ancora di un'implementazione e di un'associazione esplicite.",
"render.library_specs": "Solo specifiche",
"render.library_status": "Disponibilità",
"render.library_surfaces": "Superfici PBR predisposte",
"render.library_target": "Corpo di destinazione",
"render.library_title": "Libreria di risorse di rendering",
"render.library_unfavorite": "Rimuovi dai preferiti",
"render.library_uniform_ack": "Usa l'approssimazione uniforme senza effetti spaziali o avanzati",
"render.library_usable": "Proiezioni eseguibili",
"render.light_anchor_pending": "La modifica del sistema di coordinate delle luci non è ancora supportata.",
"render.lights_fixed_to": "Luci fissate a",
"render.linear_help": "Mantiene un master RGBA float a 32 bit prima di riduzione del rumore, esposizione, tone mapping, filtri e sfondo. sRGB lineare/D65; con alfa premoltiplicato dalla copertura. La memoria aggiuntiva viene ammessa esplicitamente. Nessuna compressione né passate aggiuntive.",
"render.linear_retain": "Conserva EXR lineare grezzo",
"render.linear_unavailable": "L'immagine completata selezionata non ha un EXR conservato. Abilita la conservazione prima del rendering; un PNG precedente non può recuperare la radianza grezza.",
"render.look_add": "Aggiungi look cromatico",
"render.look_bleach": "Ispirato al bleach bypass",
"render.look_cool": "Freddo",
"render.look_cyanotype": "Ispirato alla cianotipia",
"render.look_faded": "Stampa sbiadita",
"render.look_mono": "Monocromatico",
"render.look_sepia": "Seppia",
"render.look_strength": "Intensità del look",
"render.look_teal_orange": "Turchese / arancione",
"render.look_title": "Pila di look creativi",
"render.look_warm": "Caldo",
"render.mapping_scale": "Moltiplicatore di ripetizione fisica",
"render.material_absorption": "Assorbimento R · G · B (per mm)",
"render.material_add": "Aggiungi o modifica questo corpo",
"render.material_assignments": "Assegnazioni ai corpi",
"render.material_binding_enable": "Includi la sostituzione di questo corpo",
"render.material_box": "Parallelepipedo allineato agli assi",
"render.material_browse": "Scegli immagine…",
"render.material_certification": "Il vetro chiuso usa la distanza geometrica. Topologia, orientamento, sovrapposizione e confini ottici vengono controllati durante la preparazione GPU; Verifica ammette soltanto la richiesta.",
"render.material_choose_body": "Scegli un corpo della scena",
"render.material_closed": "Mesh solida chiusa",
"render.material_coat": "Strato trasparente sopra il materiale di base",
"render.material_coat_enable": "Abilita strato trasparente",
"render.material_coat_help": "Rivestimento dielettrico illustrativo sopra l'aspetto opaco esistente. Con peso zero il materiale di base resta invariato.",
"render.material_color_map": "Immagine del colore di base (sRGB)",
"render.material_color_replace": "La mappa di base sostituisce il colore del corpo",
"render.material_custom": "Ottica illustrativa personalizzata",
"render.material_enable": "Usa queste sostituzioni di materiale GPU",
"render.material_filter": "Filtra i corpi della scena…",
"render.material_filter_help": "Vengono mostrati fino a 128 corpi corrispondenti. Restringi il filtro per le scene di grandi dimensioni.",
"render.material_glass": "Vetro e assorbimento ottico",
"render.material_glass_enable": "Usa vetro fisico su questo corpo",
"render.material_glass_exclusive": "In questo motore di rendering il vetro non può condividere un corpo con lo strato trasparente o con le mappe a runtime.",
"render.material_glass_help": "Ricette illustrative originali. Le campionature mostrano la trasmittanza, non un'anteprima renderizzata. L'assorbimento è −ln(trasmittanza lineare) / distanza di riferimento; l'alfa resta invariato.",
"render.material_gpu_required": "Queste sostituzioni di materiale attive richiedono il path tracing su GPU. Seleziona GPU o disattiva le sostituzioni prima di Verifica o Avvia.",
"render.material_ior": "Indice di rifrazione (IOR)",
"render.material_limits": "Al massimo 128 sostituzioni di corpi, 32 corpi di vetro disgiunti, 64 strati trasparenti e 128 associazioni di texture. Le mappe identiche condividono lo spazio di memoria; restano comunque validi i limiti effettivi del dispositivo e della memoria totale.",
"render.material_map_invalid": "I percorsi delle mappe devono essere percorsi locali limitati; l'intensità delle normali deve essere finita e compresa tra 0 e 1.",
"render.material_map_required": "Scegli un'immagine del colore o un'immagine delle normali prima di usare le mappe.",
"render.material_maps": "Mappe planari di colore e normali",
"render.material_maps_enable": "Abilita le mappe per questo corpo opaco",
"render.material_maps_help": "PNG/JPEG fino a 1024×1024; 16 MiB codificati in totale. U e V sono vettori di ripetizione ortogonali in mm globali (massimo 128 ripetizioni). Il colore è sRGB; i dati delle normali usano OpenGL +Y. I file vengono acquisiti con Verifica/Avvia.",
"render.material_metallic_map": "Mappa del metallo (lineare)",
"render.material_normal_map": "Immagine delle normali (OpenGL, +Y)",
"render.material_normal_strength": "Intensità delle normali (0–1)",
"render.material_origin": "Origine della mappatura X · Y · Z (mm)",
"render.material_refresh": "Aggiorna i corpi della scena",
"render.material_refresh_needed": "La scena è cambiata. Aggiorna l'elenco dei corpi prima di aggiungere una destinazione.",
"render.material_remove": "Rimuovi questa assegnazione",
"render.material_repeat_u": "Una ripetizione U X · Y · Z (mm)",
"render.material_repeat_v": "Una ripetizione V X · Y · Z (mm)",
"render.material_revalidate": "Riconvalida questo corpo",
"render.material_revalidate_needed": "Questa assegnazione appartiene a una revisione precedente della scena. Riconvalida l'identità esatta del corpo prima del rendering.",
"render.material_roughness": "Rugosità dello strato trasparente (0,045–1)",
"render.material_roughness_map": "Mappa della rugosità (lineare)",
"render.material_shadow": "Trasmetti i raggi d'ombra rettilinei",
"render.material_target_missing": "L'ordinale e il nome del corpo non corrispondono più. Rimuovi questa assegnazione e scegli di nuovo esplicitamente il corpo desiderato.",
"render.material_thickness": "Spessore del foglio sottile (mm)",
"render.material_thin": "Foglio sottile",
"render.material_title": "Materiali immagine GPU",
"render.material_transient": "Sostituzioni ottiche temporanee per questa scheda del documento. Non vengono salvate nel progetto, nell'impostazione di rendering né nella libreria dei materiali.",
"render.material_v_up": "La V della texture punta verso l'alto nell'immagine",
"render.material_weight": "Peso dello strato trasparente (0–1)",
"render.method_cpu": "Ray tracing su CPU",
"render.method_gpu": "Path tracing su GPU",
"render.method_limit_raster": "Il raster usa l'anteprima Studio fissa e opaca. Seleziona un metodo di ray tracing esplicito per i comandi ottici supportati.",
"render.method_raster": "Raster su CPU",
"render.navigation_help": "La camera si muove come in Progettazione (Preferenze › Navigazione). Salva impostazione memorizza la camera corrente.",
"render.nested_enable": "Dielettrici annidati certificati",
"render.nested_help": "Fino a 16 livelli contenitori; ogni genitore deve essere convesso e ogni figlio strettamente al suo interno. Intersezioni, superfici a contatto, fogli sottili e trasmissione di ombre rettilinee vengono rifiutati. Lo stato con la camera all'interno segue la gerarchia certificata. Non crea una superficie liquida né unisce i confini CAD a contatto.",
"render.opaque_image_summary": "PNG di anteprima · PBR opaco · trasparenza miscelata",
"render.opaque_preview_help": "PBR opaco e colori semplici; trasparenza miscelata. Rifrazione, HDRI e rendering finale non sono ancora disponibili.",
"render.optics_remove": "Rimuovi ottica salvata",
"render.optics_replace": "Sostituisci esplicitamente l'ottica salvata di questa destinazione",
"render.optics_save": "Salva questa ottica nell'impostazione",
"render.optics_saved": "Destinazioni ottiche salvate",
"render.optics_saved_help": "L'identità esatta di definizione, lavorazione e occorrenza sopravvive alla riapertura offline. Le destinazioni mancanti, sostituite o nascoste vengono rifiutate; i materiali tecnici restano invariati. Salva o scarta le modifiche numeriche prima di rimuovere una destinazione salvata.",
"render.outer_half_angle": "Semiangolo esterno",
"render.output_format_status": "Il PNG è l'immagine visualizzata completata, esattamente com'è. L'EXR GPU facoltativo conserva la radianza FLOAT32 lineare della scena, grezza, prima dei filtri di visualizzazione. L'esportazione non sostituisce mai la cache dell'anteprima né un lavoro diverso.",
"render.output_lock_ratio": "Blocca proporzioni",
"render.output_over_budget": "L'immagine richiesta supera i limiti di risorse selezionati. Scegli esplicitamente una dimensione o un profilo compatibile; non avviene alcun declassamento automatico.",
"render.output_ratio_refused": "La dimensione collegata supera il limite di dimensioni di questo metodo. Viene mantenuta la dimensione precedente; sblocca le proporzioni o scegli un valore più piccolo.",
"render.output_swap_orientation": "Scambia larghezza e altezza",
"render.output_tools_inspector": "Modifica dimensioni e formato nell'ispettore Uscita.",
"render.page_aging": "Invecchiamento e contaminazione",
"render.page_all": "Tutti i comandi",
"render.page_appearance": "Aspetto",
"render.page_background": "Sfondi",
"render.page_camera": "Camera",
"render.page_diagnostics": "Diagnostica",
"render.page_effects": "Effetti obiettivo e di finitura",
"render.page_environment": "Ambiente",
"render.page_lighting": "Illuminazione",
"render.page_output": "Uscita",
"render.page_scene": "Scena",
"render.paint_label": "Vernice",
"render.passive_stage": "Piano d'appoggio e scenografia passiva",
"render.passive_stage_help": "I pannelli passivi finiti appartengono solo alle immagini renderizzate. Non aggiungono corpi CAD né massa. Il posizionamento è fisso dopo l'applicazione; se intersecano l'ingombro del prodotto, vengono rifiutati. La CPU non fornisce illuminazione diffusa di rimbalzo.",
"render.perspective": "Camera prospettica",
"render.physical_acknowledge": "Comprendo che questo riferimento parziale richiede una revisione di grado, condizione e fonte",
"render.physical_associations": "Candidati fisici e ruoli",
"render.physical_background_help": "Pavimento e parete passivi reali, separati dallo sfondo della camera. Il ciclorama usa 24 strisce poligonali; non è una superficie infinita né analiticamente liscia. Sostituisce la scenografia salvata solo con il tuo consenso.",
"render.physical_copy_plan": "Copia il piano con fonti e omissioni",
"render.physical_cyclorama": "Adatta ciclorama poligonale",
"render.physical_floor_wall": "Adatta pavimento e parete fisici",
"render.physical_material_name": "Nome proposto per il materiale di riferimento",
"render.physical_omissions": "Proprietà non rappresentabili nella scheda nativa",
"render.physical_plan_only": "Piano di sola lettura preparato. Nessun materiale è stato creato o assegnato. Conserva il suo profilo esteso e le omissioni quando esamini la scheda nativa.",
"render.physical_prepare_plan": "Prepara piano di creazione (non lo applica)",
"render.physical_separate": "L'aspetto non equivale all'identificazione del materiale. Si tratta di riferimenti documentati, non di proprietà effettive certificate. Massa, materiali tecnici e ottica esistenti restano invariati.",
"render.physical_unknown": "Nessun candidato numerico è stabilito. Occorre specificare il grado, la formulazione o la costruzione; sconosciuto non significa zero.",
"render.pick_body": "Corpo",
"render.pick_component": "Componente",
"render.pick_face": "Faccia",
"render.pick_help": "Scegli Corpo, Faccia o Componente. Fai clic nello spazio vuoto per deselezionare; Shift o Ctrl aggiunge o commuta la selezione. Le evidenziazioni compaiono solo nella vista live del prodotto.",
"render.pick_label": "Seleziona",
"render.pick_up_label": "Preleva",
"render.pick_waiting": "La selezione sul prodotto non è ancora supportata.",
"render.post_contrast": "Contrasto",
"render.post_gain_b": "Guadagno blu",
"render.post_gain_g": "Guadagno verde",
"render.post_gain_r": "Guadagno rosso",
"render.post_help": "Solo presentazione creativa. I guadagni RGB precedono il tone mapping; contrasto, saturazione e vignettatura seguono nella luce lineare di visualizzazione. Avvia rendering crea nuovi campioni di trasporto. La correzione colore usa il master grezzo conservato selezionato, senza riduzione del rumore né nuovi raggi.",
"render.post_reset": "Reimposta i filtri di presentazione",
"render.post_saturation": "Saturazione",
"render.post_title": "Filtri di presentazione",
"render.post_vignette": "Vignettatura",
"render.preview": "Anteprima integrata",
"render.preview_help": "Ombreggiatura raster e trasparenza miscelata. Rifrazione, HDRI e rendering finale non sono ancora disponibili.",
"render.preview_image_settings_help": "L'anteprima live mantiene un'illuminazione da studio fissa. L'esposizione e l'illuminazione dell'immagine si applicano al lavoro immagine quando scegli Verifica o Avvia.",
"render.preview_lighting_help": "L'anteprima live mostra solo la luce diretta e nessuna ombra.",
"render.preview_retry": "Riprova l'anteprima live",
"render.preview_unavailable_help": "L'anteprima live non è disponibile. Le impostazioni salvate e i controlli del lavoro immagine restano accessibili. Modifica la scena o riprova esplicitamente; una scena rifiutata non viene ricostruita a ogni fotogramma.",
"render.preview_upload": "Payload dei vertici dell'anteprima live",
"render.preview_upload_help": "Byte esatti dei vertici dell'anteprima, non la memoria totale di GPU o processo. La geometria non viene semplificata. I lavori immagine usano una propria ammissione e una propria illuminazione.",
"render.progressive_image_summary": "PNG di anteprima · PBR e vetro · campioni progressivi",
"render.property_conditions": "Condizioni: {value}",
"render.property_fallback": "proprietà",
"render.property_qualifier": "Qualificatore: {value}",
"render.property_source": "Fonte: {id} - {locator}",
"render.property_uncertainty": "Incertezza: {value}",
"render.property_unknown": "sconosciuto",
"render.quality_ack": "Conferma la proiezione a budget fisso e le omissioni",
"render.quality_apply": "Usa questo budget di campionamento fisso",
"render.quality_projection_help": "Le preimpostazioni Q includono requisiti futuri. Questa azione proietta solo un budget PNG a campioni fissi supportato e omette esplicitamente l'arresto adattivo, l'output lineare grezzo e i limiti di trasmissione indipendenti.",
"render.quality_review": "Esamina il budget di campionamento",
"render.queue_pending": "In questa interfaccia non esiste una coda di produzione automatica né un renderer di animazioni. Le immagini fisse completate restano esportabili separatamente.",
"render.radial_distortion": "Distorsione radiale",
"render.regrade_action": "Correggi il colore del master grezzo (senza riduzione del rumore)",
"render.regrade_help": "Crea un PNG separato dal master grezzo completato selezionato, usando questi controlli di presentazione. Non traccia raggi, non modifica dimensioni, camera o luci acquisite e non sovrascrive l'EXR. La riduzione del rumore non viene riapplicata: i master grezzi non conservano le sue guide. Il derivato resta esportabile con gli stessi controlli del lavoro.",
"render.regrade_label": "Correzione colore",
"render.reload_settings": "Ricarica impostazioni salvate",
"render.replace_ground": "Conferma la sostituzione della scenografia esistente",
"render.replace_label": "Sostituisci",
"render.replace_saved_surface": "Sostituisci un'associazione salvata esistente per questa destinazione",
"render.restore_camera": "Ripristina camera salvata",
"render.result_actual_help": "Un pixel dell'immagine per ogni pixel dello schermo.",
"render.result_actual_size": "100%",
"render.result_capture": "Revisione acquisita",
"render.result_current": "La revisione del modello acquisita è attuale.",
"render.result_empty": "Nessuna immagine completata. Verifica le impostazioni, poi avvia un rendering.",
"render.result_fit": "Adatta immagine",
"render.result_job": "Lavoro",
"render.result_navigation": "Panoramica e zoom usano le preferenze di Navigazione. Space + trascinamento esegue la panoramica.",
"render.result_open": "Apri l'immagine completata nella vista principale.",
"render.result_preview": "Anteprima live",
"render.result_provisional": "Immagine CPU provvisoria",
"render.result_provisional_help": "Questo punto di ripristino non è esportabile. L'esportazione mantiene l'ultimo risultato completato; l'annullamento torna a quel risultato.",
"render.result_reduced_display": "Anteprima ridotta al limite di dispositivo/cache della vista. Il PNG conservato e l'esportazione mantengono la risoluzione piena; l'ispezione nativa al 100% non è disponibile per questa vista ridotta.",
"render.result_retained": "Viene mostrata l'ultima immagine completata; un rendering più recente non l'ha ancora sostituita.",
"render.result_sequence": "Punto di ripristino",
"render.result_title": "Risultato del rendering",
"render.return_design": "Torna a Progettazione",
"render.review_stale": "Questa revisione è obsoleta. Risolvi o verifica di nuovo prima di applicare.",
"render.ribbon_aging": "Invecchiamento",
"render.ribbon_backgrounds": "Sfondi",
"render.ribbon_check": "Verifica",
"render.ribbon_check_help": "Convalida l'esatta bozza attuale che il rendering invierà. Nessun ripiego su un altro motore di rendering, nessun ridimensionamento silenzioso né sostituzione di risorse.",
"render.ribbon_edit_lights": "Modifica luci",
"render.ribbon_effects": "Effetti",
"render.ribbon_environment_help": "L'illuminazione HDR, gli sfondi visibili solo alla camera e le superfici fisiche del set sono controlli separati, con consenso esplicito per la sostituzione.",
"render.ribbon_finish_dialog": "Termina prima il file o la finestra di conferma corrente.",
"render.ribbon_frame": "Inquadra",
"render.ribbon_hdr_library": "Libreria HDR",
"render.ribbon_job_active": "Un rendering è già in corso; annullalo esplicitamente prima di avviarne un altro.",
"render.ribbon_light_rigs": "Rig di luci",
"render.ribbon_lights_help": "Esamina i rig predisposti o modifica le luci supportate senza sostituire l'impostazione attuale finché non applichi esplicitamente la modifica.",
"render.ribbon_materials": "Materiali",
"render.ribbon_materials_help": "Apri l'ispettore degli aspetti condiviso e la libreria originale di superfici. Le modifiche ottiche non cambiano mai in silenzio le proprietà ingegneristiche.",
"render.ribbon_no_active_job": "Nessun rendering attivo da annullare.",
"render.ribbon_no_result": "Completa un rendering prima di esportarne l'immagine esatta.",
"render.ribbon_no_saved_camera": "Salva un'inquadratura prima di ripristinarne la camera.",
"render.ribbon_saved_camera": "Camera salvata",
"render.ribbon_shots": "Inquadrature",
"render.ribbon_studios": "Studi",
"render.ribbon_studios_help": "Sfoglia le composizioni di studio implementate e verifica le sostituzioni prima di applicarle. Le scene solo concettuali restano contrassegnate.",
"render.ribbon_surface_maps": "Mappe di superficie",
"render.sampling_title": "Campionamento adattivo e di trasmissione",
"render.save_continue": "Salva e continua",
"render.save_setup": "Salva impostazione",
"render.save_shot": "Salva inquadratura",
"render.saved_maps_runtime_conflict": "Le associazioni di superficie salvate non possono essere combinate con override ottici temporanei o con un HDR non salvato. Salva l'HDR o rimuovi esplicitamente gli input temporanei.",
"render.saved_surface_remove": "Rimuovi l'associazione salvata",
"render.saved_surfaces": "Associazioni di superficie salvate",
"render.saved_surfaces_help": "Le mappe integrate fissate seguono l'occorrenza selezionata in millimetri locali. Una destinazione sostituita o mancante è un errore, mai una riassegnazione automatica.",
"render.scene_apply": "Applica lo studio esaminato",
"render.scene_consent": "Conferma la sostituzione di illuminazione, ambiente, esposizione e scenografia",
"render.scene_preserved_fields": "Camera, campionamento, dimensioni, associazioni ottiche, geometria CAD e materiali ingegneristici vengono conservati.",
"render.scene_preserves_design": "Compone l'illuminazione e un set passivo per il soggetto visibile. Geometria, materiali ingegneristici e camera restano separati.",
"render.scene_replaces": "Sostituisce",
"render.scene_review": "Risolvi ed esamina",
"render.scene_review_help": "Esamina la composizione nativa completa prima di applicarla. Le specifiche SCENE avanzate non associate non vengono sostituite.",
"render.scene_scope_details": "Ambito della composizione",
"render.setup_legacy_environment": "Questa impostazione precedente usa la rotazione o l'intensità dell'ambiente nel formato obsoleto. Questi valori vengono conservati; convertili esplicitamente prima di salvare un lavoro immagine completo.",
"render.setup_name": "Nome dell'impostazione",
"render.setup_numeric_help": "Salva registra il metodo immagine attivo e tutte le sue impostazioni numeriche. Ricaricare o scegliere un'altra impostazione sostituisce questa bozza; ripristina la camera separatamente.",
"render.setup_offline_help": "Puoi modificare e salvare questo metodo senza il suo motore di rendering. Verifica e Avvia richiedono un host disponibile.",
"render.setup_runtime_unsupported": "Questo lavoro completo non può ancora essere salvato: contiene mappe o associazioni ai corpi della scena. Rimuovi questi input temporanei prima di salvare un'impostazione portabile.",
"render.setup_save_missing": "Impossibile trovare la configurazione di rendering salvata dopo il completamento del comando.",
"render.sharpening": "Nitidezza dei dettagli",
"render.shell_tab_appearance": "ASPETTO RENDERING",
"render.shell_tab_camera": "CAMERA RENDERING",
"render.shell_tab_scene": "SCENA RENDERING",
"render.shot_duplicate": "Duplica l'inquadratura salvata",
"render.shot_manager": "Inquadrature salvate",
"render.shot_new_name": "Nome della nuova inquadratura",
"render.shot_remove": "Rimuovi l'inquadratura salvata",
"render.shot_remove_help": "Rimuove solo questa impostazione salvata. La geometria di origine e le immagini completate vengono conservate; l'azione può essere annullata.",
"render.shot_remove_title": "Rimuovere l'inquadratura salvata?",
"render.shot_rename": "Rinomina l'inquadratura salvata",
"render.shot_saved_only": "Salva prima la bozza attuale. Duplica e Rinomina conservano esattamente le opzioni salvate e i riferimenti alle risorse.",
"render.show_shots_label": "Mostra la barra delle inquadrature",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Suolo · RGB lineare",
"render.sky_horizon": "Orizzonte · RGB lineare",
"render.sky_zenith": "Zenit · RGB lineare",
"render.soft_focus": "Messa a fuoco morbida",
"render.spot_cone": "Cono dello spot",
"render.stage_frame": "Fotogramma",
"render.stage_light": "Luce",
"render.stage_look": "Aspetto",
"render.stage_orthographic": "Ortografica",
"render.stage_output": "Uscita",
"render.stage_panel_count": "Pannelli salvati",
"render.stage_preview_note": "Anteprima integrata · luce diretta",
"render.strip_label": "Barra",
"render.studio_add_area": "Aggiungi luce ad area",
"render.studio_ambient": "Radianza costante dell'ambiente",
"render.studio_ambient_rgb": "Radianza costante dell'ambiente (RGB lineare)",
"render.studio_aperture": "Raggio dell'apertura",
"render.studio_area": "Luce ad area",
"render.studio_area_help": "Fino a quattro rettangoli a una sola faccia. I semilati ortogonali U e V definiscono le dimensioni; U × V è rivolto verso il lato illuminato. Le coordinate sono in millimetri globali.",
"render.studio_center": "Centro X, Y, Z (mm)",
"render.studio_denoise": "Riduci il rumore nell'immagine finale",
"render.studio_denoise_help": "Filtro finale che preserva i bordi; i dettagli fini possono perdere nitidezza. Il vetro e le superfici speculari nitide escludono il filtro.",
"render.studio_direction": "Direzione verso il sole (X, Y, Z)",
"render.studio_environment": "Ambiente",
"render.studio_environment_bounds": "La rotazione dell'ambiente deve essere finita entro ±1,000,000 radianti e l'intensità compresa tra 0 e 100.",
"render.studio_environment_none": "Nessuna mappa dell'ambiente",
"render.studio_focus": "Distanza di messa a fuoco assiale",
"render.studio_half_u": "Semilato U (mm)",
"render.studio_half_v": "Semilato V (mm)",
"render.studio_hdr": "File HDR Radiance",
"render.studio_hdr_browse": "Scegli HDR…",
"render.studio_hdr_help": "Radiance .hdr, panorama 2:1, fino a 2048 × 1024. EXR non è disponibile. L'ipotesi sul colore si applica solo quando i primari non sono specificati.",
"render.studio_hdr_required": "Scegli un file .hdr locale.",
"render.studio_hdr_srgb": "Interpreta i primari non specificati come sRGB lineare",
"render.studio_intensity": "Intensità dell'ambiente",
"render.studio_lens": "Profondità di campo",
"render.studio_lens_perspective": "La profondità di campo richiede una camera prospettica.",
"render.studio_lighting": "Illuminazione dello studio",
"render.studio_lighting_enable": "Usa l'illuminazione personalizzata dello studio",
"render.studio_needs_review": "Verifica metodo e impostazioni",
"render.studio_radiance": "Radianza RGB lineare",
"render.studio_ready": "Pronto per la verifica",
"render.studio_remove_area": "Rimuovi luce ad area",
"render.studio_rotation": "Rotazione dell'ambiente",
"render.studio_runtime_help": "Le impostazioni numeriche dello studio e le sorgenti HDR verificate possono essere salvate con l'impostazione. Le sostituzioni ottiche e di materiale dei corpi restano temporanee e non modificano gli aspetti salvati.",
"render.studio_saved": "Impostazione salvata / camera corrente",
"render.studio_sky": "Cielo artistico",
"render.studio_sky_help": "Gradiente di cielo originale per l'illuminazione; non è un modello atmosferico calibrato.",
"render.studio_sun": "Sole",
"render.studio_sun_radius": "Raggio angolare",
"render.studio_title": "Studio di rendering",
"render.studio_tone_map": "Mappatura tonale",
"render.subsurface_enable": "Random walk di diffusione interna",
"render.subsurface_help": "Solo dielettrici chiusi. Lo scattering e l'assorbimento RGB sono coefficienti separati per mm. I percorsi si diffondono all'interno della geometria effettiva, poi si rifrangono o si riflettono sul contorno. Richiede di disattivare la trasmissione diretta delle ombre, la riduzione del rumore sulle superfici e il volume esterno, e di usare uno strato di Fresnel. Non è uno shader a diffusione, una griglia di densità né un materiale misurato. I mezzi densi possono richiedere più campioni e una maggiore profondità dei percorsi.",
"render.subsurface_rate": "Frequenza di collisione dello scattering",
"render.tone_aces_fitted": "ACES fitted",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "Il vetro su GPU supporta mezzi disgiunti certificati. I mezzi annidati senza restrizioni e uno stimatore della trasmissione privo di rumore non sono disponibili.",
"render.transmission_strata": "Strati di Fresnel condizionali",
"render.transmission_strata_help": "1 mantiene il flusso originale. 2 o 4 sottopercorsi stratificano la prima scelta tra riflessione e trasmissione nel vetro, con leggi di Snell e di assorbimento invariate. Più percorsi richiedono più lavoro; non è una riduzione del rumore, un supporto ai mezzi annidati né una promessa di rendering più rapido.",
"render.tree_add_light": "Aggiungi luce",
"render.tree_add_shot": "Aggiungi inquadratura",
"render.tree_browser": "Struttura del rendering",
"render.tree_by_look": "Per aspetto",
"render.tree_by_object": "Per oggetto",
"render.tree_constant": "Ambiente costante",
"render.tree_default": "Predefinito",
"render.tree_directional": "Direzionale",
"render.tree_environment": "Ambiente",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} facce",
"render.tree_face_one": "{count} faccia",
"render.tree_fixed_studio": "Studio fisso",
"render.tree_hdr": "HDR",
"render.tree_lights": "Luci",
"render.tree_lights_pending": "I comandi per le luci con nome non sono ancora disponibili.",
"render.tree_mixed": "Misto",
"render.tree_more": "altri {count}",
"render.tree_mute": "Silenzia luce",
"render.tree_no_environment": "Nessun ambiente",
"render.tree_objects": "Oggetti",
"render.tree_output": "Uscita",
"render.tree_point": "Puntiforme",
"render.tree_rectangle": "Rettangolare",
"render.tree_search": "Cerca oggetti",
"render.tree_selection": "Selezione di rendering",
"render.tree_shots": "Inquadrature",
"render.tree_sky": "Cielo",
"render.tree_solo": "Isola luce",
"render.tree_spot": "Spot",
"render.tree_sun": "Sole",
"render.tree_switch": "Commuta",
"render.tree_user_one": "{count} oggetto",
"render.tree_users": "{count} oggetti",
"render.unavailable_preview": "Questa impostazione richiede un profilo di anteprima non disponibile.",
"render.unsaved": "Modifiche all'anteprima non salvate",
"render.use_preview": "Usa anteprima integrata",
"render.volume_albedo": "Albedo di scattering · RGB lineare",
"render.volume_anisotropy": "Coseno medio di fase",
"render.volume_enable": "Abilita mezzo partecipante",
"render.volume_extinction": "Coefficiente di estinzione",
"render.volume_help": "Trasporto su GPU all'interno di un unico parallelepipedo finito, con attenuazione di Beer e scattering HG sui percorsi della camera e su quelli indiretti. Usa un'illuminazione esplicita di studio, HDR o cielo, compresa l'attenuazione delle ombre. Un coseno di fase positivo diffonde in avanti. I contorni di vetro e la riduzione del rumore sulle superfici devono essere disattivati esplicitamente. Un'estinzione pari a zero lascia invariato il trasporto. Non è un'atmosfera lunare fisica, una griglia di densità, un'emissione volumetrica, un trasporto spettrale né una proprietà di materiale certificata.",
"render.volume_max": "Limiti massimi · mm globali",
"render.volume_min": "Limiti minimi · mm globali",
"render.volume_title": "Volume omogeneo delimitato",
"render.wait_batch": "non ancora supportato: la coda di rendering delle inquadrature salvate",
"render.wait_compare": "non ancora supportato: il confronto delle immagini conservate",
"render.wait_paint": "non ancora supportato: la selezione del prodotto e l'applicazione degli aspetti con il pennello",
"render.wait_pick_up": "non ancora supportato: la selezione del prodotto e il prelievo degli aspetti",
"render.wait_replace": "non ancora supportato: la sostituzione di tutti gli usi di un aspetto",
"render.wait_solo": "non ancora supportato: la visibilità delle luci e i controlli di isolamento",
"sample.bracket.about": "Flangia di base con flange sui bordi e un orlo, con una regola da 2 mm",
"sample.bracket.name": "Staffa in lamiera",
"sample.enclosure.about": "Scatola svuotata con labbro, risalti per viti, appoggio e aggancio a scatto",
+88
View File
@@ -38,6 +38,7 @@
"All open designs": "すべての開いているデザイン",
"Allowed expressions, separated by semicolons": "使用可能な式(セミコロンで区切る)",
"Also deletes": "同時に削除される要素:",
"Also place them from the origin (fully constrained)": "原点からの位置も付ける(完全拘束)",
"Anchor": "基準点",
"Angle 2": "角度 2",
"Angle Display": "角度の表示",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "開いたデザインや保存したデザインがここに表示されます。",
"Determined by To Object. Choose Angle to edit the angular extent.": "「対象オブジェクトまで」により決定されます。角度範囲を編集するには「角度」を選択してください。",
"Diameter": "直径",
"Dimension new shapes": "新しい図形に寸法を付ける",
"Direction": "方向",
"Discard": "破棄",
"Distance": "距離",
@@ -196,6 +198,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "ドラッグしてレストを 5° 刻みで回転します。Alt または Ctrl を押したままにすると自由に回転します。",
"Drive Joint": "ジョイントを駆動",
"Duration": "時間",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "新しい図形には、自由な部分がなくなるまでスケッチの原点からの寸法も付きます。原点や配置済みの形状にすでにつながっている図形には付きません。",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "描いた図形に、描いたサイズですべての寸法が付きます(入力した値が優先されます)。スケッチですでに決まっているサイズは省かれます。",
"Edge": "エッジ",
"Edges": "エッジ",
"Edit": "編集",
@@ -254,6 +258,8 @@
"Flanges": "フランジ",
"Flat Pattern": "フラットパターン",
"Flat size": "展開サイズ",
"Flat size X": "展開サイズ X",
"Flat size Y": "展開サイズ Y",
"Follow camera (Look At sketches)": "カメラ追従(スケッチを正面視)",
"Follow the camera (Look At sketches)": "カメラ追従(スケッチを正面視)",
"Font": "フォント",
@@ -812,7 +818,9 @@
"cmd.component_create": "新規コンポーネント",
"cmd.component_cycle_color": "コンポーネントの色を順に変更",
"cmd.component_delete": "コンポーネントを削除",
"cmd.component_edit_in_place": "その場で編集",
"cmd.component_extract": "ファイルに抽出",
"cmd.component_finish_edit": "編集を終了",
"cmd.component_from_bodies": "ボディからコンポーネントを作成",
"cmd.component_insert_design": "デザインを挿入",
"cmd.component_links": "リンクを一覧表示",
@@ -1171,6 +1179,7 @@
"cmd.view.render_dock": "レンダードックを移動",
"cmd.view.render_focus": "Renderフォーカス表示",
"cmd.view_ambient_occlusion": "アンビエントオクルージョン",
"cmd.view_angle_readout": "ビュー角度",
"cmd.view_apply": "名前付きビューを復元",
"cmd.view_back": "背面ビュー",
"cmd.view_bottom": "下面ビュー",
@@ -1305,6 +1314,7 @@
"help.appearance.assign": "選択した立体、面、コンポーネントに、重さを変えずに色や材質の見た目を付けます。部品を見分けるときや仕上げを確認するときに使います。",
"help.attributions": "帰属表示 (ATTRIBUTION.md)",
"help.build": "バージョン {version} · コミット {commit} · ビルド日 {date}",
"help.component.finish_edit": "その場で編集中の部品を保存し、アセンブリに戻って、その部品でアセンブリを更新します。リンクされた部品への変更が終わったときに使います。",
"help.connect_note": "各アシスタントを再起動すると SolidCraft サーバーが読み込まれます。変更したファイルは .bak としてバックアップされています。",
"help.connect_title": "AI アシスタントを接続",
"help.face.delete": "選択した面を削除し、隣の面でその穴をふさぎます。穴を開いたまま面として残すこともできます。じゃまな丸み、穴、突起を取り除くときに使います。",
@@ -1782,8 +1792,12 @@
"prefs.layout_note": "コンパクトではパネルをウィンドウの端に固定します。ブラウザーの半透明表示はフローティングで使用できます。アシスタントの配置はアシスタントページで変更します。",
"prefs.left": "左",
"prefs.left_click": "左クリック",
"prefs.linked_designs": "リンクされたデザイン",
"prefs.live_input": "現在の入力",
"prefs.live_preview": "ライブプレビュー",
"prefs.logo": "ロゴ",
"prefs.logo_accent": "アクセント",
"prefs.logo_theme": "テーマの色",
"prefs.minutes": "分",
"prefs.minutes_suffix": " min",
"prefs.mouse": "マウスとトラックパッド",
@@ -1832,6 +1846,10 @@
"prefs.sketch_selection": "スケッチと選択",
"prefs.sketch_selection_heading": "スケッチと選択",
"prefs.sketch_selection_note": "スケッチのスナップとクリックによる選択。",
"prefs.sketch_tab_always": "スケッチ タブを常に表示",
"prefs.sketch_tab_always_note": "スケッチを開いていないときも、スケッチ タブをリボンのモデルのすぐ後に表示します。そこにある作図ツールは、選択した平面または面に、なければ次に選ぶ平面にスケッチを開始し、そのスケッチでツールをすぐ使える状態にします。",
"prefs.sketch_tracking_guides": "中心・中点の整列ガイド",
"prefs.sketch_tracking_guides_note": "円の中心や直線辺の中点にカーソルを合わせ、水平・垂直に移動すると一時的な点線ガイドを表示します。",
"prefs.sketching": "スケッチ",
"prefs.snap_drawing_note": "スケッチの描画中または点のドラッグ中に使用します。",
"prefs.source": "入力元",
@@ -1844,12 +1862,16 @@
"prefs.supersampling_brief": "大きく描画して縮小するため、非常に鮮明になりますが負荷も増えます。",
"prefs.tab_accent_note": "アクセント色はアクティブなタブに従います",
"prefs.theme_file": "テーマファイル",
"prefs.theme_file_or_paste": "ファイルまたは貼り付け",
"prefs.theme_follow": "テーマファイルに従う",
"prefs.theme_follow_error": "適用できません: {error}。最後に正常に適用されたテーマを維持します。",
"prefs.theme_follow_launch": "今回の起動時のみ有効です (--theme-file)。別のツールがファイルを書き換えるたびに再読み込みします。",
"prefs.theme_follow_note": "別のツールがファイルを書き換えるたびに再読み込みします。テーマを選ぶと追従を停止します。",
"prefs.theme_follow_off": "オフ",
"prefs.theme_follow_stop": "追従を停止",
"prefs.theme_import_hint": "クリックしてテーマファイルを選ぶか、ここにドロップするか、テーマをコピーした状態で Ctrl+V(Mac では Cmd+V)を押します",
"prefs.theme_paste": "テーマを貼り付け",
"prefs.theme_paste_none": "クリップボードに SolidCraft のテーマがありません",
"prefs.timeline_half_hour": "−30 分",
"prefs.timeline_now": "現在",
"prefs.timeline_quarter_hour": "−15",
@@ -1916,6 +1938,7 @@
"render.all_controls_help": "現在の全コントロールをまとめて表示します。各ページでは同じ要求を保ちながら項目別に編集できます。",
"render.all_shots_label": "すべてのショット",
"render.appearance_physics_separate": "外観の設定では、密度、熱特性などの工学的な物性値は割り当てられません。",
"render.appearances": "外観",
"render.availability_native": "ネイティブ構成。適用前に確認してください",
"render.availability_projection": "対応する部分適用。範囲と省略項目を確認してください",
"render.availability_reference": "参照データ。自動割り当てではありません",
@@ -1970,6 +1993,10 @@
"render.camera_set": "レンダーカメラを設定",
"render.camera_target": "ターゲット位置・mm",
"render.camera_yaw": "ヨー",
"render.category_metal": "金属",
"render.category_paint": "塗装",
"render.category_plastic": "プラスチック",
"render.category_wood": "木材",
"render.chromatic_offset": "色収差のずれ",
"render.clear_stage": "Remove saved stage",
"render.copy_request": "JSONをコピー",
@@ -2069,6 +2096,7 @@
"render.effects_reset_lens": "レンズ効果をリセット",
"render.effects_seed": "パターンシード",
"render.emitted_axis": "照射軸",
"render.environment_tiles_require_raytrace": "環境には CPU または GPU レイトレーシングが必要です。出力エディターで選択してください。",
"render.error_area_samples": "area_samplesは1、4、16、64のいずれかです",
"render.error_binding_allocation": "マテリアルの割り当て領域を確保できません",
"render.error_body_bound": "製品プレビューが取得ボディ数の上限を超えています",
@@ -2140,6 +2168,8 @@
"render.flare_strength": "ハイライトフレア強度",
"render.flare_threshold": "シーンリニアしきい値",
"render.fold_browser": "ブラウザーを折りたたむ",
"render.frame_presets": "構図プリセット",
"render.frame_presets_pending": "ショットエディターとともに追加予定",
"render.gpu_depth": "最大パス深度",
"render.gpu_options_help": "サンプル数、深度、シード、露出をこの設定に保存します。保存するのは選択中の画像方式だけです。",
"render.gpu_path_failed": "GPUパストレーサーを利用できません",
@@ -2211,8 +2241,12 @@
"render.lens_effects_title": "レンズ風・写真効果",
"render.library_all": "カタログ",
"render.library_all_states": "すべての利用可能状態",
"render.library_appearance_available": "利用可能な外観",
"render.library_applicable": "適用に適したリソース",
"render.library_applied": "リソース変換を適用しました。開始前にレンダリング要求全体を確認してください。",
"render.library_apply_appearance": "外観を適用",
"render.library_apply_hdr": "このHDR環境と一緒に保存",
"render.library_apply_hint": "クリックで適用 · モデルにドラッグ",
"render.library_apply_maps": "作成済みGPUサーフェスマップを使用",
"render.library_apply_studio": "作成済みスタジオ変換を保存",
"render.library_apply_uniform": "均一な不透明外観を適用",
@@ -2228,15 +2262,23 @@
"render.library_extent": "対象の大きさ",
"render.library_favorite": "お気に入りに追加",
"render.library_favorites": "お気に入り",
"render.library_filters": "カタログと利用状況",
"render.library_grid": "グリッド",
"render.library_hdr": "組み込みHDR環境",
"render.library_hdr_help": "元のHDRを保存設定に埋め込みます。作成時の経度原点を明示的に変換します。保存後は外部ファイルが不要です。",
"render.library_in_design": "デザイン内",
"render.library_inspect_only": "選択すると詳細を確認できます。自動適用はされません。お気に入りと履歴は、この開いている文書のセッションに属します。",
"render.library_ior": "屈折率",
"render.library_light_concepts": "照明構想",
"render.library_list": "リスト",
"render.library_maps_help": "Built-in maps can be saved with pinned sources and local occurrence mapping. Temporary optical overrides remain a separate mode.",
"render.library_material_concepts": "マテリアル構想",
"render.library_metallic": "金属度",
"render.library_native_scenes": "ネイティブスタジオ",
"render.library_next": "次のページ",
"render.library_omitted": "含まれない項目",
"render.library_opacity": "不透明度",
"render.library_other": "その他の外観",
"render.library_physical_profiles": "Physical reference profiles",
"render.library_previous": "前のページ",
"render.library_quality_concepts": "品質仕様",
@@ -2246,6 +2288,7 @@
"render.library_results": "一致するリソース",
"render.library_rig_help": "Fit once at an explicit center and physical extent. Complete rigs include passive cards; calibration blockers still refuse. Conservative emitter/card clearance is checked before saving.",
"render.library_rigs": "作成済み照明リグ",
"render.library_roughness": "粗さ",
"render.library_save_maps": "Save maps to this setup",
"render.library_scene_bounds": "取得したシーン境界を使用",
"render.library_scenes": "シーン仕様",
@@ -2269,6 +2312,7 @@
"render.library_unfavorite": "お気に入りから削除",
"render.library_uniform_ack": "空間変化や高度な効果のない均一近似を使用",
"render.library_usable": "実行可能な部分適用",
"render.library_users": "使用箇所",
"render.light_anchor_pending": "ライトの座標系の変更はまだサポートされていません。",
"render.lights_fixed_to": "ライトの固定先",
"render.linear_help": "ノイズ除去、露出、トーンマッピング、フィルター、背景処理より前の32ビット浮動小数点RGBAを保持します。線形sRGB/D65で、被覆率を乗算した値です。追加メモリを明示的に見積もります。圧縮や追加パスはありません。",
@@ -2487,6 +2531,7 @@
"render.scene_review": "解決して確認",
"render.scene_review_help": "適用前にネイティブ構成の全体を確認してください。未接続の高度なSCENE仕様への暗黙の置換はありません。",
"render.scene_scope_details": "構成の範囲",
"render.search_appearances": "{count} 件の外観を検索",
"render.setup_legacy_environment": "この旧設定には従来の環境回転または強度が含まれています。値は保持されます。画像ジョブ全体を保存する前に明示的に変換してください。",
"render.setup_name": "セットアップ名",
"render.setup_numeric_help": "保存すると、選択中の画像方式とその数値設定をすべて保存します。再読み込みや別の設定の選択で下書きを置き換えます。カメラは別途復元します。",
@@ -2505,10 +2550,19 @@
"render.shot_remove_title": "保存済みショットを削除しますか?",
"render.shot_rename": "保存済みショットの名前を変更",
"render.shot_saved_only": "先に現在の下書きを保存してください。複製と名前変更では正確な保存オプションとリソース参照を保持します。",
"render.shots_camera_changed": "このショットの保存後にカメラが変更されました",
"render.shots_name_help": "現在のショットに一意の名前を入力してください。",
"render.shots_no_result": "レンダリング結果なし",
"render.shots_result": "レンダー {number} · {width} × {height}",
"render.shots_revert": "元に戻す",
"render.shots_save": "ショットを保存",
"render.shots_update": "ショットを更新",
"render.show_shots_label": "ショットストリップを表示",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "フルHD",
"render.size_hd": "HD",
"render.size_presets": "サイズプリセット",
"render.size_presets_pending": "出力エディターとともに追加予定",
"render.sky_ground": "地面・線形RGB",
"render.sky_horizon": "地平線・線形RGB",
"render.sky_zenith": "天頂・線形RGB",
@@ -2559,8 +2613,10 @@
"render.studio_sky_help": "照明用のオリジナル空グラデーションです。校正された大気モデルではありません。",
"render.studio_sun": "太陽",
"render.studio_sun_radius": "角半径",
"render.studio_tiles_require_gpu": "スタジオには GPU パストレーシングが必要です。出力エディターで GPU を選択してください。",
"render.studio_title": "レンダースタジオ",
"render.studio_tone_map": "トーンマッピング",
"render.studios_environments": "スタジオと環境",
"render.subsurface_enable": "内部散乱ランダムウォーク",
"render.subsurface_help": "閉じた誘電体専用。散乱とRGB吸収は別々の毎mm係数です。実際の形状内で散乱し、境界で屈折・反射します。直線透過影、表面ノイズ除去、外部ボリュームを無効にし、フレネル層数を1にします。拡散シェーダー、密度グリッド、実測物性ではありません。高密度ではサンプル数と深度が必要です。",
"render.subsurface_rate": "散乱衝突率",
@@ -2668,6 +2724,7 @@
"select two components": "2つのコンポーネントを選択してください",
"set by the sketch's lines": "スケッチの線で決まります",
"settings.display_quality_note": "表示だけに影響します。設計や書き出しは変わりません。",
"settings.double_click_components": "コンポーネントをダブルクリックしてアクティブにする、またはリンクされたものをその場で編集する",
"settings.frame_rate_details_note": "直近のフレーム時間のグラフ(描画した三角形数を重ねて表示)、フレーム時間のヒストグラム、GPU が描画した内容を追加します。ビューのフレームレートをクリックすると表示/非表示を切り替えます。",
"settings.frame_rate_note": "ビューの右下に 1 秒あたりのフレーム数を表示します。",
"settings.measure_axis_distances": "計測のX・Y・Z距離を表示",
@@ -2680,6 +2737,7 @@
"settings.reset_intro": "次の設定はこのコンピューターでは使用できず、SolidCraft が起動できなくなるため変更されました:",
"settings.reset_title": "設定が変更されました",
"settings.supersampling_note": "ビューを高い解像度で描画してから縮小します。4K 未満の画面でエッジ、線、グリッドが滑らかになります。GPU の負荷が増えます(1.5× で約 2.25 倍、2× で 4 倍のピクセル)。",
"settings.update_changed_links": "タブに戻ったときに変更されたリンク先デザインを更新",
"settings.window_system_details": "詳細",
"settings.window_system_note_now": "再起動後に適用されます。現在: {now}。",
"settings.window_system_wayland_limited": "ネイティブ Wayland では一部の機能が制限されます。",
@@ -3283,6 +3341,24 @@
"ui.easyprint_uploading": "Printables にアップロード中…",
"ui.edit": "編集",
"ui.editJointLimits": "ジョイント制限を編集",
"ui.edit_in_place": "その場で編集",
"ui.edit_in_place_after_turn": "エージェントのターンが終わると編集を終了します",
"ui.edit_in_place_agent_busy": "エージェントがまだこのデザインで作業中です。そのターンが終わってから再度お試しください",
"ui.edit_in_place_already_queued": "エージェントのターンの終了を待っている編集がすでにあります",
"ui.edit_in_place_assembly_closed": "{name} はもう開いていません",
"ui.edit_in_place_banner": "{name} 内で編集中",
"ui.edit_in_place_busy": "先に開いているものを終了またはキャンセルしてください",
"ui.edit_in_place_none": "その場で編集中のリンクされたデザインはありません",
"ui.edit_in_place_not_saved": "部品に保存されていない変更があります。編集を終了するには保存してください",
"ui.edit_in_place_open_elsewhere": "{name} は別の SolidCraft で開かれています",
"ui.edit_in_place_opens_after_turn": "エージェントのターンが終わると部品が開きます",
"ui.edit_in_place_refresh_dropped": "リンクの更新中にアセンブリが変更されました。もう一度実行してください",
"ui.edit_in_place_refresh_stopped": "リンクの更新が完了前に停止しました",
"ui.edit_in_place_refreshing": "{name} のリンクを更新中…",
"ui.edit_in_place_save_first": "先にアセンブリを保存してください。リンクされたデザインはそのファイルから見つけます",
"ui.edit_in_place_save_waits": "{name} のリンクを更新中です。完了してから保存してください",
"ui.edit_in_place_saved_elsewhere": "部品は別のファイルに保存されました。アセンブリは引き続き {name} にリンクしています",
"ui.edit_in_place_wait": "デザインで実行中の処理が終わるまでお待ちください",
"ui.edit_section_analysis": "断面解析を編集",
"ui.ellipse": "楕円",
"ui.emboss_wrap_note": "サポートされる円柱に接する直交線のプロファイルは自動的に巻き付けられます。対象を選ぶには壁を選択してください。",
@@ -3357,6 +3433,7 @@
"ui.heading_edit": "編集",
"ui.heading_extrude": "押し出し",
"ui.heading_fillet": "フィレット",
"ui.heading_finish_editing": "編集を終了",
"ui.heading_finish_sketch": "スケッチを終了",
"ui.heading_form": "フォーム",
"ui.heading_front": "正面",
@@ -3616,6 +3693,8 @@
"ui.restore_defaults": "初期値に戻す",
"ui.reverse_horizontal_pan_direction": "水平パンの方向を反転",
"ui.reverse_horizontal_pan_tip": "水平方向の2本指スクロールとサムホイールで、反対方向にパンします",
"ui.reverse_vertical_pan_direction": "垂直パンの方向を反転",
"ui.reverse_vertical_pan_tip": "垂直方向の2本指スクロールで、反対方向にパンします",
"ui.reverse_zoom_direction": "ズーム方向を反転",
"ui.revolutions": "巻き数",
"ui.revolve": "回転",
@@ -3761,6 +3840,15 @@
"ui.updateToCurrentView": "現在のビューに更新",
"ui.upload": "アップロード",
"ui.vertical_constraint": "垂直拘束",
"ui.view_angles": "ビュー角度",
"ui.view_angles_convention": "上方向の軸まわりの角度(度)。ヨー 0° が正面ビュー、90° が左、−90° が右、180° が背面です。ピッチ 90° が上面ビューです。ロールが正のとき、モデルは画面上で時計回りに回ります。",
"ui.view_angles_help": "方向ギズモの下に、ビューのピッチ、ヨー、ロール(度)と投影法を表示します。表示をクリックすると正確な角度を入力できます。",
"ui.view_angles_ortho": "平行投影",
"ui.view_angles_persp": "透視投影",
"ui.view_angles_pitch": "ピッチ",
"ui.view_angles_readout": "ピッチ {pitch} · ヨー {yaw} · ロール {roll}",
"ui.view_angles_roll": "ロール",
"ui.view_angles_yaw": "ヨー",
"ui.view_centre": "ビュー中心",
"ui.viewport_theme_follow": "テーマに従う",
"ui.visual_shaded_hidden_edges": "隠線付きシェーディング",
+78
View File
@@ -33,6 +33,7 @@
"All open designs": "열린 모든 디자인",
"Allowed expressions, separated by semicolons": "허용되는 식, 세미콜론으로 구분",
"Also deletes": "함께 삭제됨",
"Also place them from the origin (fully constrained)": "원점 기준 위치도 지정(완전 구속)",
"Angle 2": "각도 2",
"Animate": "애니메이션",
"App/system information and command settings are included. Review private details before sharing.": "앱/시스템 정보와 명령 설정이 포함됩니다. 공유하기 전에 개인 정보를 확인하세요.",
@@ -157,6 +158,7 @@
"Designs you open or save appear here.": "열거나 저장한 디자인이 여기에 표시됩니다.",
"Determined by To Object. Choose Angle to edit the angular extent.": "대상 객체까지로 결정됩니다. 각도 범위를 편집하려면 각도를 선택하세요.",
"Diameter": "지름",
"Dimension new shapes": "새 도형에 치수 지정",
"Direction": "방향",
"Discard": "버리기",
"Distance": "거리",
@@ -167,6 +169,8 @@
"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": "지속 시간",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "새 도형마다 자유로운 부분이 없어질 때까지 스케치 원점 기준 치수도 지정됩니다. 원점이나 배치된 형상에 이미 연결된 도형은 지정되지 않습니다.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "그린 도형마다 그린 크기로 모든 치수가 지정됩니다(입력한 값이 우선). 스케치에서 이미 정해진 크기는 생략됩니다.",
"Edge": "모서리",
"Edges": "모서리",
"Edit": "편집",
@@ -717,6 +721,8 @@
"cmd.component_capture_position": "위치 캡처",
"cmd.component_create": "새 구성 요소",
"cmd.component_delete": "구성 요소 삭제",
"cmd.component_edit_in_place": "제자리에서 편집",
"cmd.component_finish_edit": "편집 완료",
"cmd.component_from_bodies": "바디로 구성 요소 만들기",
"cmd.component_insert_design": "설계 삽입",
"cmd.component_links": "링크 목록",
@@ -1048,6 +1054,7 @@
"cmd.view.render_dock": "렌더 도크 이동",
"cmd.view.render_focus": "렌더 집중 보기",
"cmd.view_ambient_occlusion": "앰비언트 오클루전",
"cmd.view_angle_readout": "뷰 각도",
"cmd.view_apply": "이름 있는 보기 복원",
"cmd.view_delete": "이름 있는 보기 삭제",
"cmd.view_graphics_preset": "그래픽 프리셋",
@@ -1149,6 +1156,7 @@
"help.apache": "Apache 라이선스 2.0",
"help.attributions": "저작자 표시 (ATTRIBUTION.md)",
"help.build": "버전 {version} · 커밋 {commit} · 빌드 날짜 {date}",
"help.component.finish_edit": "제자리에서 편집 중인 부품을 저장하고 어셈블리로 돌아가 그 부품으로 어셈블리를 업데이트합니다. 연결된 부품의 변경을 마쳤을 때 사용하세요.",
"help.font_details": "인터페이스는 egui의 내장 글꼴을 사용합니다(Ubuntu Font Licence 및 MIT/Bitstream Vera 라이선스의 Ubuntu Light와 Hack, OFL 및 MIT의 Noto Emoji와 이모지 아이콘 글꼴). 스케치 텍스트는 Liberation Sans(SIL OFL 1.1)를 사용합니다. The Crafting Apps의 선택적 글꼴 팩 craft-fonts(BIZ UDPGothic, Shippori Mincho, BIZ UDMincho, Noto Sans CJK SC, Noto Sans Arabic; SIL OFL 1.1)는 SolidCraft 빌드에 포함되지 않습니다.",
"help.fonts": "글꼴",
"help.licences": "라이선스",
@@ -1550,6 +1558,10 @@
"prefs.sketch_selection": "스케치 및 선택",
"prefs.sketch_selection_heading": "스케치 및 선택",
"prefs.sketch_selection_note": "스케치가 스냅되는 방식과 클릭으로 선택하는 방식입니다.",
"prefs.sketch_tab_always": "스케치 탭 항상 표시",
"prefs.sketch_tab_always_note": "스케치가 열려 있지 않을 때도 스케치 탭이 리본에서 모델 바로 다음에 남아 있습니다. 그 그리기 도구는 선택한 평면이나 면, 또는 다음에 고르는 평면에서 스케치를 시작하고 그 안에서 도구를 바로 쓸 수 있게 합니다.",
"prefs.sketch_tracking_guides": "중심 및 중점 정렬 안내선",
"prefs.sketch_tracking_guides_note": "원 중심이나 직선 모서리의 중점에 마우스를 올린 다음 수평 또는 수직으로 이동하면 임시 점선 안내선이 표시됩니다.",
"prefs.sketching": "스케치",
"prefs.snap_drawing_note": "스케치 점을 그리거나 드래그하는 동안.",
"prefs.source": "소스",
@@ -1596,6 +1608,7 @@
"recovery.never_saved": "저장된 적 없음",
"render.add_ground": "Add fitted ground to setup",
"render.all_shots_label": "모든 샷",
"render.appearances": "외관",
"render.background": "장면 배경",
"render.bloom_enable": "표시 블룸",
"render.bloom_help": "양의 선형 하이라이트를 세 번의 정규화 필터로 확산하는 출력 전용 효과입니다. 반경은 출력 픽셀 단위이며 sRGB 전에 더합니다. 렌즈·볼륨·수렴 개선이 아니며 원본 EXR은 변하지 않습니다.",
@@ -1603,6 +1616,10 @@
"render.bloom_radius": "블룸 반경",
"render.bloom_strength": "블룸 강도",
"render.bloom_threshold": "선형 하이라이트 임계값",
"render.category_metal": "금속",
"render.category_paint": "페인트",
"render.category_plastic": "플라스틱",
"render.category_wood": "목재",
"render.clear_stage": "Remove saved stage",
"render.cpu_budget": "CPU 리소스 프로필",
"render.cpu_budget_bodies": "바디 수 상한",
@@ -1616,6 +1633,7 @@
"render.cpu_budget_triangles": "삼각형 수 상한",
"render.cpu_budget_workstation": "워크스테이션 (대규모 장면)",
"render.emitted_axis": "방출 축",
"render.environment_tiles_require_raytrace": "환경에는 CPU 또는 GPU 광선 추적이 필요합니다. 출력 편집기에서 선택하세요.",
"render.error_area_samples": "area_samples는 1, 4, 16 또는 64여야 함",
"render.error_binding_allocation": "재질 연결을 할당할 수 없음",
"render.error_body_bound": "제품 미리 보기가 캡처된 바디 한도를 초과함",
@@ -1679,6 +1697,8 @@
"render.fixed_camera": "카메라",
"render.fixed_world": "월드",
"render.fold_browser": "브라우저 접기",
"render.frame_presets": "구도 프리셋",
"render.frame_presets_pending": "샷 편집기와 함께 제공 예정",
"render.heading_batch": "일괄 처리",
"render.heading_frame": "프레임",
"render.heading_lens": "렌즈",
@@ -1711,8 +1731,12 @@
"render.inner_half_angle": "내부 반각",
"render.inspector": "속성 검사기",
"render.layer_off_suffix": " (꺼짐)",
"render.library_appearance_available": "사용 가능한 외관",
"render.library_applicable": "적용 가능한 리소스",
"render.library_applied": "리소스 변환을 적용했습니다. 시작 전에 전체 렌더 요청을 확인하세요.",
"render.library_apply_appearance": "외관 적용",
"render.library_apply_hdr": "이 HDR 환경과 함께 저장",
"render.library_apply_hint": "클릭하여 적용 · 모델로 드래그",
"render.library_apply_maps": "제작된 GPU 표면 맵 사용",
"render.library_apply_studio": "제작된 스튜디오 변환 저장",
"render.library_apply_uniform": "균일한 불투명 외관 적용",
@@ -1722,12 +1746,21 @@
"render.library_emitters_only_ack": "광원만 사용하고 명시된 수동 반사판은 생략",
"render.library_environment_concepts": "환경 구상",
"render.library_extent": "대상 크기",
"render.library_filters": "카탈로그 및 사용 가능 여부",
"render.library_grid": "격자",
"render.library_hdr": "내장 HDR 환경",
"render.library_hdr_help": "원본 HDR을 저장 설정에 포함합니다. 제작된 경도 원점을 명시적으로 변환하며 저장 후 외부 파일이 필요하지 않습니다.",
"render.library_in_design": "디자인 내",
"render.library_inspect_only": "선택하여 확인 · 검사기에서 적용",
"render.library_ior": "굴절률",
"render.library_light_concepts": "조명 구상",
"render.library_list": "목록",
"render.library_maps_help": "Built-in maps can be saved with pinned sources and local occurrence mapping. Temporary optical overrides remain a separate mode.",
"render.library_material_concepts": "재질 구상",
"render.library_metallic": "금속성",
"render.library_next": "다음 페이지",
"render.library_opacity": "불투명도",
"render.library_other": "기타 외관",
"render.library_physical_profiles": "Physical reference profiles",
"render.library_previous": "이전 페이지",
"render.library_quality_concepts": "품질 사양",
@@ -1736,6 +1769,7 @@
"render.library_results": "일치하는 리소스",
"render.library_rig_help": "Fit once at an explicit center and physical extent. Complete rigs include passive cards; calibration blockers still refuse. Conservative emitter/card clearance is checked before saving.",
"render.library_rigs": "제작된 조명 리그",
"render.library_roughness": "거칠기",
"render.library_save_maps": "Save maps to this setup",
"render.library_scene_bounds": "캡처된 장면 범위 사용",
"render.library_scenes": "장면 사양",
@@ -1746,6 +1780,7 @@
"render.library_target": "대상 바디",
"render.library_title": "렌더 리소스 라이브러리",
"render.library_uniform_ack": "공간 변화나 고급 효과 없는 균일 근사 사용",
"render.library_users": "사용 위치",
"render.light_anchor_pending": "조명 좌표계 변경은 아직 지원되지 않습니다.",
"render.lights_fixed_to": "조명 고정 기준",
"render.material_color_replace": "기본 맵으로 바디 색상 교체",
@@ -1823,14 +1858,24 @@
"render.saved_surface_remove": "Remove saved binding",
"render.saved_surfaces": "Saved surface bindings",
"render.saved_surfaces_help": "Pinned built-in maps follow the selected occurrence in local millimeters. A replaced or missing target is an error, never an automatic reassignment.",
"render.search_appearances": "외관 {count}개 검색",
"render.setup_name": "설정 이름",
"render.shell_tab_appearance": "모양",
"render.shell_tab_camera": "카메라",
"render.shell_tab_scene": "장면",
"render.shots_camera_changed": "이 샷을 저장한 후 카메라가 변경되었습니다",
"render.shots_name_help": "현재 샷의 고유한 이름을 입력하세요.",
"render.shots_no_result": "렌더링 결과 없음",
"render.shots_result": "렌더 {number} · {width} × {height}",
"render.shots_revert": "되돌리기",
"render.shots_save": "샷 저장",
"render.shots_update": "샷 업데이트",
"render.show_shots_label": "샷 스트립 표시",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "풀 HD",
"render.size_hd": "HD",
"render.size_presets": "크기 프리셋",
"render.size_presets_pending": "출력 편집기와 함께 제공 예정",
"render.spot_cone": "스폿 원뿔",
"render.stage_frame": "구도",
"render.stage_light": "조명",
@@ -1840,6 +1885,8 @@
"render.stage_panel_count": "Saved panels",
"render.stage_preview_note": "통합 미리 보기 · 직접광",
"render.strip_label": "스트립",
"render.studio_tiles_require_gpu": "스튜디오에는 GPU 경로 추적이 필요합니다. 출력 편집기에서 GPU를 선택하세요.",
"render.studios_environments": "스튜디오 및 환경",
"render.tone_aces_fitted": "ACES 근사",
"render.tone_reinhard": "Reinhard",
"render.tree_add_light": "조명 추가",
@@ -1931,6 +1978,7 @@
"select the sheet edge first": "판금 모서리를 먼저 선택하세요",
"select two components": "구성요소 두 개를 선택하세요",
"settings.display_quality_note": "세밀할수록 곡면과 모서리가 더 매끄럽게 표시되지만 메시 생성 시간이 늘어납니다. 뷰포트만 바뀌며 설계나 내보내기는 바뀌지 않습니다.",
"settings.double_click_components": "구성 요소를 두 번 클릭하여 활성화하거나 연결된 구성 요소를 제자리에서 편집",
"settings.frame_rate_note": "뷰의 오른쪽 아래에 초당 프레임 수를 표시합니다.",
"settings.measure_axis_distances": "X/Y/Z 거리 표시",
"settings.measure_axis_distances_help": "측정 대화상자가 열려 있는 동안 전체 거리와 함께 월드 축 방향 치수와 거리를 표시합니다.",
@@ -2475,6 +2523,24 @@
"ui.easyprint_uploading": "Printables에 업로드하는 중…",
"ui.edit": "편집",
"ui.editJointLimits": "조인트 제한 편집",
"ui.edit_in_place": "제자리에서 편집",
"ui.edit_in_place_after_turn": "에이전트의 차례가 끝나면 편집이 완료됩니다",
"ui.edit_in_place_agent_busy": "에이전트가 아직 이 디자인에서 작업 중입니다. 차례가 끝난 후 다시 시도하세요",
"ui.edit_in_place_already_queued": "에이전트의 차례가 끝나기를 기다리는 편집이 이미 있습니다",
"ui.edit_in_place_assembly_closed": "{name}이(가) 더 이상 열려 있지 않습니다",
"ui.edit_in_place_banner": "{name}에서 편집 중",
"ui.edit_in_place_busy": "먼저 열려 있는 작업을 완료하거나 취소하세요",
"ui.edit_in_place_none": "제자리에서 편집 중인 연결된 디자인이 없습니다",
"ui.edit_in_place_not_saved": "부품에 저장되지 않은 변경 사항이 있습니다. 편집을 완료하려면 저장하세요",
"ui.edit_in_place_open_elsewhere": "{name}이(가) 다른 SolidCraft에서 열려 있습니다",
"ui.edit_in_place_opens_after_turn": "에이전트의 차례가 끝나면 부품이 열립니다",
"ui.edit_in_place_refresh_dropped": "링크 업데이트 중에 어셈블리가 변경되었습니다. 다시 실행하세요",
"ui.edit_in_place_refresh_stopped": "링크 업데이트가 완료되기 전에 중지되었습니다",
"ui.edit_in_place_refreshing": "{name}의 링크 업데이트 중…",
"ui.edit_in_place_save_first": "먼저 어셈블리를 저장하세요. 연결된 디자인은 해당 파일을 기준으로 찾습니다",
"ui.edit_in_place_save_waits": "{name}에서 링크 업데이트가 실행 중입니다. 완료된 후 저장하세요",
"ui.edit_in_place_saved_elsewhere": "부품이 다른 파일에 저장되었습니다. 어셈블리는 여전히 {name}에 연결되어 있습니다",
"ui.edit_in_place_wait": "디자인에서 실행 중인 작업이 끝날 때까지 기다리세요",
"ui.edit_section_analysis": "단면 분석 편집",
"ui.ellipse": "타원",
"ui.emboss_wrap_note": "지원되는 원통에 접하는 직교 선 프로파일은 자동으로 감깁니다. 대상을 고르려면 벽을 선택하세요.",
@@ -2542,6 +2608,7 @@
"ui.heading_edit": "편집",
"ui.heading_extrude": "돌출",
"ui.heading_fillet": "필렛",
"ui.heading_finish_editing": "편집 완료",
"ui.heading_finish_sketch": "스케치 종료",
"ui.heading_form": "폼",
"ui.heading_front": "정면",
@@ -2775,6 +2842,8 @@
"ui.restore_defaults": "기본값 복원",
"ui.reverse_horizontal_pan_direction": "수평 이동 방향 반전",
"ui.reverse_horizontal_pan_tip": "두 손가락 수평 스크롤과 엄지 휠이 반대 방향으로 이동합니다",
"ui.reverse_vertical_pan_direction": "수직 이동 방향 반전",
"ui.reverse_vertical_pan_tip": "두 손가락 수직 스크롤이 반대 방향으로 이동합니다",
"ui.reverse_zoom_direction": "확대/축소 방향 반전",
"ui.revolutions": "권수",
"ui.revolve": "회전",
@@ -2902,6 +2971,15 @@
"ui.up_axis_note": "뷰(축 뷰, 홈, 보기)에서 위쪽을 가리키는 축입니다. 디자인은 변경되지 않습니다.",
"ui.updateToCurrentView": "현재 보기로 업데이트",
"ui.upload": "업로드",
"ui.view_angles": "뷰 각도",
"ui.view_angles_convention": "위쪽 축을 기준으로 한 각도(도)입니다. 요 0°는 정면 뷰, 90°는 왼쪽, −90°는 오른쪽, 180°는 뒷면이고, 피치 90°는 평면 뷰입니다. 롤이 양수이면 모델이 화면에서 시계 방향으로 회전합니다.",
"ui.view_angles_help": "방향 기즈모 아래에 뷰의 피치, 요, 롤(도)과 투영 방식을 표시합니다. 표시를 클릭하면 정확한 각도를 입력할 수 있습니다.",
"ui.view_angles_ortho": "직교",
"ui.view_angles_persp": "원근",
"ui.view_angles_pitch": "피치",
"ui.view_angles_readout": "피치 {pitch} · 요 {yaw} · 롤 {roll}",
"ui.view_angles_roll": "롤",
"ui.view_angles_yaw": "요",
"ui.view_centre": "뷰 중심",
"ui.viewport_theme_follow": "테마 따르기",
"ui.visual_shaded_hidden_edges": "음영 처리 및 숨겨진 모서리",
+710
View File
@@ -37,6 +37,7 @@
"All open designs": "Semua reka bentuk terbuka",
"Allowed expressions, separated by semicolons": "Ungkapan yang dibenarkan, dipisahkan dengan titik koma",
"Also deletes": "Turut memadam",
"Also place them from the origin (fully constrained)": "Letakkan juga dari asalan (terkekang penuh)",
"Anchor": "Sauh",
"Angle 2": "Sudut 2",
"Angle Display": "Paparan Sudut",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Reka bentuk dibuka atau disimpan ada di sini.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Ditentukan oleh tetapan Ke Objek. Pilih Sudut untuk mengubah julat sudut.",
"Diameter": "Diameter",
"Dimension new shapes": "Dimensikan bentuk baharu",
"Direction": "Arah",
"Discard": "Buang",
"Distance": "Jarak",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Seret untuk memutar penyokong dalam langkah 5°. Tahan Alt atau Ctrl untuk memutarnya dengan bebas.",
"Drive Joint": "Gerakkan Sendi",
"Duration": "Tempoh",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Setiap bentuk baharu juga didimensikan dari asalan lakaran sehingga tiada yang bebas. Bentuk yang sudah terikat pada asalan atau geometri yang diletakkan tidak mendapat apa-apa.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Setiap bentuk yang anda lukis mendapat semua dimensinya pada saiz yang dilukis (nilai yang ditaip diutamakan). Saiz yang sudah ditetapkan oleh lakaran ditinggalkan.",
"Edges": "Tepi",
"Edit": "Sunting",
"Edit Profile Sketch": "Sunting Lakaran Profil",
@@ -1741,21 +1745,317 @@
"recovery.just_now": "sebentar tadi",
"recovery.min_ago": "{count} min lalu",
"recovery.never_saved": "tidak pernah disimpan",
"render.adaptive_absolute": "Had bawah ralat RGB mutlak",
"render.adaptive_coverage": "Sasaran ralat liputan",
"render.adaptive_enable": "Peruntukkan sampel dengan perintis bebas",
"render.adaptive_help": "GPU sahaja. Sampel perintis bebas dibuang, kemudian 16 atau lebih sampel pengeluaran bagi setiap piksel diperuntukkan sehingga Sampel setiap piksel. Varians RGB dan liputan memandu peruntukan; laluan jarang mungkin terlepas dan piksel yang dihadkan mungkin kekal berhingar. Laporan akhir mengira kerja sebenar. Tiada jaminan hingar atau masa yang diperakui.",
"render.adaptive_minimum": "Sampel pengeluaran minimum",
"render.adaptive_pending": "Peruntukan adaptif perintis bebas GPU dan strata Fresnel bersyarat tersedia. Penumpuan yang diperakui, jaminan peristiwa jarang dan pengangkutan adaptif CPU masih tidak tersedia.",
"render.adaptive_pilots": "Sampel perintis setiap piksel",
"render.adaptive_relative": "Sasaran ralat RGB relatif",
"render.add_ground": "Tambah lantai yang disesuaikan pada persediaan",
"render.advanced_material_scope": "Satu medium GPU homogen terhingga tersedia di bawah had yang jelas. Grid ketumpatan, gabungan kaca/isi padu bersarang, permukaan serakan subpermukaan, anjakan, pengangkutan spektrum dan konsep bahan lanjutan yang belum terikat masih tidak tersedia.",
"render.aging_add": "Tambah lapisan penuaan",
"render.aging_airborne": "Habuk berudara / medium penyertaan",
"render.aging_airborne_help": "Habuk berudara ialah isi padu serakan homogen terhingga yang berasingan. Ia mengubah pengangkutan dan EXR mentah, bukan tindanan penuaan permukaan. Sekatan isi padu/kaca/penyahhingaran yang sedia ada kekal jelas; tiada atmosfera ditambah secara automatik.",
"render.aging_all_bodies": "Semua jasad legap yang layak",
"render.aging_chips": "Cat terkelupas",
"render.aging_class_any": "Semua kelas bahan legap",
"render.aging_class_dielectric": "Permukaan bukan logam sahaja",
"render.aging_class_metal": "Permukaan logam sahaja",
"render.aging_color": "Warna lapisan · sRGB",
"render.aging_coverage": "Liputan",
"render.aging_dust": "Habuk termendap",
"render.aging_empty": "Tiada lapisan penuaan: permukaan asal kekal tidak berubah.",
"render.aging_fading": "Salutan pudar",
"render.aging_grime": "Kotoran & kesan noda",
"render.aging_help": "Gabungkan sehingga lapan lapisan optik, mengikut urutan. Karat dan patina ialah penampilan yang direka, bukan simulasi usia/kakisan. Skala dalam milimeter dunia. Tiada geometri, jisim atau sifat kejuruteraan diubah; kaca dan pentas pasif dikecualikan.",
"render.aging_metallic": "Pecahan logam lapisan",
"render.aging_origin": "Titik asal medan · mm dunia",
"render.aging_patina": "Patina hijau kuprum",
"render.aging_refresh_targets": "Periksa jasad semasa",
"render.aging_roughness": "Kekasaran lapisan",
"render.aging_rust": "Besi teroksida / karat",
"render.aging_scale": "Skala corak",
"render.aging_scratches": "Calar halus",
"render.aging_target": "Sasaran & koordinat",
"render.aging_target_help": "Sasaran bernama mesti masih sepadan dengan indeks dan nama yang dirakam. Topeng global bersauh pada dunia; ia tidak mengikut bahagian yang bergerak. Ini bukan pengesanan rongga mahupun haus tepi sebenar. Tapis senarai untuk mencapai jasad tambahan.",
"render.aging_target_search": "Tapis nama jasad",
"render.aging_upward": "Pemendapan menghadap ke atas",
"render.all_controls_help": "Pemeriksaan padat bagi semua kawalan semasa. Halaman seksyen menyediakan penyuntingan berfokus tanpa mengubah permintaan asas.",
"render.all_shots_label": "Semua Syot",
"render.appearance_physics_separate": "Penampilan visual tidak menetapkan ketumpatan, data terma atau sifat kejuruteraan lain.",
"render.availability_native": "Gubahan asli; semak sebelum menggunakan",
"render.availability_projection": "Unjuran disokong; lihat skop dan perkara yang ditinggalkan",
"render.availability_reference": "Data rujukan; bukan penetapan automatik",
"render.backdrop_alpha_conflict": "Pilih latar ini atau keluaran PNG telus; enjin render tidak akan mengabaikan sama ada tetapan secara senyap.",
"render.backdrop_enable": "Gunakan latar kecerunan untuk kamera sahaja",
"render.backdrop_first": "Warna mula / tengah",
"render.backdrop_help": "Latar ruang skrin ini tidak menerangi, tidak menghasilkan bayang, tidak memantul dan tidak mewakili rupa bumi. Ia dikecualikan daripada EXR mentah. Geometri, lampu dan persekitaran HDR kekal bebas.",
"render.backdrop_horizontal": "Kecerunan mendatar",
"render.backdrop_radial": "Kecerunan jejarian",
"render.backdrop_radius": "Jejari",
"render.backdrop_second": "Warna hujung / tepi",
"render.backdrop_vertical": "Kecerunan menegak",
"render.backdrop_x": "Pusat X",
"render.backdrop_y": "Pusat Y",
"render.background": "Latar belakang adegan",
"render.background_camera_section": "Latar belakang kamera · persembahan PNG",
"render.background_completed_frozen": "Hasil yang dipaparkan ialah imej siap yang dibekukan. Menyunting latar belakang tidak melukis semula hasil itu secara automatik. Gunakan Gred Semula Warna untuk perubahan kamera sahaja, atau Render untuk pentas fizikal baharu.",
"render.background_hdr_separate": "Sumber HDR semasa menerangi dan memantul pada permukaan; ia tidak dipaparkan secara automatik sebagai panorama di belakang subjek. Menukar kecerunan tidak memutar atau mewarnakan semula pencahayaan.",
"render.background_lighting_section": "Pencahayaan HDR · berasingan daripada latar belakang kamera",
"render.background_no_alpha_override": "Latar belakang kamera tidak ditambah secara senyap pada keluaran telus. Gred semula warna induk mentah menggunakan liputan yang dirakam dan tidak menggunakan semula penyahhingaran; EXR sumber kekal tidak berubah.",
"render.background_not_light": "Warna latar belakang ialah persembahan, bukan sumber pencahayaan tambahan.",
"render.background_regrade": "Gunakan pada induk mentah yang dikekalkan",
"render.background_stage_occlusion": "Syot ini mengandungi geometri pentas fizikal. Lantai atau dinding yang besar boleh memenuhi bingkai dan menyembunyikan latar belakang kamera sahaja. Kosongkan atau ubah saiz pentas dengan sengaja, atau ubah kepantulan fizikalnya. Gred semula warna tidak dapat membuang geometri yang dirakam.",
"render.background_workflow": "Pilih latar belakang yang anda maksudkan: warna/kecerunan untuk kamera sahaja, pentas fizikal yang menerima cahaya, atau pencahayaan HDR. Ketiga-tiganya bebas. Pratonton Langsung ialah paparan pemodelan; render imej baharu atau gred semula warna induk yang dikekalkan untuk melihat kemasan kamera.",
"render.base_appearance": "Penampilan jasad yang boleh disunting",
"render.base_apply": "Gunakan penampilan jasad",
"render.base_apply_help": "Satu penetapan visual yang boleh dibuat asal pada jasad tepat yang disemak. Gaya khusus muka dan bahan kejuruteraan yang sedia ada kekal berasingan.",
"render.base_color": "Warna asas · sRGB",
"render.base_metallic": "Pecahan logam",
"render.base_opaque_only": "Penyunting ini mengekalkan semantik jasad legap. Gunakan kawalan kaca yang khusus untuk transmisi optik.",
"render.bloom_enable": "Papar bloom",
"render.bloom_help": "Pendaran kreatif untuk keluaran sahaja daripada serlahan linear positif, disebarkan dengan tiga laluan kotak ternormal. Jejari dalam piksel keluaran. Ditambah dalam cahaya paparan linear sebelum sRGB; bukan kesan kanta, kesan volumetrik atau peningkatan penumpuan. EXR mentah tidak berubah.",
"render.bloom_opaque": "Bloom memerlukan keluaran legap. PNG telus ditolak, bukan diratakan secara senyap.",
"render.bloom_radius": "Jejari bloom",
"render.bloom_strength": "Kekuatan bloom",
"render.bloom_threshold": "Ambang serlahan linear",
"render.browse_capabilities": "Periksa katalog keupayaan lengkap",
"render.browse_environments": "Semak imbas persekitaran HDR asal",
"render.browse_native_scenes": "Semak imbas studio asli",
"render.browse_physical": "Periksa rujukan fizikal",
"render.browse_quality": "Periksa spesifikasi kualiti",
"render.browse_rigs": "Semak imbas rig lampu yang direka",
"render.browse_scene_specs": "Semak imbas spesifikasi adegan lanjutan",
"render.browse_surfaces": "Semak imbas permukaan yang direka",
"render.browser_library": "Koleksi",
"render.browser_model": "Model",
"render.camera_distance": "Jarak mata ke sasaran",
"render.camera_exact_help": "Milimeter dunia; sudut dipaparkan dalam darjah dan disimpan sebagai radian. Navigasi menggunakan kamera yang sama dengan tetingkap pandangan.",
"render.camera_fov": "Medan pandangan menegak",
"render.camera_pitch": "Pic kamera",
"render.camera_roll": "Gelek",
"render.camera_set": "Tetapkan Kamera Render",
"render.camera_target": "Kedudukan sasaran · mm",
"render.camera_yaw": "Yaw",
"render.chromatic_offset": "Ofset tepi kromatik",
"render.clear_stage": "Buang pentas yang disimpan",
"render.copy_request": "Salin JSON",
"render.cpu_aa_help": "Sampel ruang: lebih banyak sampel menambah baik tepi dan menambah masa render.",
"render.cpu_area_add": "Tambah lampu segi empat tepat CPU",
"render.cpu_area_editor": "Lampu segi empat tepat CPU",
"render.cpu_area_editor_help": "Vektor sisi penuh dalam milimeter; U silang V menghala ke sisi yang memancar. Ini berbeza daripada vektor separuh tepi GPU.",
"render.cpu_area_full_u": "Sisi U penuh · mm",
"render.cpu_area_full_v": "Sisi V penuh · mm",
"render.cpu_area_samples": "Sampel lampu kawasan",
"render.cpu_binding_confirm": "Sahkan jasad ini",
"render.cpu_binding_stale": "Adegan telah berubah. Sahkan sasaran pantulan ini sekali lagi sebelum merender.",
"render.cpu_body_choose": "Pilih jasad",
"render.cpu_body_filter": "Tapis jasad mengikut nama",
"render.cpu_body_filter_more": "Perhalusi tapisan untuk melihat lebih banyak jasad.",
"render.cpu_body_missing": "Sasaran pantulan hilang, tersembunyi, taksa atau mempunyai nama yang lebih panjang daripada 128 bait. Pilih semula.",
"render.cpu_budget": "Profil sumber CPU",
"render.cpu_budget_bodies": "Had atas jasad",
"render.cpu_budget_compact": "Padat (had lama)",
"render.cpu_budget_details": "Had sumber",
"render.cpu_budget_help": "Pilih had yang lebih besar secara jelas. Resolusi dan sampel tidak pernah dikurangkan secara automatik.",
"render.cpu_budget_memory": "Had atas memori kerja",
"render.cpu_budget_not_guarantee": "Ini ialah had atas kemasukan, bukan tempahan RAM atau jaminan kelajuan. Geometri, filem dan pratonton yang dikekalkan berkongsi bajet memori; render kekal boleh dibatalkan.",
"render.cpu_budget_resize": "Draf melebihi profil CPU ini atau bajet sampel kameranya. Terima dimensi yang lebih kecil secara jelas atau pilih profil yang lebih besar.",
"render.cpu_budget_studio": "Studio (imej besar)",
"render.cpu_budget_triangles": "Had atas segi tiga",
"render.cpu_budget_workstation": "Stesen kerja (adegan berat)",
"render.cpu_captured_hdr": "HDR yang dirakam untuk imej ini",
"render.cpu_check_capture_help": "Semak dan Mula mengesahkan cincang fail yang sama atau menggunakan HDR terbenam. Setiap imej mengekalkan sumber yang dirakamnya.",
"render.cpu_check_changed": "Kawalan atau model berubah selepas semakan ini. Semak semula sebelum merender.",
"render.cpu_constant_help": "Radiance malar kelihatan kepada sinar yang dipantulkan atau ditransmisikan. Ia tidak memberikan pencahayaan resap langsung.",
"render.cpu_custom_directions": "Gantikan pratetap dengan lampu berarah tersuai",
"render.cpu_direction": "Arah menuju lampu (X, Y, Z)",
"render.cpu_directional": "Lampu berarah",
"render.cpu_directional_add": "Tambah lampu berarah",
"render.cpu_environment": "Persekitaran CPU",
"render.cpu_environment_background": "Latar belakang imej kekal berasingan daripada pencahayaan persekitaran.",
"render.cpu_environment_bounds": "Keamatan CPU mestilah 0–64, putaran HDR terhingga dalam ±1,000,000 radian, dan sampel HDR 1, 4, 16 atau 64.",
"render.cpu_environment_constant": "Persekitaran sinar sekunder malar",
"render.cpu_environment_none": "Tiada persekitaran CPU",
"render.cpu_environment_samples": "Sampel pencahayaan HDR",
"render.cpu_exposure_help": "Pendedahan CPU mestilah antara −16 dan 16 EV. Pendedahan GPU di luar julat itu dikekalkan sehingga anda mengubahnya.",
"render.cpu_fixed": "Imej tunggal",
"render.cpu_hdr_help": "Radiance .hdr, panorama 2:1, sehingga 2048 × 1024 dan 16 MiB. CPU memerlukan primari sRGB/D65 yang dinyatakan secara jelas dalam fail; primari yang tidak dinyatakan dan EXR ditolak.",
"render.cpu_hdr_reflection_help": "Pantulan kasar HDR memerlukan permukaan jasad dan muka yang berlogam sepenuhnya. Semak melaporkan gabungan yang tidak disokong.",
"render.cpu_key_rim": "Utama dan pinggir",
"render.cpu_last_check": "Semakan CPU terakhir",
"render.cpu_light_help": "Sehingga lapan lampu berarah. Senarai tersuai yang kosong mematikannya; memilih pratetap memulihkan lampunya. Warna ialah RGB linear dan keamatan bersifat relatif, bukan watt.",
"render.cpu_light_intensity": "Keamatan relatif (0–64)",
"render.cpu_light_minimum": "Jarak minimum untuk pelemahan",
"render.cpu_light_position": "Kedudukan dunia (X, Y, Z)",
"render.cpu_light_reference": "Jarak rujukan untuk keamatan",
"render.cpu_light_remove": "Buang lampu",
"render.cpu_lighting": "Pratetap pencahayaan",
"render.cpu_lights": "Lampu CPU",
"render.cpu_linear_color": "Warna linear (R, G, B)",
"render.cpu_neutral": "Neutral",
"render.cpu_opaque_required": "Penjejakan sinar CPU memerlukan latar belakang legap. Nyahtandakan Latar belakang telus untuk meneruskan.",
"render.cpu_options_pending": "Panel CPU ini belum dapat menyunting pancaran, kesan permukaan, kaca atau anisotropi. Kosongkan pilihan API tersebut sebelum menggunakannya.",
"render.cpu_point": "Lampu titik",
"render.cpu_point_add": "Tambah lampu titik",
"render.cpu_point_help": "Sehingga lapan lampu titik, ditambah pada pencahayaan berarah yang dipilih. Jarak dalam mm; jarak minimum tidak boleh melebihi jarak rujukan.",
"render.cpu_primary_samples": "Sampel tepi setiap piksel",
"render.cpu_progressive": "CPU progresif",
"render.cpu_progressive_help": "Kumpulkan hasil penyepadu CPU sedia ada dalam pas satu sampel utama. Pantulan yang dipilih memerlukan satu sampel; lampu kawasan, dielektrik dan anisotropi memerlukan Imej tunggal.",
"render.cpu_progressive_limits": "Paling banyak 1,048,576 piksel dan 16,777,216 penilaian piksel × sampel. Menukar sampel tidak mengubah saiz imej secara automatik.",
"render.cpu_progressive_seed": "Benih pensampelan CPU",
"render.cpu_progressive_spp": "sampel setiap piksel",
"render.cpu_reflection_add": "Tambah pantulan kasar",
"render.cpu_reflection_depth": "Kedalaman pantulan (1–8)",
"render.cpu_reflection_empty": "Tiada jasad dipilih: pantulan adegan dimatikan.",
"render.cpu_reflection_help": "Pilih jasad dan tetapkan Dimatikan, Cermin atau Kasar. Kasar menggunakan kekasaran permukaan yang ditetapkan. Lebih banyak sampel dan lantunan menambah masa; ini ialah pengangkutan spekular terhad, bukan pencahayaan global.",
"render.cpu_reflection_limit": "Sehingga 64 jasad terpantul disokong.",
"render.cpu_reflection_mirror": "Cermin",
"render.cpu_reflection_off": "Dimatikan",
"render.cpu_reflection_rough": "Kasar",
"render.cpu_reflection_samples": "Sampel pantulan (1–64)",
"render.cpu_reflections": "Pantulan CPU",
"render.cpu_runtime_help": "Tetapan lampu dan persekitaran berangka disimpan bersama persediaan. Pantulan jasad dan fail HDR kekal sementara. Nilai lampu kawasan dan kon lampu sorot yang sedia ada dikekalkan.",
"render.cpu_sampling_mode": "Mod pensampelan CPU",
"render.cpu_shadows": "Hasilkan bayang",
"render.cpu_summary": "Penjejakan sinar CPU · pantulan · HDR · lampu berarah dan lampu titik",
"render.cpu_warm_cool": "Hangat dan sejuk",
"render.diag_bodies": "Jasad kelihatan",
"render.diag_job_details": "Butiran kerja yang dirakam",
"render.diag_last_check": "Semakan awal terakhir",
"render.diag_memory": "Anggaran kemasukan logik",
"render.diag_not_implemented": "Sempadan keupayaan yang dinyatakan secara jelas",
"render.diag_preflight_details": "Butiran semakan awal",
"render.diag_request": "Permintaan semasa yang tepat",
"render.diag_triangles": "Segi tiga",
"render.discard_continue": "Buang draf dan teruskan",
"render.draft_confirm_help": "Draf render semasa mempunyai suntingan yang belum digunakan. Simpan sebelum menukar, buang secara jelas, atau teruskan menyunting.",
"render.draft_confirm_title": "Kekalkan tetapan render yang disunting",
"render.effects_gpu_only": "Kesan ini memerlukan penjejakan laluan GPU. Menukar halaman tidak pernah menukar enjin render secara automatik.",
"render.effects_help": "Gabungkan gaya warna yang tersusun dan kesan kanta dalam ruang imej. Merender dan gred semula warna induk mentah menggunakan tetapan tersimpan yang sama. EXR mentah kekal tidak berubah. Ini ialah kawalan artistik asli, bukan emulasi kanta yang ditentukur atau filem berjenama.",
"render.effects_reset_lens": "Set semula kesan kanta",
"render.effects_seed": "Benih corak",
"render.emitted_axis": "Paksi pancaran",
"render.error_area_samples": "area_samples mestilah 1, 4, 16 atau 64",
"render.error_binding_allocation": "tidak dapat memperuntukkan pengikatan bahan",
"render.error_body_bound": "pratonton produk melebihi had jasad yang dirakam",
"render.error_checkpoint_dimensions": "dimensi titik semak berbeza daripada permintaan yang dirakam",
"render.error_decode_budget": "bajet penyahkodan imej melimpah",
"render.error_denoise_setting": "tetapan penyahhingaran natif tidak sah",
"render.error_display_dimensions": "dimensi paparan imej tidak sah",
"render.error_display_fit": "paparan imej tidak muat pada peranti ini",
"render.error_display_height": "ketinggian paparan melimpah",
"render.error_display_width": "lebar paparan melimpah",
"render.error_duplicate_face": "penampilan muka produk berganda",
"render.error_export_document": "Dokumen eksport render berubah semasa memilih destinasinya",
"render.error_face_cap": "pratonton produk melebihi had kemasukan penampilan muka",
"render.error_finish_gesture": "selesaikan gerak isyarat pemodelan sebelum pratonton",
"render.error_finish_operation": "selesaikan operasi pemodelan semasa sebelum memasuki Render",
"render.error_fixed_preview": "pratonton Studio tetap memerlukan pendedahan 0, putaran persekitaran 0 dan keamatan 1",
"render.error_geometry_size": "saiz geometri produk melimpah",
"render.error_glass_recipe": "resipi kaca tidak dikenali",
"render.error_gpu_preview": "Pratonton produk GPU tidak tersedia pada hos ini. Persediaan yang disimpan kekal tersedia.",
"render.error_gpu_samples": "bilangan sampel GPU tidak disokong",
"render.error_image_dimensions": "dimensi imej render tidak sepadan dengan kerjanya",
"render.error_image_profile": "imej render melebihi profil sumber yang dirakam",
"render.error_interactive_command": "perintah Render interaktif tidak terikat",
"render.error_job_action": "bukan tindakan kerja imej interaktif",
"render.error_job_identity": "identiti kerja render tidak sah: {error}",
"render.error_library_reply": "respons koleksi render tidak sah",
"render.error_material_binding": "pengikatan bahan tiada",
"render.error_no_completed_image": "render tiada imej yang selesai",
"render.error_no_geometry": "tiada geometri produk",
"render.error_no_scene": "tiada adegan produk",
"render.error_opacity": "kelegapan penampilan produk tidak sah",
"render.error_pbr_opacity": "PBR legap memerlukan kelegapan 1",
"render.error_physical_glass": "resipi yang dipilih bukan kaca fizikal",
"render.error_preview_device": "pratonton produk memerlukan peranti terpasang dengan penimbal kedalaman",
"render.error_product_triangle": "segi tiga produk tidak sah",
"render.error_provisional_identity": "identiti render sementara atau bilangan sampel tidak sah",
"render.error_quality_bounds": "unjuran kualiti melebihi had natif",
"render.error_quality_method": "unjuran kualiti memerlukan kaedah GPU eksplisit yang sama",
"render.error_quality_projection": "unjuran kualiti natif tidak sah",
"render.error_regrade_identity": "identiti gred semula warna tidak sah: {error}",
"render.error_scene_bodies": "jasad adegan render tiada",
"render.error_scene_body_limit": "adegan render melebihi had jasadnya",
"render.error_scene_identity": "identiti adegan render tidak sah",
"render.error_setup_panicked": "pemulaan penjejak laluan GPU tergendala",
"render.error_setup_stopped": "pekerja pemulaan berhenti tanpa memulangkan hos",
"render.error_setup_worker": "tidak dapat memulakan pekerja pemulaan: {error}",
"render.error_source_preview": "pratonton sumber melebihi had baitnya",
"render.error_surface_normals": "PBR memerlukan normal permukaan bukan sifar",
"render.error_surface_reply": "balasan permukaan ciptaan tidak sah",
"render.error_triangle_bound": "pratonton produk melebihi had sumber lapan juta segi tiga",
"render.error_triangle_count": "limpahan bilangan segi tiga produk",
"render.error_upload_slot": "slot muat naik pratonton produk tidak tersedia",
"render.error_vertex_allocation": "peruntukan bucu pratonton produk gagal",
"render.error_vertex_envelope": "pratonton produk melebihi had muatan bucu {limit} MiB; geometri tidak dipermudahkan",
"render.error_vertex_packing": "pembungkusan pratonton produk berbeza daripada muatan bucu yang dibenarkan",
"render.error_visible_solid": "Cipta pepejal yang kelihatan dalam Reka untuk pratonton di sini.",
"render.exit_focus": "Keluar fokus",
"render.export_display": "Eksport: PNG paparan",
"render.export_image_label": "Eksport Imej",
"render.export_linear": "Eksport: EXR linear mentah",
"render.exr_pending": "GPU boleh mengekalkan EXR linear mentah. Pemampatan, imej berbilang lapisan dan pas render tambahan belum tersedia.",
"render.film_grain": "Bijian fotografi",
"render.fit": "Muatkan Produk",
"render.fixed_camera": "Kamera",
"render.fixed_world": "Dunia",
"render.flare_ghosts": "Cincin bayang setiap sumber",
"render.flare_halo": "Halo kilau",
"render.flare_streak": "Alur gaya anamorfik",
"render.flare_strength": "Kekuatan kilau bahagian terang",
"render.flare_threshold": "Ambang kilau linear adegan",
"render.fold_browser": "Ringkaskan Pelayar",
"render.gpu_depth": "Kedalaman laluan maksimum",
"render.gpu_options_help": "Sampel, kedalaman, benih dan pendedahan disimpan bersama persediaan ini. Hanya kaedah imej yang aktif disimpan.",
"render.gpu_path_failed": "Penjejak laluan GPU tidak tersedia",
"render.gpu_path_first_setup": "Persediaan pertama pada GPU ini boleh mengambil masa beberapa minit; SolidCraft masih boleh digunakan sementara itu. Permulaan seterusnya menggunakan semula pembayang yang telah dikompil jika pemacu menyimpannya.",
"render.gpu_path_preparing": "Penjejak laluan GPU: mengompil pembayang…",
"render.gpu_seed": "Benih rawak",
"render.gpu_unavailable": "Penjejakan laluan GPU belum sedia pada peranti ini.",
"render.ground_apply": "Muatkan dan simpan lantai",
"render.ground_gap": "Jarak kelegaan eksplisit",
"render.ground_linear_rgb": "Pantulan serakan · RGB linear",
"render.ground_margin": "Jidar julat lantai",
"render.hdr_details": "Butiran sumber HDR",
"render.hdr_embedded": "HDR disimpan dalam reka bentuk ini",
"render.hdr_embedded_help": "Proses render menggunakan bait yang disertakan dalam reka bentuk; fail asal tidak lagi diperlukan.",
"render.hdr_file_captured": "Fail HDR telah disemak. Simpan akan membenamkan bait ini; jika fail berubah, semak semula secara eksplisit.",
"render.hdr_inspect": "Semak fail HDR",
"render.hdr_inspect_required": "Pilih dan semak fail HDR sebelum menyimpan atau merender.",
"render.hdr_primaries_declared": "Sumber mengisytiharkan primer warnanya.",
"render.hdr_primaries_srgb": "Primer warna: sRGB/D65",
"render.hdr_primaries_undeclared": "Sumber tidak mengisytiharkan primer; semak keperluan warna enjin render.",
"render.hdr_resource_missing": "Reka bentuk ini tiada sumber HDR yang disimpan.",
"render.heading_batch": "KELOMPOK",
"render.heading_frame": "BINGKAI",
"render.heading_lens": "LENSA",
"render.heading_results": "HASIL",
"render.heading_shots": "SYOT",
"render.hide_shots_label": "Sembunyi jalur Syot",
"render.image_advanced": "Kawalan GPU lanjutan",
"render.image_cancelled": "Render dibatalkan",
"render.image_cancelling": "Membatalkan",
"render.image_completed": "Imej sedia untuk dieksport",
"render.image_encoding": "Mengekod PNG",
"render.image_export": "Eksport PNG",
"render.image_exposure": "Pendedahan",
"render.image_failed": "Render gagal",
"render.image_height": "Ketinggian",
"render.image_help": "Imej pratonton CPU · PNG · ketelusan dianggarkan",
"render.image_host_missing": "Tiada hos imej dipasang.",
"render.image_method": "Kaedah imej",
"render.image_overwrite": "Ganti fail sedia ada",
"render.image_preparing": "Menyediakan imej",
"render.image_progressive": "Render progresif",
"render.image_queued": "Menunggu render",
"render.image_reduce": "Cuba imej lebih kecil atau adegan lebih ringkas.",
"render.image_running": "Menghasilkan imej",
"render.image_samples": "Sampel setiap piksel",
"render.image_scene_stale": "Selesaikan gerak isyarat pemodelan atau muat semula adegan sebelum menyemak atau memulakan imej.",
"render.image_stale": "Imej ini menggunakan adegan yang dirakam sebelum perubahan terbaharu.",
"render.image_start": "Mulakan Render",
"render.image_supported": "Permintaan render disokong; baris gilir dan peruntukan memori akan disemak semula apabila render bermula.",
@@ -1765,20 +2065,430 @@
"render.image_unknown": "Status render tidak tersedia",
"render.image_use_largest": "Gunakan saiz terbesar pada nisbah aspek ini:",
"render.image_width": "Lebar",
"render.include_rig_cards": "Sertakan kad dan bendera pasif",
"render.inner_half_angle": "Separuh sudut dalam",
"render.inspect_scene": "Muat semula ringkasan adegan yang dirakam",
"render.inspector": "Pemeriksa",
"render.keep_editing": "Teruskan menyunting",
"render.layer_down": "Alih ke bawah",
"render.layer_enabled": "Lapisan diaktifkan",
"render.layer_off_suffix": " (dimatikan)",
"render.layer_remove": "Buang lapisan",
"render.layer_strength": "Kekuatan lapisan",
"render.layer_up": "Alih ke atas",
"render.lens_effects_help": "Kilau menggunakan sehingga empat sumber terang yang terpisah dalam imej linear sebenar. Bayang, halo, alur, ofset kromatik dan herotan jejarian ialah anggaran artistik dalam ruang imej. Kesan ruang memerlukan keluaran legap; sampel di luar imej menyambung tepi imej. Bijian bersifat deterministik. Tiada fizik, EXR atau geometri diubah.",
"render.lens_effects_title": "Berinspirasikan lensa & fotografi",
"render.library_all": "Katalog",
"render.library_all_states": "Semua status ketersediaan",
"render.library_applied": "Unjuran sumber telah digunakan. Semak permintaan render yang lengkap sebelum memulakan.",
"render.library_apply_hdr": "Simpan dengan persekitaran HDR ini",
"render.library_apply_maps": "Gunakan peta permukaan GPU ciptaan",
"render.library_apply_studio": "Simpan unjuran studio ciptaan",
"render.library_apply_uniform": "Gunakan penampilan legap seragam",
"render.library_authored_help": "Sumber ciptaan asal bersifat ilustrasi, bukan data kejuruteraan yang diukur. Setiap tindakan hanya menggunakan unjuran yang dinyatakan.",
"render.library_blocked": "Disekat / memerlukan penentukuran",
"render.library_capabilities": "Spesifikasi keupayaan",
"render.library_center": "Pusat rig",
"render.library_clear_search": "Kosongkan",
"render.library_details": "Spesifikasi dan asal usul",
"render.library_emitters_only_ack": "Gunakan pemancar sahaja; tinggalkan kad pasif yang didokumenkan",
"render.library_empty": "Tiada sumber yang sepadan. Cuba pertanyaan atau penapis ketersediaan yang lain.",
"render.library_environment_concepts": "Konsep persekitaran",
"render.library_extent": "Julat subjek",
"render.library_favorite": "Tambah kegemaran",
"render.library_favorites": "Kegemaran",
"render.library_hdr": "Persekitaran HDR terbina dalam",
"render.library_hdr_help": "Membenamkan HDR asal dalam persediaan yang disimpan. Asal longitud ciptaan ditukar secara eksplisit; tiada fail luaran diperlukan selepas disimpan.",
"render.library_inspect_only": "Pilih untuk memeriksa; tiada apa-apa digunakan secara automatik. Kegemaran dan sejarah terkini terikat pada sesi dokumen terbuka ini.",
"render.library_light_concepts": "Konsep pencahayaan",
"render.library_maps_help": "Peta terbina dalam boleh disimpan bersama sumber yang disemat dan pemetaan kejadian setempat. Penimpaan optik sementara kekal sebagai mod yang berasingan.",
"render.library_material_concepts": "Konsep bahan",
"render.library_native_scenes": "Studio asli",
"render.library_next": "Halaman seterusnya",
"render.library_omitted": "Tidak disertakan",
"render.library_physical_profiles": "Profil rujukan fizikal",
"render.library_previous": "Halaman sebelumnya",
"render.library_quality_concepts": "Spesifikasi kualiti",
"render.library_recent": "Terkini",
"render.library_replace_environment": "Ganti persekitaran sedia ada secara eksplisit",
"render.library_replace_studio": "Ganti pencahayaan, persekitaran dan pentas yang disimpan",
"render.library_results": "Sumber yang sepadan",
"render.library_rig_help": "Muatkan sekali pada pusat dan julat fizikal yang eksplisit. Rig lengkap termasuk kad pasif; penyekat tentukuran tetap menolak. Kelegaan pemancar/kad yang konservatif disemak sebelum menyimpan.",
"render.library_rigs": "Rig pencahayaan ciptaan",
"render.library_save_maps": "Simpan peta ke persediaan ini",
"render.library_scene_bounds": "Gunakan sempadan adegan yang dirakam",
"render.library_scenes": "Spesifikasi adegan",
"render.library_search": "Cari dalam koleksi",
"render.library_select_hint": "Pilih sumber dalam Koleksi untuk memeriksa tindakan yang disokong dan batasannya.",
"render.library_selene": "Penampilan legap SELENE",
"render.library_selene_shots": "Spesifikasi syot SELENE",
"render.library_short_blocked": "Tidak tersedia",
"render.library_short_native": "Gubahan asli",
"render.library_short_projection": "Unjuran yang disokong",
"render.library_short_reference": "Rujukan sahaja",
"render.library_short_specification": "Spesifikasi sahaja",
"render.library_source_preview": "Muatkan pratonton peta sumber",
"render.library_source_preview_help": "Peta sumber warna asas ciptaan. Ini bukan pratonton bahan yang dirender atau diukur.",
"render.library_specification_only": "Spesifikasi sahaja: bukan pratetap boleh laku yang lengkap. Kesan, sumber dan peranan subjek yang diperlukan masih memerlukan pelaksanaan dan pengikatan yang jelas.",
"render.library_specs": "Spesifikasi sahaja",
"render.library_status": "Ketersediaan",
"render.library_surfaces": "Permukaan PBR yang dicipta",
"render.library_target": "Jasad sasaran",
"render.library_title": "Koleksi sumber render",
"render.library_unfavorite": "Buang kegemaran",
"render.library_uniform_ack": "Guna penghampiran seragam tanpa kesan ruang atau lanjutan",
"render.library_usable": "Unjuran boleh laku",
"render.light_anchor_pending": "Menukar rangka koordinat lampu belum disokong lagi.",
"render.lights_fixed_to": "Lampu tetap pada",
"render.linear_help": "Menyimpan induk RGBA titik apungan 32-bit sebelum penyahhingaran, dedahan, pemetaan ton, penapis dan latar. sRGB linear/D65; didarab awal dengan liputan. Memori tambahan dibenarkan secara jelas. Tiada mampatan atau lintasan tambahan.",
"render.linear_retain": "Kekalkan EXR linear mentah",
"render.linear_unavailable": "Bingkai siap yang dipilih tidak mempunyai EXR yang dikekalkan. Aktifkan pengekalan sebelum merender; PNG lama tidak dapat memulihkan radians mentah.",
"render.look_add": "Tambah gaya warna",
"render.look_bleach": "Berilhamkan pintas peluntur",
"render.look_cool": "Sejuk",
"render.look_cyanotype": "Berilhamkan sianotaip",
"render.look_faded": "Cetakan pudar",
"render.look_mono": "Monokrom",
"render.look_sepia": "Sepia",
"render.look_strength": "Kekuatan gaya",
"render.look_teal_orange": "Hijau kebiruan / oren",
"render.look_title": "Tindanan gaya kreatif",
"render.look_warm": "Hangat",
"render.mapping_scale": "Pengganda ulangan fizikal",
"render.material_absorption": "Serapan R · G · B (setiap mm)",
"render.material_add": "Tambah atau sunting jasad ini",
"render.material_assignments": "Penetapan jasad",
"render.material_binding_enable": "Sertakan penggantian jasad ini",
"render.material_box": "Kotak terjajar paksi",
"render.material_browse": "Pilih imej…",
"render.material_certification": "Kaca tertutup menggunakan jarak geometri. Topologi, orientasi, pertindihan dan sempadan optik disemak semasa penyediaan GPU; Semak hanya menerima permintaan.",
"render.material_choose_body": "Pilih jasad adegan",
"render.material_closed": "Mesh pepejal tertutup",
"render.material_coat": "Salutan jernih di atas bahan asas",
"render.material_coat_enable": "Aktifkan salutan jernih",
"render.material_coat_help": "Salutan dielektrik ilustrasi di atas penampilan legap sedia ada. Berat sifar membiarkan bahan asas tidak berubah.",
"render.material_color_map": "Imej warna asas (sRGB)",
"render.material_color_replace": "Peta asas menggantikan warna jasad",
"render.material_custom": "Optik ilustrasi tersuai",
"render.material_enable": "Guna penggantian bahan GPU ini",
"render.material_filter": "Tapis jasad adegan…",
"render.material_filter_help": "Sehingga 128 jasad yang sepadan dipaparkan. Perincikan penapis untuk adegan yang besar.",
"render.material_glass": "Kaca dan serapan optik",
"render.material_glass_enable": "Guna kaca fizikal pada jasad ini",
"render.material_glass_exclusive": "Kaca tidak boleh berkongsi jasad dengan salutan jernih atau peta masa jalan dalam enjin render ini.",
"render.material_glass_help": "Resipi ilustrasi asal. Petak warna menunjukkan transmitans, bukan pratonton yang dirender. Serapan ialah −ln(transmitans linear) / jarak rujukan; alfa tidak berubah.",
"render.material_gpu_required": "Penggantian bahan aktif ini memerlukan penjejakan laluan GPU. Pilih GPU atau matikan penggantian sebelum Semak atau Mula.",
"render.material_ior": "Indeks biasan (IOR)",
"render.material_limits": "Paling banyak 128 penggantian jasad, 32 jasad kaca yang terpisah, 64 salutan dan 128 pengikatan tekstur. Peta yang serupa berkongsi storan; had peranti dan memori keseluruhan yang sebenar masih terpakai.",
"render.material_map_invalid": "Laluan peta mestilah laluan tempatan yang terhad; kekuatan normal mestilah terhingga dan antara 0 dengan 1.",
"render.material_map_required": "Pilih imej warna atau imej normal sebelum menggunakan peta.",
"render.material_maps": "Peta warna dan normal satah",
"render.material_maps_enable": "Aktifkan peta untuk jasad legap ini",
"render.material_maps_help": "PNG/JPEG sehingga 1024×1024; jumlah terkod 16 MiB. U dan V ialah vektor ulangan dunia dalam mm yang ortogon (maksimum 128 ulangan). Warna ialah sRGB; data normal menggunakan OpenGL +Y. Fail diambil semasa Semak/Mula.",
"render.material_metallic_map": "Peta logam (linear)",
"render.material_normal_map": "Imej normal (OpenGL, +Y)",
"render.material_normal_strength": "Kekuatan normal (0–1)",
"render.material_origin": "Titik asal pemetaan X · Y · Z (mm)",
"render.material_refresh": "Muat semula jasad adegan",
"render.material_refresh_needed": "Adegan telah berubah. Muat semula senarai jasad sebelum menambah sasaran.",
"render.material_remove": "Buang penetapan ini",
"render.material_repeat_u": "Satu ulangan U X · Y · Z (mm)",
"render.material_repeat_v": "Satu ulangan V X · Y · Z (mm)",
"render.material_revalidate": "Sahkan semula jasad ini",
"render.material_revalidate_needed": "Penetapan ini milik semakan adegan yang lebih awal. Sahkan semula identiti jasadnya yang tepat sebelum merender.",
"render.material_roughness": "Kekasaran salutan (0.045–1)",
"render.material_roughness_map": "Peta kekasaran (linear)",
"render.material_shadow": "Benarkan sinar bayang lurus menembusi",
"render.material_target_missing": "Nombor turutan dan nama jasad tidak lagi sepadan. Buang penetapan ini dan pilih jasad yang dimaksudkan semula secara jelas.",
"render.material_thickness": "Ketebalan kepingan nipis (mm)",
"render.material_thin": "Kepingan nipis",
"render.material_title": "Bahan imej GPU",
"render.material_transient": "Penggantian optik sementara untuk tab dokumen ini. Ia tidak disimpan dalam reka bentuk, persediaan render atau koleksi bahan.",
"render.material_v_up": "V tekstur menghala ke atas dalam imej",
"render.material_weight": "Berat salutan (0–1)",
"render.method_cpu": "Penjejakan sinar CPU",
"render.method_gpu": "Penjejakan laluan GPU",
"render.method_limit_raster": "Raster menggunakan pratonton studio legap yang tetap. Pilih kaedah penjejakan sinar yang jelas untuk kawalan optik yang disokong.",
"render.method_raster": "Raster CPU",
"render.navigation_help": "Kamera seperti Reka Bentuk (Tetapan › Navigasi). Simpan Persediaan merekod kamera semasa.",
"render.nested_enable": "Dielektrik bersarang yang disahkan",
"render.nested_help": "Sehingga 16 lapisan pengandung; setiap induk mestilah cembung dan setiap anak mestilah sepenuhnya di dalamnya. Persilangan, permukaan bersentuhan, kepingan nipis dan penghantaran sinar bayang lurus akan ditolak. Keadaan kamera di dalam mengikut hierarki yang disahkan. Tidak mencipta permukaan cecair atau menggabungkan sempadan CAD yang bersentuhan.",
"render.opaque_image_summary": "Pratonton PNG · PBR legap · ketelusan campuran",
"render.opaque_preview_help": "PBR legap dan warna ringkas; ketelusan campuran. Pembiasan, HDRI dan render akhir belum tersedia.",
"render.optics_remove": "Buang optik tersimpan",
"render.optics_replace": "Ganti optik tersimpan sasaran ini secara jelas",
"render.optics_save": "Simpan optik ini ke persediaan",
"render.optics_saved": "Sasaran optik tersimpan",
"render.optics_saved_help": "Identiti takrifan, ciri dan kejadian yang tepat kekal apabila dibuka semula di luar talian. Sasaran yang hilang/diganti/disembunyikan akan ditolak; bahan kejuruteraan tidak berubah. Simpan atau buang suntingan berangka sebelum membuang sasaran tersimpan.",
"render.outer_half_angle": "Separuh sudut luar",
"render.output_format_status": "PNG ialah imej paparan siap yang tepat. EXR GPU pilihan menyimpan radians FLOAT32 linear adegan yang mentah sebelum penapis paparan. Eksport tidak sekali-kali menggantikan cache pratonton atau tugas yang lain.",
"render.output_lock_ratio": "Kunci nisbah aspek",
"render.output_over_budget": "Imej yang diminta melebihi sampul sumber yang dipilih. Pilih saiz atau profil yang serasi secara jelas; tiada penurunan taraf automatik berlaku.",
"render.output_ratio_refused": "Dimensi terpaut melebihi had saiz kaedah ini. Saiz sebelumnya dikekalkan; buka kunci nisbah atau pilih nilai yang lebih kecil.",
"render.output_swap_orientation": "Tukar lebar dan ketinggian",
"render.output_tools_inspector": "Sunting saiz dan format dalam pemeriksa Keluaran.",
"render.page_aging": "Penuaan & pencemaran",
"render.page_all": "Semua kawalan",
"render.page_appearance": "Penampilan",
"render.page_background": "Latar belakang",
"render.page_camera": "Kamera",
"render.page_diagnostics": "Diagnostik",
"render.page_effects": "Kanta & kesan penamat",
"render.page_environment": "Persekitaran",
"render.page_lighting": "Pencahayaan",
"render.page_output": "Keluaran",
"render.page_scene": "Adegan",
"render.paint_label": "Cat",
"render.passive_stage": "Lantai dan pentas pasif",
"render.passive_stage_help": "Panel pasif terhingga hanya tergolong dalam imej yang dirender. Ia tidak menambah jasad CAD atau jisim. Penempatan menjadi tetap selepas digunakan; sempadan produk yang bersilang akan ditolak. CPU tidak menyediakan pencahayaan pantulan resap.",
"render.perspective": "Kamera perspektif",
"render.physical_acknowledge": "Saya faham rujukan separa ini memerlukan semakan gred, keadaan dan sumber",
"render.physical_associations": "Calon fizikal dan peranan",
"render.physical_background_help": "Lantai dan dinding pasif yang sebenar, berasingan daripada latar kamera. Siklorama menggunakan 24 jalur poligon; ia bukan permukaan tak terhingga atau licin secara analitik. Hanya menggantikan pentas render tersimpan dengan persetujuan anda.",
"render.physical_copy_plan": "Salin pelan dengan sumber dan peninggalan",
"render.physical_cyclorama": "Padankan siklorama poligon",
"render.physical_floor_wall": "Padankan lantai dan dinding fizikal",
"render.physical_material_name": "Nama bahan rujukan yang dicadangkan",
"render.physical_omissions": "Sifat yang tidak dapat diwakili dalam kad natif",
"render.physical_plan_only": "Pelan baca sahaja telah disediakan. Tiada bahan dicipta atau ditetapkan. Kekalkan profil lanjutan dan peninggalannya semasa menyemak kad natif.",
"render.physical_prepare_plan": "Sediakan pelan penciptaan (tidak dilaksanakan)",
"render.physical_separate": "Penampilan bukan pengenalpastian bahan. Ini ialah rujukan bersumber, bukan sifat berkesan yang disahkan. Jisim, bahan kejuruteraan dan optik sedia ada tidak berubah.",
"render.physical_unknown": "Tiada calon berangka ditetapkan. Gred, formulasi atau binaan mesti dinyatakan; nilai tidak diketahui bukan sifar.",
"render.pick_body": "Jasad",
"render.pick_component": "Komponen",
"render.pick_face": "Muka",
"render.pick_help": "Pilih Jasad, Muka atau Komponen. Klik ruang kosong untuk mengosongkan; Shift atau Ctrl menambah atau menogol. Serlahan hanya muncul dalam paparan produk langsung.",
"render.pick_label": "Pilih",
"render.pick_up_label": "Ambil",
"render.pick_waiting": "Pemilihan produk belum disokong.",
"render.post_contrast": "Kontras",
"render.post_gain_b": "Gandaan biru",
"render.post_gain_g": "Gandaan hijau",
"render.post_gain_r": "Gandaan merah",
"render.post_help": "Persembahan kreatif sahaja. Gandaan RGB mendahului pemetaan ton; kontras, ketepuan dan vinyet menyusul dalam cahaya linear paparan. Mula Render menjana sampel pengangkutan baharu. Gred semula warna menggunakan induk mentah yang dipilih dan disimpan, tanpa penyahdesauan atau sinar baharu.",
"render.post_reset": "Set semula penapis persembahan",
"render.post_saturation": "Ketepuan",
"render.post_title": "Penapis persembahan",
"render.post_vignette": "Vinyet",
"render.preview": "Pratonton bersepadu",
"render.preview_help": "Lorekan raster dan ketelusan campuran. Pembiasan, HDRI dan render akhir belum tersedia.",
"render.preview_image_settings_help": "Pratonton Langsung mengekalkan pencahayaan studio tetap. Pendedahan dan pencahayaan imej digunakan pada kerja imej apabila anda menekan Semak atau Mula.",
"render.preview_lighting_help": "Pratonton langsung hanya menunjukkan cahaya langsung dan tiada bayang.",
"render.preview_retry": "Cuba semula pratonton langsung",
"render.preview_unavailable_help": "Pratonton langsung tidak tersedia. Persediaan tersimpan dan kawalan kerja imej kekal boleh diakses. Ubah adegan atau cuba semula secara eksplisit; adegan yang ditolak tidak dibina semula pada setiap bingkai.",
"render.preview_upload": "Muatan bucu pratonton langsung",
"render.preview_upload_help": "Bait bucu pratonton yang tepat, bukan jumlah memori GPU atau proses. Geometri tidak dipermudah. Kerja imej menggunakan kebenaran kemasukan dan pencahayaan sendiri.",
"render.progressive_image_summary": "PNG pratonton · PBR dan kaca · sampel progresif",
"render.property_conditions": "Keadaan: {value}",
"render.property_fallback": "sifat",
"render.property_qualifier": "Kualifikasi: {value}",
"render.property_source": "Sumber: {id} - {locator}",
"render.property_uncertainty": "Ketidakpastian: {value}",
"render.property_unknown": "tidak diketahui",
"render.quality_ack": "Akui unjuran bajet tetap dan perkara yang ditinggalkan",
"render.quality_apply": "Gunakan bajet pensampelan tetap ini",
"render.quality_projection_help": "Pratetap Q merangkumi keperluan masa hadapan. Tindakan ini hanya mengunjurkan bajet PNG sampel tetap yang disokong dan dengan jelas mengabaikan penghentian adaptif, output linear mentah serta had transmisi bebas.",
"render.quality_review": "Tinjau bajet pensampelan",
"render.queue_pending": "Tiada baris gilir pengeluaran automatik atau enjin render animasi dalam UI ini. Imej pegun yang telah siap kekal boleh dieksport secara berasingan.",
"render.radial_distortion": "Herotan jejarian",
"render.regrade_action": "Gred semula warna induk mentah (tanpa penyahdesauan)",
"render.regrade_help": "Mencipta PNG berasingan daripada induk mentah siap yang dipilih, menggunakan kawalan persembahan ini. Tidak menjejak sinar, tidak mengubah saiz/kamera/lampu yang dirakam dan tidak menulis ganti EXR. Penyahdesauan tidak dikenakan semula: induk mentah tidak menyimpan panduannya. Terbitan ini kekal boleh dieksport melalui kawalan kerja yang sama.",
"render.regrade_label": "Gred semula warna",
"render.reload_settings": "Muat Semula Tetapan Tersimpan",
"render.replace_ground": "Sahkan penggantian pentas sedia ada",
"render.replace_label": "Ganti",
"render.replace_saved_surface": "Ganti pengikatan tersimpan sedia ada untuk sasaran ini",
"render.restore_camera": "Pulihkan Kamera Tersimpan",
"render.result_actual_help": "Satu piksel imej bagi setiap piksel paparan.",
"render.result_actual_size": "100%",
"render.result_capture": "Semakan dirakam",
"render.result_current": "Semakan model yang dirakam masih terkini.",
"render.result_empty": "Belum ada imej siap. Semak tetapan, kemudian mulakan render.",
"render.result_fit": "Muatkan Imej",
"render.result_job": "Kerja",
"render.result_navigation": "Sorot dan zum menggunakan keutamaan Navigasi. Space + seret untuk menyorot.",
"render.result_open": "Buka imej siap dalam kanvas utama.",
"render.result_preview": "Pratonton Langsung",
"render.result_provisional": "Imej CPU sementara",
"render.result_provisional_help": "Titik semak ini tidak boleh dieksport. Eksport mengekalkan hasil siap yang terakhir; pembatalan kembali kepada hasil itu.",
"render.result_reduced_display": "Pratonton paparan dikurangkan kepada had peranti/cache tetingkap pandang. PNG yang disimpan dan eksport mengekalkan resolusi penuh; pemeriksaan 100% asli tidak tersedia untuk paparan yang dikurangkan ini.",
"render.result_retained": "Memaparkan imej siap yang terakhir; render yang lebih baharu belum menggantikannya.",
"render.result_sequence": "Titik Semak",
"render.result_title": "Hasil Render",
"render.return_design": "Kembali ke Reka Bentuk",
"render.review_stale": "Tinjauan ini sudah lapuk. Selesaikan atau semak semula sebelum menggunakan.",
"render.ribbon_aging": "Penuaan",
"render.ribbon_backgrounds": "Latar Belakang",
"render.ribbon_check": "Semak",
"render.ribbon_check_help": "Sahkan draf semasa yang tepat yang akan dihantar oleh Render. Tiada enjin render sandaran, pengubahan saiz senyap atau penggantian sumber.",
"render.ribbon_edit_lights": "Sunting Lampu",
"render.ribbon_effects": "Kesan",
"render.ribbon_environment_help": "Pencahayaan HDR, latar belakang kamera sahaja dan permukaan pentas fizikal ialah kawalan berasingan dengan persetujuan penggantian yang jelas.",
"render.ribbon_finish_dialog": "Siapkan dahulu fail atau dialog pengesahan semasa.",
"render.ribbon_frame": "Bingkai",
"render.ribbon_hdr_library": "Koleksi HDR",
"render.ribbon_job_active": "Satu render sedang berjalan; batalkannya secara eksplisit sebelum memulakan yang lain.",
"render.ribbon_light_rigs": "Rig Lampu",
"render.ribbon_lights_help": "Periksa rig karangan atau sunting lampu yang disokong tanpa menggantikan persediaan semasa sehingga anda menggunakan perubahan itu secara eksplisit.",
"render.ribbon_materials": "Bahan",
"render.ribbon_materials_help": "Buka pemeriksa penampilan yang dikongsi dan koleksi permukaan asal. Suntingan optik tidak sekali-kali mengubah sifat kejuruteraan secara senyap.",
"render.ribbon_no_active_job": "Tiada render aktif untuk dibatalkan.",
"render.ribbon_no_result": "Siapkan render sebelum mengeksport imej tepatnya.",
"render.ribbon_no_saved_camera": "Simpan syot sebelum memulihkan kameranya.",
"render.ribbon_saved_camera": "Kamera Tersimpan",
"render.ribbon_shots": "Syot",
"render.ribbon_studios": "Studio",
"render.ribbon_studios_help": "Layari komposisi studio yang telah dilaksanakan dan tinjau penggantiannya sebelum menggunakan. Adegan konsep sahaja kekal berlabel.",
"render.ribbon_surface_maps": "Peta Permukaan",
"render.sampling_title": "Pensampelan adaptif dan transmisi",
"render.save_continue": "Simpan dan teruskan",
"render.save_setup": "Simpan Persediaan",
"render.save_shot": "Simpan Syot",
"render.saved_maps_runtime_conflict": "Pengikatan permukaan tersimpan tidak boleh dicampur dengan penggantian optik sementara atau HDR yang belum disimpan. Simpan HDR atau buang input sementara secara eksplisit.",
"render.saved_surface_remove": "Buang pengikatan tersimpan",
"render.saved_surfaces": "Pengikatan permukaan tersimpan",
"render.saved_surfaces_help": "Peta terbina dalam yang disemat mengikut kejadian yang dipilih dalam milimeter tempatan. Sasaran yang diganti atau hilang ialah ralat, bukan penugasan semula automatik.",
"render.scene_apply": "Gunakan studio yang ditinjau",
"render.scene_consent": "Sahkan penggantian pencahayaan, persekitaran, pendedahan dan pentas",
"render.scene_preserved_fields": "Kamera, pensampelan, dimensi, pengikatan optik, geometri CAD dan bahan kejuruteraan dikekalkan.",
"render.scene_preserves_design": "Menggubah pencahayaan dan pentas pasif untuk subjek yang kelihatan. Geometri, bahan kejuruteraan dan kamera kekal berasingan.",
"render.scene_replaces": "Menggantikan",
"render.scene_review": "Selesaikan dan tinjau",
"render.scene_review_help": "Tinjau komposisi natif yang lengkap sebelum menggunakan. Spesifikasi SCENE lanjutan yang tidak terikat tidak digantikan.",
"render.scene_scope_details": "Skop komposisi",
"render.setup_legacy_environment": "Persediaan lama ini menggunakan putaran atau keamatan persekitaran warisan. Nilai itu dikekalkan; tukarkannya secara eksplisit sebelum menyimpan kerja imej penuh.",
"render.setup_name": "Nama persediaan",
"render.setup_numeric_help": "Simpan merekodkan kaedah imej aktif dan semua tetapan angkanya. Muat semula atau memilih persediaan lain menggantikan draf ini; pulihkan kamera secara berasingan.",
"render.setup_offline_help": "Anda boleh menyunting dan menyimpan kaedah ini tanpa enjin rendernya. Semak dan Mula memerlukan hos yang tersedia.",
"render.setup_runtime_unsupported": "Kerja penuh ini belum boleh disimpan: ia mengandungi peta atau pengikatan jasad adegan. Buang input sementara itu sebelum menyimpan persediaan mudah alih.",
"render.setup_save_missing": "Konfigurasi render yang disimpan tidak ditemui selepas perintah selesai.",
"render.sharpening": "Penajaman perincian",
"render.shell_tab_appearance": "PENAMPILAN RENDER",
"render.shell_tab_camera": "KAMERA RENDER",
"render.shell_tab_scene": "ADEGAN RENDER",
"render.shot_duplicate": "Gandakan syot tersimpan",
"render.shot_manager": "Syot tersimpan",
"render.shot_new_name": "Nama syot baharu",
"render.shot_remove": "Buang syot tersimpan",
"render.shot_remove_help": "Buang persediaan tersimpan ini sahaja. Geometri sumber dan imej siap dikekalkan; tindakan ini boleh dibuat asal.",
"render.shot_remove_title": "Buang syot tersimpan?",
"render.shot_rename": "Tukar nama syot tersimpan",
"render.shot_saved_only": "Simpan draf semasa dahulu. Gandakan dan tukar nama mengekalkan pilihan tersimpan dan rujukan sumber dengan tepat.",
"render.show_shots_label": "Papar jalur Syot",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "HD Penuh",
"render.size_hd": "HD",
"render.sky_ground": "Tanah · RGB linear",
"render.sky_horizon": "Ufuk · RGB linear",
"render.sky_zenith": "Zenit · RGB linear",
"render.soft_focus": "Fokus lembut",
"render.spot_cone": "Kon lampu sorot",
"render.stage_frame": "Bingkai",
"render.stage_light": "Lampu",
"render.stage_look": "Gaya",
"render.stage_orthographic": "Ortografik",
"render.stage_output": "Keluaran",
"render.stage_panel_count": "Panel disimpan",
"render.stage_preview_note": "Pratonton bersepadu · cahaya langsung",
"render.strip_label": "Jalur",
"render.studio_add_area": "Tambah lampu kawasan",
"render.studio_ambient": "Radians persekitaran malar",
"render.studio_ambient_rgb": "Radians persekitaran malar (RGB linear)",
"render.studio_aperture": "Jejari apertur",
"render.studio_area": "Lampu kawasan",
"render.studio_area_help": "Sehingga empat segi empat tepat satu sisi. Separuh tepi ortogon U dan V menentukan saiz; U × V menghadap sisi yang diterangi. Koordinat ialah milimeter dalam ruang dunia.",
"render.studio_center": "Pusat X, Y, Z (mm)",
"render.studio_denoise": "Kurangkan hingar dalam imej siap",
"render.studio_denoise_help": "Penapis akhir yang peka tepi; butiran halus mungkin menjadi lembut. Kaca dan permukaan spekular tajam melangkau penapis ini.",
"render.studio_direction": "Arah menuju matahari (X, Y, Z)",
"render.studio_environment": "Persekitaran",
"render.studio_environment_bounds": "Putaran persekitaran mesti terhingga dalam lingkungan ±1,000,000 radian dan keamatan antara 0 dengan 100.",
"render.studio_environment_none": "Tiada peta persekitaran",
"render.studio_focus": "Jarak fokus paksi",
"render.studio_half_u": "Separuh tepi U (mm)",
"render.studio_half_v": "Separuh tepi V (mm)",
"render.studio_hdr": "Fail HDR Radiance",
"render.studio_hdr_browse": "Pilih HDR…",
"render.studio_hdr_help": "Radiance .hdr, panorama 2:1, sehingga 2048 × 1024. EXR tidak tersedia. Andaian warna hanya terpakai apabila warna primer tidak dinyatakan.",
"render.studio_hdr_required": "Pilih fail .hdr setempat.",
"render.studio_hdr_srgb": "Tafsirkan warna primer yang tidak dinyatakan sebagai sRGB linear",
"render.studio_intensity": "Keamatan persekitaran",
"render.studio_lens": "Kedalaman medan",
"render.studio_lens_perspective": "Kedalaman medan memerlukan kamera perspektif.",
"render.studio_lighting": "Pencahayaan studio",
"render.studio_lighting_enable": "Gunakan pencahayaan studio tersuai",
"render.studio_needs_review": "Semak kaedah dan tetapan",
"render.studio_radiance": "Radians RGB linear",
"render.studio_ready": "Sedia untuk disemak",
"render.studio_remove_area": "Buang lampu kawasan",
"render.studio_rotation": "Putaran persekitaran",
"render.studio_runtime_help": "Tetapan studio berangka dan sumber HDR yang telah disemak boleh disimpan bersama persediaan. Penggantian optik/bahan jasad kekal sementara dan tidak mengubah penampilan yang disimpan.",
"render.studio_saved": "Persediaan disimpan / kamera semasa",
"render.studio_sky": "Langit artistik",
"render.studio_sky_help": "Kecerunan langit asli untuk pencahayaan; bukan model atmosfera yang ditentukur.",
"render.studio_sun": "Matahari",
"render.studio_sun_radius": "Jejari sudut",
"render.studio_title": "Studio render",
"render.studio_tone_map": "Pemetaan ton",
"render.subsurface_enable": "Perjalanan rawak serakan dalaman",
"render.subsurface_help": "Dielektrik tertutup sahaja. Serakan dan penyerapan RGB ialah pekali berasingan per mm. Laluan menyerak dalam geometri sebenar, kemudian dibiaskan atau dipantulkan pada sempadan. Matikan penghantaran bayang lurus, pengurangan hingar permukaan dan isi padu luaran; gunakan satu stratum Fresnel. Bukan shader resapan, grid ketumpatan atau bahan yang diukur. Medium tumpat mungkin memerlukan lebih banyak sampel dan kedalaman laluan.",
"render.subsurface_rate": "Kadar perlanggaran serakan",
"render.tone_aces_fitted": "ACES dipadankan",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "Kaca GPU menyokong medium tak bersilang yang diperakui. Medium bersarang tanpa had dan penganggar penghantaran bebas hingar tidak disediakan.",
"render.transmission_strata": "Strata Fresnel bersyarat",
"render.transmission_strata_help": "1 mengekalkan strim asal. 2 atau 4 sublaluan menstratifikasi pilihan pantulan/penghantaran kaca pertama dengan hukum Snell dan penyerapan yang tidak berubah. Lebih banyak laluan memerlukan lebih banyak kerja; ini bukan pengurangan hingar, sokongan medium bersarang atau janji render yang lebih pantas.",
"render.tree_add_light": "Tambah lampu",
"render.tree_add_shot": "Tambah syot",
"render.tree_browser": "Pelayar Render",
"render.tree_by_look": "Mengikut gaya",
"render.tree_by_object": "Mengikut objek",
"render.tree_constant": "Persekitaran malar",
"render.tree_default": "Lalai",
"render.tree_directional": "Berarah",
"render.tree_environment": "Persekitaran",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} muka",
"render.tree_face_one": "{count} muka",
"render.tree_fixed_studio": "Studio tetap",
"render.tree_hdr": "HDR",
"render.tree_lights": "Lampu",
"render.tree_lights_pending": "Perintah lampu bernama belum tersedia.",
"render.tree_mixed": "Bercampur",
"render.tree_more": "{count} lagi",
"render.tree_mute": "Senyapkan lampu",
"render.tree_no_environment": "Tiada persekitaran",
"render.tree_objects": "Objek",
"render.tree_output": "Keluaran",
"render.tree_point": "Titik",
"render.tree_rectangle": "Segi empat tepat",
"render.tree_search": "Cari objek",
"render.tree_selection": "Pilihan render",
"render.tree_shots": "Syot",
"render.tree_sky": "Langit",
"render.tree_solo": "Lampu solo",
"render.tree_spot": "Lampu sorot",
"render.tree_sun": "Matahari",
"render.tree_switch": "Beralih",
"render.tree_user_one": "{count} objek",
"render.tree_users": "{count} objek",
"render.unavailable_preview": "Persediaan ini menggunakan profil pratonton yang tidak tersedia.",
"render.unsaved": "Perubahan pratonton belum disimpan",
"render.use_preview": "Gunakan Pratonton Bersepadu",
"render.volume_albedo": "Albedo serakan · RGB linear",
"render.volume_anisotropy": "Min kosinus fasa",
"render.volume_enable": "Aktifkan medium penyertaan",
"render.volume_extinction": "Pekali kepupusan",
"render.volume_help": "Pengangkutan GPU dalam satu kotak terhingga, dengan pelemahan Beer dan serakan HG pada laluan kamera dan laluan tak langsung. Menggunakan pencahayaan studio/HDR/langit eksplisit, termasuk pelemahan bayang. Kosinus fasa positif menyerak ke hadapan. Sempadan kaca dan pengurangan hingar permukaan mesti dimatikan secara eksplisit. Kepupusan sifar tidak mengubah pengangkutan. Bukan atmosfera bulan yang fizikal, grid ketumpatan, pancaran isi padu, pengangkutan spektrum atau sifat bahan yang diperakui.",
"render.volume_max": "Sempadan maksimum · mm dunia",
"render.volume_min": "Sempadan minimum · mm dunia",
"render.volume_title": "Isi padu homogen bersempadan",
"render.wait_batch": "belum disokong: baris gilir render syot yang disimpan",
"render.wait_compare": "belum disokong: perbandingan imej yang dikekalkan",
"render.wait_paint": "belum disokong: pemilihan produk dan pengecatan penampilan",
"render.wait_pick_up": "belum disokong: pemilihan produk dan pensampelan penampilan",
"render.wait_replace": "belum disokong: penggantian semua penggunaan sesuatu penampilan",
"render.wait_solo": "belum disokong: keterlihatan lampu dan kawalan solo",
"sample.bracket.about": "Bebibir asas dengan bebibir tepi dan kelim mengikut peraturan 2 mm",
"sample.bracket.name": "Pendakap Logam Kepingan",
"sample.enclosure.about": "Kotak berongga dengan bibir, bonggol skru, penyokong dan sambungan sentap",
+710
View File
@@ -37,6 +37,7 @@
"All open designs": "Alle åpne design",
"Allowed expressions, separated by semicolons": "Tillatte uttrykk, atskilt med semikolon",
"Also deletes": "Sletter også",
"Also place them from the origin (fully constrained)": "Plasser dem også fra origo (fullt bestemt)",
"Anchor": "Anker",
"Angle 2": "Vinkel 2",
"Angle Display": "Vinkelvisning",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Design du åpner eller lagrer, vises her.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Bestemmes av Til objekt. Velg Vinkel for å endre vinkelutstrekningen.",
"Diameter": "Diameter",
"Dimension new shapes": "Sett mål på nye figurer",
"Direction": "Retning",
"Discard": "Forkast",
"Distance": "Avstand",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Dra for å vri anlegget i trinn på 5°. Hold Alt eller Ctrl for å vri det fritt.",
"Drive Joint": "Driv ledd",
"Duration": "Varighet",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Hver ny figur får også mål fra skissens origo til ingenting av den er fritt. En figur som allerede er festet til origo eller til plassert geometri, får ingen.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Hver figur du tegner får alle målene sine i størrelsene du tegnet (inntastede verdier går foran). En størrelse skissen allerede bestemmer, utelates.",
"Edges": "Kanter",
"Edit": "Rediger",
"Edit Profile Sketch": "Rediger profilskisse",
@@ -1745,21 +1749,317 @@
"recovery.just_now": "nettopp",
"recovery.min_ago": "for {count} min siden",
"recovery.never_saved": "aldri lagret",
"render.adaptive_absolute": "Nedre grense for absolutt RGB-feil",
"render.adaptive_coverage": "Mål for dekningsfeil",
"render.adaptive_enable": "Fordel prøver med uavhengige pilotprøver",
"render.adaptive_help": "Kun GPU. Uavhengige pilotprøver forkastes, og deretter fordeles 16 eller flere produksjonsprøver per piksel, opptil Prøver per piksel. Varians i RGB og dekning styrer fordelingen. Sjeldne baner kan bli oversett, og piksler som har nådd taket kan fortsatt være støyende. Sluttrapporten teller faktisk utført arbeid. Ingen sertifisert garanti for støy eller tid.",
"render.adaptive_minimum": "Minimum produksjonsprøver",
"render.adaptive_pending": "Adaptiv GPU-fordeling med uavhengige piloter og betingede Fresnel-strata er tilgjengelig. Sertifisert konvergens, garantier for sjeldne hendelser og adaptiv CPU-transport er fortsatt utilgjengelig.",
"render.adaptive_pilots": "Pilotprøver per piksel",
"render.adaptive_relative": "Mål for relativ RGB-feil",
"render.add_ground": "Legg til tilpasset gulv i oppsettet",
"render.advanced_material_scope": "Ett endelig, homogent GPU-medium er tilgjengelig innenfor eksplisitte grenser. Tetthetsrutenett, nestede kombinasjoner av glass og volum, flater med underflatespredning, forskyvning, spektral transport og uknyttede avanserte materialkonsepter er fortsatt utilgjengelige.",
"render.aging_add": "Legg til aldringslag",
"render.aging_airborne": "Støv i luften / deltakende medium",
"render.aging_airborne_help": "Støv i luften er et eget endelig, homogent spredningsvolum. Det endrer transport og rå EXR, ikke stabelen for overflatealdring. Eksisterende begrensninger for volum, glass og støyfjerning gjelder fortsatt eksplisitt; ingen atmosfære legges til automatisk.",
"render.aging_all_bodies": "Alle kvalifiserte ugjennomsiktige kropper",
"render.aging_chips": "Avskallet maling",
"render.aging_class_any": "Alle ugjennomsiktige materialklasser",
"render.aging_class_dielectric": "Kun ikke-metalliske flater",
"render.aging_class_metal": "Kun metalliske flater",
"render.aging_color": "Lagfarge · sRGB",
"render.aging_coverage": "Dekning",
"render.aging_dust": "Avsatt støv",
"render.aging_empty": "Ingen aldringslag: de opprinnelige flatene forblir uendret.",
"render.aging_fading": "Falmet belegg",
"render.aging_grime": "Smuss og flekker",
"render.aging_help": "Kombiner opptil åtte optiske lag, i rekkefølge. Rust og patina er utformede utseender, ikke simuleringer av aldring eller korrosjon. Skalaen er i verdensmillimeter. Ingen geometri, masse eller teknisk egenskap endres; glass og passive dekor er utelatt.",
"render.aging_metallic": "Metallfraksjon for lag",
"render.aging_origin": "Feltets origo · mm i verden",
"render.aging_patina": "Kobbergrønn patina",
"render.aging_refresh_targets": "Inspiser gjeldende kropper",
"render.aging_roughness": "Ruhet for lag",
"render.aging_rust": "Oksidert jern / rust",
"render.aging_scale": "Mønsterskala",
"render.aging_scratches": "Fine riper",
"render.aging_target": "Mål og koordinater",
"render.aging_target_help": "Et navngitt mål må fortsatt samsvare med sin lagrede indeks og sitt navn. Globale masker er forankret i verden og følger ikke bevegelige deler. Dette er verken hulromsdeteksjon eller ekte kantslitasje. Filtrer listen for å nå flere kropper.",
"render.aging_target_search": "Filtrer kroppsnavn",
"render.aging_upward": "Avsetning på oppadvendte flater",
"render.all_controls_help": "Tett oversikt over alle gjeldende kontroller. Seksjonssidene gir fokusert redigering uten å endre den underliggende forespørselen.",
"render.all_shots_label": "Alle opptak",
"render.appearance_physics_separate": "Visuelt utseende tildeler ikke tetthet, termiske data eller andre tekniske egenskaper.",
"render.availability_native": "Innebygd sammensetning; gjennomgå før bruk",
"render.availability_projection": "Støttet projeksjon; se omfang og utelatelser",
"render.availability_reference": "Referansedata; ikke en automatisk tildeling",
"render.backdrop_alpha_conflict": "Velg enten dette bakteppet eller gjennomsiktig PNG-utdata; rendringsmotoren ignorerer ingen av innstillingene i det stille.",
"render.backdrop_enable": "Bruk gradientbakteppe kun for kameraet",
"render.backdrop_first": "Start-/midtfarge",
"render.backdrop_help": "Dette skjermromsbakteppet lyser ikke opp, kaster ikke skygger, reflekterer ikke og representerer ikke terreng. Det er utelatt fra rå EXR. Geometri, lys og HDR-omgivelsen forblir uavhengige.",
"render.backdrop_horizontal": "Horisontal gradient",
"render.backdrop_radial": "Radiell gradient",
"render.backdrop_radius": "Radius",
"render.backdrop_second": "Slutt-/kantfarge",
"render.backdrop_vertical": "Vertikal gradient",
"render.backdrop_x": "Senter X",
"render.backdrop_y": "Senter Y",
"render.background": "Scenebakgrunn",
"render.background_camera_section": "Kamerabakgrunn · PNG-presentasjon",
"render.background_completed_frozen": "Det viste resultatet er et fryst, ferdig bilde. Når du redigerer en bakgrunn, males ikke dette resultatet automatisk på nytt. Bruk Ny fargekorrigering for endringer som kun gjelder kameraet, eller Rendring for et nytt fysisk rendringsdekor.",
"render.background_hdr_separate": "De gjeldende HDR-ressursene lyser opp og reflekteres i flater, men vises ikke automatisk som et panorama bak motivet. Å endre en gradient roterer eller omfarger ikke belysningen.",
"render.background_lighting_section": "HDR-belysning · atskilt fra kamerabakgrunn",
"render.background_no_alpha_override": "En kamerabakgrunn legges ikke i det stille til gjennomsiktig utdata. Ny fargekorrigering av den rå masteren bruker lagret dekning og bruker ikke støyfjerning på nytt; kilde-EXR forblir uendret.",
"render.background_not_light": "Bakgrunnsfarge er presentasjon, ikke en ekstra lyskilde.",
"render.background_regrade": "Bruk på beholdt rå master",
"render.background_stage_occlusion": "Dette opptaket inneholder fysisk geometri fra rendringsdekoret. Et stort gulv eller en stor vegg kan fylle bildet og skjule en bakgrunn som kun gjelder kameraet. Fjern rendringsdekoret eller endre størrelsen på det bevisst, eller endre dens fysiske reflektans. Ny fargekorrigering kan ikke fjerne lagret geometri.",
"render.background_workflow": "Velg bakgrunnen du ønsker: en farge eller gradient kun for kameraet, et fysisk rendringsdekor som mottar lys, eller HDR-belysning. De er uavhengige. Direkte forhåndsvisning er en modelleringsvisning; rendre et nytt bilde eller fargekorriger en beholdt master på nytt for å se kameraets etterbehandling.",
"render.base_appearance": "Redigerbart kroppsutseende",
"render.base_apply": "Bruk kroppsutseende",
"render.base_apply_help": "Én visuell tildeling som kan angres, til den gjennomgåtte nøyaktige kroppen. Eksisterende flatespesifikke stiler og tekniske materialer forblir atskilt.",
"render.base_color": "Grunnfarge · sRGB",
"render.base_metallic": "Metallfraksjon",
"render.base_opaque_only": "Denne redigeringen bevarer semantikken for ugjennomsiktige kropper. Bruk de eksplisitte glasskontrollene for optisk transmisjon.",
"render.bloom_enable": "Vis bloom",
"render.bloom_help": "Kreativ glød kun i utdata, fra positive lineære høylys, spredt med tre normaliserte boksfilterpasseringer. Radius er i utdatapiksler. Legges til i lineært visningslys før sRGB; ikke en linse- eller volumeffekt eller en forbedring av konvergens. Rå EXR er uendret.",
"render.bloom_opaque": "Bloom krever ugjennomsiktig utdata. Gjennomsiktig PNG avvises og flates ikke ut i det stille.",
"render.bloom_radius": "Bloom-radius",
"render.bloom_strength": "Bloom-styrke",
"render.bloom_threshold": "Terskel for lineære høylys",
"render.browse_capabilities": "Inspiser hele katalogen over funksjoner",
"render.browse_environments": "Bla gjennom originale HDR-omgivelser",
"render.browse_native_scenes": "Bla gjennom innebygde studioer",
"render.browse_physical": "Inspiser fysiske referanser",
"render.browse_quality": "Inspiser kvalitetsspesifikasjoner",
"render.browse_rigs": "Bla gjennom utformede lysoppsett",
"render.browse_scene_specs": "Bla gjennom avanserte scenespesifikasjoner",
"render.browse_surfaces": "Bla gjennom utformede flater",
"render.browser_library": "Bibliotek",
"render.browser_model": "Modell",
"render.camera_distance": "Avstand fra øye til mål",
"render.camera_exact_help": "Verdensmillimeter; vinkler vises i grader og lagres som radianer. Navigasjonen bruker samme kamera som visningsvinduet.",
"render.camera_fov": "Vertikalt synsfelt",
"render.camera_pitch": "Kamerahelning",
"render.camera_roll": "Rull",
"render.camera_set": "Sett rendringskamera",
"render.camera_target": "Målposisjon · mm",
"render.camera_yaw": "Giring",
"render.chromatic_offset": "Kromatisk kantforskyvning",
"render.clear_stage": "Fjern lagret rendringsdekor",
"render.copy_request": "Kopier JSON",
"render.cpu_aa_help": "Romlige prøver: flere prøver forbedrer kanter og øker rendringstiden.",
"render.cpu_area_add": "Legg til rektangulært CPU-lys",
"render.cpu_area_editor": "Rektangulære CPU-lys",
"render.cpu_area_editor_help": "Fulle sidevektorer i millimeter; U kryss V peker mot den lysende siden. Dette skiller seg fra GPU-vektorer for halve kanter.",
"render.cpu_area_full_u": "Full U-side · mm",
"render.cpu_area_full_v": "Full V-side · mm",
"render.cpu_area_samples": "Prøver for arealys",
"render.cpu_binding_confirm": "Bekreft denne kroppen",
"render.cpu_binding_stale": "Scenen er endret. Bekreft dette refleksjonsmålet på nytt før rendring.",
"render.cpu_body_choose": "Velg en kropp",
"render.cpu_body_filter": "Filtrer kropper etter navn",
"render.cpu_body_filter_more": "Avgrens filteret for å se flere kropper.",
"render.cpu_body_missing": "Et refleksjonsmål mangler, er skjult, er flertydig eller har et navn som er lengre enn 128 byte. Velg det på nytt.",
"render.cpu_budget": "CPU-ressursprofil",
"render.cpu_budget_bodies": "Øvre grense for kropper",
"render.cpu_budget_compact": "Kompakt (eldre grenser)",
"render.cpu_budget_details": "Ressursgrenser",
"render.cpu_budget_help": "Velg større grenser eksplisitt. Oppløsning og prøver reduseres aldri automatisk.",
"render.cpu_budget_memory": "Øvre minnegrense for jobb",
"render.cpu_budget_not_guarantee": "Dette er grenser for å starte en jobb, ikke en RAM-reservasjon eller en hastighetsgaranti. Geometri, film og beholdte forhåndsvisninger deler minnebudsjettet; rendringen kan fortsatt avbrytes.",
"render.cpu_budget_resize": "Utkastet overstiger denne CPU-profilen eller budsjettet for kameraprøver. Godta mindre dimensjoner eksplisitt, eller velg en større profil.",
"render.cpu_budget_studio": "Studio (store bilder)",
"render.cpu_budget_triangles": "Øvre grense for trekanter",
"render.cpu_budget_workstation": "Arbeidsstasjon (tunge scener)",
"render.cpu_captured_hdr": "HDR lagret for dette bildet",
"render.cpu_check_capture_help": "Sjekk og Start verifiserer samme filsjekksum eller bruker den innebygde HDR-en. Hvert bilde beholder sin lagrede kilde.",
"render.cpu_check_changed": "Kontrollene eller modellen ble endret etter denne sjekken. Sjekk på nytt før rendring.",
"render.cpu_constant_help": "Konstant strålingstetthet er synlig for reflekterte eller transmitterte stråler. Den gir ikke direkte diffus belysning.",
"render.cpu_custom_directions": "Erstatt forhåndsinnstillingen med egendefinerte retningslys",
"render.cpu_direction": "Retning mot lyset (X, Y, Z)",
"render.cpu_directional": "Retningslys",
"render.cpu_directional_add": "Legg til retningslys",
"render.cpu_environment": "CPU-omgivelse",
"render.cpu_environment_background": "Bildebakgrunnen er adskilt fra omgivelsesbelysningen.",
"render.cpu_environment_bounds": "CPU-intensiteten må være 0–64, HDR-rotasjonen et endelig tall innenfor ±1 000 000 radianer, og HDR-prøver 1, 4, 16 eller 64.",
"render.cpu_environment_constant": "Konstant omgivelse for sekundærstråler",
"render.cpu_environment_none": "Ingen CPU-omgivelse",
"render.cpu_environment_samples": "Prøver for HDR-belysning",
"render.cpu_exposure_help": "CPU-eksponeringen må ligge mellom −16 og 16 EV. En GPU-eksponering utenfor dette området beholdes til du endrer den.",
"render.cpu_fixed": "Enkeltbilde",
"render.cpu_hdr_help": "Radiance .hdr, 2:1-panorama, opptil 2048 × 1024 og 16 MiB. CPU krever eksplisitte sRGB/D65-primærfarger i filen; uspesifiserte primærfarger og EXR avvises.",
"render.cpu_hdr_reflection_help": "Grove HDR-refleksjoner krever helmetalliske overflater på kropper og flater. Sjekk melder om kombinasjoner som ikke støttes.",
"render.cpu_key_rim": "Hovedlys og kantlys",
"render.cpu_last_check": "Siste CPU-sjekk",
"render.cpu_light_help": "Opptil åtte retningslys. En tom egendefinert liste slår dem av; når du velger en forhåndsinnstilling, gjenopprettes lysene. Farger er lineær RGB, og intensiteten er relativ, ikke watt.",
"render.cpu_light_intensity": "Relativ intensitet (0–64)",
"render.cpu_light_minimum": "Minimumsavstand for demping",
"render.cpu_light_position": "Posisjon i verden (X, Y, Z)",
"render.cpu_light_reference": "Referanseavstand for intensitet",
"render.cpu_light_remove": "Fjern lys",
"render.cpu_lighting": "Forhåndsinnstilling for belysning",
"render.cpu_lights": "CPU-lys",
"render.cpu_linear_color": "Lineær farge (R, G, B)",
"render.cpu_neutral": "Nøytral",
"render.cpu_opaque_required": "CPU-strålesporing krever en ugjennomsiktig bakgrunn. Fjern avmerkingen for «Gjennomsiktig bakgrunn» for å fortsette.",
"render.cpu_options_pending": "Dette CPU-panelet kan ennå ikke redigere emisjon, overflateeffekter, glass eller anisotropi. Fjern disse API-alternativene før du bruker det.",
"render.cpu_point": "Punktlys",
"render.cpu_point_add": "Legg til punktlys",
"render.cpu_point_help": "Opptil åtte punktlys, lagt til i den valgte retningsbelysningen. Avstander er i mm; minimumsavstanden må ikke overstige referanseavstanden.",
"render.cpu_primary_samples": "Kantprøver per piksel",
"render.cpu_progressive": "Progressiv CPU",
"render.cpu_progressive_help": "Akkumuler den eksisterende CPU-integratoren i omganger på én primærprøve. Valgte refleksjoner krever én prøve; arealys, dielektriske materialer og anisotropi krever Enkeltbilde.",
"render.cpu_progressive_limits": "Maksimalt 1 048 576 piksler og 16 777 216 evalueringer av piksel × prøve. Endring av antall prøver endrer aldri bildestørrelsen automatisk.",
"render.cpu_progressive_seed": "Startverdi for CPU-prøvetaking",
"render.cpu_progressive_spp": "prøver per piksel",
"render.cpu_reflection_add": "Legg til grov refleksjon",
"render.cpu_reflection_depth": "Refleksjonsdybde (1–8)",
"render.cpu_reflection_empty": "Ingen kropper valgt: scenerefleksjoner er av.",
"render.cpu_reflection_help": "Velg kropper og still inn Av, Speil eller Grov. Grov bruker den tildelte overflateruheten. Flere prøver og sprett øker tiden; dette er begrenset spekulær lystransport, ikke global belysning.",
"render.cpu_reflection_limit": "Opptil 64 reflekterte kropper støttes.",
"render.cpu_reflection_mirror": "Speil",
"render.cpu_reflection_off": "Av",
"render.cpu_reflection_rough": "Grov",
"render.cpu_reflection_samples": "Refleksjonsprøver (1–64)",
"render.cpu_reflections": "CPU-refleksjoner",
"render.cpu_runtime_help": "Numeriske lys- og omgivelsesinnstillinger lagres sammen med oppsettet. Kroppsrefleksjoner og HDR-filer er fortsatt midlertidige. Eksisterende verdier for arealys og spotlyskjegle beholdes.",
"render.cpu_sampling_mode": "CPU-prøvetakingsmodus",
"render.cpu_shadows": "Kast skygger",
"render.cpu_summary": "CPU-strålesporing · refleksjoner · HDR · retningslys og punktlys",
"render.cpu_warm_cool": "Varm og kald",
"render.diag_bodies": "Synlige kropper",
"render.diag_job_details": "Detaljer om lagret jobb",
"render.diag_last_check": "Siste forhåndssjekk",
"render.diag_memory": "Logisk estimat for godkjenning",
"render.diag_not_implemented": "Eksplisitte funksjonsgrenser",
"render.diag_preflight_details": "Detaljer om forhåndssjekk",
"render.diag_request": "Nøyaktig gjeldende forespørsel",
"render.diag_triangles": "Trekanter",
"render.discard_continue": "Forkast utkast og fortsett",
"render.draft_confirm_help": "Det gjeldende rendringsutkastet har endringer som ikke er brukt. Lagre dem før du bytter, forkast dem uttrykkelig, eller fortsett å redigere.",
"render.draft_confirm_title": "Behold redigerte rendringsinnstillinger",
"render.effects_gpu_only": "Disse effektene krever GPU-path tracing. Når du bytter side, byttes rendringsmotoren aldri automatisk.",
"render.effects_help": "Kombiner fargestiler i bestemt rekkefølge og linseeffekter i bildeplanet. Rendring og ny fargekorrigering av råmasteren bruker de samme lagrede innstillingene. Rå EXR forblir uendret. Dette er originale kunstneriske kontroller, ikke kalibrerte emuleringer av bestemte linser eller filmmerker.",
"render.effects_reset_lens": "Tilbakestill linseeffekter",
"render.effects_seed": "Startverdi for mønster",
"render.emitted_axis": "Emisjonsakse",
"render.error_area_samples": "area_samples må være 1, 4, 16 eller 64",
"render.error_binding_allocation": "kunne ikke reservere materialbinding",
"render.error_body_bound": "produktforhåndsvisningen overskrider grensen for lagrede kropper",
"render.error_checkpoint_dimensions": "sjekkpunktets dimensjoner avviker fra den lagrede forespørselen",
"render.error_decode_budget": "overskridelse av budsjettet for bildedekoding",
"render.error_denoise_setting": "ugyldig innebygd innstilling for støyfjerning",
"render.error_display_dimensions": "ugyldige visningsdimensjoner for bildet",
"render.error_display_fit": "bildevisningen får ikke plass på denne enheten",
"render.error_display_height": "overflyt i visningshøyden",
"render.error_display_width": "overflyt i visningsbredden",
"render.error_duplicate_face": "duplisert produktflateutseende",
"render.error_export_document": "Dokumentet for rendringseksporten ble endret mens målet ble valgt",
"render.error_face_cap": "produktforhåndsvisningen overskrider godkjenningsgrensen for flateutseender",
"render.error_finish_gesture": "fullfør modelleringsbevegelsen før forhåndsvisning",
"render.error_finish_operation": "fullfør den pågående modelleringsoperasjonen før du går til Rendring",
"render.error_fixed_preview": "fast Studio-forhåndsvisning krever eksponering 0, omgivelsesrotasjon 0 og intensitet 1",
"render.error_geometry_size": "overflyt i størrelsen på produktgeometrien",
"render.error_glass_recipe": "ukjent glassoppskrift",
"render.error_gpu_preview": "GPU-produktforhåndsvisning er ikke tilgjengelig på denne verten. Lagrede oppsett er fortsatt tilgjengelige.",
"render.error_gpu_samples": "antall GPU-prøver støttes ikke",
"render.error_image_dimensions": "dimensjonene på rendringsbildet samsvarer ikke med jobben",
"render.error_image_profile": "rendringsbildet overskrider den lagrede ressursprofilen",
"render.error_interactive_command": "ubundet interaktiv Rendring-kommando",
"render.error_job_action": "ikke en interaktiv handling for bildejobb",
"render.error_job_identity": "ugyldig identitet for rendringsjobb: {error}",
"render.error_library_reply": "ugyldig svar fra rendringsbiblioteket",
"render.error_material_binding": "manglende materialbinding",
"render.error_no_completed_image": "rendringen har ikke noe fullført bilde",
"render.error_no_geometry": "ingen produktgeometri",
"render.error_no_scene": "ingen produktscene",
"render.error_opacity": "ugyldig opasitet for produktutseende",
"render.error_pbr_opacity": "ugjennomsiktig PBR krever opasitet 1",
"render.error_physical_glass": "den valgte oppskriften er ikke fysisk glass",
"render.error_preview_device": "produktforhåndsvisning krever en installert enhet med dybdebuffer",
"render.error_product_triangle": "ugyldig produkttrekant",
"render.error_provisional_identity": "ugyldig midlertidig rendringsidentitet eller ugyldig antall prøver",
"render.error_quality_bounds": "kvalitetsprojeksjonen overskrider de innebygde grensene",
"render.error_quality_method": "kvalitetsprojeksjonen krever den samme eksplisitte GPU-metoden",
"render.error_quality_projection": "ugyldig innebygd kvalitetsprojeksjon",
"render.error_regrade_identity": "ugyldig identitet for ny fargekorrigering: {error}",
"render.error_scene_bodies": "manglende kropper i rendringsscenen",
"render.error_scene_body_limit": "rendringsscenen overskrider kroppsgrensen",
"render.error_scene_identity": "ugyldig identitet for rendringsscenen",
"render.error_setup_panicked": "initialiseringen av GPU-path traceren krasjet",
"render.error_setup_stopped": "arbeidstråden for initialisering stoppet uten å returnere en vert",
"render.error_setup_worker": "kunne ikke starte arbeidstråd for initialisering: {error}",
"render.error_source_preview": "kildeforhåndsvisningen overskrider bytegrensen",
"render.error_surface_normals": "PBR krever overflatenormaler som ikke er null",
"render.error_surface_reply": "ugyldig svar for medfølgende overflate",
"render.error_triangle_bound": "produktforhåndsvisningen overskrider kildegrensen på åtte millioner trekanter",
"render.error_triangle_count": "overflyt i antall produkttrekanter",
"render.error_upload_slot": "opplastingsspor for produktforhåndsvisning er ikke tilgjengelig",
"render.error_vertex_allocation": "tildeling av hjørner for produktforhåndsvisningen mislyktes",
"render.error_vertex_envelope": "produktforhåndsvisningen overskrider rammen på {limit} MiB for hjørnedata; geometrien ble ikke forenklet",
"render.error_vertex_packing": "pakkingen av produktforhåndsvisningen avviker fra de godkjente hjørnedataene",
"render.error_visible_solid": "Opprett en synlig volumkropp i Design for å forhåndsvise den her.",
"render.exit_focus": "Avslutt fokus",
"render.export_display": "Eksporter: PNG for visning",
"render.export_image_label": "Eksporter bilde",
"render.export_linear": "Eksporter: rå lineær EXR",
"render.exr_pending": "GPU-en kan beholde rå lineær EXR. Komprimering, flerlagsbilder og ekstra rendringspass er fortsatt utilgjengelige.",
"render.film_grain": "Fotografisk korn",
"render.fit": "Tilpass produkt",
"render.fixed_camera": "Kamera",
"render.fixed_world": "Verden",
"render.flare_ghosts": "Spøkelsesringer per kilde",
"render.flare_halo": "Halo for linseflekk",
"render.flare_streak": "Strek i anamorfisk stil",
"render.flare_strength": "Styrke på linseflekk i høylys",
"render.flare_threshold": "Terskel for linseflekk (scenelineær)",
"render.fold_browser": "Brett sammen modelltreet",
"render.gpu_depth": "Maksimal banedybde",
"render.gpu_options_help": "Prøver, dybde, startverdi og eksponering lagres med dette oppsettet. Bare den aktive bildemetoden lagres.",
"render.gpu_path_failed": "GPU-banesporing er ikke tilgjengelig",
"render.gpu_path_first_setup": "Det første oppsettet på denne GPU-en kan ta flere minutter; SolidCraft kan brukes som vanlig i mellomtiden. Senere starter gjenbruker de kompilerte shaderne der driveren beholder dem.",
"render.gpu_path_preparing": "GPU-banesporing: kompilerer shadere…",
"render.gpu_seed": "Tilfeldig startverdi",
"render.gpu_unavailable": "GPU-banesporing er ikke klar på denne enheten.",
"render.ground_apply": "Tilpass og lagre gulv",
"render.ground_gap": "Eksplisitt klaring",
"render.ground_linear_rgb": "Diffus reflektans · lineær RGB",
"render.ground_margin": "Marg for gulvutstrekning",
"render.hdr_details": "Detaljer om HDR-kilden",
"render.hdr_embedded": "HDR lagret i dette designet",
"render.hdr_embedded_help": "Rendringen bruker bytene som er inkludert i designet; den opprinnelige filen trengs ikke lenger.",
"render.hdr_file_captured": "HDR-filen er sjekket. Lagring bygger inn disse bytene; hvis filen endres, må du sjekke den på nytt eksplisitt.",
"render.hdr_inspect": "Sjekk HDR-fil",
"render.hdr_inspect_required": "Velg og sjekk en HDR-fil før du lagrer eller rendrer.",
"render.hdr_primaries_declared": "Kilden oppgir fargeprimærene sine.",
"render.hdr_primaries_srgb": "Fargeprimærer: sRGB/D65",
"render.hdr_primaries_undeclared": "Kilden oppgir ikke fargeprimærer; se gjennom fargekravene til rendringsmotoren.",
"render.hdr_resource_missing": "Dette designet mangler den lagrede HDR-ressursen.",
"render.heading_batch": "SERIE",
"render.heading_frame": "BILDERUTE",
"render.heading_lens": "LINSE",
"render.heading_results": "RESULTATER",
"render.heading_shots": "OPPTAK",
"render.hide_shots_label": "Skjul opptaksstripen",
"render.image_advanced": "Avanserte GPU-innstillinger",
"render.image_cancelled": "Rendring avbrutt",
"render.image_cancelling": "Avbryter",
"render.image_completed": "Bilde klart til eksport",
"render.image_encoding": "Koder PNG",
"render.image_export": "Eksporter PNG",
"render.image_exposure": "Eksponering",
"render.image_failed": "Rendring mislyktes",
"render.image_height": "Høyde",
"render.image_help": "CPU-forhåndsvisningsbilde · PNG · omtrentlig transparens",
"render.image_host_missing": "Ingen bildemotor er installert.",
"render.image_method": "Bildemetode",
"render.image_overwrite": "Erstatt eksisterende fil",
"render.image_preparing": "Forbereder bilde",
"render.image_progressive": "Progressiv rendring",
"render.image_queued": "Venter på å rendre",
"render.image_reduce": "Prøv et mindre bilde eller en enklere scene.",
"render.image_running": "Rendrer bilde",
"render.image_samples": "Prøver per piksel",
"render.image_scene_stale": "Fullfør modelleringsbevegelsen eller oppdater scenen før du sjekker eller starter et bilde.",
"render.image_stale": "Bildet viser scenen slik den var da rendringen startet. Senere endringer er ikke med.",
"render.image_start": "Start rendring",
"render.image_supported": "Rendringsforespørselen støttes. Visningen og tilgjengelig minne kontrolleres på nytt ved start.",
@@ -1769,20 +2069,430 @@
"render.image_unknown": "Rendringsstatus utilgjengelig",
"render.image_use_largest": "Bruk største størrelse for dette sideforholdet:",
"render.image_width": "Bredde",
"render.include_rig_cards": "Ta med passive kort og flagg",
"render.inner_half_angle": "Indre halvvinkel",
"render.inspect_scene": "Oppdater sammendraget av den fangede scenen",
"render.inspector": "Inspektør",
"render.keep_editing": "Fortsett redigering",
"render.layer_down": "Flytt ned",
"render.layer_enabled": "Lag aktivert",
"render.layer_off_suffix": " (av)",
"render.layer_remove": "Fjern lag",
"render.layer_strength": "Lagstyrke",
"render.layer_up": "Flytt opp",
"render.lens_effects_help": "Linseflekk bruker opptil fire adskilte lyse kilder i det faktiske lineære bildet. Spøkelsesringer, halo, striper, kromatiske forskyvninger og radial forvrengning er kunstneriske tilnærminger i bilderommet. Romlige effekter krever ugjennomsiktig utdata; prøver utenfor kanten utvider bildekanten. Korn er deterministisk. Ingen fysikk, EXR eller geometri endres.",
"render.lens_effects_title": "Linseinspirert og fotografisk",
"render.library_all": "Katalog",
"render.library_all_states": "Alle tilgjengelighetsstatuser",
"render.library_applied": "Ressursprojeksjonen er brukt. Sjekk hele rendringsforespørselen før du starter.",
"render.library_apply_hdr": "Lagre med denne HDR-omgivelsen",
"render.library_apply_maps": "Bruk medfølgende GPU-overflatekart",
"render.library_apply_studio": "Lagre medfølgende studioprojeksjon",
"render.library_apply_uniform": "Bruk ensartet, ugjennomsiktig utseende",
"render.library_authored_help": "Originale medfølgende ressurser er illustrative, ikke målte tekniske data. Hver handling bruker bare den oppgitte projeksjonen.",
"render.library_blocked": "Blokkert / krever kalibrering",
"render.library_capabilities": "Kapabilitetsspesifikasjoner",
"render.library_center": "Riggens senter",
"render.library_clear_search": "Tøm",
"render.library_details": "Spesifikasjon og opphav",
"render.library_emitters_only_ack": "Bruk bare lyskilder; utelat de dokumenterte passive kortene",
"render.library_empty": "Ingen samsvarende ressurser. Prøv et annet søk eller et annet tilgjengelighetsfilter.",
"render.library_environment_concepts": "Omgivelseskonsepter",
"render.library_extent": "Motivets utstrekning",
"render.library_favorite": "Legg til favoritt",
"render.library_favorites": "Favoritter",
"render.library_hdr": "Innebygde HDR-omgivelser",
"render.library_hdr_help": "Bygger den opprinnelige HDR-en inn i det lagrede oppsettet. Den medfølgende lengdegradsopprinnelsen konverteres eksplisitt; ingen ekstern fil trengs etter lagring.",
"render.library_inspect_only": "Velg for å inspisere; ingenting brukes automatisk. Favoritter og nylige valg hører til denne åpne dokumentøkten.",
"render.library_light_concepts": "Lyskonsepter",
"render.library_maps_help": "Innebygde kart kan lagres med festede kilder og lokal tilordning per forekomst. Midlertidige optiske overstyringer er fortsatt en egen modus.",
"render.library_material_concepts": "Materialkonsepter",
"render.library_native_scenes": "Innebygde studioer",
"render.library_next": "Neste side",
"render.library_omitted": "Ikke inkludert",
"render.library_physical_profiles": "Fysiske referanseprofiler",
"render.library_previous": "Forrige side",
"render.library_quality_concepts": "Kvalitetsspesifikasjoner",
"render.library_recent": "Nylige",
"render.library_replace_environment": "Erstatt den eksisterende omgivelsen eksplisitt",
"render.library_replace_studio": "Erstatt lagret belysning, omgivelse og rendringsdekor",
"render.library_results": "Samsvarende ressurser",
"render.library_rig_help": "Tilpass én gang med eksplisitt senter og fysisk utstrekning. Komplette rigger inkluderer passive kort; kalibreringshindringer avviser fortsatt. Konservativ klaring mellom lyskilder og kort sjekkes før lagring.",
"render.library_rigs": "Medfølgende lysrigger",
"render.library_save_maps": "Lagre kart i dette oppsettet",
"render.library_scene_bounds": "Bruk grensene til den fangede scenen",
"render.library_scenes": "Scenespesifikasjoner",
"render.library_search": "Søk i biblioteket",
"render.library_select_hint": "Velg en ressurs i biblioteket for å se hvilke handlinger og begrensninger den har.",
"render.library_selene": "Ugjennomsiktige SELENE-utseender",
"render.library_selene_shots": "SELENE-opptaksspesifikasjoner",
"render.library_short_blocked": "Utilgjengelig",
"render.library_short_native": "Innebygd komposisjon",
"render.library_short_projection": "Støttet projeksjon",
"render.library_short_reference": "Bare referanse",
"render.library_short_specification": "Bare spesifikasjon",
"render.library_source_preview": "Last inn forhåndsvisning av kildekart",
"render.library_source_preview_help": "Medfølgende basisfargekart. Dette er ikke en rendret eller målt materialforhåndsvisning.",
"render.library_specification_only": "Kun spesifikasjon: ikke en komplett kjørbar forhåndsinnstilling. Nødvendige effekter, ressurser og motivroller må fortsatt implementeres og bindes eksplisitt.",
"render.library_specs": "Kun spesifikasjoner",
"render.library_status": "Tilgjengelighet",
"render.library_surfaces": "Håndlagde PBR-overflater",
"render.library_target": "Målkropp",
"render.library_title": "Bibliotek for rendringsressurser",
"render.library_unfavorite": "Fjern favoritt",
"render.library_uniform_ack": "Bruk den ensartede tilnærmingen uten romlige eller avanserte effekter",
"render.library_usable": "Kjørbare projeksjoner",
"render.light_anchor_pending": "Det er ikke støttet ennå å endre lysets koordinatsystem.",
"render.lights_fixed_to": "Lys festet til",
"render.linear_help": "Beholder en RGBA-master med 32-biters flyttall før støyreduksjon, eksponering, tonekartlegging, filtre og bakgrunn. Lineær sRGB/D65; dekningsforhåndsmultiplisert. Ekstra minne tillates eksplisitt. Ingen komprimering eller ekstra pass.",
"render.linear_retain": "Behold rå lineær EXR",
"render.linear_unavailable": "Det valgte ferdige bildet har ingen beholdt EXR. Aktiver beholdning før rendring; en eldre PNG kan ikke gjenskape rå radians.",
"render.look_add": "Legg til fargestil",
"render.look_bleach": "Inspirert av bleach bypass",
"render.look_cool": "Kjølig",
"render.look_cyanotype": "Inspirert av cyanotypi",
"render.look_faded": "Falmet trykk",
"render.look_mono": "Monokrom",
"render.look_sepia": "Sepia",
"render.look_strength": "Stilstyrke",
"render.look_teal_orange": "Blågrønn / oransje",
"render.look_title": "Kreativ stilstabel",
"render.look_warm": "Varm",
"render.mapping_scale": "Multiplikator for fysisk gjentakelse",
"render.material_absorption": "Absorpsjon R · G · B (per mm)",
"render.material_add": "Legg til eller rediger denne kroppen",
"render.material_assignments": "Kroppstilordninger",
"render.material_binding_enable": "Ta med denne kroppsoverstyringen",
"render.material_box": "Akseparallell boks",
"render.material_browse": "Velg bilde…",
"render.material_certification": "Lukket glass bruker geometrisk avstand. Topologi, orientering, overlapp og optiske grenser kontrolleres under GPU-forberedelsen; Sjekk godtar bare forespørselen.",
"render.material_choose_body": "Velg en kropp i scenen",
"render.material_closed": "Lukket volumnett",
"render.material_coat": "Klarlakk over grunnmaterialet",
"render.material_coat_enable": "Aktiver klarlakk",
"render.material_coat_help": "Illustrativt dielektrisk belegg over det eksisterende ugjennomsiktige utseendet. Vekt null lar grunnmaterialet være uendret.",
"render.material_color_map": "Bilde for grunnfarge (sRGB)",
"render.material_color_replace": "Grunnkartet erstatter kroppsfargen",
"render.material_custom": "Egendefinert illustrativ optikk",
"render.material_enable": "Bruk disse GPU-materialoverstyringene",
"render.material_filter": "Filtrer kropper i scenen…",
"render.material_filter_help": "Opptil 128 samsvarende kropper vises. Avgrens filteret for store scener.",
"render.material_glass": "Glass og optisk absorpsjon",
"render.material_glass_enable": "Bruk fysisk glass på denne kroppen",
"render.material_glass_exclusive": "Glass kan ikke ligge på samme kropp som klarlakk eller kjøretidskart i denne rendringsmotoren.",
"render.material_glass_help": "Originale illustrative oppskrifter. Fargeprøvene viser transmittans, ikke en rendret forhåndsvisning. Absorpsjon er −ln(lineær transmittans) / referanseavstand; alfa er uendret.",
"render.material_gpu_required": "Disse aktive materialoverstyringene krever GPU-banesporing. Velg GPU eller deaktiver overstyringene før Sjekk eller Start.",
"render.material_ior": "Brytningsindeks (IOR)",
"render.material_limits": "Høyst 128 kroppsoverstyringer, 32 adskilte glasskropper, 64 lakklag og 128 teksturbindinger. Identiske kart deler lagring; de faktiske grensene for enhet og totalt minne gjelder fortsatt.",
"render.material_map_invalid": "Filbaner til kart må være begrensede lokale baner; normalstyrken må være endelig og mellom 0 og 1.",
"render.material_map_required": "Velg et fargebilde eller et normalbilde før du bruker kart.",
"render.material_maps": "Plane farge- og normalkart",
"render.material_maps_enable": "Aktiver kart for denne ugjennomsiktige kroppen",
"render.material_maps_help": "PNG/JPEG opptil 1024×1024; 16 MiB kodet totalt. U og V er ortogonale gjentakelsesvektorer i verdens-mm (maksimalt 128 gjentakelser). Farge er sRGB; normaldata bruker OpenGL +Y. Filene hentes inn ved Sjekk/Start.",
"render.material_metallic_map": "Metallkart (lineært)",
"render.material_normal_map": "Normalbilde (OpenGL, +Y)",
"render.material_normal_strength": "Normalstyrke (0–1)",
"render.material_origin": "Kartleggingens origo X · Y · Z (mm)",
"render.material_refresh": "Oppdater kropper i scenen",
"render.material_refresh_needed": "Scenen er endret. Oppdater kroppslisten før du legger til et mål.",
"render.material_remove": "Fjern denne tilordningen",
"render.material_repeat_u": "Én U-gjentakelse X · Y · Z (mm)",
"render.material_repeat_v": "Én V-gjentakelse X · Y · Z (mm)",
"render.material_revalidate": "Valider denne kroppen på nytt",
"render.material_revalidate_needed": "Denne tilordningen hører til en tidligere scenerevisjon. Valider kroppens nøyaktige identitet på nytt før rendring.",
"render.material_roughness": "Lakkens ruhet (0,045–1)",
"render.material_roughness_map": "Ruhetskart (lineært)",
"render.material_shadow": "Slipp rette skyggestråler gjennom",
"render.material_target_missing": "Kroppens ordenstall og navn stemmer ikke lenger overens. Fjern denne tilordningen og velg den tiltenkte kroppen på nytt.",
"render.material_thickness": "Tykkelse for tynt ark (mm)",
"render.material_thin": "Tynt ark",
"render.material_title": "GPU-bildematerialer",
"render.material_transient": "Midlertidige optiske overstyringer for denne dokumentfanen. De lagres ikke i designet, rendringsoppsettet eller materialbiblioteket.",
"render.material_v_up": "Tekstur-V peker oppover i bildet",
"render.material_weight": "Lakkens vekt (0–1)",
"render.method_cpu": "CPU-strålesporing",
"render.method_gpu": "GPU-banesporing",
"render.method_limit_raster": "Raster bruker den faste, ugjennomsiktige studioforhåndsvisningen. Velg en eksplisitt strålesporingsmetode for støttede optiske kontroller.",
"render.method_raster": "CPU-raster",
"render.navigation_help": "Kameraet beveger seg som i Design (Innstillinger › Navigasjon). Lagre oppsett registrerer gjeldende kamera.",
"render.nested_enable": "Sertifiserte nestede dielektrika",
"render.nested_help": "Opptil 16 omsluttende lag; hver forelder må være konveks og hvert barn må ligge strengt innenfor. Skjæringer, berørende flater, tynne ark og gjennomslipp av rette skygger avvises. Tilstanden med kameraet inni følger det sertifiserte hierarkiet. Oppretter ikke en væskeoverflate og slår ikke sammen berørende CAD-grenser.",
"render.opaque_image_summary": "Forhåndsvisnings-PNG · ugjennomsiktig PBR · blandet transparens",
"render.opaque_preview_help": "Ugjennomsiktig PBR og enkle farger, med blandet transparens. Lysbrytning, HDRI og sluttrendring er ikke tilgjengelig ennå.",
"render.optics_remove": "Fjern lagret optikk",
"render.optics_replace": "Erstatt dette målets lagrede optikk eksplisitt",
"render.optics_save": "Lagre denne optikken i oppsettet",
"render.optics_saved": "Lagrede optiske mål",
"render.optics_saved_help": "Nøyaktig identitet for definisjon, funksjon og forekomst bevares når filen åpnes på nytt, også frakoblet. Manglende/erstattede/skjulte mål avvises; ingeniørmaterialer er uendret. Lagre eller forkast numeriske endringer før du fjerner et lagret mål.",
"render.outer_half_angle": "Ytre halvvinkel",
"render.output_format_status": "PNG er det nøyaktige ferdige visningsbildet. Valgfri GPU-EXR beholder rå scenelineær FLOAT32-radians før visningsfiltre. Eksport erstatter aldri forhåndsvisningsbufferen eller en annen jobb.",
"render.output_lock_ratio": "Lås sideforhold",
"render.output_over_budget": "Det forespurte bildet overskrider den valgte ressursrammen. Velg en kompatibel størrelse eller profil eksplisitt; ingen automatisk nedgradering skjer.",
"render.output_ratio_refused": "Det koblede målet overskrider størrelsesgrensen for denne metoden. Forrige størrelse beholdes; lås opp forholdet eller velg en mindre verdi.",
"render.output_swap_orientation": "Bytt bredde og høyde",
"render.output_tools_inspector": "Rediger størrelse og format i utdatainspektøren.",
"render.page_aging": "Aldring og forurensning",
"render.page_all": "Alle kontroller",
"render.page_appearance": "Utseende",
"render.page_background": "Bakgrunner",
"render.page_camera": "Kamera",
"render.page_diagnostics": "Diagnostikk",
"render.page_effects": "Objektiv- og etterbehandlingseffekter",
"render.page_environment": "Omgivelse",
"render.page_lighting": "Belysning",
"render.page_output": "Utdata",
"render.page_scene": "Scene",
"render.paint_label": "Maling",
"render.passive_stage": "Gulv og passivt rendringsdekor",
"render.passive_stage_help": "Endelige passive paneler hører bare til rendrede bilder. De legger ikke til CAD-kropper eller masse. Plasseringen er fast etter at den er brukt; skjæring med produktets avgrensning avvises. CPU gir ikke diffus indirekte belysning.",
"render.perspective": "Perspektivkamera",
"render.physical_acknowledge": "Jeg forstår at denne delvise referansen krever gjennomgang av kvalitetsklasse, tilstand og kilde",
"render.physical_associations": "Fysiske kandidater og roller",
"render.physical_background_help": "Reelt passivt gulv og vegg, atskilt fra kamerabakgrunnen. Syklorama bruker 24 mangekantede striper; det er ikke en uendelig eller analytisk jevn flate. Erstatter det lagrede rendringsdekoret bare med ditt samtykke.",
"render.physical_copy_plan": "Kopier plan med kilder og utelatelser",
"render.physical_cyclorama": "Tilpass polygonalt syklorama",
"render.physical_floor_wall": "Tilpass fysisk gulv og vegg",
"render.physical_material_name": "Foreslått navn på referansemateriale",
"render.physical_omissions": "Egenskaper som ikke kan representeres i det opprinnelige kortet",
"render.physical_plan_only": "Skrivebeskyttet plan er klargjort. Ingen materialer ble opprettet eller tilordnet. Ta den utvidede profilen og utelatelsene med i vurderingen når du gjennomgår det opprinnelige kortet.",
"render.physical_prepare_plan": "Forbered opprettelsesplan (gjennomføres ikke)",
"render.physical_separate": "Utseende er ikke materialidentifikasjon. Dette er kildebelagte referanser, ikke sertifiserte effektive egenskaper. Eksisterende masse, ingeniørmaterialer og optikk er uendret.",
"render.physical_unknown": "Ingen numerisk kandidat er fastsatt. Kvalitet, sammensetning eller konstruksjon må spesifiseres; ukjent er ikke null.",
"render.pick_body": "Kropp",
"render.pick_component": "Komponent",
"render.pick_face": "Flate",
"render.pick_help": "Velg kropp, flate eller komponent. Klikk i tomt område for å fjerne valget; Shift eller Ctrl legger til eller veksler. Utheving vises bare i live-produktvisningen.",
"render.pick_label": "Velg",
"render.pick_up_label": "Plukk opp",
"render.pick_waiting": "Valg i produktvisningen støttes ikke ennå.",
"render.post_contrast": "Kontrast",
"render.post_gain_b": "Blå forsterkning",
"render.post_gain_g": "Grønn forsterkning",
"render.post_gain_r": "Rød forsterkning",
"render.post_help": "Kun kreativ presentasjon. RGB-forsterkning kommer før tonemapping; kontrast, metning og vignettering følger i skjermlineært lys. Start rendring oppretter nye transportsampler. Ny fargekorrigering bruker den valgte beholdte råmasteren uten støyfjerning eller nye stråler.",
"render.post_reset": "Tilbakestill presentasjonsfiltre",
"render.post_saturation": "Metning",
"render.post_title": "Presentasjonsfiltre",
"render.post_vignette": "Vignettering",
"render.preview": "Integrert forhåndsvisning",
"render.preview_help": "Rasterskyggelegging og blandet transparens. Lysbrytning, HDRI og sluttrendring er ikke tilgjengelig ennå.",
"render.preview_image_settings_help": "Live-forhåndsvisningen beholder fast studiobelysning. Eksponering og bildebelysning gjelder for bildejobben når du velger Sjekk eller Start.",
"render.preview_lighting_help": "Live-forhåndsvisningen viser bare direkte lys og ingen skygger.",
"render.preview_retry": "Prøv live-forhåndsvisning igjen",
"render.preview_unavailable_help": "Live-forhåndsvisningen er utilgjengelig. Lagrede oppsett og kontroller for bildejobber er fortsatt tilgjengelige. Endre scenen eller prøv eksplisitt på nytt; en avvist scene bygges ikke på nytt for hver bilderute.",
"render.preview_upload": "Verteksdata for live-forhåndsvisning",
"render.preview_upload_help": "Nøyaktige byte for forhåndsvisningens verteksdata, ikke samlet GPU- eller prosessminne. Geometrien forenkles ikke. Bildejobber bruker egen godkjenning og egen belysning.",
"render.progressive_image_summary": "Forhåndsvisnings-PNG · PBR og glass · progressive sampler",
"render.property_conditions": "Betingelser: {value}",
"render.property_fallback": "egenskap",
"render.property_qualifier": "Kvalifikator: {value}",
"render.property_source": "Kilde: {id} - {locator}",
"render.property_uncertainty": "Usikkerhet: {value}",
"render.property_unknown": "ukjent",
"render.quality_ack": "Bekreft projeksjonen med fast budsjett og utelatelsene",
"render.quality_apply": "Bruk dette faste samplingbudsjettet",
"render.quality_projection_help": "Q-forhåndsinnstillinger inkluderer framtidige krav. Denne handlingen projiserer bare et støttet PNG-budsjett med fast antall sampler, og utelater eksplisitt adaptiv stopp, rå lineær utdata og uavhengige transmisjonsgrenser.",
"render.quality_review": "Gjennomgå samplingbudsjett",
"render.queue_pending": "Dette grensesnittet har ingen automatisk produksjonskø eller animasjonsrendring. Ferdige stillbilder kan fortsatt eksporteres hver for seg.",
"render.radial_distortion": "Radiell forvrengning",
"render.regrade_action": "Fargekorriger råmaster på nytt (uten støyfjerning)",
"render.regrade_help": "Oppretter en separat PNG fra den valgte ferdige råmasteren med disse presentasjonskontrollene. Sporer ingen stråler, endrer ikke registrert størrelse, kamera eller lys, og overskriver ikke EXR-filen. Støyfjerning brukes ikke på nytt: råmastere beholder ikke hjelpedataene for den. Den avledede filen kan fortsatt eksporteres med de samme jobbkontrollene.",
"render.regrade_label": "Ny fargekorrigering",
"render.reload_settings": "Last inn lagrede innstillinger på nytt",
"render.replace_ground": "Bekreft erstatning av eksisterende rendringsdekor",
"render.replace_label": "Erstatt",
"render.replace_saved_surface": "Erstatt en eksisterende lagret tilordning for dette målet",
"render.restore_camera": "Gjenopprett lagret kamera",
"render.result_actual_help": "Én bildepiksel per skjermpiksel.",
"render.result_actual_size": "100%",
"render.result_capture": "Registrert revisjon",
"render.result_current": "Den registrerte modellrevisjonen er gjeldende.",
"render.result_empty": "Ingen ferdig bilde ennå. Sjekk innstillingene og start deretter en rendring.",
"render.result_fit": "Tilpass bildet",
"render.result_job": "Jobb",
"render.result_navigation": "Panorering og zooming følger navigasjonsinnstillingene. Mellomrom + dra panorerer.",
"render.result_open": "Åpne det ferdige bildet i hovedlerretet.",
"render.result_preview": "Live-forhåndsvisning",
"render.result_provisional": "Midlertidig CPU-bilde",
"render.result_provisional_help": "Dette sjekkpunktet kan ikke eksporteres. Eksport beholder det siste ferdige resultatet; avbryting går tilbake til dette resultatet.",
"render.result_reduced_display": "Skjermforhåndsvisningen er redusert til grensen for visningsenhet/hurtigbuffer. Den beholdte PNG-en og eksporten har full oppløsning; innebygd 100%-inspeksjon er ikke tilgjengelig for denne reduserte visningen.",
"render.result_retained": "Viser det siste ferdige bildet; en nyere rendring har ikke erstattet det.",
"render.result_sequence": "Sjekkpunkt",
"render.result_title": "Rendringsresultat",
"render.return_design": "Tilbake til design",
"render.review_stale": "Denne gjennomgangen er utdatert. Avklar eller sjekk på nytt før du bruker den.",
"render.ribbon_aging": "Aldring",
"render.ribbon_backgrounds": "Bakgrunner",
"render.ribbon_check": "Sjekk",
"render.ribbon_check_help": "Valider nøyaktig det gjeldende utkastet som rendringen sender inn. Ingen reserveløsning for rendringsmotor, ingen stille endring av størrelse og ingen stille erstatning av ressurser.",
"render.ribbon_edit_lights": "Rediger lys",
"render.ribbon_effects": "Effekter",
"render.ribbon_environment_help": "HDR-belysning, bakgrunner som bare vises for kameraet og fysiske overflater i rendringsdekoret er separate kontroller med eksplisitt samtykke til erstatning.",
"render.ribbon_finish_dialog": "Fullfør den gjeldende fil- eller bekreftelsesdialogen først.",
"render.ribbon_frame": "Ramme inn",
"render.ribbon_hdr_library": "HDR-bibliotek",
"render.ribbon_job_active": "En rendring kjører allerede; avbryt den eksplisitt før du starter en ny.",
"render.ribbon_light_rigs": "Lysrigger",
"render.ribbon_lights_help": "Inspiser forhåndsdefinerte rigger eller rediger støttede lys uten å erstatte det gjeldende oppsettet før du eksplisitt bruker endringen.",
"render.ribbon_materials": "Materialer",
"render.ribbon_materials_help": "Åpne den delte utseendeinspektøren og det originale overflatebiblioteket. Optiske endringer endrer aldri tekniske egenskaper i det stille.",
"render.ribbon_no_active_job": "Det finnes ingen aktiv rendring å avbryte.",
"render.ribbon_no_result": "Fullfør en rendring før du eksporterer det nøyaktige bildet.",
"render.ribbon_no_saved_camera": "Lagre et opptak før du gjenoppretter kameraet.",
"render.ribbon_saved_camera": "Lagret kamera",
"render.ribbon_shots": "Opptak",
"render.ribbon_studios": "Studioer",
"render.ribbon_studios_help": "Bla gjennom implementerte studiokomposisjoner og gå gjennom hva de erstatter før de brukes. Scener som bare er konsepter, forblir merket.",
"render.ribbon_surface_maps": "Overflatekart",
"render.sampling_title": "Adaptiv sampling og transmisjonssampling",
"render.save_continue": "Lagre og fortsett",
"render.save_setup": "Lagre oppsett",
"render.save_shot": "Lagre opptak",
"render.saved_maps_runtime_conflict": "Lagrede overflatetilordninger kan ikke blandes med midlertidige optiske overstyringer eller en ulagret HDR. Lagre HDR-en eller fjern de midlertidige inndataene eksplisitt.",
"render.saved_surface_remove": "Fjern lagret tilordning",
"render.saved_surfaces": "Lagrede overflatetilordninger",
"render.saved_surfaces_help": "Festede innebygde kart følger den valgte forekomsten i lokale millimeter. Et erstattet eller manglende mål er en feil, aldri en automatisk ny tilordning.",
"render.scene_apply": "Bruk gjennomgått studio",
"render.scene_consent": "Bekreft erstatning av belysning, omgivelse, eksponering og rendringsdekor",
"render.scene_preserved_fields": "Kamera, sampling, bildestørrelse, optiske tilordninger, CAD-geometri og tekniske materialer beholdes.",
"render.scene_preserves_design": "Komponer belysning og et passivt rendringsdekor for det synlige motivet. Geometri, tekniske materialer og kamera forblir adskilt.",
"render.scene_replaces": "Erstatter",
"render.scene_review": "Avklar og gjennomgå",
"render.scene_review_help": "Gå gjennom hele den innebygde komposisjonen før du bruker den. Ubundne avanserte SCENE-spesifikasjoner erstattes ikke.",
"render.scene_scope_details": "Komposisjonens omfang",
"render.setup_legacy_environment": "Dette eldre oppsettet bruker utdatert rotasjon eller intensitet for omgivelsen. Disse verdiene beholdes; konverter dem eksplisitt før du lagrer en full bildejobb.",
"render.setup_name": "Oppsettsnavn",
"render.setup_numeric_help": "Lagre registrerer den aktive bildemetoden og alle numeriske innstillinger. Ny innlasting eller valg av et annet oppsett erstatter dette utkastet; gjenopprett kameraet separat.",
"render.setup_offline_help": "Du kan redigere og lagre denne metoden uten rendringsmotoren. Sjekk og Start krever en tilgjengelig vert.",
"render.setup_runtime_unsupported": "Denne fulle jobben kan ikke lagres ennå: den inneholder kart eller tilordninger til kropper i scenen. Fjern disse midlertidige inndataene før du lagrer et portabelt oppsett.",
"render.setup_save_missing": "Den lagrede rendringskonfigurasjonen ble ikke funnet etter at kommandoen var fullført.",
"render.sharpening": "Detaljskjerping",
"render.shell_tab_appearance": "RENDRINGSUTSEENDE",
"render.shell_tab_camera": "RENDRINGSKAMERA",
"render.shell_tab_scene": "RENDRINGSSCENE",
"render.shot_duplicate": "Dupliser lagret opptak",
"render.shot_manager": "Lagrede opptak",
"render.shot_new_name": "Navn på nytt opptak",
"render.shot_remove": "Fjern lagret opptak",
"render.shot_remove_help": "Fjerner bare dette lagrede oppsettet. Kildegeometri og ferdige bilder beholdes; handlingen kan angres.",
"render.shot_remove_title": "Fjerne lagret opptak?",
"render.shot_rename": "Gi nytt navn til lagret opptak",
"render.shot_saved_only": "Lagre det gjeldende utkastet først. Duplisering og omdøping beholder de nøyaktige lagrede alternativene og ressursreferansene.",
"render.show_shots_label": "Vis opptaksstripen",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Bakke · lineær RGB",
"render.sky_horizon": "Horisont · lineær RGB",
"render.sky_zenith": "Zenit · lineær RGB",
"render.soft_focus": "Mykt fokus",
"render.spot_cone": "Spotkjegle",
"render.stage_frame": "Utsnitt",
"render.stage_light": "Lys",
"render.stage_look": "Stil",
"render.stage_orthographic": "Ortografisk",
"render.stage_output": "Utdata",
"render.stage_panel_count": "Lagrede paneler",
"render.stage_preview_note": "Integrert forhåndsvisning · direkte lys",
"render.strip_label": "Stripe",
"render.studio_add_area": "Legg til arealys",
"render.studio_ambient": "Konstant omgivelsesstråling",
"render.studio_ambient_rgb": "Konstant omgivelsesstråling (lineær RGB)",
"render.studio_aperture": "Blenderradius",
"render.studio_area": "Arealys",
"render.studio_area_help": "Opptil fire énsidige rektangler. De ortogonale halvkantene U og V bestemmer størrelsen; U × V peker mot den opplyste siden. Koordinatene er i verdensrom, i millimeter.",
"render.studio_center": "Senter X, Y, Z (mm)",
"render.studio_denoise": "Reduser støy i det ferdige bildet",
"render.studio_denoise_help": "Avsluttende kantbevisst filter. Fine detaljer kan bli mykere. Glass og skarpe, speilende flater går utenom filteret.",
"render.studio_direction": "Retning mot solen (X, Y, Z)",
"render.studio_environment": "Omgivelse",
"render.studio_environment_bounds": "Omgivelsesrotasjonen må være et endelig tall innenfor ±1 000 000 radianer, og intensiteten må ligge mellom 0 og 100.",
"render.studio_environment_none": "Ingen omgivelseskart",
"render.studio_focus": "Aksial fokusavstand",
"render.studio_half_u": "Halvkant U (mm)",
"render.studio_half_v": "Halvkant V (mm)",
"render.studio_hdr": "Radiance HDR-fil",
"render.studio_hdr_browse": "Velg HDR…",
"render.studio_hdr_help": "Radiance .hdr, 2:1-panorama, opptil 2048 × 1024. EXR er ikke tilgjengelig. Fargeantakelsen gjelder bare når primærfargene ikke er angitt.",
"render.studio_hdr_required": "Velg en lokal .hdr-fil.",
"render.studio_hdr_srgb": "Tolk uspesifiserte primærfarger som lineær sRGB",
"render.studio_intensity": "Omgivelsesintensitet",
"render.studio_lens": "Dybdeskarphet",
"render.studio_lens_perspective": "Dybdeskarphet krever et perspektivkamera.",
"render.studio_lighting": "Studiobelysning",
"render.studio_lighting_enable": "Bruk egendefinert studiobelysning",
"render.studio_needs_review": "Gå gjennom metode og innstillinger",
"render.studio_radiance": "Lineær RGB-stråling",
"render.studio_ready": "Klar for kontroll",
"render.studio_remove_area": "Fjern arealys",
"render.studio_rotation": "Omgivelsesrotasjon",
"render.studio_runtime_help": "Numeriske studioinnstillinger og kontrollerte HDR-kilder kan lagres sammen med oppsettet. Optiske overstyringer og materialoverstyringer på kropper er midlertidige og endrer ikke lagrede utseender.",
"render.studio_saved": "Lagret oppsett / gjeldende kamera",
"render.studio_sky": "Kunstnerisk himmel",
"render.studio_sky_help": "Original himmelgradient for belysning; ikke en kalibrert atmosfæremodell.",
"render.studio_sun": "Sol",
"render.studio_sun_radius": "Vinkelradius",
"render.studio_title": "Rendringsstudio",
"render.studio_tone_map": "Tonemapping",
"render.subsurface_enable": "Indre spredning (tilfeldig vandring)",
"render.subsurface_help": "Bare for lukkede dielektrikum. Spredning og RGB-absorpsjon er separate koeffisienter per mm. Lysbaner spres inne i den faktiske geometrien og brytes eller reflekteres deretter ved grensen. Slå av rett skyggegjennomgang, overflatestøyreduksjon og eksternt volum; bruk ett Fresnel-sjikt. Ikke en diffusjonsshader, et tetthetsrutenett eller et målt materiale. Tette medier kan kreve flere prøver og større banedybde.",
"render.subsurface_rate": "Kollisjonsrate for spredning",
"render.tone_aces_fitted": "ACES tilpasset",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "GPU-glass støtter sertifiserte disjunkte medier. Ubegrenset nestede medier og en støyfri transmisjonsestimator finnes ikke.",
"render.transmission_strata": "Betingede Fresnel-sjikt",
"render.transmission_strata_help": "1 beholder den opprinnelige tilfeldighetsstrømmen. 2 eller 4 delbaner stratifiserer det første valget mellom refleksjon og transmisjon i glass, med uendrede lover for Snell og absorpsjon. Flere baner koster mer beregningsarbeid; dette er verken støyreduksjon, støtte for nestede medier eller et løfte om raskere rendring.",
"render.tree_add_light": "Legg til lys",
"render.tree_add_shot": "Legg til opptak",
"render.tree_browser": "Rendringstre",
"render.tree_by_look": "Etter stil",
"render.tree_by_object": "Etter objekt",
"render.tree_constant": "Konstant omgivelse",
"render.tree_default": "Standard",
"render.tree_directional": "Retningsbestemt",
"render.tree_environment": "Omgivelse",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} flater",
"render.tree_face_one": "{count} flate",
"render.tree_fixed_studio": "Fiksert studio",
"render.tree_hdr": "HDR",
"render.tree_lights": "Lys",
"render.tree_lights_pending": "Kommandoer for navngitte lys er ikke tilgjengelige ennå.",
"render.tree_mixed": "Blandet",
"render.tree_more": "{count} til",
"render.tree_mute": "Demp lys",
"render.tree_no_environment": "Ingen omgivelse",
"render.tree_objects": "Objekter",
"render.tree_output": "Utdata",
"render.tree_point": "Punkt",
"render.tree_rectangle": "Rektangel",
"render.tree_search": "Søk i objekter",
"render.tree_selection": "Rendringsutvalg",
"render.tree_shots": "Opptak",
"render.tree_sky": "Himmel",
"render.tree_solo": "Solo-lys",
"render.tree_spot": "Spot",
"render.tree_sun": "Sol",
"render.tree_switch": "Bytt",
"render.tree_user_one": "{count} objekt",
"render.tree_users": "{count} objekter",
"render.unavailable_preview": "Dette oppsettet ber om en utilgjengelig forhåndsvisningsprofil.",
"render.unsaved": "Ulagrede forhåndsvisningsendringer",
"render.use_preview": "Bruk integrert forhåndsvisning",
"render.volume_albedo": "Spredningsalbedo · lineær RGB",
"render.volume_anisotropy": "Gjennomsnittlig fasekosinus",
"render.volume_enable": "Aktiver deltakende medium",
"render.volume_extinction": "Ekstinksjonskoeffisient",
"render.volume_help": "GPU-lystransport inne i én endelig boks, med Beer-demping og HG-spredning på kamerabaner og indirekte baner. Bruker eksplisitt studio-, HDR- og himmelbelysning, inkludert skyggedemping. Positiv fasekosinus spreder fremover. Glassgrenser og overflatestøyreduksjon må slås av eksplisitt. Null ekstinksjon lar transporten være uendret. Ikke en fysisk måneatmosfære, et tetthetsrutenett, volumemisjon, spektraltransport eller en sertifisert materialegenskap.",
"render.volume_max": "Maksimumsgrenser · verden mm",
"render.volume_min": "Minimumsgrenser · verden mm",
"render.volume_title": "Avgrenset homogent volum",
"render.wait_batch": "støttes ikke ennå: rendringskøen for lagrede opptak",
"render.wait_compare": "støttes ikke ennå: sammenligning av lagrede bilder",
"render.wait_paint": "støttes ikke ennå: valg av produkt og maling av utseende",
"render.wait_pick_up": "støttes ikke ennå: valg av produkt og opptak av utseende",
"render.wait_replace": "støttes ikke ennå: erstatning av alle bruk av et utseende",
"render.wait_solo": "støttes ikke ennå: lysenes synlighet og solo-kontroller",
"sample.bracket.about": "Basisflens med kantflenser og kantomslag, med en plateregel for 2 mm tykkelse",
"sample.bracket.name": "Platebrakett",
"sample.enclosure.about": "Uthulet boks med leppekant, skruefester, anlegg og snap-fit",
+712
View File
@@ -37,6 +37,7 @@
"All open designs": "Alle geopende ontwerpen",
"Allowed expressions, separated by semicolons": "Toegestane expressies, gescheiden door puntkomma's",
"Also deletes": "Verwijdert ook",
"Also place them from the origin (fully constrained)": "Ook vanaf de oorsprong plaatsen (volledig bepaald)",
"Anchor": "Anker",
"Angle 2": "Hoek 2",
"Angle Display": "Hoekweergave",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Ontwerpen die u opent of opslaat, verschijnen hier.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Bepaald door Tot object. Kies Hoek om de hoekomvang te bewerken.",
"Diameter": "Diameter",
"Dimension new shapes": "Nieuwe vormen maatvoeren",
"Direction": "Richting",
"Discard": "Verwerpen",
"Distance": "Afstand",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Sleep om het rustvlak in stappen van 5° te draaien. Houd Alt of Ctrl ingedrukt om het vrij te draaien.",
"Drive Joint": "Verbinding aansturen",
"Duration": "Duur",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Elke nieuwe vorm krijgt ook maten vanaf de schetsoorsprong tot er niets meer vrij is. Een vorm die al aan de oorsprong of aan geplaatste geometrie vastzit, krijgt er geen.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Elke vorm die je tekent krijgt al zijn maten op de getekende grootte (getypte waarden gaan voor). Een maat die de schets al vastlegt, wordt weggelaten.",
"Edges": "Randen",
"Edit": "Bewerken",
"Edit Profile Sketch": "Profielschets bewerken",
@@ -1697,6 +1701,8 @@
"prefs.sketch_selection": "Schets en selectie",
"prefs.sketch_selection_heading": "Schets en selectie",
"prefs.sketch_selection_note": "Hoe schetsen snappen en hoe klikken selecteren.",
"prefs.sketch_tab_always": "Schets-tab altijd tonen",
"prefs.sketch_tab_always_note": "De Schets-tab blijft in het lint staan, direct na Model, ook als er geen schets open is. Zijn tekentools beginnen dan een schets op het geselecteerde vlak, of op het vlak dat je daarna kiest, met de tool daarin klaar voor gebruik.",
"prefs.sketching": "Schetsen",
"prefs.snap_drawing_note": "Tijdens het tekenen of slepen van een schetspunt.",
"prefs.source": "Bron",
@@ -1741,21 +1747,317 @@
"recovery.just_now": "zojuist",
"recovery.min_ago": "{count} min geleden",
"recovery.never_saved": "nooit opgeslagen",
"render.adaptive_absolute": "Absolute RGB-foutondergrens",
"render.adaptive_coverage": "Doel voor bedekkingsfout",
"render.adaptive_enable": "Samples verdelen met onafhankelijke pilots",
"render.adaptive_help": "Alleen GPU. Onafhankelijke pilotsamples worden verworpen; daarna worden 16 of meer productiesamples per pixel verdeeld, tot Samples per pixel. De variantie van RGB en bedekking stuurt de verdeling; zeldzame paden kunnen gemist worden en pixels op de limiet kunnen ruis houden. Het eindrapport telt het daadwerkelijke werk. Geen gecertificeerde garantie voor ruis of tijd.",
"render.adaptive_minimum": "Minimaal aantal productiesamples",
"render.adaptive_pending": "Adaptieve verdeling met onafhankelijke GPU-pilots en voorwaardelijke Fresnel-strata zijn beschikbaar. Gecertificeerde convergentie, garanties voor zeldzame gebeurtenissen en adaptief CPU-transport blijven niet beschikbaar.",
"render.adaptive_pilots": "Pilotsamples per pixel",
"render.adaptive_relative": "Doel voor relatieve RGB-fout",
"render.add_ground": "Passende vloer aan opstelling toevoegen",
"render.advanced_material_scope": "Eén eindig homogeen GPU-medium is beschikbaar binnen expliciete limieten. Dichtheidsrasters, geneste combinaties van glas en volume, subsurface-oppervlakken, displacement, spectraal transport en niet-gekoppelde geavanceerde materiaalconcepten blijven niet beschikbaar.",
"render.aging_add": "Verouderingslaag toevoegen",
"render.aging_airborne": "Stof in de lucht / participerend medium",
"render.aging_airborne_help": "Stof in de lucht is een apart, eindig, homogeen verstrooiend volume. Het wijzigt het transport en de ruwe EXR, niet de stapel voor oppervlakteveroudering. Bestaande beperkingen voor volume, glas en ruisonderdrukking blijven expliciet; er wordt niet automatisch een atmosfeer toegevoegd.",
"render.aging_all_bodies": "Alle geschikte ondoorzichtige lichamen",
"render.aging_chips": "Afgebladderde verf",
"render.aging_class_any": "Alle ondoorzichtige materiaalklassen",
"render.aging_class_dielectric": "Alleen niet-metalen oppervlakken",
"render.aging_class_metal": "Alleen metalen oppervlakken",
"render.aging_color": "Laagkleur · sRGB",
"render.aging_coverage": "Bedekking",
"render.aging_dust": "Afgezet stof",
"render.aging_empty": "Geen verouderingslagen: de oorspronkelijke oppervlakken blijven ongewijzigd.",
"render.aging_fading": "Verbleekte coating",
"render.aging_grime": "Vuil en vlekken",
"render.aging_help": "Combineer tot acht optische lagen, in volgorde. Roest en patina zijn ontworpen uiterlijken, geen simulaties van veroudering of corrosie. De schaal is in wereldmillimeters. Er wordt geen geometrie, massa of technische eigenschap gewijzigd; glas en passieve decors zijn uitgesloten.",
"render.aging_metallic": "Metaalfractie van laag",
"render.aging_origin": "Veldoorsprong · wereld, mm",
"render.aging_patina": "Groene koperpatina",
"render.aging_refresh_targets": "Huidige lichamen inspecteren",
"render.aging_roughness": "Ruwheid van laag",
"render.aging_rust": "Geoxideerd ijzer / roest",
"render.aging_scale": "Patroonschaal",
"render.aging_scratches": "Fijne krassen",
"render.aging_target": "Doel en coördinaten",
"render.aging_target_help": "Een benoemd doel moet nog overeenkomen met de vastgelegde index en naam. Globale maskers zijn aan de wereld verankerd; ze volgen bewegende onderdelen niet. Dit is geen holtedetectie en ook geen echte randslijtage. Filter de lijst om extra lichamen te bereiken.",
"render.aging_target_search": "Lichaamsnamen filteren",
"render.aging_upward": "Afzetting op naar boven gerichte vlakken",
"render.all_controls_help": "Compact overzicht van alle huidige bedieningselementen. Sectiepagina's bieden gerichte bewerking zonder het onderliggende verzoek te wijzigen.",
"render.all_shots_label": "Alle opnamen",
"render.appearance_physics_separate": "Het visuele uiterlijk kent geen dichtheid, thermische gegevens of andere technische eigenschappen toe.",
"render.availability_native": "Ingebouwde samenstelling; controleren voor het toepassen",
"render.availability_projection": "Ondersteunde projectie; zie bereik en weglatingen",
"render.availability_reference": "Referentiegegevens; geen automatische toewijzing",
"render.backdrop_alpha_conflict": "Kies deze achtergrond of transparante PNG-uitvoer; de renderer negeert geen van beide instellingen stilzwijgend.",
"render.backdrop_enable": "Verloopachtergrond alleen voor de camera gebruiken",
"render.backdrop_first": "Start-/middenkleur",
"render.backdrop_help": "Deze achtergrond in schermruimte verlicht niet, werpt geen schaduw, weerspiegelt niet en stelt geen terrein voor. Hij is uitgesloten van de ruwe EXR. Geometrie, lichten en de HDR-omgeving blijven onafhankelijk.",
"render.backdrop_horizontal": "Horizontaal verloop",
"render.backdrop_radial": "Radiaal verloop",
"render.backdrop_radius": "Straal",
"render.backdrop_second": "Eind-/randkleur",
"render.backdrop_vertical": "Verticaal verloop",
"render.backdrop_x": "Midden X",
"render.backdrop_y": "Midden Y",
"render.background": "Scèneachtergrond",
"render.background_camera_section": "Camera-achtergrond · PNG-presentatie",
"render.background_completed_frozen": "Het getoonde resultaat is een bevroren, voltooide afbeelding. Het bewerken van een achtergrond tekent dat resultaat niet automatisch opnieuw. Gebruik Opnieuw kleurcorrigeren voor wijzigingen alleen aan de camera, of Renderen voor een nieuw fysiek decor.",
"render.background_hdr_separate": "De huidige HDR-bronnen verlichten oppervlakken en worden erop weerspiegeld; ze worden niet automatisch als panorama achter het onderwerp getoond. Een verloop wijzigen draait of herkleurt de verlichting niet.",
"render.background_lighting_section": "HDR-verlichting · los van de camera-achtergrond",
"render.background_no_alpha_override": "Een camera-achtergrond wordt niet stilzwijgend aan transparante uitvoer toegevoegd. Een nieuwe kleurcorrectie van de ruwe master gebruikt de vastgelegde bedekking en past ruisonderdrukking niet opnieuw toe; de bron-EXR blijft ongewijzigd.",
"render.background_not_light": "Achtergrondkleur is presentatie, geen extra lichtbron.",
"render.background_regrade": "Toepassen op bewaarde ruwe master",
"render.background_stage_occlusion": "Deze opname bevat fysieke decorgeometrie. Een grote vloer of wand kan het beeld vullen en een achtergrond alleen voor de camera verbergen. Wis het decor of pas het formaat bewust aan, of wijzig de fysieke reflectie ervan. Een nieuwe kleurcorrectie kan vastgelegde geometrie niet verwijderen.",
"render.background_workflow": "Kies de achtergrond die je bedoelt: een kleur of verloop alleen voor de camera, een fysiek decor dat licht ontvangt, of HDR-verlichting. Ze zijn onafhankelijk. Het live voorbeeld is een modelleerweergave; render een nieuwe afbeelding of kleurcorrigeer een bewaarde master opnieuw om de camera-afwerking te zien.",
"render.base_appearance": "Bewerkbaar lichaamsuiterlijk",
"render.base_apply": "Lichaamsuiterlijk toepassen",
"render.base_apply_help": "Eén ongedaan te maken visuele toewijzing aan het gecontroleerde exacte lichaam. Bestaande vlakspecifieke looks en technische materialen blijven gescheiden.",
"render.base_color": "Basiskleur · sRGB",
"render.base_metallic": "Metaalfractie",
"render.base_opaque_only": "Deze editor behoudt de semantiek van ondoorzichtige lichamen. Gebruik de expliciete glasbesturing voor optische transmissie.",
"render.bloom_enable": "Bloom tonen",
"render.bloom_help": "Creatieve gloed, alleen in de uitvoer, afkomstig van positieve lineaire highlights en verspreid met drie genormaliseerde boxpassen. De straal is in uitvoerpixels. Toegevoegd in lineair weergavelicht vóór sRGB; geen lens- of volumetrisch effect en geen verbetering van de convergentie. De ruwe EXR blijft ongewijzigd.",
"render.bloom_opaque": "Bloom vereist ondoorzichtige uitvoer. Transparante PNG wordt geweigerd, niet stilzwijgend afgevlakt.",
"render.bloom_radius": "Bloomstraal",
"render.bloom_strength": "Bloomsterkte",
"render.bloom_threshold": "Lineaire highlightdrempel",
"render.browse_capabilities": "Volledige catalogus met mogelijkheden bekijken",
"render.browse_environments": "Originele HDR-omgevingen doorbladeren",
"render.browse_native_scenes": "Ingebouwde studio's doorbladeren",
"render.browse_physical": "Fysieke referenties bekijken",
"render.browse_quality": "Kwaliteitsspecificaties bekijken",
"render.browse_rigs": "Ontworpen lichtopstellingen doorbladeren",
"render.browse_scene_specs": "Geavanceerde scènespecificaties doorbladeren",
"render.browse_surfaces": "Ontworpen oppervlakken doorbladeren",
"render.browser_library": "Bibliotheek",
"render.browser_model": "Model",
"render.camera_distance": "Afstand van oog tot doel",
"render.camera_exact_help": "Wereldmillimeters; hoeken worden in graden getoond en als radialen opgeslagen. Navigatie gebruikt dezelfde camera als de viewport.",
"render.camera_fov": "Verticaal gezichtsveld",
"render.camera_pitch": "Camerakanteling",
"render.camera_roll": "Rollen",
"render.camera_set": "Rendercamera instellen",
"render.camera_target": "Doelpositie · mm",
"render.camera_yaw": "Gieren",
"render.chromatic_offset": "Chromatische randverschuiving",
"render.clear_stage": "Opgeslagen decor verwijderen",
"render.copy_request": "JSON kopiëren",
"render.cpu_aa_help": "Ruimtelijke samples: meer samples verbeteren randen en verlengen de rendertijd.",
"render.cpu_area_add": "Rechthoekig CPU-licht toevoegen",
"render.cpu_area_editor": "Rechthoekige CPU-lichten",
"render.cpu_area_editor_help": "Volledige zijvectoren in millimeters; het kruisproduct U × V wijst naar de uitstralende zijde. Dit verschilt van de halve-randvectoren van de GPU.",
"render.cpu_area_full_u": "Volledige zijde U · mm",
"render.cpu_area_full_v": "Volledige zijde V · mm",
"render.cpu_area_samples": "Samples voor vlaklichten",
"render.cpu_binding_confirm": "Dit lichaam bevestigen",
"render.cpu_binding_stale": "De scène is gewijzigd. Bevestig dit reflectiedoel opnieuw voordat je rendert.",
"render.cpu_body_choose": "Kies een lichaam",
"render.cpu_body_filter": "Lichamen filteren op naam",
"render.cpu_body_filter_more": "Verfijn het filter om meer lichamen te zien.",
"render.cpu_body_missing": "Een reflectiedoel ontbreekt, is verborgen of dubbelzinnig, of heeft een naam langer dan 128 bytes. Kies het opnieuw.",
"render.cpu_budget": "CPU-resourceprofiel",
"render.cpu_budget_bodies": "Maximum aantal lichamen",
"render.cpu_budget_compact": "Compact (oude limieten)",
"render.cpu_budget_details": "Resourcelimieten",
"render.cpu_budget_help": "Kies expliciet grotere limieten. Resolutie en samples worden nooit automatisch verlaagd.",
"render.cpu_budget_memory": "Geheugenlimiet per taak",
"render.cpu_budget_not_guarantee": "Dit zijn toelatingslimieten, geen RAM-reservering of snelheidsgarantie. Geometrie, film en bewaarde voorbeelden delen het geheugenbudget; het renderen blijft annuleerbaar.",
"render.cpu_budget_resize": "Het concept overschrijdt dit CPU-profiel of het budget voor camerasamples. Accepteer expliciet kleinere afmetingen of kies een groter profiel.",
"render.cpu_budget_studio": "Studio (grote afbeeldingen)",
"render.cpu_budget_triangles": "Maximum aantal driehoeken",
"render.cpu_budget_workstation": "Werkstation (zware scènes)",
"render.cpu_captured_hdr": "HDR vastgelegd voor deze afbeelding",
"render.cpu_check_capture_help": "Controleren en Starten verifiëren dezelfde bestandshash of gebruiken de ingesloten HDR. Elke afbeelding behoudt haar vastgelegde bron.",
"render.cpu_check_changed": "De instellingen of het model zijn gewijzigd na deze controle. Controleer opnieuw voordat je rendert.",
"render.cpu_constant_help": "Constante straling is zichtbaar voor gereflecteerde of doorgelaten stralen. Het levert geen directe diffuse belichting.",
"render.cpu_custom_directions": "Voorinstelling vervangen door aangepaste richtingslichten",
"render.cpu_direction": "Richting naar het licht (X, Y, Z)",
"render.cpu_directional": "Richtingslicht",
"render.cpu_directional_add": "Richtingslicht toevoegen",
"render.cpu_environment": "CPU-omgeving",
"render.cpu_environment_background": "De achtergrond van de afbeelding blijft gescheiden van de omgevingsverlichting.",
"render.cpu_environment_bounds": "CPU-intensiteit moet 0–64 zijn, HDR-rotatie eindig binnen ±1.000.000 radialen en HDR-samples 1, 4, 16 of 64.",
"render.cpu_environment_constant": "Constante omgeving voor secundaire stralen",
"render.cpu_environment_none": "Geen CPU-omgeving",
"render.cpu_environment_samples": "Samples voor HDR-verlichting",
"render.cpu_exposure_help": "CPU-belichting moet tussen −16 en 16 EV liggen. Een GPU-belichting buiten dat bereik blijft behouden totdat je die wijzigt.",
"render.cpu_fixed": "Enkele afbeelding",
"render.cpu_hdr_help": "Radiance .hdr, 2:1-panorama, tot 2048 × 1024 en 16 MiB. CPU vereist expliciete sRGB/D65-primaire kleuren in het bestand; niet-opgegeven primaire kleuren en EXR worden geweigerd.",
"render.cpu_hdr_reflection_help": "Ruwe HDR-reflecties vereisen volledig metalen lichaams- en vlakoppervlakken. Controleren meldt niet-ondersteunde combinaties.",
"render.cpu_key_rim": "Hoofd- en randlicht",
"render.cpu_last_check": "Laatste CPU-controle",
"render.cpu_light_help": "Maximaal acht richtingslichten. Een lege aangepaste lijst schakelt ze uit; als je een voorinstelling kiest, worden de lichten ervan hersteld. Kleuren zijn lineair RGB en de intensiteit is relatief, niet in watt.",
"render.cpu_light_intensity": "Relatieve intensiteit (0–64)",
"render.cpu_light_minimum": "Minimale afstand voor demping",
"render.cpu_light_position": "Wereldpositie (X, Y, Z)",
"render.cpu_light_reference": "Referentieafstand voor intensiteit",
"render.cpu_light_remove": "Licht verwijderen",
"render.cpu_lighting": "Verlichtingsvoorinstelling",
"render.cpu_lights": "CPU-lichten",
"render.cpu_linear_color": "Lineaire kleur (R, G, B)",
"render.cpu_neutral": "Neutraal",
"render.cpu_opaque_required": "CPU-raytracing vereist een ondoorzichtige achtergrond. Schakel Transparante achtergrond uit om door te gaan.",
"render.cpu_options_pending": "Dit CPU-paneel kan emissie, oppervlakte-effecten, glas of anisotropie nog niet bewerken. Wis die API-opties voordat je het gebruikt.",
"render.cpu_point": "Puntlicht",
"render.cpu_point_add": "Puntlicht toevoegen",
"render.cpu_point_help": "Maximaal acht puntlichten, toegevoegd aan de gekozen richtingsverlichting. Afstanden zijn in mm; het minimum mag de referentieafstand niet overschrijden.",
"render.cpu_primary_samples": "Randsamples per pixel",
"render.cpu_progressive": "CPU progressief",
"render.cpu_progressive_help": "Accumuleert de bestaande CPU-integrator in passes van één primaire sample. Gekozen reflecties vereisen één sample; vlaklichten, diëlektrica en anisotropie vereisen Enkele afbeelding.",
"render.cpu_progressive_limits": "Maximaal 1.048.576 pixels en 16.777.216 evaluaties van pixel × sample. Het wijzigen van samples verandert de afbeeldingsgrootte nooit automatisch.",
"render.cpu_progressive_seed": "Seed voor CPU-sampling",
"render.cpu_progressive_spp": "samples per pixel",
"render.cpu_reflection_add": "Ruwe reflectie toevoegen",
"render.cpu_reflection_depth": "Reflectiediepte (1–8)",
"render.cpu_reflection_empty": "Geen lichamen gekozen: scènereflecties zijn uit.",
"render.cpu_reflection_help": "Kies lichamen en stel Uit, Spiegel of Ruw in. Ruw gebruikt de toegewezen oppervlakteruwheid. Meer samples en weerkaatsingen verlengen de rekentijd; dit is begrensd speculair transport, geen globale verlichting.",
"render.cpu_reflection_limit": "Maximaal 64 weerspiegelde lichamen worden ondersteund.",
"render.cpu_reflection_mirror": "Spiegel",
"render.cpu_reflection_off": "Uit",
"render.cpu_reflection_rough": "Ruw",
"render.cpu_reflection_samples": "Reflectiesamples (1–64)",
"render.cpu_reflections": "CPU-reflecties",
"render.cpu_runtime_help": "Numerieke licht- en omgevingsinstellingen worden met de opstelling opgeslagen. Lichaamsreflecties en HDR-bestanden blijven tijdelijk. Bestaande waarden voor vlaklichten en spotkegels blijven behouden.",
"render.cpu_sampling_mode": "CPU-samplingmodus",
"render.cpu_shadows": "Schaduwen werpen",
"render.cpu_summary": "CPU-raytracing · reflecties · HDR · richtings- en puntlichten",
"render.cpu_warm_cool": "Warm en koel",
"render.diag_bodies": "Zichtbare lichamen",
"render.diag_job_details": "Details van vastgelegde taak",
"render.diag_last_check": "Laatste voorcontrole",
"render.diag_memory": "Schatting logische toelating",
"render.diag_not_implemented": "Expliciete functiegrenzen",
"render.diag_preflight_details": "Details van voorcontrole",
"render.diag_request": "Exacte huidige aanvraag",
"render.diag_triangles": "Driehoeken",
"render.discard_continue": "Concept verwerpen en doorgaan",
"render.draft_confirm_help": "Het huidige renderconcept heeft niet-toegepaste wijzigingen. Sla ze op voordat je wisselt, verwerp ze expliciet of blijf bewerken.",
"render.draft_confirm_title": "Bewerkte renderinstellingen behouden",
"render.effects_gpu_only": "Deze effecten vereisen GPU-pathtracing. Het wisselen van pagina schakelt de renderer nooit automatisch om.",
"render.effects_help": "Combineer geordende kleurlooks en lenseffecten in beeldruimte. Renderen en het opnieuw kleurcorrigeren van de ruwe master gebruiken dezelfde opgeslagen instellingen. Ruwe EXR blijft ongewijzigd. Dit zijn eigen artistieke regelaars, geen gekalibreerde lens- of merkfilmemulaties.",
"render.effects_reset_lens": "Lenseffecten herstellen",
"render.effects_seed": "Patroonseed",
"render.emitted_axis": "Emissieas",
"render.error_area_samples": "area_samples moet 1, 4, 16 of 64 zijn",
"render.error_binding_allocation": "kon materiaalkoppeling niet reserveren",
"render.error_body_bound": "productvoorbeeld overschrijdt de grens voor vastgelegde lichamen",
"render.error_checkpoint_dimensions": "afmetingen van het controlepunt komen niet overeen met de vastgelegde aanvraag",
"render.error_decode_budget": "decodeerbudget van afbeelding overschreden",
"render.error_denoise_setting": "ongeldige native instelling voor ruisonderdrukking",
"render.error_display_dimensions": "ongeldige weergaveafmetingen van afbeelding",
"render.error_display_fit": "afbeeldingsweergave past niet op dit apparaat",
"render.error_display_height": "weergavehoogte overschreden",
"render.error_display_width": "weergavebreedte overschreden",
"render.error_duplicate_face": "dubbel uiterlijk voor productvlak",
"render.error_export_document": "Het ontwerp is gewijzigd tijdens het kiezen van de bestemming van de renderexport",
"render.error_face_cap": "productvoorbeeld overschrijdt de toelatingslimiet voor vlakuiterlijken",
"render.error_finish_gesture": "voltooi het modelleergebaar voordat je een voorbeeld toont",
"render.error_finish_operation": "voltooi de huidige modelleerbewerking voordat je Renderen opent",
"render.error_fixed_preview": "vast studiovoorbeeld vereist belichting 0, omgevingsrotatie 0 en intensiteit 1",
"render.error_geometry_size": "grootte van productgeometrie overschreden",
"render.error_glass_recipe": "onbekend glasrecept",
"render.error_gpu_preview": "GPU-productvoorbeeld is niet beschikbaar op deze host. Opgeslagen opstellingen blijven beschikbaar.",
"render.error_gpu_samples": "niet-ondersteund aantal GPU-samples",
"render.error_image_dimensions": "afmetingen van renderafbeelding komen niet overeen met de taak",
"render.error_image_profile": "renderafbeelding overschrijdt het vastgelegde resourceprofiel",
"render.error_interactive_command": "niet-gebonden interactieve renderopdracht",
"render.error_job_action": "geen actie van een interactieve beeldtaak",
"render.error_job_identity": "ongeldige identiteit van rendertaak: {error}",
"render.error_library_reply": "ongeldig antwoord van renderbibliotheek",
"render.error_material_binding": "ontbrekende materiaalkoppeling",
"render.error_no_completed_image": "render heeft geen voltooide afbeelding",
"render.error_no_geometry": "geen productgeometrie",
"render.error_no_scene": "geen productscène",
"render.error_opacity": "ongeldige dekking van productuiterlijk",
"render.error_pbr_opacity": "ondoorzichtige PBR vereist dekking 1",
"render.error_physical_glass": "het gekozen recept is geen fysiek glas",
"render.error_preview_device": "productvoorbeeld vereist een geïnstalleerd apparaat met een dieptebuffer",
"render.error_product_triangle": "ongeldige productdriehoek",
"render.error_provisional_identity": "ongeldige voorlopige renderidentiteit of ongeldig aantal samples",
"render.error_quality_bounds": "kwaliteitsprojectie overschrijdt de native grenzen",
"render.error_quality_method": "kwaliteitsprojectie vereist dezelfde expliciete GPU-methode",
"render.error_quality_projection": "ongeldige native kwaliteitsprojectie",
"render.error_regrade_identity": "ongeldige identiteit van nieuwe kleurcorrectie: {error}",
"render.error_scene_bodies": "ontbrekende lichamen in renderscène",
"render.error_scene_body_limit": "renderscène overschrijdt de limiet voor lichamen",
"render.error_scene_identity": "ongeldige identiteit van renderscène",
"render.error_setup_panicked": "initialisatie van de GPU-pathtracer is vastgelopen",
"render.error_setup_stopped": "initialisatieworker is gestopt zonder een host terug te geven",
"render.error_setup_worker": "kon initialisatieworker niet starten: {error}",
"render.error_source_preview": "bronvoorbeeld overschrijdt het bytebereik",
"render.error_surface_normals": "PBR vereist oppervlaktenormalen ongelijk aan nul",
"render.error_surface_reply": "ongeldig antwoord voor het ontworpen oppervlak",
"render.error_triangle_bound": "het productvoorbeeld overschrijdt de bronlimiet van acht miljoen driehoeken",
"render.error_triangle_count": "overloop van het aantal productdriehoeken",
"render.error_upload_slot": "uploadslot voor het productvoorbeeld niet beschikbaar",
"render.error_vertex_allocation": "toewijzing van hoekpunten voor het productvoorbeeld mislukt",
"render.error_vertex_envelope": "het productvoorbeeld overschrijdt de limiet van {limit} MiB voor hoekpuntgegevens; de geometrie is niet vereenvoudigd",
"render.error_vertex_packing": "de verpakking van het productvoorbeeld wijkt af van de toegelaten hoekpuntgegevens",
"render.error_visible_solid": "Maak in Ontwerp een zichtbaar volumelichaam om hier een voorbeeld te zien.",
"render.exit_focus": "Focus verlaten",
"render.export_display": "Exporteren: PNG voor weergave",
"render.export_image_label": "Afbeelding exporteren",
"render.export_linear": "Exporteren: ruwe lineaire EXR",
"render.exr_pending": "De GPU kan ruwe lineaire EXR bewaren. Compressie, afbeeldingen met meerdere lagen en aanvullende renderpasses blijven niet beschikbaar.",
"render.film_grain": "Fotografische korrel",
"render.fit": "Product passend maken",
"render.fixed_camera": "Camera",
"render.fixed_world": "Wereld",
"render.flare_ghosts": "Spookringen per bron",
"render.flare_halo": "Flare-halo",
"render.flare_streak": "Streep in anamorfe stijl",
"render.flare_strength": "Flare-sterkte voor highlights",
"render.flare_threshold": "Flare-drempel (scènelineair)",
"render.fold_browser": "Browser samenvouwen",
"render.gpu_depth": "Maximale paddiepte",
"render.gpu_options_help": "Samples, diepte, seed en belichting worden opgeslagen bij deze opstelling. Alleen de actieve beeldmethode wordt opgeslagen.",
"render.gpu_path_failed": "GPU-pathtracer niet beschikbaar",
"render.gpu_path_first_setup": "De eerste voorbereiding op deze GPU kan enkele minuten duren; SolidCraft blijft ondertussen bruikbaar. Latere starts gebruiken de gecompileerde shaders opnieuw als het stuurprogramma die bewaart.",
"render.gpu_path_preparing": "GPU-pathtracer: shaders compileren…",
"render.gpu_seed": "Willekeurige seed",
"render.gpu_unavailable": "GPU-pathtracing is niet gereed op dit apparaat.",
"render.ground_apply": "Vloer aanpassen en opslaan",
"render.ground_gap": "Expliciete speling",
"render.ground_linear_rgb": "Diffuse reflectie · lineair RGB",
"render.ground_margin": "Marge van de vloeromvang",
"render.hdr_details": "Details van HDR-bron",
"render.hdr_embedded": "HDR opgeslagen in dit ontwerp",
"render.hdr_embedded_help": "Bij het renderen worden de bytes uit het ontwerp gebruikt; het oorspronkelijke bestand is niet meer nodig.",
"render.hdr_file_captured": "HDR-bestand gecontroleerd. Bij het opslaan worden deze bytes ingesloten; als het bestand verandert, controleer je het opnieuw expliciet.",
"render.hdr_inspect": "HDR-bestand controleren",
"render.hdr_inspect_required": "Selecteer en controleer een HDR-bestand voordat je opslaat of rendert.",
"render.hdr_primaries_declared": "De bron vermeldt de primaire kleuren.",
"render.hdr_primaries_srgb": "Primaire kleuren: sRGB/D65",
"render.hdr_primaries_undeclared": "De bron vermeldt geen primaire kleuren; controleer de kleurvereisten van de renderer.",
"render.hdr_resource_missing": "In dit ontwerp ontbreken de opgeslagen HDR-gegevens.",
"render.heading_batch": "BATCH",
"render.heading_frame": "FRAME",
"render.heading_lens": "LENS",
"render.heading_results": "RESULTATEN",
"render.heading_shots": "OPNAMEN",
"render.hide_shots_label": "Opnamestrook verbergen",
"render.image_advanced": "Geavanceerde GPU-instellingen",
"render.image_cancelled": "Render geannuleerd",
"render.image_cancelling": "Annuleren",
"render.image_completed": "Afbeelding klaar voor export",
"render.image_encoding": "PNG coderen",
"render.image_export": "PNG exporteren",
"render.image_exposure": "Belichting",
"render.image_failed": "Render mislukt",
"render.image_height": "Hoogte",
"render.image_help": "CPU-voorbeeldafbeelding · PNG · benaderde transparantie",
"render.image_host_missing": "Er is geen beeldhost geïnstalleerd.",
"render.image_method": "Beeldmethode",
"render.image_overwrite": "Bestaand bestand vervangen",
"render.image_preparing": "Afbeelding voorbereiden",
"render.image_progressive": "Progressief renderen",
"render.image_queued": "Wachten op renderen",
"render.image_reduce": "Probeer een kleinere afbeelding of eenvoudiger scène.",
"render.image_running": "Afbeelding renderen",
"render.image_samples": "Samples per pixel",
"render.image_scene_stale": "Voltooi de modelleerhandeling of vernieuw de scène voordat je de afbeelding controleert of de render start.",
"render.image_stale": "Deze afbeelding gebruikt de scène zoals vastgelegd vóór latere wijzigingen.",
"render.image_start": "Render starten",
"render.image_supported": "Het renderverzoek wordt ondersteund; de wachtrij en het geheugen worden bij het starten opnieuw gecontroleerd.",
@@ -1765,20 +2067,430 @@
"render.image_unknown": "Renderstatus niet beschikbaar",
"render.image_use_largest": "Grootste formaat met deze verhouding gebruiken:",
"render.image_width": "Breedte",
"render.include_rig_cards": "Passieve kaarten en vlaggen opnemen",
"render.inner_half_angle": "Halve binnenhoek",
"render.inspect_scene": "Samenvatting van vastgelegde scène vernieuwen",
"render.inspector": "Inspector",
"render.keep_editing": "Blijven bewerken",
"render.layer_down": "Omlaag verplaatsen",
"render.layer_enabled": "Laag ingeschakeld",
"render.layer_off_suffix": " (uit)",
"render.layer_remove": "Laag verwijderen",
"render.layer_strength": "Sterkte van laag",
"render.layer_up": "Omhoog verplaatsen",
"render.lens_effects_help": "Flare gebruikt maximaal vier gescheiden heldere bronnen in de werkelijke lineaire afbeelding. Spookbeelden, halo, strepen, chromatische verschuivingen en radiale vervorming zijn artistieke benaderingen in beeldruimte. Ruimtelijke effecten vereisen een dekkende uitvoer; samples buiten het beeld verlengen de beeldrand. Korrel is deterministisch. Er worden geen fysica, EXR of geometrie gewijzigd.",
"render.lens_effects_title": "Lensgeïnspireerd & fotografisch",
"render.library_all": "Catalogus",
"render.library_all_states": "Alle beschikbaarheidsstatussen",
"render.library_applied": "Projectie van de bron toegepast. Controleer de volledige renderopdracht voordat je start.",
"render.library_apply_hdr": "Opslaan met deze HDR-omgeving",
"render.library_apply_maps": "Ontworpen GPU-oppervlaktetexturen gebruiken",
"render.library_apply_studio": "Ontworpen studioprojectie opslaan",
"render.library_apply_uniform": "Uniform dekkend uiterlijk toepassen",
"render.library_authored_help": "Oorspronkelijk ontworpen bronnen zijn illustratief en geen gemeten technische gegevens. Elke actie past alleen de vermelde projectie toe.",
"render.library_blocked": "Geblokkeerd / vereist kalibratie",
"render.library_capabilities": "Specificaties van mogelijkheden",
"render.library_center": "Midden van rig",
"render.library_clear_search": "Wissen",
"render.library_details": "Specificatie en herkomst",
"render.library_emitters_only_ack": "Alleen lichtbronnen gebruiken; de gedocumenteerde passieve kaarten weglaten",
"render.library_empty": "Geen overeenkomende bronnen. Probeer een andere zoekopdracht of een ander beschikbaarheidsfilter.",
"render.library_environment_concepts": "Omgevingsconcepten",
"render.library_extent": "Omvang van het onderwerp",
"render.library_favorite": "Favoriet toevoegen",
"render.library_favorites": "Favorieten",
"render.library_hdr": "Ingebouwde HDR-omgevingen",
"render.library_hdr_help": "Sluit de oorspronkelijke HDR in de opgeslagen opstelling in. De ontworpen oorsprong van de lengtegraad wordt expliciet omgerekend; na het opslaan is geen extern bestand nodig.",
"render.library_inspect_only": "Selecteer om te inspecteren; er wordt niets automatisch toegepast. Favorieten en recente geschiedenis horen bij deze sessie van het geopende document.",
"render.library_light_concepts": "Lichtconcepten",
"render.library_maps_help": "Ingebouwde texturen kunnen worden opgeslagen met vastgemaakte bronnen en lokale toewijzing per voorkomen. Tijdelijke optische overschrijvingen blijven een aparte modus.",
"render.library_material_concepts": "Materiaalconcepten",
"render.library_native_scenes": "Eigen studio's",
"render.library_next": "Volgende pagina",
"render.library_omitted": "Niet inbegrepen",
"render.library_physical_profiles": "Fysieke referentieprofielen",
"render.library_previous": "Vorige pagina",
"render.library_quality_concepts": "Kwaliteitsspecificaties",
"render.library_recent": "Recent",
"render.library_replace_environment": "De bestaande omgeving expliciet vervangen",
"render.library_replace_studio": "Opgeslagen verlichting, omgeving en decor vervangen",
"render.library_results": "Overeenkomende bronnen",
"render.library_rig_help": "Eenmalig passend maken op een expliciet middelpunt en een fysieke omvang. Volledige rigs omvatten passieve kaarten; rigs die kalibratie vereisen, worden nog steeds geweigerd. Een voorzichtige speling tussen lichtbron en kaart wordt gecontroleerd voordat wordt opgeslagen.",
"render.library_rigs": "Ontworpen lichtrigs",
"render.library_save_maps": "Texturen opslaan in deze opstelling",
"render.library_scene_bounds": "Vastgelegde scènebegrenzing gebruiken",
"render.library_scenes": "Scènespecificaties",
"render.library_search": "Bibliotheek doorzoeken",
"render.library_select_hint": "Kies een bron in de bibliotheek om de ondersteunde acties en beperkingen te bekijken.",
"render.library_selene": "Dekkende SELENE-uiterlijken",
"render.library_selene_shots": "SELENE-opnamespecificaties",
"render.library_short_blocked": "Niet beschikbaar",
"render.library_short_native": "Eigen compositie",
"render.library_short_projection": "Ondersteunde projectie",
"render.library_short_reference": "Alleen referentie",
"render.library_short_specification": "Alleen specificatie",
"render.library_source_preview": "Voorbeeld van brontextuur laden",
"render.library_source_preview_help": "Ontworpen brontextuur voor de basiskleur. Dit is geen gerenderd of gemeten materiaalvoorbeeld.",
"render.library_specification_only": "Alleen specificatie: geen volledige uitvoerbare voorinstelling. Vereiste effecten, bronnen en onderwerprollen moeten nog expliciet worden geïmplementeerd en gekoppeld.",
"render.library_specs": "Alleen specificaties",
"render.library_status": "Beschikbaarheid",
"render.library_surfaces": "Zelf ontworpen PBR-oppervlakken",
"render.library_target": "Doellichaam",
"render.library_title": "Bibliotheek met renderbronnen",
"render.library_unfavorite": "Favoriet verwijderen",
"render.library_uniform_ack": "De uniforme benadering gebruiken zonder ruimtelijke of geavanceerde effecten",
"render.library_usable": "Uitvoerbare projecties",
"render.light_anchor_pending": "Het wijzigen van het coördinatensysteem van het licht wordt nog niet ondersteund.",
"render.lights_fixed_to": "Lichten vast aan",
"render.linear_help": "Bewaart een 32-bits float-RGBA-master vóór ruisonderdrukking, belichting, tone mapping, filters en achtergrond. Lineair sRGB/D65; met voorvermenigvuldigde dekking. Extra geheugen wordt expliciet toegestaan. Geen compressie of extra passes.",
"render.linear_retain": "Ruwe lineaire EXR bewaren",
"render.linear_unavailable": "Het geselecteerde voltooide frame heeft geen bewaarde EXR. Schakel bewaren in vóór het renderen; een oudere PNG kan de ruwe radiantie niet herstellen.",
"render.look_add": "Kleurlook toevoegen",
"render.look_bleach": "Geïnspireerd op bleach bypass",
"render.look_cool": "Koel",
"render.look_cyanotype": "Geïnspireerd op cyanotypie",
"render.look_faded": "Vervaagde afdruk",
"render.look_mono": "Monochroom",
"render.look_sepia": "Sepia",
"render.look_strength": "Sterkte van look",
"render.look_teal_orange": "Teal / oranje",
"render.look_title": "Stapel creatieve looks",
"render.look_warm": "Warm",
"render.mapping_scale": "Vermenigvuldiger voor fysieke herhaling",
"render.material_absorption": "Absorptie R · G · B (per mm)",
"render.material_add": "Dit lichaam toevoegen of bewerken",
"render.material_assignments": "Lichaamstoewijzingen",
"render.material_binding_enable": "Deze overschrijving voor het lichaam opnemen",
"render.material_box": "Kubus uitgelijnd op de assen",
"render.material_browse": "Afbeelding kiezen…",
"render.material_certification": "Gesloten glas gebruikt geometrische afstand. Topologie, oriëntatie, overlap en optische grenzen worden gecontroleerd tijdens de GPU-voorbereiding; Controleren laat alleen de aanvraag toe.",
"render.material_choose_body": "Kies een lichaam in de scène",
"render.material_closed": "Gesloten massieve mesh",
"render.material_coat": "Clearcoat over het basismateriaal",
"render.material_coat_enable": "Clearcoat inschakelen",
"render.material_coat_help": "Illustratieve diëlektrische coating over het bestaande ondoorzichtige uiterlijk. Gewicht nul laat de basis ongewijzigd.",
"render.material_color_map": "Basiskleurafbeelding (sRGB)",
"render.material_color_replace": "Basistextuur vervangt de lichaamskleur",
"render.material_custom": "Aangepaste illustratieve optiek",
"render.material_enable": "Deze GPU-materiaaloverschrijvingen gebruiken",
"render.material_filter": "Lichamen in de scène filteren…",
"render.material_filter_help": "Er worden maximaal 128 overeenkomende lichamen getoond. Verfijn het filter bij grote scènes.",
"render.material_glass": "Glas en optische absorptie",
"render.material_glass_enable": "Fysiek glas op dit lichaam gebruiken",
"render.material_glass_exclusive": "Glas kan in deze renderer een lichaam niet delen met clearcoat of runtimetexturen.",
"render.material_glass_help": "Originele illustratieve recepten. De stalen tonen transmissie, geen gerenderd voorbeeld. Absorptie is −ln(lineaire transmissie) / referentieafstand; alfa blijft ongewijzigd.",
"render.material_gpu_required": "Deze actieve materiaaloverschrijvingen vereisen GPU-pathtracing. Kies GPU of schakel de overschrijvingen uit vóór Controleren of Starten.",
"render.material_ior": "Brekingsindex (IOR)",
"render.material_limits": "Maximaal 128 lichaamsoverschrijvingen, 32 afzonderlijke glaslichamen, 64 coatings en 128 textuurkoppelingen. Identieke texturen delen opslag; de werkelijke limieten van apparaat en totaal geheugen blijven van kracht.",
"render.material_map_invalid": "De paden naar de afbeeldingen moeten begrensde lokale paden zijn; de normaalsterkte moet eindig zijn en tussen 0 en 1 liggen.",
"render.material_map_required": "Kies een kleurafbeelding of een normaalafbeelding voordat je texturen gebruikt.",
"render.material_maps": "Planaire kleur- en normaaltexturen",
"render.material_maps_enable": "Texturen inschakelen voor dit ondoorzichtige lichaam",
"render.material_maps_help": "PNG/JPEG tot 1024×1024; in totaal 16 MiB gecodeerd. U en V zijn orthogonale herhalingsvectoren in wereld-mm (maximaal 128 herhalingen). Kleur is sRGB; normaaldata gebruikt OpenGL +Y. Bestanden worden vastgelegd bij Controleren/Starten.",
"render.material_metallic_map": "Metallic-textuur (lineair)",
"render.material_normal_map": "Normaalafbeelding (OpenGL, +Y)",
"render.material_normal_strength": "Normaalsterkte (0–1)",
"render.material_origin": "Oorsprong van mapping X · Y · Z (mm)",
"render.material_refresh": "Lichamen in de scène vernieuwen",
"render.material_refresh_needed": "De scène is gewijzigd. Vernieuw de lijst met lichamen voordat je een doel toevoegt.",
"render.material_remove": "Deze toewijzing verwijderen",
"render.material_repeat_u": "Eén U-herhaling X · Y · Z (mm)",
"render.material_repeat_v": "Eén V-herhaling X · Y · Z (mm)",
"render.material_revalidate": "Dit lichaam opnieuw valideren",
"render.material_revalidate_needed": "Deze toewijzing hoort bij een eerdere revisie van de scène. Valideer de exacte lichaamsidentiteit opnieuw voordat je rendert.",
"render.material_roughness": "Ruwheid van coating (0,045–1)",
"render.material_roughness_map": "Ruwheidstextuur (lineair)",
"render.material_shadow": "Rechte schaduwstralen doorlaten",
"render.material_target_missing": "Het volgnummer en de naam van het lichaam komen niet meer overeen. Verwijder deze toewijzing en kies het bedoelde lichaam opnieuw, expliciet.",
"render.material_thickness": "Dikte dun vel (mm)",
"render.material_thin": "Dun vel",
"render.material_title": "GPU-afbeeldingsmaterialen",
"render.material_transient": "Tijdelijke optische overschrijvingen voor dit documenttabblad. Ze worden niet opgeslagen in het ontwerp, de renderopstelling of de materiaalbibliotheek.",
"render.material_v_up": "Textuur-V wijst omhoog in de afbeelding",
"render.material_weight": "Gewicht van coating (0–1)",
"render.method_cpu": "CPU-raytracing",
"render.method_gpu": "GPU-pathtracing",
"render.method_limit_raster": "Raster gebruikt het vaste, ondoorzichtige studiovoorbeeld. Kies een expliciete raytracingmethode voor ondersteunde optische instellingen.",
"render.method_raster": "CPU-raster",
"render.navigation_help": "De camera beweegt zoals in Ontwerp (Voorkeuren › Navigatie). Opstelling opslaan legt de huidige camera vast.",
"render.nested_enable": "Gecertificeerde geneste diëlektrica",
"render.nested_help": "Tot 16 omvattende lagen; elke bovenliggende laag moet convex zijn en elke onderliggende laag moet er strikt binnen liggen. Doorsnijdingen, rakende oppervlakken, dunne vellen en doorlating van rechte schaduwen worden geweigerd. De toestand met de camera binnenin volgt de gecertificeerde hiërarchie. Maakt geen vloeistofoppervlak en voegt rakende CAD-grenzen niet samen.",
"render.opaque_image_summary": "Voorbeeld-PNG · ondoorzichtige PBR · gemengde transparantie",
"render.opaque_preview_help": "Ondoorzichtige PBR en eenvoudige kleuren; gemengde transparantie. Breking, HDRI en eindrendering zijn nog niet beschikbaar.",
"render.optics_remove": "Opgeslagen optiek verwijderen",
"render.optics_replace": "De opgeslagen optiek van dit doel expliciet vervangen",
"render.optics_save": "Deze optiek opslaan in de opstelling",
"render.optics_saved": "Opgeslagen optische doelen",
"render.optics_saved_help": "De exacte identiteit van definitie, kenmerk en exemplaar blijft behouden bij offline heropenen. Ontbrekende, vervangen of verborgen doelen worden geweigerd; technische materialen blijven ongewijzigd. Sla numerieke bewerkingen op of verwerp ze voordat je een opgeslagen doel verwijdert.",
"render.outer_half_angle": "Buitenste halve hoek",
"render.output_format_status": "PNG is de exacte voltooide weergaveafbeelding. Optionele GPU-EXR bewaart de ruwe scènelineaire FLOAT32-radiantie vóór weergavefilters. Exporteren vervangt nooit de voorbeeldcache of een andere taak.",
"render.output_lock_ratio": "Beeldverhouding vergrendelen",
"render.output_over_budget": "De gevraagde afbeelding overschrijdt de limieten van de gekozen bronnen. Kies expliciet een compatibele grootte of een compatibel profiel; er vindt geen automatische verlaging plaats.",
"render.output_ratio_refused": "De gekoppelde afmeting overschrijdt de groottelimiet van deze methode. De vorige grootte blijft behouden; ontgrendel de verhouding of kies een kleinere waarde.",
"render.output_swap_orientation": "Breedte en hoogte omwisselen",
"render.output_tools_inspector": "Bewerk grootte en bestandsindeling in de inspecteur Uitvoer.",
"render.page_aging": "Veroudering en vervuiling",
"render.page_all": "Alle instellingen",
"render.page_appearance": "Uiterlijk",
"render.page_background": "Achtergronden",
"render.page_camera": "Camera",
"render.page_diagnostics": "Diagnostiek",
"render.page_effects": "Lens- en afwerkingseffecten",
"render.page_environment": "Omgeving",
"render.page_lighting": "Verlichting",
"render.page_output": "Uitvoer",
"render.page_scene": "Scène",
"render.paint_label": "Verf",
"render.passive_stage": "Vloer en passief decor",
"render.passive_stage_help": "Eindige passieve panelen horen alleen bij gerenderde afbeeldingen. Ze voegen geen CAD-lichamen of massa toe. De plaatsing staat vast na het toepassen; als ze de grenzen van het product snijden, worden ze geweigerd. CPU levert geen diffuse weerkaatste verlichting.",
"render.perspective": "Perspectiefcamera",
"render.physical_acknowledge": "Ik begrijp dat deze gedeeltelijke referentie een controle van kwaliteitsklasse, conditie en bron vereist",
"render.physical_associations": "Fysieke kandidaten en rollen",
"render.physical_background_help": "Echte passieve vloer en wand, los van de camera-achtergrond. Het cyclorama gebruikt 24 veelhoekige stroken; het is geen oneindig of analytisch glad oppervlak. Vervangt het opgeslagen decor alleen met jouw toestemming.",
"render.physical_copy_plan": "Plan kopiëren met bronnen en weglatingen",
"render.physical_cyclorama": "Veelhoekig cyclorama passend maken",
"render.physical_floor_wall": "Fysieke vloer en wand passend maken",
"render.physical_material_name": "Voorgestelde naam van het referentiemateriaal",
"render.physical_omissions": "Eigenschappen die de eigen materiaalkaart niet kan weergeven",
"render.physical_plan_only": "Alleen-lezenplan voorbereid. Er is geen materiaal gemaakt of toegewezen. Behoud het uitgebreide profiel en de weglatingen bij het beoordelen van de eigen materiaalkaart.",
"render.physical_prepare_plan": "Aanmaakplan voorbereiden (wordt niet toegepast)",
"render.physical_separate": "Uiterlijk is geen materiaalidentificatie. Dit zijn referenties met bronvermelding, geen gecertificeerde effectieve eigenschappen. Bestaande massa, technische materialen en optiek blijven ongewijzigd.",
"render.physical_unknown": "Er is geen numerieke kandidaatwaarde vastgesteld. Kwaliteit, samenstelling of constructie moet worden opgegeven; onbekend is niet nul.",
"render.pick_body": "Lichaam",
"render.pick_component": "Component",
"render.pick_face": "Vlak",
"render.pick_help": "Kies Lichaam, Vlak of Component. Klik op lege ruimte om de selectie te wissen; Shift of Ctrl voegt toe of schakelt om. Markeringen verschijnen alleen in de live productweergave.",
"render.pick_label": "Kiezen",
"render.pick_up_label": "Overnemen",
"render.pick_waiting": "Kiezen in de productweergave wordt nog niet ondersteund.",
"render.post_contrast": "Contrast",
"render.post_gain_b": "Versterking blauw",
"render.post_gain_g": "Versterking groen",
"render.post_gain_r": "Versterking rood",
"render.post_help": "Alleen voor creatieve presentatie. De RGB-versterkingen gaan vooraf aan de tone mapping; contrast, verzadiging en vignettering volgen in weergavelineair licht. Render starten maakt nieuwe transportsamples. Een nieuwe kleurcorrectie gebruikt de gekozen bewaarde ruwe master zonder ruisonderdrukking of nieuwe stralen.",
"render.post_reset": "Presentatiefilters herstellen",
"render.post_saturation": "Verzadiging",
"render.post_title": "Presentatiefilters",
"render.post_vignette": "Vignettering",
"render.preview": "Geïntegreerd voorbeeld",
"render.preview_help": "Rasterschaduw en gemengde transparantie. Breking, HDRI en eindrendering zijn nog niet beschikbaar.",
"render.preview_image_settings_help": "Het live voorbeeld behoudt vaste studioverlichting. Belichting en beeldverlichting gelden voor de afbeeldingstaak wanneer je Controleren of Starten kiest.",
"render.preview_lighting_help": "Het live voorbeeld toont alleen direct licht en geen schaduwen.",
"render.preview_retry": "Live voorbeeld opnieuw proberen",
"render.preview_unavailable_help": "Het live voorbeeld is niet beschikbaar. Opgeslagen opstellingen en de besturing van afbeeldingstaken blijven toegankelijk. Wijzig de scène of probeer het expliciet opnieuw; een geweigerde scène wordt niet bij elk frame opnieuw opgebouwd.",
"render.preview_upload": "Hoekpuntgegevens van live voorbeeld",
"render.preview_upload_help": "Exacte bytes van de voorbeeldhoekpunten, niet het totale GPU- of procesgeheugen. De geometrie wordt niet vereenvoudigd. Afbeeldingstaken hebben hun eigen toelating en verlichting.",
"render.progressive_image_summary": "Voorbeeld-PNG · PBR en glas · progressieve samples",
"render.property_conditions": "Voorwaarden: {value}",
"render.property_fallback": "eigenschap",
"render.property_qualifier": "Kwalificatie: {value}",
"render.property_source": "Bron: {id} - {locator}",
"render.property_uncertainty": "Onzekerheid: {value}",
"render.property_unknown": "onbekend",
"render.quality_ack": "De projectie met vast budget en de weglatingen bevestigen",
"render.quality_apply": "Dit vaste samplingbudget gebruiken",
"render.quality_projection_help": "De Q-voorinstellingen bevatten toekomstige vereisten. Deze actie projecteert alleen een ondersteund PNG-budget met een vast aantal samples en laat adaptief stoppen, ruwe lineaire uitvoer en onafhankelijke transmissielimieten uitdrukkelijk weg.",
"render.quality_review": "Samplingbudget beoordelen",
"render.queue_pending": "Deze UI heeft geen automatische productiewachtrij of animatierenderer. Voltooide stilstaande beelden blijven afzonderlijk exporteerbaar.",
"render.radial_distortion": "Radiale vervorming",
"render.regrade_action": "Ruwe master opnieuw kleurcorrigeren (geen ruisonderdrukking)",
"render.regrade_help": "Maakt een afzonderlijke PNG van de gekozen voltooide ruwe master met deze presentatiebesturing. Traceert geen stralen, wijzigt de vastgelegde grootte, camera en lichten niet en overschrijft de EXR niet. Ruisonderdrukking wordt niet opnieuw toegepast: ruwe masters bewaren de bijbehorende hulpkanalen niet. Het afgeleide beeld blijft exporteerbaar via dezelfde taakbesturing.",
"render.regrade_label": "Nieuwe kleurcorrectie",
"render.reload_settings": "Opgeslagen instellingen opnieuw laden",
"render.replace_ground": "Vervanging van het bestaande renderdecor bevestigen",
"render.replace_label": "Vervangen",
"render.replace_saved_surface": "Een bestaande opgeslagen koppeling voor dit doel vervangen",
"render.restore_camera": "Opgeslagen camera herstellen",
"render.result_actual_help": "Eén beeldpixel per schermpixel.",
"render.result_actual_size": "100%",
"render.result_capture": "Vastgelegde revisie",
"render.result_current": "De vastgelegde modelrevisie is actueel.",
"render.result_empty": "Nog geen voltooide afbeelding. Controleer de instellingen en start dan een render.",
"render.result_fit": "Afbeelding passend maken",
"render.result_job": "Taak",
"render.result_navigation": "Pannen en zoomen volgen de navigatievoorkeuren. Spatie + slepen pant.",
"render.result_open": "De voltooide afbeelding openen in het hoofdcanvas.",
"render.result_preview": "Live voorbeeld",
"render.result_provisional": "Voorlopige CPU-afbeelding",
"render.result_provisional_help": "Dit controlepunt is niet exporteerbaar. Exporteren behoudt het laatste voltooide resultaat; annuleren keert terug naar dat resultaat.",
"render.result_reduced_display": "Het weergavevoorbeeld is verkleind tot de limiet van het viewportapparaat of de cache. De bewaarde PNG en de export behouden de volledige resolutie; natieve 100%-inspectie is voor deze verkleinde weergave niet beschikbaar.",
"render.result_retained": "De laatste voltooide afbeelding wordt getoond; een nieuwere render heeft die nog niet vervangen.",
"render.result_sequence": "Controlepunt",
"render.result_title": "Renderresultaat",
"render.return_design": "Terug naar Ontwerp",
"render.review_stale": "Deze beoordeling is verouderd. Los het op of controleer opnieuw voordat je toepast.",
"render.ribbon_aging": "Veroudering",
"render.ribbon_backgrounds": "Achtergronden",
"render.ribbon_check": "Controleren",
"render.ribbon_check_help": "Valideert het exacte huidige concept dat Render indient. Geen terugval op een andere renderer, geen stille formaatwijziging en geen vervanging van bronnen.",
"render.ribbon_edit_lights": "Lichten bewerken",
"render.ribbon_effects": "Effecten",
"render.ribbon_environment_help": "HDR-verlichting, achtergronden die alleen voor de camera zichtbaar zijn en fysieke decoroppervlakken zijn afzonderlijke besturingen met uitdrukkelijke toestemming voor vervanging.",
"render.ribbon_finish_dialog": "Rond eerst het huidige bestands- of bevestigingsvenster af.",
"render.ribbon_frame": "Inkaderen",
"render.ribbon_hdr_library": "HDR-bibliotheek",
"render.ribbon_job_active": "Er loopt al een render; annuleer die expliciet voordat je een andere start.",
"render.ribbon_light_rigs": "Lichtopstellingen",
"render.ribbon_lights_help": "Bekijk de ontworpen lichtopstellingen of bewerk ondersteunde lichten zonder de huidige opstelling te vervangen totdat je de wijziging expliciet toepast.",
"render.ribbon_materials": "Materialen",
"render.ribbon_materials_help": "Opent de gedeelde uiterlijkinspector en de originele oppervlaktebibliotheek. Optische wijzigingen veranderen nooit stilzwijgend technische eigenschappen.",
"render.ribbon_no_active_job": "Er is geen actieve render om te annuleren.",
"render.ribbon_no_result": "Voltooi een render voordat je de exacte afbeelding exporteert.",
"render.ribbon_no_saved_camera": "Sla een opname op voordat je de bijbehorende camera herstelt.",
"render.ribbon_saved_camera": "Opgeslagen camera",
"render.ribbon_shots": "Opnamen",
"render.ribbon_studios": "Studio's",
"render.ribbon_studios_help": "Blader door geïmplementeerde studiocomposities en bekijk wat ze vervangen voordat je ze toepast. Scènes die alleen een concept zijn, blijven als zodanig gemarkeerd.",
"render.ribbon_surface_maps": "Oppervlaktemaps",
"render.sampling_title": "Adaptieve sampling en transmissiesampling",
"render.save_continue": "Opslaan en doorgaan",
"render.save_setup": "Opstelling opslaan",
"render.save_shot": "Opname opslaan",
"render.saved_maps_runtime_conflict": "Opgeslagen oppervlaktekoppelingen kunnen niet worden gecombineerd met tijdelijke optische overschrijvingen of een niet-opgeslagen HDR. Sla de HDR op of verwijder de tijdelijke invoer expliciet.",
"render.saved_surface_remove": "Opgeslagen koppeling verwijderen",
"render.saved_surfaces": "Opgeslagen oppervlaktekoppelingen",
"render.saved_surfaces_help": "Vastgemaakte ingebouwde maps volgen het gekozen exemplaar in lokale millimeters. Een vervangen of ontbrekend doel is een fout, nooit een automatische hertoewijzing.",
"render.scene_apply": "Beoordeelde studio toepassen",
"render.scene_consent": "Vervanging van verlichting, omgeving, belichting en renderdecor bevestigen",
"render.scene_preserved_fields": "Camera, sampling, afmetingen, optische koppelingen, CAD-geometrie en technische materialen blijven behouden.",
"render.scene_preserves_design": "Stelt verlichting en een passief decor samen voor het zichtbare onderwerp. Geometrie, technische materialen en de camera blijven afzonderlijk.",
"render.scene_replaces": "Vervangt",
"render.scene_review": "Uitwerken en beoordelen",
"render.scene_review_help": "Bekijk de volledige native compositie voordat je toepast. Niet-gekoppelde geavanceerde SCENE-specificaties worden niet door een alternatief vervangen.",
"render.scene_scope_details": "Reikwijdte van de compositie",
"render.setup_legacy_environment": "Deze oudere opstelling gebruikt verouderde omgevingsrotatie of -intensiteit. Die waarden blijven behouden; converteer ze expliciet voordat je een volledige afbeeldingstaak opslaat.",
"render.setup_name": "Naam van opstelling",
"render.setup_numeric_help": "Opslaan legt de actieve afbeeldingsmethode en alle bijbehorende numerieke instellingen vast. Opnieuw laden of een andere opstelling kiezen vervangt dit concept; herstel de camera afzonderlijk.",
"render.setup_offline_help": "Je kunt deze methode bewerken en opslaan zonder de renderer. Controleren en Starten vereisen een beschikbare host.",
"render.setup_runtime_unsupported": "Deze volledige taak kan nog niet worden opgeslagen: ze bevat maps of koppelingen met scènelichamen. Verwijder die tijdelijke invoer voordat je een draagbare opstelling opslaat.",
"render.setup_save_missing": "De opgeslagen renderconfiguratie is na het voltooien van de opdracht niet gevonden.",
"render.sharpening": "Detailverscherping",
"render.shell_tab_appearance": "RENDER-UITERLIJK",
"render.shell_tab_camera": "RENDER-CAMERA",
"render.shell_tab_scene": "RENDER-SCÈNE",
"render.shot_duplicate": "Opgeslagen opname dupliceren",
"render.shot_manager": "Opgeslagen opnamen",
"render.shot_new_name": "Naam van nieuwe opname",
"render.shot_remove": "Opgeslagen opname verwijderen",
"render.shot_remove_help": "Verwijdert alleen deze opgeslagen opstelling. De brongeometrie en voltooide afbeeldingen blijven behouden; de actie kan ongedaan worden gemaakt.",
"render.shot_remove_title": "Opgeslagen opname verwijderen?",
"render.shot_rename": "Opgeslagen opname hernoemen",
"render.shot_saved_only": "Sla eerst het huidige concept op. Dupliceren en hernoemen behouden de exacte opgeslagen opties en bronverwijzingen.",
"render.show_shots_label": "Opnamenstrook tonen",
"render.size_4k_uhd": "4K UHD",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.sky_ground": "Vloer · lineair RGB",
"render.sky_horizon": "Horizon · lineair RGB",
"render.sky_zenith": "Zenit · lineair RGB",
"render.soft_focus": "Zachte focus",
"render.spot_cone": "Spotkegel",
"render.stage_frame": "Kader",
"render.stage_light": "Licht",
"render.stage_look": "Look",
"render.stage_orthographic": "Orthografisch",
"render.stage_output": "Uitvoer",
"render.stage_panel_count": "Opgeslagen panelen",
"render.stage_preview_note": "Geïntegreerd voorbeeld · direct licht",
"render.strip_label": "Opnamestrook",
"render.studio_add_area": "Oppervlaktelicht toevoegen",
"render.studio_ambient": "Constante omgevingsstraling",
"render.studio_ambient_rgb": "Constante omgevingsstraling (lineair RGB)",
"render.studio_aperture": "Diafragmastraal",
"render.studio_area": "Oppervlaktelicht",
"render.studio_area_help": "Maximaal vier eenzijdige rechthoeken. Loodrechte halve randen U en V bepalen de grootte; U × V wijst naar de verlichte zijde. Coördinaten zijn wereldcoördinaten in millimeter.",
"render.studio_center": "Midden X, Y, Z (mm)",
"render.studio_denoise": "Ruis verminderen in de voltooide afbeelding",
"render.studio_denoise_help": "Laatste randbehoudende filter; fijne details kunnen zachter worden. Glas en scherpe spiegelende oppervlakken omzeilen het filter.",
"render.studio_direction": "Richting naar de zon (X, Y, Z)",
"render.studio_environment": "Omgeving",
"render.studio_environment_bounds": "De omgevingsrotatie moet een eindig getal binnen ±1.000.000 radialen zijn en de intensiteit moet tussen 0 en 100 liggen.",
"render.studio_environment_none": "Geen omgevingskaart",
"render.studio_focus": "Axiale scherpstelafstand",
"render.studio_half_u": "Halve rand U (mm)",
"render.studio_half_v": "Halve rand V (mm)",
"render.studio_hdr": "Radiance HDR-bestand",
"render.studio_hdr_browse": "HDR kiezen…",
"render.studio_hdr_help": "Radiance .hdr, 2:1-panorama, tot 2048 × 1024. EXR is niet beschikbaar. De kleuraanname geldt alleen als de primaire kleuren niet zijn opgegeven.",
"render.studio_hdr_required": "Kies een lokaal .hdr-bestand.",
"render.studio_hdr_srgb": "Niet-opgegeven primaire kleuren interpreteren als lineair sRGB",
"render.studio_intensity": "Intensiteit van de omgeving",
"render.studio_lens": "Scherptediepte",
"render.studio_lens_perspective": "Scherptediepte vereist een perspectiefcamera.",
"render.studio_lighting": "Studioverlichting",
"render.studio_lighting_enable": "Aangepaste studioverlichting gebruiken",
"render.studio_needs_review": "Methode en instellingen controleren",
"render.studio_radiance": "Lineaire RGB-straling",
"render.studio_ready": "Gereed voor controle",
"render.studio_remove_area": "Oppervlaktelicht verwijderen",
"render.studio_rotation": "Omgevingsrotatie",
"render.studio_runtime_help": "Numerieke studio-instellingen en gecontroleerde HDR-bronnen kunnen met de opstelling worden opgeslagen. Optische en materiaaloverschrijvingen per lichaam blijven tijdelijk en wijzigen opgeslagen uiterlijken niet.",
"render.studio_saved": "Opgeslagen opstelling / huidige camera",
"render.studio_sky": "Artistieke hemel",
"render.studio_sky_help": "Oorspronkelijk hemelverloop voor de verlichting; geen gekalibreerd atmosfeermodel.",
"render.studio_sun": "Zon",
"render.studio_sun_radius": "Hoekstraal",
"render.studio_title": "Renderstudio",
"render.studio_tone_map": "Tone mapping",
"render.subsurface_enable": "Random walk voor inwendige verstrooiing",
"render.subsurface_help": "Alleen voor gesloten diëlektrica. Verstrooiing en RGB-absorptie zijn aparte coëfficiënten per mm. Paden verstrooien binnen de werkelijke geometrie en breken of reflecteren daarna aan de grens. Schakel rechte schaduwtransmissie, ruisonderdrukking van oppervlakken en uitwendig volume uit; gebruik één Fresnel-stratum. Dit is geen diffusieshader, dichtheidsraster of gemeten materiaal. Dichte media kunnen meer samples en een grotere paddiepte nodig hebben.",
"render.subsurface_rate": "Botsingsfrequentie van verstrooiing",
"render.tone_aces_fitted": "ACES-benadering",
"render.tone_reinhard": "Reinhard",
"render.transmission_scope": "Glas op de GPU ondersteunt gecertificeerde, niet-overlappende media. Onbeperkt geneste media en een ruisvrije transmissieschatter zijn niet beschikbaar.",
"render.transmission_strata": "Voorwaardelijke Fresnel-strata",
"render.transmission_strata_help": "1 behoudt de oorspronkelijke stroom. 2 of 4 subpaden stratificeren de eerste keuze tussen reflectie en transmissie aan glas, met ongewijzigde wetten van Snellius en absorptie. Meer paden kosten meer rekenwerk; dit is geen ruisonderdrukking, geen ondersteuning voor geneste media en geen belofte van sneller renderen.",
"render.tree_add_light": "Licht toevoegen",
"render.tree_add_shot": "Opname toevoegen",
"render.tree_browser": "Renderbrowser",
"render.tree_by_look": "Per look",
"render.tree_by_object": "Per object",
"render.tree_constant": "Constante omgeving",
"render.tree_default": "Standaard",
"render.tree_directional": "Richtingslicht",
"render.tree_environment": "Omgeving",
"render.tree_environment_values": "{rotation}° · {intensity}×",
"render.tree_face_count": "{count} vlakken",
"render.tree_face_one": "{count} vlak",
"render.tree_fixed_studio": "Vaste studio",
"render.tree_hdr": "HDR",
"render.tree_lights": "Lichten",
"render.tree_lights_pending": "Opdrachten voor benoemde lichten zijn nog niet beschikbaar.",
"render.tree_mixed": "Gemengd",
"render.tree_more": "{count} meer",
"render.tree_mute": "Licht dempen",
"render.tree_no_environment": "Geen omgeving",
"render.tree_objects": "Objecten",
"render.tree_output": "Uitvoer",
"render.tree_point": "Punt",
"render.tree_rectangle": "Rechthoek",
"render.tree_search": "Objecten zoeken",
"render.tree_selection": "Renderselectie",
"render.tree_shots": "Opnamen",
"render.tree_sky": "Hemel",
"render.tree_solo": "Licht solo",
"render.tree_spot": "Spot",
"render.tree_sun": "Zon",
"render.tree_switch": "Overschakelen",
"render.tree_user_one": "{count} object",
"render.tree_users": "{count} objecten",
"render.unavailable_preview": "Deze opstelling vraagt een niet-beschikbaar voorbeeldprofiel aan.",
"render.unsaved": "Niet-opgeslagen wijzigingen in voorbeeld",
"render.use_preview": "Geïntegreerd voorbeeld gebruiken",
"render.volume_albedo": "Verstrooiingsalbedo · lineair RGB",
"render.volume_anisotropy": "Gemiddelde fasecosinus",
"render.volume_enable": "Participerend medium inschakelen",
"render.volume_extinction": "Extinctiecoëfficiënt",
"render.volume_help": "GPU-transport binnen één eindige kubus, met Beer-demping en HG-verstrooiing op camerapaden en indirecte paden. Gebruikt expliciete studio-, HDR- of hemelverlichting, inclusief schaduwdemping. Een positieve fasecosinus verstrooit voorwaarts. Glasgrenzen en ruisonderdrukking van oppervlakken moeten uitdrukkelijk worden uitgeschakeld. Bij extinctie nul blijft het transport ongewijzigd. Geen fysieke maanatmosfeer, dichtheidsraster, volume-emissie, spectraal transport of gecertificeerde materiaaleigenschap.",
"render.volume_max": "Maximale grenzen · wereld, mm",
"render.volume_min": "Minimale grenzen · wereld, mm",
"render.volume_title": "Begrensd homogeen volume",
"render.wait_batch": "nog niet ondersteund: de renderwachtrij voor opgeslagen opnamen",
"render.wait_compare": "nog niet ondersteund: vergelijking van bewaarde afbeeldingen",
"render.wait_paint": "nog niet ondersteund: producten kiezen en uiterlijken schilderen",
"render.wait_pick_up": "nog niet ondersteund: producten kiezen en uiterlijken overnemen",
"render.wait_replace": "nog niet ondersteund: alle toepassingen van een uiterlijk vervangen",
"render.wait_solo": "nog niet ondersteund: lichtzichtbaarheid en solo-bediening",
"sample.bracket.about": "Basisflens met randflenzen en een zoom op een regel van 2 mm",
"sample.bracket.name": "Plaatwerkbeugel",
"sample.enclosure.about": "Uitgeholde doos met een lip, schroefnokken, een rustvlak en een snapverbinding",
+4
View File
@@ -26,6 +26,7 @@
"All open designs": "Wszystkie otwarte projekty",
"Allowed expressions, separated by semicolons": "Dozwolone wyrażenia, rozdzielone średnikami",
"Also deletes": "Usuwa również",
"Also place them from the origin (fully constrained)": "Umieść je też względem początku (w pełni związane)",
"Angle 2": "Kąt 2",
"Animate": "Animuj",
"App/system information and command settings are included. Review private details before sharing.": "Dołączone są informacje o aplikacji i systemie oraz ustawienia poleceń. Przed udostępnieniem sprawdź, czy nie ma tam prywatnych danych.",
@@ -118,6 +119,7 @@
"Describe what happened before continuing.": "Zanim przejdziesz dalej, opisz, co się stało.",
"Designs you open or save appear here.": "Tutaj pojawiają się otwierane lub zapisywane projekty.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Wynika z opcji Do obiektu. Wybierz Kąt, aby edytować zakres kątowy.",
"Dimension new shapes": "Wymiaruj nowe kształty",
"Direction": "Kierunek",
"Discard": "Odrzuć",
"Do not export hidden edges": "Nie eksportuj krawędzi niewidocznych",
@@ -131,6 +133,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Przeciągnij, aby obrócić podparcie co 5°. Przytrzymaj Alt lub Ctrl, aby obracać swobodnie.",
"Drive Joint": "Steruj złączem",
"Duration": "Czas trwania",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Każdy nowy kształt otrzymuje też wymiary od początku szkicu, aż nic nie pozostanie swobodne. Kształt już połączony z początkiem lub z umieszczoną geometrią nie otrzymuje żadnych.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Każdy narysowany kształt otrzymuje wszystkie swoje wymiary w narysowanych rozmiarach (wpisane wartości mają pierwszeństwo). Rozmiar, który szkic już określa, jest pomijany.",
"Edges": "Krawędzie",
"Edit": "Edytuj",
"Edit Profile Sketch": "Edytuj szkic profilu",
+4
View File
@@ -30,6 +30,7 @@
"All open designs": "Todos os projetos abertos",
"Allowed expressions, separated by semicolons": "Expressões permitidas, separadas por ponto e vírgula",
"Also deletes": "Também exclui",
"Also place them from the origin (fully constrained)": "Posicioná-las também a partir da origem (totalmente restritas)",
"Angle 2": "Ângulo 2",
"Animate": "Animar",
"App/system information and command settings are included. Review private details before sharing.": "Informações do aplicativo/sistema e configurações estão incluídas. Revise detalhes privados antes de compartilhar.",
@@ -145,6 +146,7 @@
"Designs you open or save appear here.": "Os projetos que você abrir ou salvar aparecem aqui.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Determinado por Até o objeto. Escolha Ângulo para editar a extensão angular.",
"Diameter": "Diâmetro",
"Dimension new shapes": "Cotar novas formas",
"Direction": "Direção",
"Discard": "Descartar",
"Distance": "Distância",
@@ -155,6 +157,8 @@
"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": "Clique duplo com o botão do meio na vista: Início (a vista inicial, enquadrando o que é mostrado), Ajustar (enquadra o que é mostrado, mantendo a orientação) ou nada",
"Drive Joint": "Acionar junta",
"Duration": "Duração",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Cada nova forma também recebe cotas a partir da origem do esboço até nada ficar livre. Uma forma já ligada à origem ou a uma geometria posicionada não recebe nenhuma.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Cada forma que você desenha recebe todas as suas cotas nos tamanhos desenhados (valores digitados têm prioridade). Um tamanho que o esboço já define é omitido.",
"Edges": "Arestas",
"Edit": "Editar",
"Edit Profile Sketch": "Editar esboço do perfil",
+951 -1
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -37,6 +37,7 @@
"All open designs": "Все открытые дизайны",
"Allowed expressions, separated by semicolons": "Разрешённые выражения через точку с запятой",
"Also deletes": "Также удаляет",
"Also place them from the origin (fully constrained)": "Также привязывать к началу координат (полностью определено)",
"Anchor": "Опорная точка",
"Angle 2": "Угол 2",
"Angle Display": "Отображение углов",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Здесь появляются открытые и сохранённые дизайны.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Определяется параметром «До объекта». Выберите «Угол», чтобы задать угловой предел.",
"Diameter": "Диаметр",
"Dimension new shapes": "Проставлять размеры новых фигур",
"Direction": "Направление",
"Discard": "Отменить",
"Distance": "Расстояние",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Перетащите, чтобы повернуть опору с шагом 5°. Удерживайте Alt или Ctrl, чтобы поворачивать свободно.",
"Drive Joint": "Привод сопряжения",
"Duration": "Длительность",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Каждая новая фигура также получает размеры от начала координат эскиза, пока в ней не останется ничего свободного. Фигура, уже привязанная к началу или к размещённой геометрии, их не получает.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Каждая нарисованная фигура получает все свои размеры по нарисованным величинам (введённые значения важнее). Размер, который эскиз уже задаёт, пропускается.",
"Edges": "Рёбра",
"Edit": "Изменить",
"Edit Profile Sketch": "Редактировать эскиз профиля",
File diff suppressed because it is too large Load Diff
+4
View File
@@ -37,6 +37,7 @@
"All open designs": "Alla öppna konstruktioner",
"Allowed expressions, separated by semicolons": "Tillåtna uttryck, avgränsade med semikolon",
"Also deletes": "Tar även bort",
"Also place them from the origin (fully constrained)": "Placera dem också från origo (helt bestämda)",
"Anchor": "Ankare",
"Angle 2": "Vinkel 2",
"Angle Display": "Vinkelvisning",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Konstruktioner du öppnar eller sparar visas här.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Bestäms av Till objekt. Välj Vinkel för att redigera vinkelutsträckningen.",
"Diameter": "Diameter",
"Dimension new shapes": "Måttsätt nya former",
"Direction": "Riktning",
"Discard": "Förkasta",
"Distance": "Avstånd",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Dra för att vrida stödet i steg om 5°. Håll Alt eller Ctrl för att vrida det fritt.",
"Drive Joint": "Drivled",
"Duration": "Varaktighet",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Varje ny form får också mått från skissens origo tills inget av den är fritt. En form som redan sitter i origo eller i placerad geometri får inga.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Varje form du ritar får alla sina mått i de ritade storlekarna (inskrivna värden har företräde). En storlek som skissen redan bestämmer utelämnas.",
"Edges": "Kanter",
"Edit": "Redigera",
"Edit Profile Sketch": "Redigera profilskiss",
+4
View File
@@ -37,6 +37,7 @@
"All open designs": "Tüm açık tasarımlar",
"Allowed expressions, separated by semicolons": "Noktalı virgülle ayrılmış izin verilen ifadeler",
"Also deletes": "Bunları da siler",
"Also place them from the origin (fully constrained)": "Orijinden de konumlandır (tam kısıtlı)",
"Anchor": "Çapa",
"Angle 2": "Açı 2",
"Angle Display": "Açı görünümü",
@@ -170,6 +171,7 @@
"Designs you open or save appear here.": "Açtığınız veya kaydettiğiniz tasarımlar burada görünür.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Nesneye kadar seçeneğiyle belirlenir. Açısal kapsamı düzenlemek için Açı seçeneğini seçin.",
"Diameter": "Çap",
"Dimension new shapes": "Yeni şekillere ölçü ver",
"Direction": "Yön",
"Discard": "At",
"Distance": "Mesafe",
@@ -186,6 +188,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "Dayamayı 5° adımlarla çevirmek için sürükleyin. Serbestçe çevirmek için Alt veya Ctrl tuşunu basılı tutun.",
"Drive Joint": "Bağlantıyı tahrik et",
"Duration": "Süre",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Her yeni şekle, serbest bir şey kalmayana kadar çizim orijininden de ölçü verilir. Orijine veya yerleştirilmiş geometriye zaten bağlı bir şekle verilmez.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Çizdiğiniz her şekil, çizdiğiniz boyutlarda tüm ölçülerini alır (yazılan değerler önceliklidir). Çizimin zaten belirlediği bir boyut atlanır.",
"Edges": "Kenarlar",
"Edit": "Düzenle",
"Edit Profile Sketch": "Profil eskizini düzenle",
+1127 -921
View File
File diff suppressed because it is too large Load Diff
+88
View File
@@ -38,6 +38,7 @@
"All open designs": "Tất cả thiết kế đang mở",
"Allowed expressions, separated by semicolons": "Các biểu thức hợp lệ, phân tách bằng dấu chấm phẩy",
"Also deletes": "Đồng thời xóa",
"Also place them from the origin (fully constrained)": "Đồng thời định vị từ gốc tọa độ (ràng buộc hoàn toàn)",
"Anchor": "Điểm neo",
"Angle 2": "Góc 2",
"Angle Display": "Hiển thị góc",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "Các thiết kế bạn mở hoặc lưu sẽ xuất hiện tại đây.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Được xác định theo Đến đối tượng (To Object). Chọn Góc để chỉnh sửa góc mở rộng.",
"Diameter": "Đường kính",
"Dimension new shapes": "Ghi kích thước cho hình mới",
"Direction": "Hướng",
"Discard": "Hủy bỏ thay đổi",
"Distance": "Khoảng cách",
@@ -196,6 +198,8 @@
"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",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "Mỗi hình mới cũng được ghi kích thước từ gốc phác thảo cho đến khi không còn phần nào tự do. Hình đã gắn với gốc hoặc với hình học đã đặt sẽ không nhận thêm.",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "Mỗi hình bạn vẽ nhận đủ các kích thước theo cỡ đã vẽ (giá trị nhập tay được ưu tiên). Kích thước mà bản phác thảo đã xác định sẽ được bỏ qua.",
"Edge": "Cạnh",
"Edges": "Các cạnh",
"Edit": "Sửa",
@@ -254,6 +258,8 @@
"Flanges": "Gờ viền (Flanges)",
"Flat Pattern": "Bản khai triển phẳng",
"Flat size": "Kích thước phôi phẳng",
"Flat size X": "Kích thước phôi phẳng X",
"Flat size Y": "Kích thước phôi phẳng Y",
"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ữ",
@@ -812,7 +818,9 @@
"cmd.component_create": "Tạo mới Cụm chi tiết",
"cmd.component_cycle_color": "Đổi màu cụm chi tiết xoay vòng",
"cmd.component_delete": "Xóa Cụm chi tiết",
"cmd.component_edit_in_place": "Chỉnh sửa tại chỗ",
"cmd.component_extract": "Trích xuất ra tệp riêng",
"cmd.component_finish_edit": "Hoàn tất chỉnh sửa",
"cmd.component_from_bodies": "Tạo cụm chi tiết từ các thân khối",
"cmd.component_insert_design": "Chèn thiết kế vào cụm",
"cmd.component_links": "Danh sách liên kết",
@@ -1171,6 +1179,7 @@
"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_angle_readout": "Góc hướng nhìn",
"cmd.view_apply": "Áp dụng góc nhìn đã lưu",
"cmd.view_back": "Góc nhìn phía sau",
"cmd.view_bottom": "Góc nhìn từ dưới",
@@ -1305,6 +1314,7 @@
"help.appearance.assign": "Gán màu hoặc vẻ ngoài vật liệu cho các khối, mặt hoặc thành phần đã chọn mà không thay đổi khối lượng. Dùng để phân biệt các chi tiết hoặc xem trước lớp hoàn thiện.",
"help.attributions": "Ghi công (ATTRIBUTION.md)",
"help.build": "Phiên bản {version} · commit {commit} · dựng ngày {date}",
"help.component.finish_edit": "Lưu chi tiết đang được chỉnh sửa tại chỗ, quay lại cụm lắp ráp của nó và cập nhật cụm lắp ráp từ chi tiết đó. Dùng khi bạn đã hoàn tất các thay đổi cho chi tiết liên kết.",
"help.connect_note": "Khởi động lại từng trợ lý ảo để nạp SolidCraft server. Mỗi tập tin cấu hình đều đã được sao lưu thành .bak trước khi thay đổi.",
"help.connect_title": "Kết nối trợ lý ảo AI",
"help.face.delete": "Xóa các mặt đã chọn và để các mặt lân cận khép kín chỗ trống, hoặc giữ lỗ hở dưới dạng bề mặt. Dùng để bỏ một cạnh bo tròn, một lỗ hoặc một phần lồi đang vướng.",
@@ -1782,8 +1792,12 @@
"prefs.layout_note": "Chế độ Gọn (Compact) gắn các bảng vào mép cửa sổ. Độ trong suốt của Cây thư mục chỉ khả dụng ở chế độ Nổi (Floating). Thay đổi vị trí của Trợ lý trong trang Trợ lý.",
"prefs.left": "Bên trái",
"prefs.left_click": "Nhấp chuột trái",
"prefs.linked_designs": "Thiết kế liên kết",
"prefs.live_input": "Nhập liệu trực tiếp",
"prefs.live_preview": "Xem trước trực tiếp",
"prefs.logo": "Logo",
"prefs.logo_accent": "Màu nhấn",
"prefs.logo_theme": "Màu của chủ đề",
"prefs.minutes": "phút",
"prefs.minutes_suffix": " phút",
"prefs.mouse": "Chuột và bàn di cảm ứng",
@@ -1832,6 +1846,10 @@
"prefs.sketch_selection": "Phác thảo & chọn đối tượng",
"prefs.sketch_selection_heading": "Phác thảo và lựa chọn",
"prefs.sketch_selection_note": "Cách phác thảo bắt dính và cách nhấp chuột chọn đối tượng.",
"prefs.sketch_tab_always": "Luôn hiện thẻ Bản phác",
"prefs.sketch_tab_always_note": "Thẻ Bản phác vẫn nằm trên thanh công cụ, ngay sau Mô hình, khi không có bản phác nào đang mở. Khi đó các công cụ vẽ của nó bắt đầu một bản phác trên mặt phẳng hoặc mặt đã chọn, hoặc trên mặt phẳng bạn chọn tiếp theo, với công cụ sẵn sàng trong đó.",
"prefs.sketch_tracking_guides": "Đường căn chỉnh tâm và trung điểm",
"prefs.sketch_tracking_guides_note": "Di con trỏ lên tâm đường tròn hoặc trung điểm của cạnh thẳng, rồi di chuyển theo phương ngang hoặc dọc để hiển thị đường căn chỉnh nét đứt tạm thời.",
"prefs.sketching": "Vẽ phác thảo",
"prefs.snap_drawing_note": "Khi đang vẽ hoặc kéo một điểm phác thảo.",
"prefs.source": "Nguồn",
@@ -1844,12 +1862,16 @@
"prefs.supersampling_brief": "Vẽ khung nhìn ở độ phân giải lớn hơn rồi lọc giảm tỷ lệ: rất sắc nét, nhưng tốn tài nguyên hơn.",
"prefs.tab_accent_note": "Màu nhấn theo tab đang kích hoạt",
"prefs.theme_file": "tệp chủ đề",
"prefs.theme_file_or_paste": "tệp hoặc dán",
"prefs.theme_follow": "Theo dõi tệp chủ đề",
"prefs.theme_follow_error": "Chưa áp dụng: {error}. Chủ đề hợp lệ gần nhất vẫn được giữ.",
"prefs.theme_follow_launch": "Chỉ theo dõi trong lần chạy này (--theme-file); tải lại mỗi khi công cụ khác ghi lại tệp.",
"prefs.theme_follow_note": "Tải lại mỗi khi công cụ khác ghi lại tệp. Chọn chủ đề sẽ dừng theo dõi.",
"prefs.theme_follow_off": "Tắt",
"prefs.theme_follow_stop": "Dừng theo dõi",
"prefs.theme_import_hint": "Nhấp để chọn tệp giao diện, thả tệp vào đây, hoặc nhấn Ctrl+V (Cmd+V trên Mac) khi đã sao chép một giao diện",
"prefs.theme_paste": "Dán giao diện",
"prefs.theme_paste_none": "Bộ nhớ tạm không chứa giao diện SolidCraft nào",
"prefs.timeline_half_hour": "−30 phút",
"prefs.timeline_now": "bây giờ",
"prefs.timeline_quarter_hour": "−15 phút",
@@ -1916,6 +1938,7 @@
"render.all_controls_help": "Xem chi tiết toàn bộ các điều khiển hiện tại. Các trang chuyên mục cho phép chỉnh sửa tập trung mà không làm thay đổi yêu cầu cơ bản bên dưới.",
"render.all_shots_label": "Mọi cảnh chụp",
"render.appearance_physics_separate": "Diện mạo thị giác không gán khối lượng riêng, dữ liệu nhiệt hay các đặc tính kỹ thuật khác.",
"render.appearances": "Diện mạo",
"render.availability_native": "Tổ hợp gốc; hãy xem xét trước khi áp dụng",
"render.availability_projection": "Chiếu một phần được hỗ trợ; xem phạm vi và các mục lược bỏ",
"render.availability_reference": "Dữ liệu tham chiếu; không tự động gán",
@@ -1970,6 +1993,10 @@
"render.camera_set": "Đặt camera kết xuất",
"render.camera_target": "Vị trí mục tiêu · mm",
"render.camera_yaw": "Góc quay ngang camera (Yaw)",
"render.category_metal": "Kim loại",
"render.category_paint": "Sơn",
"render.category_plastic": "Nhựa",
"render.category_wood": "Gỗ",
"render.chromatic_offset": "Độ lệch sắc sai viền",
"render.clear_stage": "Xóa sân khấu đã lưu",
"render.copy_request": "Sao chép JSON",
@@ -2069,6 +2096,7 @@
"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.environment_tiles_require_raytrace": "Môi trường cần dò tia trên CPU hoặc GPU. Chọn trong trình chỉnh Đầu ra.",
"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",
@@ -2140,6 +2168,8 @@
"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.frame_presets": "Khung đặt sẵn",
"render.frame_presets_pending": "Sẽ có cùng trình chỉnh cảnh chụp",
"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",
@@ -2211,8 +2241,12 @@
"render.lens_effects_title": "Phong cách ống kính và nhiếp ảnh",
"render.library_all": "Danh mục",
"render.library_all_states": "Tất cả trạng thái khả dụng",
"render.library_appearance_available": "Diện mạo khả dụng",
"render.library_applicable": "Tài nguyên áp dụng được",
"render.library_applied": "Đã áp dụng phép chiếu tài nguyên. Hãy kiểm tra toàn bộ yêu cầu kết xuất trước khi bắt đầu.",
"render.library_apply_appearance": "Áp dụng diện mạo",
"render.library_apply_hdr": "Lưu kèm môi trường HDR này",
"render.library_apply_hint": "Bấm để áp dụng · kéo vào mô hình",
"render.library_apply_maps": "Sử dụng bản đồ bề mặt GPU đã tạo",
"render.library_apply_studio": "Lưu phép chiếu studio đã tạo",
"render.library_apply_uniform": "Áp dụng diện mạo đục đồng nhất",
@@ -2228,15 +2262,23 @@
"render.library_extent": "Phạm vi chủ thể",
"render.library_favorite": "Thêm vào yêu thích",
"render.library_favorites": "Yêu thích",
"render.library_filters": "Danh mục và tình trạng sẵn có",
"render.library_grid": "Lưới",
"render.library_hdr": "Môi trường HDR tích hợp",
"render.library_hdr_help": "Nhúng HDR gốc vào thiết lập đã lưu. Gốc kinh độ đã thiết kế được chuyển đổi rõ ràng; không cần tệp bên ngoài sau khi lưu.",
"render.library_in_design": "Trong thiết kế",
"render.library_inspect_only": "Chọn để kiểm tra; không có gì được tự động áp dụng. Mục yêu thích và lịch sử gần đây thuộc về phiên tài liệu đang mở này.",
"render.library_ior": "Chiết suất",
"render.library_light_concepts": "Khái niệm chiếu sáng",
"render.library_list": "Danh sách",
"render.library_maps_help": "Các bản đồ tích hợp có thể lưu cùng nguồn đã ghim và ánh xạ thực thể cục bộ. Ghi đè quang học tạm thời vẫn là chế độ riêng biệt.",
"render.library_material_concepts": "Khái niệm vật liệu",
"render.library_metallic": "Độ kim loại",
"render.library_native_scenes": "Studio gốc",
"render.library_next": "Trang sau",
"render.library_omitted": "Không bao gồm",
"render.library_opacity": "Độ đục",
"render.library_other": "Diện mạo khác",
"render.library_physical_profiles": "Hồ sơ tham chiếu vật lý",
"render.library_previous": "Trang trước",
"render.library_quality_concepts": "Thông số kỹ thuật chất lượng",
@@ -2246,6 +2288,7 @@
"render.library_results": "Tài nguyên phù hợp",
"render.library_rig_help": "Khớp một lần tại tâm và phạm vi vật lý rõ ràng. Bộ đèn đầy đủ bao gồm các tấm phản quang thụ động; các bộ phận chưa hiệu chuẩn vẫn bị từ chối. Khoảng cách an toàn của bộ phát sáng/tấm hắt được kiểm tra trước khi lưu.",
"render.library_rigs": "Bộ đèn chiếu sáng đã thiết kế",
"render.library_roughness": "Độ nhám",
"render.library_save_maps": "Lưu bản đồ vào thiết lập này",
"render.library_scene_bounds": "Sử dụng ranh giới khung cảnh đã ghi nhận",
"render.library_scenes": "Thông số kỹ thuật khung cảnh",
@@ -2269,6 +2312,7 @@
"render.library_unfavorite": "Bỏ yêu thích",
"render.library_uniform_ack": "Sử dụng xấp xỉ đồng nhất không có hiệu ứng không gian hoặc nâng cao",
"render.library_usable": "Phép chiếu có thể thực thi",
"render.library_users": "Người dùng",
"render.light_anchor_pending": "Chưa hỗ trợ đổi hệ tọa độ của đèn.",
"render.lights_fixed_to": "Đèn gắn cố định với",
"render.linear_help": "Giữ lại bản gốc RGBA số thực 32-bit trước khi khử nhiễu, phơi sáng, ánh xạ sắc điệu, lọc và phông nền. Tuyến tính sRGB/D65; nhân trước với độ phủ. Bộ nhớ bổ sung được tiếp nhận rõ ràng. Không nén hay thêm kênh phụ.",
@@ -2487,6 +2531,7 @@
"render.scene_review": "Xử lý và xem xét",
"render.scene_review_help": "Xem xét toàn bộ tổ hợp gốc trước khi áp dụng. Không tự động thay thế bằng các thông số kỹ thuật SCENE nâng cao chưa liên kết.",
"render.scene_scope_details": "Phạm vi tổ hợp",
"render.search_appearances": "Tìm trong {count} diện mạo",
"render.setup_legacy_environment": "Thiết lập cũ này sử dụng góc xoay hoặc cường độ môi trường kiểu cũ. Các giá trị đó được giữ lại; hãy chủ động chuyển đổi trước khi lưu toàn bộ tác vụ hình ảnh.",
"render.setup_name": "Tên thiết lập",
"render.setup_numeric_help": "Lưu sẽ ghi lại phương thức tạo ảnh đang hoạt động và tất cả cài đặt số của nó. Tải lại hoặc chọn thiết lập khác sẽ thay thế bản nháp này; khôi phục camera riêng biệt.",
@@ -2505,10 +2550,19 @@
"render.shot_remove_title": "Xóa khung hình đã lưu?",
"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.shots_camera_changed": "Máy ảnh đã đổi kể từ khi lưu cảnh chụp này",
"render.shots_name_help": "Nhập tên duy nhất cho cảnh chụp hiện tại.",
"render.shots_no_result": "Chưa kết xuất",
"render.shots_result": "Kết xuất {number} · {width} × {height}",
"render.shots_revert": "Hoàn nguyên",
"render.shots_save": "Lưu cảnh chụp",
"render.shots_update": "Cập nhật cảnh chụp",
"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.size_presets": "Cỡ đặt sẵn",
"render.size_presets_pending": "Sẽ có cùng trình chỉnh Đầu ra",
"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",
@@ -2559,8 +2613,10 @@
"render.studio_sky_help": "Dải chuyển màu bầu trời gốc dùng cho chiếu sáng; không phải mô hình khí quyển hiệu chuẩn.",
"render.studio_sun": "Mặt trời",
"render.studio_sun_radius": "Bán kính góc",
"render.studio_tiles_require_gpu": "Studio cần dò đường đi của tia bằng GPU. Chọn GPU trong trình chỉnh Đầu ra.",
"render.studio_title": "Studio kết xuất",
"render.studio_tone_map": "Ánh xạ sắc điệu (Tone mapping)",
"render.studios_environments": "Studio và môi trường",
"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ạ",
@@ -2668,6 +2724,7 @@
"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.double_click_components": "Nhấp đúp vào một thành phần để kích hoạt nó, hoặc chỉnh sửa tại chỗ một thành phần liên kết",
"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.",
"settings.frame_rate_note": "Hiển thị số khung hình trên giây (FPS) ở góc dưới bên phải khung nhìn.",
"settings.measure_axis_distances": "Hiển thị khoảng cách theo trục X/Y/Z",
@@ -2680,6 +2737,7 @@
"settings.reset_intro": "Các cài đặt sau không hoạt động trên máy tính này và có thể khiến SolidCraft không thể khởi động, vì vậy chúng đã được tự động điều chỉnh:",
"settings.reset_title": "Cài đặt đã được thay đổi",
"settings.supersampling_note": "Vẽ khung nhìn ở độ phân giải cao hơn rồi nén lại: giúp các cạnh, đường nét và lưới mượt mà hơn trên màn hình dưới 4K. Tính năng này tiêu tốn tài nguyên GPU: gấp khoảng 2,25 lần số điểm ảnh ở mức 1,5× và 4 lần ở mức 2×.",
"settings.update_changed_links": "Cập nhật các thiết kế liên kết đã thay đổi khi quay lại một thẻ",
"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.",
@@ -3283,6 +3341,24 @@
"ui.easyprint_uploading": "Đang tải lên Printables…",
"ui.edit": "Chỉnh sửa",
"ui.editJointLimits": "Chỉnh sửa giới hạn khớp nối",
"ui.edit_in_place": "Chỉnh sửa tại chỗ",
"ui.edit_in_place_after_turn": "Việc chỉnh sửa sẽ hoàn tất khi lượt của tác tử kết thúc",
"ui.edit_in_place_agent_busy": "Tác tử vẫn đang làm việc trong thiết kế này; hãy thử lại khi lượt của nó kết thúc",
"ui.edit_in_place_already_queued": "Đã có một thao tác chỉnh sửa đang chờ lượt của tác tử kết thúc",
"ui.edit_in_place_assembly_closed": "{name} không còn mở",
"ui.edit_in_place_banner": "Đang chỉnh sửa trong {name}",
"ui.edit_in_place_busy": "Hãy hoàn tất hoặc hủy những gì đang mở trước",
"ui.edit_in_place_none": "Không có thiết kế liên kết nào đang được chỉnh sửa tại chỗ",
"ui.edit_in_place_not_saved": "Chi tiết có thay đổi chưa lưu; hãy lưu để hoàn tất chỉnh sửa",
"ui.edit_in_place_open_elsewhere": "{name} đang mở trong một SolidCraft khác",
"ui.edit_in_place_opens_after_turn": "Chi tiết sẽ mở khi lượt của tác tử kết thúc",
"ui.edit_in_place_refresh_dropped": "Cụm lắp ráp đã thay đổi trong khi cập nhật liên kết; hãy chạy lại",
"ui.edit_in_place_refresh_stopped": "Cập nhật liên kết đã dừng trước khi hoàn tất",
"ui.edit_in_place_refreshing": "Đang cập nhật liên kết trong {name}…",
"ui.edit_in_place_save_first": "Hãy lưu cụm lắp ráp trước: các thiết kế liên kết của nó được tìm từ tệp của nó",
"ui.edit_in_place_save_waits": "Đang cập nhật liên kết trong {name}; hãy lưu sau khi hoàn tất",
"ui.edit_in_place_saved_elsewhere": "Chi tiết đã được lưu vào tệp khác; cụm lắp ráp vẫn liên kết với {name}",
"ui.edit_in_place_wait": "Hãy chờ những gì đang chạy trong thiết kế hoàn tất",
"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.",
@@ -3357,6 +3433,7 @@
"ui.heading_edit": "CHỈNH SỬA",
"ui.heading_extrude": "ĐÙN KHỐI",
"ui.heading_fillet": "BO TRÒN",
"ui.heading_finish_editing": "HOÀN TẤT CHỈNH SỬA",
"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",
@@ -3616,6 +3693,8 @@
"ui.restore_defaults": "Khôi phục mặc định",
"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_vertical_pan_direction": "Đảo hướng kéo dọc",
"ui.reverse_vertical_pan_tip": "Cuộn dọc bằng hai ngón tay sẽ kéo theo hướng 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",
@@ -3761,6 +3840,15 @@
"ui.updateToCurrentView": "Cập nhật theo góc nhìn hiện tại",
"ui.upload": "Tải lên",
"ui.vertical_constraint": "Ràng buộc thẳng đứng",
"ui.view_angles": "Góc hướng nhìn",
"ui.view_angles_convention": "Độ quanh trục hướng lên. Lệch 0° là góc nhìn phía trước, 90° bên trái, −90° bên phải, 180° phía sau; chúc 90° là góc nhìn từ trên; nghiêng dương xoay mô hình trên màn hình theo chiều kim đồng hồ.",
"ui.view_angles_help": "Hiển thị góc chúc, góc lệch và góc nghiêng của góc nhìn theo độ cùng kiểu chiếu, bên dưới gizmo định hướng. Bấm vào phần hiển thị để nhập góc chính xác.",
"ui.view_angles_ortho": "Trực giao",
"ui.view_angles_persp": "Phối cảnh",
"ui.view_angles_pitch": "Chúc",
"ui.view_angles_readout": "Chúc {pitch} · Lệch {yaw} · Nghiêng {roll}",
"ui.view_angles_roll": "Nghiêng",
"ui.view_angles_yaw": "Lệch",
"ui.view_centre": "Tâm góc nhìn",
"ui.viewport_theme_follow": "Theo chủ đề giao diện",
"ui.visual_shaded_hidden_edges": "Tô bóng kèm nét khuất",
+710
View File
@@ -38,6 +38,7 @@
"All open designs": "所有開啟的設計",
"Allowed expressions, separated by semicolons": "允許的運算式,以分號分隔",
"Also deletes": "同時刪除",
"Also place them from the origin (fully constrained)": "同時從原點定位(完全約束)",
"Anchor": "錨點",
"Angle 2": "角度 2",
"Angle Display": "角度顯示",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "您開啟或儲存的設計會顯示在此處。",
"Determined by To Object. Choose Angle to edit the angular extent.": "由「到物件」確定。選擇「角度」可編輯角度範圍。",
"Diameter": "直徑",
"Dimension new shapes": "為新圖形標註尺寸",
"Direction": "方向",
"Discard": "捨棄",
"Distance": "距離",
@@ -196,6 +198,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "拖曳以 5° 為間隔旋轉墊塊。按住 Alt 或 Ctrl 可自由旋轉。",
"Drive Joint": "驅動接頭",
"Duration": "時長",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "每個新圖形也會從草圖原點標註尺寸,直到沒有任何自由度。已連接到原點或已放置幾何的圖形不會再加。",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "您繪製的每個圖形都會依繪製的大小取得所有尺寸(輸入的值優先)。草圖已決定的尺寸會略過。",
"Edge": "邊",
"Edges": "邊",
"Edit": "編輯",
@@ -1831,21 +1835,317 @@
"recovery.just_now": "剛剛",
"recovery.min_ago": "{count} 分鐘前",
"recovery.never_saved": "從未儲存",
"render.adaptive_absolute": "絕對 RGB 誤差下限",
"render.adaptive_coverage": "覆蓋率誤差目標",
"render.adaptive_enable": "以獨立先導取樣分配取樣數",
"render.adaptive_help": "僅限 GPU。獨立先導取樣會被捨棄,接著為每個像素分配 16 個以上的正式取樣,上限為「每像素取樣數」。RGB 與覆蓋率的變異數會引導分配;罕見光徑可能被遺漏,達到上限的像素仍可能有雜訊。最終報告會計入實際工作量。不保證經認證的雜訊量或時間。",
"render.adaptive_minimum": "最小正式取樣數",
"render.adaptive_pending": "已可使用 GPU 獨立先導式自適應分配與條件式菲涅耳分層。經認證的收斂、罕見事件保證與 CPU 自適應傳輸仍無法使用。",
"render.adaptive_pilots": "每像素先導取樣數",
"render.adaptive_relative": "相對 RGB 誤差目標",
"render.add_ground": "將貼合的地面新增至設定",
"render.advanced_material_scope": "在明確限制下,可使用單一有限的均質 GPU 介質。密度網格、巢狀玻璃/體積組合、次表面散射曲面、置換、光譜傳輸,以及未綁定的進階材質概念仍無法使用。",
"render.aging_add": "新增老化層",
"render.aging_airborne": "空氣中的灰塵 / 參與介質",
"render.aging_airborne_help": "空氣中的灰塵是獨立的有限均質散射體積。它會改變光傳輸與原始 EXR,但不屬於表面老化堆疊。現有的體積/玻璃/降噪限制依然明確適用;不會自動加入大氣。",
"render.aging_all_bodies": "所有符合條件的不透明實體",
"render.aging_chips": "剝落的漆面",
"render.aging_class_any": "所有不透明材質類別",
"render.aging_class_dielectric": "僅非金屬表面",
"render.aging_class_metal": "僅金屬表面",
"render.aging_color": "層顏色 · sRGB",
"render.aging_coverage": "覆蓋率",
"render.aging_dust": "沉積灰塵",
"render.aging_empty": "沒有老化層:原始表面保持不變。",
"render.aging_fading": "褪色的塗層",
"render.aging_grime": "污垢與髒汙",
"render.aging_help": "依序組合最多八個光學層。鏽蝕與銅綠是人工製作的外觀,並非老化/腐蝕模擬。比例以世界座標毫米為單位。不會變更幾何、質量或任何工程屬性;玻璃與被動佈景不受影響。",
"render.aging_metallic": "層金屬比例",
"render.aging_origin": "場域原點 · 世界座標 mm",
"render.aging_patina": "銅綠",
"render.aging_refresh_targets": "檢查目前實體",
"render.aging_roughness": "層粗糙度",
"render.aging_rust": "氧化鐵 / 鏽蝕",
"render.aging_scale": "圖樣縮放",
"render.aging_scratches": "細微刮痕",
"render.aging_target": "目標與座標",
"render.aging_target_help": "具名目標必須仍與其擷取的索引及名稱相符。全域遮罩錨定於世界座標,不會跟隨移動的零件。這既不是凹陷偵測,也不是真正的邊緣磨損。請篩選清單以找到其他實體。",
"render.aging_target_search": "篩選實體名稱",
"render.aging_upward": "朝上的沉積",
"render.all_controls_help": "密集檢視目前所有控制項。各分區頁面提供專注的編輯方式,不會變更底層請求。",
"render.all_shots_label": "所有鏡頭",
"render.appearance_physics_separate": "視覺外觀不會指定密度、熱學資料或其他工程屬性。",
"render.availability_native": "原生組合;套用前請先檢閱",
"render.availability_projection": "支援的投影;請參閱範圍與省略項目",
"render.availability_reference": "參考資料;不會自動指派",
"render.backdrop_alpha_conflict": "請擇一使用此背景或透明 PNG 輸出;彩現器不會默默忽略任一項設定。",
"render.backdrop_enable": "使用僅限相機的漸層背景",
"render.backdrop_first": "起點 / 中心顏色",
"render.backdrop_help": "此螢幕空間背景不會照明、投射陰影、產生反射,也不代表地形。它不包含在原始 EXR 中。幾何、燈光與 HDR 環境保持獨立。",
"render.backdrop_horizontal": "水平漸層",
"render.backdrop_radial": "放射狀漸層",
"render.backdrop_radius": "半徑",
"render.backdrop_second": "終點 / 邊緣顏色",
"render.backdrop_vertical": "垂直漸層",
"render.backdrop_x": "中心 X",
"render.backdrop_y": "中心 Y",
"render.background": "場景背景",
"render.background_camera_section": "相機背景 · PNG 呈現",
"render.background_completed_frozen": "目前顯示的結果是已完成的凍結影像。編輯背景不會自動重繪該結果。僅相機層級的變更請使用「重新調色」,若要拍攝新的實體佈景,請使用「彩現」。",
"render.background_hdr_separate": "目前的 HDR 資源會照亮表面並在表面上產生反射;它們不會自動顯示為主體後方的全景。變更漸層不會旋轉燈光,也不會改變燈光的顏色。",
"render.background_lighting_section": "HDR 照明 · 與相機背景分開",
"render.background_no_alpha_override": "相機背景不會默默加入透明輸出。原始母檔的重新調色會使用已擷取的覆蓋率,且不會重新套用降噪;來源 EXR 保持不變。",
"render.background_not_light": "背景顏色僅用於呈現,並非額外的光源。",
"render.background_regrade": "套用至保留的原始母檔",
"render.background_stage_occlusion": "此鏡頭包含實體佈景幾何。大面積的地板或牆面可能佔滿畫面,並遮住僅限相機的背景。請刻意清除或調整佈景大小,或變更其實體反射率。重新調色無法移除已擷取的幾何。",
"render.background_workflow": "請選擇您想要的背景:僅限相機的顏色/漸層、接收光線的實體佈景,或 HDR 照明。三者各自獨立。即時預覽是建模檢視;請彩現新影像,或對保留的母檔重新調色,才能看到相機後製效果。",
"render.base_appearance": "可編輯的實體外觀",
"render.base_apply": "套用實體外觀",
"render.base_apply_help": "對已檢閱的確切實體進行一次可復原的視覺指派。既有的各面專屬外觀與工程材質保持獨立。",
"render.base_color": "基底顏色 · sRGB",
"render.base_metallic": "金屬比例",
"render.base_opaque_only": "此編輯器保留不透明實體的語意。光學穿透請使用專屬的玻璃控制項。",
"render.bloom_enable": "顯示泛光",
"render.bloom_help": "僅用於輸出的創意輝光,由線性正值高光經三次正規化方框模糊擴散而成。半徑以輸出像素為單位。在轉換為 sRGB 之前,於線性顯示光中疊加;並非鏡頭效果、體積效果,也無法改善收斂。原始 EXR 保持不變。",
"render.bloom_opaque": "泛光需要不透明輸出。透明 PNG 會被拒絕,而不會默默壓平。",
"render.bloom_radius": "泛光半徑",
"render.bloom_strength": "泛光強度",
"render.bloom_threshold": "線性高光臨界值",
"render.browse_capabilities": "檢查完整功能目錄",
"render.browse_environments": "瀏覽原創 HDR 環境",
"render.browse_native_scenes": "瀏覽原生 Studio",
"render.browse_physical": "檢查物理參考資料",
"render.browse_quality": "檢查品質規格",
"render.browse_rigs": "瀏覽預先設計的燈光組",
"render.browse_scene_specs": "瀏覽進階場景規格",
"render.browse_surfaces": "瀏覽預先設計的表面",
"render.browser_library": "資源庫",
"render.browser_model": "模型",
"render.camera_distance": "視點至目標距離",
"render.camera_exact_help": "世界座標毫米;角度以度顯示,並以弧度儲存。導覽使用與視埠相同的相機。",
"render.camera_fov": "垂直視角",
"render.camera_pitch": "相機俯仰",
"render.camera_roll": "滾轉",
"render.camera_set": "設定彩現相機",
"render.camera_target": "目標位置 · mm",
"render.camera_yaw": "偏航",
"render.chromatic_offset": "邊緣色差偏移",
"render.clear_stage": "移除已儲存的佈景",
"render.copy_request": "複製 JSON",
"render.cpu_aa_help": "空間取樣:取樣越多,邊緣越平滑,但彩現時間也越長。",
"render.cpu_area_add": "新增矩形 CPU 燈光",
"render.cpu_area_editor": "CPU 矩形燈光",
"render.cpu_area_editor_help": "完整邊向量以毫米為單位;U 叉乘 V 指向發光側。這與 GPU 的半邊向量不同。",
"render.cpu_area_full_u": "完整 U 邊 · mm",
"render.cpu_area_full_v": "完整 V 邊 · mm",
"render.cpu_area_samples": "面光源取樣數",
"render.cpu_binding_confirm": "確認此實體",
"render.cpu_binding_stale": "場景已變更。彩現前請重新確認此反射目標。",
"render.cpu_body_choose": "選擇實體",
"render.cpu_body_filter": "依名稱篩選實體",
"render.cpu_body_filter_more": "請調整篩選條件以查看更多實體。",
"render.cpu_body_missing": "反射目標遺失、已隱藏、有歧義,或名稱超過 128 位元組。請重新選擇。",
"render.cpu_budget": "CPU 資源設定檔",
"render.cpu_budget_bodies": "實體上限",
"render.cpu_budget_compact": "精簡(舊版限制)",
"render.cpu_budget_details": "資源限制",
"render.cpu_budget_help": "請明確選擇較大的限制。解析度與取樣數絕不會被自動降低。",
"render.cpu_budget_memory": "工作記憶體上限",
"render.cpu_budget_not_guarantee": "這些是受理上限,並非 RAM 保留或速度保證。幾何、影像緩衝區與保留的預覽共用記憶體預算;彩現仍可隨時取消。",
"render.cpu_budget_resize": "草稿超出此 CPU 設定檔或其相機取樣預算。請明確接受較小的尺寸,或選擇較大的設定檔。",
"render.cpu_budget_studio": "Studio(大型影像)",
"render.cpu_budget_triangles": "三角形上限",
"render.cpu_budget_workstation": "工作站(重型場景)",
"render.cpu_captured_hdr": "此影像擷取的 HDR",
"render.cpu_check_capture_help": "「檢查」和「開始」會驗證相同的檔案摘要,或使用內嵌的 HDR。每張影像都保留其擷取的來源。",
"render.cpu_check_changed": "此次檢查之後,控制項或模型已變更。請在彩現前重新檢查。",
"render.cpu_constant_help": "恆定輻射亮度對反射或穿透的光線可見,但不提供直接的漫射照明。",
"render.cpu_custom_directions": "以自訂方向光取代預設",
"render.cpu_direction": "朝向光源的方向(X, Y, Z)",
"render.cpu_directional": "方向光",
"render.cpu_directional_add": "新增方向光",
"render.cpu_environment": "CPU 環境",
"render.cpu_environment_background": "影像背景與環境照明保持獨立。",
"render.cpu_environment_bounds": "CPU 強度必須介於 0–64,HDR 旋轉必須為有限值且在 ±1,000,000 弧度內,HDR 取樣數必須為 1、4、16 或 64。",
"render.cpu_environment_constant": "恆定的次級光線環境",
"render.cpu_environment_none": "無 CPU 環境",
"render.cpu_environment_samples": "HDR 照明取樣數",
"render.cpu_exposure_help": "CPU 曝光必須介於 −16 和 16 EV 之間。超出此範圍的 GPU 曝光值會保留,直到您變更為止。",
"render.cpu_fixed": "單張影像",
"render.cpu_hdr_help": "Radiance .hdr,2:1 全景圖,最大 2048 × 1024 且不超過 16 MiB。CPU 要求檔案中明確指定 sRGB/D65 原色;未指定原色的檔案和 EXR 會被拒絕。",
"render.cpu_hdr_reflection_help": "HDR 粗糙反射需要完全金屬的實體和面表面。「檢查」會回報不支援的組合。",
"render.cpu_key_rim": "主光與輪廓光",
"render.cpu_last_check": "上次 CPU 檢查",
"render.cpu_light_help": "最多八個方向光。自訂清單為空時會關閉所有方向光;選擇預設則會還原其光源。顏色為線性 RGB,強度為相對值,而非瓦特。",
"render.cpu_light_intensity": "相對強度(0–64)",
"render.cpu_light_minimum": "衰減最小距離",
"render.cpu_light_position": "世界座標位置(X, Y, Z)",
"render.cpu_light_reference": "強度參考距離",
"render.cpu_light_remove": "移除光源",
"render.cpu_lighting": "照明預設",
"render.cpu_lights": "CPU 光源",
"render.cpu_linear_color": "線性顏色(R, G, B)",
"render.cpu_neutral": "中性",
"render.cpu_opaque_required": "CPU 光線追蹤需要不透明背景。請取消勾選「透明背景」以繼續。",
"render.cpu_options_pending": "此 CPU 面板尚無法編輯發光、表面效果、玻璃或各向異性。使用前請先清除這些 API 選項。",
"render.cpu_point": "點光源",
"render.cpu_point_add": "新增點光源",
"render.cpu_point_help": "最多八個點光源,疊加於所選的方向光照明之上。距離單位為 mm;最小距離不得超過參考距離。",
"render.cpu_primary_samples": "每像素邊緣取樣數",
"render.cpu_progressive": "CPU 漸進式",
"render.cpu_progressive_help": "以每輪一個主取樣為單位,累積現有的 CPU 積分器。所選反射需使用一個取樣;面光源、介電質和各向異性需使用「單張影像」。",
"render.cpu_progressive_limits": "最多 1,048,576 像素和 16,777,216 次像素 × 取樣評估。變更取樣數不會自動調整影像大小。",
"render.cpu_progressive_seed": "CPU 取樣種子",
"render.cpu_progressive_spp": "取樣/像素",
"render.cpu_reflection_add": "新增粗糙反射",
"render.cpu_reflection_depth": "反射深度(1–8)",
"render.cpu_reflection_empty": "未選取任何實體:場景反射已關閉。",
"render.cpu_reflection_help": "選擇實體並設為「關閉」、「鏡面」或「粗糙」。「粗糙」使用所指派的表面粗糙度。取樣數和彈射次數越多,耗時越長;這是有限度的鏡面光傳輸,並非全域照明。",
"render.cpu_reflection_limit": "最多支援 64 個反射實體。",
"render.cpu_reflection_mirror": "鏡面",
"render.cpu_reflection_off": "關閉",
"render.cpu_reflection_rough": "粗糙",
"render.cpu_reflection_samples": "反射取樣數(1–64)",
"render.cpu_reflections": "CPU 反射",
"render.cpu_runtime_help": "光源和環境的數值設定會與此設定一併儲存。實體反射和 HDR 檔案仍為暫存。既有的面光源和聚光錐角數值會保留。",
"render.cpu_sampling_mode": "CPU 取樣模式",
"render.cpu_shadows": "投射陰影",
"render.cpu_summary": "CPU 光線追蹤 · 反射 · HDR · 方向光和點光源",
"render.cpu_warm_cool": "暖光與冷光",
"render.diag_bodies": "可見實體",
"render.diag_job_details": "擷取的工作詳細資料",
"render.diag_last_check": "上次預檢",
"render.diag_memory": "邏輯准入估算",
"render.diag_not_implemented": "明確的功能邊界",
"render.diag_preflight_details": "預檢詳細資料",
"render.diag_request": "目前的完整請求",
"render.diag_triangles": "三角形",
"render.discard_continue": "捨棄草稿並繼續",
"render.draft_confirm_help": "目前的彩現草稿含有尚未套用的編輯。請在切換前儲存、明確捨棄,或繼續編輯。",
"render.draft_confirm_title": "保留已編輯的彩現設定",
"render.effects_gpu_only": "這些效果需要 GPU 路徑追蹤。切換頁面不會自動變更彩現器。",
"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",
"render.exr_pending": "GPU 可保留原始線性 EXR。壓縮、多圖層影像和輔助彩現通道仍無法使用。",
"render.film_grain": "攝影顆粒",
"render.fit": "適合產品檢視",
"render.fixed_camera": "相機",
"render.fixed_world": "世界",
"render.flare_ghosts": "每個光源的鬼影環數",
"render.flare_halo": "眩光光暈",
"render.flare_streak": "變形鏡頭風格光條",
"render.flare_strength": "亮部眩光強度",
"render.flare_threshold": "場景線性眩光閾值",
"render.fold_browser": "摺疊瀏覽器",
"render.gpu_depth": "最大路徑深度",
"render.gpu_options_help": "取樣數、深度、種子和曝光會隨此設定一併儲存。僅儲存目前啟用的影像方法。",
"render.gpu_path_failed": "GPU 路徑追蹤器無法使用",
"render.gpu_path_first_setup": "此 GPU 上的首次設定可能需要數分鐘;期間 SolidCraft 仍可正常使用。若驅動程式保留已編譯的著色器,之後啟動時會重複使用。",
"render.gpu_path_preparing": "GPU 路徑追蹤器:正在編譯著色器…",
"render.gpu_seed": "隨機種子",
"render.gpu_unavailable": "此裝置尚未準備好 GPU 路徑追蹤。",
"render.ground_apply": "擬合並儲存地面",
"render.ground_gap": "明確指定的間隙",
"render.ground_linear_rgb": "漫反射率 · 線性 RGB",
"render.ground_margin": "地面範圍餘量",
"render.hdr_details": "HDR 來源詳細資料",
"render.hdr_embedded": "HDR 已儲存於此設計內",
"render.hdr_embedded_help": "彩現使用設計內含的位元組;不再需要原始檔案。",
"render.hdr_file_captured": "HDR 檔案已檢查。儲存時將內嵌這些位元組;若檔案有變更,請再次明確檢查。",
"render.hdr_inspect": "檢查 HDR 檔案",
"render.hdr_inspect_required": "儲存或彩現前,請先選擇並檢查 HDR 檔案。",
"render.hdr_primaries_declared": "來源已宣告其色彩原色。",
"render.hdr_primaries_srgb": "色彩原色:sRGB/D65",
"render.hdr_primaries_undeclared": "來源未宣告原色;請查看彩現器的色彩需求。",
"render.hdr_resource_missing": "此設計缺少已儲存的 HDR 資源。",
"render.heading_batch": "批次",
"render.heading_frame": "畫面",
"render.heading_lens": "透鏡",
"render.heading_results": "結果",
"render.heading_shots": "鏡頭",
"render.hide_shots_label": "隱藏鏡頭列",
"render.image_advanced": "進階 GPU 控制項",
"render.image_cancelled": "彩現已取消",
"render.image_cancelling": "正在取消",
"render.image_completed": "影像可匯出",
"render.image_encoding": "正在編碼 PNG",
"render.image_export": "匯出 PNG",
"render.image_exposure": "曝光",
"render.image_failed": "彩現失敗",
"render.image_height": "高度",
"render.image_help": "CPU 預覽影像 · PNG · 近似透明度",
"render.image_host_missing": "未安裝影像主機。",
"render.image_method": "影像方法",
"render.image_overwrite": "取代現有檔案",
"render.image_preparing": "正在準備影像",
"render.image_progressive": "漸進式彩現",
"render.image_queued": "等待彩現",
"render.image_reduce": "請嘗試更小的影像或更簡單的場景。",
"render.image_running": "正在彩現影像",
"render.image_samples": "每像素取樣數",
"render.image_scene_stale": "請先完成建模操作或重新整理場景,再檢查或開始影像。",
"render.image_stale": "此影像使用後續變更之前擷取的場景。",
"render.image_start": "開始彩現",
"render.image_supported": "支援此彩現請求;開始時將再次檢查佇列和記憶體池。",
@@ -1855,20 +2155,430 @@
"render.image_unknown": "彩現狀態不可用",
"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": "上移",
"render.lens_effects_help": "眩光最多使用實際線性影像中四個彼此分離的亮光源。鬼影、光暈、光條、色差偏移和徑向畸變是影像空間中的藝術化近似。空間效果需要不透明輸出;超出範圍的取樣會延伸影像邊緣。顆粒具確定性。不會更改任何物理運算、EXR 或幾何。",
"render.lens_effects_title": "仿透鏡與攝影效果",
"render.library_all": "目錄",
"render.library_all_states": "所有可用性狀態",
"render.library_applied": "已套用資源投影。開始前請檢查完整的彩現請求。",
"render.library_apply_hdr": "以此 HDR 環境儲存",
"render.library_apply_maps": "使用原創 GPU 表面貼圖",
"render.library_apply_studio": "儲存原創攝影棚投影",
"render.library_apply_uniform": "套用均勻不透明外觀",
"render.library_authored_help": "原創資源僅供示意,並非實測的工程資料。每個操作只會套用其所述的投影。",
"render.library_blocked": "已封鎖 / 需要校準",
"render.library_capabilities": "功能規格",
"render.library_center": "燈組中心",
"render.library_clear_search": "清除",
"render.library_details": "規格與來源出處",
"render.library_emitters_only_ack": "僅使用發光體;省略已記載的被動反光卡",
"render.library_empty": "沒有符合的資源。請嘗試其他查詢或可用性篩選。",
"render.library_environment_concepts": "環境概念",
"render.library_extent": "主體範圍",
"render.library_favorite": "加入收藏",
"render.library_favorites": "收藏",
"render.library_hdr": "內建 HDR 環境",
"render.library_hdr_help": "將原始 HDR 內嵌於已儲存的設定。原創經度原點會明確轉換;儲存後不再需要外部檔案。",
"render.library_inspect_only": "選擇即可檢視;不會自動套用任何內容。收藏和最近記錄屬於此開啟的文件工作階段。",
"render.library_light_concepts": "燈光概念",
"render.library_maps_help": "內建貼圖可連同已固定的來源和局部實例對應一併儲存。暫時的光學覆寫仍為獨立模式。",
"render.library_material_concepts": "材質概念",
"render.library_native_scenes": "原生攝影棚",
"render.library_next": "下一頁",
"render.library_omitted": "未包含",
"render.library_physical_profiles": "物理參考設定檔",
"render.library_previous": "上一頁",
"render.library_quality_concepts": "品質規格",
"render.library_recent": "最近使用",
"render.library_replace_environment": "明確取代現有環境",
"render.library_replace_studio": "取代已儲存的燈光、環境和佈景",
"render.library_results": "符合的資源",
"render.library_rig_help": "在明確指定的中心和實際範圍一次完成擬合。完整燈組包含被動反光卡;校準阻礙仍會被拒絕。儲存前會以保守標準檢查發光體與反光卡的間隙。",
"render.library_rigs": "原創燈組",
"render.library_save_maps": "將貼圖儲存到此設定",
"render.library_scene_bounds": "使用已擷取的場景邊界",
"render.library_scenes": "場景規格",
"render.library_search": "搜尋資源庫",
"render.library_select_hint": "在資源庫中選擇資源,即可檢視其支援的操作與限制。",
"render.library_selene": "SELENE 不透明外觀",
"render.library_selene_shots": "SELENE 鏡頭規格",
"render.library_short_blocked": "無法使用",
"render.library_short_native": "原生構成",
"render.library_short_projection": "支援投影",
"render.library_short_reference": "僅供參考",
"render.library_short_specification": "僅有規格",
"render.library_source_preview": "載入來源貼圖預覽",
"render.library_source_preview_help": "原創基礎色來源貼圖。這不是彩現或實測的材質預覽。",
"render.library_specification_only": "僅有規格:並非完整可執行的預設。所需的效果、資源與主體角色仍須明確實作並綁定。",
"render.library_specs": "僅有規格",
"render.library_status": "可用性",
"render.library_surfaces": "原創 PBR 表面",
"render.library_target": "目標實體",
"render.library_title": "彩現資源庫",
"render.library_unfavorite": "移除收藏",
"render.library_uniform_ack": "使用均勻近似,不含空間或進階效果",
"render.library_usable": "可執行的投影",
"render.light_anchor_pending": "尚無法變更燈光座標系。",
"render.lights_fixed_to": "燈光固定於",
"render.linear_help": "在降噪、曝光、色調對應、濾鏡與背景之前,保留 32 位元浮點 RGBA 母檔。線性 sRGB/D65;覆蓋率預乘。額外記憶體須明確核可。無壓縮,也無額外通道。",
"render.linear_retain": "保留原始線性 EXR",
"render.linear_unavailable": "所選的已完成畫面沒有保留 EXR。請在彩現前啟用保留;較舊的 PNG 無法還原原始輻射亮度。",
"render.look_add": "新增色彩風格",
"render.look_bleach": "仿留銀沖印風格",
"render.look_cool": "冷色",
"render.look_cyanotype": "仿藍曬風格",
"render.look_faded": "褪色相片",
"render.look_mono": "單色",
"render.look_sepia": "深褐色",
"render.look_strength": "風格強度",
"render.look_teal_orange": "青綠 / 橘橙",
"render.look_title": "創意風格堆疊",
"render.look_warm": "暖色",
"render.mapping_scale": "實際重複倍率",
"render.material_absorption": "吸收 R · G · B(每 mm)",
"render.material_add": "新增或編輯此實體",
"render.material_assignments": "實體指派",
"render.material_binding_enable": "納入此實體的覆寫",
"render.material_box": "軸向對齊長方體",
"render.material_browse": "選擇影像…",
"render.material_certification": "封閉玻璃採用幾何距離。拓撲、方向、重疊與光學邊界會在 GPU 準備期間檢查;「檢查」僅受理該請求。",
"render.material_choose_body": "選擇場景實體",
"render.material_closed": "封閉實體網格",
"render.material_coat": "基底材質上的透明塗層",
"render.material_coat_enable": "啟用透明塗層",
"render.material_coat_help": "疊加在既有不透明外觀上的示意性介電塗層。權重為零時,基底維持不變。",
"render.material_color_map": "基底顏色影像(sRGB)",
"render.material_color_replace": "基底貼圖取代實體顏色",
"render.material_custom": "自訂示意光學",
"render.material_enable": "使用這些 GPU 材質覆寫",
"render.material_filter": "篩選場景實體…",
"render.material_filter_help": "最多顯示 128 個符合的實體。場景較大時,請縮小篩選範圍。",
"render.material_glass": "玻璃與光學吸收",
"render.material_glass_enable": "在此實體上使用物理玻璃",
"render.material_glass_exclusive": "在此彩現器中,玻璃不能與透明塗層或執行階段貼圖共用同一實體。",
"render.material_glass_help": "原創示意配方。色票顯示的是穿透率,並非彩現預覽。吸收 = −ln(線性穿透率) / 參考距離;Alpha 不變。",
"render.material_gpu_required": "這些啟用中的材質覆寫需要 GPU 路徑追蹤。請在「檢查」或「開始」前選擇 GPU,或停用覆寫。",
"render.material_ior": "折射率(IOR)",
"render.material_limits": "最多 128 個實體覆寫、32 個互不相交的玻璃實體、64 個塗層與 128 個紋理綁定。相同貼圖共用儲存空間;裝置與總記憶體的實際限制仍然適用。",
"render.material_map_invalid": "貼圖路徑必須是有界的本機路徑;法線強度必須為有限值,且介於 0 到 1 之間。",
"render.material_map_required": "使用貼圖前,請先選擇顏色影像或法線影像。",
"render.material_maps": "平面顏色與法線貼圖",
"render.material_maps_enable": "為此不透明實體啟用貼圖",
"render.material_maps_help": "PNG/JPEG 最大 1024×1024;編碼後總計 16 MiB。U 與 V 為互相正交的世界座標 mm 重複向量(最多重複 128 次)。顏色為 sRGB;法線資料採用 OpenGL +Y。檔案會在「檢查」/「開始」時擷取。",
"render.material_metallic_map": "金屬度貼圖(線性)",
"render.material_normal_map": "法線影像(OpenGL, +Y)",
"render.material_normal_strength": "法線強度(0–1)",
"render.material_origin": "貼圖原點 X · Y · Z(mm)",
"render.material_refresh": "重新整理場景實體",
"render.material_refresh_needed": "場景已變更。新增目標前,請先重新整理實體清單。",
"render.material_remove": "移除此指派",
"render.material_repeat_u": "單次 U 重複 X · Y · Z(mm)",
"render.material_repeat_v": "單次 V 重複 X · Y · Z(mm)",
"render.material_revalidate": "重新驗證此實體",
"render.material_revalidate_needed": "此指派屬於較早的場景修訂版本。彩現前,請重新驗證其確切的實體身分。",
"render.material_roughness": "塗層粗糙度(0.045–1)",
"render.material_roughness_map": "粗糙度貼圖(線性)",
"render.material_shadow": "穿透直線陰影光線",
"render.material_target_missing": "實體序號與名稱已不相符。請移除此指派,並明確重新選擇目標實體。",
"render.material_thickness": "薄板厚度(mm)",
"render.material_thin": "薄板",
"render.material_title": "GPU 影像材質",
"render.material_transient": "此文件分頁的暫時光學覆寫。不會儲存到設計、彩現設定或材質資源庫中。",
"render.material_v_up": "紋理 V 軸在影像中朝上",
"render.material_weight": "塗層權重(0–1)",
"render.method_cpu": "CPU 光線追蹤",
"render.method_gpu": "GPU 路徑追蹤",
"render.method_limit_raster": "光柵化使用固定的不透明攝影棚預覽。若要使用支援的光學控制項,請明確選擇光線追蹤方法。",
"render.method_raster": "CPU 光柵化",
"render.navigation_help": "相機的操作與設計中相同(偏好設定 › 導覽)。儲存設定會記錄目前相機。",
"render.nested_enable": "經認證的巢狀介電質",
"render.nested_help": "最多 16 個包含層;每個父層都必須是凸形,且每個子層都必須嚴格位於其內部。相交、表面接觸、薄板與直線陰影穿透都會被拒絕。相機位於內部的狀態遵循經認證的階層。不會建立液體表面,也不會合併相接的 CAD 邊界。",
"render.opaque_image_summary": "預覽 PNG · 不透明 PBR · 混合透明",
"render.opaque_preview_help": "不透明 PBR 和純色;透明效果使用混合。不支援折射、HDRI 和最終彩現。",
"render.optics_remove": "移除已儲存的光學設定",
"render.optics_replace": "明確取代此目標已儲存的光學設定",
"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": "所要求的影像超出所選的資源範圍。請明確選擇相容的尺寸或設定檔;不會自動降級。",
"render.output_ratio_refused": "連動的尺寸超出此方法的大小上限。先前的尺寸會保留;請解除鎖定比例,或選擇較小的值。",
"render.output_swap_orientation": "交換寬度與高度",
"render.output_tools_inspector": "請在「輸出」檢查器中編輯尺寸與格式。",
"render.page_aging": "老化與污染",
"render.page_all": "所有控制項",
"render.page_appearance": "外觀",
"render.page_background": "背景",
"render.page_camera": "相機",
"render.page_diagnostics": "診斷",
"render.page_effects": "透鏡與後製效果",
"render.page_environment": "環境",
"render.page_lighting": "照明",
"render.page_output": "輸出",
"render.page_scene": "場景",
"render.paint_label": "塗料",
"render.passive_stage": "地面與被動佈景",
"render.passive_stage_help": "有限的被動面板僅屬於彩現影像,不會新增 CAD 實體或質量。放置位置在套用後即固定;與產品邊界相交時會被拒絕。CPU 不提供漫射反彈照明。",
"render.perspective": "透視相機",
"render.physical_acknowledge": "我了解這份部分參考資料需要檢閱等級、狀況與來源",
"render.physical_associations": "物理候選項與角色",
"render.physical_background_help": "真實的被動地板與牆面,與相機背景分開。環形幕(cyclorama)使用 24 條多邊形帶;它並非無限或解析平滑的表面。僅在您同意後,才會取代已儲存的佈景。",
"render.physical_copy_plan": "複製計畫(含來源與省略項目)",
"render.physical_cyclorama": "擬合多邊形環形幕",
"render.physical_floor_wall": "擬合物理地板與牆面",
"render.physical_material_name": "擬定的參考材質名稱",
"render.physical_omissions": "原生卡片無法表示的屬性",
"render.physical_plan_only": "已準備唯讀計畫。未建立或指派任何材質。檢閱原生卡片時,請保留其延伸設定檔與省略項目。",
"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": "尚未支援產品選取。",
"render.post_contrast": "對比",
"render.post_gain_b": "藍色增益",
"render.post_gain_g": "綠色增益",
"render.post_gain_r": "紅色增益",
"render.post_help": "僅供創意呈現。RGB 增益在色調對應之前套用;對比、飽和度與暈影則在顯示線性光中接續套用。「開始彩現」會產生新的傳輸取樣。「重新調色」使用所選保留的原始母檔,不進行降噪,也不發射新光線。",
"render.post_reset": "重設呈現濾鏡",
"render.post_saturation": "飽和度",
"render.post_title": "呈現濾鏡",
"render.post_vignette": "暈影",
"render.preview": "整合預覽",
"render.preview_help": "光柵著色和混合透明度。暫不支援折射、HDRI 和最終彩現。",
"render.preview_image_settings_help": "即時預覽維持固定的攝影棚照明。曝光與影像照明會在您按下「檢查」或「開始」時套用於影像工作。",
"render.preview_lighting_help": "即時預覽僅顯示直接光,不含陰影。",
"render.preview_retry": "重試即時預覽",
"render.preview_unavailable_help": "無法使用即時預覽。已儲存的設定與影像工作控制項仍可使用。請變更場景或明確重試;遭拒絕的場景不會在每個影格重新建構。",
"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 預算,並明確省略自適應停止、原始線性輸出與獨立的穿透上限。",
"render.quality_review": "檢閱取樣預算",
"render.queue_pending": "此介面沒有自動化的正式生產佇列或動畫彩現器。已完成的靜態影像仍可單獨匯出。",
"render.radial_distortion": "徑向畸變",
"render.regrade_action": "重新調色原始母檔(不降噪)",
"render.regrade_help": "以這些呈現控制項,從所選的已完成原始母檔建立獨立的 PNG。不會追蹤光線、變更已擷取的尺寸/相機/光源,也不會覆寫 EXR。不會重新套用降噪:原始母檔不保留其引導資料。衍生檔仍可透過相同的工作控制項匯出。",
"render.regrade_label": "重新調色",
"render.reload_settings": "重新載入已儲存設定",
"render.replace_ground": "確認取代現有佈景",
"render.replace_label": "取代",
"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": "尚無已完成的影像。請檢查設定,然後開始彩現。",
"render.result_fit": "適合影像",
"render.result_job": "工作",
"render.result_navigation": "平移與縮放遵循「導覽」偏好設定。Space + 拖曳可平移。",
"render.result_open": "在主畫布中開啟已完成的影像。",
"render.result_preview": "即時預覽",
"render.result_provisional": "暫定 CPU 影像",
"render.result_provisional_help": "此檢查點無法匯出。匯出會保留上一個已完成的結果;取消則會回到該結果。",
"render.result_reduced_display": "顯示預覽已縮減至視埠裝置/快取的上限。保留的 PNG 與匯出檔維持完整解析度;此縮減檢視無法進行原生 100% 檢視。",
"render.result_retained": "顯示上一張已完成的影像;較新的彩現尚未取代它。",
"render.result_sequence": "檢查點",
"render.result_title": "彩現結果",
"render.return_design": "返回設計",
"render.review_stale": "此檢閱已過期。請先解決或重新檢查,再套用。",
"render.ribbon_aging": "老化",
"render.ribbon_backgrounds": "背景",
"render.ribbon_check": "檢查",
"render.ribbon_check_help": "驗證「彩現」將提交的目前草稿原貌。不會自動改用其他彩現器、默默調整大小或取代資源。",
"render.ribbon_edit_lights": "編輯燈光",
"render.ribbon_effects": "效果",
"render.ribbon_environment_help": "HDR 照明、僅限相機的背景與實體佈景表面為各自獨立的控制項,取代時需明確同意。",
"render.ribbon_finish_dialog": "請先完成目前的檔案或確認對話方塊。",
"render.ribbon_frame": "取景",
"render.ribbon_hdr_library": "HDR 資源庫",
"render.ribbon_job_active": "彩現正在執行;請先明確取消,再開始另一個。",
"render.ribbon_light_rigs": "燈組",
"render.ribbon_lights_help": "檢視原創燈組或編輯受支援的光源,在您明確套用變更之前,不會取代目前的設定。",
"render.ribbon_materials": "材質",
"render.ribbon_materials_help": "開啟共用的外觀檢視器與原創表面資源庫。光學編輯絕不會默默變更工程屬性。",
"render.ribbon_no_active_job": "沒有可取消的作用中彩現。",
"render.ribbon_no_result": "請先完成彩現,再匯出其確切影像。",
"render.ribbon_no_saved_camera": "請先儲存鏡頭,再還原其相機。",
"render.ribbon_saved_camera": "已儲存的相機",
"render.ribbon_shots": "鏡頭",
"render.ribbon_studios": "攝影棚",
"render.ribbon_studios_help": "瀏覽已實作的攝影棚組合,並在套用前檢閱將取代的內容。僅為概念的場景仍會加上標示。",
"render.ribbon_surface_maps": "表面貼圖",
"render.sampling_title": "自適應與穿透取樣",
"render.save_continue": "儲存並繼續",
"render.save_setup": "儲存設定",
"render.save_shot": "儲存鏡頭",
"render.saved_maps_runtime_conflict": "已儲存的表面繫結不可與暫時的光學覆寫或未儲存的 HDR 混用。請儲存該 HDR,或明確移除暫時性的輸入。",
"render.saved_surface_remove": "移除已儲存的繫結",
"render.saved_surfaces": "已儲存的表面繫結",
"render.saved_surfaces_help": "固定的內建貼圖以局部毫米為單位,跟隨所選的實例。目標被取代或遺失時會視為錯誤,絕不會自動重新指派。",
"render.scene_apply": "套用已檢閱的攝影棚",
"render.scene_consent": "確認取代燈光、環境、曝光與佈景",
"render.scene_preserved_fields": "相機、取樣、尺寸、光學繫結、CAD 幾何與工程材質皆會保留。",
"render.scene_preserves_design": "為可見的主體組合燈光與被動佈景。幾何、工程材質與相機維持獨立。",
"render.scene_replaces": "取代內容",
"render.scene_review": "解析並檢閱",
"render.scene_review_help": "套用前請檢閱完整的原生組合。未繫結的進階 SCENE 規格不會被替代。",
"render.scene_scope_details": "組合範圍",
"render.setup_legacy_environment": "此舊版設定使用傳統的環境旋轉或強度。這些值會保留;儲存完整影像工作前,請明確轉換它們。",
"render.setup_name": "設定名稱",
"render.setup_numeric_help": "「儲存」會記錄作用中的影像方法及其所有數值設定。重新載入或選擇其他設定會取代此草稿;相機請另行還原。",
"render.setup_offline_help": "沒有彩現器也可編輯並儲存此方法。「檢查」與「開始」需要可用的主機。",
"render.setup_runtime_unsupported": "尚無法儲存此完整工作:其中包含貼圖或場景實體繫結。請先移除這些暫時性輸入,再儲存可攜式設定。",
"render.setup_save_missing": "指令完成後,找不到已儲存的彩現組態。",
"render.sharpening": "細節銳利化",
"render.shell_tab_appearance": "彩現外觀",
"render.shell_tab_camera": "彩現相機",
"render.shell_tab_scene": "彩現場景",
"render.shot_duplicate": "複製已儲存的鏡頭",
"render.shot_manager": "已儲存的鏡頭",
"render.shot_new_name": "新鏡頭名稱",
"render.shot_remove": "移除已儲存的鏡頭",
"render.shot_remove_help": "僅移除此已儲存的設定。來源幾何與已完成的影像都會保留;此操作可復原。",
"render.shot_remove_title": "移除已儲存的鏡頭?",
"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": "風格",
"render.stage_orthographic": "正交",
"render.stage_output": "輸出",
"render.stage_panel_count": "已儲存的面板",
"render.stage_preview_note": "整合式預覽 · 直接光",
"render.strip_label": "鏡頭列",
"render.studio_add_area": "新增面光源",
"render.studio_ambient": "恆定環境輻射亮度",
"render.studio_ambient_rgb": "恆定環境輻射亮度(線性 RGB)",
"render.studio_aperture": "光圈半徑",
"render.studio_area": "面光源",
"render.studio_area_help": "最多四個單面矩形。互相正交的半邊長 U 與 V 決定大小;U × V 朝向受光面。座標為世界座標,單位為毫米。",
"render.studio_center": "中心 X, Y, Z(mm)",
"render.studio_denoise": "降低完成影像的雜訊",
"render.studio_denoise_help": "最終的邊緣感知濾鏡;細節可能會變柔和。玻璃與銳利的鏡面反射表面會略過此濾鏡。",
"render.studio_direction": "朝向太陽的方向(X, Y, Z)",
"render.studio_environment": "環境",
"render.studio_environment_bounds": "環境旋轉必須為有限值,且在 ±1,000,000 弧度以內;強度必須介於 0 到 100 之間。",
"render.studio_environment_none": "無環境貼圖",
"render.studio_focus": "軸向對焦距離",
"render.studio_half_u": "半邊長 U(mm)",
"render.studio_half_v": "半邊長 V(mm)",
"render.studio_hdr": "Radiance HDR 檔案",
"render.studio_hdr_browse": "選擇 HDR…",
"render.studio_hdr_help": "Radiance .hdr,2:1 全景圖,最大 2048 × 1024。不支援 EXR。色彩假設僅在未指定原色時適用。",
"render.studio_hdr_required": "請選擇本機的 .hdr 檔案。",
"render.studio_hdr_srgb": "將未指定的原色視為線性 sRGB",
"render.studio_intensity": "環境強度",
"render.studio_lens": "景深",
"render.studio_lens_perspective": "景深需要透視相機。",
"render.studio_lighting": "攝影棚燈光",
"render.studio_lighting_enable": "使用自訂攝影棚燈光",
"render.studio_needs_review": "檢閱方法與設定",
"render.studio_radiance": "線性 RGB 輻射亮度",
"render.studio_ready": "可供檢查",
"render.studio_remove_area": "移除面光源",
"render.studio_rotation": "環境旋轉",
"render.studio_runtime_help": "攝影棚的數值設定和已檢查的 HDR 來源可隨此設定一併儲存。實體的光學/材質覆寫仍為暫時性,不會變更已儲存的外觀。",
"render.studio_saved": "已儲存的設定 / 目前相機",
"render.studio_sky": "藝術天空",
"render.studio_sky_help": "用於照明的原創天空漸層;並非經校準的大氣模型。",
"render.studio_sun": "太陽",
"render.studio_sun_radius": "角半徑",
"render.studio_title": "彩現攝影棚",
"render.studio_tone_map": "色調對應",
"render.subsurface_enable": "內部散射隨機漫步",
"render.subsurface_help": "僅限封閉的介電質。散射係數與 RGB 吸收係數是各自獨立的每 mm 係數。光徑會在實際幾何內部散射,然後在邊界處折射或反射。請停用直接陰影穿透、表面降噪和外部體積,並使用單一菲涅爾分層。這不是擴散著色器、密度網格或實測材質。高密度介質可能需要更多取樣數和路徑深度。",
"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": "使用整合預覽",
"render.volume_albedo": "散射反照率 · 線性 RGB",
"render.volume_anisotropy": "相位平均餘弦",
"render.volume_enable": "啟用參與介質",
"render.volume_extinction": "消光係數",
"render.volume_help": "GPU 光傳輸在單一有限長方體內進行,於相機光徑和間接光徑上套用比爾衰減與 HG 散射。使用明確指定的攝影棚/HDR/天空照明,包含陰影衰減。正的相位餘弦會向前散射。必須明確停用玻璃邊界和表面降噪。消光係數為零時,光傳輸保持不變。這不是真實的月球大氣、密度網格、體積發光、光譜傳輸,也不是經認證的材質屬性。",
"render.volume_max": "最大邊界 · 世界座標 mm",
"render.volume_min": "最小邊界 · 世界座標 mm",
"render.volume_title": "有界均質體積",
"render.wait_batch": "尚未支援:已儲存鏡頭的彩現佇列",
"render.wait_compare": "尚未支援:保留影像的比較",
"render.wait_paint": "尚未支援:產品拾取與外觀塗刷",
"render.wait_pick_up": "尚未支援:產品拾取與外觀吸取",
"render.wait_replace": "尚未支援:取代外觀的所有使用處",
"render.wait_solo": "尚未支援:燈光可見性與獨奏控制項",
"sample.bracket.about": "以 2 mm 規則建立的基礎凸緣、邊線凸緣和摺邊",
"sample.bracket.name": "鈑金支架",
"sample.enclosure.about": "薄殼盒體,含唇緣、螺絲凸座、墊塊和卡扣",
+88
View File
@@ -38,6 +38,7 @@
"All open designs": "所有打开的设计",
"Allowed expressions, separated by semicolons": "允许的表达式,以分号分隔",
"Also deletes": "同时删除",
"Also place them from the origin (fully constrained)": "同时从原点定位(完全约束)",
"Anchor": "基准点",
"Angle 2": "角度 2",
"Angle Display": "角度显示",
@@ -180,6 +181,7 @@
"Designs you open or save appear here.": "你打开或保存的设计会显示在此处。",
"Determined by To Object. Choose Angle to edit the angular extent.": "由“到对象”确定。选择“角度”可编辑角度范围。",
"Diameter": "直径",
"Dimension new shapes": "为新图形标注尺寸",
"Direction": "方向",
"Discard": "放弃",
"Distance": "距离",
@@ -196,6 +198,8 @@
"Drag to turn the rest in 5° steps. Hold Alt or Ctrl to turn it freely.": "拖动以 5° 为步长旋转垫块。按住 Alt 或 Ctrl 可自由旋转。",
"Drive Joint": "驱动接头",
"Duration": "时长",
"Each new shape is also dimensioned from the sketch origin until nothing of it is left free. A shape already attached to the origin or to placed geometry gets none.": "每个新图形也会从草图原点标注尺寸,直到没有任何自由度。已连接到原点或已放置几何的图形不会再加。",
"Each shape you draw gets all its dimensions, at the sizes you drew (typed values win). A size the sketch already sets is left out.": "您绘制的每个图形都会按绘制的大小获得所有尺寸(输入的值优先)。草图已确定的尺寸会被跳过。",
"Edge": "边",
"Edges": "边",
"Edit": "编辑",
@@ -254,6 +258,8 @@
"Flanges": "法兰",
"Flat Pattern": "展开图",
"Flat size": "平板尺寸",
"Flat size X": "平板尺寸 X",
"Flat size Y": "平板尺寸 Y",
"Follow camera (Look At sketches)": "跟随相机(注视草图)",
"Follow the camera (Look At sketches)": "跟随相机(注视草图)",
"Font": "字体",
@@ -812,7 +818,9 @@
"cmd.component_create": "新建组件",
"cmd.component_cycle_color": "循环切换组件颜色",
"cmd.component_delete": "删除组件",
"cmd.component_edit_in_place": "原位编辑",
"cmd.component_extract": "提取到文件",
"cmd.component_finish_edit": "完成编辑",
"cmd.component_from_bodies": "由实体创建组件",
"cmd.component_insert_design": "插入设计",
"cmd.component_links": "列出链接",
@@ -1171,6 +1179,7 @@
"cmd.view.render_dock": "移动渲染停靠面板",
"cmd.view.render_focus": "渲染专注视图",
"cmd.view_ambient_occlusion": "环境光遮蔽",
"cmd.view_angle_readout": "视图角度",
"cmd.view_apply": "还原命名视图",
"cmd.view_back": "后视图",
"cmd.view_bottom": "仰视图",
@@ -1305,6 +1314,7 @@
"help.appearance.assign": "为所选的实体、面或组件设置颜色或材质外观,不改变其重量。用于区分零件或预览表面效果。",
"help.attributions": "署名信息 (ATTRIBUTION.md)",
"help.build": "版本 {version} · 提交 {commit} · 构建日期 {date}",
"help.component.finish_edit": "保存正在原位编辑的零件,返回其装配体,并用该零件更新装配体。对链接零件的更改完成后使用。",
"help.connect_note": "请重启各个助手以加载 SolidCraft 服务器。每个被修改的文件都已备份为 .bak。",
"help.connect_title": "连接 AI 助手",
"help.face.delete": "删除所选的面,并由相邻的面封闭留下的缺口,也可以让缺口保持开放、成为曲面。用于去掉碍事的圆角、孔或凸台。",
@@ -1782,8 +1792,12 @@
"prefs.layout_note": "紧凑模式将面板停靠在窗口边缘。浏览器半透明仅适用于浮动模式。助手面板的位置在助手页面中设置。",
"prefs.left": "左侧",
"prefs.left_click": "左键单击",
"prefs.linked_designs": "链接设计",
"prefs.live_input": "实时输入",
"prefs.live_preview": "实时预览",
"prefs.logo": "标志",
"prefs.logo_accent": "强调色",
"prefs.logo_theme": "主题颜色",
"prefs.minutes": "分钟",
"prefs.minutes_suffix": " min",
"prefs.mouse": "鼠标与触控板",
@@ -1832,6 +1846,10 @@
"prefs.sketch_selection": "草图与选择",
"prefs.sketch_selection_heading": "草图和选择",
"prefs.sketch_selection_note": "草图如何捕捉,以及单击如何选择。",
"prefs.sketch_tab_always": "始终显示草图选项卡",
"prefs.sketch_tab_always_note": "未打开草图时,草图选项卡也保留在功能区中紧随模型之后。其中的绘图工具会先在所选平面或面上(否则在接下来选取的平面上)创建草图,并在其中准备好该工具。",
"prefs.sketch_tracking_guides": "圆心和中点对齐辅助线",
"prefs.sketch_tracking_guides_note": "将光标悬停在圆心或直线边的中点,然后水平或垂直移动以显示临时虚线辅助线。",
"prefs.sketching": "草图",
"prefs.snap_drawing_note": "在绘制或拖动草图点时使用。",
"prefs.source": "来源",
@@ -1844,12 +1862,16 @@
"prefs.supersampling_brief": "以更高分辨率绘制后滤波缩小:更清晰,但负载更高。",
"prefs.tab_accent_note": "强调色跟随当前选项卡",
"prefs.theme_file": "主题文件",
"prefs.theme_file_or_paste": "文件或粘贴",
"prefs.theme_follow": "跟随主题文件",
"prefs.theme_follow_error": "未应用:{error}。保留上次有效的主题。",
"prefs.theme_follow_launch": "仅本次运行跟随 (--theme-file);其他工具改写文件时会重新加载。",
"prefs.theme_follow_note": "其他工具改写文件时会重新加载。选择主题将停止跟随。",
"prefs.theme_follow_off": "关闭",
"prefs.theme_follow_stop": "停止跟随",
"prefs.theme_import_hint": "单击选择主题文件,拖放到此处,或复制主题后按 Ctrl+V(Mac 上为 Cmd+V)",
"prefs.theme_paste": "粘贴主题",
"prefs.theme_paste_none": "剪贴板中没有 SolidCraft 主题",
"prefs.timeline_half_hour": "−30 分钟",
"prefs.timeline_now": "现在",
"prefs.timeline_quarter_hour": "−15",
@@ -1916,6 +1938,7 @@
"render.all_controls_help": "集中显示当前所有控件;各分页可针对相应任务编辑,不改变底层请求。",
"render.all_shots_label": "所有镜头",
"render.appearance_physics_separate": "视觉外观不会分配密度、热学数据或其他工程属性。",
"render.appearances": "外观",
"render.availability_native": "原生组合;应用前请审阅",
"render.availability_projection": "支持的部分映射;请查看范围和省略项",
"render.availability_reference": "参考数据;不会自动分配",
@@ -1970,6 +1993,10 @@
"render.camera_set": "设置渲染相机",
"render.camera_target": "目标位置 · mm",
"render.camera_yaw": "偏航",
"render.category_metal": "金属",
"render.category_paint": "涂漆",
"render.category_plastic": "塑料",
"render.category_wood": "木材",
"render.chromatic_offset": "边缘色差偏移",
"render.clear_stage": "移除已保存的舞台",
"render.copy_request": "复制 JSON",
@@ -2069,6 +2096,7 @@
"render.effects_reset_lens": "重置镜头效果",
"render.effects_seed": "图案种子",
"render.emitted_axis": "发射轴",
"render.environment_tiles_require_raytrace": "环境需要 CPU 或 GPU 光线追踪。请在输出编辑器中选择。",
"render.error_area_samples": "area_samples 必须为 1、4、16 或 64",
"render.error_binding_allocation": "无法分配材质绑定",
"render.error_body_bound": "产品预览超出捕获实体数上限",
@@ -2140,6 +2168,8 @@
"render.flare_strength": "高光耀斑强度",
"render.flare_threshold": "场景线性耀斑阈值",
"render.fold_browser": "折叠浏览器",
"render.frame_presets": "构图预设",
"render.frame_presets_pending": "随镜头编辑器推出",
"render.gpu_depth": "最大路径深度",
"render.gpu_options_help": "采样数、深度、种子和曝光会随此配置保存。仅保存当前图像方法。",
"render.gpu_path_failed": "GPU 路径追踪器不可用",
@@ -2211,8 +2241,12 @@
"render.lens_effects_title": "镜头风格与摄影",
"render.library_all": "目录",
"render.library_all_states": "全部可用状态",
"render.library_appearance_available": "可用外观",
"render.library_applicable": "适用资源",
"render.library_applied": "资源映射已应用;开始前请检查完整渲染请求。",
"render.library_apply_appearance": "应用外观",
"render.library_apply_hdr": "使用此 HDR 环境保存",
"render.library_apply_hint": "点击应用 · 拖到模型上",
"render.library_apply_maps": "使用已制作的 GPU 表面贴图",
"render.library_apply_studio": "保存已制作的工作室映射",
"render.library_apply_uniform": "应用均匀不透明外观",
@@ -2228,15 +2262,23 @@
"render.library_extent": "主体范围",
"render.library_favorite": "添加收藏",
"render.library_favorites": "收藏",
"render.library_filters": "目录与可用性",
"render.library_grid": "网格",
"render.library_hdr": "内置 HDR 环境",
"render.library_hdr_help": "将原始 HDR 嵌入已保存设置。明确转换创作时的经度原点;保存后不再需要外部文件。",
"render.library_in_design": "设计中",
"render.library_inspect_only": "选择仅用于检查,不会自动应用;收藏和最近记录属于当前打开的文档会话。",
"render.library_ior": "折射率",
"render.library_light_concepts": "照明概念",
"render.library_list": "列表",
"render.library_maps_help": "内置贴图可连同固定源和局部实例映射一起保存;临时光学覆盖仍属于独立模式。",
"render.library_material_concepts": "材质概念",
"render.library_metallic": "金属度",
"render.library_native_scenes": "原生工作室",
"render.library_next": "下一页",
"render.library_omitted": "未包含的内容",
"render.library_opacity": "不透明度",
"render.library_other": "其他外观",
"render.library_physical_profiles": "物理参考配置",
"render.library_previous": "上一页",
"render.library_quality_concepts": "质量规格",
@@ -2246,6 +2288,7 @@
"render.library_results": "匹配资源",
"render.library_rig_help": "在明确的中心和物理范围下适配一次。完整组合包含被动反光板;需要校准时仍会拒绝。保存前检查发光体及反光板的保守间隙。",
"render.library_rigs": "已制作的灯光组合",
"render.library_roughness": "粗糙度",
"render.library_save_maps": "将贴图保存到此设置",
"render.library_scene_bounds": "使用捕获的场景边界",
"render.library_scenes": "场景规格",
@@ -2269,6 +2312,7 @@
"render.library_unfavorite": "移除收藏",
"render.library_uniform_ack": "使用不含空间或高级效果的均匀近似",
"render.library_usable": "可执行映射",
"render.library_users": "使用位置",
"render.light_anchor_pending": "暂不支持更改灯光坐标系。",
"render.lights_fixed_to": "灯光固定到",
"render.linear_help": "保留降噪、曝光、色调映射、滤镜和背景处理前的 32 位浮点 RGBA。线性 sRGB/D65,预乘覆盖率。额外内存经明确准入检查;无压缩或额外通道。",
@@ -2487,6 +2531,7 @@
"render.scene_review": "解析并审阅",
"render.scene_review_help": "应用前请审阅完整原生组合;不会替换为未绑定的高级 SCENE 规格。",
"render.scene_scope_details": "组合范围",
"render.search_appearances": "搜索 {count} 种外观",
"render.setup_legacy_environment": "此旧设置使用旧版环境旋转或强度。这些值会保留;保存完整图像任务前,请明确转换它们。",
"render.setup_name": "设置名称",
"render.setup_numeric_help": "保存会记录当前图像方法及其全部数值设置。重新加载或选择其他设置会替换此草稿;相机需单独恢复。",
@@ -2505,10 +2550,19 @@
"render.shot_remove_title": "删除已保存镜头?",
"render.shot_rename": "重命名已保存镜头",
"render.shot_saved_only": "请先保存当前草稿;复制和重命名会保留精确的保存选项与资源引用。",
"render.shots_camera_changed": "相机已在此镜头保存后发生变化",
"render.shots_name_help": "请输入当前镜头的唯一名称。",
"render.shots_no_result": "尚无渲染结果",
"render.shots_result": "渲染 {number} · {width} × {height}",
"render.shots_revert": "还原",
"render.shots_save": "保存镜头",
"render.shots_update": "更新镜头",
"render.show_shots_label": "显示镜头条",
"render.size_4k_uhd": "4K 超高清",
"render.size_full_hd": "全高清",
"render.size_hd": "HD",
"render.size_presets": "尺寸预设",
"render.size_presets_pending": "随输出编辑器推出",
"render.sky_ground": "地面 · 线性 RGB",
"render.sky_horizon": "地平线 · 线性 RGB",
"render.sky_zenith": "天顶 · 线性 RGB",
@@ -2559,8 +2613,10 @@
"render.studio_sky_help": "原创天空渐变用于照明,并非校准的大气模型。",
"render.studio_sun": "太阳",
"render.studio_sun_radius": "角半径",
"render.studio_tiles_require_gpu": "摄影棚需要 GPU 路径追踪。请在输出编辑器中选择 GPU。",
"render.studio_title": "渲染工作室",
"render.studio_tone_map": "色调映射",
"render.studios_environments": "摄影棚和环境",
"render.subsurface_enable": "内部散射随机游走",
"render.subsurface_help": "仅适用于封闭介质。散射和RGB吸收使用独立的每毫米系数。路径在实际几何内部散射,并在边界折射或反射。关闭直线透射阴影、表面降噪和外部体积;使用一个菲涅耳分层。这不是扩散着色器、密度网格或实测材料。高密度可能需要更多样本和路径深度。",
"render.subsurface_rate": "散射碰撞率",
@@ -2668,6 +2724,7 @@
"select two components": "请选择两个组件",
"set by the sketch's lines": "由草图的线条决定",
"settings.display_quality_note": "仅影响显示,不影响设计和导出。",
"settings.double_click_components": "双击组件以激活它,或在原位编辑链接组件",
"settings.frame_rate_details_note": "添加最近各帧耗时的图表(叠加绘制的三角形数)、帧耗时直方图以及 GPU 绘制的内容。点击视图中的帧率可显示或隐藏。",
"settings.frame_rate_note": "在视图右下角显示每秒帧数。",
"settings.measure_axis_distances": "显示 X/Y/Z 距离",
@@ -2680,6 +2737,7 @@
"settings.reset_intro": "这些设置在此计算机上无法正常工作,会导致 SolidCraft 无法启动,因此已更改:",
"settings.reset_title": "设置已更改",
"settings.supersampling_note": "以更高分辨率绘制视图再缩小:在低于 4K 的屏幕上边、线和网格更平滑。会消耗 GPU 时间:1.5× 时约 2.25 倍像素,2× 时 4 倍。",
"settings.update_changed_links": "返回标签页时更新已更改的链接设计",
"settings.window_system_details": "详情",
"settings.window_system_note_now": "重启后生效。当前:{now}。",
"settings.window_system_wayland_limited": "在原生 Wayland 下部分功能受限。",
@@ -3283,6 +3341,24 @@
"ui.easyprint_uploading": "正在上传到 Printables…",
"ui.edit": "编辑",
"ui.editJointLimits": "编辑接头限制",
"ui.edit_in_place": "原位编辑",
"ui.edit_in_place_after_turn": "代理本轮结束后将完成编辑",
"ui.edit_in_place_agent_busy": "代理仍在此设计中工作;请在其本轮结束后重试",
"ui.edit_in_place_already_queued": "已有编辑在等待代理本轮结束",
"ui.edit_in_place_assembly_closed": "{name} 已不再打开",
"ui.edit_in_place_banner": "正在 {name} 中编辑",
"ui.edit_in_place_busy": "请先完成或取消打开的操作",
"ui.edit_in_place_none": "没有正在原位编辑的链接设计",
"ui.edit_in_place_not_saved": "零件有未保存的更改;请保存以完成编辑",
"ui.edit_in_place_open_elsewhere": "{name} 已在另一个 SolidCraft 中打开",
"ui.edit_in_place_opens_after_turn": "代理本轮结束后将打开零件",
"ui.edit_in_place_refresh_dropped": "更新链接期间装配体已更改;请再次运行",
"ui.edit_in_place_refresh_stopped": "更新链接在完成前已停止",
"ui.edit_in_place_refreshing": "正在更新 {name} 中的链接…",
"ui.edit_in_place_save_first": "请先保存装配体:其链接设计根据其文件查找",
"ui.edit_in_place_save_waits": "正在更新 {name} 中的链接;请在完成后保存",
"ui.edit_in_place_saved_elsewhere": "零件已保存到其他文件;装配体仍链接 {name}",
"ui.edit_in_place_wait": "请等待设计中正在运行的操作完成",
"ui.edit_section_analysis": "编辑截面分析",
"ui.ellipse": "椭圆",
"ui.emboss_wrap_note": "与受支持圆柱相切的正交线轮廓会自动缠绕。选择一个壁以指定目标。",
@@ -3357,6 +3433,7 @@
"ui.heading_edit": "编辑",
"ui.heading_extrude": "拉伸",
"ui.heading_fillet": "圆角",
"ui.heading_finish_editing": "完成编辑",
"ui.heading_finish_sketch": "完成草图",
"ui.heading_form": "造型",
"ui.heading_front": "前视",
@@ -3616,6 +3693,8 @@
"ui.restore_defaults": "恢复默认值",
"ui.reverse_horizontal_pan_direction": "反转水平平移方向",
"ui.reverse_horizontal_pan_tip": "水平双指滚动和拇指滚轮向相反方向平移",
"ui.reverse_vertical_pan_direction": "反转垂直平移方向",
"ui.reverse_vertical_pan_tip": "双指垂直滚动向相反方向平移",
"ui.reverse_zoom_direction": "反转缩放方向",
"ui.revolutions": "圈数",
"ui.revolve": "旋转",
@@ -3761,6 +3840,15 @@
"ui.updateToCurrentView": "更新为当前视图",
"ui.upload": "上传",
"ui.vertical_constraint": "垂直约束",
"ui.view_angles": "视图角度",
"ui.view_angles_convention": "绕向上轴的角度(度)。偏航 0° 为前视图,90° 为左视图,−90° 为右视图,180° 为后视图;俯仰 90° 为俯视图;滚转为正时,模型在屏幕上顺时针旋转。",
"ui.view_angles_help": "在方向小部件下方显示视图的俯仰、偏航和滚转角(度)以及投影方式。单击读数可输入精确角度。",
"ui.view_angles_ortho": "正交",
"ui.view_angles_persp": "透视",
"ui.view_angles_pitch": "俯仰",
"ui.view_angles_readout": "俯仰 {pitch} · 偏航 {yaw} · 滚转 {roll}",
"ui.view_angles_roll": "滚转",
"ui.view_angles_yaw": "偏航",
"ui.view_centre": "视图中心",
"ui.viewport_theme_follow": "跟随主题",
"ui.visual_shaded_hidden_edges": "带隐藏边的着色",
+7 -4
View File
@@ -10,7 +10,7 @@ struct U {
acc_u: vec4<f32>, // accessibility map axes (xyz, offset)
acc_v: vec4<f32>,
eye: vec4<f32>, // eye position, w = 1 for perspective (0: orthographic, looking along -back)
ao: vec4<f32>, // radius in world units (zero: disabled)
ao: vec4<f32>, // x: radius in world units (zero: disabled), y: samples per pixel
// analysis colours (`theme::AnalysisColors`): draft positive, between, negative; reachable,
// blocked; curvature flat, middle, tight
ana_c: array<vec4<f32>, 8>,
@@ -333,9 +333,12 @@ fn occlusion(i: TOut) -> f32 {
// the buffer runs reversed). The map is cleared to its far plane either way, so a texel
// with nothing in it reads as 1 and the `d < 1.0` test below skips it.
let flip = reversed();
// Fewer samples while the view moves (#7165), spread over the same hemisphere. 32 is the
// still picture's count, `AO_SAMPLES` in view.rs.
let count = u32(clamp(u.ao.y, 1.0, 32.0));
var blocked = 0.0;
for (var j = 0u; j < 32u; j = j + 1u) {
let f = (f32(j) + 0.5) / 32.0;
for (var j = 0u; j < count; j = j + 1u) {
let f = (f32(j) + 0.5) / f32(count);
let angle = f32(j) * 2.39996323;
let direction = t * (cos(angle) * sqrt(f)) + b * (sin(angle) * sqrt(f)) + n * sqrt(1.0 - f);
let reach = radius * (0.2 + 0.8 * fract(f32(j) * 0.61803399 + 0.5));
@@ -356,7 +359,7 @@ fn occlusion(i: TOut) -> f32 {
blocked = blocked + smoothstep(0.005, 0.15, delta) * (1.0 - smoothstep(0.5, 1.0, delta));
}
}
return 1.0 - 0.85 * blocked / 32.0;
return 1.0 - 0.85 * blocked / f32(count);
}
/// How fast the normal turns across the pixel (per mm).
+7 -4
View File
@@ -193,8 +193,10 @@ impl Tokens {
sketch_halo: Color32::from_rgb(240, 243, 247),
sketch_point: Color32::BLACK,
sketch_locked: Color32::from_rgb(0, 140, 60),
dimension: Color32::from_rgb(36, 40, 48),
dimension_driven: Color32::from_rgb(120, 126, 138),
// Sketch dimensions in a plum of their own, apart from the blue and black curves for
// every colour vision mode (#7861).
dimension: Color32::from_rgb(130, 42, 110),
dimension_driven: Color32::from_rgb(160, 90, 120),
sketch_point_free: Color32::from_rgb(30, 90, 200),
section_cap: Color32::from_rgb(214, 128, 72),
dialog_bg: Color32::from_rgb(250, 251, 252),
@@ -358,8 +360,9 @@ impl Tokens {
t.sketch_halo = Color32::from_rgb(28, 32, 40);
t.sketch_point = Color32::from_rgb(232, 234, 238);
t.sketch_locked = Color32::from_rgb(96, 204, 116);
t.dimension = Color32::from_rgb(224, 228, 234);
t.dimension_driven = Color32::from_rgb(142, 150, 164);
// Sketch dimensions: Light's plum, lightened for the dark view (#7861).
t.dimension = Color32::from_rgb(224, 176, 224);
t.dimension_driven = Color32::from_rgb(176, 104, 144);
t.sketch_point_free = Color32::from_rgb(92, 150, 255);
t.profile_fill = Color32::from_rgba_unmultiplied_const(120, 150, 200, 40);
t.dialog_bg = Color32::from_rgb(39, 43, 52);
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#efece8",
"dialog_label": "#403d38",
"dialog_rule": "#d9d5d0",
"dimension": "#403d38",
"dimension_driven": "#6c6863",
"dimension": "#006a70",
"dimension_driven": "#4d8a8c",
"error": "#c71529",
"field": "#fffdfa",
"file_rail": "#e1ddd8",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#100b04",
"dialog_label": "#f3ca87",
"dialog_rule": "#3b280d",
"dimension": "#ffe2a5",
"dimension_driven": "#9b6922",
"dimension": "#f5e050",
"dimension_driven": "#a8962e",
"error": "#fff0ca",
"field": "#100b04",
"form_accent": "#ca892b",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#0c223c",
"dialog_label": "#e3f0fa",
"dialog_rule": "#254764",
"dimension": "#e3f0fa",
"dimension_driven": "#94b2cb",
"dimension": "#ffd970",
"dimension_driven": "#c9a95a",
"error": "#ff968d",
"field": "#071d35",
"form_accent": "#baade8",
@@ -50,8 +50,8 @@
"dialog_footer": "#1e1e2e",
"dialog_label": "#cdd6f4",
"dialog_rule": "#45475a",
"dimension": "#cdd6f4",
"dimension_driven": "#a6adc8",
"dimension": "#94e2d5",
"dimension_driven": "#6c9d95",
"error": "#f38ba8",
"field": "#181825",
"form_accent": "#a9b2f2",
+2 -2
View File
@@ -45,8 +45,8 @@
"dialog_footer": "#000000",
"dialog_label": "#55ffff",
"dialog_rule": "#00aaaa",
"dimension": "#ffffff",
"dimension_driven": "#aaaaaa",
"dimension": "#ffff55",
"dimension_driven": "#aa5500",
"error": "#ff5555",
"field": "#000000",
"file_background": "#000000",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#29241f",
"dialog_label": "#c3bdb5",
"dialog_rule": "#403930",
"dimension": "#c3bdb5",
"dimension_driven": "#9d9285",
"dimension": "#5fc4c0",
"dimension_driven": "#4f9895",
"error": "#f85052",
"field": "#3c352d",
"form_accent": "#a6a2fc",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#f4eee3",
"dialog_label": "#423e36",
"dialog_rule": "#e0d8c9",
"dimension": "#423e36",
"dimension_driven": "#726a5d",
"dimension": "#006a70",
"dimension_driven": "#4a8688",
"error": "#c71529",
"field": "#fdfaf3",
"form_accent": "#5844bc",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#ececec",
"dialog_label": "#262628",
"dialog_rule": "#c6c6c8",
"dimension": "#262628",
"dimension_driven": "#6e6e73",
"dimension": "#00646b",
"dimension_driven": "#3d8087",
"error": "#d53137",
"field": "#ffffff",
"form_accent": "#8b62bf",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#25272b",
"dialog_label": "#e0e2e5",
"dialog_rule": "#484d55",
"dimension": "#e0e2e5",
"dimension_driven": "#a0a6b0",
"dimension": "#5fd0c8",
"dimension_driven": "#4a9a95",
"error": "#ed7777",
"field": "#1c1e21",
"form_accent": "#a08fc4",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#061009",
"dialog_label": "#8def9f",
"dialog_rule": "#173b22",
"dimension": "#8def9f",
"dimension_driven": "#5b9b6a",
"dimension": "#c8ff4d",
"dimension_driven": "#7fa040",
"error": "#d8ffdf",
"field": "#061009",
"form_accent": "#1faa4e",
@@ -55,8 +55,8 @@
"sketch_fixed": "#ebdbb2",
"sketch_halo": "#141617",
"sketch_locked": "#b8bb26",
"dimension": "#ebdbb2",
"dimension_driven": "#928374",
"dimension": "#fabd2f",
"dimension_driven": "#b57614",
"sketch_point": "#ebdbb2",
"sketch_point_free": "#83a598",
"dialog_bg": "#3c3836",
@@ -56,8 +56,8 @@
"sketch_fixed": "#ebdbb2",
"sketch_halo": "#1d2021",
"sketch_locked": "#b8bb26",
"dimension": "#ebdbb2",
"dimension_driven": "#928374",
"dimension": "#fabd2f",
"dimension_driven": "#b57614",
"sketch_point": "#ebdbb2",
"sketch_point_free": "#83a598",
"dialog_bg": "#3c3836",
+2 -2
View File
@@ -56,8 +56,8 @@
"sketch_fixed": "#ebdbb2",
"sketch_halo": "#1d2021",
"sketch_locked": "#b8bb26",
"dimension": "#ebdbb2",
"dimension_driven": "#928374",
"dimension": "#fabd2f",
"dimension_driven": "#b57614",
"sketch_point": "#ebdbb2",
"sketch_point_free": "#83a598",
"dialog_bg": "#3c3836",
@@ -55,8 +55,8 @@
"sketch_fixed": "#282828",
"sketch_halo": "#fbf8e3",
"sketch_locked": "#79740e",
"dimension": "#3c3836",
"dimension_driven": "#7c6f64",
"dimension": "#1f5c40",
"dimension_driven": "#4f7d64",
"sketch_point": "#282828",
"sketch_point_free": "#076678",
"dialog_bg": "#f9f5d7",
@@ -55,8 +55,8 @@
"sketch_fixed": "#282828",
"sketch_halo": "#f6edd0",
"sketch_locked": "#79740e",
"dimension": "#3c3836",
"dimension_driven": "#7c6f64",
"dimension": "#1f5c40",
"dimension_driven": "#4f7d64",
"sketch_point": "#282828",
"sketch_point_free": "#076678",
"dialog_bg": "#f2e5bc",
+2 -2
View File
@@ -55,8 +55,8 @@
"sketch_fixed": "#282828",
"sketch_halo": "#fcf5d8",
"sketch_locked": "#79740e",
"dimension": "#3c3836",
"dimension_driven": "#7c6f64",
"dimension": "#1f5c40",
"dimension_driven": "#4f7d64",
"sketch_point": "#282828",
"sketch_point_free": "#076678",
"dialog_bg": "#fbf1c7",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#000000",
"dialog_label": "#ffffff",
"dialog_rule": "#a0a0a0",
"dimension": "#ffffff",
"dimension_driven": "#cccccc",
"dimension": "#ffff66",
"dimension_driven": "#c8c850",
"error": "#ff6666",
"field": "#000000",
"form_accent": "#d98af9",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#2e3440",
"dialog_label": "#eceff4",
"dialog_rule": "#4c566a",
"dimension": "#eceff4",
"dimension_driven": "#a4b0c2",
"dimension": "#d08770",
"dimension_driven": "#a87060",
"error": "#bf616a",
"field": "#242933",
"form_accent": "#cfa7c7",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#282a36",
"dialog_label": "#f8f8f2",
"dialog_rule": "#50546d",
"dimension": "#f8f8f2",
"dimension_driven": "#a1a4c4",
"dimension": "#8be9fd",
"dimension_driven": "#62a3b1",
"error": "#ff5555",
"field": "#21222c",
"form_accent": "#c096e8",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#1b1e20",
"dialog_label": "#bbbec1",
"dialog_rule": "#2f3235",
"dimension": "#bbbec1",
"dimension_driven": "#8f9296",
"dimension": "#5fc4c0",
"dimension_driven": "#4f9895",
"error": "#f85052",
"field": "#2c2e31",
"file_rail": "#0f1113",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#2f343e",
"dialog_label": "#b4bbc8",
"dialog_rule": "#353b47",
"dimension": "#abb2bf",
"dimension_driven": "#7f848e",
"dimension": "#56b6c2",
"dimension_driven": "#3f8590",
"error": "#e06c75",
"field": "#1e2227",
"form_accent": "#d283e9",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#dddddd",
"dialog_label": "#222222",
"dialog_rule": "#aaaaaa",
"dimension": "#222222",
"dimension_driven": "#666666",
"dimension": "#00787f",
"dimension_driven": "#4d9196",
"error": "#bb3333",
"field": "#ffffff",
"form_accent": "#704e81",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#eee8d5",
"dialog_label": "#586e75",
"dialog_rule": "#b6b3a1",
"dimension": "#586e75",
"dimension_driven": "#657b83",
"dimension": "#136059",
"dimension_driven": "#3d8f88",
"error": "#dc322f",
"field": "#fdf6e3",
"form_accent": "#6b70c3",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#c0c0c0",
"dialog_label": "#000000",
"dialog_rule": "#808080",
"dimension": "#000000",
"dimension_driven": "#808080",
"dimension": "#ffffff",
"dimension_driven": "#ffff00",
"error": "#ff0000",
"field": "#ffffff",
"form_accent": "#800080",
+2 -2
View File
@@ -50,8 +50,8 @@
"dialog_footer": "#1a1b26",
"dialog_label": "#c0caf5",
"dialog_rule": "#414868",
"dimension": "#c0caf5",
"dimension_driven": "#9aa5ce",
"dimension": "#73daca",
"dimension_driven": "#4f9a90",
"error": "#f7768e",
"field": "#16161e",
"form_accent": "#b190ec",
+43 -17
View File
@@ -1,15 +1,40 @@
//! Lists the design-format changes in `src/format/`: one file per change, in `v<N>/` once a
//! release fixed its number, else in `pending/` (see `src/format/pending/README.md`). The list is
//! Lists the format changes of each family of files versioned by `src/format.rs`: designs in
//! `src/format/`, drawings in `src/drawing/format/` (#3890). One file per change, in `v<N>/` once a
//! release fixed its number, else in `pending/` (see `src/format/pending/README.md`). The lists are
//! generated so that a change adds a file and never edits a line another change also edits.
use std::fmt::Write as _;
use std::path::{Path, PathBuf};
/// The last format whose upgrade steps are written out in `format.rs` (`JSON_STEPS`).
const HAND_WRITTEN: u32 = 22;
/// A family's change files: their folder, the last format before them, and the prefix of the
/// family's lists in `format.rs`.
struct Family {
folder: &'static str,
base: u32,
list_prefix: &'static str,
}
/// Every family, each read by `scripts/fold-format-pending.sh` too. A design's upgrade steps are
/// written out in `format.rs` up to 22 (`JSON_STEPS`); a drawing's first format is 1.
const FAMILIES: [Family; 2] =
[Family { folder: "src/format", base: 22, list_prefix: "" }, Family { folder: "src/drawing/format", base: 1, list_prefix: "DRAWING_" }];
fn main() {
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("src/format");
let manifest = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let mut out = String::new();
let mut mods = String::new();
for family in &FAMILIES {
lists(family, &manifest, &mut out, &mut mods);
}
out.push_str(&mods);
let dest = PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("format_parts.rs");
std::fs::write(dest, out).unwrap();
}
/// A family's `FOLDED` and `PENDING` lists; its folded formats follow on from its base.
fn lists(family: &Family, manifest: &Path, out: &mut String, mods: &mut String) {
let Family { folder, base, list_prefix } = family;
let root = manifest.join(folder);
println!("cargo:rerun-if-changed={}", root.display());
let mut folded: Vec<(u32, PathBuf)> = std::fs::read_dir(&root)
.unwrap_or_else(|e| panic!("{}: {e}", root.display()))
@@ -21,23 +46,24 @@ fn main() {
.collect();
folded.sort();
for (i, (version, _)) in folded.iter().enumerate() {
let expected = HAND_WRITTEN + 1 + i as u32;
assert_eq!(*version, expected, "src/format/: expected v{expected}/ next, found v{version}/ (versions are contiguous)");
let expected = base + 1 + i as u32;
assert_eq!(*version, expected, "{folder}/: expected v{expected}/ next, found v{version}/ (versions are contiguous)");
}
let mut out = String::new();
let mut mods = String::new();
out.push_str("/// The changes of each format after the hand-written ones, oldest first.\nconst FOLDED: &[(u32, &[Part])] = &[\n");
// Module names start with the family's (`drawing_pending_…`), so two families' changes of one
// name never clash.
let module = list_prefix.to_ascii_lowercase();
let _ = writeln!(
out,
"/// The changes of each format after the base, oldest first (`{folder}/v<N>/`).\nconst {list_prefix}FOLDED: &[(u32, &[Part])] = &["
);
for (version, dir) in &folded {
let _ = writeln!(out, " ({version}, &[");
parts(dir, &format!("v{version}"), &mut out, &mut mods);
parts(dir, &format!("{module}v{version}"), out, mods);
out.push_str(" ]),\n");
}
out.push_str("];\n\n/// The changes no release has a number for yet (`src/format/pending/`).\nconst PENDING: &[Part] = &[\n");
parts(&root.join("pending"), "pending", &mut out, &mut mods);
out.push_str("];\n");
out.push_str(&mods);
let dest = PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("format_parts.rs");
std::fs::write(dest, out).unwrap();
let _ = writeln!(out, "];\n\n/// The changes no release has a number for yet (`{folder}/pending/`).\nconst {list_prefix}PENDING: &[Part] = &[");
parts(&root.join("pending"), &format!("{module}pending"), out, mods);
out.push_str("];\n\n");
}
/// The `Part`s of the change files in `dir`, in file-name order, and a module for each.
+2
View File
@@ -815,6 +815,8 @@ mod tests {
bad.boundary = GlassBoundary::Thin { thickness_mm: 10001.0 };
assert!(bad.validate().is_err());
}
// The swatch shows the transmission as sRGB codes.
assert_eq!(find("starter.glass.smoky-neutral").unwrap().preview_color(), [160, 166, 173]);
}
#[test]
+1 -4
View File
@@ -154,10 +154,7 @@ impl VisualPreset {
match self.recipe {
Recipe::Opaque(r) => r.color,
// A UI swatch of the transmission values, not rendered glass or absorption.
Recipe::Glass(r) => r.transmission_linear_rgb.map(|v| {
let encoded = if v <= 0.0031308 { 12.92 * v } else { 1.055 * v.powf(1.0 / 2.4) - 0.055 };
(encoded.clamp(0.0, 1.0) * 255.0).round() as u8
}),
Recipe::Glass(r) => r.transmission_linear_rgb.map(solidcraft_geom::srgb::encode8),
}
}
+42
View File
@@ -124,6 +124,48 @@ fn identity() -> Mat {
IDENTITY
}
/// How a component counts in the bill of materials of an assembly it is placed in. It is a part
/// property (the `bom_type` key of the component's [`Metadata`](crate::Metadata)); a component
/// without one is [`BomType::Normal`].
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BomType {
/// A row of its own; every occurrence adds to its quantity.
#[default]
Normal,
/// No row of its own: what it holds counts as if placed directly in its parent.
Phantom,
/// Shown, but counted nowhere, and nothing inside it is counted either.
Reference,
/// Bought: one row, with nothing inside it counted or listed.
Purchased,
/// Made as one item that doesn't come apart (a welded frame): one row in the assembly it is
/// placed in. What it holds is listed in its own bill of materials, and its purchased parts
/// also in the parts-only list of the assembly it is placed in.
Inseparable,
}
impl BomType {
/// Every type, in the order commands and documentation list them.
pub const ALL: [BomType; 5] = [BomType::Normal, BomType::Phantom, BomType::Reference, BomType::Purchased, BomType::Inseparable];
/// The word the design file and commands use.
pub fn as_str(self) -> &'static str {
match self {
BomType::Normal => "normal",
BomType::Phantom => "phantom",
BomType::Reference => "reference",
BomType::Purchased => "purchased",
BomType::Inseparable => "inseparable",
}
}
/// The type a word names, if it names one.
pub fn parse(word: &str) -> Option<BomType> {
BomType::ALL.into_iter().find(|t| t.as_str() == word)
}
}
/// How deep and how many placements [`Document::placements`] walks.
pub const MAX_PLACEMENT_DEPTH: usize = 64;
pub const MAX_PLACEMENTS: usize = 100_000;
+305
View File
@@ -0,0 +1,305 @@
//! A drawing (#3890): sheets of paper that draw designs saved in their own files. A drawing is a
//! file of its own, `"format": "solidcraft-drawing/N"`, versioned by the same code as designs
//! ([`DRAWING`]); format 1 is this record.
//!
//! - **Sources** are the designs it draws: an id and the design file's path, relative to the
//! drawing's folder once the drawing is saved, else as given, with `/` between folders (a linked
//! design's [`DesignLink`](crate::DesignLink) rule). What a design was when the drawing last saw
//! it is not saved here.
//! - **Sheets**: the paper, a copy of its drawing border, the resolution its pictures are rendered
//! at, the component it documents, and whether it is left out of the sheet count or of printing.
//! The border is a copy of the profile it was made with, never a name, so a later built-in never
//! changes a saved drawing.
//! - **Units** follow each view's design or are one length unit for the whole drawing. The
//! **language** is the content's, a BCP 47 tag chosen when the drawing is made, whatever the
//! interface's is. **Properties** follow [`Metadata`]'s rules.
//!
//! The rules, which every later kind of record (views, annotations, tables) keeps too:
//! - Every object has an id of [`crate::ids`]: random, so objects added side by side never take
//! the same one, and written as 13 characters of base32. No two objects share an id, and a run
//! never gives a removed object's id again ([`Drawing::allocate_id`]).
//! - Every reference between records is an id and must resolve: a file with one that doesn't is
//! damaged and refused, never patched.
//! - 1 to [`MAX_SHEETS`] sheets and at most [`MAX_SOURCES`] sources; names of 1 to
//! [`MAX_NAME_BYTES`] bytes; paths of 1 to [`MAX_PATH_BYTES`] bytes, without NUL.
//! - Nothing derived is saved, and a drawing always saves as the same bytes: fields in their
//! order, maps sorted.
//! - A later change to the record is one file in `src/drawing/format/pending/` (its README).
//!
//! [`Drawing::from_json`] reads a file in this order: at most [`MAX_DRAWING_BYTES`] of text, the
//! family's format check, every number in range, the upgrade, the typed record, then
//! [`Drawing::validate`].
use std::collections::BTreeSet;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use solidcraft_geom::drawing_sheet::{self, DrawingBorderProfile};
use crate::format::DRAWING;
use crate::ids::{self, IdSource};
use crate::{DocError, Metadata, Result, expr};
/// The most sheets a drawing may have.
pub const MAX_SHEETS: usize = 1000;
/// The most designs a drawing may draw.
pub const MAX_SOURCES: usize = 64;
/// The longest name of a drawing or a sheet, in bytes.
pub const MAX_NAME_BYTES: usize = 256;
/// The longest path to a design, in bytes.
pub const MAX_PATH_BYTES: usize = 4096;
/// The longest language tag: what RFC 5646 asks every reader to take (§4.4.1).
pub const MAX_LANGUAGE_CHARS: usize = 35;
/// The largest drawing read, as JSON text.
pub const MAX_DRAWING_BYTES: usize = 16 << 20;
/// The resolution a sheet's pictures (its shaded views) are rendered at unless it says, in dots
/// per inch.
pub const DEFAULT_DPI: f64 = 300.0;
/// The lowest resolution a sheet may ask for.
pub const MIN_DPI: f64 = 25.0;
/// The highest resolution a sheet may ask for.
pub const MAX_DPI: f64 = 2400.0;
/// A drawing: its sheets and the designs they draw.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Drawing {
/// `solidcraft-drawing/N`: the format this build writes, whatever the file said.
pub format: String,
/// The changes of `format` this drawing has while they are pending
/// ([`Family::pending_names`](crate::format::Family::pending_names)). Empty, and not saved,
/// otherwise.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub format_pending: Vec<String>,
pub name: String,
/// The designs the drawing draws.
pub sources: Vec<Source>,
/// The drawing's properties and other tools' data, kept as they are.
#[serde(default, skip_serializing_if = "Metadata::is_empty")]
pub properties: Metadata,
#[serde(default)]
pub units: Units,
/// The language of the drawing's content, a BCP 47 tag (`en-GB`).
pub language: String,
/// In order, each behind its own `Arc`, so an undo step shares every sheet it didn't change.
pub sheets: Vec<Arc<Sheet>>,
}
/// A design the drawing draws.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Source {
#[serde(with = "crate::ids")]
pub id: u64,
/// The design file: relative to the drawing's folder once the drawing is saved, else as given
/// (`/` separates folders).
pub path: String,
}
/// The length unit a drawing gives its measurements in.
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub enum Units {
/// Each view's design's own units.
#[default]
FollowModel,
/// One length unit for the whole drawing, by its name in [`expr::UNITS`] (`mm`, `in`).
Fixed { unit: String },
}
/// One sheet of a drawing.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Sheet {
#[serde(with = "crate::ids")]
pub id: u64,
pub name: String,
/// The paper: its size and the way it lies.
pub sheet: drawing_sheet::Sheet,
/// A copy of the drawing border's profile (`None`: no drawing border).
pub border: Option<DrawingBorderProfile>,
/// The resolution its pictures (its shaded views) are rendered at, in dots per inch.
#[serde(default = "default_dpi")]
pub dpi: f64,
/// The component the sheet documents, which its title block reads.
pub documents: Option<SheetComponent>,
#[serde(default)]
pub excluded: Excluded,
}
/// A component of one of the drawing's designs.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SheetComponent {
/// The [`Source`]'s id.
#[serde(with = "crate::ids")]
pub source: u64,
/// The component's id in that design, as the design writes it (0: the design itself).
pub component: u64,
}
/// What a sheet is left out of.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct Excluded {
/// The sheet count ("sheet 2 of 3" on the other sheets).
pub count: bool,
/// Printing and exporting every sheet.
pub print: bool,
}
fn default_dpi() -> f64 {
DEFAULT_DPI
}
impl Drawing {
/// A drawing of no designs yet, named `name` and written in `language`, with one sheet named
/// `sheet`: the paper `paper` with a copy of `border`, its id from `id_source`.
pub fn new(
name: &str,
language: &str,
sheet: &str,
paper: drawing_sheet::Sheet,
border: Option<DrawingBorderProfile>,
id_source: &mut IdSource,
) -> Result<Drawing> {
let id = id_source.next(&BTreeSet::new())?;
let first = Sheet { id, name: sheet.into(), sheet: paper, border, dpi: DEFAULT_DPI, documents: None, excluded: Excluded::default() };
let drawing = Drawing {
format: DRAWING.format_string(DRAWING.current()),
format_pending: DRAWING.pending_names(),
name: name.into(),
sources: Vec::new(),
properties: Metadata::default(),
units: Units::default(),
language: language.into(),
sheets: vec![Arc::new(first)],
};
drawing.validate()?;
Ok(drawing)
}
/// Read a drawing file's JSON (any format this build knows; older ones are upgraded). A file
/// that breaks a rule of the record is damaged and refused, never patched.
pub fn from_json(s: &str) -> Result<Drawing> {
if s.len() > MAX_DRAWING_BYTES {
return Err(DocError::Invalid(format!("drawing too large (at most {} MiB)", MAX_DRAWING_BYTES >> 20)));
}
let mut v: Value = serde_json::from_str(s).map_err(|e| DocError::Invalid(format!("not a SolidCraft drawing: {e}")))?;
let (version, applied) = DRAWING.take_version(&mut v)?;
DRAWING.check_numbers(&v, "properties")?;
DRAWING.upgrade(&mut v, version, applied.as_deref())?;
let d: Drawing = serde_json::from_value(v).map_err(damaged)?;
d.validate().map_err(damaged)?;
Ok(Drawing { format: DRAWING.format_string(DRAWING.current()), format_pending: DRAWING.pending_names(), ..d })
}
/// The drawing's JSON: the same bytes for the same drawing. JSON longer than a read takes
/// ([`MAX_DRAWING_BYTES`]) is refused, so every drawing saved opens again: other tools'
/// properties are kept as they came, and indenting them can make a drawing that read in
/// under the limit save over it.
pub fn to_json(&self) -> Result<String> {
let text = serde_json::to_string_pretty(self).map_err(|e| DocError::Invalid(format!("drawing not saved: {e}")))?;
require(text.len() <= MAX_DRAWING_BYTES, || format!("drawing too large to save (at most {} MiB)", MAX_DRAWING_BYTES >> 20))?;
Ok(text)
}
/// An id for a new object: one no object of the drawing has, from `id_source`, which never
/// gives one twice.
pub fn allocate_id(&self, id_source: &mut IdSource) -> Result<u64> {
id_source.next(&self.ids().collect())
}
/// Every object's id, of every kind: what a new id must differ from. Each later kind adds its
/// own here.
fn ids(&self) -> impl Iterator<Item = u64> {
self.sources.iter().map(|s| s.id).chain(self.sheets.iter().map(|s| s.id))
}
/// The record's rules (the module's notes): what reading a file checks, and what every edit
/// keeps.
pub fn validate(&self) -> Result<()> {
require((1..=MAX_SHEETS).contains(&self.sheets.len()), || format!("a drawing has 1 to {MAX_SHEETS} sheets"))?;
require(self.sources.len() <= MAX_SOURCES, || format!("a drawing draws at most {MAX_SOURCES} designs"))?;
check_name(&self.name, "the drawing's")?;
require(is_language_tag(&self.language), || {
format!("the language is not a BCP 47 tag of 2 to {MAX_LANGUAGE_CHARS} characters (such as `en` or `en-GB`)")
})?;
if let Units::Fixed { unit } = &self.units {
// A length unit of the expression unit table, written as the table writes it.
let length = unit.trim() == unit.as_str() && expr::unit_info(unit).is_some_and(|(kind, _)| kind == expr::Kind::Length);
require(length, || "the drawing's unit is not a length unit (such as `mm` or `in`)".into())?;
}
let mut seen = BTreeSet::new();
for id in self.ids() {
require(id != 0, || "an object has the id 0, which is never one".into())?;
require(seen.insert(id), || format!("two objects have the id {}", ids::encode(id)))?;
}
for source in &self.sources {
let path = &source.path;
require(!path.is_empty() && path.len() <= MAX_PATH_BYTES && !path.contains('\0'), || {
format!("source {}: a design's path is 1 to {MAX_PATH_BYTES} bytes, without NUL", ids::encode(source.id))
})?;
}
for sheet in &self.sheets {
self.check_sheet(sheet).map_err(|e| DocError::Invalid(format!("sheet {}: {e}", ids::encode(sheet.id))))?;
}
Ok(())
}
/// A sheet's own rules, and that the source it documents is one of the drawing's.
fn check_sheet(&self, sheet: &Sheet) -> Result<()> {
check_name(&sheet.name, "its")?;
sheet.sheet.size_mm().map_err(from_sheet)?;
if let Some(border) = &sheet.border {
border.validate().map_err(from_sheet)?;
}
require((MIN_DPI..=MAX_DPI).contains(&sheet.dpi), || format!("its pictures are {MIN_DPI} to {MAX_DPI} dpi"))?;
match sheet.documents {
Some(SheetComponent { source, .. }) => {
let named = || format!("it documents source {}, which the drawing doesn't have", ids::encode(source));
require(self.sources.iter().any(|s| s.id == source), named)
}
None => Ok(()),
}
}
}
/// `Ok` when `ok`, else the rule `broken` names.
fn require(ok: bool, broken: impl FnOnce() -> String) -> Result<()> {
if ok { Ok(()) } else { Err(DocError::Invalid(broken())) }
}
/// A name: 1 to [`MAX_NAME_BYTES`] bytes, not only spaces, without control characters.
fn check_name(name: &str, whose: &str) -> Result<()> {
require(!name.trim().is_empty() && name.len() <= MAX_NAME_BYTES && !name.chars().any(char::is_control), || {
format!("{whose} name is 1 to {MAX_NAME_BYTES} bytes, not only spaces, without control characters")
})
}
/// A well-formed language tag, as far as a drawing needs (RFC 5646 §2.1): 2 to
/// [`MAX_LANGUAGE_CHARS`] characters, subtags of 1 to 8 ASCII letters and digits joined by `-`,
/// the first of 2 to 8 letters (`en`, `en-GB`, `zh-Hans-CN`). Whether the subtags are registered
/// isn't checked, and a private-use tag alone (`x-…`) isn't taken.
fn is_language_tag(tag: &str) -> bool {
let mut subtags = tag.split('-');
let first = subtags.next().unwrap_or_default();
(2..=MAX_LANGUAGE_CHARS).contains(&tag.len())
&& (2..=8).contains(&first.len())
&& first.bytes().all(|b| b.is_ascii_alphabetic())
&& subtags.all(|s| (1..=8).contains(&s.len()) && s.bytes().all(|b| b.is_ascii_alphanumeric()))
}
/// A file that breaks a rule of the record.
fn damaged(e: impl std::fmt::Display) -> DocError {
DocError::Invalid(format!("damaged drawing: {e}"))
}
fn from_sheet(e: drawing_sheet::Invalid) -> DocError {
DocError::Invalid(e.to_string())
}
#[cfg(test)]
#[path = "drawing_tests.rs"]
mod tests;
@@ -0,0 +1,30 @@
# Pending drawing-format changes
One file per change to what a drawing file saves that no release has shipped yet. Drawings
(`"format": "solidcraft-drawing/N"`, #3890) are versioned by the same code as designs
(`crates/doc/src/format.rs`, `Family`), from their own first format, 1. Adding a file here is the
whole format bump: never edit the `DRAWING` family in `format.rs`, another change's file or a
`../v<N>/` folder.
- Name it after the change, lowercase with dashes: `sheet-views.rs`.
- Start it with a `//!` note: what is saved, what an older drawing gets without it, and what
the last release does with a drawing that has it (it refuses the newer format number).
- If older drawings must be rewritten as they open, add the step to the same file:
```rust
//! …the note…
use serde_json::Value;
pub fn step(v: &mut Value) -> crate::Result<()> {
// rewrite the drawing's JSON here
Ok(())
}
```
Steps run in file-name order, after the steps of every older format.
While this folder has a change in it, the build writes the next drawing format number (the last
folded one + 1, which no release reads), and lists the changes a drawing has in its
`format_pending` field, so a later build applies only the steps that drawing is missing. At
release time `scripts/fold-format-pending.sh` moves these files into `../v<N>/`, as it does the
design format's (`crates/doc/src/format/pending/README.md`).
+553
View File
@@ -0,0 +1,553 @@
use serde_json::json;
use solidcraft_geom::drawing_sheet::{Margins, Orientation, PaperSize, SheetSize};
use super::*;
/// The seed every test drawing's ids come from.
const SEED: u64 = 3890;
/// A profile of its own: ISO 5457's filing margin and trimming marks, which the built-in leaves off.
fn own_border() -> DrawingBorderProfile {
DrawingBorderProfile { filing_margin: true, trimming_mark_mm: Some([10.0, 5.0]), ..DrawingBorderProfile::iso() }
}
/// Three designs on two sheets: the first sheet (A3, the ISO border) documents component 7 of the
/// first design; the second (A4 portrait, a border of its own, 600 dpi, left out of printing)
/// documents the second design. The third design is on no sheet yet.
fn plate() -> Drawing {
let mut id_source = IdSource::seeded(SEED);
let a3 = drawing_sheet::Sheet::standard(PaperSize::A3, Orientation::Landscape);
let mut d = Drawing::new("Plate assembly", "en-GB", "Assembly", a3, Some(DrawingBorderProfile::iso()), &mut id_source).unwrap();
for path in ["plate.sc", "../parts/bolt.sc", "bracket.sc"] {
let id = d.allocate_id(&mut id_source).unwrap();
d.sources.push(Source { id, path: path.into() });
}
let (plate_id, bolt_id) = (d.sources[0].id, d.sources[1].id);
let id = d.allocate_id(&mut id_source).unwrap();
d.sheets.push(Arc::new(Sheet {
id,
name: "Bolt".into(),
sheet: drawing_sheet::Sheet::standard(PaperSize::A4, Orientation::Portrait),
border: Some(own_border()),
dpi: 600.0,
documents: Some(SheetComponent { source: bolt_id, component: 0 }),
excluded: Excluded { count: false, print: true },
}));
Arc::make_mut(&mut d.sheets[0]).documents = Some(SheetComponent { source: plate_id, component: 7 });
d.properties.set(crate::metadata::Owner::Design, "author", json!("Jane Doe")).unwrap();
d.units = Units::Fixed { unit: "in".into() };
d.validate().unwrap();
d
}
/// One A4 sheet that documents nothing, no sources: the base the caps grow from.
fn bare() -> Drawing {
let a4 = drawing_sheet::Sheet::standard(PaperSize::A4, Orientation::Landscape);
Drawing::new("Bare", "en", "Sheet", a4, None, &mut IdSource::seeded(SEED)).unwrap()
}
fn file(d: &Drawing) -> Value {
serde_json::from_str(&d.to_json().unwrap()).unwrap()
}
fn read(file: &Value) -> Result<Drawing> {
Drawing::from_json(&file.to_string())
}
/// Why `file` is refused, or "read".
fn refusal(file: &Value) -> String {
read(file).map_or_else(|e| e.to_string(), |_| "read".into())
}
/// Why `d`'s file, changed by `edit`, is refused, or "read".
fn refused(d: &Drawing, edit: impl FnOnce(&mut Value)) -> String {
let mut v = file(d);
edit(&mut v);
refusal(&v)
}
/// A drawing reads back as it was saved, and save, open and save again writes the same bytes, as
/// does another run from the same seed. The file holds each field under the record's name for it,
/// ids as their 13 characters, and no counter.
#[test]
fn a_drawing_reads_back_as_saved_and_saves_the_same_bytes_again() {
let d = plate();
let saved = d.to_json().unwrap();
let reopened = Drawing::from_json(&saved).unwrap();
assert_eq!(reopened, d);
assert_eq!(reopened.to_json().unwrap(), saved);
assert_eq!(plate().to_json().unwrap(), saved, "a seeded run makes the same drawing");
let v = file(&d);
let [plate_id, bolt_id, bracket_id] = [0, 1, 2].map(|i| ids::encode(d.sources[i].id));
let [assembly_id, bolt_sheet_id] = [0, 1].map(|i| ids::encode(d.sheets[i].id));
assert_eq!(assembly_id, "1ge30wkvq38r0", "the seed's first id, as splitmix64 gives it");
assert_eq!(v["format"], DRAWING.format_string(DRAWING.current()));
assert_eq!(v.get("format_pending").is_some(), !DRAWING.pending_names().is_empty());
assert_eq!(v.get("next_id"), None);
assert_eq!((&v["name"], &v["language"]), (&json!("Plate assembly"), &json!("en-GB")));
assert_eq!(
v["sources"],
json!([{"id": plate_id, "path": "plate.sc"}, {"id": bolt_id, "path": "../parts/bolt.sc"}, {"id": bracket_id, "path": "bracket.sc"}])
);
assert_eq!(v["properties"], json!({"author": "Jane Doe"}));
assert_eq!(v["units"], json!({"fixed": {"unit": "in"}}));
assert_eq!((&v["sheets"][0]["id"], &v["sheets"][0]["dpi"]), (&json!(assembly_id), &json!(300.0)));
assert_eq!(v["sheets"][0]["sheet"], json!({"size": {"standard": "a3"}, "orientation": "landscape"}));
assert_eq!(v["sheets"][0]["documents"], json!({"source": plate_id, "component": 7}));
assert_eq!(v["sheets"][0]["excluded"], json!({"count": false, "print": false}));
assert_eq!(
v["sheets"][1],
json!({
"id": bolt_sheet_id, "name": "Bolt", "sheet": {"size": {"standard": "a4"}, "orientation": "portrait"},
"border": serde_json::to_value(own_border()).unwrap(), "dpi": 600.0,
"documents": {"source": bolt_id, "component": 0}, "excluded": {"count": false, "print": true}
})
);
}
/// A hand-written file may leave out what has a default, and reads as a new drawing has it; the
/// rest is needed.
#[test]
fn a_file_may_leave_out_what_has_a_default() {
let minimal = json!({
"format": DRAWING.format_string(1),
"name": "Bracket",
"sources": [],
"language": "de",
"sheets": [{"id": "0000000000001", "name": "Blatt 1", "sheet": {"size": {"standard": "a3"}}}]
});
let d = read(&minimal).unwrap();
assert_eq!((d.sheets[0].id, &d.units, d.properties.is_empty()), (1, &Units::FollowModel, true));
let sheet = &d.sheets[0];
assert_eq!(sheet.sheet, drawing_sheet::Sheet::standard(PaperSize::A3, Orientation::Landscape));
assert_eq!((sheet.border, sheet.dpi, sheet.documents, sheet.excluded), (None, DEFAULT_DPI, None, Excluded::default()));
// The format as this build writes it, however the file spelt it.
let mut spelt = minimal.clone();
spelt["format"] = json!("solidcraft-drawing/+1");
assert_eq!(read(&spelt).unwrap().format, DRAWING.format_string(DRAWING.current()));
for key in ["name", "sources", "language", "sheets"] {
let mut v = minimal.clone();
v.as_object_mut().unwrap().remove(key);
let why = refusal(&v);
assert!(why.starts_with("damaged drawing: ") && why.contains(&format!("missing field `{key}`")), "{why}");
}
}
/// Every cap on both sides: sheets, sources, the bytes of paths and names (two-byte characters too).
#[test]
fn every_cap_holds_on_both_sides() {
let base = file(&bare());
let with = |key: &str, value: Value| {
let mut v = base.clone();
v[key] = value;
v
};
let sheet = base["sheets"][0].clone();
let sheets = |n: u64| {
let one = |id: u64| {
let mut s = sheet.clone();
s["id"] = json!(ids::encode(id));
s
};
Value::Array((1..=n).map(one).collect())
};
assert_eq!(read(&with("sheets", sheets(1000))).unwrap().sheets.len(), 1000);
for n in [0, 1001] {
assert_eq!(refusal(&with("sheets", sheets(n))), "damaged drawing: a drawing has 1 to 1000 sheets", "{n} sheets");
}
// Sources from id 1: the sheet's id is the seed's, far from them.
let sources = |n: u64| Value::Array((1..=n).map(|id| json!({"id": ids::encode(id), "path": format!("part{id}.sc")})).collect());
assert_eq!(read(&with("sources", sources(64))).unwrap().sources.len(), 64);
assert_eq!(refusal(&with("sources", sources(65))), "damaged drawing: a drawing draws at most 64 designs");
let path = |p: &str| refusal(&with("sources", json!([{"id": ids::encode(1), "path": p}])));
for fits in ["a".repeat(4096), "é".repeat(2048), "/".into()] {
assert_eq!(path(fits.as_str()), "read", "{} bytes", fits.len());
}
let rule = "damaged drawing: source 0000000000001: a design's path is 1 to 4096 bytes, without NUL";
for broken in ["a".repeat(4097), "é".repeat(2048) + "a", String::new(), "plate\0.sc".into()] {
assert_eq!(path(broken.as_str()), rule, "{} bytes", broken.len());
}
let names = |name: &str| {
let mut sheet_named = base.clone();
sheet_named["sheets"][0]["name"] = json!(name);
(refusal(&with("name", json!(name))), refusal(&sheet_named))
};
for fits in ["x".repeat(256), "é".repeat(128), "A".into(), "Blatt 1 – Übersicht".into()] {
assert_eq!(names(fits.as_str()), ("read".to_string(), "read".to_string()), "{} bytes", fits.len());
}
let rule = "name is 1 to 256 bytes, not only spaces, without control characters";
let sheet_id = ids::encode(bare().sheets[0].id);
for broken in ["x".repeat(257), "é".repeat(128) + "a", String::new(), " ".into(), "two\nlines".into(), "bell\u{7}".into(), "nul\0".into()] {
let expected = (format!("damaged drawing: the drawing's {rule}"), format!("damaged drawing: sheet {sheet_id}: its {rule}"));
assert_eq!(names(broken.as_str()), expected, "{broken:?}");
}
}
/// The content language is a well-formed BCP 47 tag of 2 to 35 characters.
#[test]
fn the_language_is_a_bcp_47_tag_of_2_to_35_characters() {
let base = file(&bare());
let why = |tag: &str| {
let mut v = base.clone();
v["language"] = json!(tag);
refusal(&v)
};
let longest = "en-abcdefgh-abcdefgh-abcdefgh-abcde";
assert_eq!(longest.len(), 35);
for tag in ["en", "de", "ast", "en-GB", "EN-gb", "zh-Hans-CN", "sr-Latn-RS", "es-419", longest] {
assert_eq!(why(tag), "read", "{tag}");
}
let rule = "damaged drawing: the language is not a BCP 47 tag of 2 to 35 characters (such as `en` or `en-GB`)";
let too_long = format!("{longest}f");
let broken =
["e", "", too_long.as_str(), "en_GB", "en-", "-en", "en--GB", "e1", "x-private", "en-abcdefghi", "abcdefghi", "日本", "en GB", "en\n"];
for tag in broken {
assert_eq!(why(tag), rule, "{tag:?}");
}
}
/// A fixed unit is a length unit of the expression unit table, written as the table writes it.
#[test]
fn a_fixed_unit_is_a_length_unit_of_the_expression_table() {
let base = file(&bare());
let units = |units: Value| {
let mut v = base.clone();
v["units"] = units;
read(&v).map(|d| d.units)
};
for (unit, kind, _) in expr::UNITS {
assert_eq!(units(json!({"fixed": {"unit": unit}})).is_ok(), kind == expr::Kind::Length, "{unit}");
}
assert_eq!(units(json!({"fixed": {"unit": "in"}})).unwrap(), Units::Fixed { unit: "in".into() });
assert_eq!(units(json!("follow_model")).unwrap(), Units::FollowModel);
let rule = "damaged drawing: the drawing's unit is not a length unit (such as `mm` or `in`)";
for unit in ["furlong", "deg", "°", "none", "", " in", "in ", "IN"] {
assert_eq!(units(json!({"fixed": {"unit": unit}})).unwrap_err().to_string(), rule, "{unit:?}");
}
for broken in [json!("follow_design"), json!({"fixed": "in"}), json!({"fixed": {}}), json!(null)] {
assert!(units(broken.clone()).is_err(), "{broken}");
}
}
/// A sheet's border is saved as a copy of its profile, field by field, and read back as saved, so
/// a later built-in never changes it; a profile's name in its place is refused.
#[test]
fn a_border_is_saved_as_a_copy_of_its_profile() {
let v = file(&plate());
assert_eq!(v["sheets"][0]["border"], serde_json::to_value(DrawingBorderProfile::iso()).unwrap());
assert_eq!(v["sheets"][1]["border"], serde_json::to_value(own_border()).unwrap());
assert_eq!(read(&v).unwrap().sheets[1].border, Some(own_border()));
let mut edited = v.clone();
edited["sheets"][0]["border"]["margins"]["left_mm"] = json!(15.0);
let iso = DrawingBorderProfile::iso();
let wider = DrawingBorderProfile { margins: Margins { left_mm: 15.0, ..iso.margins }, ..iso };
assert_eq!(read(&edited).unwrap().sheets[0].border, Some(wider));
edited["sheets"][0]["border"] = json!("iso");
assert!(refusal(&edited).starts_with("damaged drawing: "));
edited["sheets"][0]["border"] = Value::Null;
assert_eq!(read(&edited).unwrap().sheets[0].border, None, "no drawing border");
}
/// What reading refuses: each damage the rules name, refused rather than patched, and files this
/// build can't read.
#[test]
fn damaged_files_are_refused_and_never_patched() {
let d = plate();
let plate_id = ids::encode(d.sources[0].id);
let [assembly_id, bolt_sheet_id] = [0, 1].map(|i| ids::encode(d.sheets[i].id));
// Two objects with one id, of one kind and of two kinds.
assert_eq!(refused(&d, |v| v["sources"][1]["id"] = json!(plate_id)), format!("damaged drawing: two objects have the id {plate_id}"));
assert_eq!(refused(&d, |v| v["sheets"][1]["id"] = json!(assembly_id)), format!("damaged drawing: two objects have the id {assembly_id}"));
assert_eq!(refused(&d, |v| v["sources"][2]["id"] = json!(bolt_sheet_id)), format!("damaged drawing: two objects have the id {bolt_sheet_id}"));
// An id that isn't one, where an object has it and where a reference names it; no number form,
// and no counter.
let not_an_id = "damaged drawing: an id is 13 characters of lowercase Crockford base32, not all 0";
for text in ["0000000000000", "FZZZZZZZZZZZZ", "000000000001", "0000000000001 ", "000000000000o", "g000000000000"] {
assert_eq!(refused(&d, |v| v["sources"][2]["id"] = json!(text)), not_an_id, "{text:?}");
assert_eq!(refused(&d, |v| v["sheets"][1]["documents"]["source"] = json!(text)), not_an_id, "{text:?}");
}
assert!(refused(&d, |v| v["sources"][2]["id"] = json!(5)).starts_with("damaged drawing: invalid type"));
assert!(refused(&d, |v| v["next_id"] = json!(6)).contains("unknown field `next_id`"));
let mut in_memory = d.clone();
in_memory.sources[2].id = 0;
assert_eq!(in_memory.validate().unwrap_err().to_string(), "an object has the id 0, which is never one");
// A reference to nothing, or to an object of another kind; a source a sheet documents removed.
for missing in [ids::encode(99), assembly_id.clone()] {
let expected = format!("damaged drawing: sheet {bolt_sheet_id}: it documents source {missing}, which the drawing doesn't have");
assert_eq!(refused(&d, |v| v["sheets"][1]["documents"]["source"] = json!(missing)), expected);
}
let without_plate = refused(&d, |v| {
v["sources"].as_array_mut().unwrap().remove(0);
});
assert_eq!(without_plate, format!("damaged drawing: sheet {assembly_id}: it documents source {plate_id}, which the drawing doesn't have"));
// The paper, its border and its resolution, through the sheet's own rules.
let custom = |sides: Value| refused(&d, |v| v["sheets"][0]["sheet"]["size"] = json!({"custom": {"sides_mm": sides}}));
assert_eq!(custom(json!([5000.0, 0.5])), "read");
for sides in [json!([5000.1, 100.0]), json!([0.0, 100.0]), json!([-1.0, 100.0])] {
let expected = format!("damaged drawing: sheet {assembly_id}: drawing sheet: a custom side is finite, above 0 and at most 5000 mm");
assert_eq!(custom(sides), expected);
}
let why = custom(json!([1e10, 100.0]));
assert!(why.starts_with("damaged drawing: the number ") && why.ends_with(" is out of range"), "checked before the record: {why}");
let nan = d.to_json().unwrap().replacen("600.0", "NaN", 1);
assert!(Drawing::from_json(&nan).unwrap_err().to_string().starts_with("not a SolidCraft drawing: "), "NaN isn't JSON");
assert_eq!(
refused(&d, |v| v["sheets"][1]["border"]["margins"]["top_mm"] = json!(-1.0)),
format!("damaged drawing: sheet {bolt_sheet_id}: drawing sheet: a margin is finite and 0 to 5000 mm")
);
for dpi in [25.0, 2400.0] {
assert_eq!(refused(&d, |v| v["sheets"][1]["dpi"] = json!(dpi)), "read", "{dpi}");
}
for dpi in [24.9, 2400.1, 0.0, -300.0] {
let expected = format!("damaged drawing: sheet {bolt_sheet_id}: its pictures are 25 to 2400 dpi");
assert_eq!(refused(&d, |v| v["sheets"][1]["dpi"] = json!(dpi)), expected, "{dpi}");
}
// In memory, where NaN can be, the same rules.
let mut in_memory = plate();
Arc::make_mut(&mut in_memory.sheets[1]).dpi = f64::NAN;
assert_eq!(in_memory.validate().unwrap_err().to_string(), format!("sheet {bolt_sheet_id}: its pictures are 25 to 2400 dpi"));
let sheet = Arc::make_mut(&mut in_memory.sheets[1]);
sheet.dpi = DEFAULT_DPI;
sheet.sheet.size = SheetSize::Custom { sides_mm: [f64::NAN, 100.0] };
assert!(in_memory.validate().unwrap_err().to_string().starts_with(&format!("sheet {bolt_sheet_id}: drawing sheet: a custom side")));
// An unknown field anywhere.
let unknown: [fn(&mut Value); 8] = [
|v| v["views"] = json!([]),
|v| v["sources"][0]["name"] = json!("Plate"),
|v| v["sheets"][0]["scale"] = json!(1),
|v| v["sheets"][0]["sheet"]["colour"] = json!("white"),
|v| v["sheets"][0]["border"]["style"] = json!("iso"),
|v| v["sheets"][0]["documents"]["view"] = json!(1),
|v| v["sheets"][0]["excluded"]["export"] = json!(true),
|v| v["units"]["fixed"]["precision"] = json!(2),
];
for (i, edit) in unknown.into_iter().enumerate() {
let why = refused(&d, edit);
assert!(why.starts_with("damaged drawing: ") && why.contains("unknown field"), "{i}: {why}");
}
// A newer build's file is refused as one before anything in it is read: a field this build
// doesn't know, or a number out of its range.
let (current, newer) = (DRAWING.current(), DRAWING.current() + 1);
let why = refused(&d, |v| {
v["format"] = json!(DRAWING.format_string(newer));
v["views"] = json!([]);
v["sheets"][0]["dpi"] = json!(1e10);
});
assert_eq!(
why,
format!(
"this drawing was saved by a newer SolidCraft (file format {newer}; this version reads formats up to {current}): update SolidCraft to open it"
)
);
// A list of pending changes means nothing beside a format made of none; beside the pending
// number, a change this build doesn't know is a newer build's.
let why = refused(&d, |v| v["format_pending"] = json!(["a-later-change"]));
if DRAWING.pending_names().is_empty() {
assert_eq!(why, "read");
} else {
assert!(why.contains("newer SolidCraft"), "{why}");
}
// A design is never read as a drawing, nor a drawing as a design.
let design = crate::Document::new("Plate").to_json();
let design_format = crate::format::format_string(crate::format::FORMAT);
assert_eq!(Drawing::from_json(&design).unwrap_err().to_string(), format!("not a SolidCraft drawing (format `{design_format}`)"));
let drawing_format = DRAWING.format_string(current);
assert_eq!(
crate::Document::from_json(&d.to_json().unwrap()).unwrap_err().to_string(),
format!("not a SolidCraft design (format `{drawing_format}`)")
);
// Not an object, not JSON, nested too deeply, too large.
assert_eq!(Drawing::from_json("[]").unwrap_err().to_string(), "not a SolidCraft drawing (expected a JSON object)");
assert!(Drawing::from_json("").unwrap_err().to_string().starts_with("not a SolidCraft drawing: "));
let deep: Value = serde_json::from_str(&format!("{}1{}", "[".repeat(100), "]".repeat(100))).unwrap();
assert_eq!(refused(&d, |v| v["views"] = deep), "damaged drawing: nested too deeply");
let deeper = format!("{{\"format\": \"{drawing_format}\", \"views\": {}1{}}}", "[".repeat(200), "]".repeat(200));
assert!(Drawing::from_json(&deeper).unwrap_err().to_string().starts_with("not a SolidCraft drawing: "));
let text = d.to_json().unwrap();
let at_cap = text.clone() + &" ".repeat(MAX_DRAWING_BYTES - text.len());
assert_eq!(Drawing::from_json(&at_cap).unwrap(), d);
assert_eq!(Drawing::from_json(&(at_cap + " ")).unwrap_err().to_string(), "drawing too large (at most 16 MiB)");
}
/// A run never gives an id twice: not one in use, and not a removed object's. Only another run from
/// the same seed, which tests and replays start from the same file, can give a removed id again.
#[test]
fn a_run_never_gives_an_id_twice() {
let mut id_source = IdSource::seeded(SEED);
let a4 = drawing_sheet::Sheet::standard(PaperSize::A4, Orientation::Landscape);
let mut d = Drawing::new("Ids", "en", "Sheet", a4, None, &mut id_source).unwrap();
let mut given = BTreeSet::from([d.sheets[0].id]);
for _ in 0..MAX_SOURCES {
let id = d.allocate_id(&mut id_source).unwrap();
d.sources.push(Source { id, path: "part.sc".into() });
assert!(given.insert(id), "{id:#x} given twice");
}
let removed = d.sources.pop().unwrap().id;
for _ in 0..10_000 {
let id = d.allocate_id(&mut id_source).unwrap();
assert!(id != removed && given.insert(id), "{id:#x} given twice");
}
// The same seed, from the start, over a file it made: every draw up to the removed id is in use.
let reopened = Drawing::from_json(&d.to_json().unwrap()).unwrap();
let again = reopened.allocate_id(&mut IdSource::seeded(SEED)).unwrap();
assert!(!reopened.ids().any(|id| id == again));
assert_eq!(again, removed);
}
/// Properties follow the design metadata's rules: other tools' data and a well-known key of another
/// kind are kept as they are, never read as numbers, while the same number elsewhere is refused.
#[test]
fn properties_are_kept_as_they_are() {
let mut v = file(&plate());
v["properties"]["com.example.pdm"] = json!({"huge": 1e300, "ids": [1, 2, 3]});
v["properties"]["revision"] = json!(3);
let d = read(&v).unwrap();
assert_eq!(d.properties.get("com.example.pdm"), Some(&json!({"huge": 1e300, "ids": [1, 2, 3]})));
assert_eq!((d.properties.revision(), d.properties.get("revision")), (None, Some(&json!(3))));
assert_eq!(read(&file(&d)).unwrap(), d);
v["sheets"][0]["dpi"] = json!(1e300);
let why = refusal(&v);
assert!(why.starts_with("damaged drawing: the number ") && why.ends_with(" is out of range"), "{why}");
}
/// A drawing whose JSON would be over the read limit isn't saved. Other tools' properties are kept
/// as they came, and indenting them can grow a file read in under the limit past it, so the save
/// refuses rather than write a file that won't open: every drawing saved opens again.
#[test]
fn a_drawing_too_large_to_reopen_is_not_saved() {
let file = |zeros: usize| {
let items = vec!["0"; zeros].join(",");
let sheet = r#"{"id":"0000000000001","name":"S","sheet":{"size":{"standard":"a4"}}}"#;
let format = DRAWING.format_string(1);
format!(
r#"{{"format":"{format}","name":"A","sources":[],"language":"en","sheets":[{sheet}],"properties":{{"com.example":{{"items":[{items}]}}}}}}"#
)
};
// The case found in review (#3891): 2,000,000 zeros read in at about 4 MB and indent past 16 MiB.
let big = Drawing::from_json(&file(2_000_000)).unwrap();
assert_eq!(big.to_json().unwrap_err().to_string(), "drawing too large to save (at most 16 MiB)");
let small = Drawing::from_json(&file(100_000)).unwrap();
assert_eq!(Drawing::from_json(&small.to_json().unwrap()).unwrap(), small);
}
/// A new drawing has one sheet, its id the source's first, follows its designs' units and renders
/// pictures at 300 dpi; a name, language or border that breaks the rules is refused.
#[test]
fn a_new_drawing_has_one_sheet_and_keeps_the_rules() {
let d = bare();
let first = IdSource::seeded(SEED).next(&BTreeSet::new()).unwrap();
assert_eq!((d.sheets.len(), d.sheets[0].id, d.sheets[0].dpi, &d.units), (1, first, DEFAULT_DPI, &Units::FollowModel));
assert_eq!((d.format, d.format_pending), (DRAWING.format_string(DRAWING.current()), DRAWING.pending_names()));
let a4 = drawing_sheet::Sheet::standard(PaperSize::A4, Orientation::Landscape);
let thin = DrawingBorderProfile { drawing_border_line_mm: 0.0, ..DrawingBorderProfile::iso() };
let broken = [("", "en", "Sheet", None), ("Bare", "en_GB", "Sheet", None), ("Bare", "en", "\n", None), ("Bare", "en", "Sheet", Some(thin))];
for (name, language, sheet, border) in broken {
let made = Drawing::new(name, language, sheet, a4, border, &mut IdSource::seeded(SEED));
assert!(made.is_err(), "{name:?} {language:?} {sheet:?} {border:?}");
}
}
/// Hostile input never panics: a valid file's text cut, overwritten and given lies, and its JSON
/// values replaced, repeated and dropped. Each read gives an error, or a drawing that keeps the
/// rules and reads back as it saves.
#[test]
fn mutated_files_give_an_error_or_a_valid_drawing_never_a_panic() {
let good = plate().to_json().unwrap();
let tree: Value = serde_json::from_str(&good).unwrap();
let nodes = count(&tree) as u64;
let lies = [
json!(null),
json!(0),
json!(-1),
json!(1),
json!(1e10),
json!(u64::MAX),
json!(""),
json!("x".repeat(300)),
json!("0000000000000"),
json!("0000000000001"),
json!("fzzzzzzzzzzzz"),
json!("FZZZZZZZZZZZZ"),
json!([]),
json!({}),
json!(true),
json!("follow_model"),
json!({"fixed": {"unit": "deg"}}),
];
let words = ["NaN", "1e400", "-0", "18446744073709551616", "\"", "{", "]", ",", "null", "\u{0}", "é", "o", "I"];
let mut seed: u64 = 0x9e37_79b9_7f4a_7c15;
let mut rnd = move || {
seed ^= seed << 13;
seed ^= seed >> 7;
seed ^= seed << 17;
seed
};
let mut read_back = 0;
for i in 0..10_000 {
let text = if i % 2 == 0 {
let mut v = tree.clone();
let lie = &lies[(rnd() % lies.len() as u64) as usize];
mutate(&mut v, &mut ((rnd() % nodes) as usize), lie, rnd() % 3);
v.to_string()
} else {
let mut s = good.clone().into_bytes();
for _ in 0..1 + rnd() % 3 {
// A run of up to 15 bytes taken out, overwritten by one byte or replaced by a lie.
let at = (rnd() % (s.len() as u64 + 1)) as usize;
let cut = ((rnd() % 16) as usize).min(s.len() - at);
let byte = [(rnd() >> 56) as u8];
let put: &[u8] = match rnd() % 3 {
0 => &[],
1 => &byte,
_ => words[(rnd() % words.len() as u64) as usize].as_bytes(),
};
let next = [&s[..at], put, &s[at + cut..]].concat();
s = next;
if rnd() % 8 == 0 {
s.truncate(at);
}
}
String::from_utf8_lossy(&s).into_owned()
};
if let Ok(d) = Drawing::from_json(&text) {
assert!(d.validate().is_ok() && d.ids().all(|id| id != 0), "{text}");
assert_eq!(Drawing::from_json(&d.to_json().unwrap()).unwrap(), d, "{text}");
read_back += 1;
}
}
assert!(read_back > 50, "only {read_back} mutated files read: the mutations hardly reach the record's rules");
}
/// The number of values in `v`, itself included.
fn count(v: &Value) -> usize {
1 + match v {
Value::Array(a) => a.iter().map(count).sum::<usize>(),
Value::Object(o) => o.values().map(count).sum(),
_ => 0,
}
}
/// Change the `pick`th value of `v`, depth first: `how` 1 repeats a list's first element (two
/// objects with one id), 2 drops an object's first field, and otherwise `lie` takes its place.
fn mutate(v: &mut Value, pick: &mut usize, lie: &Value, how: u64) -> bool {
if *pick == 0 {
match (v, how) {
(Value::Array(a), 1) if !a.is_empty() => {
let first = a[0].clone();
a.push(first);
}
(Value::Object(o), 2) if !o.is_empty() => {
let key = o.keys().next().cloned().unwrap_or_default();
o.remove(&key);
}
(v, _) => *v = lie.clone(),
}
return true;
}
*pick -= 1;
match v {
Value::Array(a) => a.iter_mut().any(|x| mutate(x, pick, lie, how)),
Value::Object(o) => o.values_mut().any(|x| mutate(x, pick, lie, how)),
_ => false,
}
}
+1 -1
View File
@@ -485,7 +485,7 @@ fn mirror_y(r: &Region2) -> Region2 {
.iter()
.map(|s| match *s {
Seg2::Arc { center, radius, start, sweep } => Seg2::Arc { center: f(center), radius, start: -start, sweep: -sweep },
other => sheet::map_controls(&other, f),
other => other.map_controls(f),
})
.collect();
Loop2 { segs }.ccw()
+5
View File
@@ -183,6 +183,11 @@ impl Document {
return Err(DocError::Invalid("this face has no supported construction certificate; choose a fixed plane instead".into()));
}
let indices = self.configuration_face_indices(body, &target)?;
// A copy a pattern or mirror made on the same body carries its seed's certificate,
// which finds the seed's face: the copy is attached by its own history name below.
if !indices.contains(&index) {
return Err(DocError::Invalid("this face has no supported construction certificate; choose a fixed plane instead".into()));
}
self.coplanar_pieces(body, &indices, |_| true)?;
Ok(target)
});
+350 -77
View File
@@ -232,6 +232,11 @@
//! this build writes the next number (which no release reads), with the names of these changes
//! in `format_pending`, so a later build applies just the steps a file is missing. At release
//! time `scripts/fold-format-pending.sh` moves them into the next `v<N>/`.
//!
//! Drawings (`solidcraft-drawing/N`, #3890) are versioned by the same code ([`Family`]) from their
//! own first format, 1 (the record in [`crate::drawing`]): each later change is one file in
//! `src/drawing/format/`, in `v<N>/` or `pending/` as above, and the release script folds that
//! folder too.
use serde_json::Value;
@@ -244,11 +249,11 @@ pub const FORMAT: u32 = FORMATS.current();
/// of [`Part`]s (`src/format/`, listed by `build.rs`).
const HAND_WRITTEN: u32 = 22;
/// One change to the file format: a file in `src/format/v<N>/` or `src/format/pending/`.
/// One change to a family's file format: a file in its `v<N>/` or `pending/` folder.
pub(crate) struct Part {
/// The file's name, which a file written while the change was pending lists.
pub name: &'static str,
/// How a design from before the change is rewritten as it opens, if it is.
/// How a file from before the change is rewritten as it opens, if it is.
pub step: Option<JsonStep>,
}
@@ -257,13 +262,102 @@ include!(concat!(env!("OUT_DIR"), "/format_parts.rs"));
/// Every format this build knows and how to upgrade a design through them.
const FORMATS: Formats<'static> = Formats { hand: &JSON_STEPS, folded: FOLDED, pending: PENDING };
/// The names of the pending changes this build writes into a design (`format_pending`).
pub fn pending_names() -> Vec<String> {
FORMATS.pending.iter().map(|p| p.name.to_string()).collect()
/// A kind of file whose format is versioned here: designs, and drawings (#3890). Each family has
/// its own format tag, its own numbers and its own folder of change files (`build.rs` lists them);
/// reading a file's format, refusing a file a newer build saved and the upgrade are the same code
/// for every family.
pub struct Family<'a> {
/// What a file of the family is called in messages.
noun: &'static str,
/// The tag before the number in a file's `format`.
prefix: &'static str,
/// The tag files saved before the rename carry: read, never written (docs/compatibility.md).
legacy_prefix: Option<&'static str>,
/// The format of a file that names none: designs saved before format strings are format 1; a
/// drawing always names its own.
untagged: Option<u32>,
formats: Formats<'a>,
}
/// The upgrade path: the hand-written steps up to [`HAND_WRITTEN`], the folded formats after it
/// (each a list of changes) and the pending changes, which make the next format.
/// Designs (`solidcraft/N`): the upgrade steps written out up to format 22, then the change files
/// in `src/format/`.
pub const DESIGN: Family<'static> =
Family { noun: "design", prefix: "solidcraft/", legacy_prefix: Some(LEGACY_FORMAT_PREFIX), untagged: Some(1), formats: FORMATS };
/// Drawings (`solidcraft-drawing/N`, #3890): format 1 is the first drawing record, and every later
/// change is a file in `src/drawing/format/`.
pub const DRAWING: Family<'static> = Family {
noun: "drawing",
prefix: "solidcraft-drawing/",
legacy_prefix: None,
untagged: None,
formats: Formats { hand: &[], folded: DRAWING_FOLDED, pending: DRAWING_PENDING },
};
impl Family<'_> {
/// The format this build writes: the last folded one, or the next while changes are pending.
pub const fn current(&self) -> u32 {
self.formats.current()
}
/// The names of the pending changes this build writes into a file (`format_pending`).
pub fn pending_names(&self) -> Vec<String> {
self.formats.pending.iter().map(|p| p.name.to_string()).collect()
}
/// The format tag of format `n`.
pub fn format_string(&self, n: u32) -> String {
format!("{}{n}", self.prefix)
}
/// The version in one of this family's format tags; `None` for any other tag, another
/// family's included.
pub fn version_of(&self, s: &str) -> Option<u32> {
s.strip_prefix(self.prefix).or_else(|| self.legacy_prefix.and_then(|p| s.strip_prefix(p)))?.parse().ok()
}
/// Read a file's format and take its `format_pending` out of its JSON, before anything else
/// in it is read: a file that isn't this family's, or that a newer build saved, is refused
/// here, so nothing a newer build saved is judged by this build's rules.
pub fn take_version(&self, v: &mut Value) -> Result<(u32, Option<Vec<String>>)> {
let noun = self.noun;
let not_ours = |what: String| DocError::Invalid(format!("not a SolidCraft {noun} ({what})"));
let Some(obj) = v.as_object() else { return Err(not_ours("expected a JSON object".into())) };
let version = match obj.get("format") {
None => self.untagged.ok_or_else(|| not_ours("no format".into()))?,
Some(Value::String(f)) => self.version_of(f).ok_or_else(|| not_ours(format!("format `{f}`")))?,
Some(_) => return Err(not_ours("format is not a string".into())),
};
let applied = take_names(v, "format_pending", noun)?;
self.formats.check(noun, version, applied.as_deref())?;
Ok((version, applied))
}
/// Bring a file of format `version` up to this build's; `applied` is its `format_pending`
/// (both from [`Family::take_version`]).
pub fn upgrade(&self, v: &mut Value, version: u32, applied: Option<&[String]>) -> Result<()> {
self.formats.upgrade(self.noun, v, version, applied)
}
/// Every number a file of the family holds is in range ([`check_numbers`]), but for its
/// top-level `kept` field: other tools' data (a design's `metadata`, a drawing's `properties`),
/// kept as it is and never read as a number (#1015); parsing already bounds its nesting.
pub(crate) fn check_numbers(&self, v: &Value, kept: &str) -> Result<()> {
match v {
Value::Object(m) => m.iter().filter(|(k, _)| k.as_str() != kept).try_for_each(|(_, x)| check_numbers(x, self.noun, 1)),
v => check_numbers(v, self.noun, 0),
}
}
}
/// The names of the pending changes this build writes into a design (`format_pending`).
pub fn pending_names() -> Vec<String> {
DESIGN.pending_names()
}
/// A family's upgrade path: the steps written out by hand (designs' up to [`HAND_WRITTEN`]), the
/// folded formats after them (each a list of changes) and the pending changes, which make the
/// next format.
struct Formats<'a> {
hand: &'a [JsonStep],
folded: &'a [(u32, &'a [Part])],
@@ -300,26 +394,41 @@ impl Formats<'_> {
}
}
/// Bring a design of format `version` up to [`Formats::current`]. `applied` is the file's
/// `format_pending`: the changes of its format it already has, when it was written while they
/// were pending; the others' steps run first. Recognize changes across the entire history:
/// a branch's pending change may have landed at a later number. Unknown changes are refused
/// even after folding, and already-applied changes never run again at their later number.
fn upgrade(&self, v: &mut Value, version: u32, applied: Option<&[String]>) -> Result<()> {
if version == 0 || version > self.current() {
return Err(DocError::Invalid(format!("not a SolidCraft design (format {version})")));
/// Refuse a `noun` of format `version` that this build can't read: format 0, a newer number,
/// or a change `applied` (its `format_pending`) names that this build doesn't have anywhere in
/// its history, which only a newer build's file can. Changes are recognized across the entire
/// history: a branch's pending change may have landed at a later number. A list beside a format
/// that isn't made of changes means nothing (a tool or a test set an older number on a newer
/// file).
fn check(&self, noun: &str, version: u32, applied: Option<&[String]>) -> Result<()> {
let newer = |what: String| DocError::Invalid(format!("this {noun} was saved by a newer SolidCraft ({what}): update SolidCraft to open it"));
let current = self.current();
if version == 0 {
return Err(DocError::Invalid(format!("not a SolidCraft {noun} (format 0)")));
}
// A list beside a format that isn't made of changes means nothing (a tool or a test set
// an older number on a newer file): it is ignored, like any field an upgrade drops.
if version > current {
return Err(newer(format!("file format {version}; this version reads formats up to {current}")));
}
let applied = applied.filter(|_| self.parts(version).is_some()).unwrap_or_default();
match applied.iter().find(|name| !self.knows_part_name(self.canonical_applied_name(version, name))) {
Some(unknown) => Err(newer(format!("file format {version} with `{unknown}`, which this version doesn't know"))),
None => Ok(()),
}
}
/// Bring a `noun` of format `version` up to [`Formats::current`]. `applied` is the file's
/// `format_pending`: the changes of its format it already has, when it was written while they
/// were pending; the others' steps run first. A file [`Formats::check`] refuses is refused,
/// whoever calls, before anything is changed; already-applied changes never run again at
/// their later number.
fn upgrade(&self, noun: &str, v: &mut Value, version: u32, applied: Option<&[String]>) -> Result<()> {
self.check(noun, version, applied)?;
// A list beside a format that isn't made of changes is ignored, like any field an upgrade
// drops.
let applied = applied.filter(|_| self.parts(version).is_some());
let already_applied =
|part: &Part| applied.is_some_and(|names| names.iter().any(|name| self.canonical_applied_name(version, name) == part.name));
if let Some(applied) = applied {
if let Some(unknown) = applied.iter().find(|name| !self.knows_part_name(self.canonical_applied_name(version, name))) {
return Err(DocError::Invalid(format!(
"this design was saved by a newer SolidCraft (file format {version} with `{unknown}`, which this version doesn't know): update SolidCraft to open it"
)));
}
if applied.is_some() {
for part in self.parts(version).unwrap_or_default().iter().filter(|part| !already_applied(part)) {
part.step.map_or(Ok(()), |step| step(v))?;
}
@@ -338,25 +447,26 @@ impl Formats<'_> {
}
}
/// Take a file's `format_pending` (the pending changes it has) out of its JSON.
fn take_pending(v: &mut Value) -> Result<Option<Vec<String>>> {
let Some(list) = v.as_object_mut().and_then(|o| o.remove("format_pending")) else { return Ok(None) };
let invalid = || DocError::Invalid("damaged design: `format_pending` is not a short list of names".into());
/// Take a short list of names out of a file's JSON: its `format_pending` (the pending changes it
/// has).
fn take_names(v: &mut Value, key: &str, noun: &str) -> Result<Option<Vec<String>>> {
let Some(list) = v.as_object_mut().and_then(|o| o.remove(key)) else { return Ok(None) };
let invalid = || DocError::Invalid(format!("damaged {noun}: `{key}` is not a short list of names"));
let list = list.as_array().filter(|l| l.len() <= 1000).ok_or_else(invalid)?;
list.iter().map(|n| n.as_str().filter(|n| n.len() <= 128).map(str::to_string).ok_or_else(invalid)).collect::<Result<_>>().map(Some)
}
pub fn format_string(n: u32) -> String {
format!("solidcraft/{n}")
DESIGN.format_string(n)
}
/// The format tag of designs saved before the rename. Compatibility shim (docs/compatibility.md):
/// read, never written.
pub const LEGACY_FORMAT_PREFIX: &str = "solvecraft/";
/// The version in a format string (`solidcraft/N`, or the legacy `solvecraft/N`).
/// The version in a design's format string (`solidcraft/N`, or the legacy `solvecraft/N`).
pub fn version_of(s: &str) -> Option<u32> {
s.strip_prefix("solidcraft/").or_else(|| s.strip_prefix(LEGACY_FORMAT_PREFIX))?.parse().ok()
DESIGN.version_of(s)
}
/// JSON-level upgrades up to [`HAND_WRITTEN`]: entry `i` turns format `i + 1` into `i + 2`.
@@ -566,23 +676,7 @@ fn v2_to_v3(v: &mut Value) -> Result<()> {
/// Read a design file's JSON, upgrading older formats.
pub fn read(s: &str) -> Result<Document> {
let mut v: Value = serde_json::from_str(s).map_err(|e| DocError::Invalid(format!("not a SolidCraft design: {e}")))?;
let Some(obj) = v.as_object() else {
return Err(DocError::Invalid("not a SolidCraft design (expected a JSON object)".into()));
};
let version = match obj.get("format") {
None => 1,
Some(Value::String(f)) => version_of(f).ok_or_else(|| DocError::Invalid(format!("not a SolidCraft design (format `{f}`)")))?,
Some(_) => return Err(DocError::Invalid("not a SolidCraft design (format is not a string)".into())),
};
let applied = take_pending(&mut v)?;
if version == 0 {
return Err(DocError::Invalid("not a SolidCraft design (format 0)".into()));
}
if version > FORMAT {
return Err(DocError::Invalid(format!(
"this design was saved by a newer SolidCraft (file format {version}; this version reads formats up to {FORMAT}): update SolidCraft to open it"
)));
}
let (version, applied) = DESIGN.take_version(&mut v)?;
check_design_numbers(&v)?;
crate::config::validate_rules_json(&v)?;
crate::config::validate_styles_json(&v)?;
@@ -594,7 +688,7 @@ pub fn read(s: &str) -> Result<Document> {
crate::format_offsets::validate_raw(&v)?;
let legacy_wires = validate_wires(&v, version)?;
validate_body_transfers(&v)?;
FORMATS.upgrade(&mut v, version, applied.as_deref())?;
DESIGN.upgrade(&mut v, version, applied.as_deref())?;
let mut d: Document = serde_json::from_value(v).map_err(|e| DocError::Invalid(format!("design file: {e}")))?;
check_typed_numbers(&d)?;
let mut legacy_by_feature = std::collections::BTreeMap::<usize, Vec<usize>>::new();
@@ -1060,22 +1154,22 @@ const MAX_REAL: f64 = 1e9;
/// already bounds its nesting. Engineering SI constants have their own bounded admission
/// (e.g. E in Pa): only the exact root user-material card field bypasses the coordinate bound.
fn check_design_numbers(v: &Value) -> Result<()> {
let Some(root) = v.as_object() else { return check_numbers(v, 0) };
let Some(root) = v.as_object() else { return check_numbers(v, "design", 0) };
for (key, value) in root {
if key == "metadata" {
continue;
}
if key != "user_materials" {
check_numbers(value, 1)?;
check_numbers(value, "design", 1)?;
continue;
}
let Some(materials) = value.as_array() else { return check_numbers(value, 1) };
let Some(materials) = value.as_array() else { return check_numbers(value, "design", 1) };
if materials.len() > crate::MAX_USER_MATERIALS {
return Err(DocError::Invalid("document exceeds 1000 user materials".into()));
}
for material in materials {
let Some(fields) = material.as_object() else {
check_numbers(material, 2)?;
check_numbers(material, "design", 2)?;
continue;
};
for (field, data) in fields {
@@ -1084,7 +1178,7 @@ fn check_design_numbers(v: &Value) -> Result<()> {
if field == "physical_card" && !data.is_null() {
crate::physical_material::validate_card(data)?;
} else {
check_numbers(data, 3)?;
check_numbers(data, "design", 3)?;
}
}
}
@@ -1102,21 +1196,22 @@ fn check_typed_numbers(d: &Document) -> Result<()> {
check_design_numbers(&typed)
}
/// Every non-integer number outside separately validated engineering cards is finite and within ±`MAX_REAL` (a damaged or hostile
/// file is refused instead of overflowing the geometry later).
fn check_numbers(v: &Value, depth: usize) -> Result<()> {
/// Every non-integer number in a `noun`'s file, outside separately validated engineering cards,
/// is finite and within ±`MAX_REAL` (a damaged or hostile file is refused instead of overflowing
/// the geometry later).
fn check_numbers(v: &Value, noun: &str, depth: usize) -> Result<()> {
if depth > 64 {
return Err(DocError::Invalid("damaged design: nested too deeply".into()));
return Err(DocError::Invalid(format!("damaged {noun}: nested too deeply")));
}
match v {
Value::Number(n) if !(n.is_u64() || n.is_i64()) => {
let x = n.as_f64().unwrap_or(f64::NAN);
if !(x.is_finite() && x.abs() <= MAX_REAL) {
return Err(DocError::Invalid(format!("damaged design: the number {n} is out of range")));
return Err(DocError::Invalid(format!("damaged {noun}: the number {n} is out of range")));
}
}
Value::Array(a) => a.iter().try_for_each(|x| check_numbers(x, depth + 1))?,
Value::Object(m) => m.values().try_for_each(|x| check_numbers(x, depth + 1))?,
Value::Array(a) => a.iter().try_for_each(|x| check_numbers(x, noun, depth + 1))?,
Value::Object(m) => m.values().try_for_each(|x| check_numbers(x, noun, depth + 1))?,
_ => {}
}
Ok(())
@@ -1224,25 +1319,25 @@ mod tests {
assert_eq!(formats.current(), next);
for version in [1, HAND_WRITTEN, next - 1] {
let mut v = serde_json::json!({"features": [], "assembly": {"joints": [{"flip": false}]}});
formats.upgrade(&mut v, version, None).unwrap();
formats.upgrade("design", &mut v, version, None).unwrap();
assert_eq!(trace_of(&v), ["a", "b"], "from format {version}");
// The hand-written steps ran too: format 3's joints were flipped on the way up.
assert_eq!(v["assembly"]["joints"][0]["flip"], Value::Bool(version < 4), "from format {version}");
}
// A design of the pending number written before `b-second` existed gets just that step.
let mut v = serde_json::json!({});
formats.upgrade(&mut v, next, Some(&["a-first".to_string()])).unwrap();
formats.upgrade("design", &mut v, next, Some(&["a-first".to_string()])).unwrap();
assert_eq!(trace_of(&v), ["b"]);
// One that has both, or that this build wrote, needs nothing.
let mut v = serde_json::json!({});
formats.upgrade(&mut v, next, Some(&["a-first".into(), "b-second".into()])).unwrap();
formats.upgrade("design", &mut v, next, Some(&["a-first".into(), "b-second".into()])).unwrap();
assert_eq!(trace_of(&v), Vec::<&str>::new());
// A change this build doesn't know is a newer build's: refused, not guessed at.
let err = formats.upgrade(&mut serde_json::json!({}), next, Some(&["c-later".into()])).unwrap_err();
let err = formats.upgrade("design", &mut serde_json::json!({}), next, Some(&["c-later".into()])).unwrap_err();
assert!(err.to_string().contains("newer SolidCraft"), "{err}");
// A list on a format that isn't made of changes means nothing.
let mut v = serde_json::json!({});
formats.upgrade(&mut v, HAND_WRITTEN, Some(&["a-first".into()])).unwrap();
formats.upgrade("design", &mut v, HAND_WRITTEN, Some(&["a-first".into()])).unwrap();
assert_eq!(trace_of(&v), ["a", "b"]);
}
@@ -1257,13 +1352,13 @@ mod tests {
let formats = Formats { hand: &JSON_STEPS, folded: &folded, pending: &[] };
assert_eq!(formats.current(), next);
let mut old = serde_json::json!({});
formats.upgrade(&mut old, HAND_WRITTEN, None).unwrap();
formats.upgrade("design", &mut old, HAND_WRITTEN, None).unwrap();
assert_eq!(trace_of(&old), ["a", "b"]);
let mut nightly = serde_json::json!({});
formats.upgrade(&mut nightly, next, Some(&["a-first".into()])).unwrap();
formats.upgrade("design", &mut nightly, next, Some(&["a-first".into()])).unwrap();
assert_eq!(trace_of(&nightly), ["b"]);
let mut released = serde_json::json!({});
formats.upgrade(&mut released, next, None).unwrap();
formats.upgrade("design", &mut released, next, None).unwrap();
assert_eq!(trace_of(&released), Vec::<&str>::new());
}
@@ -1276,7 +1371,7 @@ mod tests {
let folded = Formats { hand: &hand, folded: &[(29, &first), (30, &cards)], pending: &[] };
for formats in [pending, folded] {
let mut file = serde_json::json!({"trace": ["b"]});
formats.upgrade(&mut file, 29, Some(&["physical-material-cards".into()])).unwrap();
formats.upgrade("design", &mut file, 29, Some(&["physical-material-cards".into()])).unwrap();
assert_eq!(trace_of(&file), ["b", "a"], "never replay existing card semantics");
}
}
@@ -1288,7 +1383,7 @@ mod tests {
let formats = Formats { hand: &hand, folded: &[(29, &first)], pending: &[] };
let mut file = serde_json::json!({"trace": [], "sentinel": 7});
let original = file.clone();
let error = formats.upgrade(&mut file, 29, Some(&["physical-material-cards".into()])).unwrap_err();
let error = formats.upgrade("design", &mut file, 29, Some(&["physical-material-cards".into()])).unwrap_err();
assert!(error.to_string().contains("physical-material-cards"), "{error}");
assert_eq!(file, original);
}
@@ -1303,7 +1398,7 @@ mod tests {
for version in [28, 30] {
let mut file = serde_json::json!({"trace": []});
let original = file.clone();
let error = formats.upgrade(&mut file, version, Some(&["physical-material-cards".into()])).unwrap_err();
let error = formats.upgrade("design", &mut file, version, Some(&["physical-material-cards".into()])).unwrap_err();
assert!(error.to_string().contains("physical-material-cards"), "{error}");
assert_eq!(file, original);
}
@@ -1320,7 +1415,7 @@ mod tests {
{
let mut file = serde_json::json!({"trace": ["b"]});
let original = file.clone();
let error = formats.upgrade(&mut file, 29, Some(&names)).unwrap_err();
let error = formats.upgrade("design", &mut file, 29, Some(&names)).unwrap_err();
assert!(error.to_string().contains("unknown-card-codec"), "{error}");
assert_eq!(file, original);
}
@@ -1337,7 +1432,7 @@ mod tests {
vec!["material-engineering-cards".into(), "physical-material-cards".into()],
] {
let mut file = serde_json::json!({"trace": ["b"]});
formats.upgrade(&mut file, 29, Some(&names)).unwrap();
formats.upgrade("design", &mut file, 29, Some(&names)).unwrap();
assert_eq!(trace_of(&file), ["b", "a"]);
}
}
@@ -1350,7 +1445,7 @@ mod tests {
let formats = Formats { hand: &hand, folded: &[(29, &first)], pending: &cards };
let mut file = serde_json::json!({"trace": ["a"], "metadata": {"format_pending": ["physical-material-cards"]}});
let metadata = file["metadata"].clone();
formats.upgrade(&mut file, 29, None).unwrap();
formats.upgrade("design", &mut file, 29, None).unwrap();
assert_eq!(trace_of(&file), ["a", "b"]);
assert_eq!(file["metadata"], metadata);
}
@@ -1365,7 +1460,7 @@ mod tests {
let formats = Formats { hand: &[], folded: &[(2, &parts)], pending };
let mut file = serde_json::json!({"trace": []});
let original = file.clone();
let err = formats.upgrade(&mut file, 2, Some(&["experimental-card".into()])).unwrap_err();
let err = formats.upgrade("design", &mut file, 2, Some(&["experimental-card".into()])).unwrap_err();
assert!(err.to_string().contains("experimental-card") && err.to_string().contains("update SolidCraft"), "{err}");
assert_eq!(file, original, "refuse before applying even a known migration");
}
@@ -1381,14 +1476,192 @@ mod tests {
let folded = Formats { hand: &[], folded: &[(2, &first), (3, &later)], pending: &[] };
for formats in [pending, folded] {
let mut experimental = serde_json::json!({"trace": ["b"]});
formats.upgrade(&mut experimental, 2, Some(&["b-second".into()])).unwrap();
formats.upgrade("design", &mut experimental, 2, Some(&["b-second".into()])).unwrap();
assert_eq!(trace_of(&experimental), ["b", "a"]);
let mut released = serde_json::json!({"trace": ["a"]});
formats.upgrade(&mut released, 2, None).unwrap();
formats.upgrade("design", &mut released, 2, None).unwrap();
assert_eq!(trace_of(&released), ["a", "b"], "ordinary released files still get later migrations");
}
}
/// A design naming a pending change this build doesn't have is a newer build's, refused as
/// such before anything else in it is checked (as a newer number is), so a newer build's
/// fields never read as damage.
#[test]
fn a_newer_builds_pending_change_is_refused_before_the_design_is_checked() {
let mut file: Value = serde_json::from_str(&Document::new("A").to_json()).unwrap();
file["format_pending"] = serde_json::json!(["not-a-change-anyone-made"]);
file["features"] = serde_json::json!([{"type": "emboss", "face": {"body": "Body", "at": [0, 0, 0], "a_newer_key": true}}]);
let error = read(&file.to_string()).unwrap_err().to_string();
if PENDING.is_empty() {
assert!(error.contains("emboss face"), "a list beside a folded format means nothing: {error}");
} else {
assert_eq!(
error,
format!(
"this design was saved by a newer SolidCraft (file format {FORMAT} with `not-a-change-anyone-made`, which this version doesn't know): update SolidCraft to open it"
)
);
}
}
/// Drawings follow the same rules from their own first format: folded formats follow on from 1
/// (`v2/`, `v3/`, …), the next number is written while changes are pending, and the build lists
/// every change file in the drawing's folder, in file-name order.
#[test]
fn drawing_formats_follow_on_from_one_and_every_change_file_is_listed() {
for (i, (version, parts)) in DRAWING_FOLDED.iter().enumerate() {
assert_eq!(*version, 2 + i as u32);
assert!(!parts.is_empty(), "drawing format {version} has no changes");
}
assert_eq!(DRAWING.current(), 1 + DRAWING_FOLDED.len() as u32 + u32::from(!DRAWING_PENDING.is_empty()));
let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src/drawing/format");
let names = |dir: &str| -> Vec<String> {
let mut names: Vec<String> = std::fs::read_dir(root.join(dir))
.map(|d| d.filter_map(|e| e.ok()?.file_name().to_str()?.strip_suffix(".rs").map(str::to_string)).collect())
.unwrap_or_default();
names.sort();
names
};
assert_eq!(names("pending"), DRAWING.pending_names());
for (version, parts) in DRAWING_FOLDED {
assert_eq!(names(&format!("v{version}")), parts.iter().map(|p| p.name).collect::<Vec<_>>());
}
}
/// A design's format tag never reads as a drawing's, nor a drawing's as a design's, at any
/// number: no family's tag starts another's, the legacy tag is a design's only, and each family
/// refuses the other's files by name.
#[test]
fn a_design_never_reads_as_a_drawing_or_the_other_way_round() {
let families = [&DESIGN, &DRAWING];
for a in families {
assert!(a.prefix.len() > 1 && a.prefix.ends_with('/'), "{}", a.prefix);
for b in families.into_iter().filter(|b| b.prefix != a.prefix) {
assert!(!a.prefix.starts_with(b.prefix), "{} starts {}", b.prefix, a.prefix);
}
}
for n in [0, 1, FORMAT, FORMAT + 1, DRAWING.current(), DRAWING.current() + 1, u32::MAX] {
assert_eq!(DESIGN.version_of(&DESIGN.format_string(n)), Some(n));
assert_eq!(DRAWING.version_of(&DRAWING.format_string(n)), Some(n));
assert_eq!(DRAWING.version_of(&DESIGN.format_string(n)), None, "{n}");
assert_eq!(DESIGN.version_of(&DRAWING.format_string(n)), None, "{n}");
assert_eq!(DRAWING.version_of(&format!("{LEGACY_FORMAT_PREFIX}{n}")), None, "{n}: the legacy tag is a design's");
}
for tag in [
"",
"solidcraft-drawing/",
"solidcraft-drawing",
"solidcraft-drawing/x",
"solidcraft-drawing/-1",
"solidcraft-drawing/4294967296",
"Solidcraft-drawing/1",
"solidcraft-drawing/1 ",
"solidcraft-drawings/1",
"solidcraft/drawing/1",
] {
assert_eq!(DRAWING.version_of(tag), None, "{tag:?}");
}
// The number reads as Rust reads a `u32`, a leading `+` included, as in a design's tag.
assert_eq!(DRAWING.version_of("solidcraft-drawing/+1"), Some(1));
let error = DRAWING.take_version(&mut serde_json::json!({"format": format_string(FORMAT)})).unwrap_err().to_string();
assert_eq!(error, format!("not a SolidCraft drawing (format `solidcraft/{FORMAT}`)"));
let error = read(&serde_json::json!({"format": DRAWING.format_string(1)}).to_string()).unwrap_err().to_string();
assert_eq!(error, "not a SolidCraft design (format `solidcraft-drawing/1`)");
}
/// Every refusal names its family: a design's read exactly as they did before drawings had one
/// (the troubleshooting guide quotes them), a drawing's say "drawing". A file that names no
/// format is a design from before format strings, never a drawing.
#[test]
fn refusals_name_the_family_and_a_designs_read_as_before() {
use serde_json::json;
fn refusal(family: &Family<'_>, mut file: Value) -> String {
family.take_version(&mut file).map_or_else(|e| e.to_string(), |opened| format!("read as {opened:?}"))
}
fn tagged(family: &Family<'_>, n: u32) -> Value {
serde_json::json!({"format": family.format_string(n)})
}
fn newer(noun: &str, n: u32, current: u32) -> String {
format!(
"this {noun} was saved by a newer SolidCraft (file format {n}; this version reads formats up to {current}): update SolidCraft to open it"
)
}
assert_eq!(refusal(&DESIGN, tagged(&DESIGN, FORMAT + 1)), newer("design", FORMAT + 1, FORMAT));
assert_eq!(read(&tagged(&DESIGN, FORMAT + 1).to_string()).unwrap_err().to_string(), newer("design", FORMAT + 1, FORMAT));
let current = DRAWING.current();
assert!(matches!(DRAWING.take_version(&mut tagged(&DRAWING, current)), Ok((v, None)) if v == current));
for n in [current + 1, u32::MAX] {
assert_eq!(refusal(&DRAWING, tagged(&DRAWING, n)), newer("drawing", n, current));
}
for (family, noun) in [(&DESIGN, "design"), (&DRAWING, "drawing")] {
assert_eq!(refusal(family, tagged(family, 0)), format!("not a SolidCraft {noun} (format 0)"));
assert_eq!(refusal(family, json!([])), format!("not a SolidCraft {noun} (expected a JSON object)"));
assert_eq!(refusal(family, json!({"format": 1})), format!("not a SolidCraft {noun} (format is not a string)"));
assert_eq!(refusal(family, json!({"format": ""})), format!("not a SolidCraft {noun} (format ``)"));
// `format_pending`'s caps, on both sides of each.
let mut file = tagged(family, 1);
file["format_pending"] = vec!["x".repeat(128); 1000].into();
assert!(family.take_version(&mut file).is_ok(), "{noun}: 1,000 names of 128 bytes");
for damaged in [vec!["x".repeat(128); 1001], vec!["x".repeat(129)]] {
let mut file = tagged(family, 1);
file["format_pending"] = damaged.into();
assert_eq!(refusal(family, file), format!("damaged {noun}: `format_pending` is not a short list of names"));
}
}
// A change this build doesn't know, in a design of the pending number.
let pending = [traced("a-first")];
let design = Family { formats: Formats { hand: &JSON_STEPS, folded: FOLDED, pending: &pending }, ..DESIGN };
let next = design.current();
let file = json!({"format": format_string(next), "format_pending": ["c-later"]});
assert_eq!(
refusal(&design, file),
format!(
"this design was saved by a newer SolidCraft (file format {next} with `c-later`, which this version doesn't know): update SolidCraft to open it"
)
);
assert!(matches!(DESIGN.take_version(&mut json!({})), Ok((1, None))));
assert_eq!(refusal(&DRAWING, json!({})), "not a SolidCraft drawing (no format)");
}
/// One drawing change pending, as a drawing's first change will be: the build writes format 2
/// and names the change in `format_pending`. Its step runs for a drawing without the change and
/// never for one with it; a drawing naming a change this build lacks, or of format 3, is a newer
/// build's.
#[test]
fn a_pending_drawing_change_makes_format_two() {
use serde_json::json;
let pending = [traced("a-first")];
let drawing = Family { formats: Formats { hand: &[], folded: &[], pending: &pending }, ..DRAWING };
assert_eq!((drawing.current(), drawing.format_string(drawing.current())), (2, "solidcraft-drawing/2".to_string()));
assert_eq!(drawing.pending_names(), ["a-first"]);
let open = |mut file: Value| -> Result<Vec<String>> {
let (version, applied) = drawing.take_version(&mut file)?;
assert!(file.get("format_pending").is_none(), "taken out of the JSON before the record is read");
drawing.upgrade(&mut file, version, applied.as_deref())?;
Ok(trace_of(&file).into_iter().map(str::to_string).collect())
};
assert_eq!(open(json!({"format": "solidcraft-drawing/1"})).unwrap(), ["a"]);
assert_eq!(open(json!({"format": "solidcraft-drawing/2", "format_pending": []})).unwrap(), ["a"]);
assert_eq!(open(json!({"format": "solidcraft-drawing/2", "format_pending": ["a-first"]})).unwrap(), Vec::<String>::new());
// A list beside format 1 means nothing: the step still runs.
assert_eq!(open(json!({"format": "solidcraft-drawing/1", "format_pending": ["c-later"]})).unwrap(), ["a"]);
let error = open(json!({"format": "solidcraft-drawing/2", "format_pending": ["a-first", "c-later"]})).unwrap_err().to_string();
assert_eq!(
error,
"this drawing was saved by a newer SolidCraft (file format 2 with `c-later`, which this version doesn't know): update SolidCraft to open it"
);
let error = open(json!({"format": "solidcraft-drawing/3"})).unwrap_err().to_string();
assert_eq!(
error,
"this drawing was saved by a newer SolidCraft (file format 3; this version reads formats up to 2): update SolidCraft to open it"
);
// An upgrade called without `take_version` refuses in the drawing's words too, format 0 included.
let error = drawing.upgrade(&mut json!({}), 3, None).unwrap_err().to_string();
assert!(error.starts_with("this drawing was saved by a newer SolidCraft (file format 3;"), "{error}");
assert_eq!(drawing.upgrade(&mut json!({}), 0, None).unwrap_err().to_string(), "not a SolidCraft drawing (format 0)");
}
/// `format_pending` is read and checked: a damaged list is refused, a list of changes this
/// build doesn't have is a newer build's, and saving writes this build's own list.
#[test]
+195
View File
@@ -0,0 +1,195 @@
//! Object ids (#1017, #3890): random, so objects added side by side, on two branches of a
//! repository or in two copies of a file, never take the same id, and no counter changes with
//! every addition. Drawings use them from their first format; designs keep their numbered ids
//! until they move over too (#626 Phase 3).
//!
//! - In memory an id is a nonzero `u64`. 0 is never one (it stands for a design's root
//! component).
//! - An [`IdSource`] gives them: splitmix64 from a seed, each draw checked against the ids in
//! use and drawn again when it is one. [`IdSource::seeded`] gives the same ids for the same
//! seed, for tests and replays, and still a new one in a file that seed made;
//! [`IdSource::from_entropy`] is what a session uses.
//! - In a file an id is 13 characters of Crockford's base32, lowercase: digits and letters without
//! i, l, o and u, the first `0` to `f` (`0000000000001`, `fzzzzzzzzzzzz`). [`encode`] writes it
//! and [`decode`] reads only that spelling, so an id has one form in a file's text. A field
//! holding an id says `#[serde(with = "crate::ids")]`.
use std::collections::BTreeSet;
use std::collections::hash_map::RandomState;
use std::hash::BuildHasher;
use std::sync::atomic::{AtomicU64, Ordering};
use serde::{Deserialize, Deserializer, Serializer};
use crate::{DocError, Result};
/// The characters of an id in a file: 64 bits in 5-bit digits, the first holding the top four.
pub const ID_CHARS: usize = 13;
/// Crockford's base32 digits, lowercase.
const DIGITS: &[u8; 32] = b"0123456789abcdefghjkmnpqrstvwxyz";
/// splitmix64's step: odd, so the state passes every `u64` before it comes round again.
const GAMMA: u64 = 0x9e37_79b9_7f4a_7c15;
/// Gives ids from a seed.
#[derive(Clone, Debug)]
pub struct IdSource {
state: u64,
}
impl IdSource {
/// The same ids for the same seed, for tests and replays.
pub fn seeded(seed: u64) -> IdSource {
IdSource { state: seed }
}
/// Ids another run gives only by chance: seeded from the standard library's hash keys (random
/// where the platform gives it randomness), the time, and a count of sources made, so two
/// sources made together differ.
pub fn from_entropy() -> IdSource {
static MADE: AtomicU64 = AtomicU64::new(0);
let nanos = web_time::SystemTime::now().duration_since(web_time::UNIX_EPOCH).map_or(0, |d| d.as_nanos());
IdSource::seeded(RandomState::new().hash_one((nanos, MADE.fetch_add(1, Ordering::Relaxed))))
}
/// The next id that isn't 0 and isn't `in_use`. A run never draws a number twice, so at most
/// one draw per id in use, and one 0, come before a free one.
pub fn next(&mut self, in_use: &BTreeSet<u64>) -> Result<u64> {
for _ in 0..in_use.len().saturating_add(2) {
let id = self.draw();
if id != 0 && !in_use.contains(&id) {
return Ok(id);
}
}
Err(DocError::Invalid("no free id".into()))
}
/// splitmix64: its mixing is one-to-one, so a run never gives one number twice.
fn draw(&mut self) -> u64 {
self.state = self.state.wrapping_add(GAMMA);
let mut z = self.state;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
}
/// `id` as a file writes it: [`ID_CHARS`] base32 digits, the most significant first.
pub fn encode(id: u64) -> String {
(0..ID_CHARS).rev().map(|k| DIGITS.get(((id >> (5 * k)) & 31) as usize).map_or('0', |&d| char::from(d))).collect()
}
/// The id `text` writes, if it is one in [`encode`]'s spelling: anything else, 0 included, is not.
pub fn decode(text: &str) -> Option<u64> {
if text.len() != ID_CHARS {
return None;
}
// A first digit above `f` overflows the 64 bits.
let id = text.bytes().try_fold(0u64, |id, b| id.checked_mul(32)?.checked_add(DIGITS.iter().position(|&d| d == b)? as u64))?;
(id != 0).then_some(id)
}
/// serde's `with` for an id field: written as [`encode`] writes it, read as [`decode`] reads it.
pub fn serialize<S: Serializer>(id: &u64, s: S) -> std::result::Result<S::Ok, S::Error> {
s.serialize_str(&encode(*id))
}
/// See [`serialize`].
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> std::result::Result<u64, D::Error> {
let text = String::deserialize(d)?;
decode(&text).ok_or_else(|| serde::de::Error::custom(format!("an id is {ID_CHARS} characters of lowercase Crockford base32, not all 0")))
}
#[cfg(test)]
mod tests {
use super::*;
fn none() -> BTreeSet<u64> {
BTreeSet::new()
}
/// Every boundary of the spelling: 1, the last value of one digit and the first of two, the
/// top digit alone and the largest id, and splitmix64's first output for seed 0.
#[test]
fn an_id_is_written_as_13_digits_and_read_back() {
let pinned = [
(1, "0000000000001"),
(31, "000000000000z"),
(32, "0000000000010"),
(1 << 60, "1000000000000"),
(u64::MAX, "fzzzzzzzzzzzz"),
(0xe220_a839_7b1d_cdaf, "e485875xhvkdf"),
];
for (id, text) in pinned {
assert_eq!((encode(id), decode(text)), (text.to_string(), Some(id)), "{id:#x}");
}
let mut source = IdSource::seeded(1);
for _ in 0..10_000 {
let id = source.next(&none()).unwrap();
assert_eq!(decode(&encode(id)), Some(id), "{id:#x}");
}
}
/// Only [`encode`]'s spelling is an id: the wrong length, 0, a first digit past `f`, capitals
/// (case-sensitive, so an id has one spelling to search for), the letters Crockford leaves
/// out, and anything not ASCII.
#[test]
fn only_the_written_spelling_is_an_id() {
let not_ids = [
"",
"000000000001",
"00000000000001",
"0000000000000",
"g000000000000",
"zzzzzzzzzzzzz",
"Fzzzzzzzzzzzz",
"000000000000A",
"000000000000i",
"000000000000l",
"000000000000o",
"000000000000u",
"00000000000é",
"000000000000-",
" 000000000001",
"000000000001\n",
];
for text in not_ids {
assert_eq!(decode(text), None, "{text:?}");
}
}
/// A seed gives the same ids every time (splitmix64's published first outputs for seed 0), and
/// a run never gives one twice.
#[test]
fn a_seeded_source_repeats_its_ids_and_never_gives_one_twice() {
let mut zero = IdSource::seeded(0);
assert_eq!([zero.draw(), zero.draw(), zero.draw()], [0xe220_a839_7b1d_cdaf, 0x6e78_9e6a_a1b9_65f4, 0x06c4_5d18_8009_454f]);
let run = |seed| {
let mut source = IdSource::seeded(seed);
(0..10_000).map(|_| source.next(&none()).unwrap()).collect::<Vec<_>>()
};
assert_eq!(run(7), run(7));
assert_ne!(run(7), run(8));
assert_eq!(run(7).into_iter().collect::<BTreeSet<_>>().len(), 10_000);
}
/// A draw that is in use, or 0, is drawn again: a file the same seed made, reopened with that
/// seed, collides on every one of its ids in turn and still gets a new one.
#[test]
fn a_taken_id_or_0_is_drawn_again() {
let mut seven = IdSource::seeded(7);
let made: Vec<u64> = (0..101).map(|_| seven.draw()).collect();
let in_use: BTreeSet<u64> = made.iter().take(100).copied().collect();
assert_eq!(IdSource::seeded(7).next(&in_use).unwrap(), made[100]);
// The state just before 0's: its first draw is 0, and the next is seed 0's first.
let before_zero = 0u64.wrapping_sub(GAMMA);
assert_eq!(IdSource::seeded(before_zero).draw(), 0);
assert_eq!(IdSource::seeded(before_zero).next(&none()).unwrap(), IdSource::seeded(0).draw());
}
/// Two sources made together still give different ids.
#[test]
fn sources_from_entropy_differ() {
let (mut a, mut b) = (IdSource::from_entropy(), IdSource::from_entropy());
assert_ne!(a.next(&none()).unwrap(), b.next(&none()).unwrap());
}
}
+4 -2
View File
@@ -23,6 +23,7 @@ pub mod construct;
pub mod display_quality;
pub mod display_units;
mod document;
pub mod drawing;
mod eval;
pub mod expr;
pub mod face_anchor;
@@ -34,6 +35,7 @@ mod format_offsets;
pub mod frame;
mod history_names;
pub mod hole_reference;
pub mod ids;
pub use format_offsets::whole_profile_selection_from_value;
pub mod joints;
mod lineage;
@@ -69,8 +71,8 @@ pub mod sheet;
pub mod text_params;
pub use assembly::{
IDENTITY, MAX_PLACEMENT_DEPTH, MAX_PLACEMENTS, Mat, Occurrence, WorldNames, apply_point, apply_vector, is_identity, map_point_expr, mat_inverse,
mat_mul, rigid,
BomType, IDENTITY, MAX_PLACEMENT_DEPTH, MAX_PLACEMENTS, Mat, Occurrence, WorldNames, apply_point, apply_vector, is_identity, map_point_expr,
mat_inverse, mat_mul, rigid,
};
pub use document::*;
pub use eval::{
+58 -6
View File
@@ -6,6 +6,7 @@
//! each may be set (the design, a component or both), how its value is checked and its label.
//! It keeps every other key exactly as it was through open, edit and save. Other tools keep
//! their own data under one reverse-DNS key each (`com.example.tool`), holding an object.
//! A component's part properties have one more key: its bill of materials type (`bom_type`).
//!
//! Reading never validates: a well-known key holding something other than text is kept as it
//! is and reads as absent, so a file another tool wrote always opens. Writing through
@@ -20,7 +21,7 @@
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use crate::{DocError, Result};
use crate::{BomType, DocError, Result};
pub const PROJECT: &str = "project";
pub const PART_NUMBER: &str = "part_number";
@@ -92,6 +93,11 @@ pub static KEYS: &[Key] = &[
/// own, and the Bill of Materials window edits them.
pub static BOM_KEYS: &[&str] = &[PART_NUMBER, DESCRIPTION, REVISION];
/// A component's [`BomType`] in the bill of materials (one of [`BomType::as_str`]'s words). It is
/// a part property of a component only, not a row of [`KEYS`], so the Design Properties dialog
/// doesn't list it and a design refuses it.
pub const BOM_TYPE: &str = "bom_type";
/// Longest key, in bytes.
pub const MAX_KEY_BYTES: usize = 128;
/// Longest well-known text value, in bytes.
@@ -114,9 +120,10 @@ pub fn keys(owner: Owner) -> impl Iterator<Item = &'static Key> {
KEYS.iter().filter(move |k| k.scope.covers(owner))
}
/// The names of [`keys`]`(owner)`, as refusals list them.
/// The names of [`keys`]`(owner)`, and a component's [`BOM_TYPE`], as refusals list them.
pub fn key_list(owner: Owner) -> String {
keys(owner).map(|k| k.name).collect::<Vec<_>>().join(", ")
let bom_type = (owner == Owner::Component).then_some(BOM_TYPE);
keys(owner).map(|k| k.name).chain(bom_type).collect::<Vec<_>>().join(", ")
}
/// One of SolidCraft's keys, by name.
@@ -126,7 +133,7 @@ pub fn key(name: &str) -> Option<&'static Key> {
/// A key SolidCraft reads as a design or part property.
pub fn is_well_known(name: &str) -> bool {
key(name).is_some()
key(name).is_some() || name == BOM_TYPE
}
/// A reverse-DNS key another tool keeps its data under: two or more dot-separated labels of
@@ -162,6 +169,19 @@ fn text(key: &str, value: Value) -> Result<Option<Value>> {
}
}
/// The bill of materials type's check: one of [`BomType`]'s words, which empty text (like
/// `null`) removes, so the component reads as normal again.
fn bom_type(value: Value) -> Result<Option<Value>> {
let Some(word) = text(BOM_TYPE, value)? else { return Ok(None) };
let s = word.as_str().unwrap_or_default();
if BomType::parse(s).is_none() {
let shown: String = s.chars().take(64).collect();
let words: Vec<&str> = BomType::ALL.iter().map(|t| t.as_str()).collect();
return Err(invalid(format!("`{BOM_TYPE}` is one of {}, not `{shown}`", words.join(", "))));
}
Ok(Some(word))
}
fn depth(v: &Value) -> usize {
// Iterative, so a hostile value can't overflow the stack here.
let mut deepest = 0;
@@ -223,6 +243,11 @@ impl Metadata {
pub fn license(&self) -> Option<&str> {
self.text(LICENSE)
}
/// The component's bill of materials type: normal when the key is missing, or holds a word
/// this build doesn't know (a newer SolidCraft's type reads as normal and is kept as it is).
pub fn bom_type(&self) -> BomType {
self.text(BOM_TYPE).and_then(BomType::parse).unwrap_or_default()
}
/// The keys SolidCraft doesn't read (other tools' data, or keys a newer SolidCraft added),
/// kept as they are.
@@ -260,6 +285,9 @@ impl Metadata {
/// `value` as `key` may hold it in `owner`'s metadata (`None`: remove the key), or why it can't.
fn check(owner: Owner, key: &str, value: Value) -> Result<Option<Value>> {
if key == BOM_TYPE && owner == Owner::Component {
return bom_type(value);
}
if let Some(k) = self::key(key).filter(|k| k.scope.covers(owner)) {
return (k.check)(key, value);
}
@@ -333,6 +361,30 @@ mod tests {
assert_eq!(m.0.keys().collect::<Vec<_>>(), ["description"]);
}
#[test]
fn a_bom_type_takes_one_of_its_words_and_reads_as_normal_otherwise() {
let mut m = Metadata::default();
assert_eq!(m.bom_type(), BomType::Normal, "no key: normal");
for t in BomType::ALL {
assert!(m.set(Component, BOM_TYPE, json!(t.as_str())).is_ok(), "{t:?}");
assert_eq!(m.bom_type(), t);
assert_eq!(BomType::parse(t.as_str()), Some(t));
}
for bad in [json!("Phantom"), json!("kit"), json!(" phantom"), json!(1), json!({"type": "phantom"}), json!("a\u{7}")] {
assert!(m.set(Component, BOM_TYPE, bad.clone()).is_err(), "{bad}");
}
assert_eq!(m.bom_type(), BomType::Inseparable, "a refused value leaves the old one");
assert!(m.set(Component, BOM_TYPE, json!("")).unwrap(), "empty text removes it");
assert_eq!(m.bom_type(), BomType::Normal);
assert!(m.others().next().is_none(), "SolidCraft reads it, so it isn't another tool's key");
// A word a newer build wrote is kept as it is and reads as normal here.
let newer: Metadata = serde_json::from_value(json!({"bom_type": "kit"})).unwrap();
assert_eq!(newer.bom_type(), BomType::Normal);
assert_eq!(newer.get(BOM_TYPE), Some(&json!("kit")));
assert!(!keys(Design).any(|k| k.name == BOM_TYPE), "the Design Properties dialog doesn't list it");
assert!(Metadata::default().set(Design, BOM_TYPE, json!("phantom")).is_err(), "a design has no bill of materials type");
}
#[test]
fn the_limits_refuse_growth_but_let_an_oversized_file_shrink() {
let mut m = Metadata::default();
@@ -370,7 +422,7 @@ mod tests {
}
// Every key SolidCraft took on the design and on a component before the table still is.
assert_eq!(key_list(Design), "project, part_number, revision, author, organization, description, license");
assert_eq!(key_list(Component), key_list(Design));
assert_eq!(key_list(Component), format!("{}, {BOM_TYPE}", key_list(Design)), "a component also takes its bill of materials type");
}
#[test]
@@ -402,7 +454,7 @@ mod tests {
assert_eq!(
refusal(Component, "colour"),
"`colour` is not a part property: SolidCraft's are project, part_number, revision, author, organization, \
description, license; another tool's data goes under a reverse-DNS key such as `com.example.tool`"
description, license, bom_type; another tool's data goes under a reverse-DNS key such as `com.example.tool`"
);
for owner in [Design, Component] {
let word = owner.names().0;
+62
View File
@@ -306,9 +306,61 @@ pub(crate) fn warm_names<'a>(bodies: impl Iterator<Item = &'a ModelBody>) {
}
}
/// Bodies whose names are worked out one from the other, oldest first, at most this many apart
/// (see [`warm_chain`]).
const WARM_STEP: usize = 16;
/// Up to this many earlier versions of a body are walked to name it from the oldest up.
const MAX_CHAIN: usize = 100_000;
/// The body `b`'s names are worked out from first: the body it is a moved copy of, else the
/// body of its name before the feature that made it (`None`: none, or past [`MAX_DEPTH`]).
fn predecessor(b: &ModelBody) -> Option<&ModelBody> {
if let Some(source) = &b.names.copy_of {
return Some(source);
}
let o = b.names.origin.as_ref().filter(|o| o.depth < MAX_DEPTH)?;
o.before.body(&b.name)
}
/// Work out the names of the earlier versions of `b` that are not known yet, oldest first and
/// every [`WARM_STEP`]th, so that naming `b` never recurses through more than that many of them.
/// A body's names are found from the names of the body it was made from, which are found the
/// same way: a body moved or changed by a few hundred features in a row whose names nothing
/// asked for overflowed the window thread's stack the first time something did (a fillet after
/// them evaluated again when an earlier feature is reordered or moved: #7587, #7926). `ready` says whether a
/// body's names are known, `name` works them out. The names are the same either way.
fn warm_chain(b: &ModelBody, ready: fn(&ModelBody) -> bool, name: fn(&ModelBody)) {
let mut chain: Vec<&ModelBody> = Vec::new();
let mut at = b;
while chain.len() < MAX_CHAIN
&& let Some(p) = predecessor(at)
&& !ready(p)
{
chain.push(p);
at = p;
}
if chain.len() <= WARM_STEP {
return;
}
for p in chain.iter().rev().step_by(WARM_STEP) {
name(p);
}
}
/// A body's names, with what finding them again needs: from the history of the feature that
/// made it where it reports one, else from geometry (unverified).
pub(crate) fn names(b: &ModelBody) -> Arc<Names> {
if let Some(known) = b.names.names.get() {
return known.clone();
}
warm_chain(
b,
|x| x.names.names.get().is_some(),
|x| {
let _ = names(x);
},
);
// A moved copy has its source's names (the source's cell keeps them for both).
if let Some(source) = &b.names.copy_of {
return b.names.names.get_or_init(|| names(source)).clone();
@@ -333,6 +385,16 @@ pub(crate) fn names(b: &ModelBody) -> Arc<Names> {
/// as those builds gave them, pieces of a split face numbered along the longest axis of their
/// spread (`#1`, `#2`, …).
pub(crate) fn legacy_face_names(b: &ModelBody) -> Arc<Vec<String>> {
if let Some(known) = b.names.legacy.get() {
return known.clone();
}
warm_chain(
b,
|x| x.names.legacy.get().is_some(),
|x| {
let _ = legacy_face_names(x);
},
);
if let Some(source) = &b.names.copy_of {
return legacy_face_names(source);
}
+3 -18
View File
@@ -114,21 +114,6 @@ fn chorded_region(region: &Region2) -> Result<Region2> {
})
}
/// A line or free-form segment with its points mapped by `f`: exact under any affine map (a
/// conic keeps its weight). An arc is given by angles, not points, and stays as it is.
pub(crate) fn map_controls(seg: &Seg2, f: impl Fn(Vec2) -> Vec2) -> Seg2 {
match *seg {
Seg2::Line { a, b } => Seg2::Line { a: f(a), b: f(b) },
Seg2::Cubic { p0, p1, p2, p3 } => Seg2::Cubic { p0: f(p0), p1: f(p1), p2: f(p2), p3: f(p3) },
Seg2::Conic { a, apex, b, w } => Seg2::Conic { a: f(a), apex: f(apex), b: f(b), w },
Seg2::Bezier { n, mut p } => {
p.iter_mut().take(usize::from(n) + 1).for_each(|q| *q = f(*q));
Seg2::Bezier { n, p }
}
arc @ Seg2::Arc { .. } => arc,
}
}
fn planar_region(region: &Region2) -> Result<Region2> {
if region.holes.len() > MAX_FLAT_PIECES {
return Err(flat_budget_error());
@@ -4315,7 +4300,7 @@ impl SheetBody {
}
}
// Free-form segments map exactly, through their control points.
other => map_controls(&other, map),
other => other.map_controls(map),
}
};
let map_loop = |lp: &Loop2| Loop2 { segs: lp.segs.iter().map(seg).collect() };
@@ -4676,7 +4661,7 @@ fn flip_x_loop(l: &Loop2) -> Loop2 {
Seg2::Arc { center, radius, start, sweep } => {
Seg2::Arc { center: flip_x(center), radius, start: std::f64::consts::PI - start, sweep: -sweep }
}
other => map_controls(&other, flip_x),
other => other.map_controls(flip_x),
})
.collect();
Loop2 { segs }.reversed()
@@ -5325,7 +5310,7 @@ mod tests {
// right: the same ellipse on the sheet, every curve through its mirrored controls.
let below = Plane { origin: Vec3::ZERO, x: Vec3::X, y: Vec3::Y * -1.0 };
let mirror = |p: Vec2| Vec2::new(p.x, -p.y);
let seen = Region2 { outer: Loop2 { segs: hole.outer.segs.iter().map(|x| map_controls(x, mirror)).collect() }, holes: vec![] };
let seen = Region2 { outer: Loop2 { segs: hole.outer.segs.iter().map(|x| x.map_controls(mirror)).collect() }, holes: vec![] };
let mapped = s.region_to_flat(None, &below, &seen).unwrap();
assert!(mapped.outer.is_ccw() && mapped.outer.segs.len() == 4 && mapped.outer.segs.iter().all(|x| hole.outer.segs.contains(x)), "{mapped:?}");
// A cubic and a quartic closed by a line, clockwise in that plane: counter-clockwise on
+95 -37
View File
@@ -5,11 +5,17 @@
//! `assembly.bom` counts the placed components of the design, or of one component, and lists
//! them as rows, optionally written to a CSV or JSON file. With `group_children`, a part with a
//! part number keeps the parts placed inside it (a bolt's washers and nut) in its own row.
//!
//! A component's bill of materials type (`bom_type`, a part property) decides how it counts: a
//! phantom has no row and what it holds counts in its parent; a reference counts nowhere, and
//! nothing inside it does; a purchased or inseparable component is one row, and of what an
//! inseparable one holds only its purchased parts reach the parts-only list.
use std::collections::{BTreeMap, HashSet};
use serde_json::{Map, Value, json};
use solidcraft_doc::metadata::{BOM_KEYS, MAX_KEYS, Owner, check_text, key_list};
use solidcraft_doc::BomType;
use solidcraft_doc::metadata::{BOM_KEYS, BOM_TYPE, MAX_KEYS, Owner, check_text, key_list};
use super::CommandSpec;
use crate::params::{bad, str_};
@@ -18,13 +24,14 @@ use crate::{EngineError, Result, Session};
pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("component.metadata", "Part Properties", read).icon("settings").noundo().doc_only().params(
"component: id or name (0 or \"root\": the design's own properties) → component, name, part_number, description, revision, \
metadata (as saved, other tools' keys too), properties: {name: text}",
bom_type (components only), metadata (as saved, other tools' keys too), properties: {name: text}",
),
CommandSpec::new("component.metadata.set", "Change Part Properties", set).icon("settings").doc_only().params(
"component: id or name (not the root: use document.metadata.set); part_number?, description?, revision?: text (empty or null \
removes); values?: {key: value} (SolidCraft's keys, as document.metadata's properties lists them, or a reverse-DNS key \
holding an object); properties?: {name: text, …} (free properties; empty or null removes). All or nothing, one undo step \
→ component, metadata, properties, changed: [keys]",
removes); bom_type?: normal|phantom|reference|purchased|inseparable (empty or null: normal); values?: {key: value} \
(SolidCraft's keys, as document.metadata's properties lists them, bom_type, or a reverse-DNS key holding an object); \
properties?: {name: text, …} (free properties; empty or null removes). All or nothing, one undo step → component, \
metadata, properties, changed: [keys]",
),
CommandSpec::new("assembly.bom", "Bill of Materials", bom).at("SOLID", "INSPECT").icon("bom").noundo().params(
"component?: id or name (default the design); levels?: flat (default: every part at any depth, counted through its \
@@ -32,8 +39,10 @@ pub static COMMANDS: &[CommandSpec] = &[
(default; components without a part number get a row per definition) | [\"definition\"]; group_children?: true (a component \
with a part number is one row, the parts placed inside it listed under it as children: [{item, part_number, description, \
revision, each, count, definition}], not as rows of their own); path?: write a .csv or .json file (children as items 1.1, \
1.2…); format?: csv|json (default from the path) → rows: [{item, part_number, description, revision, count, definition, \
components, properties, children?}] sorted by part number, total_occurrences (children included)",
1.2…); format?: csv|json (default from the path). Each component's bom_type counts: phantom has no row (what it holds \
counts here), reference counts nowhere, purchased and inseparable are one row (in flat, an inseparable one's purchased \
parts are listed too) → rows: [{item, part_number, description, revision, bom_type, count, definition, components, \
properties, children?}] sorted by part number, total_occurrences (children included)",
),
];
@@ -72,6 +81,10 @@ fn read(s: &mut Session, p: &Value) -> Result<Value> {
for k in BOM_KEYS {
out.insert(k.to_string(), json!(m.text(k)));
}
// A bill of materials type is a component's; the design has none.
if id != 0 {
out.insert(BOM_TYPE.into(), json!(m.bom_type().as_str()));
}
out.insert("metadata".into(), json!(m));
out.insert("properties".into(), properties);
Ok(Value::Object(out))
@@ -111,7 +124,7 @@ fn set(s: &mut Session, p: &Value) -> Result<Value> {
Some(Value::Object(_)) => return Err(bad(cmd, format!("`values` can hold at most {MAX_KEYS} keys"))),
Some(_) => return Err(bad(cmd, "`values` must be an object: {key: value, …}")),
}
for k in BOM_KEYS {
for k in BOM_KEYS.iter().chain([&BOM_TYPE]) {
if let Some(v) = p.get(*k) {
entries.push((k.to_string(), v.clone()));
}
@@ -123,7 +136,7 @@ fn set(s: &mut Session, p: &Value) -> Result<Value> {
Some(_) => return Err(bad(cmd, "`properties` must be an object: {name: text, …}")),
};
if entries.is_empty() && props.is_empty() {
return Err(bad(cmd, format!("give {}, values or properties ({})", BOM_KEYS.join(", "), key_list(Owner::Component))));
return Err(bad(cmd, format!("give {}, {BOM_TYPE}, values or properties ({})", BOM_KEYS.join(", "), key_list(Owner::Component))));
}
let mut changed: Vec<String> = Vec::new();
for (k, v) in entries {
@@ -176,6 +189,7 @@ struct Row {
part_number: String,
description: String,
revision: String,
bom_type: BomType,
count: u64,
components: Vec<u64>,
names: Vec<String>,
@@ -225,6 +239,8 @@ struct Index {
owners: HashSet<u64>,
/// Components with a part number: with `group_children`, one row however much is inside.
numbered: HashSet<u64>,
/// Components whose bill of materials type isn't normal.
types: BTreeMap<u64, BomType>,
}
impl Index {
@@ -234,8 +250,22 @@ impl Index {
children.entry(o.parent).or_default().push(o.component);
}
let numbered = s.doc.components.iter().filter(|c| c.metadata.part_number().is_some_and(|n| !n.is_empty())).map(|c| c.id).collect();
Index { children, owners: s.doc.body_owners(&s.model.state()), numbered }
let types = s.doc.components.iter().map(|c| (c.id, c.metadata.bom_type())).filter(|(_, t)| *t != BomType::Normal).collect();
Index { children, owners: s.doc.body_owners(&s.model.state()), numbered, types }
}
fn bom_type(&self, component: u64) -> BomType {
self.types.get(&component).copied().unwrap_or_default()
}
}
/// What a walk below a component lists.
#[derive(Clone, Copy, PartialEq)]
enum Walk {
/// What the bill of materials lists.
Listed,
/// Inside an inseparable component, in parts only: just its purchased parts.
Purchased,
}
fn group_key(g: &str, cmd: &str) -> Result<Group> {
@@ -246,63 +276,88 @@ fn group_key(g: &str, cmd: &str) -> Result<Group> {
}
}
/// How many times each component is placed below `root`: in `Top`, its direct children; in
/// `Flat`, every placement at any depth (a part in a subassembly placed twice counts twice),
/// not below a numbered part when `fold`.
/// How many times each component is listed below `root`, by its bill of materials type: in
/// `Top`, the direct children; in `Flat`, the parts at any depth (a part in a subassembly placed
/// twice counts twice), not below a purchased part, nor below a numbered part when `fold`, and of
/// what an inseparable part holds only its purchased parts. A phantom's contents count where the
/// phantom is placed; a reference counts nowhere, and nothing inside it does.
fn counts(ix: &Index, root: u64, levels: Levels, fold: bool, cmd: &str) -> Result<BTreeMap<u64, u64>> {
let mut out: BTreeMap<u64, u64> = BTreeMap::new();
let mut placed = 0usize;
let mut stack: Vec<(u64, usize)> = vec![(root, 0)];
while let Some((comp, depth)) = stack.pop() {
let mut stack: Vec<(u64, usize, Walk)> = vec![(root, 0, Walk::Listed)];
while let Some((comp, depth, walk)) = stack.pop() {
for child in ix.children.get(&comp).into_iter().flatten() {
placed += 1;
if depth >= MAX_DEPTH || placed > MAX_PLACEMENTS {
return Err(bad(cmd, format!("the assembly is deeper than {MAX_DEPTH} levels or has more than {MAX_PLACEMENTS} placements")));
}
*out.entry(*child).or_default() += 1;
if levels == Levels::Flat && !(fold && ix.numbered.contains(child)) {
stack.push((*child, depth + 1));
let inside = ix.children.contains_key(child);
match (ix.bom_type(*child), walk) {
(BomType::Reference, _) => {}
(BomType::Phantom, _) => stack.push((*child, depth + 1, walk)),
(BomType::Purchased, _) => *out.entry(*child).or_default() += 1,
(_, Walk::Purchased) => {
if inside {
stack.push((*child, depth + 1, Walk::Purchased));
}
}
(BomType::Inseparable, Walk::Listed) => {
*out.entry(*child).or_default() += 1;
if levels == Levels::Flat && inside {
stack.push((*child, depth + 1, Walk::Purchased));
}
}
(BomType::Normal, Walk::Listed) => {
// Parts only: a subassembly is listed through its parts, unless it has bodies
// of its own (or, folding, a part number).
let folded = fold && ix.numbered.contains(child);
if levels == Levels::Top || !inside || folded || ix.owners.contains(child) {
*out.entry(*child).or_default() += 1;
}
if levels == Levels::Flat && inside && !folded {
stack.push((*child, depth + 1, Walk::Listed));
}
}
}
}
}
if levels == Levels::Flat {
// Parts only: a subassembly is listed through its parts, unless it has bodies of its own
// (or, folding, a part number).
out.retain(|c, _| !ix.children.contains_key(c) || (fold && ix.numbered.contains(c)) || ix.owners.contains(c));
}
Ok(out)
}
/// How a kit reads when rows are compared: its parts by part number (else definition) and count.
fn kit_key(s: &Session, kit: &BTreeMap<u64, u64>) -> String {
/// How a kit reads when rows are compared: its parts by part number (else definition), bill of
/// materials type and count, so a kit holding a bought bolt isn't the kit holding a made one.
fn kit_key(s: &Session, ix: &Index, kit: &BTreeMap<u64, u64>) -> String {
let mut parts: Vec<String> = kit
.iter()
.map(|(id, n)| {
let pn = s.doc.components.iter().find(|c| c.id == *id).and_then(|c| c.metadata.part_number()).unwrap_or_default();
if pn.is_empty() { format!("#{id}×{n}") } else { format!("{pn}×{n}") }
let bom_type = ix.bom_type(*id).as_str();
if pn.is_empty() { format!("#{id} {bom_type}×{n}") } else { format!("{pn} {bom_type}×{n}") }
})
.collect();
parts.sort();
parts.join("\n")
}
fn rows(s: &Session, counts: &BTreeMap<u64, u64>, group: Group, kits: &BTreeMap<u64, BTreeMap<u64, u64>>) -> Vec<Row> {
let mut grouped: BTreeMap<(String, String, u64), Row> = BTreeMap::new();
fn rows(s: &Session, ix: &Index, counts: &BTreeMap<u64, u64>, group: Group, kits: &BTreeMap<u64, BTreeMap<u64, u64>>) -> Vec<Row> {
let mut grouped: BTreeMap<(String, String, u64, BomType), Row> = BTreeMap::new();
for (id, n) in counts {
let Some(c) = s.doc.components.iter().find(|c| c.id == *id) else { continue };
let m = &c.metadata;
let part_number = m.part_number().unwrap_or_default().to_string();
let kit = kits.get(id).cloned().unwrap_or_default();
let bom_type = ix.bom_type(*id);
// Without a part number a definition is its own row; parts with different contents
// (a bolt with or without its nut) are different rows.
// (a bolt with or without its nut) or different bill of materials types are different rows.
let k = match group {
Group::PartNumber if !part_number.is_empty() => (part_number.clone(), kit_key(s, &kit), 0),
_ => (String::new(), String::new(), *id),
Group::PartNumber if !part_number.is_empty() => (part_number.clone(), kit_key(s, ix, &kit), 0, bom_type),
_ => (String::new(), String::new(), *id, bom_type),
};
let row = grouped.entry(k).or_insert_with(|| Row {
part_number: part_number.clone(),
description: String::new(),
revision: String::new(),
bom_type,
count: 0,
components: Vec::new(),
names: Vec::new(),
@@ -361,10 +416,11 @@ fn bom(s: &mut Session, p: &Value) -> Result<Value> {
let o = options(p, cmd)?;
let ix = Index::new(s);
let counts = counts(&ix, root, o.levels, o.fold, cmd)?;
// Folding: what one of each numbered part holds, as parts at any depth.
// Folding: what one of each numbered part holds, as parts at any depth. A purchased or
// inseparable part already keeps what it holds out of the list.
let mut kits: BTreeMap<u64, BTreeMap<u64, u64>> = BTreeMap::new();
if o.fold {
for id in counts.keys().filter(|id| ix.numbered.contains(id)) {
for id in counts.keys().filter(|id| ix.numbered.contains(id) && ix.bom_type(**id) == BomType::Normal) {
let kit = self::counts(&ix, *id, Levels::Flat, false, cmd)?;
if !kit.is_empty() {
kits.insert(*id, kit);
@@ -372,22 +428,24 @@ fn bom(s: &mut Session, p: &Value) -> Result<Value> {
}
}
let mut total: u64 = 0;
let rows: Vec<Value> = rows(s, &counts, o.group, &kits)
let rows: Vec<Value> = rows(s, &ix, &counts, o.group, &kits)
.into_iter()
.enumerate()
.map(|(i, r)| {
total += r.count;
let mut v = json!({"item": i + 1, "part_number": r.part_number, "description": r.description, "revision": r.revision,
"count": r.count, "definition": r.names.join("; "), "components": r.components, "properties": r.properties});
"bom_type": r.bom_type.as_str(), "count": r.count, "definition": r.names.join("; "), "components": r.components,
"properties": r.properties});
if !r.kit.is_empty() {
let children: Vec<Value> = self::rows(s, &r.kit, Group::PartNumber, &BTreeMap::new())
let children: Vec<Value> = self::rows(s, &ix, &r.kit, Group::PartNumber, &BTreeMap::new())
.into_iter()
.enumerate()
.map(|(j, c)| {
let count = c.count.saturating_mul(r.count);
total += count;
json!({"item": format!("{}.{}", i + 1, j + 1), "part_number": c.part_number, "description": c.description,
"revision": c.revision, "each": c.count, "count": count, "definition": c.names.join("; ")})
"revision": c.revision, "bom_type": c.bom_type.as_str(), "each": c.count, "count": count,
"definition": c.names.join("; ")})
})
.collect();
v["children"] = Value::Array(children);
+227 -3
View File
@@ -267,7 +267,7 @@ fn a_components_refusals_speak_of_part_properties() {
assert!(
bogus.ends_with(
"`bogus` is not a part property: SolidCraft's are project, part_number, revision, author, organization, description, \
license; another tool's data goes under a reverse-DNS key such as `com.example.tool`"
license, bom_type; another tool's data goes under a reverse-DNS key such as `com.example.tool`"
),
"{bogus}"
);
@@ -275,8 +275,8 @@ fn a_components_refusals_speak_of_part_properties() {
assert!(refusal(&mut s, json!({"component": "Pin", "values": {"": "x"}})).contains("`` is not a part property"));
// Nothing to change: the same list as before the table.
assert!(refusal(&mut s, json!({"component": "Pin"})).ends_with(
"give part_number, description, revision, values or properties (project, part_number, revision, author, organization, \
description, license)"
"give part_number, description, revision, bom_type, values or properties (project, part_number, revision, author, \
organization, description, license, bom_type)"
));
// Only the bill of materials' keys are parameters of their own; the others go in `values`.
assert!(refusal(&mut s, json!({"component": "Pin", "author": "Jane"})).contains("give part_number, description, revision"));
@@ -400,3 +400,227 @@ fn body_owners_match_each_bodys_component() {
assert_eq!(s.doc.model_body_components(&st), in_order);
}
}
/// A machine: a plate, and a gearbox (no bodies of its own) that holds a shaft and a bearing.
/// Each is placed once.
fn machine() -> Session {
let mut s = Session::default();
run(&mut s, "component.create", json!({"name": "Plate"}));
run(&mut s, "solid.box", json!({"length": 100, "width": 60, "height": 10}));
run(&mut s, "component.activate", json!({"component": 0}));
run(&mut s, "component.create", json!({"name": "Gearbox", "activate": false}));
for (name, diameter, height) in [("Shaft", 10, 80), ("Bearing", 22, 7)] {
run(&mut s, "component.create", json!({"name": name, "parent": "Gearbox"}));
run(&mut s, "solid.cylinder", json!({"diameter": diameter, "height": height}));
run(&mut s, "component.activate", json!({"component": 0}));
}
for (c, pn) in [("Plate", "PL-1"), ("Gearbox", "GB-1"), ("Shaft", "SH-1"), ("Bearing", "BR-1")] {
run(&mut s, "component.metadata.set", json!({"component": c, "part_number": pn}));
}
s
}
/// Each row's part number, bill of materials type and count.
fn typed(r: &Value) -> Vec<(String, String, u64)> {
r["rows"]
.as_array()
.unwrap()
.iter()
.map(|r| (r["part_number"].as_str().unwrap().to_string(), r["bom_type"].as_str().unwrap().to_string(), r["count"].as_u64().unwrap()))
.collect()
}
fn row(part_number: &str, bom_type: &str, count: u64) -> (String, String, u64) {
(part_number.to_string(), bom_type.to_string(), count)
}
fn set_type(s: &mut Session, component: &str, bom_type: &str) {
run(s, "component.metadata.set", json!({"component": component, "bom_type": bom_type}));
}
#[test]
fn bom_types_decide_what_is_a_row_and_what_counts_inside_it() {
let mut s = machine();
let top = |s: &mut Session| typed(&run(s, "assembly.bom", json!({"levels": "top"})));
let flat = |s: &mut Session| typed(&run(s, "assembly.bom", json!({})));
let own = |s: &mut Session| typed(&run(s, "assembly.bom", json!({"component": "Gearbox"})));
// Normal: the gearbox is a row at the top and is listed through its parts in parts only.
assert_eq!(top(&mut s), [row("GB-1", "normal", 1), row("PL-1", "normal", 1)]);
assert_eq!(flat(&mut s), [row("BR-1", "normal", 1), row("PL-1", "normal", 1), row("SH-1", "normal", 1)]);
// Purchased: one row, with nothing inside it listed; its own bill of materials still lists it.
set_type(&mut s, "Gearbox", "purchased");
assert_eq!(top(&mut s), [row("GB-1", "purchased", 1), row("PL-1", "normal", 1)]);
assert_eq!(flat(&mut s), [row("GB-1", "purchased", 1), row("PL-1", "normal", 1)]);
assert_eq!(own(&mut s), [row("BR-1", "normal", 1), row("SH-1", "normal", 1)]);
// Inseparable: one row; of what it holds only purchased parts reach the parts-only list.
set_type(&mut s, "Gearbox", "inseparable");
assert_eq!(flat(&mut s), [row("GB-1", "inseparable", 1), row("PL-1", "normal", 1)]);
set_type(&mut s, "Bearing", "purchased");
assert_eq!(top(&mut s), [row("GB-1", "inseparable", 1), row("PL-1", "normal", 1)]);
assert_eq!(flat(&mut s), [row("BR-1", "purchased", 1), row("GB-1", "inseparable", 1), row("PL-1", "normal", 1)]);
assert_eq!(own(&mut s), [row("BR-1", "purchased", 1), row("SH-1", "normal", 1)], "in its own context an ordinary assembly");
// Reference: counted nowhere, and nothing inside it is counted, purchased parts included.
set_type(&mut s, "Gearbox", "reference");
assert_eq!(top(&mut s), [row("PL-1", "normal", 1)]);
assert_eq!(flat(&mut s), [row("PL-1", "normal", 1)]);
assert_eq!(run(&mut s, "assembly.bom", json!({}))["total_occurrences"], 1);
// Phantom: no row; what it holds counts where it is placed, at the top level too.
set_type(&mut s, "Gearbox", "phantom");
assert_eq!(top(&mut s), [row("BR-1", "purchased", 1), row("PL-1", "normal", 1), row("SH-1", "normal", 1)]);
assert_eq!(flat(&mut s), [row("BR-1", "purchased", 1), row("PL-1", "normal", 1), row("SH-1", "normal", 1)]);
// Back to normal (empty text removes the key) gives the first lists again.
set_type(&mut s, "Gearbox", "");
set_type(&mut s, "Bearing", "normal");
assert_eq!(top(&mut s), [row("GB-1", "normal", 1), row("PL-1", "normal", 1)]);
assert_eq!(flat(&mut s), [row("BR-1", "normal", 1), row("PL-1", "normal", 1), row("SH-1", "normal", 1)]);
assert_eq!(run(&mut s, "component.metadata", json!({"component": "Gearbox"}))["bom_type"], "normal");
}
#[test]
fn a_phantom_counts_what_it_holds_in_its_parent_merged_with_the_same_parts() {
// A fastener set (no bodies) of two screws, placed three times, and one more screw placed directly.
let mut s = Session::default();
run(&mut s, "component.create", json!({"name": "Set", "activate": false}));
run(&mut s, "component.create", json!({"name": "Screw", "parent": "Set"}));
run(&mut s, "solid.cylinder", json!({"diameter": 6, "height": 20}));
run(&mut s, "component.activate", json!({"component": 0}));
run(&mut s, "occurrence.copy", json!({"component": "Screw", "parent": "Set", "translate": [10, 0, 0]}));
for y in [50, 100] {
run(&mut s, "occurrence.copy", json!({"component": "Set", "translate": [0, y, 0]}));
}
run(&mut s, "occurrence.copy", json!({"component": "Screw", "parent": 0, "translate": [0, -50, 0]}));
run(&mut s, "component.metadata.set", json!({"component": "Screw", "part_number": "SC-6"}));
run(&mut s, "component.metadata.set", json!({"component": "Set", "part_number": "SET-1"}));
assert_eq!(typed(&run(&mut s, "assembly.bom", json!({"levels": "top"}))), [row("SC-6", "normal", 1), row("SET-1", "normal", 3)]);
assert_eq!(typed(&run(&mut s, "assembly.bom", json!({}))), [row("SC-6", "normal", 7)], "2 x 3 + 1");
set_type(&mut s, "Set", "phantom");
assert_eq!(typed(&run(&mut s, "assembly.bom", json!({"levels": "top"}))), [row("SC-6", "normal", 7)], "promoted and merged");
let flat = run(&mut s, "assembly.bom", json!({}));
assert_eq!(typed(&flat), [row("SC-6", "normal", 7)]);
assert_eq!(flat["total_occurrences"], 7);
// A phantom inside a phantom promotes through both.
run(&mut s, "component.create", json!({"name": "Kit", "activate": false}));
run(&mut s, "occurrence.copy", json!({"component": "Set", "parent": "Kit"}));
run(&mut s, "occurrence.copy", json!({"component": "Kit", "translate": [0, 200, 0]}));
set_type(&mut s, "Kit", "phantom");
// The Kit created at the root holds one Set; its copy holds the same: 2 kits x 2 screws more.
assert_eq!(typed(&run(&mut s, "assembly.bom", json!({"levels": "top"}))), [row("SC-6", "normal", 11)]);
}
/// Kits with one part number fold into one row only when what they hold is the same, its bill of
/// materials types included: a kit holding a bought bolt isn't the kit holding a made one.
#[test]
fn kits_with_one_part_number_fold_together_only_when_their_contents_types_match() {
let mut s = Session::default();
for (kit, bolt) in [("KitA", "BoltA"), ("KitB", "BoltB")] {
run(&mut s, "component.create", json!({"name": kit, "activate": false}));
run(&mut s, "component.create", json!({"name": bolt, "parent": kit}));
run(&mut s, "solid.cylinder", json!({"diameter": 6, "height": 20}));
run(&mut s, "component.activate", json!({"component": 0}));
run(&mut s, "component.metadata.set", json!({"component": kit, "part_number": "KIT"}));
run(&mut s, "component.metadata.set", json!({"component": bolt, "part_number": "BOLT"}));
}
// Each kit row: its count, and each child's definition, count in one kit and count in all.
let kits = |s: &mut Session| -> Vec<(u64, Vec<(String, u64, u64)>)> {
let r = run(s, "assembly.bom", json!({"group_children": true}));
let child = |c: &Value| (c["definition"].as_str().unwrap().to_string(), c["each"].as_u64().unwrap(), c["count"].as_u64().unwrap());
r["rows"]
.as_array()
.unwrap()
.iter()
.map(|k| (k["count"].as_u64().unwrap(), k["children"].as_array().unwrap().iter().map(child).collect()))
.collect()
};
let same = kits(&mut s);
assert_eq!((same.len(), same[0].0, same[0].1.len(), same[0].1[0].1, same[0].1[0].2), (1, 2, 1, 1, 2), "{same:?}");
set_type(&mut s, "BoltB", "purchased");
assert_eq!(kits(&mut s), [(1, vec![("BoltA".into(), 1, 1)]), (1, vec![("BoltB".into(), 1, 1)])]);
}
#[test]
fn a_purchased_part_keeps_what_is_placed_inside_it_out_of_the_list() {
let mut s = bolts();
// Each inserted bolt is a definition of its own; buy them all.
let bolts = run(&mut s, "assembly.bom", json!({}))["rows"][0]["components"].clone();
assert_eq!(bolts.as_array().map(Vec::len), Some(3));
for bolt in bolts.as_array().unwrap() {
run(&mut s, "component.metadata.set", json!({"component": bolt, "bom_type": "purchased"}));
}
// The washers and nuts placed inside two of them are no longer listed.
let plain = run(&mut s, "assembly.bom", json!({}));
assert_eq!(typed(&plain), [row("ISO 4017 M6x30", "purchased", 3)], "{plain}");
assert_eq!(plain["total_occurrences"], 3);
// Folding has nothing to fold: a purchased part is one row already.
let folded = run(&mut s, "assembly.bom", json!({"group_children": true}));
assert_eq!(typed(&folded), [row("ISO 4017 M6x30", "purchased", 3)]);
assert!(folded["rows"][0].get("children").is_none(), "{folded}");
// One bolt bought and two made gives two rows for the one part number.
run(&mut s, "component.metadata.set", json!({"component": bolts[0], "bom_type": null}));
run(&mut s, "component.metadata.set", json!({"component": bolts[1], "bom_type": null}));
let mixed = typed(&run(&mut s, "assembly.bom", json!({})));
assert!(mixed.contains(&row("ISO 4017 M6x30", "normal", 2)) && mixed.contains(&row("ISO 4017 M6x30", "purchased", 1)), "{mixed:?}");
}
#[test]
fn a_bom_type_is_one_undo_step_survives_save_and_open_and_evaluates_nothing() {
let dir = scratch("bom-type");
let mut s = machine();
let undo = s.undo.len();
s.evaluations = 0;
let r = run(&mut s, "component.metadata.set", json!({"component": "Gearbox", "bom_type": "inseparable"}));
assert_eq!(r["changed"], json!(["bom_type"]));
assert_eq!(s.undo.len(), undo + 1);
assert_eq!(s.evaluations, 0, "a part property changes no geometry");
for (file, format) in [("machine.json", "json"), ("machine.solidcraft", "container")] {
let path = dir.join(file);
run(&mut s, "file.save_as", json!({"path": path, "format": format}));
let mut back = Session::default();
run(&mut back, "doc.open", json!({"path": path}));
assert_eq!(run(&mut back, "component.metadata", json!({"component": "Gearbox"}))["bom_type"], "inseparable", "{format}");
assert_eq!(typed(&run(&mut back, "assembly.bom", json!({}))), typed(&run(&mut s, "assembly.bom", json!({}))), "{format}");
}
run(&mut s, "edit.undo", json!({}));
assert_eq!(run(&mut s, "component.metadata", json!({"component": "Gearbox"}))["bom_type"], "normal");
// Through `values` too, and the same word again changes nothing.
run(&mut s, "component.metadata.set", json!({"component": "Gearbox", "values": {"bom_type": "phantom"}}));
let again = run(&mut s, "component.metadata.set", json!({"component": "Gearbox", "bom_type": "phantom"}));
assert_eq!(again["changed"], json!([]));
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn hostile_bom_types_are_refused_without_a_change() {
let mut s = machine();
let undo = s.undo.len();
for p in [
json!({"component": "Gearbox", "bom_type": "virtual"}),
json!({"component": "Gearbox", "bom_type": "Phantom"}),
json!({"component": "Gearbox", "bom_type": 3}),
json!({"component": "Gearbox", "bom_type": ["phantom"]}),
json!({"component": "Gearbox", "bom_type": "x".repeat(5000)}),
json!({"component": "Gearbox", "values": {"bom_type": "phantom\u{7}"}}),
json!({"component": 0, "bom_type": "phantom"}),
json!({"component": "Gearbox", "part_number": "GB-2", "bom_type": "nope"}),
] {
assert!(s.execute("component.metadata.set", &p).is_err(), "{p}");
}
assert!(s.execute("document.metadata.set", &json!({"key": "bom_type", "value": "phantom"})).is_err(), "not a design property");
assert!(s.execute("document.metadata.set", &json!({"values": {"bom_type": "purchased"}})).is_err());
assert_eq!(s.undo.len(), undo, "nothing changed");
let gb = run(&mut s, "component.metadata", json!({"component": "Gearbox"}));
assert_eq!((gb["part_number"].as_str(), gb["bom_type"].as_str()), (Some("GB-1"), Some("normal")), "all or nothing");
// A word another build wrote is kept and reads as normal.
let id = s.doc.find_component("Gearbox").unwrap();
if let Some(c) = s.doc_mut().components.iter_mut().find(|c| c.id == id) {
c.metadata.0.insert("bom_type".into(), json!("kit"));
}
assert_eq!(run(&mut s, "component.metadata", json!({"component": "Gearbox"}))["bom_type"], "normal");
assert_eq!(typed(&run(&mut s, "assembly.bom", json!({"levels": "top"}))), [row("GB-1", "normal", 1), row("PL-1", "normal", 1)]);
}
+124 -16
View File
@@ -39,7 +39,7 @@ pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("view.delete", "Delete Named View", view_delete).icon("delete").params("view: name"),
CommandSpec::new("view.list", "List Named Views", view_list).icon("list").noundo().doc_only(),
CommandSpec::new("view.apply", "Restore Named View", view_apply).icon("camera").noundo().params(
"view?: front|back|top|bottom|left|right|iso|home (frames the model) | a named view's name; or camera?: {target: [x,y,z], yaw, pitch, distance, fov?, roll?} (radians, mm; roll defaults to 0, must be finite and is clamped to ±π; up is refused: the up axis comes from the design settings) → camera. The viewport (and the MCP screenshot) moves there. View state: not saved, not an undo step",
"view?: front|back|top|bottom|left|right|iso|home (frames the model) | a named view's name; or camera?: {target: [x,y,z], yaw, pitch, distance, fov?, roll?} (radians, mm, about the up axis; yaw: heading of the line of sight, 0 along +Y (Front), π/2 along +X (Left), π (Back), −π/2 (Right); pitch: the eye's elevation, within ±π/2, π/2 = Top; roll defaults to 0, turns the picture clockwise, must be finite and is clamped to ±π; the View angles readout shows these in degrees; up is refused: the up axis comes from the design settings) → camera. The viewport (and the MCP screenshot) moves there. View state: not saved, not an undo step",
),
CommandSpec::new("browser.order", "Order Browser Items", order).icon("reorder").params("folder, component?, order: [keys] (the folder's items in display order)"),
CommandSpec::new("browser.visibility", "Show/Hide", visibility).icon("eye").params(
@@ -196,30 +196,62 @@ fn is_construction(k: &FeatureKind) -> bool {
matches!(k, FeatureKind::ConstructionPlane { .. } | FeatureKind::ConstructionAxis { .. } | FeatureKind::ConstructionPoint { .. })
}
/// The item a key names, or `None` when it names none.
///
/// The rule, the same for showing and for hiding: an exact name wins over a name that only
/// matches it by case, so the body called "Back Lid" is not the sketch called "Back lid"
/// (#6967). Among the exact matches the order is the one there always was: a feature (by id
/// or by name), then a body, then a joint. With no exact match the name is compared without
/// regard to case, as it always was: a feature first, then an origin item.
fn shown_item(s: &Session, key: &str) -> Option<Shown> {
if let Some(f) = s.doc.find_feature(key) {
if matches!(f.kind, FeatureKind::Sketch { .. }) {
// A sketch and a body with exactly the same name, a sketch named after the body it
// makes (#7206): the name is the body's. The browser names a sketch by its id and a
// body only by its name, so the body could not be reached otherwise.
if f.name == key && s.world_state().bodies.iter().any(|b| b.name == key) {
return Some(Shown::Body(key.to_string()));
}
return Some(Shown::Sketch(f.id));
}
if is_construction(&f.kind) {
return Some(Shown::Origin(f.name.clone()));
}
shown_item_exact(s, key).or_else(|| shown_item_ignore_case(s, key))
}
/// The item a key names exactly: a feature, a body or a joint whose name is the key itself.
fn shown_item_exact(s: &Session, key: &str) -> Option<Shown> {
// A feature is found by id or by name, as `find_feature` does, but the name must be the
// key itself here.
let feature = match key.parse::<u64>() {
Ok(id) => s.doc.feature(id).or_else(|| s.doc.features.iter().find(|f| f.name == key)),
Err(_) => s.doc.features.iter().find(|f| f.name == key),
};
if let Some(shown) = feature.and_then(|f| shown_feature(s, f, key)) {
return Some(shown);
}
if s.world_state().bodies.iter().any(|b| b.name == key) {
return Some(Shown::Body(key.to_string()));
}
if let Some(j) = s.doc.assembly.joints.iter().find(|j| j.name == key) {
return Some(Shown::Joint(j.id));
s.doc.assembly.joints.iter().find(|j| j.name == key).map(|j| Shown::Joint(j.id))
}
/// The item a key names when nothing matches it exactly: the name is compared without regard to
/// case, as it always was.
fn shown_item_ignore_case(s: &Session, key: &str) -> Option<Shown> {
if let Some(shown) = s.doc.find_feature(key).and_then(|f| shown_feature(s, f, key)) {
return Some(shown);
}
ORIGIN.iter().find(|o| o.eq_ignore_ascii_case(key)).map(|o| Shown::Origin(o.to_string()))
}
/// The item a feature is: a sketch, or construction geometry by name. A feature that is neither
/// (an extrude, a fillet) is not an item of its own, and the key goes on to the next kind. A
/// sketch that shares its name with a body is the body's (#7206).
fn shown_feature(s: &Session, f: &solidcraft_doc::Feature, key: &str) -> Option<Shown> {
if matches!(f.kind, FeatureKind::Sketch { .. }) {
// A sketch and a body with exactly the same name, a sketch named after the body it
// makes (#7206): the name is the body's. The browser names a sketch by its id and a
// body only by its name, so the body could not be reached otherwise.
if f.name == key && s.world_state().bodies.iter().any(|b| b.name == key) {
return Some(Shown::Body(key.to_string()));
}
return Some(Shown::Sketch(f.id));
}
if is_construction(&f.kind) {
return Some(Shown::Origin(f.name.clone()));
}
None
}
/// A browser folder or group key (`Visibility::hidden_folders`): `c0` or `o:<ids>`, then
/// `/bodies`, `/sketches`, `/construction`, `/joints`, `/canvases` or `/g<group id>`.
fn tree_folder_key(k: &str) -> bool {
@@ -719,6 +751,10 @@ fn view_apply(s: &mut Session, p: &Value) -> Result<Value> {
None => 0.0,
};
let v: solidcraft_doc::NamedView = serde_json::from_value(c.clone()).map_err(|e| bad(cmd, format!("bad camera: {e}")))?;
// Past a pole the same view has other angles; the orbit would snap it back (#6032).
if !(v.pitch.abs() <= std::f64::consts::FRAC_PI_2 + 1e-9) {
return Err(bad(cmd, "camera `pitch` must be within ±π/2 radians (±90°)"));
}
crate::render::Camera { roll: roll.clamp(-std::f64::consts::PI, std::f64::consts::PI), ..camera_of(&v) }
}
// Standard view names come first, as in the browser's Named Views folder.
@@ -1549,6 +1585,43 @@ mod tests {
}
}
/// The View angles popup (#6032) sets the view through `view.apply`: the readout's degrees are
/// the camera's radians, named views read round numbers, and hostile angles never leave a
/// camera past a pole or a NaN behind.
#[test]
fn applying_a_camera_by_view_angles_reads_back_and_refuses_hostile_pitch() {
use crate::render::ViewAngles;
let mut s = Session::default();
for (view, (yaw, pitch)) in
[("front", (0.0, 0.0)), ("left", (90.0, 0.0)), ("right", (-90.0, 0.0)), ("back", (180.0, 0.0)), ("top", (0.0, 90.0))]
{
run(&mut s, "view.apply", json!({"view": view}));
let a = s.camera.expect("a camera for the standard view").view_angles();
assert!((a.yaw - yaw).abs() < 1e-3 && (a.pitch - pitch).abs() < 1e-3 && a.roll == 0.0, "{view}: {a:?}");
}
let typed = ViewAngles { yaw: -30.0, pitch: 15.0, roll: 5.0 };
let cam = crate::render::Camera::default().with_view_angles(typed).expect("finite angles");
let p = json!({"camera": {"target": [0, 0, 0], "yaw": cam.yaw, "pitch": cam.pitch, "roll": cam.roll, "distance": 80}});
run(&mut s, "view.apply", p);
let a = s.camera.expect("the typed camera").view_angles();
assert!((a.yaw - typed.yaw).abs() < 1e-9 && (a.pitch - typed.pitch).abs() < 1e-9 && (a.roll - typed.roll).abs() < 1e-9, "{a:?}");
// Straight down is allowed (90° in radians may round a hair past π/2).
run(&mut s, "view.apply", json!({"camera": {"target": [0, 0, 0], "yaw": 0, "pitch": 90.0_f64.to_radians(), "distance": 80}}));
// Many turns of yaw are the same heading; the readout brings it into range.
run(&mut s, "view.apply", json!({"camera": {"target": [0, 0, 0], "yaw": 1e300, "pitch": 0, "distance": 80}}));
let a = s.camera.expect("a camera").view_angles();
assert!(a.yaw.is_finite() && (-180.0..=180.0).contains(&a.yaw), "{a:?}");
let before = serde_json::to_value(s.camera).unwrap();
for pitch in [json!(2.0), json!(-1.6), json!(1e300), json!(-f64::MAX), json!(f64::NAN), json!("90"), json!(null)] {
let err = s.execute("view.apply", &json!({"camera": {"target": [0, 0, 0], "yaw": 0, "pitch": pitch, "distance": 80}})).unwrap_err();
assert!(err.to_string().contains("camera"), "{pitch}: {err}");
assert_eq!(serde_json::to_value(s.camera).unwrap(), before, "a refused camera leaves the view alone");
}
for yaw in [json!(f64::NAN), json!(f64::INFINITY), json!("0")] {
assert!(s.execute("view.apply", &json!({"camera": {"target": [0, 0, 0], "yaw": yaw, "pitch": 0, "distance": 80}})).is_err(), "{yaw}");
}
}
#[test]
fn named_views_are_saved_renamed_and_deleted() {
let mut s = Session::default();
@@ -1718,6 +1791,41 @@ mod tests {
assert_eq!(s.visibility, before);
}
/// #6967: a body and a sketch whose names differ only in case. The exact name is the one
/// asked for: "Back Lid" is the body, not the sketch called "Back lid". With no exact match
/// the case-insensitive one is the only match, and it is the same rule for showing and for
/// hiding.
#[test]
fn an_exact_body_name_wins_over_a_sketch_that_only_matches_by_case() {
let mut s = Session::default();
let sketch = run(&mut s, "sketch.create", json!({"plane": "XY"}))["sketch"].as_u64().unwrap();
run(&mut s, "sketch.point", json!({"point": [10, 10]}));
run(&mut s, "sketch.finish", json!({}));
run(&mut s, "timeline.rename", json!({"feature": sketch, "name": "Back lid"}));
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 10, "body_name": "Back Lid"}));
assert_eq!(names(&s), vec!["Back Lid".to_string()]);
// Hiding "Back Lid" hides the body, not the sketch that only matches by case.
let r = run(&mut s, "browser.visibility", json!({"items": ["Back Lid"], "visible": false}));
assert_eq!(r["changed"], 1);
assert_eq!(s.visibility.hidden_bodies, vec!["Back Lid".to_string()]);
assert!(s.visibility.hidden_sketches.is_empty(), "the sketch is not the item that changed");
// Showing it again shows the body and leaves the sketch alone.
run(&mut s, "browser.visibility", json!({"items": ["Back Lid"], "visible": true}));
assert!(s.visibility.hidden_bodies.is_empty());
assert!(s.visibility.shown_sketches.is_empty(), "the sketch is not the item that changed");
// With no exact match the case-insensitive one is the only match, and it is the sketch:
// the same rule for showing and for hiding.
run(&mut s, "browser.visibility", json!({"items": ["BACK LID"], "visible": false}));
assert_eq!(s.visibility.hidden_sketches, vec![sketch]);
assert!(s.visibility.hidden_bodies.is_empty());
run(&mut s, "browser.visibility", json!({"items": ["BACK LID"], "visible": true}));
assert!(s.visibility.hidden_sketches.is_empty());
assert_eq!(s.visibility.shown_sketches, vec![sketch]);
}
/// #2219: hiding is a step of its own, so Ctrl+Z brings the body back instead of undoing the
/// command before the hide, and Ctrl+Y hides it again.
#[test]
+53
View File
@@ -11,8 +11,13 @@ use solidcraft_geom::Vec3;
use super::CommandSpec;
use crate::params::{bad, bool_, str_, string_list, vec3};
use crate::schema::component::{EditInPlaceParams, EditInPlaceResult, FinishEditParams, FinishEditResult};
use crate::schema::{TypedContract, output_schema_for};
use crate::{Result, Session};
const EDIT_IN_PLACE_CONTRACT: TypedContract<EditInPlaceParams> = TypedContract::new();
const FINISH_EDIT_CONTRACT: TypedContract<FinishEditParams> = TypedContract::new();
#[path = "component_drag.rs"]
mod drag;
#[path = "component_matrix.rs"]
@@ -43,6 +48,30 @@ pub static COMMANDS: &[CommandSpec] = &[
.icon("component")
.params("bodies: [names] → one new component per body, named after it"),
CommandSpec::new("component.activate", "Activate Component", activate).icon("activate").noundo().params("component: id or name (0 or \"root\" for the design); occurrence?, path?: exact placement used to author shared geometry"),
CommandSpec::new("component.edit_in_place", "Edit in Place", crate::checked!("component.edit_in_place", edit_in_place))
.icon("edit")
.noundo()
.doc_only()
.contract(&EDIT_IN_PLACE_CONTRACT)
.output(output_schema_for::<EditInPlaceResult>)
.params(
"component: id or name of a linked component; path?: its placement (occurrence ids, default its first) → in the app \
window: open the design it links in a tab of its own with the assembly drawn around it (component.finish_edit goes \
back); fails when it is not linked, the assembly has no file yet, something is open or running in it, or the file is \
missing, on a network location not allowed yet or open in another SolidCraft; asked during the agent's turn it opens \
once the turn ends (queued: true); elsewhere it only checks",
),
CommandSpec::new("component.finish_edit", "Finish Edit", crate::checked!("component.finish_edit", finish_edit))
.icon("finish_edit")
.noundo()
.doc_only()
.contract(&FINISH_EDIT_CONTRACT)
.output(output_schema_for::<FinishEditResult>)
.params(
"no parameters → in the app window: go back from the linked design edited in place to its assembly, which reads it again; \
fails while the design has unsaved changes (run file.save first) or something is open in it; asked during the agent's \
turn it finishes once the turn ends (queued: true); elsewhere nothing changes",
),
CommandSpec::new("component.list", "List Components", list).icon("list").noundo().params(
"compact?: bool (counts of bodies, features, sketches and construction planes instead of their names; occurrences leave out \
identity transforms; children as occurrence ids); bodies?: bool (with compact: body names, not their count)",
@@ -193,6 +222,30 @@ fn from_bodies(s: &mut Session, p: &Value) -> Result<Value> {
transfer::from_bodies(s, p)
}
/// The app window opens the edit in place from what this returns; here the component and its
/// placement are only checked.
fn edit_in_place(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "component.edit_in_place";
let id = component(s, p, "component", cmd)?;
if !s.doc.links.contains_key(&id) {
return Err(bad(cmd, "that component is not linked to a design"));
}
let path = match p.get("path") {
Some(_) => serde_json::from_value::<Vec<u64>>(p["path"].clone()).map_err(|_| bad(cmd, "`path` must be occurrence ids"))?,
None => s.doc.first_path(id),
};
if s.occurrence_placement(&path).map_err(|e| bad(cmd, e.to_string()))?.component != id {
return Err(bad(cmd, "`path` is a placement of another component"));
}
serde_json::to_value(EditInPlaceResult { component: id, path, ..Default::default() }).map_err(|e| crate::EngineError::Other(e.to_string()))
}
/// The app window finishes an edit in place (it knows the part's tab and its assembly); here
/// there is none, so nothing changes.
fn finish_edit(_s: &mut Session, _p: &Value) -> Result<Value> {
serde_json::to_value(FinishEditResult::default()).map_err(|e| crate::EngineError::Other(e.to_string()))
}
fn activate(s: &mut Session, p: &Value) -> Result<Value> {
let id = component(s, p, "component", "component.activate")?;
let path = if p.get("path").is_some() || p.get("occurrence").is_some() {
+8 -1
View File
@@ -1670,6 +1670,11 @@ fn redefine(s: &mut Session, p: &Value) -> Result<Value> {
if let Some(e) = trial.model.result(id).and_then(|r| r.error.clone()) {
return Err(EngineError::Other(e));
}
// What this edit rebuilt: the trial computed the edited feature and the features after it. The
// session's evaluation below only takes those results from what the trial kept, so its own
// counters read as "nothing was rebuilt" (#5694).
let rebuilt = trial.model.last_recomputed;
let reused = trial.model.last_restored;
let original_ids: std::collections::BTreeSet<u64> = s.doc.features.iter().map(|feature| feature.id).collect();
let added_ids: std::collections::BTreeSet<u64> =
trial.doc.features.iter().filter(|feature| !original_ids.contains(&feature.id)).map(|feature| feature.id).collect();
@@ -1711,7 +1716,9 @@ fn redefine(s: &mut Session, p: &Value) -> Result<Value> {
if let Some(e) = s.model.result(id).and_then(|r| r.error.clone()) {
return Err(EngineError::Other(e));
}
Ok(json!({"feature": id, "recomputed": s.model.last_recomputed, "restored": s.model.last_restored}))
// Report the trial's rebuild, plus anything the session still had to compute itself (a kept
// result its budget dropped); `s.model`'s own counters would only report the reuse (#5694).
Ok(json!({"feature": id, "recomputed": rebuilt + s.model.last_recomputed, "restored": reused}))
}
fn dependents(s: &mut Session, p: &Value) -> Result<Value> {
+52 -2
View File
@@ -185,7 +185,8 @@ fn redefining_a_blend_replaces_persistent_edge_selection_and_survives_resize() {
/// A redefine computes the features after the edited one once: its trial's results are kept
/// for the session's own evaluation, though the cache holds only the last state (a large
/// design's).
/// design's). The reply reports that one rebuild (#5694): a session that had to compute the
/// features again would count them twice.
#[test]
fn redefining_computes_the_later_features_once() {
let mut s = Session::default();
@@ -196,11 +197,29 @@ fn redefining_computes_the_later_features_once() {
*s.model.cache.lock().unwrap() = solidcraft_doc::EvalCache::with_budget(1);
let reply =
run(&mut s, "timeline.redefine", json!({"feature": "Base", "command": "solid.box", "params": {"length": 25, "width": 10, "height": 5}}));
assert_eq!(reply["recomputed"], 0, "{reply}");
assert_eq!((reply["recomputed"].as_u64(), reply["restored"].as_u64()), (Some(4), Some(0)), "{reply}");
let volume = run(&mut s, "inspect.measure", json!({}))["total"]["volume_mm3"].as_f64().unwrap();
assert!((volume - (25.0 * 10.0 * 5.0 + 3.0 * 125.0)).abs() < 1e-6, "{volume}");
}
/// #5694: the reply reports what the redefine rebuilt — the edited feature and the features
/// after it — not the session's reuse of the trial's own results, which read as "nothing was
/// rebuilt" and did not match what the same change reports through `timeline.edit`.
#[test]
fn redefining_reports_the_features_it_rebuilt() {
let mut s = Session::default();
run(&mut s, "solid.box", json!({"length": 40, "width": 40, "height": 20, "center": [0, 0, 10], "name": "Block"}));
run(&mut s, "solid.hole", json!({"position": [0, 0, 20], "diameter": 6, "depth": 12, "name": "H"}));
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 5, "center": [30, 0, 2.5], "operation": "new", "name": "Other"}));
let reply = run(
&mut s,
"timeline.redefine",
json!({"feature": "H", "command": "solid.hole",
"params": {"position": [0, 0, 20], "type": "counterbore", "diameter": 6, "depth": 12, "cb_diameter": 10, "cb_depth": 4}}),
);
assert_eq!((reply["recomputed"].as_u64(), reply["restored"].as_u64()), (Some(2), Some(0)), "{reply}");
}
#[test]
fn redefining_preserves_body_names_participants_and_marker_without_temporary_features() {
let mut s = Session::default();
@@ -1282,3 +1301,34 @@ fn select_same_look_uses_resolved_looks_without_document_history_edits_and_refus
assert!(std::sync::Arc::ptr_eq(&doc, &s.doc));
assert_eq!(history, (s.undo.len(), s.redo.len(), s.evaluations));
}
/// A body changed by a few hundred features in a row whose names nothing asks for, then
/// filleted: reordering or moving an earlier feature evaluates them all again, and the fillet
/// finds its edge by the names of the body before it, which are worked out from the body before
/// that, and so on back to the start. That walk recursed once per feature and overflowed the
/// window thread's stack (1 MB on Windows), ending the app (#7587, #7926). On a thread with that
/// stack, both moves are made.
#[test]
fn a_move_before_a_long_history_of_one_body_fits_a_window_threads_stack() {
let mut s = Session::default();
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 10, "body_name": "Peg"}));
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 10, "corner": [50, 0, 0], "body_name": "Other"}));
for i in 0..300 {
run(&mut s, "solid.move", json!({"bodies": ["Peg"], "translate": [0, 0, if i % 2 == 0 { 1 } else { -1 }]}));
}
run(&mut s, "solid.fillet", json!({"body": "Peg", "radius": 1, "edges": [[5, 0, 10]]}));
let other = s.doc.features.get(1).map(|f| f.id).unwrap();
let fillet = s.doc.features.last().map(|f| f.id).unwrap();
let moved = std::thread::Builder::new()
.stack_size(1024 * 1024)
.spawn(move || {
run(&mut s, "timeline.reorder", json!({"feature": other, "position": 0}));
assert!(s.model.result(fillet).is_some_and(|r| r.error.is_none()), "the fillet is made after the reorder");
run(&mut s, "timeline.move_many", json!({"features": [other], "position": 2}));
assert_eq!(s.doc.features.get(1).map(|f| f.id), Some(other));
assert!(s.model.result(fillet).is_some_and(|r| r.error.is_none()), "the fillet is made after the move");
})
.unwrap()
.join();
assert!(moved.is_ok());
}
+16 -1
View File
@@ -181,9 +181,24 @@ type FacePick = (std::sync::Arc<Mesh>, u32, f64, String);
/// The face under a point of `only` (any body when `None`). Where faces of several bodies are
/// equally near (bodies touching flush), the pick is ambiguous: `Err` names those bodies.
/// A pick of the running command was resolved against the placed model, so the body under it
/// wins: a body that only shares its place in the model is not in the way (#419). A named
/// body still wins over that.
fn face_at_in(s: &Session, p: Vec3, only: Option<&str>) -> std::result::Result<Option<FacePick>, Vec<String>> {
let st = s.model.state();
face_at_state(&st, p, only)
match (crate::frames::picked(p), only) {
(Some(names), None) if names.len() > 1 => Err(model_names(&st, &names)),
(Some(names), None) => {
let under = names.first().and_then(|n| st.bodies.iter().find(|b| b.definition_name() == n.as_str()).map(|b| b.name.clone()));
face_at_state(&st, p, under.as_deref())
}
(_, only) => face_at_state(&st, p, only),
}
}
/// The names the model gives the bodies a pick met.
fn model_names(st: &solidcraft_doc::ModelState, names: &[String]) -> Vec<String> {
names.iter().map(|n| st.bodies.iter().find(|b| b.definition_name() == n.as_str()).map(|b| b.name.clone()).unwrap_or_else(|| n.clone())).collect()
}
pub(super) fn face_at_state(st: &solidcraft_doc::ModelState, p: Vec3, only: Option<&str>) -> std::result::Result<Option<FacePick>, Vec<String>> {
+38
View File
@@ -126,6 +126,44 @@ fn face_join_of_a_step_import_keeps_all_32_neighbours_unchanged() {
assert_eq!(targets, &["Wall"]);
}
/// #419: a face pick is resolved against the placed state: a leaf of an assembly that its
/// joint swung away does not make the pick ambiguous, even though both leaves are built at
/// the same local place. The pick lands on the leaf that is shown there.
#[test]
fn a_face_pick_on_an_assembly_leaf_is_resolved_where_the_leaf_is_shown() {
let mut s = Session::default();
for leaf in ["Leaf A", "Leaf B"] {
run(&mut s, "component.activate", json!({"component": "root"}));
run(&mut s, "component.create", json!({"name": leaf}));
run(&mut s, "solid.box", json!({"length": 40, "width": 30, "height": 3, "corner": [0, 0, 0]}));
run(&mut s, "solid.cylinder", json!({"base": [0, 33, 4], "axis": [1, 0, 0], "radius": 4, "height": 40, "operation": "new"}));
}
run(&mut s, "component.activate", json!({"component": "root"}));
run(&mut s, "occurrence.ground", json!({"occurrence": "Leaf A:1", "grounded": true}));
run(
&mut s,
"joint.create",
json!({
"type": "revolute",
"name": "Hinge",
"a": {"occurrence": "Leaf A:1", "circle": [1, 37, 4]},
"b": {"occurrence": "Leaf B:1", "circle": [1, 37, 4]},
"limits": [["0 deg", "180 deg"]]
}),
);
run(&mut s, "joint.drive", json!({"joint": "Hinge", "value": 60}));
// Leaf B is swung 60° away, so the pick is on Leaf A's top face, where it is shown.
let result = run(
&mut s,
"solid.extrude",
json!({"face": [13.002403831300967, 9.849781594495369, 3.0], "distance": "10 mm", "direction": "positive", "operation": "join"}),
);
assert_eq!(result["changed_bodies"], json!(["Body1"]));
let state = s.model.state();
let volume = solidcraft_kernel::measure(&state.body("Body1").unwrap().body).unwrap().volume;
assert!((volume - 15_600.0).abs() < 1e-6, "{volume}");
}
/// #1349: a profile sketched on a body's face joins that body, and leaves alone a neighbour
/// whose face it lies on too: a rib on the side of a bracket, drawn down over the motor the
/// bracket sits on, welded the motor in (a join that ran for minutes on the imported motor and
+31 -1
View File
@@ -56,7 +56,7 @@ pub static COMMANDS: &[CommandSpec] = &[
CommandSpec::new("file.export", "Export", export)
.icon("export")
.noundo()
.params("path; format?: stl|stla|obj|step|3mf|3mf-tagged|urdf|json (default from extension; 3mf-tagged: 3MF whose triangles carry their B-rep face, at full precision, for meshing and analysis tools; docs/formats/3mf-face-tags.md; urdf: the whole assembly as a robot, with STL meshes written next to it; docs/urdf.md); bodies?: [names] (JSON and URDF export the complete design); urdf only: mesh_prefix? (before each mesh file name, e.g. package://robot/meshes/), effort? (default 1000), velocity? (default 10); quality?: standard|fine|finest (STL, OBJ and 3MF: how closely the mesh follows curved faces, a chord tolerance of 2e-4, 5e-5 or 1e-5 of each body's size; default standard)"),
.params("path; format?: stl|stla|obj|step|3mf|3mf-tagged|urdf|json (default from extension; 3mf-tagged: 3MF whose triangles carry their B-rep face, at full precision, for meshing and analysis tools; docs/formats/3mf-face-tags.md; obj: the colours of the bodies go in a material library (`.mtl`) written next to the mesh file; urdf: the whole assembly as a robot, with STL meshes written next to it; docs/urdf.md); bodies?: [names] (JSON and URDF export the complete design); urdf only: mesh_prefix? (before each mesh file name, e.g. package://robot/meshes/), effort? (default 1000), velocity? (default 10); quality?: standard|fine|finest (STL, OBJ and 3MF: how closely the mesh follows curved faces, a chord tolerance of 2e-4, 5e-5 or 1e-5 of each body's size; default standard)"),
CommandSpec::new("file.save_mesh", "Save As Mesh", save_mesh)
.at("INSERT", "FILES")
.icon("mesh_export")
@@ -601,6 +601,10 @@ fn mesh_quality(p: &Value, cmd: &str) -> Result<solidcraft_io::MeshQuality> {
}
fn export_to(s: &Session, path: &str, format: Format, bodies: &[String], quality: solidcraft_io::MeshQuality) -> Result<Value> {
if format == Format::Obj {
// The colours of the bodies go in a material library beside the mesh file.
return export_obj(s, path, bodies, quality);
}
let name = std::path::Path::new(path).file_stem().map(|x| x.to_string_lossy().to_string()).unwrap_or_else(|| s.doc.name.clone());
// A design with components exports as a STEP assembly; otherwise bodies as placed.
let bytes = if format == Format::Design {
@@ -629,6 +633,32 @@ fn export(s: &mut Session, p: &Value) -> Result<Value> {
export_to(s, path, format, &string_list(p, "bodies"), quality)
}
/// The OBJ export: the mesh file and the material library beside it, with the colours of the
/// bodies. Every path is checked before anything is written; the library goes first and the
/// mesh file last, so a mesh file never names a library that is not there.
fn export_obj(s: &Session, path: &str, bodies: &[String], quality: solidcraft_io::MeshQuality) -> Result<Value> {
let mtl_path = std::path::Path::new(path).with_extension("mtl");
let mtl_name = mtl_path.file_name().map(|x| x.to_string_lossy().to_string()).unwrap_or_else(|| String::from("model.mtl"));
let files = solidcraft_io::export_obj(&s.doc.painted(&s.world_state()), bodies, &mtl_name, quality)?;
let mut targets: Vec<(String, &[u8])> = Vec::new();
if !files.mtl.is_empty() {
targets.push((mtl_path.to_string_lossy().to_string(), files.mtl.as_bytes()));
}
targets.push((path.to_string(), files.obj.as_bytes()));
for (t, _) in &targets {
solidcraft_io::vfs::check(t).map_err(|e| EngineError::Other(format!("{t}: {e}")))?;
}
let mut written: Vec<String> = Vec::new();
for (t, bytes) in &targets {
if let Err(e) = solidcraft_io::vfs::write(t, bytes) {
let before = if written.is_empty() { "none".to_string() } else { written.join(", ") };
return Err(EngineError::Other(format!("{t}: {e} (this file may be incomplete; written before it: {before})")));
}
written.push(t.clone());
}
Ok(json!({"path": path, "bytes": files.obj.len(), "format": format!("{:?}", Format::Obj), "files": written}))
}
/// The assembly as a URDF and its meshes next to it (docs/urdf.md). Every path is checked before
/// anything is written; the meshes go first and the `.urdf` last.
fn export_urdf(s: &Session, path: &str, p: &Value) -> Result<Value> {
+4 -1
View File
@@ -6,7 +6,7 @@
//! nothing: properties are no geometry.
use serde_json::{Map, Value, json};
use solidcraft_doc::metadata::{self, MAX_KEYS, Owner};
use solidcraft_doc::metadata::{self, BOM_TYPE, MAX_KEYS, Owner};
use super::CommandSpec;
use crate::params::{bad, str_};
@@ -49,6 +49,9 @@ fn set(s: &mut Session, p: &Value) -> Result<Value> {
let mut next = s.doc.metadata.clone();
let mut changed = Vec::new();
for (key, value) in entries {
if key == BOM_TYPE {
return Err(bad(cmd, "`bom_type` is a component's part property: set it with component.metadata.set"));
}
if next.set(Owner::Design, key, value.clone()).map_err(|e| bad(cmd, e.to_string()))? {
changed.push(key.to_string());
}
+1
View File
@@ -39,6 +39,7 @@ pub(crate) use face::{FaceRefForm, face_ref_form};
pub(crate) use features::profiles as feature_profiles;
pub(crate) use features::{EdgeRefForm, axis_dir_form, edge_ref_form, sketch_key};
pub use features::{auto_operation, extrude_reach};
pub use sketch::dimension_roles;
pub use sketch_import::drawing_import_command;
pub use sketch_modify::{extend_arc_preview, extend_preview, trim_piece};
pub use view_dxf::sketch::exportable as view_dxf_exportable;
+1 -7
View File
@@ -320,12 +320,6 @@ fn triple(value: &Value, command: &str) -> Result<[f64; 3]> {
fn number(value: &Value, command: &str) -> Result<f64> {
value.as_f64().filter(|n| n.is_finite()).ok_or_else(|| bad(command, "missing finite authored value"))
}
fn srgb(v: f64) -> u8 {
let v = v.clamp(0.0, 1.0);
let encoded = if v <= 0.0031308 { 12.92 * v } else { 1.055 * v.powf(1.0 / 2.4) - 0.055 };
(encoded * 255.0).round().clamp(0.0, 255.0) as u8
}
pub(super) fn apply_appearance(s: &mut Session, params: &Value) -> Result<Value> {
let command = "render.library.appearance.apply";
let input: Appearance = serde_json::from_value(params.clone()).map_err(|e| bad(command, e.to_string()))?;
@@ -339,7 +333,7 @@ pub(super) fn apply_appearance(s: &mut Session, params: &Value) -> Result<Value>
let value = item("surfaces", &input.id, command)?;
let lo = triple(&value["base_linear_low"], command)?;
let hi = triple(&value["base_linear_high"], command)?;
let color = std::array::from_fn::<_, 3, _>(|i| srgb((lo[i] + hi[i]) * 0.5));
let color = std::array::from_fn::<_, 3, _>(|i| crate::geom::srgb::encode8((lo[i] + hi[i]) * 0.5));
(
value,
json!({"color":color,"opacity":1.0,"pbr":{"metallic":value["metallic"],"roughness":value["roughness"],"dielectric_ior":1.5}}),
@@ -145,6 +145,8 @@ fn uniform_appearance_requires_acknowledged_projection_and_preserves_physical_da
assert_eq!(s.doc.to_json(), before);
let reply = s.execute("render.library.appearance.apply", &json!({"id":"SURF-001","variant":"uniform_opaque","bodies":["Target"]})).unwrap();
assert_eq!(reply["engineering_properties_unchanged"], true);
// The middle of SURF-001's linear range, as sRGB codes.
assert_eq!(reply["appearance"]["color"], json!([196, 202, 207]));
let after: Value = serde_json::from_str(&s.doc.to_json()).unwrap();
assert_eq!(after["user_materials"], before_value["user_materials"]);
assert_eq!(s.undo.len(), undo + 1);
+83 -12
View File
@@ -15,6 +15,7 @@ mod dimensioned;
mod drag;
#[path = "sketch_face.rs"]
pub(super) mod face;
pub use dimensioned::dimension_roles;
use dimensioned::draw as draw_dimensioned;
use drag::drag_entity;
@@ -51,7 +52,7 @@ pub static COMMANDS: &[CommandSpec] = &[
.params(concat!("points: [[x,y] | \"l1.end\" | {at, ref}…] (x and y each a number or an expression over the design's parameters, \"W / 2\": such a point is fixed where it comes to and follows the parameters; likewise wherever a point argument also takes a point id), closed?: bool, construction?: bool, ids?: [..], infer?: bool (add horizontal/vertical)", connect_doc!(), created_doc!())),
CommandSpec::new("sketch.draw.dimensioned", "Draw Dimensioned Sketch Geometry", draw_dimensioned).icon("dimension")
.enabled(in_sketch)
.params(concat!("command: sketch creation command, params: object, dimensions: object of role to numeric or expression value, or `name = expression` (also `#name = expression`), which defines the user parameter `name` as sketch.dimension does (the reply's `defined` lists the names); creates geometry and all driving dimensions atomically in one undo step", created_doc!())),
.params(concat!("command: sketch creation command, params: object, dimensions: object of role to numeric or expression value, or `name = expression` (also `#name = expression`), which defines the user parameter `name` as sketch.dimension does (the reply's `defined` lists the names) (optional with as_drawn or locate), as_drawn?: bool (also dimension every other role of the shape at its size as drawn; a radius or diameter given takes the place of the other, a circle otherwise takes its diameter, and a size the sketch already determines, such as the angle of a line inferred horizontal, is left out), locate?: bool (then place the shape from the sketch origin until nothing of it is left free: horizontal and vertical distances from the origin to its points, centres first, each kept only where it removes freedom, so a shape anchored to the origin or to placed geometry gets none; a point on an axis goes onto that axis instead of a 0 distance; the reply's located lists them); creates geometry and all driving dimensions atomically in one undo step", created_doc!())),
CommandSpec::new("sketch.rectangle.two_point", "2-Point Rectangle", rect_two_point)
.at("SKETCH", "CREATE")
.icon("rect")
@@ -126,7 +127,7 @@ pub static COMMANDS: &[CommandSpec] = &[
.params(concat!("p0, p1: overall ends, width", connect_doc!(), created_doc!())),
CommandSpec::new("sketch.point", "Point", draw_point).at("SKETCH", "CREATE").icon("point").enabled(in_sketch).params(concat!("point: [x,y] (each a number or an expression over the design's parameters: the point is then fixed where it comes to and follows them) or a snap: \"mid:<line>\" (held at the line's midpoint), \"on:<curve>:x,y\" (on the curve near x,y), {vertex: [x,y,z]} or {on_edge: [x,y,z]} of the model; id?", connect_doc!(), created_doc!())),
CommandSpec::new("sketch.dimension", "Sketch Dimension", dimension).at("SKETCH", "CREATE").icon("dimension").key("D").enabled(in_sketch).params(
"entities: [refs] (a line midpoint is \"mid:line_id\"), type?: auto|distance|horizontal|distance_x|vertical|distance_y|length|radius|diameter|angle, value?: number or expression (default: current; a bare number is in the design's units, e.g. 2 means 2 in in an inch design; give a unit such as \"50 mm\" to override), or `name = expression` (e.g. \"width = 40\"; also `#name = expression`), which adds the user parameter `name` with that expression and dimensions with `name` (refused when the name is taken or reserved; the reply's `defined` names it); text_at?: [x, y]. Two points or a line off the axes: with auto, text_at across from them is the distance between them, above or below them horizontal, beside them vertical. Two midpoints: placing text above or below their bounding box measures horizontally, beside it vertically. Two lines: the angle between them (acute, or 180° − it when the value is nearer that) unless text_at picks a sector. A line and a circle or arc: the distance from the line to its edge (the gap, or how far the edge reaches past a line that cuts it; 0 is tangent); dimension the centre point for the distance to the centre. A point and a circle or arc: the distance from the point to its edge (or how far within it a point inside lies). Two circles or arcs: the gap between their edges (or how far they overlap when they cross, or the narrowest gap between them when one lies inside the other); dimension their centre points for the distance between centres. An arc and one of its end points: the arc's length (type arc_length does it from the arc alone). A dimension the sketch already determines is refused (naming what determines it); if_redundant?: \"driven\" places it as a driven (reference) dimension instead. scale_sketch?: bool (the dimension tool sends true): when this is the sketch's first length dimension and nothing in the sketch fixes a size (no other driving length dimension, nothing fixed or projected), the whole sketch scales about its origin to the value instead of distorting. Returns measured in unit (mm or deg), and scaled: the factor when the sketch was scaled",
"entities: [refs] (a line midpoint is \"mid:line_id\"), type?: auto|distance|horizontal|distance_x|vertical|distance_y|length|radius|diameter|angle, value?: number or expression (default: current; a bare number is in the design's units, e.g. 2 means 2 in in an inch design; give a unit such as \"50 mm\" to override), or `name = expression` (e.g. \"width = 40\"; also `#name = expression`), which adds the user parameter `name` with that expression and dimensions with `name` (refused when the name is taken or reserved; the reply's `defined` names it); text_at?: [x, y]. Two points or a line off the axes: with auto, text_at across from them is the distance between them, above or below them horizontal, beside them vertical. Two midpoints: placing text above or below their bounding box measures horizontally, beside it vertically. Two lines: the angle between them (acute, or 180° − it when the value is nearer that) unless text_at picks a sector. A line and a circle or arc: the distance from the line to its edge (the gap, or how far the edge reaches past a line that cuts it; 0 is tangent); dimension the centre point for the distance to the centre. A point and a circle or arc: the distance from the point to its edge (or how far within it a point inside lies). Two circles or arcs: the gap between their edges (or how far they overlap when they cross, or the narrowest gap between them when one lies inside the other), or the centre-to-centre distance when they are the two caps of a slot. An arc and one of its end points: the arc's length (type arc_length does it from the arc alone). A dimension the sketch already determines is refused (naming what determines it); if_redundant?: \"driven\" places it as a driven (reference) dimension instead. scale_sketch?: bool (the dimension tool sends true): when this is the sketch's first length dimension and nothing in the sketch fixes a size (no other driving length dimension, nothing fixed or projected), the whole sketch scales about its origin to the value instead of distorting. Returns measured in unit (mm or deg), and scaled: the factor when the sketch was scaled",
),
CommandSpec::new("sketch.constraint.horizontal_vertical", "Horizontal/Vertical", c_horizontal_vertical)
.at("SKETCH", "CONSTRAINTS")
@@ -1159,14 +1160,24 @@ fn rect_rounded(s: &mut Session, p: &Value) -> Result<Value> {
}
let mut scratch = s.scratch();
let mut out = scratch.execute("sketch.rectangle.two_point", &rect)?;
let corners: Vec<Value> = ["bottom_left", "bottom_right", "top_right", "top_left"]
.iter()
.filter_map(|k| out["corners"].get(*k).filter(|v| v.is_string()).cloned())
.collect();
if corners.len() != 4 {
return Err(bad(cmd, "the rectangle's corners are missing"));
// The fillet rounds each corner by the two sides meeting there, not by the corner point: a
// corner that lands on another curve's end is shared with it, and rounding the point would
// weld the two together, leaving the corner on three curves (#7878).
let sides: Vec<String> =
["bottom", "right", "top", "left"].iter().filter_map(|k| out["sides"].get(*k).and_then(Value::as_str).map(str::to_string)).collect();
if sides.len() != 4 {
return Err(bad(cmd, "the rectangle's sides are missing"));
}
let mut fillet = json!({"points": corners, "radius": r_expr});
let (bottom, right, top, left) = (&sides[0], &sides[1], &sides[2], &sides[3]);
let mut fillet = json!({
"points": [
{"a": bottom, "b": left},
{"a": bottom, "b": right},
{"a": right, "b": top},
{"a": top, "b": left},
],
"radius": r_expr,
});
if let Some(sketch) = p.get("sketch") {
fillet["sketch"] = sketch.clone();
}
@@ -2581,9 +2592,20 @@ fn dimension(s: &mut Session, p: &Value) -> Result<Value> {
let round = |c: usize| sk.center(c).zip(sk.radius(c)).ok_or_else(|| bad(cmd, "cannot dimension that curve"));
let ((ca, ra), (cb, rb)) = (round(a)?, round(b)?);
let d = ca.dist(cb);
let circles = TwoCircles::of(d, ra, rb);
let gap = circles.gap(d, ra, rb).max(0.0);
(ConstraintKind::CircleCircleDistance { a, b, value: gap, circles }, gap)
// A slot's two arc caps: the centre-to-centre distance (the slot's length), not
// the gap between the inner edges (#7464).
if (ty == "auto" || ty == "distance") && slot_caps(sk, a, b) {
let centre = |c: usize| match sk.curves.get(c).map(|x| &x.kind) {
Some(CurveKind::Arc { c, .. }) => Some(*c),
_ => None,
};
let (pa, pb) = centre(a).zip(centre(b)).ok_or_else(|| bad(cmd, "cannot dimension that curve"))?;
(ConstraintKind::Distance { p: pa, q: pb, value: d }, d)
} else {
let circles = TwoCircles::of(d, ra, rb);
let gap = circles.gap(d, ra, rb).max(0.0);
(ConstraintKind::CircleCircleDistance { a, b, value: gap, circles }, gap)
}
}
_ => return Err(bad(cmd, "cannot dimension that combination of entities")),
};
@@ -2785,6 +2807,55 @@ fn arc_len(sk: &Sketch, c: usize) -> Option<f64> {
}
}
/// Whether two arcs are the two caps of a straight slot: each shares its end points with the same
/// two lines (the slot's sides), and those sides are tangent to both caps. The distance between
/// the caps is then their centre-to-centre distance, not the gap between their inner edges (#7464).
fn slot_caps(sk: &Sketch, a: usize, b: usize) -> bool {
if a == b {
return false;
}
let arc = |c: usize| match sk.curves.get(c).map(|x| &x.kind) {
Some(CurveKind::Arc { c, a, b }) => sk.point(*c).map(|centre| (centre, *a, *b)),
_ => None,
};
let (Some((ca, a0, a1)), Some((cb, b0, b1))) = (arc(a), arc(b)) else {
return false;
};
// Count the sides that run between the two caps and are tangent to both. Tangency keeps two
// arcs joined by two lines but bulging inward out of it: for those, centre distance plus both
// radii is not the overall length.
let mut sides = 0;
for c in &sk.curves {
let CurveKind::Line { a: la, b: lb } = &c.kind else {
continue;
};
let on = |p: &usize, (x, y): (usize, usize)| *p == x || *p == y;
let (pa, pb) = if on(la, (a0, a1)) && on(lb, (b0, b1)) {
(*la, *lb)
} else if on(lb, (a0, a1)) && on(la, (b0, b1)) {
(*lb, *la)
} else {
continue;
};
if tangent_at(sk, pa, pb, ca) && tangent_at(sk, pb, pa, cb) {
sides += 1;
}
}
sides >= 2
}
/// Whether the line from `p` to `q` is tangent to the circle about `centre` at `p`: its direction
/// is perpendicular to the radius from `centre` to `p`.
fn tangent_at(sk: &Sketch, p: usize, q: usize, centre: Vec2) -> bool {
let (Some(p), Some(q)) = (sk.point(p), sk.point(q)) else {
return false;
};
match ((q - p).normalized(), (p - centre).normalized()) {
(Some(d), Some(r)) => d.dot(r).abs() < 1e-9,
_ => false,
}
}
/// The angle dimension between two lines whose sector contains `t` (the text position): returns
/// the constraint and the current value of that sector angle.
fn angle_by_sector(a: usize, b: usize, (a0, a1): (Vec2, Vec2), (b0, b1): (Vec2, Vec2), t: Vec2) -> Option<(ConstraintKind, f64)> {

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