@things-factory/figure-ui 10.1.113 → 10.1.115
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/canvas.ts +6 -0
- package/client/modeller/editor.ts +40 -5
- package/client/modeller/face-mapping.ts +39 -0
- package/client/modeller/figure-face-mapping.ts +78 -0
- package/client/modeller/figure-preview.ts +34 -10
- package/client/modeller/figure-section-editor.ts +12 -4
- package/client/modeller/figure-section-panel.ts +5 -1
- package/client/modeller/preview-model.ts +8 -0
- package/client/pages/figure-modeller-page.ts +7 -1
- package/dist-client/modeller/canvas.js +7 -0
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +4 -0
- package/dist-client/modeller/editor.js +41 -5
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/face-mapping.d.ts +15 -0
- package/dist-client/modeller/face-mapping.js +20 -0
- package/dist-client/modeller/face-mapping.js.map +1 -0
- package/dist-client/modeller/figure-face-mapping.d.ts +16 -0
- package/dist-client/modeller/figure-face-mapping.js +85 -0
- package/dist-client/modeller/figure-face-mapping.js.map +1 -0
- package/dist-client/modeller/figure-preview.d.ts +2 -0
- package/dist-client/modeller/figure-preview.js +38 -10
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-section-editor.d.ts +4 -1
- package/dist-client/modeller/figure-section-editor.js +14 -3
- package/dist-client/modeller/figure-section-editor.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.d.ts +4 -1
- package/dist-client/modeller/figure-section-panel.js +6 -0
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/preview-model.d.ts +5 -0
- package/dist-client/modeller/preview-model.js +7 -0
- package/dist-client/modeller/preview-model.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +1 -0
- package/dist-client/pages/figure-modeller-page.js +7 -1
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/test/browser/acceptance-page.js +11 -0
- package/test/clip-consent.test.ts +1 -1
- package/test/face-mapping.test.ts +80 -0
- package/test/modeller-route.test.ts +8 -0
- package/test/preview.test.ts +39 -1
- package/test/section-panel.test.ts +1 -1
- package/translations/en.json +7 -1
- package/translations/ja.json +7 -1
- package/translations/ko.json +7 -1
- package/translations/ms.json +7 -1
- package/translations/zh.json +7 -1
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.115",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"clean": "npm run clean:server && npm run clean:client"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@hatiolab/figure-model": "^0.2.
|
|
31
|
-
"@hatiolab/things-scene": "^10.1.
|
|
30
|
+
"@hatiolab/figure-model": "^0.2.15",
|
|
31
|
+
"@hatiolab/things-scene": "^10.1.69",
|
|
32
32
|
"@material/web": "^2.0.0",
|
|
33
33
|
"@operato/data-grist": "^10.0.0",
|
|
34
34
|
"@operato/graphql": "^10.0.0",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"@operato/shell": "^10.0.0",
|
|
41
41
|
"@operato/styles": "^10.0.0",
|
|
42
42
|
"@operato/utils": "^10.0.0",
|
|
43
|
-
"@things-factory/ai-assistant": "^10.1.
|
|
44
|
-
"@things-factory/figure-service": "^10.1.
|
|
43
|
+
"@things-factory/ai-assistant": "^10.1.114",
|
|
44
|
+
"@things-factory/figure-service": "^10.1.115",
|
|
45
45
|
"three": "^0.185.1"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "3d1f480028b680a6da3d0ae6a73c3121d644b64a"
|
|
48
48
|
}
|
|
@@ -66,6 +66,17 @@ export const MODELS = {
|
|
|
66
66
|
a = applyFigureAuthoring(a, { kind: 'attach', part: 'lid', face: 'bottom', to: { part: 'bin', face: 'top' } })
|
|
67
67
|
return serializeFigureAsset(a)
|
|
68
68
|
},
|
|
69
|
+
/* A divider standing on a tote's inside floor: opening the bottom asks where the divider goes (ADR-0100 A8). */
|
|
70
|
+
'divider-in-tote': () => {
|
|
71
|
+
let a = createFigureAsset('Divider in tote')
|
|
72
|
+
a.palette = { ...a.palette, ...PALETTE }
|
|
73
|
+
a = addFigureBox(a, { id: 'bin', size: { x: 600, y: 300, z: 400 }, position: { x: 0, y: 150, z: 0 } })
|
|
74
|
+
a = applyFigureAuthoring(a, { kind: 'attach', part: 'bin', face: 'bottom', to: { plane: 'mounting-plane' } })
|
|
75
|
+
a = applyFigureAuthoring(a, { kind: 'set-cavity', part: 'bin', cavity: { wall: 10, start: { closed: 15 }, end: 'open' } })
|
|
76
|
+
a = addFigureBox(a, { id: 'divider', size: { x: 10, y: 200, z: 380 }, position: { x: 0, y: 0, z: 0 } })
|
|
77
|
+
a = applyFigureAuthoring(a, { kind: 'attach', part: 'divider', face: 'bottom', to: { part: 'bin', face: 'inside-bottom' } })
|
|
78
|
+
return serializeFigureAsset(a)
|
|
79
|
+
},
|
|
69
80
|
/* A box and a drum: rounded corners and an inside from the properties tab (ADR-0100 stage 1). */
|
|
70
81
|
shapes: () => {
|
|
71
82
|
let a = createFigureAsset('Box and drum')
|
|
@@ -76,7 +76,7 @@ test('a consent is used by one edit only, on the version and figure it was given
|
|
|
76
76
|
|
|
77
77
|
test('the modeller asks on every path an edit can stop a clip, in every language', () => {
|
|
78
78
|
const editor = read('../client/modeller/editor.ts')
|
|
79
|
-
for (const path of ['() => this.run(action)', '() => this.linkCommand(action)', '() => this.removePart(id, refitRoom)'])
|
|
79
|
+
for (const path of ['() => this.run(action)', '() => this.linkCommand(action, from)', '() => this.removePart(id, refitRoom)'])
|
|
80
80
|
assert.ok(editor.includes(`if (this.askClipLoss(error, ${path})) return`), path)
|
|
81
81
|
assert.ok(editor.includes('if (!now || now.context !== asked.context || now.revision !== asked.revision) {'), 'what was asked about is checked after the answer')
|
|
82
82
|
assert.ok(editor.includes('asked.session.withConsent({ dropClips: clips.map(c => c.id), context: asked.context, revision: asked.revision }, again)'))
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* **붙은 면을 없애는 편집에서 옮길 곳 고르기** (ADR-0100 A8, 사용자 2026-10-02: 미리 고르지 않는다 · 떼어 두기는 붙이기
|
|
3
|
+
* 관계에만 · 편집한 그 자리에서 묻는다).
|
|
4
|
+
*
|
|
5
|
+
* 커널 거절이 실어 온 것으로 줄을 짓고, 다 고른 뒤에만 remap 을 내며, 그 remap 을 붙인 같은 명령을 커널이 받는지 잰다.
|
|
6
|
+
* 편집기·단면 편집 창·단면 칸이 거절을 그 자리에 붙들어 두는지는 소스로 잰다.
|
|
7
|
+
*/
|
|
8
|
+
import { test } from 'node:test'
|
|
9
|
+
import assert from 'node:assert/strict'
|
|
10
|
+
import { readFileSync } from 'node:fs'
|
|
11
|
+
import { fileURLToPath } from 'node:url'
|
|
12
|
+
|
|
13
|
+
import { addFigureBox, applyFigureAuthoring, createFigureAsset } from '@hatiolab/figure-model'
|
|
14
|
+
import type { FigureAsset, FigureFaceMappingNeed } from '@hatiolab/figure-model'
|
|
15
|
+
|
|
16
|
+
import { DETACH, faceMappingRowsOf, remapOf, rowKey } from '../client/modeller/face-mapping.ts'
|
|
17
|
+
|
|
18
|
+
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
19
|
+
const has = (source: string, re: RegExp, message?: string) => assert.ok(re.test(source), message ?? `missing: ${re}`)
|
|
20
|
+
|
|
21
|
+
/** A tote with a floor inside and a divider standing on it. */
|
|
22
|
+
function tote(): FigureAsset {
|
|
23
|
+
let asset = addFigureBox(createFigureAsset('Tote'), { id: 'bin', size: { x: 600, y: 300, z: 400 }, position: { x: 0, y: 150, z: 0 } })
|
|
24
|
+
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'bin', face: 'bottom', to: { plane: 'mounting-plane' } })
|
|
25
|
+
asset = applyFigureAuthoring(asset, { kind: 'set-cavity', part: 'bin', cavity: { wall: 10, start: { closed: 15 }, end: 'open' } })
|
|
26
|
+
asset = addFigureBox(asset, { id: 'divider', size: { x: 10, y: 200, z: 380 }, position: { x: 0, y: 0, z: 0 } })
|
|
27
|
+
return applyFigureAuthoring(asset, { kind: 'attach', part: 'divider', face: 'bottom', to: { part: 'bin', face: 'inside-bottom' as never } })
|
|
28
|
+
}
|
|
29
|
+
const open = { kind: 'set-cavity', part: 'bin', cavity: { wall: 10, start: 'open', end: 'open' } } as const
|
|
30
|
+
const needOf = (asset: FigureAsset): FigureFaceMappingNeed => {
|
|
31
|
+
try {
|
|
32
|
+
applyFigureAuthoring(asset, open)
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return (e as { details: FigureFaceMappingNeed }).details
|
|
35
|
+
}
|
|
36
|
+
throw new Error('not refused')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test('one row per thing on a lost face, its choices the faces that remain looking the same way', () => {
|
|
40
|
+
const rows = faceMappingRowsOf(needOf(tote()))
|
|
41
|
+
assert.equal(rows.length, 1)
|
|
42
|
+
assert.equal(rows[0]!.lost, 'inside-bottom')
|
|
43
|
+
assert.ok(rows[0]!.faces.includes('top'), 'the rim looks up, as the floor did')
|
|
44
|
+
assert.ok(!rows[0]!.faces.includes('inside-left') && !rows[0]!.faces.includes('bottom'), 'not a face looking another way')
|
|
45
|
+
assert.ok(!rows[0]!.faces.includes('inside-bottom'), 'not the face the edit takes away')
|
|
46
|
+
assert.equal(rows[0]!.detach, true, 'a joint may be let go where it stands')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('a named face may only move, never be let go', () => {
|
|
50
|
+
const need: FigureFaceMappingNeed = {
|
|
51
|
+
lost: [{ face: 'inside-bottom', axis: 'y', normal: 1, refs: [{ kind: 'feature', id: 'bin.tray' }] }],
|
|
52
|
+
remain: [{ face: 'top', axis: 'y', normal: 1 }]
|
|
53
|
+
}
|
|
54
|
+
assert.equal(faceMappingRowsOf(need)[0]!.detach, false)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('nothing goes until every row is chosen, and the chosen remap is what the kernel takes', () => {
|
|
58
|
+
const asset = tote()
|
|
59
|
+
const rows = faceMappingRowsOf(needOf(asset))
|
|
60
|
+
assert.equal(remapOf(rows, {}), undefined, 'nothing chosen for the author')
|
|
61
|
+
const moved = applyFigureAuthoring(asset, { ...open, remap: remapOf(rows, { [rowKey(rows[0]!)]: 'top' })! })
|
|
62
|
+
assert.deepEqual(moved.joints!.find(j => j.id === 'divider')!.body0, { part: 'bin', face: 'top' })
|
|
63
|
+
const freed = applyFigureAuthoring(asset, { ...open, remap: remapOf(rows, { [rowKey(rows[0]!)]: DETACH })! })
|
|
64
|
+
assert.ok(!(freed.joints ?? []).some(j => j.id === 'divider'))
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('the choice is asked where the edit was made, and the same edit goes again with it', () => {
|
|
68
|
+
const editor = read('../client/modeller/editor.ts')
|
|
69
|
+
const sectionEditor = read('../client/modeller/figure-section-editor.ts')
|
|
70
|
+
const panel = read('../client/modeller/figure-section-panel.ts')
|
|
71
|
+
const mapping = read('../client/modeller/figure-face-mapping.ts')
|
|
72
|
+
has(editor, /code === 'FEATURE_MAPPING_REQUIRED' && need\?\.lost\?\.length\) \{\s*this\.faceMapping = \{ action, need, from \}/, 'the refusal is held, not only said')
|
|
73
|
+
has(editor, /linkCommand\(\{ \.\.\.held\.action, remap \}/, 'the same edit, with where things go')
|
|
74
|
+
has(editor, /if \(!this\.linkCommand\(e\.detail\.action, 'section-editor'\)\) e\.detail\.held = true/, 'the section editor stays open while held')
|
|
75
|
+
has(editor, /this\.selected = id \? ownerOf\(id\) : id\s*this\.faceMapping = undefined/, 'another part chosen lets the held edit go')
|
|
76
|
+
has(sectionEditor, /if \(!detail\.held\) this\.close\(\)/)
|
|
77
|
+
has(sectionEditor, /this\.faceMapping \? html`<figure-face-mapping/)
|
|
78
|
+
has(panel, /this\.faceMapping \? html`<figure-face-mapping/)
|
|
79
|
+
has(mapping, /\?disabled=\$\{!remap\}/, 'apply is off until every row is chosen')
|
|
80
|
+
})
|
|
@@ -36,3 +36,11 @@ test('reloading or closing the tab with unsaved work asks first — the shell do
|
|
|
36
36
|
assert.match(page, /addEventListener\('beforeunload', this\.holdUnsaved\)/)
|
|
37
37
|
assert.match(page, /removeEventListener\('beforeunload', this\.holdUnsaved\)/)
|
|
38
38
|
})
|
|
39
|
+
|
|
40
|
+
test('기존 도형을 열면 rail 은 카탈로그를 가리킨다 — 「새 Figure」를 가리키지 않는다(2026-10-03)', async () => {
|
|
41
|
+
const { readFileSync } = await import('node:fs')
|
|
42
|
+
const page = readFileSync(new URL('../client/pages/figure-modeller-page.ts', import.meta.url), 'utf8')
|
|
43
|
+
const context = page.slice(page.indexOf('get context()'), page.indexOf('render()', page.indexOf('get context()')))
|
|
44
|
+
/* The rail's rule (@operato/menu menu-active.ts): a page that names its menu wins over a menu with the same page name. */
|
|
45
|
+
assert.ok(context.includes("menu: view.id ? 'figure-list' : undefined"), 'id 가 있으면 카탈로그, 새 도형이면 이름을 대지 않는다')
|
|
46
|
+
})
|
package/test/preview.test.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
9
9
|
|
|
10
10
|
import { addFigureBox, createFigureAsset } from '@hatiolab/figure-model'
|
|
11
11
|
|
|
12
|
-
import { authoredSizeOf, PREVIEW_WAYS, previewClampsOf, previewInstances } from '../client/modeller/preview-model.ts'
|
|
12
|
+
import { authoredSizeOf, PREVIEW_WAYS, previewClampsOf, previewInstances, setupPartOf } from '../client/modeller/preview-model.ts'
|
|
13
13
|
|
|
14
14
|
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
15
15
|
|
|
@@ -54,3 +54,41 @@ test('미리보기 — 선언하지 않은 크기를 묻는 변형은 그려지
|
|
|
54
54
|
const view = readFileSync(fileURLToPath(new URL('../client/modeller/figure-preview.ts', import.meta.url)), 'utf8')
|
|
55
55
|
assert.ok(view.includes("i18next.t('figure.text.preview-clamped'"), '범례에 적는다')
|
|
56
56
|
})
|
|
57
|
+
|
|
58
|
+
test('미리보기로 가도 고른 부품이 남는다 — 화면에서 빠진 캔버스는 선택을 알리지 않는다(U03, 2026-10-03)', () => {
|
|
59
|
+
const canvas = read('../client/modeller/canvas.ts')
|
|
60
|
+
const handler = canvas.slice(canvas.indexOf("root.on('selected'"), canvas.indexOf("root.on('selected'") + 900)
|
|
61
|
+
assert.ok(handler.includes('if (!this.isConnected) return'), '장면을 치울 때 비워진 선택을 편집기에 알리지 않는다')
|
|
62
|
+
assert.ok(handler.indexOf('if (!this.isConnected) return') < handler.indexOf("new CustomEvent('part-selected'"), '알리기 전에 거른다')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('미리보기 크기 안내는 편집에서 고른 부품부터 — 안내에서 고른 것이 먼저, 없는 부품은 건너뛴다', () => {
|
|
66
|
+
assert.equal(setupPartOf('', 'roller', ['frame', 'roller']), 'roller', '편집에서 고른 부품')
|
|
67
|
+
assert.equal(setupPartOf('frame', 'roller', ['frame', 'roller']), 'frame', '안내에서 고른 것이 이긴다')
|
|
68
|
+
assert.equal(setupPartOf('', 'leg', ['frame', 'roller']), 'frame', '크기 규칙이 없는 부품이면 첫 부품')
|
|
69
|
+
assert.equal(setupPartOf('gone', '', ['frame']), 'frame', '사라진 부품은 건너뛴다')
|
|
70
|
+
assert.equal(setupPartOf('', '', []), '')
|
|
71
|
+
const editor = read('../client/modeller/editor.ts')
|
|
72
|
+
const tag = editor.slice(editor.indexOf('<figure-preview'), editor.indexOf('</figure-preview>'))
|
|
73
|
+
assert.ok(tag.includes('.selected=${this.selected}'), '편집기가 고른 부품을 넘긴다')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('미리보기 아래의 크기 안내와 조작값은 한 줄에서 줄을 바꾼다 — 좁은 폭에서 겹치지 않는다(1024 폭, 2026-10-03)', () => {
|
|
77
|
+
const preview = read('../client/modeller/figure-preview.ts')
|
|
78
|
+
const style = (sel: string) => preview.slice(preview.indexOf(sel + ' {'), preview.indexOf('}', preview.indexOf(sel + ' {')))
|
|
79
|
+
assert.match(style('div[foot]'), /position: absolute/)
|
|
80
|
+
assert.match(style('div[foot]'), /flex-wrap: wrap-reverse/)
|
|
81
|
+
assert.doesNotMatch(style('div[setup]'), /position: absolute/, '안내가 제 모서리에 따로 서지 않는다')
|
|
82
|
+
assert.doesNotMatch(style('div[clips]'), /position: absolute/, '조작값이 제 모서리에 따로 서지 않는다')
|
|
83
|
+
const foot = preview.slice(preview.indexOf('<div foot>'))
|
|
84
|
+
assert.ok(foot.indexOf('<div setup>') < foot.indexOf('this.renderDrivers('), '둘 다 한 줄 안에')
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('미리보기 재생 속도는 실제로 도는 값을 보인다 — 움직이기 전에는 0(멈춤), 1.00 으로 보이며 서 있지 않는다(2026-10-03)', () => {
|
|
88
|
+
const preview = read('../client/modeller/figure-preview.ts')
|
|
89
|
+
const drivers = preview.slice(preview.indexOf('clips.map(clip =>'))
|
|
90
|
+
assert.ok(drivers.includes('this.driving[clip] ?? 0'), '아무것도 보내지 않은 clip 은 0 으로 그린다')
|
|
91
|
+
assert.ok(!drivers.slice(0, 600).includes('this.driving[clip] ?? 1'))
|
|
92
|
+
const drive = preview.slice(preview.indexOf('private drive('), preview.indexOf('private give('))
|
|
93
|
+
assert.ok(drive.includes("this.tellInstances('clips'"), '속도는 drive 에서만 보낸다 — 그래서 보이는 값도 보낸 값뿐이다')
|
|
94
|
+
})
|
|
@@ -91,7 +91,7 @@ test('벽이 단면을 다 채우거나 모서리가 변의 절반을 넘으면,
|
|
|
91
91
|
test('편집기는 단면 칸의 명령을 세션의 이력 하나로 돌리고, 치는 동안의 값은 그리기만 한다', () => {
|
|
92
92
|
has(editor, /<figure-section-panel[\s\S]*?@command=\$\{\(e: CustomEvent\) => this\.linkCommand\(e\.detail\.action\)\}/)
|
|
93
93
|
has(editor, /@command-live=\$\{\(e: CustomEvent\) => this\.holdAction\(e\.detail\.action\)\}/)
|
|
94
|
-
has(editor, /private linkCommand\(action: FigureAuthoringAction\) \{\s*\/\*[^*]*\*\/\s*this\.holdAction\(null\)/, 'a command sent lets go of the one in hand')
|
|
94
|
+
has(editor, /private linkCommand\(action: FigureAuthoringAction, from: 'section-editor' \| 'panel' = 'panel'\): boolean \{\s*\/\*[^*]*\*\/\s*this\.holdAction\(null\)/, 'a command sent lets go of the one in hand')
|
|
95
95
|
for (const lang of ['ko', 'en', 'ja', 'zh', 'ms']) {
|
|
96
96
|
const words = JSON.parse(read(`../translations/${lang}.json`)) as Record<string, string>
|
|
97
97
|
const used = [...new Set([...(panel + drawing).matchAll(/'(figure\.(?:label|text)\.section-[\w-]+|figure\.label\.group-section)'/g)].map(m => m[1]!))]
|
package/translations/en.json
CHANGED
|
@@ -959,5 +959,11 @@
|
|
|
959
959
|
"figure.text.summary-size-input": "Its {axes} follows {field}.",
|
|
960
960
|
"figure.text.summary-size-worked-out": "Its {axes} is worked out from other measures.",
|
|
961
961
|
"figure.text.held-by-fastening": "It is fastened: its place and turn are set in 붙이기.",
|
|
962
|
-
"figure.text.held-worked-out": "{group} are worked out from other values and cannot be typed here."
|
|
962
|
+
"figure.text.held-worked-out": "{group} are worked out from other values and cannot be typed here.",
|
|
963
|
+
"figure.text.face-mapping-lost": "Faces this takes away: {faces}. Choose where what stands on them goes.",
|
|
964
|
+
"figure.label.face-mapping-to": "Where {part} goes",
|
|
965
|
+
"figure.label.face-mapping-choose": "Choose",
|
|
966
|
+
"figure.label.face-mapping-detach": "Let go (stays where it is)",
|
|
967
|
+
"figure.button.face-mapping-cancel": "Cancel",
|
|
968
|
+
"figure.button.face-mapping-apply": "Move and apply"
|
|
963
969
|
}
|
package/translations/ja.json
CHANGED
|
@@ -959,5 +959,11 @@
|
|
|
959
959
|
"figure.text.summary-size-input": "{axes}は{field}に従います。",
|
|
960
960
|
"figure.text.summary-size-worked-out": "{axes}は他の寸法から計算されます。",
|
|
961
961
|
"figure.text.held-by-fastening": "取り付けられているため、位置と回転は取り付けで決めます。",
|
|
962
|
-
"figure.text.held-worked-out": "{group}は他の値から計算されるため、ここでは変更できません。"
|
|
962
|
+
"figure.text.held-worked-out": "{group}は他の値から計算されるため、ここでは変更できません。",
|
|
963
|
+
"figure.text.face-mapping-lost": "なくなる面: {faces}。そこに付いているものの移動先を選びます。",
|
|
964
|
+
"figure.label.face-mapping-to": "{part} の移動先",
|
|
965
|
+
"figure.label.face-mapping-choose": "移動先",
|
|
966
|
+
"figure.label.face-mapping-detach": "外しておく(今の位置のまま)",
|
|
967
|
+
"figure.button.face-mapping-cancel": "やめる",
|
|
968
|
+
"figure.button.face-mapping-apply": "移して適用"
|
|
963
969
|
}
|
package/translations/ko.json
CHANGED
|
@@ -959,5 +959,11 @@
|
|
|
959
959
|
"figure.text.summary-size-input": "{axes} {field} 값을 따릅니다.",
|
|
960
960
|
"figure.text.summary-size-worked-out": "{axes} 다른 치수에서 계산됩니다.",
|
|
961
961
|
"figure.text.held-by-fastening": "붙어 있어서 위치와 회전은 붙이기에서 정합니다.",
|
|
962
|
-
"figure.text.held-worked-out": "{group}는 다른 값에서 계산되어 여기서 고칠 수 없습니다."
|
|
962
|
+
"figure.text.held-worked-out": "{group}는 다른 값에서 계산되어 여기서 고칠 수 없습니다.",
|
|
963
|
+
"figure.text.face-mapping-lost": "없어지는 면: {faces}. 거기 붙은 것을 옮길 곳을 고릅니다.",
|
|
964
|
+
"figure.label.face-mapping-to": "{part}을(를) 옮길 곳",
|
|
965
|
+
"figure.label.face-mapping-choose": "옮길 곳",
|
|
966
|
+
"figure.label.face-mapping-detach": "떼어 두기(지금 자리에 그대로)",
|
|
967
|
+
"figure.button.face-mapping-cancel": "그만두기",
|
|
968
|
+
"figure.button.face-mapping-apply": "옮기고 적용"
|
|
963
969
|
}
|
package/translations/ms.json
CHANGED
|
@@ -959,5 +959,11 @@
|
|
|
959
959
|
"figure.text.summary-size-input": "{axes} mengikut {field}.",
|
|
960
960
|
"figure.text.summary-size-worked-out": "{axes} dikira daripada ukuran lain.",
|
|
961
961
|
"figure.text.held-by-fastening": "Ia dipasang: kedudukan dan putaran ditetapkan dalam pemasangan.",
|
|
962
|
-
"figure.text.held-worked-out": "{group} dikira daripada nilai lain dan tidak boleh diubah di sini."
|
|
962
|
+
"figure.text.held-worked-out": "{group} dikira daripada nilai lain dan tidak boleh diubah di sini.",
|
|
963
|
+
"figure.text.face-mapping-lost": "Muka yang akan hilang: {faces}. Pilih ke mana benda padanya dialihkan.",
|
|
964
|
+
"figure.label.face-mapping-to": "Ke mana {part} dialihkan",
|
|
965
|
+
"figure.label.face-mapping-choose": "Pilih",
|
|
966
|
+
"figure.label.face-mapping-detach": "Lepaskan (kekal di tempatnya)",
|
|
967
|
+
"figure.button.face-mapping-cancel": "Batal",
|
|
968
|
+
"figure.button.face-mapping-apply": "Alih dan guna"
|
|
963
969
|
}
|
package/translations/zh.json
CHANGED
|
@@ -959,5 +959,11 @@
|
|
|
959
959
|
"figure.text.summary-size-input": "{axes}跟随{field}。",
|
|
960
960
|
"figure.text.summary-size-worked-out": "{axes}由其他尺寸计算得出。",
|
|
961
961
|
"figure.text.held-by-fastening": "已连接,位置和旋转在连接中设定。",
|
|
962
|
-
"figure.text.held-worked-out": "{group}由其他值计算得出,此处不能修改。"
|
|
962
|
+
"figure.text.held-worked-out": "{group}由其他值计算得出,此处不能修改。",
|
|
963
|
+
"figure.text.face-mapping-lost": "将消失的面:{faces}。请选择其上部件的去处。",
|
|
964
|
+
"figure.label.face-mapping-to": "{part} 的去处",
|
|
965
|
+
"figure.label.face-mapping-choose": "去处",
|
|
966
|
+
"figure.label.face-mapping-detach": "解除连接(保持原位)",
|
|
967
|
+
"figure.button.face-mapping-cancel": "取消",
|
|
968
|
+
"figure.button.face-mapping-apply": "移动并应用"
|
|
963
969
|
}
|