예제 PDF와 통계 및 표시 속성 한글화와 검증 기록

This commit is contained in:
Codex
2026-09-13 17:19:45 +09:00
parent 77c2892aba
commit 087e80126d
28 changed files with 16165 additions and 83 deletions
@@ -0,0 +1,53 @@
import fs from 'node:fs';import crypto from 'node:crypto';
const b='work/trilium',out=b+'/phase6';fs.mkdirSync(out,{recursive:true});
const source=JSON.parse(fs.readFileSync(b+'/release/translation.json','utf8'));
const translated=structuredClone(source),changes=[];
function walk(o,p=''){for(const[k,v]of Object.entries(o)){if(typeof v==='object'&&v)walk(v,p+k+'.');else if(typeof v==='string'){
let next=v.replaceAll('런처 바','실행 도구 모음').replaceAll('런치바','실행 도구 모음').replaceAll('런처','실행 도구').replaceAll('리비전','수정 이력').replaceAll('외관','모양');
if(next!==v){changes.push({key:p+k,before:v,after:next});o[k]=next;}
}}}
walk(translated);
const overrides={
'about.build_revision':'빌드 버전:',
'revisions.note_revisions':'노트 수정 이력',
'revisions.revision_last_edited':'이 버전은 {{date}}에 마지막으로 수정되었습니다.',
'revisions.no_revisions':'아직 저장된 수정 이력이 없습니다.',
'revisions.confirm_restore':'이 버전으로 복원하시겠습니까? 현재 제목과 본문이 선택한 버전의 내용으로 바뀝니다.',
'revisions.confirm_delete':'이 수정 이력을 삭제하시겠습니까?',
'revisions.revision_restored':'선택한 버전으로 복원했습니다.',
'revisions.snapshot_interval':'수정 이력 자동 저장 간격: {{seconds}}초',
'revisions.maximum_revisions':'보관할 수정 이력 수: {{number}}개',
'attachments_actions.upload_new_revision':'새 버전 올리기',
'attachments_actions.upload_success':'첨부 파일을 새 버전으로 교체했습니다.',
'attachments_actions.upload_failed':'첨부 파일의 새 버전을 올리지 못했습니다.',
'file_properties.upload_new_revision':'새 버전 올리기',
'file_properties.upload_success':'파일을 새 버전으로 교체했습니다.',
'file_properties.upload_failed':'파일의 새 버전을 올리지 못했습니다.',
'image_properties.upload_new_revision':'새 버전 올리기',
'image_properties.upload_success':'이미지를 새 버전으로 교체했습니다.',
'image_properties.upload_failed':'이미지의 새 버전을 올리지 못했습니다: {{message}}',
'global_menu.configure_launchbar':'실행 도구 모음 설정',
'spacer.configure_launchbar':'실행 도구 모음 설정',
'note_launcher.this_launcher_doesnt_define_target_note':'이 실행 도구에는 대상 노트가 지정되지 않았습니다.',
'revisions_snapshot_interval.note_revisions_snapshot_interval_title':'수정 이력 자동 저장 간격',
'revisions_snapshot_interval.snapshot_time_interval_label':'수정 이력 저장 간격:',
'revisions_snapshot_limit.note_revisions_snapshot_limit_title':'수정 이력 보관 개수',
'revisions_snapshot_limit.snapshot_number_limit_label':'최대 보관 개수:',
'revisions_snapshot_limit.erase_excess_revision_snapshots':'보관 개수를 초과한 수정 이력 삭제',
'revisions_snapshot_limit.erase_excess_revision_snapshots_prompt':'보관 개수를 초과한 수정 이력을 삭제했습니다.',
'theme.layout-vertical-description':'실행 도구 모음을 왼쪽에 배치합니다. 기본값입니다.',
'launcher_context_menu.reset_launcher_confirm':'“{{title}}”을 초기화하시겠습니까? 이 노트와 하위 노트의 데이터 및 설정이 사라지고 실행 도구가 원래 위치로 돌아갑니다.',
'launcher_context_menu.move-to-visible-launchers':'표시할 실행 도구로 이동'
};
for(const[key,value]of Object.entries(overrides)){const keys=key.split('.');let node=translated;for(const k of keys.slice(0,-1))node=node[k];const k=keys.at(-1);if(typeof node[k]!=='string')throw Error(key);changes.push({key,before:node[k],after:value});node[k]=value;}
const tokens=s=>JSON.stringify((s.match(/\{\{[^}]+\}\}/g)||[]).sort());
function validate(a,z,p=''){for(const[k,v]of Object.entries(a)){if(v&&typeof v==='object')validate(v,z[k],p+k+'.');else if(tokens(v)!==tokens(z[k]))throw Error('Placeholder mismatch '+p+k);}}
validate(source,translated);
fs.writeFileSync(out+'/translation.json',JSON.stringify(translated,null,2)+'\n');
fs.writeFileSync(out+'/wording-changes.json',JSON.stringify(changes,null,2)+'\n');
let main=fs.readFileSync(b+'/phase5/main.cjs','utf8');const original=main;
const from='jg=`assets/v${CR.version}-ko-20260913-r4`';if(main.split(from).length!==2)throw Error('Cache prefix mismatch');
main=main.replace(from,'jg=`assets/v${CR.version}-ko-20260913-r5`');fs.writeFileSync(out+'/main.cjs',main);
const hash=s=>crypto.createHash('sha256').update(s).digest('hex');
fs.writeFileSync(out+'/manifest.json',JSON.stringify({previousMainSha256:hash(original),previousTranslationSha256:hash(fs.readFileSync(b+'/release/translation.json')),files:Object.fromEntries(['main.cjs','translation.json'].map(n=>[n,hash(fs.readFileSync(out+'/'+n))]))},null,2));
console.log({wordingEdits:changes.length,placeholders:'preserved'});