한국어 배포판 2.0.0 통합과 신규 설치 및 업데이트 복구 검증
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
# TriliumNext Notes 한국어 패치 (번역 + main.cjs 패치)
|
||||
|
||||
최신 진행 상황: [2026-09-13 작업 기록](updates/2026-09-05/PROGRESS.md). 도움말 본문 173개와 제목 181개를 운영 서버에 반영했습니다. 전체 한글화는 추가 점검 중입니다.
|
||||
|
||||
## 2026-09-05 후속 작업
|
||||
|
||||
[최신 작업 상태와 파일](updates/2026-09-05/README.md) 및 [상세 변경 기록](updates/2026-09-05/CHANGELOG.ko.md)을 추가했습니다. 운영 서버에는 예제 노트 148개 수정과 편집기 한국어 사전 719개 문구 등을 반영했습니다. 2026-09-13에 기본 도움말 전체와 목록 제목을 서버에 반영했습니다. 전체 한글화는 진행 중입니다.
|
||||
|
||||
아래의 기존 설치 안내와 v1.0.0 다운로드는 이전 배포판에 대한 설명입니다. 이번 작업 폴더의 파일은 기존 설치 프로그램에 자동으로 포함되지 않습니다.
|
||||
|
||||
[TriliumNext Notes](https://github.com/TriliumNext/Notes)의 비공식 커뮤니티 한국어 번역입니다.
|
||||
이 글을 쓰는 시점 기준으로 TriliumNext는 한국어 언어팩이 없고, 심지어 UI 언어 선택기에
|
||||
뜨는 지원 언어 목록 자체가 `translations/` 폴더를 스캔해서 만들어지는 게 아니라 **컴파일된
|
||||
서버 번들(`main.cjs`) 안에 하드코딩된 배열**이라서, 번역 파일만 올바른 경로에 넣는다고
|
||||
"한국어"가 언어 선택기에 나타나지 않습니다. 그래서 번역 파일 외에 서버 번들을 패치하는
|
||||
스크립트도 함께 제공합니다.
|
||||
|
||||
## 압축 파일로 받기
|
||||
|
||||
Git 없이 필요한 파일만 바로 받고 싶다면 압축된 배포판을 받으세요. 두 종류가 있습니다
|
||||
([릴리스 페이지](https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/releases/tag/v1.0.0)):
|
||||
|
||||
- **[triliumnext-korean-patch.zip 다운로드](https://gitea.itosm.co.kr/attachments/11f09ff6-4d85-4234-8360-a4ae968dd437)**
|
||||
(2.5MB) — **처음 새로 설치하는 경우.** `Dockerfile`, `install.sh`, `docker-compose.yml`까지
|
||||
전부 포함되어 있어서, 압축을 풀고 `./install.sh`를 실행하거나 `docker compose up -d --build`를
|
||||
실행하면 한국어가 내장된 새 컨테이너가 만들어집니다.
|
||||
- **[triliumnext-korean-patch-only.zip 다운로드](https://gitea.itosm.co.kr/attachments/679762e6-8b68-48e4-9954-82a2163750a8)**
|
||||
(2.4MB) — **이미 Trilium을 운영 중인 경우.** 이미지를 새로 빌드하거나 컨테이너를 새로
|
||||
만들지 않고, 기존 데이터/설정을 그대로 둔 채 파일 3개만 bind-mount로 추가합니다.
|
||||
압축 안의 `README.md`에 기존 `docker-compose.yml`에 반영하는 방법이 자세히 적혀 있습니다.
|
||||
|
||||
## 포함된 파일
|
||||
|
||||
- `install.sh` — **원클릭 설치 스크립트**. 명령어 한 줄로 저장소를 내려받고, 한국어가
|
||||
내장된 이미지를 빌드해서 바로 실행시킵니다.
|
||||
- `Dockerfile` — `triliumnext/notes:latest` 위에 번역 파일과 패치된 `main.cjs`를
|
||||
구워 넣어서, 별도 bind-mount 없이 한국어가 기본 내장된 이미지를 만듭니다.
|
||||
- `docker-compose.yml` — 위 `Dockerfile`로 빌드해서 바로 띄우는 compose 파일
|
||||
(`install.sh`가 내부적으로 이걸 사용합니다).
|
||||
- `translation.json` — 클라이언트(브라우저) UI 문자열, 1,712개 키, 100% 번역 완료.
|
||||
- `server.json` — 서버 문자열, 283개 키, 100% 번역 완료.
|
||||
- `main.cjs` — **이미 패치가 적용된, 바로 쓸 수 있는 서버 번들** (`triliumnext/notes:latest`,
|
||||
빌드일 2025-06-07, appVersion 0.95.0 기준).
|
||||
- `patch_main_cjs.js` — 위 `main.cjs`를 만들어낸 패치 스크립트. 다른 버전의 이미지를 쓰거나
|
||||
이미지가 업데이트된 경우, 이 스크립트를 새 원본 `main.cjs`에 다시 돌려서 직접 패치된
|
||||
파일을 만들어야 합니다 (왜 이게 필요한지는 스크립트 상단 주석 참고).
|
||||
- `docker-compose.bind-mount.yml.example` — 이미 떠 있는 공식 이미지 컨테이너에 파일만
|
||||
bind-mount로 추가하고 싶을 때 쓰는 예시 (이미지를 새로 빌드하지 않는 방식).
|
||||
|
||||
`triliumnext/notes:latest` (빌드일 2025-06-07, appVersion 0.95.0) 기준으로 테스트했습니다.
|
||||
`main.cjs` 안의 변수명은 전부 난독화(minify)되어 있고 **빌드마다 이름이 바뀔 수 있습니다** —
|
||||
`patch_main_cjs.js`를 새 이미지에 돌렸을 때 `[skip]`이 출력되면, 스크립트가 찾는 문자열
|
||||
패턴이 그 빌드에서 바뀐 것이니 새 빌드에서 같은 패턴을 다시 찾아 스크립트를 갱신해야 합니다.
|
||||
|
||||
## 설치 방법 — 명령어 한 줄 (추천)
|
||||
|
||||
Docker와 Docker Compose 플러그인만 설치되어 있으면 됩니다:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash
|
||||
```
|
||||
|
||||
기본적으로 `./trilium-korean` 폴더에 저장소를 내려받고, 한국어가 내장된 이미지를 빌드해서
|
||||
`http://localhost:8082`로 띄웁니다. 포트를 바꾸고 싶으면:
|
||||
|
||||
```bash
|
||||
TRILIUM_KO_PORT=9000 curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash
|
||||
```
|
||||
|
||||
설치가 끝나면 브라우저로 접속해서 초기 비밀번호를 설정한 뒤, **옵션 → 언어 및 지역**에서
|
||||
"한국어"를 선택하고 페이지를 새로고침하면 됩니다 (본문 텍스트까지 전부 한국어로 바뀌려면
|
||||
새로고침이 한 번 필요합니다 — 앱 자체의 동작이며 이 패치의 문제는 아닙니다).
|
||||
|
||||
업데이트하려면 같은 명령어를 같은 폴더에서 다시 실행하면 됩니다.
|
||||
|
||||
## 설치 방법 — 이미 떠 있는 컨테이너에 추가하고 싶은 경우
|
||||
|
||||
이미지를 새로 빌드하지 않고, 이미 쓰고 있는 공식 `triliumnext/notes` 컨테이너에 파일만
|
||||
얹고 싶다면:
|
||||
|
||||
1. **번역 파일 + `main.cjs`를 `docker-compose.yml`에 bind-mount로 등록**
|
||||
(`docker cp`로만 넣지 말 것 — 아래 "문제 4" 참고):
|
||||
- `main.cjs` → `/usr/src/app/main.cjs`
|
||||
- `translation.json` → `/usr/src/app/public/translations/ko/translation.json`
|
||||
- `server.json` → `/usr/src/app/assets/translations/ko/server.json`
|
||||
2. `docker-compose.bind-mount.yml.example`을 참고해서 그대로 적용, 컨테이너 재시작.
|
||||
3. 앱 안에서 **옵션 → 언어 및 지역**에서 "한국어" 선택 후 새로고침.
|
||||
|
||||
## 설치 방법 — 다른 이미지 버전을 쓰는 경우 (직접 패치)
|
||||
|
||||
이미지 버전이 다르면 `main.cjs`의 난독화된 변수명/위치가 달라 이 저장소의 `main.cjs`가
|
||||
그대로 안 맞을 수 있습니다. 이 경우 직접 패치해야 합니다:
|
||||
|
||||
1. 번역 파일은 위와 동일하게 bind-mount.
|
||||
2. **컨테이너의 원본(패치 안 된) `main.cjs`를 추출**하고 패치 스크립트 실행:
|
||||
```bash
|
||||
docker create --name trilium-tmp triliumnext/notes:latest
|
||||
docker cp trilium-tmp:/usr/src/app/main.cjs ./main.cjs
|
||||
docker rm trilium-tmp
|
||||
node patch_main_cjs.js ./main.cjs
|
||||
node --check ./main.cjs # 반드시 배포 전에 문법 검사
|
||||
```
|
||||
`[skip]`이 출력되면 스크립트가 찾는 문자열 패턴이 그 빌드에서 바뀐 것이니, 새 빌드에서
|
||||
같은 패턴을 다시 찾아 스크립트를 갱신해야 합니다 (아래 "빌드마다 달라짐" 참고).
|
||||
3. **패치된 `main.cjs`를 `docker-compose.yml`에서 원본 위치에 bind-mount** —
|
||||
`docker-compose.bind-mount.yml.example` 참고:
|
||||
```yaml
|
||||
services:
|
||||
trilium:
|
||||
image: triliumnext/notes:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '127.0.0.1:18082:8080'
|
||||
environment:
|
||||
- TZ=Asia/Seoul
|
||||
volumes:
|
||||
- ./data:/home/node/trilium-data
|
||||
- ./main.cjs:/usr/src/app/main.cjs:ro
|
||||
- ./translation.json:/usr/src/app/public/translations/ko/translation.json:ro
|
||||
- ./server.json:/usr/src/app/assets/translations/ko/server.json:ro
|
||||
```
|
||||
4. 컨테이너 시작 후 앱 안에서 **옵션 → 언어 및 지역**에서 "한국어" 선택.
|
||||
|
||||
## 겪었던 문제와 해결 (설치 전에 꼭 읽어보세요)
|
||||
|
||||
### 문제 1 — DB에서 `locale`을 직접 `'ko'`로 바꾸면 크래시
|
||||
|
||||
지원 언어 목록에 없는 값을 옵션 DB에 직접 넣으면 앱이 시작하다가 죽습니다. 이 방법으로는
|
||||
안 되고, 반드시 아래처럼 서버 번들 자체를 패치해야 합니다.
|
||||
|
||||
### 문제 2 — `main.cjs` 패치 위치를 잘못 잡으면 문법 자체가 깨짐
|
||||
|
||||
지원 언어 배열(테스트한 빌드에서 변수명 `K5i`)에 새 항목을 삽입할 때, 배열의 여는 대괄호
|
||||
`[` **바로 뒤**가 아니라 그 앞(변수 선언문 쪽)에 잘못 삽입하면 JS 문법 자체가 깨져서 앱이
|
||||
아예 뜨지 못하고 크래시를 반복합니다. `patch_main_cjs.js`는 이 위치를 정확히 계산해서
|
||||
삽입하지만, **패치 후에는 항상 `node --check`로 문법을 먼저 확인**하고 나서 컨테이너를
|
||||
재시작하세요.
|
||||
|
||||
### 문제 3 — 완전 재생성(`docker compose down && up`) 시에만 나타나는 크래시
|
||||
|
||||
지원 언어 배열만 고치면 `docker restart`로는 잘 동작하는 것처럼 보이지만, 컨테이너를 완전히
|
||||
내렸다 올리면(`down && up`) 다시 크래시합니다. 원인은 Trilium 자체 번역과는 별개로,
|
||||
**CKEditor 내장 다국어 리소스를 지연 로드하는 두 번째 하드코딩 맵**(테스트한 빌드에서
|
||||
변수명 `IMi`)에도 `ko` 항목이 없어서 발생하는 `TypeError`입니다. 이 리소스는 애초에
|
||||
한국어용 청크가 빌드에 포함되어 있지 않아 새로 만들 수 없으므로, `patch_main_cjs.js`는
|
||||
이 항목을 영어 로더로 대체(alias)해서 우회합니다. **`restart`뿐 아니라 완전 재생성까지
|
||||
반드시 테스트**하세요 — 재시작만으로는 이 문제가 드러나지 않습니다.
|
||||
|
||||
### 문제 4 — 번역이 배포 후 시간이 지나서 "모바일에서만" 다시 영어로 보임
|
||||
|
||||
가장 까다로웠던 문제입니다. 번역을 배포하고 정상 동작까지 확인했는데, 이후 **모바일
|
||||
기기에서만** 옵션 페이지 등의 본문 텍스트가 다시 영어로 나오는 현상이 발생했습니다
|
||||
(페이지 제목이나 "한국어"라는 언어 이름 자체는 정상). 데스크톱에서는 동일 페이지가
|
||||
100% 정상이었습니다.
|
||||
|
||||
처음엔 모바일 브라우저 캐시 문제로 의심했지만, 캐시를 초기화하고 서로 다른 브라우저
|
||||
엔진(Chrome, 삼성인터넷, 네이버) 세 개로 테스트해도 완전히 동일한 증상이 재현되어
|
||||
캐시 이론은 기각했습니다.
|
||||
|
||||
**진짜 원인**: 번역 파일(`translation.json`, `server.json`)을 `docker cp`로 컨테이너
|
||||
내부에 직접 복사만 하고 `docker-compose.yml`에는 bind-mount로 등록하지 않았던 것이
|
||||
원인이었습니다. `docker cp`로 넣은 파일은 컨테이너의 쓰기 가능 레이어에만 존재하기 때문에,
|
||||
이후 `main.cjs` 패치가 완전 재생성에도 살아남는지 테스트하려고 `docker compose down && up`을
|
||||
실행했을 때 번역 파일 두 개가 컨테이너와 함께 통째로 사라졌습니다 (bind-mount 되어 있던
|
||||
`main.cjs`만 살아남음). 서버가 `translations/ko/*.json` 요청에 404를 반환하기 시작했고,
|
||||
i18next의 `fallbackLng:"en"` 설정 때문에 본문 텍스트가 조용히 영어로 대체됐습니다.
|
||||
"한국어"라는 언어 이름만 정상이었던 이유는, 그 값이 이 JSON 파일이 아니라 별도의 DB 기반
|
||||
API(`options/locales`)에서 오기 때문에 영향을 받지 않았던 것입니다.
|
||||
|
||||
데스크톱이 여전히 정상으로 보였던 이유는 단순히 파일이 사라지기 전에 브라우저가 이미
|
||||
받아둔 번역 응답을 캐시하고 있었기 때문입니다 — 즉 데스크톱 쪽이 오히려 "낡은 캐시를
|
||||
보여주던 쪽"이었고, 매번 새로 서버에 요청하는 모바일 쪽이 서버의 실제(망가진) 상태를
|
||||
정확히 반영하고 있었던 것입니다. 세 개의 다른 모바일 브라우저에서 전부 동일한 증상이
|
||||
나온 것도 이걸로 설명됩니다 — 캐시 종류와 무관하게 서버에 파일 자체가 없었으니까요.
|
||||
|
||||
**교훈**: `docker cp`로 컨테이너 안에 넣은 파일은 컨테이너가 사라지면 함께 사라집니다.
|
||||
번역 파일도 `main.cjs`와 마찬가지로 **반드시 `docker-compose.yml`의 `volumes:`에
|
||||
bind-mount로 선언**하세요 (위 설치 방법 3번, `docker-compose.yml.example` 참고). 그리고
|
||||
증상이 "특정 기기에서만 재현됨", "캐시를 지워도 재현됨"처럼 보이더라도, 실제 원인은
|
||||
클라이언트가 아니라 서버 쪽 데이터 유실일 수 있으므로 클라이언트 가설을 세우기 전에
|
||||
서버가 실제로 무엇을 응답하는지(`curl`로 정확한 URL 직접 확인)부터 검증하는 게 우선입니다.
|
||||
|
||||
## 이전 배포판의 미해결 항목 — CKEditor 자체 툴바
|
||||
|
||||
2026-09-05 후속 패치에서는 한국어 사전 719개를 적용하고 운영 화면을 확인했습니다. 다음 문단은 이전 배포판의 기록입니다.
|
||||
|
||||
CKEditor5 자체의 UI 문자열(툴바 버튼 이름 — "Paragraph", "Heading 2", "Bold" 등)은
|
||||
이 프로젝트가 건드리는 번역 시스템과 완전히 별개인 `window.CKEDITOR_TRANSLATIONS`라는
|
||||
자체 시스템에서 옵니다. 테스트한 빌드 기준으로, 독일어·프랑스어·스페인어·중국어를
|
||||
포함해 이미 "지원"되는 언어 **어느 것도** 실제 CKEditor 사전을 갖고 있지 않아서 전부
|
||||
영어 툴바로 나옵니다 — 한국어만의 문제가 아니라 업스트림 빌드 자체에 이미 있던 공백입니다.
|
||||
|
||||
## 라이선스
|
||||
|
||||
TriliumNext Notes 본체와 동일한 라이선스를 따릅니다. 무보증 — 이 프로젝트는 컴파일된
|
||||
바이너리를 난독화된 변수명 문자열 매칭 방식으로 패치하는 것이라, 버전이 올라가면
|
||||
깨지기 쉬운 구조입니다.
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
trilium:
|
||||
image: triliumnext/notes:latest
|
||||
container_name: trilium
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '127.0.0.1:18082:8080'
|
||||
environment:
|
||||
- TZ=Asia/Seoul
|
||||
volumes:
|
||||
- ./data:/home/node/trilium-data
|
||||
- ./main.cjs:/usr/src/app/main.cjs:ro
|
||||
- ./translation.json:/usr/src/app/public/translations/ko/translation.json:ro
|
||||
- ./server.json:/usr/src/app/assets/translations/ko/server.json:ro
|
||||
+4088
File diff suppressed because one or more lines are too long
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Patches TriliumNext's bundled main.cjs to register Korean ("ko") as a
|
||||
* selectable UI language.
|
||||
*
|
||||
* Why this is needed: the list of supported UI languages is not derived
|
||||
* from the translations/ folders on disk — it's a hardcoded array literal
|
||||
* baked into the minified server bundle (variable name may change between
|
||||
* builds; as of triliumnext/notes:latest on 2026-08-25 it was `K5i`).
|
||||
* A second hardcoded map (`IMi` as of the same build) lazy-loads a
|
||||
* per-language resource (CKEditor's own locale bundle) and has no entry
|
||||
* for "ko" either — since that resource is genuinely not bundled for any
|
||||
* language we didn't already support, we alias it to the English loader
|
||||
* instead of trying to fabricate a missing chunk.
|
||||
*
|
||||
* Usage: node patch_main_cjs.js /path/to/main.cjs
|
||||
*
|
||||
* Run this against a FRESH copy of main.cjs extracted from the image
|
||||
* (`docker cp trilium:/usr/src/app/main.cjs .`) any time the image is
|
||||
* updated, since the minified variable names (K5i, IMi, xvr) and byte
|
||||
* offsets are not stable across TriliumNext releases. After patching,
|
||||
* always run `node --check main.cjs` before deploying it.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = process.argv[2];
|
||||
if (!path) {
|
||||
console.error('Usage: node patch_main_cjs.js /path/to/main.cjs');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let content = fs.readFileSync(path, 'utf8');
|
||||
let patchedAnything = false;
|
||||
|
||||
// --- Patch 1: register "ko" in the main supported-locales array ---
|
||||
// Original starts with: K5i=[{id:"en",name:"English",electronLocale:"en"},{id:"de"
|
||||
// We insert a new first element right after the opening `[`.
|
||||
{
|
||||
const marker = 'K5i=[{id:"en",name:"English",electronLocale:"en"},{id:"de"';
|
||||
const idx = content.indexOf(marker);
|
||||
if (idx === -1) {
|
||||
console.log('[skip] locale-list marker not found (variable name may have changed, or already patched)');
|
||||
} else {
|
||||
const insertPoint = idx + 'K5i=['.length;
|
||||
const insertion = '{id:"ko",name:"한국어",electronLocale:"ko"},';
|
||||
content = content.slice(0, insertPoint) + insertion + content.slice(insertPoint);
|
||||
console.log('[ok] inserted "ko" into the supported-locales array');
|
||||
patchedAnything = true;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Patch 2: alias "ko" to the English loader in the per-language resource map ---
|
||||
// Original: IMi={ar:...,cn:...,de:...,en:()=>Promise.resolve().then(()=>Xe(xvr())),es:...
|
||||
{
|
||||
const imiIdx = content.indexOf('IMi={ar:');
|
||||
const marker = 'en:()=>Promise.resolve().then(()=>Xe(xvr())),es:';
|
||||
const idx = content.indexOf(marker);
|
||||
if (imiIdx === -1 || idx === -1 || idx < imiIdx || idx > imiIdx + 700) {
|
||||
console.log('[skip] per-language resource map marker not found or not where expected (already patched, or minified names changed)');
|
||||
} else {
|
||||
const insertion = 'en:()=>Promise.resolve().then(()=>Xe(xvr())),ko:()=>Promise.resolve().then(()=>Xe(xvr())),es:';
|
||||
content = content.slice(0, idx) + insertion + content.slice(idx + marker.length);
|
||||
console.log('[ok] aliased "ko" to the English loader in the resource map');
|
||||
patchedAnything = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!patchedAnything) {
|
||||
console.log('Nothing patched (file may already be patched, or this is a different TriliumNext version — re-derive the markers manually).');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
fs.writeFileSync(path, content, 'utf8');
|
||||
console.log('Wrote', path, '— now run: node --check', path);
|
||||
@@ -0,0 +1,307 @@
|
||||
{
|
||||
"keyboard_actions": {
|
||||
"back-in-note-history": "기록에서 이전 노트로 이동",
|
||||
"forward-in-note-history": "기록에서 다음 노트로 이동",
|
||||
"open-jump-to-note-dialog": "\"노트로 이동\" 대화상자 열기",
|
||||
"scroll-to-active-note": "노트 트리를 활성 노트로 스크롤",
|
||||
"quick-search": "빠른 검색 바 활성화",
|
||||
"search-in-subtree": "활성 노트의 하위 트리에서 노트 검색",
|
||||
"expand-subtree": "현재 노트의 하위 트리 펼치기",
|
||||
"collapse-tree": "전체 노트 트리 접기",
|
||||
"collapse-subtree": "현재 노트의 하위 트리 접기",
|
||||
"sort-child-notes": "하위 노트 정렬",
|
||||
"creating-and-moving-notes": "노트 만들기 및 이동",
|
||||
"create-note-after": "활성 노트 다음에 노트 만들기",
|
||||
"create-note-into": "활성 노트의 하위로 노트 만들기",
|
||||
"create-note-into-inbox": "받은편지함(정의된 경우) 또는 일일 노트에 노트 만들기",
|
||||
"delete-note": "노트 삭제",
|
||||
"move-note-up": "노트 위로 이동",
|
||||
"move-note-down": "노트 아래로 이동",
|
||||
"move-note-up-in-hierarchy": "계층 구조에서 노트 위로 이동",
|
||||
"move-note-down-in-hierarchy": "계층 구조에서 노트 아래로 이동",
|
||||
"edit-note-title": "트리에서 노트 상세로 이동해서 제목 편집",
|
||||
"edit-branch-prefix": "\"브랜치 접두사 편집\" 대화상자 표시",
|
||||
"cloneNotesTo": "선택한 노트 복제",
|
||||
"moveNotesTo": "선택한 노트 이동",
|
||||
"note-clipboard": "노트 클립보드",
|
||||
"copy-notes-to-clipboard": "선택한 노트를 클립보드에 복사",
|
||||
"paste-notes-from-clipboard": "클립보드의 노트를 활성 노트에 붙여넣기",
|
||||
"cut-notes-to-clipboard": "선택한 노트를 클립보드로 잘라내기",
|
||||
"select-all-notes-in-parent": "현재 노트 레벨의 모든 노트 선택",
|
||||
"add-note-above-to-the-selection": "선택 영역에 위 노트 추가",
|
||||
"add-note-below-to-selection": "선택 영역에 아래 노트 추가",
|
||||
"duplicate-subtree": "하위 트리 복제",
|
||||
"tabs-and-windows": "탭 및 창",
|
||||
"open-new-tab": "새 탭 열기",
|
||||
"close-active-tab": "활성 탭 닫기",
|
||||
"reopen-last-tab": "마지막으로 닫은 탭 다시 열기",
|
||||
"activate-next-tab": "오른쪽 탭 활성화",
|
||||
"activate-previous-tab": "왼쪽 탭 활성화",
|
||||
"open-new-window": "새 빈 창 열기",
|
||||
"toggle-tray": "시스템 트레이에서 애플리케이션 표시/숨김",
|
||||
"first-tab": "목록의 첫 번째 탭 활성화",
|
||||
"second-tab": "목록의 두 번째 탭 활성화",
|
||||
"third-tab": "목록의 세 번째 탭 활성화",
|
||||
"fourth-tab": "목록의 네 번째 탭 활성화",
|
||||
"fifth-tab": "목록의 다섯 번째 탭 활성화",
|
||||
"sixth-tab": "목록의 여섯 번째 탭 활성화",
|
||||
"seventh-tab": "목록의 일곱 번째 탭 활성화",
|
||||
"eight-tab": "목록의 여덟 번째 탭 활성화",
|
||||
"ninth-tab": "목록의 아홉 번째 탭 활성화",
|
||||
"last-tab": "목록의 마지막 탭 활성화",
|
||||
"dialogs": "대화상자",
|
||||
"show-note-source": "\"노트 소스\" 대화상자 표시",
|
||||
"show-options": "\"옵션\" 페이지 열기",
|
||||
"show-revisions": "\"노트 리비전\" 대화상자 표시",
|
||||
"show-recent-changes": "\"최근 변경 내역\" 대화상자 표시",
|
||||
"show-sql-console": "\"SQL 콘솔\" 페이지 열기",
|
||||
"show-backend-log": "\"백엔드 로그\" 페이지 열기",
|
||||
"show-help": "내장 사용자 가이드 열기",
|
||||
"show-cheatsheet": "일반적인 키보드 작업 모달 표시",
|
||||
"text-note-operations": "텍스트 노트 작업",
|
||||
"add-link-to-text": "텍스트에 링크를 추가하는 대화상자 열기",
|
||||
"follow-link-under-cursor": "캐럿이 위치한 링크 따라가기",
|
||||
"insert-date-and-time-to-text": "텍스트에 현재 날짜 및 시간 삽입",
|
||||
"paste-markdown-into-text": "클립보드의 Markdown을 텍스트 노트에 붙여넣기",
|
||||
"cut-into-note": "현재 노트에서 선택 영역을 잘라내서 선택한 텍스트로 하위 노트 만들기",
|
||||
"add-include-note-to-text": "노트를 포함하는 대화상자 열기",
|
||||
"edit-readonly-note": "읽기 전용 노트 편집",
|
||||
"attributes-labels-and-relations": "속성 (라벨 및 관계)",
|
||||
"add-new-label": "새 라벨 만들기",
|
||||
"create-new-relation": "새 관계 만들기",
|
||||
"ribbon-tabs": "리본 탭",
|
||||
"toggle-basic-properties": "기본 속성 전환",
|
||||
"toggle-file-properties": "파일 속성 전환",
|
||||
"toggle-image-properties": "이미지 속성 전환",
|
||||
"toggle-owned-attributes": "소유한 속성 전환",
|
||||
"toggle-inherited-attributes": "상속된 속성 전환",
|
||||
"toggle-promoted-attributes": "승격된 속성 전환",
|
||||
"toggle-link-map": "링크 지도 전환",
|
||||
"toggle-note-info": "노트 정보 전환",
|
||||
"toggle-note-paths": "노트 경로 전환",
|
||||
"toggle-similar-notes": "유사한 노트 전환",
|
||||
"other": "기타",
|
||||
"toggle-right-pane": "목차와 하이라이트가 포함된 오른쪽 패널 표시 전환",
|
||||
"print-active-note": "활성 노트 인쇄",
|
||||
"open-note-externally": "기본 애플리케이션으로 노트를 파일로 열기",
|
||||
"render-active-note": "활성 노트 렌더링(다시 렌더링)",
|
||||
"run-active-note": "활성 JavaScript(프론트엔드/백엔드) 코드 노트 실행",
|
||||
"toggle-note-hoisting": "활성 노트의 노트 호이스팅 전환",
|
||||
"unhoist": "어디서든 호이스팅 해제",
|
||||
"reload-frontend-app": "프론트엔드 다시 로드",
|
||||
"open-dev-tools": "개발자 도구 열기",
|
||||
"find-in-text": "검색 패널 전환",
|
||||
"toggle-left-note-tree-panel": "왼쪽(노트 트리) 패널 전환",
|
||||
"toggle-full-screen": "전체 화면 전환",
|
||||
"zoom-out": "축소",
|
||||
"zoom-in": "확대",
|
||||
"note-navigation": "노트 탐색",
|
||||
"reset-zoom-level": "확대/축소 수준 초기화",
|
||||
"copy-without-formatting": "서식 없이 선택한 텍스트 복사",
|
||||
"force-save-revision": "활성 노트의 새 리비전을 강제로 생성/저장",
|
||||
"toggle-book-properties": "북 속성 전환",
|
||||
"toggle-classic-editor-toolbar": "고정 도구모음이 있는 편집기의 서식 탭 전환",
|
||||
"export-as-pdf": "현재 노트를 PDF로 내보내기",
|
||||
"toggle-zen-mode": "젠 모드 활성화/비활성화 (더 집중된 편집을 위한 최소 UI)"
|
||||
},
|
||||
"login": {
|
||||
"title": "로그인",
|
||||
"heading": "Trilium 로그인",
|
||||
"incorrect-totp": "TOTP가 올바르지 않습니다. 다시 시도하세요.",
|
||||
"incorrect-password": "비밀번호가 올바르지 않습니다. 다시 시도하세요.",
|
||||
"password": "비밀번호",
|
||||
"remember-me": "로그인 상태 유지",
|
||||
"button": "로그인",
|
||||
"sign_in_with_sso": "{{ ssoIssuerName }}(으)로 로그인"
|
||||
},
|
||||
"set_password": {
|
||||
"title": "비밀번호 설정",
|
||||
"heading": "비밀번호 설정",
|
||||
"description": "웹에서 Trilium을 사용하려면 먼저 비밀번호를 설정해야 합니다. 이후 이 비밀번호로 로그인합니다.",
|
||||
"password": "비밀번호",
|
||||
"password-confirmation": "비밀번호 확인",
|
||||
"button": "비밀번호 설정"
|
||||
},
|
||||
"javascript-required": "Trilium을 사용하려면 JavaScript가 활성화되어 있어야 합니다.",
|
||||
"setup": {
|
||||
"heading": "TriliumNext Notes 설정",
|
||||
"new-document": "신규 사용자이며, 노트를 위한 새 Trilium 문서를 만들고 싶습니다",
|
||||
"sync-from-desktop": "이미 데스크톱 인스턴스가 있으며, 동기화를 설정하고 싶습니다",
|
||||
"sync-from-server": "이미 서버 인스턴스가 있으며, 동기화를 설정하고 싶습니다",
|
||||
"next": "다음",
|
||||
"init-in-progress": "문서 초기화 진행 중",
|
||||
"redirecting": "곧 애플리케이션으로 이동합니다.",
|
||||
"title": "설정"
|
||||
},
|
||||
"setup_sync-from-desktop": {
|
||||
"heading": "데스크톱에서 동기화",
|
||||
"description": "이 설정은 데스크톱 인스턴스에서 시작해야 합니다:",
|
||||
"step1": "TriliumNext Notes 데스크톱 인스턴스를 여세요.",
|
||||
"step2": "Trilium 메뉴에서 옵션을 클릭하세요.",
|
||||
"step3": "동기화 카테고리를 클릭하세요.",
|
||||
"step4": "서버 인스턴스 주소를 {{- host}}로 변경하고 저장을 클릭하세요.",
|
||||
"step5": "\"동기화 테스트\" 버튼을 클릭해서 연결이 성공하는지 확인하세요.",
|
||||
"step6": "이 단계를 완료했으면 {{- link}}를 클릭하세요.",
|
||||
"step6-here": "여기"
|
||||
},
|
||||
"setup_sync-from-server": {
|
||||
"heading": "서버에서 동기화",
|
||||
"instructions": "아래에 Trilium 서버 주소와 자격 증명을 입력하세요. 서버에서 전체 Trilium 문서를 다운로드하고 이에 대한 동기화를 설정합니다. 문서 크기와 연결 속도에 따라 시간이 걸릴 수 있습니다.",
|
||||
"server-host": "Trilium 서버 주소",
|
||||
"server-host-placeholder": "https://<hostname>:<port>",
|
||||
"proxy-server": "프록시 서버 (선택 사항)",
|
||||
"proxy-server-placeholder": "https://<hostname>:<port>",
|
||||
"note": "참고:",
|
||||
"proxy-instruction": "프록시 설정을 비워두면 시스템 프록시가 사용됩니다(데스크톱 애플리케이션에만 적용)",
|
||||
"password": "비밀번호",
|
||||
"password-placeholder": "비밀번호",
|
||||
"back": "뒤로",
|
||||
"finish-setup": "설정 완료"
|
||||
},
|
||||
"setup_sync-in-progress": {
|
||||
"heading": "동기화 진행 중",
|
||||
"successful": "동기화가 올바르게 설정되었습니다. 초기 동기화가 완료되기까지 시간이 걸립니다. 완료되면 로그인 페이지로 이동합니다.",
|
||||
"outstanding-items": "미완료 동기화 항목:",
|
||||
"outstanding-items-default": "해당 없음"
|
||||
},
|
||||
"share_404": {
|
||||
"title": "찾을 수 없음",
|
||||
"heading": "찾을 수 없음"
|
||||
},
|
||||
"share_page": {
|
||||
"parent": "상위:",
|
||||
"clipped-from": "이 노트는 원래 {{- url}}에서 클립되었습니다",
|
||||
"child-notes": "하위 노트:",
|
||||
"no-content": "이 노트에는 내용이 없습니다."
|
||||
},
|
||||
"weekdays": {
|
||||
"monday": "월요일",
|
||||
"tuesday": "화요일",
|
||||
"wednesday": "수요일",
|
||||
"thursday": "목요일",
|
||||
"friday": "금요일",
|
||||
"saturday": "토요일",
|
||||
"sunday": "일요일"
|
||||
},
|
||||
"weekdayNumber": "{weekNumber}주차",
|
||||
"months": {
|
||||
"january": "1월",
|
||||
"february": "2월",
|
||||
"march": "3월",
|
||||
"april": "4월",
|
||||
"may": "5월",
|
||||
"june": "6월",
|
||||
"july": "7월",
|
||||
"august": "8월",
|
||||
"september": "9월",
|
||||
"october": "10월",
|
||||
"november": "11월",
|
||||
"december": "12월"
|
||||
},
|
||||
"quarterNumber": "{quarterNumber}분기",
|
||||
"special_notes": {
|
||||
"search_prefix": "검색:"
|
||||
},
|
||||
"test_sync": {
|
||||
"not-configured": "동기화 서버 호스트가 구성되지 않았습니다. 먼저 동기화를 구성하세요.",
|
||||
"successful": "동기화 서버 핸드셰이크가 성공했으며, 동기화가 시작되었습니다."
|
||||
},
|
||||
"hidden-subtree": {
|
||||
"root-title": "숨겨진 노트",
|
||||
"search-history-title": "검색 기록",
|
||||
"note-map-title": "노트 지도",
|
||||
"sql-console-history-title": "SQL 콘솔 기록",
|
||||
"shared-notes-title": "공유된 노트",
|
||||
"bulk-action-title": "일괄 작업",
|
||||
"backend-log-title": "백엔드 로그",
|
||||
"user-hidden-title": "사용자 숨김",
|
||||
"launch-bar-templates-title": "런치바 템플릿",
|
||||
"base-abstract-launcher-title": "기본 추상 런처",
|
||||
"command-launcher-title": "명령 런처",
|
||||
"note-launcher-title": "노트 런처",
|
||||
"script-launcher-title": "스크립트 런처",
|
||||
"built-in-widget-title": "내장 위젯",
|
||||
"spacer-title": "여백",
|
||||
"custom-widget-title": "사용자 지정 위젯",
|
||||
"launch-bar-title": "런치바",
|
||||
"available-launchers-title": "사용 가능한 런처",
|
||||
"go-to-previous-note-title": "이전 노트로 이동",
|
||||
"go-to-next-note-title": "다음 노트로 이동",
|
||||
"new-note-title": "새 노트",
|
||||
"search-notes-title": "노트 검색",
|
||||
"jump-to-note-title": "노트로 이동",
|
||||
"calendar-title": "캘린더",
|
||||
"recent-changes-title": "최근 변경 내역",
|
||||
"bookmarks-title": "북마크",
|
||||
"open-today-journal-note-title": "오늘의 일지 노트 열기",
|
||||
"quick-search-title": "빠른 검색",
|
||||
"protected-session-title": "보호된 세션",
|
||||
"sync-status-title": "동기화 상태",
|
||||
"settings-title": "설정",
|
||||
"llm-chat-title": "노트와 채팅",
|
||||
"options-title": "옵션",
|
||||
"appearance-title": "외관",
|
||||
"shortcuts-title": "단축키",
|
||||
"text-notes": "텍스트 노트",
|
||||
"code-notes-title": "코드 노트",
|
||||
"images-title": "이미지",
|
||||
"spellcheck-title": "맞춤법 검사",
|
||||
"password-title": "비밀번호",
|
||||
"multi-factor-authentication-title": "MFA",
|
||||
"etapi-title": "ETAPI",
|
||||
"backup-title": "백업",
|
||||
"sync-title": "동기화",
|
||||
"ai-llm-title": "AI/LLM",
|
||||
"other": "기타",
|
||||
"advanced-title": "고급",
|
||||
"visible-launchers-title": "표시된 런처",
|
||||
"user-guide": "사용자 가이드",
|
||||
"localization": "언어 및 지역",
|
||||
"inbox-title": "받은편지함"
|
||||
},
|
||||
"notes": {
|
||||
"new-note": "새 노트",
|
||||
"duplicate-note-suffix": "(사본)",
|
||||
"duplicate-note-title": "{{- noteTitle }} {{ duplicateNoteSuffix }}"
|
||||
},
|
||||
"backend_log": {
|
||||
"log-does-not-exist": "백엔드 로그 파일 '{{ fileName }}'이(가) (아직) 존재하지 않습니다.",
|
||||
"reading-log-failed": "백엔드 로그 파일 '{{ fileName }}'을(를) 읽지 못했습니다."
|
||||
},
|
||||
"content_renderer": {
|
||||
"note-cannot-be-displayed": "이 노트 유형은 표시할 수 없습니다."
|
||||
},
|
||||
"pdf": {
|
||||
"export_filter": "PDF 문서 (*.pdf)",
|
||||
"unable-to-export-message": "현재 노트를 PDF로 내보낼 수 없습니다.",
|
||||
"unable-to-export-title": "PDF로 내보낼 수 없음",
|
||||
"unable-to-save-message": "선택한 파일에 쓸 수 없습니다. 다시 시도하거나 다른 위치를 선택하세요."
|
||||
},
|
||||
"tray": {
|
||||
"tooltip": "TriliumNext Notes",
|
||||
"close": "Trilium 종료",
|
||||
"recents": "최근 노트",
|
||||
"bookmarks": "북마크",
|
||||
"today": "오늘의 일지 노트 열기",
|
||||
"new-note": "새 노트",
|
||||
"show-windows": "창 표시",
|
||||
"open_new_window": "새 창 열기"
|
||||
},
|
||||
"migration": {
|
||||
"old_version": "현재 버전에서 직접 마이그레이션은 지원되지 않습니다. 먼저 최신 v0.60.4로 업그레이드한 후 이 버전으로 업그레이드하세요.",
|
||||
"error_message": "버전 {{version}}(으)로 마이그레이션하는 중 오류: {{stack}}",
|
||||
"wrong_db_version": "데이터베이스 버전({{version}})이 애플리케이션이 예상하는 버전({{targetVersion}})보다 최신입니다. 즉 더 새롭고 호환되지 않는 버전의 Trilium에서 생성되었다는 뜻입니다. 이 문제를 해결하려면 최신 버전의 Trilium으로 업그레이드하세요."
|
||||
},
|
||||
"modals": {
|
||||
"error_title": "오류"
|
||||
},
|
||||
"share_theme": {
|
||||
"site-theme": "사이트 테마",
|
||||
"search_placeholder": "검색...",
|
||||
"image_alt": "글 이미지",
|
||||
"last-updated": "{{- date}}에 마지막으로 업데이트됨",
|
||||
"subpages": "하위 페이지:",
|
||||
"on-this-page": "이 페이지에서",
|
||||
"expand": "펼치기"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user