새 원문과 이전 한국어를 키별로 비교해 추가와 변경 및 삭제를 구분한다. 배포 파일 변경 비교와 기준 해시 및 후속 작업 문서를 추가했다. 자동 검사 4개와 UI 문구 1496개 비교 및 기존 배포 파일 492개 무결성 검사를 통과했다. 운영 앱과 DB는 변경하지 않았으며 기존 배포 커밋 eddda22를 보존한다. 코드와 도움말 이식 및 새 버전 실행 검증은 대상 버전 작업 때 수행한다.
52 lines
2.9 KiB
JavaScript
52 lines
2.9 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { compare } from './translation-upgrade.mjs';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
test('추가와 변경 및 삭제를 구분하고 기존 번역을 검토 후보로 보존한다', () => {
|
|
const result = compare({ same: 'Hello', changed: 'Old', gone: 'Gone' }, { same: '안녕하세요', changed: '이전', gone: '삭제' }, { same: 'Hello', changed: 'New', added: 'Add' });
|
|
assert.deepEqual(result.map(x => x.status), ['reusable', 'source-changed', 'added', 'removed']);
|
|
assert.equal(result[1].korean, '이전');
|
|
});
|
|
test('자리표시자 누락과 미번역을 자동 재사용에서 제외한다', () => {
|
|
const en = { a: 'Hi {{name}}', b: 'Name', c: 'Value', d: 'Brand' };
|
|
assert.deepEqual(compare(en, { a: '안녕', b: '', d: 'Brand' }, en).map(x => x.status), ['placeholder-mismatch', 'missing', 'missing', 'review-identical']);
|
|
});
|
|
test('점이 포함된 키와 중첩 키 및 배열을 구분한다', () => {
|
|
const en = { 'a.b': 'One', a: { b: 'Two' }, list: ['Three'] };
|
|
const ko = { 'a.b': '하나', a: { b: '둘' }, list: ['셋'] };
|
|
assert.equal(compare(en, ko, en).filter(x => x.status === 'reusable').length, 3);
|
|
});
|
|
|
|
test('파일 비교는 변경과 삭제 및 추가를 구분하고 기존 보고서를 덮어쓰지 않는다', () => {
|
|
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'trilium-translation-'));
|
|
try {
|
|
const old = path.join(temp, 'old'), next = path.join(temp, 'next');
|
|
fs.mkdirSync(old); fs.mkdirSync(next);
|
|
fs.writeFileSync(path.join(old, 'main.cjs'), 'old');
|
|
fs.writeFileSync(path.join(next, 'main.cjs'), 'next');
|
|
fs.mkdirSync(path.join(old, 'assets/db'), { recursive: true });
|
|
fs.writeFileSync(path.join(old, 'assets/db/demo.zip'), 'old-demo');
|
|
fs.mkdirSync(path.join(next, 'public/src'), { recursive: true });
|
|
fs.writeFileSync(path.join(next, 'public/src/ko.js'), 'next-ko');
|
|
const output = path.join(temp, 'report.json');
|
|
const tool = fileURLToPath(new URL('./translation-files.mjs', import.meta.url));
|
|
const run = () => spawnSync(process.execPath, [tool, old, next, output], { encoding: 'utf8' });
|
|
assert.equal(run().status, 0);
|
|
const saved = fs.readFileSync(output, 'utf8');
|
|
const entries = JSON.parse(saved).files;
|
|
assert.equal(entries.find(x => x.file === 'main.cjs').status, 'upstream-changed');
|
|
assert.equal(entries.find(x => x.file === 'assets/db/demo.zip').status, 'removed-or-moved');
|
|
assert.equal(entries.find(x => x.file === 'public/src/ko.js').status, 'new-upstream-path');
|
|
assert.notEqual(run().status, 0);
|
|
assert.equal(fs.readFileSync(output, 'utf8'), saved);
|
|
} finally {
|
|
// 이 검사에서 만든 임시 폴더만 정리한다. 사용자 자료 경로는 받지 않는다.
|
|
fs.rmSync(temp, { recursive: true, force: true });
|
|
}
|
|
});
|