@things-factory/figure-ui 10.1.194 → 10.1.195
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/modeller/editor-styles.ts +10 -3
- package/client/modeller/editor.ts +61 -47
- package/client/modeller/figure-fasten-dialog.ts +11 -5
- package/client/modeller/refusal-teller.ts +8 -0
- package/dist-client/modeller/editor-styles.js +10 -3
- package/dist-client/modeller/editor-styles.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +18 -9
- package/dist-client/modeller/editor.js +62 -46
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-fasten-dialog.d.ts +3 -3
- package/dist-client/modeller/figure-fasten-dialog.js +11 -5
- package/dist-client/modeller/figure-fasten-dialog.js.map +1 -1
- package/dist-client/modeller/refusal-teller.d.ts +8 -0
- package/dist-client/modeller/refusal-teller.js +7 -0
- package/dist-client/modeller/refusal-teller.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/test/align.test.ts +13 -5
- package/test/browser/editing.check.mjs +9 -13
- package/test/browser/links.check.mjs +36 -22
- package/test/browser/modeller-page.js +48 -4
- package/test/browser/product-page.js +6 -0
- package/test/browser/props.check.mjs +2 -2
- package/translations/en.json +3 -5
- package/translations/es.json +3 -5
- package/translations/ja.json +3 -5
- package/translations/ko.json +3 -5
- package/translations/ms.json +3 -5
- package/translations/zh.json +3 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/figure-ui",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.195",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"@things-factory/setting-base": "^10.1.192",
|
|
49
49
|
"three": "^0.185.1"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "e22e6dec8be22ba1d8db7bf511f3bacee721ff8f"
|
|
52
52
|
}
|
package/test/align.test.ts
CHANGED
|
@@ -95,13 +95,21 @@ test('a tilted part is told it touches by a point or an edge, a ball by its lowe
|
|
|
95
95
|
assert.ok(!/기울|기운/.test(ko['figure.text.aligned-extreme-floor'] + ko['figure.text.align-to-floor-extreme']), 'a ball is not said to be tilted')
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
/*
|
|
99
|
-
|
|
98
|
+
/*
|
|
99
|
+
User 2026-10-19: the size drag's refusal told the face kept while dragging and the one written, and was not understood.
|
|
100
|
+
One line, why only -- attached turned, or tilted -- in every language; the way on is the notice's button.
|
|
101
|
+
*/
|
|
102
|
+
test('the size drag\'s refusal is one line saying why, in every language', () => {
|
|
100
103
|
for (const lang of ['en', 'ja', 'ko', 'ms', 'zh', 'es']) {
|
|
101
104
|
const t = JSON.parse(read(`../translations/${lang}.json`))
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
for (const key of ['figure.text.gizmo-size-turned-fastening', 'figure.text.gizmo-size-tilted']) {
|
|
106
|
+
assert.ok(t[key]?.includes('{part}'), `${lang} ${key}`)
|
|
107
|
+
assert.ok(!t[key].includes('{extreme}'), `${lang} ${key}: no face kept is told`)
|
|
108
|
+
assert.equal(t[key].split(/[.。]\s*/).filter(Boolean).length, 1, `${lang} ${key}: one sentence`)
|
|
109
|
+
}
|
|
110
|
+
assert.ok(t['figure.button.to-size-fields'], lang)
|
|
104
111
|
}
|
|
105
112
|
const ko = JSON.parse(read('../translations/ko.json'))
|
|
106
|
-
assert.equal(ko['figure.
|
|
113
|
+
assert.equal(ko['figure.text.gizmo-size-turned-fastening'], '{part} 부품은 돌려 붙어 있어 끌어서 크기를 바꿀 수 없습니다.')
|
|
114
|
+
assert.equal(ko['figure.button.to-size-fields'], '크기 칸으로')
|
|
107
115
|
})
|
|
@@ -532,31 +532,27 @@ describe('the recipe catalog says nothing where a template has no guide', () =>
|
|
|
532
532
|
})
|
|
533
533
|
|
|
534
534
|
/*
|
|
535
|
-
The size gizmo
|
|
536
|
-
|
|
535
|
+
The size gizmo withheld from a tilted part says why in one line (user 2026-10-19: the faces kept while dragging and
|
|
536
|
+
when written were not understood), as a notice, not the error's red. The page loads no translations; the sentence is
|
|
537
|
+
given words here, so the part it names can be read.
|
|
537
538
|
*/
|
|
538
|
-
describe('the size gizmo withheld from a tilted part says
|
|
539
|
+
describe('the size gizmo withheld from a tilted part says why, in one line, as a notice', () => {
|
|
539
540
|
before(async () => {
|
|
540
541
|
await mount('box', 'tilted-ceiling')
|
|
541
|
-
await read(() =>
|
|
542
|
-
editing.words({
|
|
543
|
-
'figure.text.gizmo-size-turned-fastening': '{part} is tilted: its size is typed, keeping {extreme}',
|
|
544
|
-
'figure.label.kept-extreme-ceiling': 'its highest point',
|
|
545
|
-
'figure.label.kept-extreme-floor': 'its lowest point'
|
|
546
|
-
})
|
|
547
|
-
)
|
|
542
|
+
await read(() => editing.words({ 'figure.text.gizmo-size-tilted': '{part} is tilted, so its size cannot be dragged.' }))
|
|
548
543
|
await pick('box')
|
|
549
544
|
})
|
|
550
545
|
after(() => read(() => editing.words(null)))
|
|
551
546
|
|
|
552
|
-
test('hung from the ceiling, the tooltip and the refusal of R
|
|
547
|
+
test('hung from the ceiling, the tooltip and the refusal of R say the same line; nothing is said of the faces it keeps', async () => {
|
|
553
548
|
const resize = (await read(() => editing.tools())).find(t => t.label === 'figure.button.gizmo-scale')
|
|
554
549
|
assert.equal(resize.disabled, true, 'not offered')
|
|
555
|
-
assert.ok(resize.title.endsWith('box is tilted
|
|
550
|
+
assert.ok(resize.title.endsWith('box is tilted, so its size cannot be dragged.'), resize.title)
|
|
556
551
|
await read(() => editing.told())
|
|
557
552
|
await press('KeyR')
|
|
558
|
-
assert.deepEqual(
|
|
553
|
+
assert.deepEqual(await read(() => editing.told()), [{ level: 'info', message: 'box is tilted, so its size cannot be dragged.' }])
|
|
559
554
|
assert.equal((await state()).attached, null, 'no gizmo on it')
|
|
555
|
+
assert.equal((await state()).error, '', 'no error')
|
|
560
556
|
})
|
|
561
557
|
})
|
|
562
558
|
|
|
@@ -370,7 +370,7 @@ describe('the fastening window on the robot arm', () => {
|
|
|
370
370
|
|
|
371
371
|
test('the parts hanging from it are said in one line, and the chips show the part names as they are written', async () => {
|
|
372
372
|
const said = await read(() => {
|
|
373
|
-
const root =
|
|
373
|
+
const root = window.fastenDialog().shadowRoot
|
|
374
374
|
const chip = root.querySelector('ox-input-select-buttons').shadowRoot.querySelector('md-filter-chip')
|
|
375
375
|
const label = chip.shadowRoot.querySelector('.label-text') ?? chip.shadowRoot.querySelector('.label')
|
|
376
376
|
return { lines: root.querySelectorAll('p[loops]').length, transform: getComputedStyle(label).textTransform }
|
|
@@ -388,14 +388,17 @@ describe('a new fastening for a door leaf: chosen in the window, seen before it
|
|
|
388
388
|
})
|
|
389
389
|
const ghosts = () => read(() => look.drawn().filter(n => n.startsWith('__preview')))
|
|
390
390
|
|
|
391
|
-
test('started, the window opens
|
|
391
|
+
test('started, the window opens over the side panel, asking what to fasten to, nothing chosen; the canvas stays in sight', async () => {
|
|
392
392
|
await pick('leaf')
|
|
393
393
|
await press('button[fasten-start]')
|
|
394
394
|
const list = await until(() => probe.fastenTargets(), [], 'the fastening window')
|
|
395
395
|
assert.deepEqual(list.filter(t => t.selected), [], 'nothing chosen')
|
|
396
396
|
assert.ok(list.some(t => t.target === 'frame' && !t.disabled), 'the frame offered')
|
|
397
397
|
assert.deepEqual((await all('[apply]')).map(b => b.disabled), [true], 'nothing to apply yet')
|
|
398
|
-
|
|
398
|
+
/* Not the modal popup (user 2026-10-19: it covered the 3D it was choosing for): over the side panel, at most its edge over the canvas. */
|
|
399
|
+
const panel = await read(() => probe.fastenPanel())
|
|
400
|
+
assert.deepEqual({ ...panel, overCanvas: undefined }, { title: 'figure.label.fastening', role: 'dialog', popup: false, overCanvas: undefined })
|
|
401
|
+
assert.ok(panel.overCanvas <= 0.1, `the canvas stays in sight: ${panel.overCanvas} of its width covered`)
|
|
399
402
|
})
|
|
400
403
|
|
|
401
404
|
test('the frame chosen: the editor is told the command, and the canvas draws where the leaf would go and the face it meets', async () => {
|
|
@@ -421,14 +424,15 @@ describe('a new fastening for a door leaf: chosen in the window, seen before it
|
|
|
421
424
|
assert.deepEqual(await ghosts(), [], 'nothing of the earlier result drawn')
|
|
422
425
|
})
|
|
423
426
|
|
|
424
|
-
test('
|
|
427
|
+
test('another part picked in the list closes the window with nothing written, and nothing it tried is drawn', async () => {
|
|
425
428
|
const start = await state()
|
|
426
|
-
/*
|
|
427
|
-
|
|
429
|
+
/* No backdrop over the page: the parts list stays reachable. The window stands over the side panel, its tabs too, as the view settings do. */
|
|
430
|
+
assert.ok((await read(() => probe.fastenPanel())).overCanvas <= 0.1)
|
|
431
|
+
await pick('frame')
|
|
428
432
|
await until(() => !probe.fastenTargets(), [], 'the window closed')
|
|
429
433
|
await until(() => !look.drawn().some(n => n.startsWith('__preview')), [], 'nothing it tried drawn')
|
|
430
|
-
assert.equal(await read(() => look.tab()), 'figure.label.tab-short-properties', 'the press did not reach the tab')
|
|
431
434
|
assert.equal((await state()).revision, start.revision, 'nothing written')
|
|
435
|
+
await pick('leaf')
|
|
432
436
|
})
|
|
433
437
|
|
|
434
438
|
test('"fasten it first" from the motion tab opens this part\'s window, on what it has, on the properties tab', async () => {
|
|
@@ -599,23 +603,32 @@ function twisted() {
|
|
|
599
603
|
}
|
|
600
604
|
|
|
601
605
|
describe('a part fastened twisted is not sized by a drag', () => {
|
|
602
|
-
test('the resize tool is off, and a size drag that still arrives is not written
|
|
606
|
+
test('the resize tool is off, and a size drag that still arrives is not written: a notice says why, in one line, with the way to its size', async () => {
|
|
603
607
|
await mount('twisted', twisted())
|
|
604
608
|
await pick('blade')
|
|
605
609
|
assert.equal((await at('button[tool]', 'figure.button.gizmo-scale'))?.disabled, true, 'the resize tool is off')
|
|
610
|
+
await read(() => probe.told())
|
|
606
611
|
const start = await state()
|
|
607
612
|
await read(() => look.transformed('blade', { scale: [1.5, 1, 1] }))
|
|
608
613
|
await settled()
|
|
609
614
|
assert.equal((await state()).revision, start.revision, 'not written')
|
|
610
|
-
|
|
615
|
+
/* A notice, not the error's red (user 2026-10-19: the reason read as a fault, and was not understood). */
|
|
616
|
+
assert.deepEqual(await read(() => probe.told()), [{ level: 'info', message: 'figure.text.gizmo-size-turned-fastening', action: 'figure.button.to-size-fields' }])
|
|
617
|
+
assert.equal((await state()).error, '', 'no error')
|
|
611
618
|
})
|
|
612
619
|
|
|
613
|
-
test('the R key says why', async () => {
|
|
620
|
+
test('the R key says why, and the notice\'s button puts the cursor in the part\'s size field', async () => {
|
|
614
621
|
await mount('twisted', twisted())
|
|
615
622
|
await pick('blade')
|
|
616
|
-
|
|
623
|
+
await read(() => probe.told())
|
|
617
624
|
await page().keyboard.press('KeyR')
|
|
618
|
-
await until(() => probe.
|
|
625
|
+
await until(() => probe.told().some(n => n.message === 'figure.text.gizmo-size-turned-fastening' && n.action === 'figure.button.to-size-fields'), [], 'the reason said with its way on')
|
|
626
|
+
assert.equal((await state()).error, '', 'no error')
|
|
627
|
+
/* From another tab: the button brings the properties tab and the size field. */
|
|
628
|
+
await tab('motion')
|
|
629
|
+
assert.equal(await read(() => probe.pressNoticeButton()), true)
|
|
630
|
+
await until(() => probe.focused()?.label?.startsWith('blade.size.'), [], 'the blade\'s size field focused')
|
|
631
|
+
assert.equal(await read(() => look.tab()), 'figure.label.tab-short-properties')
|
|
619
632
|
})
|
|
620
633
|
})
|
|
621
634
|
|
|
@@ -741,26 +754,27 @@ describe('the fastening window: tried freely, written once', () => {
|
|
|
741
754
|
await until(w => JSON.stringify(JSON.parse(document.querySelector('figure-editor').session.source()).joints.find(j => j.body1.part === 'lamp')) === w, [JSON.stringify(was)], 'one undo: the fastening as it was')
|
|
742
755
|
})
|
|
743
756
|
|
|
744
|
-
test('
|
|
757
|
+
test('the canvas is turned with the window open: nothing written, still open, the window where it was', async () => {
|
|
745
758
|
await pick('lamp')
|
|
746
759
|
await changeFastening()
|
|
747
760
|
const rect = () => read(() => {
|
|
748
|
-
const r =
|
|
761
|
+
const r = window.fastenDialog()?.getBoundingClientRect()
|
|
749
762
|
return r ? { x: Math.round(r.left), y: Math.round(r.top) } : null
|
|
750
763
|
})
|
|
751
764
|
const was = await rect()
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
765
|
+
/* A drag on the empty canvas, left of the parts: the camera turns, nothing is picked. */
|
|
766
|
+
const box = await read(() => {
|
|
767
|
+
const r = document.querySelector('figure-editor').shadowRoot.querySelector('figure-canvas').getBoundingClientRect()
|
|
768
|
+
return { x: r.left + 40, y: r.top + r.height / 2 }
|
|
755
769
|
})
|
|
756
770
|
const start = await state()
|
|
757
|
-
await page().mouse.move(
|
|
771
|
+
await page().mouse.move(box.x, box.y)
|
|
758
772
|
await page().mouse.down()
|
|
759
|
-
for (let i = 1; i <= 6; i++) await page().mouse.move(
|
|
773
|
+
for (let i = 1; i <= 6; i++) await page().mouse.move(box.x + 20 * i, box.y + 5 * i)
|
|
760
774
|
await page().mouse.up()
|
|
761
|
-
|
|
762
|
-
assert.deepEqual([moved.x - was.x, moved.y - was.y], [-180, 120], `moved with the pointer: ${JSON.stringify([was, moved])}`)
|
|
775
|
+
await settled()
|
|
763
776
|
assert.equal(await windowOpen(), true, 'still open')
|
|
777
|
+
assert.deepEqual(await rect(), was, 'the window where it was')
|
|
764
778
|
assert.equal((await state()).revision, start.revision, 'nothing written')
|
|
765
779
|
await press('[cancel]')
|
|
766
780
|
await until(() => !probe.fastenTargets(), [], 'the window closed')
|
|
@@ -771,7 +785,7 @@ describe('the fastening window: tried freely, written once', () => {
|
|
|
771
785
|
await changeFastening()
|
|
772
786
|
const litAt = y => Math.abs((document.querySelector('figure-editor').shadowRoot.querySelector('figure-canvas').highlight?.pose.t[1] ?? 0) - y) < 2
|
|
773
787
|
/* The list has the focus, on the top it is fastened to. */
|
|
774
|
-
await until(() =>
|
|
788
|
+
await until(() => window.fastenDialog()?.shadowRoot.querySelector('ox-input-select-buttons')?.shadowRoot.activeElement?.getAttribute('data-value') === 'top', [], 'the focus on the chosen chip')
|
|
775
789
|
await page().keyboard.press('ArrowLeft')
|
|
776
790
|
/* The leg's top, 700 high (the lit plate a little over it); moving the focus lights, it does not choose. */
|
|
777
791
|
await until(litAt, [702], 'the leg\'s top lit')
|
|
@@ -87,6 +87,20 @@ function deep(selector, root = document) {
|
|
|
87
87
|
|
|
88
88
|
const editor = () => document.querySelector('figure-editor')
|
|
89
89
|
const canvas = () => deep('figure-canvas')[0]
|
|
90
|
+
/** The fastening window, wherever the editor draws it. */
|
|
91
|
+
window.fastenDialog = () => deep('figure-fasten-dialog')[0] ?? null
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* What the app's notification surface is handed (`notify`), in order. The page draws no snackbar, so a notice's button
|
|
95
|
+
* is pressed here, as the snackbar's would call it.
|
|
96
|
+
*/
|
|
97
|
+
const notices = []
|
|
98
|
+
const pressable = []
|
|
99
|
+
document.addEventListener('notify', e => {
|
|
100
|
+
notices.push(e.detail)
|
|
101
|
+
const action = e.detail?.option?.action
|
|
102
|
+
if (action?.callback) pressable.push(action.callback)
|
|
103
|
+
})
|
|
90
104
|
const three = () => canvas().scene.root._threeCapability
|
|
91
105
|
const controls = () => three().gizmoManager.controls
|
|
92
106
|
|
|
@@ -218,10 +232,40 @@ window.probe = {
|
|
|
218
232
|
const chip = deep('figure-fasten-dialog')[0]?.shadowRoot.querySelector('ox-input-select-buttons')?.shadowRoot?.querySelector(`md-filter-chip[data-value="${CSS.escape(part)}"]`)
|
|
219
233
|
return chip ? centreOf(chip) : null
|
|
220
234
|
},
|
|
221
|
-
/**
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
235
|
+
/**
|
|
236
|
+
* The fastening window as it stands: its title, its role, whether a popup or its backdrop is anywhere on the page, and
|
|
237
|
+
* how much of the canvas it covers (a share of the canvas's width).
|
|
238
|
+
*/
|
|
239
|
+
fastenPanel() {
|
|
240
|
+
const dialog = deep('figure-fasten-dialog')[0]
|
|
241
|
+
const panel = dialog?.closest('[fasten-panel]')
|
|
242
|
+
if (!panel) return null
|
|
243
|
+
const p = panel.getBoundingClientRect(),
|
|
244
|
+
c = canvas().getBoundingClientRect()
|
|
245
|
+
const across = Math.max(0, Math.min(p.right, c.right) - Math.max(p.left, c.left))
|
|
246
|
+
return {
|
|
247
|
+
title: panel.querySelector('h3')?.textContent.trim(),
|
|
248
|
+
role: dialog.getAttribute('role'),
|
|
249
|
+
popup: deep('ox-floating-overlay').length > 0,
|
|
250
|
+
overCanvas: Math.round((across / c.width) * 100) / 100
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
/** What the notification surface was handed since the last call: its level, its words, its button's label. */
|
|
254
|
+
told() {
|
|
255
|
+
return notices.splice(0).map(n => ({ level: n.level, message: n.message, action: n.option?.action?.label ?? null }))
|
|
256
|
+
},
|
|
257
|
+
/** The button of the last notice that had one, pressed. */
|
|
258
|
+
pressNoticeButton() {
|
|
259
|
+
const last = [...pressable].pop()
|
|
260
|
+
if (!last) return false
|
|
261
|
+
last()
|
|
262
|
+
return true
|
|
263
|
+
},
|
|
264
|
+
/** The element that has the focus, through shadow roots: its tag and aria-label. */
|
|
265
|
+
focused() {
|
|
266
|
+
let at = document.activeElement
|
|
267
|
+
while (at?.shadowRoot?.activeElement) at = at.shadowRoot.activeElement
|
|
268
|
+
return at ? { tag: at.localName, label: at.getAttribute('aria-label') } : null
|
|
225
269
|
},
|
|
226
270
|
/** The page point of an input by its aria-label, or of the part name field. */
|
|
227
271
|
nameField() {
|
|
@@ -155,6 +155,12 @@ function shellMoves(move) {
|
|
|
155
155
|
shellMoving = true
|
|
156
156
|
try {
|
|
157
157
|
move()
|
|
158
|
+
/*
|
|
159
|
+
The address layer adopts a raw History write the next time the address is read or written, and tells its
|
|
160
|
+
subscribers then (@operato/utils 10.29.43, \`adoptForeignWrite\`). Read it here, so the shell's own move is
|
|
161
|
+
adopted while it is still known as the shell's -- not at the product's next step, recorded as the product's.
|
|
162
|
+
*/
|
|
163
|
+
void addressController().entry
|
|
158
164
|
} finally {
|
|
159
165
|
shellMoving = false
|
|
160
166
|
}
|
|
@@ -184,11 +184,11 @@ describe('a part\'s groups in one order, whatever its state', () => {
|
|
|
184
184
|
})
|
|
185
185
|
assert.deepEqual(await place(), { sentence: true, change: true, drawing: false, cells: false })
|
|
186
186
|
await press('button[change-fastening]', '「바꾸기」')
|
|
187
|
-
await until(() => !!
|
|
187
|
+
await until(() => !!window.fastenDialog(), [], 'the window')
|
|
188
188
|
assert.deepEqual(await place(), { sentence: true, change: true, drawing: false, cells: false }, 'the panel still says the result')
|
|
189
189
|
/* Closed with nothing written; another part chosen and back: one line. */
|
|
190
190
|
await page().keyboard.press('Escape')
|
|
191
|
-
await until(() => !
|
|
191
|
+
await until(() => !window.fastenDialog(), [], 'the window closed')
|
|
192
192
|
await pick('bed')
|
|
193
193
|
await pick('mark')
|
|
194
194
|
assert.equal((await place()).change, true, 'said in one line again')
|
package/translations/en.json
CHANGED
|
@@ -843,11 +843,9 @@
|
|
|
843
843
|
"figure.text.held-on-part": "Attached by its {face} to the {otherFace} of {other}",
|
|
844
844
|
"figure.button.open-fastening": "Open attachment settings",
|
|
845
845
|
"figure.button.detach-held": "Detach",
|
|
846
|
-
"figure.text.gizmo-size-turned-fastening": "{part} is
|
|
847
|
-
"figure.
|
|
848
|
-
"figure.
|
|
849
|
-
"figure.label.kept-extreme-wall": "backmost point",
|
|
850
|
-
"figure.label.kept-extreme-center": "centre",
|
|
846
|
+
"figure.text.gizmo-size-turned-fastening": "{part} is attached turned, so its size cannot be dragged.",
|
|
847
|
+
"figure.text.gizmo-size-tilted": "{part} is tilted, so its size cannot be dragged.",
|
|
848
|
+
"figure.button.to-size-fields": "Go to size",
|
|
851
849
|
"figure.label.align-input": "Follows its field ({field})",
|
|
852
850
|
"figure.label.tab-short-properties": "Properties",
|
|
853
851
|
"figure.label.tab-short-capability": "Capability",
|
package/translations/es.json
CHANGED
|
@@ -843,11 +843,9 @@
|
|
|
843
843
|
"figure.text.held-on-part": "Unida por su {face} a {otherFace} de {other}",
|
|
844
844
|
"figure.button.open-fastening": "Abrir la configuración de unión",
|
|
845
845
|
"figure.button.detach-held": "Separar",
|
|
846
|
-
"figure.text.gizmo-size-turned-fastening": "{part} está
|
|
847
|
-
"figure.
|
|
848
|
-
"figure.
|
|
849
|
-
"figure.label.kept-extreme-wall": "punto más trasero",
|
|
850
|
-
"figure.label.kept-extreme-center": "centro",
|
|
846
|
+
"figure.text.gizmo-size-turned-fastening": "{part} está unida girada, así que su tamaño no se puede arrastrar.",
|
|
847
|
+
"figure.text.gizmo-size-tilted": "{part} está inclinada, así que su tamaño no se puede arrastrar.",
|
|
848
|
+
"figure.button.to-size-fields": "Ir al tamaño",
|
|
851
849
|
"figure.label.align-input": "Sigue su campo ({field})",
|
|
852
850
|
"figure.label.tab-short-properties": "Propiedades",
|
|
853
851
|
"figure.label.tab-short-capability": "Capacidad",
|
package/translations/ja.json
CHANGED
|
@@ -843,11 +843,9 @@
|
|
|
843
843
|
"figure.text.held-on-part": "{other}の{otherFace}に{face}で取り付け",
|
|
844
844
|
"figure.button.open-fastening": "取り付け設定を開く",
|
|
845
845
|
"figure.button.detach-held": "取り付けを外す",
|
|
846
|
-
"figure.text.gizmo-size-turned-fastening": "{part}
|
|
847
|
-
"figure.
|
|
848
|
-
"figure.
|
|
849
|
-
"figure.label.kept-extreme-wall": "最も奥の点",
|
|
850
|
-
"figure.label.kept-extreme-center": "中心",
|
|
846
|
+
"figure.text.gizmo-size-turned-fastening": "{part} は回して取り付けられているため、ドラッグでサイズを変えられません。",
|
|
847
|
+
"figure.text.gizmo-size-tilted": "{part} は傾いているため、ドラッグでサイズを変えられません。",
|
|
848
|
+
"figure.button.to-size-fields": "サイズ欄へ",
|
|
851
849
|
"figure.label.align-input": "位置欄に従う ({field})",
|
|
852
850
|
"figure.label.tab-short-properties": "属性",
|
|
853
851
|
"figure.label.tab-short-capability": "能力",
|
package/translations/ko.json
CHANGED
|
@@ -843,11 +843,9 @@
|
|
|
843
843
|
"figure.text.held-on-part": "{other}의 {otherFace}에 {face}으로 붙어 있음",
|
|
844
844
|
"figure.button.open-fastening": "붙임 설정 열기",
|
|
845
845
|
"figure.button.detach-held": "붙임 풀기",
|
|
846
|
-
"figure.text.gizmo-size-turned-fastening": "{part} 부품은
|
|
847
|
-
"figure.
|
|
848
|
-
"figure.
|
|
849
|
-
"figure.label.kept-extreme-wall": "가장 뒤쪽 점",
|
|
850
|
-
"figure.label.kept-extreme-center": "중심",
|
|
846
|
+
"figure.text.gizmo-size-turned-fastening": "{part} 부품은 돌려 붙어 있어 끌어서 크기를 바꿀 수 없습니다.",
|
|
847
|
+
"figure.text.gizmo-size-tilted": "{part} 부품은 기울어 있어 끌어서 크기를 바꿀 수 없습니다.",
|
|
848
|
+
"figure.button.to-size-fields": "크기 칸으로",
|
|
851
849
|
"figure.label.align-input": "위치 칸을 따름 ({field})",
|
|
852
850
|
"figure.label.tab-short-properties": "속성",
|
|
853
851
|
"figure.label.tab-short-capability": "능력",
|
package/translations/ms.json
CHANGED
|
@@ -843,11 +843,9 @@
|
|
|
843
843
|
"figure.text.held-on-part": "Dilekatkan dengan {face} pada {otherFace} {other}",
|
|
844
844
|
"figure.button.open-fastening": "Buka tetapan lekatan",
|
|
845
845
|
"figure.button.detach-held": "Tanggalkan",
|
|
846
|
-
"figure.text.gizmo-size-turned-fastening": "{part}
|
|
847
|
-
"figure.
|
|
848
|
-
"figure.
|
|
849
|
-
"figure.label.kept-extreme-wall": "titik paling belakang",
|
|
850
|
-
"figure.label.kept-extreme-center": "tengah",
|
|
846
|
+
"figure.text.gizmo-size-turned-fastening": "{part} dilekatkan dalam keadaan berpusing, jadi saiznya tidak boleh diseret.",
|
|
847
|
+
"figure.text.gizmo-size-tilted": "{part} condong, jadi saiznya tidak boleh diseret.",
|
|
848
|
+
"figure.button.to-size-fields": "Ke medan saiz",
|
|
851
849
|
"figure.label.align-input": "Mengikut medannya ({field})",
|
|
852
850
|
"figure.label.tab-short-properties": "Sifat",
|
|
853
851
|
"figure.label.tab-short-capability": "Keupayaan",
|
package/translations/zh.json
CHANGED
|
@@ -843,11 +843,9 @@
|
|
|
843
843
|
"figure.text.held-on-part": "以{face}附着在{other}的{otherFace}上",
|
|
844
844
|
"figure.button.open-fastening": "打开附着设置",
|
|
845
845
|
"figure.button.detach-held": "解除附着",
|
|
846
|
-
"figure.text.gizmo-size-turned-fastening": "{part}
|
|
847
|
-
"figure.
|
|
848
|
-
"figure.
|
|
849
|
-
"figure.label.kept-extreme-wall": "最靠后的点",
|
|
850
|
-
"figure.label.kept-extreme-center": "中心",
|
|
846
|
+
"figure.text.gizmo-size-turned-fastening": "{part} 是旋转后附着的,无法拖动改变尺寸。",
|
|
847
|
+
"figure.text.gizmo-size-tilted": "{part} 是倾斜的,无法拖动改变尺寸。",
|
|
848
|
+
"figure.button.to-size-fields": "转到尺寸栏",
|
|
851
849
|
"figure.label.align-input": "跟随位置栏 ({field})",
|
|
852
850
|
"figure.label.tab-short-properties": "属性",
|
|
853
851
|
"figure.label.tab-short-capability": "能力",
|