@intlayer/docs 8.9.4-canary.0 → 8.9.5
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/cjs/generated/docs.entry.cjs +20 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +20 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +1 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/benchmark/index.md +0 -3
- package/docs/ar/benchmark/nextjs.md +15 -6
- package/docs/ar/benchmark/solid.md +155 -0
- package/docs/ar/benchmark/svelte.md +148 -0
- package/docs/ar/benchmark/tanstack.md +12 -3
- package/docs/ar/benchmark/vue.md +160 -0
- package/docs/ar/configuration.md +16 -12
- package/docs/ar/dictionary/content_file.md +51 -1
- package/docs/ar/mcp_server.md +30 -17
- package/docs/ar/plugins/sync-po.md +333 -0
- package/docs/bn/configuration.md +16 -12
- package/docs/cs/configuration.md +16 -12
- package/docs/de/benchmark/index.md +0 -3
- package/docs/de/benchmark/nextjs.md +15 -6
- package/docs/de/benchmark/solid.md +155 -0
- package/docs/de/benchmark/svelte.md +148 -0
- package/docs/de/benchmark/tanstack.md +12 -3
- package/docs/de/benchmark/vue.md +160 -0
- package/docs/de/configuration.md +16 -12
- package/docs/de/dictionary/content_file.md +52 -2
- package/docs/de/mcp_server.md +29 -16
- package/docs/de/plugins/sync-po.md +332 -0
- package/docs/en/benchmark/nextjs.md +11 -2
- package/docs/en/benchmark/solid.md +22 -4
- package/docs/en/benchmark/svelte.md +17 -5
- package/docs/en/benchmark/tanstack.md +18 -3
- package/docs/en/benchmark/vue.md +17 -11
- package/docs/en/configuration.md +16 -13
- package/docs/en/dictionary/content_file.md +51 -1
- package/docs/en/mcp_server.md +31 -18
- package/docs/en/plugins/sync-po.md +333 -0
- package/docs/en-GB/benchmark/index.md +0 -3
- package/docs/en-GB/benchmark/nextjs.md +15 -6
- package/docs/en-GB/benchmark/solid.md +155 -0
- package/docs/en-GB/benchmark/svelte.md +148 -0
- package/docs/en-GB/benchmark/tanstack.md +12 -3
- package/docs/en-GB/benchmark/vue.md +160 -0
- package/docs/en-GB/configuration.md +15 -11
- package/docs/en-GB/dictionary/content_file.md +51 -1
- package/docs/en-GB/mcp_server.md +31 -18
- package/docs/en-GB/plugins/sync-po.md +333 -0
- package/docs/es/benchmark/index.md +0 -3
- package/docs/es/benchmark/nextjs.md +15 -6
- package/docs/es/benchmark/solid.md +155 -0
- package/docs/es/benchmark/svelte.md +148 -0
- package/docs/es/benchmark/tanstack.md +12 -3
- package/docs/es/benchmark/vue.md +160 -0
- package/docs/es/configuration.md +16 -12
- package/docs/es/dictionary/content_file.md +51 -1
- package/docs/es/mcp_server.md +30 -17
- package/docs/es/plugins/sync-po.md +333 -0
- package/docs/fr/benchmark/index.md +0 -3
- package/docs/fr/benchmark/nextjs.md +15 -6
- package/docs/fr/benchmark/solid.md +155 -0
- package/docs/fr/benchmark/svelte.md +148 -0
- package/docs/fr/benchmark/tanstack.md +12 -3
- package/docs/fr/benchmark/vue.md +160 -0
- package/docs/fr/configuration.md +16 -12
- package/docs/fr/dictionary/content_file.md +51 -1
- package/docs/fr/mcp_server.md +30 -17
- package/docs/fr/plugins/sync-po.md +333 -0
- package/docs/hi/benchmark/nextjs.md +15 -6
- package/docs/hi/benchmark/solid.md +155 -0
- package/docs/hi/benchmark/svelte.md +148 -0
- package/docs/hi/benchmark/tanstack.md +12 -3
- package/docs/hi/benchmark/vue.md +160 -0
- package/docs/hi/configuration.md +16 -12
- package/docs/hi/dictionary/content_file.md +51 -1
- package/docs/hi/mcp_server.md +31 -18
- package/docs/hi/plugins/sync-po.md +333 -0
- package/docs/id/benchmark/index.md +0 -3
- package/docs/id/benchmark/nextjs.md +15 -6
- package/docs/id/benchmark/solid.md +155 -0
- package/docs/id/benchmark/svelte.md +148 -0
- package/docs/id/benchmark/tanstack.md +12 -3
- package/docs/id/benchmark/vue.md +160 -0
- package/docs/id/configuration.md +16 -12
- package/docs/id/dictionary/content_file.md +51 -1
- package/docs/id/mcp_server.md +30 -17
- package/docs/id/plugins/sync-po.md +333 -0
- package/docs/it/benchmark/index.md +1 -4
- package/docs/it/benchmark/nextjs.md +15 -6
- package/docs/it/benchmark/solid.md +155 -0
- package/docs/it/benchmark/svelte.md +148 -0
- package/docs/it/benchmark/tanstack.md +12 -3
- package/docs/it/benchmark/vue.md +160 -0
- package/docs/it/configuration.md +16 -12
- package/docs/it/dictionary/content_file.md +51 -1
- package/docs/it/mcp_server.md +30 -17
- package/docs/it/plugins/sync-po.md +333 -0
- package/docs/ja/benchmark/index.md +5 -5
- package/docs/ja/benchmark/nextjs.md +15 -6
- package/docs/ja/benchmark/solid.md +155 -0
- package/docs/ja/benchmark/svelte.md +148 -0
- package/docs/ja/benchmark/tanstack.md +12 -3
- package/docs/ja/benchmark/vue.md +160 -0
- package/docs/ja/configuration.md +16 -12
- package/docs/ja/dictionary/content_file.md +50 -2
- package/docs/ja/intlayer_with_nextjs_no_locale_path.md +4 -3
- package/docs/ja/mcp_server.md +29 -16
- package/docs/ja/plugins/sync-po.md +333 -0
- package/docs/ko/benchmark/nextjs.md +15 -6
- package/docs/ko/benchmark/solid.md +155 -0
- package/docs/ko/benchmark/svelte.md +148 -0
- package/docs/ko/benchmark/tanstack.md +12 -3
- package/docs/ko/benchmark/vue.md +160 -0
- package/docs/ko/configuration.md +16 -12
- package/docs/ko/dictionary/content_file.md +51 -1
- package/docs/ko/intlayer_with_nextjs_no_locale_path.md +3 -2
- package/docs/ko/mcp_server.md +31 -18
- package/docs/ko/plugins/sync-po.md +333 -0
- package/docs/nl/configuration.md +16 -12
- package/docs/pl/benchmark/index.md +0 -3
- package/docs/pl/benchmark/nextjs.md +15 -6
- package/docs/pl/benchmark/solid.md +155 -0
- package/docs/pl/benchmark/svelte.md +148 -0
- package/docs/pl/benchmark/tanstack.md +12 -3
- package/docs/pl/benchmark/vue.md +160 -0
- package/docs/pl/configuration.md +16 -12
- package/docs/pl/dictionary/content_file.md +51 -1
- package/docs/pl/mcp_server.md +30 -17
- package/docs/pl/plugins/sync-po.md +333 -0
- package/docs/pt/benchmark/index.md +0 -3
- package/docs/pt/benchmark/nextjs.md +16 -7
- package/docs/pt/benchmark/solid.md +155 -0
- package/docs/pt/benchmark/svelte.md +148 -0
- package/docs/pt/benchmark/tanstack.md +13 -4
- package/docs/pt/benchmark/vue.md +160 -0
- package/docs/pt/configuration.md +16 -12
- package/docs/pt/dictionary/content_file.md +51 -1
- package/docs/pt/mcp_server.md +30 -17
- package/docs/pt/plugins/sync-po.md +333 -0
- package/docs/ru/benchmark/nextjs.md +15 -6
- package/docs/ru/benchmark/solid.md +155 -0
- package/docs/ru/benchmark/svelte.md +148 -0
- package/docs/ru/benchmark/tanstack.md +12 -3
- package/docs/ru/benchmark/vue.md +160 -0
- package/docs/ru/configuration.md +16 -12
- package/docs/ru/dictionary/content_file.md +52 -2
- package/docs/ru/mcp_server.md +30 -17
- package/docs/ru/plugins/sync-po.md +333 -0
- package/docs/tr/benchmark/index.md +0 -3
- package/docs/tr/benchmark/nextjs.md +15 -6
- package/docs/tr/benchmark/solid.md +155 -0
- package/docs/tr/benchmark/svelte.md +148 -0
- package/docs/tr/benchmark/tanstack.md +12 -3
- package/docs/tr/benchmark/vue.md +160 -0
- package/docs/tr/configuration.md +16 -12
- package/docs/tr/dictionary/content_file.md +51 -1
- package/docs/tr/mcp_server.md +31 -18
- package/docs/tr/plugins/sync-po.md +333 -0
- package/docs/uk/benchmark/nextjs.md +15 -6
- package/docs/uk/benchmark/solid.md +155 -0
- package/docs/uk/benchmark/svelte.md +148 -0
- package/docs/uk/benchmark/tanstack.md +12 -3
- package/docs/uk/benchmark/vue.md +160 -0
- package/docs/uk/configuration.md +16 -12
- package/docs/uk/dictionary/content_file.md +51 -1
- package/docs/uk/mcp_server.md +29 -16
- package/docs/uk/plugins/sync-po.md +333 -0
- package/docs/ur/configuration.md +16 -12
- package/docs/vi/benchmark/index.md +0 -3
- package/docs/vi/benchmark/nextjs.md +15 -6
- package/docs/vi/benchmark/solid.md +155 -0
- package/docs/vi/benchmark/svelte.md +148 -0
- package/docs/vi/benchmark/tanstack.md +12 -3
- package/docs/vi/benchmark/vue.md +160 -0
- package/docs/vi/configuration.md +16 -12
- package/docs/vi/dictionary/content_file.md +51 -1
- package/docs/vi/intlayer_with_nextjs_15.md +10 -57
- package/docs/vi/mcp_server.md +30 -17
- package/docs/vi/plugins/sync-po.md +333 -0
- package/docs/zh/benchmark/nextjs.md +15 -6
- package/docs/zh/benchmark/solid.md +155 -0
- package/docs/zh/benchmark/svelte.md +148 -0
- package/docs/zh/benchmark/tanstack.md +12 -3
- package/docs/zh/benchmark/vue.md +160 -0
- package/docs/zh/configuration.md +16 -12
- package/docs/zh/dictionary/content_file.md +51 -3
- package/docs/zh/mcp_server.md +31 -18
- package/docs/zh/plugins/sync-po.md +333 -0
- package/frequent_questions/ar/intlayerNode.md +3 -3
- package/frequent_questions/de/intlayerNode.md +3 -3
- package/frequent_questions/en/intlayerNode.md +3 -3
- package/frequent_questions/en-GB/intlayerNode.md +3 -3
- package/frequent_questions/es/intlayerNode.md +3 -3
- package/frequent_questions/fr/intlayerNode.md +3 -3
- package/frequent_questions/hi/intlayerNode.md +3 -3
- package/frequent_questions/id/intlayerNode.md +3 -3
- package/frequent_questions/it/intlayerNode.md +3 -3
- package/frequent_questions/ja/intlayerNode.md +3 -3
- package/frequent_questions/ko/intlayerNode.md +3 -3
- package/frequent_questions/pl/intlayerNode.md +3 -3
- package/frequent_questions/pt/intlayerNode.md +3 -3
- package/frequent_questions/ru/intlayerNode.md +3 -3
- package/frequent_questions/tr/intlayerNode.md +3 -3
- package/frequent_questions/uk/intlayerNode.md +3 -3
- package/frequent_questions/vi/intlayerNode.md +3 -3
- package/frequent_questions/zh/intlayerNode.md +3 -3
- package/package.json +8 -8
- package/src/generated/docs.entry.ts +20 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: 2026년 Svelte를 위한 최고의 i18n 솔루션 - 벤치마크 리포트
|
|
5
|
+
description: svelte-i18n, Paraglide, Intlayer와 같은 Svelte 국제화(i18n) 라이브러리를 비교합니다. 번들 크기, 누수, 반응성에 관한 상세 성능 리포트.
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- svelte
|
|
11
|
+
- 성능
|
|
12
|
+
- intlayer
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- benchmark
|
|
16
|
+
- svelte
|
|
17
|
+
author: Aymeric PINEAU
|
|
18
|
+
applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-svelte-template
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.7.12
|
|
21
|
+
date: 2026-01-06
|
|
22
|
+
changes: "벤치마크 초기화"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Svelte i18n 라이브러리 - 2026 벤치마크 리포트
|
|
26
|
+
|
|
27
|
+
이 페이지는 Svelte i18n 솔루션에 대한 벤치마크 리포트입니다.
|
|
28
|
+
|
|
29
|
+
## 목차
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## 인터랙티브 벤치마크
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-svelte" vertical/>
|
|
36
|
+
|
|
37
|
+
## 결과 참조:
|
|
38
|
+
|
|
39
|
+
<iframe
|
|
40
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_svelte.md"
|
|
41
|
+
width="100%"
|
|
42
|
+
height="600px"
|
|
43
|
+
style="border:none;">
|
|
44
|
+
</iframe>
|
|
45
|
+
|
|
46
|
+
> https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_svelte.md
|
|
47
|
+
|
|
48
|
+
전체 벤치마크 저장소는 [여기](https://github.com/intlayer-org/benchmark-i18n/tree/main)에서 확인할 수 있습니다.
|
|
49
|
+
|
|
50
|
+
## 서론
|
|
51
|
+
|
|
52
|
+
국제화 솔루션은 Svelte 앱에서 가장 무거운 의존성 중 하나입니다. 주요 위험은 불필요한 콘텐츠, 즉 단일 경로의 번들에 다른 페이지와 다른 로케일의 번역을 포함하는 것입니다.
|
|
53
|
+
|
|
54
|
+
앱이 성장함에 따라 이 문제는 클라이언트에 전송되는 JavaScript를 빠르게 팽창시키고 내비게이션을 느리게 만들 수 있습니다.
|
|
55
|
+
|
|
56
|
+
실제로 최적화가 가장 덜 된 구현의 경우, 국제화된 페이지가 i18n이 없는 버전보다 몇 배나 무거워질 수 있습니다.
|
|
57
|
+
|
|
58
|
+
또 다른 영향은 개발자 경험(DX)입니다: 콘텐츠 선언 방식, 타입, 네임스페이스 구성, 동적 로딩, 로케일 변경 시의 반응성 등이 포함됩니다.
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: 가장 성능 효율적인 선택(v8.7.12)으로, 발자국(footprint)이 가장 작습니다.
|
|
63
|
+
- **Paraglide**: 트리 쉐이킹(tree-shaking)을 위한 강력한 후보이지만, 개발자 경험이 더 복잡하고 반응성 오버헤드가 있습니다.
|
|
64
|
+
- **svelte-i18n**: Svelte를 위한 표준적이고 기능이 완비된 솔루션이지만, 번들 무게가 훨씬 더 큽니다(Intlayer의 약 7배).
|
|
65
|
+
|
|
66
|
+
## 앱 테스트하기
|
|
67
|
+
|
|
68
|
+
i18n 누수 문제를 빠르게 파악하기 위해 [여기](https://intlayer.org/i18n-seo-scanner)에서 시도해 볼 수 있는 무료 스캐너를 구축했습니다.
|
|
69
|
+
|
|
70
|
+
<iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
71
|
+
|
|
72
|
+
## 문제점
|
|
73
|
+
|
|
74
|
+
다국어 앱의 비용을 제한하려면 두 가지 레버가 필수적입니다:
|
|
75
|
+
|
|
76
|
+
- 페이지 / 네임스페이스별로 콘텐츠를 분리하여 필요하지 않을 때 전체 사전을 로드하지 않도록 합니다.
|
|
77
|
+
- 필요할 때만 올바른 로케일을 동적으로 로드합니다.
|
|
78
|
+
|
|
79
|
+
이러한 접근 방식의 기술적 한계 이해:
|
|
80
|
+
|
|
81
|
+
**동적 로딩**
|
|
82
|
+
|
|
83
|
+
동적 로딩이 없으면 대부분의 솔루션은 첫 번째 렌더링부터 메시지를 메모리에 유지하므로 경로와 로케일이 많은 앱의 경우 상당한 오버헤드가 발생합니다.
|
|
84
|
+
|
|
85
|
+
동적 로딩을 사용하면 초기 JS는 줄어들지만 언어 전환 시 추가 요청이 발생할 수 있는 장단점을 수용하게 됩니다.
|
|
86
|
+
|
|
87
|
+
**콘텐츠 분리**
|
|
88
|
+
|
|
89
|
+
`t('a.b.c')`를 중심으로 구축된 구문은 매우 편리하지만 런타임에 큰 JSON 객체를 유지하도록 조장하는 경우가 많습니다. 이 모델은 라이브러리가 실제 페이지별 분리 전략을 제공하지 않는 한 트리 쉐이킹을 어렵게 만듭니다.
|
|
90
|
+
|
|
91
|
+
## 연구 방법론
|
|
92
|
+
|
|
93
|
+
이 벤치마크에서는 다음과 같은 라이브러리를 비교했습니다:
|
|
94
|
+
|
|
95
|
+
- `Base App` (i18n 라이브러리 없음)
|
|
96
|
+
- `svelte-intlayer` (v8.7.12)
|
|
97
|
+
- `svelte-i18n` (v4.0.1)
|
|
98
|
+
- `@inlang/paraglide-js` (v2.17.0)
|
|
99
|
+
|
|
100
|
+
프레임워크는 `Svelte`이며 **10개의 페이지**와 **10개의 언어**를 가진 다국어 앱을 사용했습니다.
|
|
101
|
+
|
|
102
|
+
**네 가지 로딩 전략**을 비교했습니다:
|
|
103
|
+
|
|
104
|
+
| 전략 | 네임스페이스 없음 (글로벌) | 네임스페이스 포함 (스코프) |
|
|
105
|
+
| :------------ | :------------------------------------------- | :-------------------------------------------------------------- |
|
|
106
|
+
| **정적 로딩** | **Static**: 시작 시 모든 것을 메모리에 로드. | **Scoped static**: 네임스페이스별 분리; 시작 시 모든 것을 로드. |
|
|
107
|
+
| **동적 로딩** | **Dynamic**: 로케일별 온디맨드 로딩. | **Scoped dynamic**: 네임스페이스 및 로케일별 세분화된 로딩. |
|
|
108
|
+
|
|
109
|
+
## 전략 요약
|
|
110
|
+
|
|
111
|
+
- **Static**: 간단함. 초기 로드 후 네트워크 지연 없음. 단점: 큰 번들 크기.
|
|
112
|
+
- **Dynamic**: 초기 무게 감소(지연 로딩). 로케일이 많을 때 적합함.
|
|
113
|
+
- **Scoped static**: 복잡한 추가 네트워크 요청 없이 코드 구조를 유지(논리적 분리).
|
|
114
|
+
- **Scoped dynamic**: 코드 분할 및 성능을 위한 최선의 접근 방식. 현재 뷰와 활성 로케일에 필요한 것만 로드하여 메모리 사용을 최소화함.
|
|
115
|
+
|
|
116
|
+
## 결과 상세
|
|
117
|
+
|
|
118
|
+
### 1 — 피해야 할 솔루션
|
|
119
|
+
|
|
120
|
+
> Svelte 에코시스템에서 분명하게 피해야 할 솔루션은 없습니다.
|
|
121
|
+
|
|
122
|
+
### 2 — 수용 가능한 솔루션
|
|
123
|
+
|
|
124
|
+
**(Paraglide)** (`@inlang/paraglide-js@2.17.0`):
|
|
125
|
+
|
|
126
|
+
`Paraglide`는 혁신적이고 잘 설계된 접근 방식을 제공합니다. Vite + Svelte 앱의 맥락에서 그들이 홍보하는 트리 쉐이킹은 기대대로 잘 작동합니다.
|
|
127
|
+
하지만 React + TanStack Start의 경우 트리 쉐이킹이 기대대로 작동하지 않았으며 Next.js도 마찬가지였습니다. 그럼에도 불구하고 Svelte 및 TanStack Start 프로젝트에서의 Paraglide 사용은 확인해 볼 가치가 있습니다.
|
|
128
|
+
워크플로우와 DX 또한 다른 옵션보다 복잡합니다.
|
|
129
|
+
개인적으로 푸시할 때마다 JS 파일을 다시 생성해야 하는 것을 선호하지 않으며, 이는 PR을 통한 개발자들 간의 지속적인 머지 충돌 위험을 만듭니다. 또한 이 도구는 Next.js보다 Vite에 더 집중하는 것으로 보입니다.
|
|
130
|
+
마지막으로 다른 솔루션과 비교하여 Paraglide는 콘텐츠를 렌더링하기 위한 현재 로케일을 가져오기 위해 스토어(예: Svelte store)를 사용하지 않습니다. 파싱되는 각 노드에 대해 localStorage / 쿠키 등에서 로케일을 요청합니다. 이는 컴포넌트 반응성에 영향을 미주는 불필요한 로직 실행을 초래합니다.
|
|
131
|
+
|
|
132
|
+
> paraglide에 관한 참고: 이 솔루션은 임포트를 위해 코드베이스에 코드를 주입하므로, 벤치마크 리포트의 'lib size' 메트릭은 거의 0에 가깝습니다. 코드 생성(Code generation)은 사용되는 함수에 필요한 로직(모든 접두사 vs 접두사 없음, 쿠키 vs 스토리지 등)만 포함되므로 좋은 방식입니다. 이에 비해 Intlayer는 빌드 시 환경 변수 주입을 통해 이 필터링을 수행하여 번들러가 로직에 따라 콘텐츠를 트리 쉐이킹하도록 강제합니다. 덕분에 paraglide와 intlayer는 i18next나 next-intl보다 6~10배 더 가벼운 솔루션이 됩니다.
|
|
133
|
+
|
|
134
|
+
**(svelte-i18n)** (`svelte-i18n@3.4.0`):
|
|
135
|
+
|
|
136
|
+
이 솔루션은 Svelte 프로젝트의 모든 i18n 요구 사항을 충족합니다. 하지만 i18next나 다른 주요 i18n 솔루션과 마찬가지로 조금 무겁습니다 (~15.9kb, `svelte-intlayer`의 약 7배).
|
|
137
|
+
|
|
138
|
+
### 3 — 추천 사항
|
|
139
|
+
|
|
140
|
+
**(Intlayer)** (`svelte-intlayer@8.7.12`):
|
|
141
|
+
|
|
142
|
+
객관성을 위해 나의 솔루션인 `svelte-intlayer`에 대해서는 직접 판단하지 않겠습니다.
|
|
143
|
+
|
|
144
|
+
### 개인적인 의견
|
|
145
|
+
|
|
146
|
+
이 의견은 개인적인 것이며 벤치마크 결과에는 영향을 미치지 않습니다. 그럼에도 불구하고 i18n 세계에서는 번역된 콘텐츠를 위해 `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>`와 같은 패턴에 대한 합의가 자주 보입니다.
|
|
147
|
+
|
|
148
|
+
Svelte 앱에서 함수를 `Slot`으로 주입하는 것은 내 견해로는 안티 패턴입니다. 또한 피할 수 있는 복잡성과 JavaScript 실행 오버헤드(거의 눈에 띄지 않더라도)를 추가합니다.
|
|
@@ -57,6 +57,13 @@ history:
|
|
|
57
57
|
|
|
58
58
|
또 다른 영향은 개발자 경험(DX)입니다: 콘텐츠 선언 방식, 타입, 네임스페이스 구성, 동적 로딩, 로케일 변경 시의 반응성 등이 포함됩니다.
|
|
59
59
|
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: TanStack Start에서 최고의 성능과 가장 작은 번들 크(v8.7.12)를 제공합니다.
|
|
63
|
+
- **react-i18next** & **use-intl**: 큰 에코시스템을 가진 성숙한 대안이지만, 훨씬 더 무겁고 최적화가 복잡합니다.
|
|
64
|
+
- **Paraglide**: 혁신적인 트리 쉐이킹 아이디어이지만 실제로는 작동하지 않습니다. TanStack Start에서 복잡한 DX와 반응성 오버헤드가 발생합니다.
|
|
65
|
+
- **피해야 할 솔루션**: **General Translation (GT)** 및 **Lingo.dev**. 심각한 성능 문제, AI 쿼터 제한 및 벤더 종속성(vendor lock-in) 때문입니다.
|
|
66
|
+
|
|
60
67
|
## 앱 테스트하기
|
|
61
68
|
|
|
62
69
|
i18n 누수 문제를 빠르게 파악하기 위해 [여기](https://intlayer.org/i18n-seo-scanner)에서 시도해 볼 수 있는 무료 스캐너를 구축했습니다.
|
|
@@ -87,12 +94,12 @@ i18n 누수 문제를 빠르게 파악하기 위해 [여기](https://intlayer.or
|
|
|
87
94
|
이 벤치마크에서는 다음과 같은 라이브러리를 비교했습니다:
|
|
88
95
|
|
|
89
96
|
- `Base App` (i18n 라이브러리 없음)
|
|
90
|
-
- `react-intlayer` (v8.7.
|
|
97
|
+
- `react-intlayer` (v8.7.12)
|
|
91
98
|
- `react-i18next` (v17.0.2)
|
|
92
99
|
- `use-intl` (v4.9.1)
|
|
93
100
|
- `@lingui/core` (v5.3.0)
|
|
94
101
|
- `@inlang/paraglide-js` (v2.15.1)
|
|
95
|
-
-
|
|
102
|
+
- `@tolgee/react` (v7.0.0)
|
|
96
103
|
- `react-intl` (v10.1.1)
|
|
97
104
|
- `wuchale` (v0.22.11)
|
|
98
105
|
- `gt-react` (vlatest)
|
|
@@ -150,7 +157,9 @@ i18n 누수 문제를 빠르게 파악하기 위해 [여기](https://intlayer.or
|
|
|
150
157
|
|
|
151
158
|
`Paraglide`는 혁신적이고 잘 설계된 접근 방식을 제공합니다. 그럼에도 불구하고 이 벤치마크에서는 광고된 트리 쉐이킹이 나의 Next.js 구현이나 TanStack Start에서 작동하지 않았습니다. 워크플로우와 DX 또한 다른 옵션보다 복잡합니다. 개인적으로 푸시할 때마다 JS 파일을 다시 생성해야 하는 것을 선호하지 않으며, 이는 PR을 통한 개발자들 간의 지속적인 머지 충돌 위험을 만듭니다.
|
|
152
159
|
|
|
153
|
-
|
|
160
|
+
> paraglide에 관한 참고: 이 솔루션은 임포트를 위해 코드베이스에 코드를 주입하므로, 벤치마크 리포트의 'lib size' 메트릭은 거의 0에 가깝습니다. 코드 생성(Code generation)은 사용되는 함수에 필요한 로직(모든 접두사 vs 접두사 없음, 쿠키 vs 스토리지 등)만 포함되므로 좋은 방식입니다. 이에 비해 Intlayer는 빌드 시 환경 변수 주입을 통해 이 필터링을 수행하여 번들러가 로직에 따라 콘텐츠를 트리 쉐이킹하도록 강제합니다. 덕분에 paraglide와 intlayer는 i18next나 next-intl보다 6~10배 더 가벼운 솔루션이 됩니다.
|
|
161
|
+
|
|
162
|
+
**(Tolgee)** (`@tolgee/react@7.0.0`):
|
|
154
163
|
|
|
155
164
|
`Tolgee`는 앞에서 언급한 많은 문제들을 해결합니다. 비슷한 접근 방식을 가진 다른 도구들보다 시작하기 더 어렵다고 느꼈습니다. 타입 안전성을 제공하지 않아 컴파일 시점에 누락된 키를 찾는 것도 매우 어렵습니다. 누락된 키 감지 기능을 추가하기 위해 Tolgee의 API를 나의 API로 래핑해야 했습니다.
|
|
156
165
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: 2026년 Vue를 위한 최고의 i18n 솔루션 - 벤치마크 리포트
|
|
5
|
+
description: vue-i18n, fluent-vue, Intlayer와 같은 Vue 국제화(i18n) 라이브러리를 비교합니다. 번들 크기, 누수, 반응성에 관한 상세 성능 리포트.
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- vue
|
|
11
|
+
- 성능
|
|
12
|
+
- intlayer
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- benchmark
|
|
16
|
+
- vue
|
|
17
|
+
author: Aymeric PINEAU
|
|
18
|
+
applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-vue-template
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.7.12
|
|
21
|
+
date: 2026-01-06
|
|
22
|
+
changes: "벤치마크 초기화"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Vue i18n 라이브러리 - 2026 벤치마크 리포트
|
|
26
|
+
|
|
27
|
+
이 페이지는 Vue i18n 솔루션에 대한 벤치마크 리포트입니다.
|
|
28
|
+
|
|
29
|
+
## 목차
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## 인터랙티브 벤치마크
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-vue" vertical/>
|
|
36
|
+
|
|
37
|
+
## 결과 참조:
|
|
38
|
+
|
|
39
|
+
<iframe
|
|
40
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_vue.md"
|
|
41
|
+
width="100%"
|
|
42
|
+
height="600px"
|
|
43
|
+
style="border:none;">
|
|
44
|
+
</iframe>
|
|
45
|
+
|
|
46
|
+
> https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_vue.md
|
|
47
|
+
|
|
48
|
+
전체 벤치마크 저장소는 [여기](https://github.com/intlayer-org/benchmark-i18n/tree/main)에서 확인할 수 있습니다.
|
|
49
|
+
|
|
50
|
+
## 서론
|
|
51
|
+
|
|
52
|
+
국제화 솔루션은 Vue 앱에서 가장 무거운 의존성 중 하나입니다. 주요 위험은 불필요한 콘텐츠, 즉 단일 경로의 번들에 다른 페이지와 다른 로케일의 번역을 포함하는 것입니다.
|
|
53
|
+
|
|
54
|
+
앱이 성장함에 따라 이 문제는 클라이언트에 전송되는 JavaScript를 빠르게 팽창시키고 내비게이션을 느리게 만들 수 있습니다.
|
|
55
|
+
|
|
56
|
+
실제로 최적화가 가장 덜 된 구현의 경우, 국제화된 페이지가 i18n이 없는 버전보다 몇 배나 무거워질 수 있습니다.
|
|
57
|
+
|
|
58
|
+
또 다른 영향은 개발자 경험(DX)입니다: 콘텐츠 선언 방식, 타입, 네임스페이스 구성, 동적 로딩, 로케일 변경 시의 반응성 등이 포함됩니다.
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: 내장된 스코핑(scoping)과 동적 로딩을 제공하는 가장 가벼운 솔루션(v8.7.12).
|
|
63
|
+
- **vue-i18n**: 풍부한 에코시스템을 가진 업계 표준이지만, 대규모 애플리케이션에서 코드 분할 최적화가 어렵고 상당히 무거워질 수 있습니다.
|
|
64
|
+
- **fluent-vue**: 혁신적인 메시지 구성을 제공하지만 타입 안전성이 부족하고 극도로 무거운 솔루션입니다.
|
|
65
|
+
|
|
66
|
+
## 앱 테스트하기
|
|
67
|
+
|
|
68
|
+
i18n 누수 문제를 빠르게 파악하기 위해 [여기](https://intlayer.org/i18n-seo-scanner)에서 시도해 볼 수 있는 무료 스캐너를 구축했습니다.
|
|
69
|
+
|
|
70
|
+
<iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
71
|
+
|
|
72
|
+
## 문제점
|
|
73
|
+
|
|
74
|
+
다국어 앱의 비용을 제한하려면 두 가지 레버가 필수적입니다:
|
|
75
|
+
|
|
76
|
+
- 페이지 / 네임스페이스별로 콘텐츠를 분리하여 필요하지 않을 때 전체 사전을 로드하지 않도록 합니다.
|
|
77
|
+
- 필요할 때만 올바른 로케일을 동적으로 로드합니다.
|
|
78
|
+
|
|
79
|
+
이러한 접근 방식의 기술적 한계 이해:
|
|
80
|
+
|
|
81
|
+
**동적 로딩**
|
|
82
|
+
|
|
83
|
+
동적 로딩이 없으면 대부분의 솔루션은 첫 번째 렌더링부터 메시지를 메모리에 유지하므로 경로와 로케일이 많은 앱의 경우 상당한 오버헤드가 발생합니다.
|
|
84
|
+
|
|
85
|
+
동적 로딩을 사용하면 초기 JS는 줄어들지만 언어 전환 시 추가 요청이 발생할 수 있는 장단점을 수용하게 됩니다.
|
|
86
|
+
|
|
87
|
+
**콘텐츠 분리**
|
|
88
|
+
|
|
89
|
+
`const { t } = useI18n()` + `t('a.b.c')`를 중심으로 구축된 구문은 매우 편리하지만 런타임에 큰 JSON 객체를 유지하도록 조장하는 경우가 많습니다. 이 모델은 라이브러리가 실제 페이지별 분리 전략을 제공하지 않는 한 트리 쉐이킹(tree-shaking)을 어렵게 만듭니다.
|
|
90
|
+
|
|
91
|
+
## 연구 방법론
|
|
92
|
+
|
|
93
|
+
이 벤치마크에서는 다음과 같은 라이브러리를 비교했습니다:
|
|
94
|
+
|
|
95
|
+
- `Base App` (i18n 라이브러리 없음)
|
|
96
|
+
- `vue-intlayer` (v8.7.12)
|
|
97
|
+
- `vue-i18n` (v11.4.0)
|
|
98
|
+
- `fluent-vue` (v3.8.2)
|
|
99
|
+
|
|
100
|
+
프레임워크는 `Vue`이며 **10개의 페이지**와 **10개의 언어**를 가진 다국어 앱을 사용했습니다.
|
|
101
|
+
|
|
102
|
+
**네 가지 로딩 전략**을 비교했습니다:
|
|
103
|
+
|
|
104
|
+
| 전략 | 네임스페이스 없음 (글로벌) | 네임스페이스 포함 (스코프) |
|
|
105
|
+
| :------------ | :------------------------------------------- | :-------------------------------------------------------------- |
|
|
106
|
+
| **정적 로딩** | **Static**: 시작 시 모든 것을 메모리에 로드. | **Scoped static**: 네임스페이스별 분리; 시작 시 모든 것을 로드. |
|
|
107
|
+
| **동적 로딩** | **Dynamic**: 로케일별 온디맨드 로딩. | **Scoped dynamic**: 네임스페이스 및 로케일별 세분화된 로딩. |
|
|
108
|
+
|
|
109
|
+
## 전략 요약
|
|
110
|
+
|
|
111
|
+
- **Static**: 간단함. 초기 로드 후 네트워크 지연 없음. 단점: 큰 번들 크기.
|
|
112
|
+
- **Dynamic**: 초기 무게 감소(지연 로딩). 로케일이 많을 때 적합함.
|
|
113
|
+
- **Scoped static**: 복잡한 추가 네트워크 요청 없이 코드 구조를 유지(논리적 분리).
|
|
114
|
+
- **Scoped dynamic**: 코드 분할 및 성능을 위한 최선의 접근 방식. 현재 뷰와 활성 로케일에 필요한 것만 로드하여 메모리 사용을 최소화함.
|
|
115
|
+
|
|
116
|
+
### 측정 항목:
|
|
117
|
+
|
|
118
|
+
각 스택에 대해 실제 브라우저에서 동일한 다국어 앱을 실행한 다음, 실제로 네트워크에 전송된 데이터와 소요 시간을 기록했습니다. 크기는 **일반적인 웹 압축 후**를 기준으로 보고되는데, 이는 원시 소스 코드 크기보다 실제 다운로드 크기에 더 가깝기 때문입니다.
|
|
119
|
+
|
|
120
|
+
- **국제화 라이브러리 크기**: 번들링, 트리 쉐이킹 및 미니피케이션 후의 i18n 라이브러리 크기는 빈 컴포넌트에서의 프로바이더 + 컴포저블(composables) 코드 크기입니다. 여기에는 번역 파일 로딩은 포함되지 않습니다. 이는 콘텐츠가 들어가기 전에 라이브러리 자체가 얼마나 "무거운지"를 나타냅니다.
|
|
121
|
+
|
|
122
|
+
- **페이지당 JavaScript**: 각 벤치마크 경로에 대해 브라우저가 해당 방문을 위해 가져오는 스크립트의 양으로, 테스트 세트의 페이지 전체(및 로케일 전체)에 대한 평균입니다. 무거운 페이지는 느린 페이지입니다.
|
|
123
|
+
|
|
124
|
+
- **다른 로케일에서의 누수 (Leakage)**: 감사 대상 페이지에서 실수로 로드되는 다른 언어의 동일 페이지 콘텐츠입니다. 이 콘텐츠는 불필요하며 피해야 합니다. (예: `/en/about` 페이지 번들에 포함된 `/fr/about` 페이지 콘텐츠)
|
|
125
|
+
|
|
126
|
+
- **다른 경로에서의 누수**: 앱의 **다른 화면**에 대해서도 동일한 개념입니다. 한 페이지만 열었을 때 다른 화면의 텍스트가 함께 포함되는지 여부입니다. (예: `/en/contact` 페이지 번들에 포함된 `/en/about` 페이지 콘텐츠). 점수가 높으면 분리가 약하거나 번들이 너무 광범위함을 암시합니다.
|
|
127
|
+
|
|
128
|
+
- **평균 컴포넌트 번들 크기**: 공통 UI 요소들을 하나씩 측정하여 국제화가 일상적인 컴포넌트들을 조용히 팽창시키는지 확인합니다. 예를 들어, 컴포넌트가 재렌더링될 때 메모리에서 해당 데이터를 모두 로드하게 됩니다. 컴포넌트에 거대한 JSON을 첨부하는 것은 사용하지 않는 데이터의 거대한 저장소를 연결하는 것과 같으며, 이는 컴포넌트의 성능을 저하시킵니다.
|
|
129
|
+
|
|
130
|
+
- **언어 전환 반응성**: 앱 자체 컨트롤을 사용하여 언어를 전환하고, 방문자가 인지할 수 있을 정도로 페이지가 명확하게 전환될 때까지의 시간을 측정합니다.
|
|
131
|
+
|
|
132
|
+
- **언어 변경 후 렌더링 작업**: 전환이 진행되는 동안 인터페이스가 새로운 언어를 위해 다시 그리는 데 소요된 노력입니다. "체감" 시간과 프레임워크 비용이 다를 때 유용합니다.
|
|
133
|
+
|
|
134
|
+
- **초기 페이지 로드 시간**: 내비게이션부터 브라우저가 테스트 시나리오에 대해 페이지가 완전히 로드되었다고 판단할 때까지의 시간입니다. 콜드 스타트(cold starts)를 비교하는 데 좋습니다.
|
|
135
|
+
|
|
136
|
+
- **하이드레이션 시간 (Hydration)**: 클라이언트가 서버 HTML을 실제 클릭 가능한 상태로 변환하는 데 걸리는 시간입니다. 표의 대시(-)는 해당 구현이 이 벤치마크에서 신뢰할 수 있는 하이드레이션 수치를 제공하지 않았음을 의미합니다.
|
|
137
|
+
|
|
138
|
+
## 결과 상세
|
|
139
|
+
|
|
140
|
+
### 1 — 피해야 할 솔루션
|
|
141
|
+
|
|
142
|
+
> Vue 에코시스템에서 분명하게 피해야 할 솔루션은 없습니다.
|
|
143
|
+
|
|
144
|
+
### 2 — 수용 가능한 솔루션
|
|
145
|
+
|
|
146
|
+
**(vue-i18n)** (`vue-i18n@11.4.0`):
|
|
147
|
+
|
|
148
|
+
- **vue-i18n**은 논쟁의 여지 없이 Vue에서 가장 많이 사용되는 i18n 라이브러리이며, 많은 기능과 거대한 에코시스템을 가지고 있습니다. 하지만 내부적으로 이 솔루션은 상당히 무겁습니다. vue-i18n이 메시지 지연 로딩을 통합하더라도 스코핑(scoping) 기능이 부족합니다. 클래식 Vue SPA 앱의 경우 문제가 없으나, @nuxt/i18n을 사용하는 Nuxt 앱의 경우 모든 페이지의 메시지가 단일 페이지에 포함되는 결과를 초래합니다. 10페이지 이상의 대규모 Nuxt 앱의 경우 이는 정말 문제가 될 수 있습니다.
|
|
149
|
+
|
|
150
|
+
패키지가 매우 무겁습니다 (~24.3kb, `vue-intlayer`의 약 9배).
|
|
151
|
+
|
|
152
|
+
**(fluent-vue)** (`fluent-vue@0.5.0`):
|
|
153
|
+
|
|
154
|
+
- **fluent-vue**는 .ftl 형식을 통해 혁신을 시도합니다. 메시지 구성이 훌륭하고 시작하기 쉽습니다. 하지만 실제로는 타입 안전성의 부재로 오류 위험이 높고 디버깅에 많은 시간이 소요될 수 있습니다. 또한, 이 솔루션은 Vite 플러그인을 사용하여 메시지를 로드하는데, 이는 모든 언어의 모든 콘텐츠를 각 페이지에 강제로 로드하게 만듭니다. 게다가 이는 극도로 무거운 솔루션입니다 (~92.7kb, `vue-intlayer`의 약 34배).
|
|
155
|
+
|
|
156
|
+
### 3 — 추천 사항
|
|
157
|
+
|
|
158
|
+
**(Intlayer)** (`vue-intlayer@8.7.12`):
|
|
159
|
+
|
|
160
|
+
객관성을 위해 나의 솔루션인 `vue-intlayer`에 대해서는 직접 판단하지 않겠습니다.
|
package/docs/ko/configuration.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-08-13
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-05-12
|
|
4
4
|
title: 구성 (Configuration)
|
|
5
5
|
description: 애플리케이션에 Intlayer를 구성하는 방법을 알아보세요. 필요에 따라 Intlayer를 맞춤설정하는 데 사용할 수 있는 다양한 설정과 옵션을 이해하세요.
|
|
6
6
|
keywords:
|
|
@@ -14,6 +14,9 @@ slugs:
|
|
|
14
14
|
- concept
|
|
15
15
|
- configuration
|
|
16
16
|
history:
|
|
17
|
+
- version: 8.9.4
|
|
18
|
+
date: 2026-05-12
|
|
19
|
+
changes: "LM Studio 공급자 지원 추가"
|
|
17
20
|
- version: 8.7.0
|
|
18
21
|
date: 2026-04-08
|
|
19
22
|
changes: "빌드 구성에 `prune` 및 `minify` 옵션 추가"
|
|
@@ -350,7 +353,7 @@ const config: IntlayerConfig = {
|
|
|
350
353
|
ai: {
|
|
351
354
|
/**
|
|
352
355
|
* 사용할 AI 프로바이더.
|
|
353
|
-
* 옵션: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
|
|
356
|
+
* 옵션: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio'
|
|
354
357
|
* 기본값: 'openai'
|
|
355
358
|
*/
|
|
356
359
|
provider: "openai",
|
|
@@ -916,16 +919,17 @@ Intlayer는 최대의 유연성을 보장하기 위해 다양한 AI 프로바이
|
|
|
916
919
|
- **Groq**
|
|
917
920
|
- **Amazon Bedrock**
|
|
918
921
|
- **Together.ai**
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
|
922
|
-
|
|
|
923
|
-
| `
|
|
924
|
-
| `
|
|
925
|
-
| `
|
|
926
|
-
| `
|
|
927
|
-
| `
|
|
928
|
-
| `
|
|
922
|
+
- **LM Studio**
|
|
923
|
+
|
|
924
|
+
| 필드 | 설명 | 타입 | 기본값 | 예시 | 참고 |
|
|
925
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
926
|
+
| `provider` | Intlayer AI 기능에 사용할 프로바이더. | `'openai'` | <br/> `'anthropic'` | <br/> `'mistral'` | <br/> `'deepseek'` | <br/> `'gemini'` | <br/> `'ollama'` | <br/> `'openrouter'` | <br/> `'alibaba'` | <br/> `'fireworks'` | <br/> `'groq'` | <br/> `'huggingface'` | <br/> `'bedrock'` | <br/> `'googleaistudio'` | <br/> `'googlevertex'` | <br/> `'togetherai'` | <br/> `'lmstudio'` | `undefined` | `'anthropic'` | 여러 프로바이더는 서로 다른 API 키가 필요하며 가격 구조도 다릅니다. |
|
|
927
|
+
| `model` | AI 기능에 사용할 AI 모델. | `string` | 없음 | `'gpt-4o-2024-11-20'` | 특정 모델은 프로바이더에 따라 다릅니다. |
|
|
928
|
+
| `temperature` | AI 응답의 무작위성을 제어합니다. | `number` | 없음 | `0.1` | 온도가 높을수록 창의적이지만 신뢰성이 낮아집니다. |
|
|
929
|
+
| `apiKey` | 선택한 프로바이더의 API 키. | `string` | 없음 | `process.env.OPENAI_API_KEY` | 비밀로 유지해야 하며 환경 변수를 사용하세요. |
|
|
930
|
+
| `applicationContext` | AI가 더 정확한 번역을 생성할 수 있도록 돕는 애플리케이션에 대한 추가 컨텍스트(도메인, 대상 고객, 어조, 용어 등). | `string` | 없음 | `'my custom app context'` | 규칙을 추가하는 데 사용할 수 있습니다 (예: `"URL은 번역하지 마세요"` ). |
|
|
931
|
+
| `baseURL` | AI API에 대한 기본 URL. | `string` | 없음 | `'https://api.openai.com/v1'` <br/> `'http://localhost:5000'` | 로컬 또는 맞춤형 AI API 엔드포인트를 가리킬 수 있습니다. |
|
|
932
|
+
| `dataSerialization` | AI 기능에 대한 데이터 직렬화 형식. | `'json'` | <br/> `'toon'` | `undefined` | `'toon'` | • `'json'`: 기본값, 안정적임; 더 많은 토큰 소비.<br/>• `'toon'`: 더 적은 토큰 소모, 덜 안정적임.<br/>• 모델에 로직 실행을 위한 추가 파라미터(추론 노력(reasoning effort) 등)를 전달합니다. |
|
|
929
933
|
|
|
930
934
|
---
|
|
931
935
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-02-07
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-05-12
|
|
4
4
|
title: 콘텐츠 파일
|
|
5
5
|
description: 콘텐츠 선언 파일의 확장자를 사용자 정의하는 방법을 배우세요. 이 문서를 따라 프로젝트에서 조건을 효율적으로 구현하세요.
|
|
6
6
|
keywords:
|
|
@@ -12,6 +12,9 @@ slugs:
|
|
|
12
12
|
- concept
|
|
13
13
|
- content
|
|
14
14
|
history:
|
|
15
|
+
- version: 8.9.0
|
|
16
|
+
date: 2026-05-12
|
|
17
|
+
changes: "`plural` 콘텐츠 노드 유형 추가"
|
|
15
18
|
- version: 8.0.0
|
|
16
19
|
date: 2026-01-28
|
|
17
20
|
changes: "`html` 콘텐츠 노드 타입 추가"
|
|
@@ -63,6 +66,7 @@ import { type ReactNode } from "react";
|
|
|
63
66
|
import {
|
|
64
67
|
t,
|
|
65
68
|
enu,
|
|
69
|
+
plural,
|
|
66
70
|
cond,
|
|
67
71
|
nest,
|
|
68
72
|
md,
|
|
@@ -82,6 +86,7 @@ interface Content {
|
|
|
82
86
|
};
|
|
83
87
|
multilingualContent: string;
|
|
84
88
|
quantityContent: string;
|
|
89
|
+
pluralContent: string;
|
|
85
90
|
conditionalContent: string;
|
|
86
91
|
markdownContent: never;
|
|
87
92
|
htmlContent: never;
|
|
@@ -118,6 +123,10 @@ export default {
|
|
|
118
123
|
">5": "몇 대의 자동차",
|
|
119
124
|
">19": "많은 자동차",
|
|
120
125
|
}),
|
|
126
|
+
pluralContent: plural({
|
|
127
|
+
one: "One car",
|
|
128
|
+
other: "{{count}} cars",
|
|
129
|
+
}),
|
|
121
130
|
conditionalContent: cond({
|
|
122
131
|
true: "검증이 활성화됨",
|
|
123
132
|
false: "검증이 비활성화됨",
|
|
@@ -172,6 +181,13 @@ export default {
|
|
|
172
181
|
">5": "몇 대의 차",
|
|
173
182
|
">19": "많은 차",
|
|
174
183
|
},
|
|
184
|
+
"pluralContent": {
|
|
185
|
+
"nodeType": "plural",
|
|
186
|
+
"plural": {
|
|
187
|
+
"one": "One car",
|
|
188
|
+
"other": "{{count}} cars",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
175
191
|
},
|
|
176
192
|
"conditionalContent": {
|
|
177
193
|
"nodeType": "condition",
|
|
@@ -219,6 +235,7 @@ export default {
|
|
|
219
235
|
- **원시 값**: 문자열, 숫자, 불리언, null, undefined
|
|
220
236
|
- **타입이 지정된 노드**: 번역, 조건, 마크다운 등과 같은 특수 콘텐츠 유형
|
|
221
237
|
- **함수**: 런타임에 평가될 수 있는 동적 콘텐츠 [함수 가져오기 참조](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/function_fetching.md)
|
|
238
|
+
- **복수형 콘텐츠**: 자세한 내용은 복수형 콘텐츠 [자세한 내용은 복수형 콘텐츠](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/plural.md)
|
|
222
239
|
- **중첩 콘텐츠**: 다른 사전에 대한 참조
|
|
223
240
|
|
|
224
241
|
#### 콘텐츠 유형
|
|
@@ -564,6 +581,8 @@ multilingualContent: t({
|
|
|
564
581
|
});
|
|
565
582
|
```
|
|
566
583
|
|
|
584
|
+
> 자세한 내용은 [번역 콘텐츠 (`t`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/translation.md) 를 참조하세요.
|
|
585
|
+
|
|
567
586
|
### 조건 콘텐츠 (`cond`)
|
|
568
587
|
|
|
569
588
|
불리언 조건에 따라 변경되는 콘텐츠:
|
|
@@ -577,6 +596,8 @@ conditionalContent: cond({
|
|
|
577
596
|
});
|
|
578
597
|
```
|
|
579
598
|
|
|
599
|
+
> 자세한 내용은 [조건 콘텐츠 (`cond`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/condition.md) 를 참조하세요.
|
|
600
|
+
|
|
580
601
|
### 열거형 콘텐츠 (`enu`)
|
|
581
602
|
|
|
582
603
|
열거형 값에 따라 달라지는 콘텐츠:
|
|
@@ -591,6 +612,23 @@ statusContent: enu({
|
|
|
591
612
|
});
|
|
592
613
|
```
|
|
593
614
|
|
|
615
|
+
> 자세한 내용은 [열거형 콘텐츠 (`enu`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/enumeration.md) 를 참조하세요.
|
|
616
|
+
|
|
617
|
+
### 복수형 콘텐츠 (`plural`)
|
|
618
|
+
|
|
619
|
+
복수형 규칙에 따라 달라지는 콘텐츠:
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
import { plural } from "intlayer";
|
|
623
|
+
|
|
624
|
+
pluralContent: plural({
|
|
625
|
+
one: "One car",
|
|
626
|
+
other: "{{count}} cars",
|
|
627
|
+
});
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
> 자세한 내용은 [복수형 콘텐츠 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/plural.md) 를 참조하세요.
|
|
631
|
+
|
|
594
632
|
### 삽입 콘텐츠 (`insert`)
|
|
595
633
|
|
|
596
634
|
다른 콘텐츠에 삽입할 수 있는 콘텐츠:
|
|
@@ -601,6 +639,8 @@ import { insert } from "intlayer";
|
|
|
601
639
|
insertionContent: insert("이 텍스트는 어디에나 삽입할 수 있습니다");
|
|
602
640
|
```
|
|
603
641
|
|
|
642
|
+
> 자세한 내용은 [삽입 콘텐츠 (`insert`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/insertion.md) 를 참조하세요.
|
|
643
|
+
|
|
604
644
|
### 중첩 콘텐츠 (`nest`)
|
|
605
645
|
|
|
606
646
|
다른 사전에 대한 참조:
|
|
@@ -611,6 +651,8 @@ import { nest } from "intlayer";
|
|
|
611
651
|
nestedContent: nest("about-page");
|
|
612
652
|
```
|
|
613
653
|
|
|
654
|
+
> 자세한 내용은 [중첩 콘텐츠 (`nest`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/nesting.md) 를 참조하세요.
|
|
655
|
+
|
|
614
656
|
### 마크다운 콘텐츠 (`md`)
|
|
615
657
|
|
|
616
658
|
마크다운 형식의 리치 텍스트 콘텐츠:
|
|
@@ -623,6 +665,8 @@ markdownContent: md(
|
|
|
623
665
|
);
|
|
624
666
|
```
|
|
625
667
|
|
|
668
|
+
> 자세한 내용은 [마크다운 콘텐츠 (`md`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/markdown.md) 를 참조하세요.
|
|
669
|
+
|
|
626
670
|
### HTML 콘텐츠 (`html`)
|
|
627
671
|
|
|
628
672
|
표준 태그 또는 사용자 정의 컴포넌트를 사용할 수 있는 리치 HTML 콘텐츠:
|
|
@@ -640,6 +684,8 @@ localizedHtmlContent: t({
|
|
|
640
684
|
});
|
|
641
685
|
```
|
|
642
686
|
|
|
687
|
+
> 자세한 내용은 [HTML 콘텐츠 (`html`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/html.md) 를 참조하세요.
|
|
688
|
+
|
|
643
689
|
### 성별에 따른 콘텐츠 (`gender`)
|
|
644
690
|
|
|
645
691
|
성별에 따라 달라지는 콘텐츠:
|
|
@@ -654,6 +700,8 @@ genderContent: gender({
|
|
|
654
700
|
});
|
|
655
701
|
```
|
|
656
702
|
|
|
703
|
+
> 자세한 내용은 [성별에 따른 콘텐츠 (`gender`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/gender.md) 를 참조하세요.
|
|
704
|
+
|
|
657
705
|
### 파일 콘텐츠 (`file`)
|
|
658
706
|
|
|
659
707
|
외부 파일에 대한 참조:
|
|
@@ -664,6 +712,8 @@ import { file } from "intlayer";
|
|
|
664
712
|
fileContent: file("./path/to/content.txt");
|
|
665
713
|
```
|
|
666
714
|
|
|
715
|
+
> 자세한 내용은 [파일 콘텐츠 (`file`) 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/file.md) 를 참조하세요.
|
|
716
|
+
|
|
667
717
|
## 콘텐츠 파일 생성하기
|
|
668
718
|
|
|
669
719
|
### 기본 콘텐츠 파일 구조
|
|
@@ -625,7 +625,7 @@ Intlayer는 TypeScript의 이점을 얻고 코드베이스를 더욱 견고하
|
|
|
625
625
|
|
|
626
626
|
TypeScript 구성에 자동 생성된 타입들이 포함되어 있는지 확인하세요.
|
|
627
627
|
|
|
628
|
-
|
|
628
|
+
```json5 fileName="tsconfig.json"
|
|
629
629
|
{
|
|
630
630
|
// ... 기존 TypeScript 구성
|
|
631
631
|
"include": [
|
|
@@ -633,6 +633,7 @@ TypeScript 구성에 자동 생성된 타입들이 포함되어 있는지 확인
|
|
|
633
633
|
".intlayer/**/*.ts", // 자동으로 생성된 타입 포함
|
|
634
634
|
],
|
|
635
635
|
}
|
|
636
|
+
```
|
|
636
637
|
|
|
637
638
|
### Git 구성
|
|
638
639
|
|
|
@@ -643,7 +644,7 @@ Intlayer에 의해 생성된 파일을 무시하는 것을 권장합니다. 이
|
|
|
643
644
|
```plaintext fileName=".gitignore"
|
|
644
645
|
# Intlayer에 의해 생성된 파일 무시
|
|
645
646
|
.intlayer
|
|
646
|
-
|
|
647
|
+
```
|
|
647
648
|
|
|
648
649
|
### VS Code 확장
|
|
649
650
|
|