@gaonjs/cli 0.62.0 → 0.62.1
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.
|
@@ -164,7 +164,29 @@ async switchLocale() {
|
|
|
164
164
|
전환 뒤에는 새 로케일 카탈로그 청크가 필요하므로 **전체 리로드가 정답**이다(그 한 번의
|
|
165
165
|
왕복이 깜빡임 0을 보장한다). `<html lang>` 은 최초 문서에서 협상 로케일을 자동 추종한다(결정 214).
|
|
166
166
|
|
|
167
|
-
### 8.
|
|
167
|
+
### 8. 런타임에 키가 없으면 — **키 렌더 + 경고**(요청은 산다 · 결정 455)
|
|
168
|
+
|
|
169
|
+
번역 누락은 **페이지 크래시 사유가 아니다.** 서버 `t()`·클라 `t()` 둘 다 같은 계약이다:
|
|
170
|
+
|
|
171
|
+
1. 활성 로케일 → `fallbackLng` 순으로 찾는다(폴백에 있으면 그 텍스트가 나온다).
|
|
172
|
+
2. 둘 다 없으면 **키 문자열을 그대로 렌더**한다(`posts.heading` 이 화면에 보인다).
|
|
173
|
+
3. 동시에 **경고를 한 번 남긴다** — 서버는 `log.warn`, 클라는 `console.warn`.
|
|
174
|
+
같은 키·같은 로케일은 한 번만(로그 도배 방지) · 어느 로케일에서 비었는지 함께 찍힌다.
|
|
175
|
+
|
|
176
|
+
**정적 키는 여기까지 오지 않는다** — `.gaon/messages.d.ts` 가 빌드·`gaon check` 에서 막는다.
|
|
177
|
+
런타임까지 오는 것은 **동적 키**(`t(변수)`)와 진짜 카탈로그 누락뿐이라, 그 둘만 우아하게
|
|
178
|
+
degrade 한다. 즉 **빌드 = 차단 / 런타임 = 키 렌더 + 경고**의 2단이다.
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
const key = `posts.${kind}` // 동적 키 — 컴파일 게이트가 못 본다
|
|
182
|
+
t(key as never) // 없으면 'posts.abc' 가 화면에 뜨고 경고 1줄
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
- **경고를 삼키지 말 것** — 화면에 키가 보이는데 로그가 조용하면 원인을 찾는 데 시간이
|
|
186
|
+
녹는다(이 계약이 막는 것이 정확히 그 침묵이다).
|
|
187
|
+
- 런타임까지 **실패로 만들고 싶다면**(엄격 모드) 지금은 지원하지 않는다 — 필요하면 요청하라.
|
|
188
|
+
|
|
189
|
+
### 9. 로케일 커버리지 — `locale-parity` 경고 (결정 216)
|
|
168
190
|
|
|
169
191
|
키 유니온은 기준 로케일 하나에서 나오므로, 어떤 키를 `ko` 에만 넣고 `ja` 에 빠뜨리면
|
|
170
192
|
컴파일은 통과하고 일본어 사용자만 조용히 fallback 을 본다. `gaon doctor` 의 `locale-parity`
|
|
@@ -244,6 +266,9 @@ gaon gen
|
|
|
244
266
|
이스케이프하지만 `v-html` 은 하지 않는다(서버·클라 모두 `escapeValue:false`).
|
|
245
267
|
- **카탈로그에 비밀·미출시 문구를 두지 말 것** — `frontend.json` 은 클라로 나간다. 권한이
|
|
246
268
|
갈리는 화면은 **앱을 나눈다**(같은 앱 안에서는 문구가 갈리지 않는다).
|
|
269
|
+
- **화면에 키 문자열이 보이면 카탈로그 누락이다** — 크래시가 아니라 의도된 degrade 다
|
|
270
|
+
(결정 455). 서버 로그·브라우저 콘솔의 `[i18n]`·`[gaonjs/vue]` 경고가 어느 키·어느
|
|
271
|
+
로케일인지 짚어 준다.
|
|
247
272
|
- **잡·크론은 로케일을 페이로드에 싣는다** — 요청 밖이라 ALS 가 없다(`runWithLanguage`).
|
|
248
273
|
- **메일은 요청 로케일이 아니라 수신자 로케일** — `deliver(data, { locale })`(결정 160).
|
|
249
274
|
- **`i18n.dir`·`fallbackLng` 는 문자열 리터럴로**(결정 412) — 변수·env 표현식은 타입 축과
|
|
@@ -268,4 +293,5 @@ gaon gen
|
|
|
268
293
|
| 결정 352 | 기준 로케일 = `fallbackLng` · `i18n.dir` 존중 |
|
|
269
294
|
| 결정 353 · 413 | 빈 카탈로그·지목 로케일 부재 = 부팅 fail-loud + check 사전 검사 |
|
|
270
295
|
| 결정 412 · 414 | i18n config 정적 분석 범위·경고 · 생성 키 이스케이프 · `supportedLngs: []` |
|
|
296
|
+
| **결정 455** | 런타임 없는키 = **키 렌더 + 경고**(서버·클라 동일) · 요청/화면을 죽이지 않는다 · 폴백 해석은 유지 · 정적 키는 컴파일에서 차단(2단) |
|
|
271
297
|
| **결정 454** | **클라 `t()`(`gaonjs/vue`) · backend/frontend 폴더 레이아웃 · 두 갈래 타입 · 앱별 카탈로그 청크(immutable·seal 면제) · 공유 prop `locale`(연성 예약) · doctor `i18n-layout`·`i18n-app-scope`** |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaonjs/cli",
|
|
3
|
-
"version": "0.62.
|
|
3
|
+
"version": "0.62.1",
|
|
4
4
|
"description": "Gaon CLI — 스캐폴딩·제너레이터·마이그레이션·dev/serve/work/hub·doctor·check (bin: gaon)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"typescript": "^5.9.0",
|
|
34
34
|
"vite": "^7.0.0",
|
|
35
35
|
"@gaonjs/async": "0.22.0",
|
|
36
|
-
"@gaonjs/config": "0.25.
|
|
37
|
-
"@gaonjs/i18n": "0.4.0",
|
|
36
|
+
"@gaonjs/config": "0.25.9",
|
|
38
37
|
"@gaonjs/core": "0.3.0",
|
|
39
|
-
"@gaonjs/
|
|
40
|
-
"@gaonjs/mail": "0.5.
|
|
41
|
-
"@gaonjs/web": "0.32.0"
|
|
38
|
+
"@gaonjs/i18n": "0.4.1",
|
|
39
|
+
"@gaonjs/mail": "0.5.3",
|
|
40
|
+
"@gaonjs/web": "0.32.0",
|
|
41
|
+
"@gaonjs/data": "0.25.4"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json && node -e \"const fs=require('fs');fs.cpSync('src/templates','dist/templates',{recursive:true,filter:(s)=>!s.endsWith('.ts')});fs.rmSync('dist/templates/index.ts',{force:true})\""
|