@things-factory/figure-service 10.1.106 → 10.1.109
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/dist-server/service/figure/event-subscriber.d.ts +0 -10
- package/dist-server/service/figure/event-subscriber.js +13 -7
- package/dist-server/service/figure/event-subscriber.js.map +1 -1
- package/dist-server/service/figure/figure-format.d.ts +11 -1
- package/dist-server/service/figure/figure-format.js +46 -0
- package/dist-server/service/figure/figure-format.js.map +1 -1
- package/dist-server/service/figure/figure-history.d.ts +2 -0
- package/dist-server/service/figure/figure-history.js +13 -0
- package/dist-server/service/figure/figure-history.js.map +1 -1
- package/dist-server/service/figure/figure-mutation.js +6 -2
- package/dist-server/service/figure/figure-mutation.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/server/service/figure/event-subscriber.ts +14 -5
- package/server/service/figure/figure-format.test.ts +30 -1
- package/server/service/figure/figure-format.ts +44 -0
- package/server/service/figure/figure-history.ts +16 -0
- package/server/service/figure/figure-mutation.ts +7 -3
- package/server/service/figure/figure-release-record-db.test.ts +94 -0
- package/translations/en.json +11 -1
- package/translations/ko.json +11 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/figure-service",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.109",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -25,15 +25,15 @@
|
|
|
25
25
|
"test:templates": "node --test scripts/templates.test.mts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@hatiolab/figure-model": "^0.2.
|
|
28
|
+
"@hatiolab/figure-model": "^0.2.8",
|
|
29
29
|
"@operato/typeorm-history": "^10.0.0",
|
|
30
30
|
"@things-factory/ai-client-base": "^10.1.81",
|
|
31
|
-
"@things-factory/auth-base": "^10.1.
|
|
31
|
+
"@things-factory/auth-base": "^10.1.107",
|
|
32
32
|
"@things-factory/env": "^10.1.20",
|
|
33
33
|
"@things-factory/shell": "^10.1.106",
|
|
34
34
|
"graphql-scalars": "^1.22.4",
|
|
35
35
|
"graphql-upload": "^15.0.2",
|
|
36
36
|
"koa-router": "^7.4.0"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "4d51757c50d8347e83c96aeba73d770bdde55b73"
|
|
39
39
|
}
|
|
@@ -13,8 +13,19 @@ import { FigureHistory } from './figure-history.js'
|
|
|
13
13
|
* **발행한 것**이므로 그때만 베낀다. board 가 같은 규칙으로 돈다(`board-service` 의 같은 이름 파일).
|
|
14
14
|
*
|
|
15
15
|
* 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어
|
|
16
|
-
* 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 도형의 것이 아니다.
|
|
16
|
+
* 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 도형의 것이 아니다. 정본 형식
|
|
17
|
+
* (`__releaseFormat`)과 직전 판에 견준 변경(`__releaseChanges`)도 같은 길로 옮긴다(ADR-0104).
|
|
17
18
|
*/
|
|
19
|
+
/** What `releaseFigure` laid on the entity for this release, moved onto the history row. */
|
|
20
|
+
function releaseRecordOnto(history: FigureHistory, entity: Figure): FigureHistory {
|
|
21
|
+
const e = entity as any
|
|
22
|
+
;(history as any).comment = e.__releaseComment ?? null
|
|
23
|
+
history.assetFormat = e.__releaseFormat ?? null
|
|
24
|
+
/* [] stays "[]" (nothing changed); null stays null (not compared). */
|
|
25
|
+
history.changes = e.__releaseChanges == null ? null : JSON.stringify(e.__releaseChanges)
|
|
26
|
+
return history
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
@EventSubscriber()
|
|
19
30
|
export class FigureHistoryEntitySubscriber extends HistoryEntitySubscriber<Figure, FigureHistory> {
|
|
20
31
|
public get entity() {
|
|
@@ -26,13 +37,11 @@ export class FigureHistoryEntitySubscriber extends HistoryEntitySubscriber<Figur
|
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
public beforeInsertHistory(history: FigureHistory, entity: Figure): FigureHistory {
|
|
29
|
-
|
|
30
|
-
return history
|
|
40
|
+
return releaseRecordOnto(history, entity)
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
public beforeUpdateHistory(history: FigureHistory, entity: Figure): FigureHistory {
|
|
34
|
-
|
|
35
|
-
return history
|
|
44
|
+
return releaseRecordOnto(history, entity)
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
public async afterInsert(event: any): Promise<void> {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { createFigureAsset, addFigureBox, addFigurePrimitive, serializeFigureAsset, applyFigureAuthoring, proposeFigureOccupancy, placeholderType, figureScoreOf } from '@hatiolab/figure-model'
|
|
10
10
|
import type { FigureAsset } from '@hatiolab/figure-model'
|
|
11
11
|
|
|
12
|
-
import { FigureSourceError, consumablePayloadOf, inspectSource, parseSource } from './figure-format'
|
|
12
|
+
import { FigureSourceError, consumablePayloadOf, inspectSource, parseSource, releaseRecordOf } from './figure-format'
|
|
13
13
|
|
|
14
14
|
/** 온전한 자산 하나: 바닥에 선 상자와, 부품에서 제안받아 확정한 점유 부피. */
|
|
15
15
|
function figureAsset(): FigureAsset {
|
|
@@ -320,4 +320,33 @@ describe('figure-format — 판을 알아보는 문', () => {
|
|
|
320
320
|
expect(() => consumablePayloadOf(JSON.stringify(broken))).toThrow()
|
|
321
321
|
})
|
|
322
322
|
})
|
|
323
|
+
|
|
324
|
+
/* ADR-0104 decision 5: a release records its format and what changed against the last one, once, as it was then. */
|
|
325
|
+
describe('발행이 스스로 남기는 것 — 형식과 직전 판에 견준 변경', () => {
|
|
326
|
+
const wider = () => {
|
|
327
|
+
let asset = createFigureAsset('Mixer')
|
|
328
|
+
asset = addFigureBox(asset, { id: 'body', size: { x: 300, y: 100, z: 100 }, position: { x: 0, y: 50, z: 0 } })
|
|
329
|
+
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'body', face: 'bottom', to: { plane: 'mounting-plane' } })
|
|
330
|
+
return serializeFigureAsset(applyFigureAuthoring(asset, { kind: 'declare-occupancy', proposal: proposeFigureOccupancy(asset, { over: 'range' }), placement: 'floor' }))
|
|
331
|
+
}
|
|
332
|
+
it('a first release: its format, and nothing changed', () => {
|
|
333
|
+
expect(releaseRecordOf(serializeFigureAsset(figureAsset()))).toEqual({ format: 'figure-asset-1', changes: [] })
|
|
334
|
+
})
|
|
335
|
+
it('the same again changes nothing; a wider room is said and does not block', () => {
|
|
336
|
+
const v1 = serializeFigureAsset(figureAsset())
|
|
337
|
+
expect(releaseRecordOf(v1, v1).changes).toEqual([])
|
|
338
|
+
const room = releaseRecordOf(wider(), v1).changes!.find(c => c.code === 'occupancy-changed')!
|
|
339
|
+
expect(room.blocking).toBe(false)
|
|
340
|
+
expect(String(room.values.after)).toMatch(/x -150…150/)
|
|
341
|
+
})
|
|
342
|
+
it('a last release that cannot be read is "not compared" (null), never "nothing changed" ([])', () => {
|
|
343
|
+
expect(releaseRecordOf(serializeFigureAsset(figureAsset()), '{ not json').changes).toBeNull()
|
|
344
|
+
})
|
|
345
|
+
it('every new change has its sentence in both languages', () => {
|
|
346
|
+
const KO = require('../../../translations/ko.json') as Record<string, string>
|
|
347
|
+
const EN = require('../../../translations/en.json') as Record<string, string>
|
|
348
|
+
for (const code of ['occupancy-changed', 'contact-face-changed', 'public-input-gone', 'public-input-range-narrowed', 'public-input-added'])
|
|
349
|
+
for (const dict of [KO, EN]) for (const field of ['message', 'why']) expect(dict[`figure.gate.contract.${code}.${field}`]).toBeTruthy()
|
|
350
|
+
})
|
|
351
|
+
})
|
|
323
352
|
})
|
|
@@ -420,7 +420,51 @@ function figureContractWording(change: FigureContractChange, say: Say): Pick<Gat
|
|
|
420
420
|
message: say(key('message'), v, `The capability '${v.name}' is new.`),
|
|
421
421
|
why: say(key('why'), {}, 'It adds what the figure can do. Placed instances stand as they are.')
|
|
422
422
|
}
|
|
423
|
+
/* Said, never refused (ADR-0104): a consumer that pins a release reads these before it moves to this one. */
|
|
424
|
+
case 'occupancy-changed':
|
|
425
|
+
return {
|
|
426
|
+
message: say(key('message'), v, `The room the figure takes changed from ${v.before || 'none'} to ${v.after || 'none'}.`),
|
|
427
|
+
why: say(key('why'), {}, 'A consumer places the figure by this room. One that moves to this release sees it take the new room.')
|
|
428
|
+
}
|
|
429
|
+
case 'contact-face-changed':
|
|
430
|
+
return {
|
|
431
|
+
message: say(key('message'), v, 'The face the figure is mounted by changed.'),
|
|
432
|
+
why: say(key('why'), {}, 'A consumer that moves to this release sees it stand on the new face.')
|
|
433
|
+
}
|
|
434
|
+
case 'public-input-gone':
|
|
435
|
+
return {
|
|
436
|
+
message: say(key('message'), { ...v, input: change.subject ?? '' }, `'${change.subject}' is no longer set on a board.`),
|
|
437
|
+
why: say(key('why'), {}, 'Values placed instances give it do nothing after this release.')
|
|
438
|
+
}
|
|
439
|
+
case 'public-input-range-narrowed':
|
|
440
|
+
return {
|
|
441
|
+
message: say(key('message'), { ...v, input: change.subject ?? '' }, `The range of '${change.subject}' narrowed from ${v.before} to ${v.after}.`),
|
|
442
|
+
why: say(key('why'), {}, 'An instance may have set a value outside the new range. Which values are placed is not recorded.')
|
|
443
|
+
}
|
|
444
|
+
case 'public-input-added':
|
|
445
|
+
return {
|
|
446
|
+
message: say(key('message'), { ...v, input: change.subject ?? '' }, `'${change.subject}' can now be set on a board.`),
|
|
447
|
+
why: say(key('why'), {}, 'Placed instances that give no value stand at its default.')
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* What a release records about itself (ADR-0104 decision 5): the format its asset is written in, and what changed
|
|
454
|
+
* against the previous release -- the kernel's own comparison, kept as it was then so a consumer that pins releases
|
|
455
|
+
* reads it rather than computing it again. `[]` for a first release; `null` when the previous release could not be
|
|
456
|
+
* read, which is a different fact from "nothing changed".
|
|
457
|
+
*/
|
|
458
|
+
export function releaseRecordOf(sourceJson: string, releasedJson?: string | null): { format: string; changes: FigureContractChange[] | null } {
|
|
459
|
+
const asset = parseFigureAsset(sourceJson)
|
|
460
|
+
if (!releasedJson) return { format: asset.version, changes: [] }
|
|
461
|
+
let before: FigureAsset
|
|
462
|
+
try {
|
|
463
|
+
before = parseFigureAsset(releasedJson)
|
|
464
|
+
} catch {
|
|
465
|
+
return { format: asset.version, changes: null }
|
|
423
466
|
}
|
|
467
|
+
return { format: asset.version, changes: figureContractChanges(before, asset) }
|
|
424
468
|
}
|
|
425
469
|
|
|
426
470
|
/**
|
|
@@ -94,6 +94,22 @@ export class FigureHistory implements HistoryEntityInterface<Figure> {
|
|
|
94
94
|
@Field({ nullable: true, description: 'The note left when this version was released.' })
|
|
95
95
|
comment?: string
|
|
96
96
|
|
|
97
|
+
/*
|
|
98
|
+
* 이 판의 정본 형식(`figure-asset-1`)과, 직전 판에 견준 변경(ADR-0104 결정 5). 발행할 때 한 번 정하고 다시
|
|
99
|
+
* 계산하지 않는다 — 판을 고정해 쓰는 쪽은 다음 판으로 옮기기 전에 이것을 읽는다.
|
|
100
|
+
*/
|
|
101
|
+
@Column({ nullable: true })
|
|
102
|
+
@Field({ nullable: true, description: 'The asset format this version was written in (figure-asset-1).' })
|
|
103
|
+
assetFormat?: string
|
|
104
|
+
|
|
105
|
+
@Column({ nullable: true, ...longTextColumn() })
|
|
106
|
+
@Field({
|
|
107
|
+
nullable: true,
|
|
108
|
+
description:
|
|
109
|
+
'What changed against the previous release, as JSON: [{ code, blocking, subject?, values, detail }]. [] for the first release; null when the previous release could not be read.'
|
|
110
|
+
})
|
|
111
|
+
changes?: string
|
|
112
|
+
|
|
97
113
|
@Column({ nullable: true })
|
|
98
114
|
@Field({ nullable: true, description: 'When the original figure was created.' })
|
|
99
115
|
createdAt?: Date
|
|
@@ -11,7 +11,7 @@ import { FigureReplacedDraft } from './figure-replaced-draft.js'
|
|
|
11
11
|
import { revertKeepingDraft, undoRevert } from './figure-revert.js'
|
|
12
12
|
import { recordProposals } from './figure-proposal.js'
|
|
13
13
|
import { FigureProposal, ProposeRequest } from './figure-propose-type.js'
|
|
14
|
-
import { inspectSource } from './figure-format.js'
|
|
14
|
+
import { inspectSource, releaseRecordOf } from './figure-format.js'
|
|
15
15
|
import { renameDraftType, renameFacts } from './figure-rename.js'
|
|
16
16
|
import { parseSource } from './figure-format.js'
|
|
17
17
|
import { ProposeFigureFailure, proposeFigureSteps } from './figure-propose-steps.js'
|
|
@@ -319,6 +319,8 @@ export class FigureMutation {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
const nextVersion = released?.version ? Number(released.version) + 1 : 1
|
|
322
|
+
/* What this release records about itself: its format, and what changed against the last one (ADR-0104). */
|
|
323
|
+
const record = releaseRecordOf(figure.source!, released?.source)
|
|
322
324
|
|
|
323
325
|
return await repository.save({
|
|
324
326
|
/*
|
|
@@ -333,8 +335,10 @@ export class FigureMutation {
|
|
|
333
335
|
version: nextVersion,
|
|
334
336
|
state: 'released',
|
|
335
337
|
updater: user,
|
|
336
|
-
/* 판본 구독자가
|
|
337
|
-
__releaseComment: comment ?? null
|
|
338
|
+
/* 판본 구독자가 이것들을 판본의 comment · assetFormat · changes 로 옮긴다. Figure 의 칸이 아니다. */
|
|
339
|
+
__releaseComment: comment ?? null,
|
|
340
|
+
__releaseFormat: record.format,
|
|
341
|
+
__releaseChanges: record.changes
|
|
338
342
|
} as any)
|
|
339
343
|
}
|
|
340
344
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A release keeps its format and what changed against the last one on its history row -- on sqlite, through the
|
|
3
|
+
* subscriber that writes history (ADR-0104 decision 5). `[]` and `null` stay apart: nothing changed is not "not compared".
|
|
4
|
+
*/
|
|
5
|
+
import type { DataSource } from 'typeorm'
|
|
6
|
+
|
|
7
|
+
const { DataSource: TypeOrmDataSource } = require('typeorm')
|
|
8
|
+
const shell = require('@things-factory/shell')
|
|
9
|
+
const authBase = require('@things-factory/auth-base')
|
|
10
|
+
const { createFigureAsset, addFigureBox, serializeFigureAsset, applyFigureAuthoring, proposeFigureOccupancy } = require('@hatiolab/figure-model')
|
|
11
|
+
|
|
12
|
+
let dataSource: DataSource | null = null
|
|
13
|
+
let Figure: any
|
|
14
|
+
let FigureHistory: any
|
|
15
|
+
let Subscriber: any
|
|
16
|
+
let FigureMutation: any
|
|
17
|
+
|
|
18
|
+
function loadCompiled(modulePath: string): any {
|
|
19
|
+
const { existsSync } = require('fs')
|
|
20
|
+
const { join } = require('path')
|
|
21
|
+
const resolved = join(__dirname, '..', '..', '..', 'dist-server', `${modulePath}.js`)
|
|
22
|
+
if (!existsSync(resolved))
|
|
23
|
+
throw new Error(`figure-service 산출물이 없다: ${resolved}\n먼저 빌드할 것:\n yarn workspace @things-factory/figure-service build:server`)
|
|
24
|
+
return require(resolved)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
Figure = loadCompiled('service/figure/figure').Figure
|
|
29
|
+
FigureHistory = loadCompiled('service/figure/figure-history').FigureHistory
|
|
30
|
+
Subscriber = loadCompiled('service/figure/event-subscriber').FigureHistoryEntitySubscriber
|
|
31
|
+
FigureMutation = loadCompiled('service/figure/figure-mutation').FigureMutation
|
|
32
|
+
dataSource = new TypeOrmDataSource({
|
|
33
|
+
type: 'sqlite',
|
|
34
|
+
database: ':memory:',
|
|
35
|
+
synchronize: true,
|
|
36
|
+
dropSchema: true,
|
|
37
|
+
namingStrategy: new shell.NamingStrategy(),
|
|
38
|
+
entities: [...shell.entities, ...authBase.entities, Figure, FigureHistory],
|
|
39
|
+
subscribers: [Subscriber],
|
|
40
|
+
logging: false
|
|
41
|
+
})
|
|
42
|
+
await dataSource.initialize()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
afterAll(async () => {
|
|
46
|
+
await dataSource?.destroy()
|
|
47
|
+
dataSource = null
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const SOURCE = serializeFigureAsset(addFigureBox(createFigureAsset('Probe'), { id: 'body', size: { x: 100, y: 100, z: 100 }, position: { x: 0, y: 50, z: 0 } }))
|
|
51
|
+
|
|
52
|
+
async function release(extra: Record<string, unknown>) {
|
|
53
|
+
const domain = await dataSource!.getRepository(shell.Domain).save({ name: `d-${Math.random()}`, subdomain: `d${Date.now()}${Math.random()}` })
|
|
54
|
+
const figure = await dataSource!.getRepository(Figure).save({ type: 'RECORD_PROBE', name: 'probe', source: SOURCE, state: 'draft', version: 0, domain })
|
|
55
|
+
await dataSource!.getRepository(Figure).save({ ...figure, domain, version: 1, state: 'released', __releaseComment: 'first', ...extra })
|
|
56
|
+
return dataSource!.getRepository(FigureHistory).findOneOrFail({ where: { originalId: figure.id } })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe('a release record on its history row', () => {
|
|
60
|
+
it('keeps the format and the changes as they were', async () => {
|
|
61
|
+
const changes = [{ code: 'occupancy-changed', blocking: false, values: { before: 'x -50…50', after: 'x -150…150' }, detail: 'declared room changed' }]
|
|
62
|
+
const row = await release({ __releaseFormat: 'figure-asset-1', __releaseChanges: changes })
|
|
63
|
+
expect(row.assetFormat).toBe('figure-asset-1')
|
|
64
|
+
expect(JSON.parse(row.changes)).toEqual(changes)
|
|
65
|
+
expect(row.comment).toBe('first')
|
|
66
|
+
})
|
|
67
|
+
it('[] stays nothing changed, null stays not compared', async () => {
|
|
68
|
+
expect((await release({ __releaseFormat: 'figure-asset-1', __releaseChanges: [] })).changes).toBe('[]')
|
|
69
|
+
expect((await release({ __releaseFormat: 'figure-asset-1', __releaseChanges: null })).changes).toBeNull()
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
/* The whole door, called as the resolver is: releaseFigure works the record out and the row carries it. */
|
|
74
|
+
describe('releaseFigure records it', () => {
|
|
75
|
+
const releasable = (width: number) => {
|
|
76
|
+
let a = addFigureBox(createFigureAsset('Mixer'), { id: 'body', size: { x: width, y: 100, z: 100 }, position: { x: 0, y: 50, z: 0 } })
|
|
77
|
+
a = applyFigureAuthoring(a, { kind: 'attach', part: 'body', face: 'bottom', to: { plane: 'mounting-plane' } })
|
|
78
|
+
return serializeFigureAsset(applyFigureAuthoring(a, { kind: 'declare-occupancy', proposal: proposeFigureOccupancy(a, { over: 'range' }), placement: 'floor' }))
|
|
79
|
+
}
|
|
80
|
+
it('first release: [], the second: the wider room', async () => {
|
|
81
|
+
const domain = await dataSource!.getRepository(shell.Domain).save({ name: 'release-door', subdomain: 'release-door' })
|
|
82
|
+
const tx = dataSource!.manager
|
|
83
|
+
const context = { state: { domain, user: undefined, tx } }
|
|
84
|
+
const figure = await dataSource!.getRepository(Figure).save({ type: 'RELEASE_DOOR', name: 'door', source: releasable(100), state: 'draft', version: 0, domain })
|
|
85
|
+
await new FigureMutation().releaseFigure(figure.id, 'one', context)
|
|
86
|
+
await dataSource!.getRepository(Figure).save({ ...(await dataSource!.getRepository(Figure).findOneOrFail({ where: { id: figure.id } })), domain, source: releasable(300), state: 'draft' })
|
|
87
|
+
await new FigureMutation().releaseFigure(figure.id, 'two', context)
|
|
88
|
+
const rows = await dataSource!.getRepository(FigureHistory).find({ where: { originalId: figure.id }, order: { version: 'ASC' } })
|
|
89
|
+
expect(rows.map((r: any) => [r.version, r.assetFormat, r.comment])).toEqual([[1, 'figure-asset-1', 'one'], [2, 'figure-asset-1', 'two']])
|
|
90
|
+
expect(rows[0].changes).toBe('[]')
|
|
91
|
+
const codes = JSON.parse(rows[1].changes).map((c: any) => c.code)
|
|
92
|
+
expect(codes).toContain('occupancy-changed')
|
|
93
|
+
})
|
|
94
|
+
})
|
package/translations/en.json
CHANGED
|
@@ -64,5 +64,15 @@
|
|
|
64
64
|
"figure.gate.contract.capability-gone.message": "The capability '{name}' is gone.",
|
|
65
65
|
"figure.gate.contract.capability-gone.why": "Scenes attach behaviour by this name. Placed instances lose what it did.",
|
|
66
66
|
"figure.gate.contract.capability-added.message": "The capability '{name}' is new.",
|
|
67
|
-
"figure.gate.contract.capability-added.why": "It adds what the figure can do. Placed instances stand as they are."
|
|
67
|
+
"figure.gate.contract.capability-added.why": "It adds what the figure can do. Placed instances stand as they are.",
|
|
68
|
+
"figure.gate.contract.occupancy-changed.message": "The room the figure takes changed: {before} → {after}.",
|
|
69
|
+
"figure.gate.contract.occupancy-changed.why": "A consumer places the figure by this room. One that moves to this release sees it take the new room.",
|
|
70
|
+
"figure.gate.contract.contact-face-changed.message": "The face the figure is mounted by changed.",
|
|
71
|
+
"figure.gate.contract.contact-face-changed.why": "A consumer that moves to this release sees it stand on the new face.",
|
|
72
|
+
"figure.gate.contract.public-input-gone.message": "'{input}' is no longer set on a board.",
|
|
73
|
+
"figure.gate.contract.public-input-gone.why": "Values placed instances give it do nothing after this release.",
|
|
74
|
+
"figure.gate.contract.public-input-range-narrowed.message": "The range of '{input}' narrowed: {before} → {after}.",
|
|
75
|
+
"figure.gate.contract.public-input-range-narrowed.why": "An instance may have set a value outside the new range. Which values are placed is not recorded.",
|
|
76
|
+
"figure.gate.contract.public-input-added.message": "'{input}' can now be set on a board.",
|
|
77
|
+
"figure.gate.contract.public-input-added.why": "Placed instances that give no value stand at its default."
|
|
68
78
|
}
|
package/translations/ko.json
CHANGED
|
@@ -64,5 +64,15 @@
|
|
|
64
64
|
"figure.gate.contract.capability-gone.message": "'{name}' 능력이 없어졌습니다.",
|
|
65
65
|
"figure.gate.contract.capability-gone.why": "씬이 이 이름으로 동작을 붙입니다. 놓인 인스턴스가 그 동작을 잃습니다.",
|
|
66
66
|
"figure.gate.contract.capability-added.message": "'{name}' 능력이 새로 생겼습니다.",
|
|
67
|
-
"figure.gate.contract.capability-added.why": "도형이 할 수 있는 일이 늘어납니다. 놓인 인스턴스는 그대로 서 있습니다."
|
|
67
|
+
"figure.gate.contract.capability-added.why": "도형이 할 수 있는 일이 늘어납니다. 놓인 인스턴스는 그대로 서 있습니다.",
|
|
68
|
+
"figure.gate.contract.occupancy-changed.message": "도형이 차지하는 공간이 바뀌었습니다: {before} → {after}.",
|
|
69
|
+
"figure.gate.contract.occupancy-changed.why": "받는 쪽은 이 공간으로 도형을 놓습니다. 이 발행본으로 옮기면 새 공간으로 놓입니다.",
|
|
70
|
+
"figure.gate.contract.contact-face-changed.message": "도형이 붙는 면이 바뀌었습니다.",
|
|
71
|
+
"figure.gate.contract.contact-face-changed.why": "이 발행본으로 옮기면 새 면으로 섭니다.",
|
|
72
|
+
"figure.gate.contract.public-input-gone.message": "'{input}' 값은 이제 보드에서 정할 수 없습니다.",
|
|
73
|
+
"figure.gate.contract.public-input-gone.why": "놓인 인스턴스가 준 값은 이 발행본부터 아무 일도 하지 않습니다.",
|
|
74
|
+
"figure.gate.contract.public-input-range-narrowed.message": "'{input}' 값의 범위가 좁아졌습니다: {before} → {after}.",
|
|
75
|
+
"figure.gate.contract.public-input-range-narrowed.why": "새 범위 밖의 값을 준 인스턴스가 있을 수 있습니다. 어떤 값이 놓였는지는 기록하지 않습니다.",
|
|
76
|
+
"figure.gate.contract.public-input-added.message": "'{input}' 값을 이제 보드에서 정할 수 있습니다.",
|
|
77
|
+
"figure.gate.contract.public-input-added.why": "값을 주지 않은 인스턴스는 기본값으로 섭니다."
|
|
68
78
|
}
|