54 lines
8.1 KiB
JavaScript
54 lines
8.1 KiB
JavaScript
import fs from 'node:fs';
|
|
const b='work/trilium';
|
|
fs.mkdirSync(b+'/release',{recursive:true});
|
|
let ko=JSON.parse(fs.readFileSync(b+'/translation.ko.json'));
|
|
let overrides=JSON.parse(fs.readFileSync(b+'/ui-overrides.json'));
|
|
function set(k,v){let keys=k.split('.'),o=ko;for(let p of keys.slice(0,-1))o=o[p];if(!(keys.at(-1) in o))throw Error(k);o[keys.at(-1)]=v}
|
|
for(let[k,v]of Object.entries(overrides))set(k,v);
|
|
for(let k of ['add_label.label_name_title','delete_label.label_name_title','rename_label.name_title','update_label_value.label_name_title','add_relation.allowed_characters','delete_relation.allowed_characters','rename_relation.allowed_characters','update_relation_target.allowed_characters'])set(k,'영문자와 숫자 및 콜론과 밑줄만 사용할 수 있습니다.');
|
|
set('attribute_detail.print_page_size','PDF로 내보낼 때의 용지 크기입니다. A0~A6와 Legal 및 Letter를 지원합니다. Tabloid와 Ledger도 사용할 수 있습니다.');
|
|
set('attribute_detail.title_template','하위 노트를 만들 때 사용할 기본 제목입니다. JavaScript 문자열로 처리되므로 <code>now</code>와 <code>parentNote</code> 변수를 사용할 수 있습니다.<ul><li><code>${parentNote.getLabelValue(\'authorName\')}의 작품</code></li><li><code>${now.format(\'YYYY-MM-DD HH:mm:ss\')} 기록</code></li></ul>자세한 내용은 <a href="https://triliumnext.github.io/Docs/Wiki/default-note-title.html">도움말</a>과 <a href="https://zadam.github.io/trilium/backend_api/Note.html">parentNote API</a> 및 <a href="https://day.js.org/docs/en/display/format">now API</a> 문서를 참고하세요.');
|
|
fs.writeFileSync(b+'/release/translation.json',JSON.stringify(ko,null,2)+'\n');
|
|
const official=await import('data:text/javascript;base64,'+fs.readFileSync(b+'/ckeditor.ko.official.js').toString('base64'));
|
|
const dict=official.default.ko.dictionary;
|
|
Object.assign(dict,{
|
|
'Include note':'노트 포함','Keyboard shortcut':'단축키','Insert mermaid source code':'Mermaid 소스 코드 입력','Mermaid widget':'Mermaid 다이어그램','Mermaid toolbar':'Mermaid 도구 모음','Insert Mermaid diagram':'Mermaid 다이어그램 삽입','Read more about Mermaid diagram syntax':'Mermaid 다이어그램 문법 도움말','Equation preview':'수식 미리 보기','Insert equation in TeX format.':'TeX 형식으로 수식을 입력하세요.','Display mode':'표시 방식','Insert math':'수식 삽입','Code block copied to clipboard':'코드 블록을 클립보드에 복사했습니다.','No code block selected or found.':'선택한 코드 블록이 없거나 코드 블록을 찾을 수 없습니다.','Unable to find code block element to copy from.':'복사할 코드 블록을 찾을 수 없습니다.',
|
|
'Editor toolbar':'편집 도구 모음','Text formatting':'글자 서식','Italic':'기울임','Paragraph':'본문','Bulleted List':'글머리 기호 목록','Numbered List':'번호 목록','To-do List':'체크리스트','Show more items':'도구 더 보기','Font Size':'글자 크기','Font Color':'글자 색상','Font Background Color':'글자 배경색','Remove Format':'서식 지우기','Text Alternative':'대체 텍스트','Block quote':'인용문','Widget toolbar':'위젯 도구 모음',
|
|
'Keystrokes that can be used when a widget is selected (for example: image, table, etc.)':'이미지나 표 등의 위젯을 선택했을 때 사용할 수 있는 단축키',
|
|
'Move focus between form fields (inputs, buttons, etc.)':'입력란과 버튼 사이에서 초점 이동',
|
|
'Move focus to the toolbar, navigate between toolbars':'도구 모음으로 초점 이동 또는 도구 모음 사이 이동',
|
|
'Move focus to the menu bar, navigate between menu bars':'메뉴 모음으로 초점 이동 또는 메뉴 모음 사이 이동',
|
|
'Close contextual balloons, dropdowns, and dialogs':'팝업과 펼침 메뉴 및 대화상자 닫기',
|
|
'Rich Text Editor':'서식 있는 텍스트 편집기','Rich Text Editor. Editing area: %0':'서식 있는 텍스트 편집기. 편집 영역: %0',
|
|
'TeX':'TeX','Mermaid':'Mermaid','Copy':'복사','Preview':'미리 보기','Source':'소스','Cancel':'취소','Save':'저장'
|
|
});
|
|
Object.assign(dict,{'Admonition':'안내 상자','Insert table':'표 삽입','Insert code block':'코드 블록 삽입','Code block':'코드 블록','Rich Text Editor. Editing area: %0':'서식 있는 본문 편집기'});
|
|
fs.writeFileSync(b+'/release/ckeditor-ko.js','/* CKEditor 45.2.0 Korean translations. Copyright CKSource. See https://ckeditor.com/legal/ckeditor-licensing-options */\nexport default '+JSON.stringify({ko:{dictionary:dict}})+';\n');
|
|
let layout=fs.readFileSync(b+'/layout_commons.js','utf8');
|
|
if((layout.match(/clipboard:\{copy:ib\},language:"en"/g)||[]).length!==1)throw Error('Unexpected editor language occurrences');
|
|
layout='import triliumKoreanEditorTranslations from "./ckeditor-ko.js";\n'+layout.replace('clipboard:{copy:ib},language:"en"','clipboard:{copy:ib},language:"ko",translations:triliumKoreanEditorTranslations').replace('a.language:"en",content:l','a.language:"ko",content:l');
|
|
layout=layout.replace('label:"Text formatting"','label:"글자 서식"').replace('title:"Block align"','title:"블록 정렬"');
|
|
layout=layout.replace('new e({theme:this.themeStyle,onChange:','new e({langCode:"ko-KR",theme:this.themeStyle,onChange:');
|
|
layout=layout.replace('new this.MindElixir({el:this.$content[0],direction:','new this.MindElixir({locale:"ko",el:this.$content[0],direction:');
|
|
const mindKo={addChild:'하위 항목 추가',addParent:'상위 항목 추가',addSibling:'같은 단계의 항목 추가',removeNode:'항목 삭제',focus:'집중 모드',cancelFocus:'집중 모드 해제',moveUp:'위로 이동',moveDown:'아래로 이동',link:'연결',clickTips:'연결할 항목을 클릭하세요',font:'글자 색상',background:'배경색',tag:'태그',icon:'아이콘',tagsSeparate:'태그를 쉼표로 구분하세요',iconsSeparate:'아이콘을 쉼표로 구분하세요',url:'웹페이지 주소',memo:'메모',summary:'요약'};
|
|
layout=layout.replace('Yn={cn:vf,','Yn={ko:'+JSON.stringify(mindKo)+',cn:vf,');
|
|
layout=layout.replace('new URL("en.json",import.meta.url)','new URL("emoji-ko.json",import.meta.url)');
|
|
fs.writeFileSync(b+'/release/layout_commons.js',layout);
|
|
let editor=fs.readFileSync(b+'/ckeditor5.js','utf8');
|
|
editor=editor.replace('s9={note:{title:"Note"},tip:{title:"Tip"},important:{title:"Important"},caution:{title:"Caution"},warning:{title:"Warning"}}','s9={note:{title:"참고"},tip:{title:"도움말"},important:{title:"중요"},caution:{title:"주의"},warning:{title:"경고"}}');
|
|
fs.writeFileSync(b+'/release/ckeditor5.js',editor);
|
|
let mind=fs.readFileSync(b+'/MindElixir.js','utf8');
|
|
mind=mind.replace(/ko:\{addChild:"자식 추가"[^}]+\}/,'ko:'+JSON.stringify(mindKo));
|
|
for(const[k,v]of Object.entries({'Bidirectional Link':'양방향 연결','Can not remove root node':'최상위 항목은 삭제할 수 없습니다','Custom Link':'사용자 지정 연결','No selected node.':'선택한 항목이 없습니다.','Can not select root node.':'최상위 항목은 선택할 수 없습니다.','Please select nodes in the same main topic.':'같은 주제에 속한 항목을 선택하세요.'}))mind=mind.replaceAll(JSON.stringify(k),JSON.stringify(v));
|
|
fs.writeFileSync(b+'/release/MindElixir.js',mind);
|
|
const rawEmoji=JSON.parse(fs.readFileSync(b+'/emoji-en.json'));
|
|
const cldr={...JSON.parse(fs.readFileSync(b+'/emoji-cldr-ko.json')).annotations.annotations,...JSON.parse(fs.readFileSync(b+'/emoji-cldr-derived-ko.json')).annotationsDerived.annotations};
|
|
const canon=s=>s.replace(/\uFE0F/g,'');
|
|
const emojiMap=Object.fromEntries(Object.entries(cldr).map(([k,v])=>[canon(k),v]));
|
|
const missingEmoji=[];
|
|
function localizeEmoji(items){for(const item of items){const found=emojiMap[canon(item.emoji)];if(found){item.annotation=found.tts[0].replace(/, /g,' · ');item.tags=found.default||[];}else missingEmoji.push({emoji:item.emoji,annotation:item.annotation});if(item.skins)localizeEmoji(item.skins)}}
|
|
localizeEmoji(rawEmoji);
|
|
fs.writeFileSync(b+'/release/emoji-ko.json',JSON.stringify(rawEmoji));
|
|
fs.writeFileSync(b+'/emoji-missing.json',JSON.stringify(missingEmoji,null,2));
|
|
console.log(JSON.stringify({uiOverrides:Object.keys(overrides).length+10,editorTranslations:Object.keys(dict).length}));
|