@iyulab/modern-app 0.39.0 → 0.40.0
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/CHANGELOG.md +11 -0
- package/README.md +3 -1
- package/dist/App.d.ts +9 -0
- package/dist/App.js +20 -11
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.40.0] - 2026-10-07
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **With `i18n` configured, i18next's language drives the whole app** — at load and on every `changeLanguage()` it is
|
|
8
|
+
handed to `@iyulab/components`' `Locale` (shell, primitives and component chrome follow, re-rendering on screen) and
|
|
9
|
+
to `<html lang>` (WCAG 3.1.1). Before, `changeLanguage('ko')` changed the app's own text while button names, empty
|
|
10
|
+
states and validation messages stayed in the old language, and a first load could show two languages when i18next's
|
|
11
|
+
`lng` differed from `<html lang>` or the browser's. Without `i18n` nothing changes — `Locale.set()` chooses.
|
|
12
|
+
- **Requires `@iyulab/components` 2.8.0** (peer `>=2.8.0`) — the version whose components re-render on a locale switch.
|
|
13
|
+
|
|
3
14
|
## [0.39.0] - 2026-10-06
|
|
4
15
|
|
|
5
16
|
### Fixed
|
package/README.md
CHANGED
|
@@ -148,7 +148,9 @@ html`<p>${translate('common::greeting')}</p>`;
|
|
|
148
148
|
The package's own strings — the page header's back link, empty-state copy, the shell's toggle and
|
|
149
149
|
close labels, the wizard's buttons and step announcement — live in the `modern-app` namespace of
|
|
150
150
|
`@iyulab/components`' `Locale`. English and Korean are built in, English being the default; pick the
|
|
151
|
-
language once, with `Locale.set()` — the primitives and `@iyulab/flex-table` follow the same call.
|
|
151
|
+
language once, with `Locale.set()` — the primitives and `@iyulab/flex-table` follow the same call. With
|
|
152
|
+
`i18n` configured you do not call it: i18next's language (at load and on every `changeLanguage()`) is
|
|
153
|
+
handed to `Locale` and to `<html lang>`.
|
|
152
154
|
Register other languages, or your own wording, in the same namespace:
|
|
153
155
|
|
|
154
156
|
```typescript
|
package/dist/App.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ declare class App {
|
|
|
14
14
|
private _screen?;
|
|
15
15
|
private _user?;
|
|
16
16
|
private _gateTeardown?;
|
|
17
|
+
/** i18next 언어 → components `Locale` 동기화 해제(`unload`). */
|
|
18
|
+
private _languageSync?;
|
|
17
19
|
private constructor();
|
|
18
20
|
/** 싱글톤 인스턴스 반환 */
|
|
19
21
|
static get instance(): App;
|
|
@@ -32,6 +34,13 @@ declare class App {
|
|
|
32
34
|
/** 앱 로드 및 초기화 */
|
|
33
35
|
load(config: AppConfig): Promise<void>;
|
|
34
36
|
/** 앱 언로드 */
|
|
37
|
+
/**
|
|
38
|
+
* i18next 를 설정한 앱에서는 **i18next 가 언어의 정본**이다 — 그 언어를 셸·컴포넌트 chrome(`@iyulab/components` 의
|
|
39
|
+
* `Locale`, 이 패키지의 `modernAppLocale` 이 그것을 따른다)과 문서 `<html lang>`(WCAG 3.1.1, 낭독기 발음)에 잇는다.
|
|
40
|
+
* 종전에는 둘이 따로였다: `i18next.changeLanguage('ko')` 가 앱 문장만 바꾸고 버튼 이름·빈 상태·검증 메시지는 옛 언어로,
|
|
41
|
+
* 첫 로드에서도 i18next `lng` 와 `<html lang>`/브라우저 언어가 다르면 한 화면에 두 언어가 섰다.
|
|
42
|
+
*/
|
|
43
|
+
private syncLanguage;
|
|
35
44
|
unload(): void;
|
|
36
45
|
/** 페이지 이동 */
|
|
37
46
|
navigate(path: string): void;
|
package/dist/App.js
CHANGED
|
@@ -4,23 +4,24 @@ import { Router as n } from "@iyulab/router";
|
|
|
4
4
|
import { setDefaultBaseUrl as r } from "@iyulab/components/dist/utilities/icons.js";
|
|
5
5
|
import { Theme as i } from "@iyulab/components/dist/utilities/Theme.js";
|
|
6
6
|
import { Toast as a } from "@iyulab/components/dist/utilities/Toast.js";
|
|
7
|
+
import { Locale as o } from "@iyulab/components/dist/utilities/Locale.js";
|
|
7
8
|
//#region src/App.ts
|
|
8
|
-
var
|
|
9
|
-
function
|
|
10
|
-
if (!
|
|
9
|
+
var s = "\n:where(body) { margin: 0; }\n@media screen {\n :where(body) { width: 100vw; height: 100vh; }\n}\n", c;
|
|
10
|
+
function l() {
|
|
11
|
+
if (!c) {
|
|
11
12
|
if ("adoptedStyleSheets" in document && typeof CSSStyleSheet < "u" && typeof CSSStyleSheet.prototype.replaceSync == "function") {
|
|
12
13
|
let e = new CSSStyleSheet();
|
|
13
|
-
e.replaceSync(
|
|
14
|
+
e.replaceSync(s), document.adoptedStyleSheets = [...document.adoptedStyleSheets, e], c = e;
|
|
14
15
|
} else {
|
|
15
16
|
let e = document.createElement("style");
|
|
16
|
-
e.textContent =
|
|
17
|
+
e.textContent = s, document.head.prepend(e), c = e;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
var
|
|
21
|
+
var u = class s {
|
|
21
22
|
constructor() {}
|
|
22
23
|
static get instance() {
|
|
23
|
-
return
|
|
24
|
+
return s._instance ||= new s(), s._instance;
|
|
24
25
|
}
|
|
25
26
|
get config() {
|
|
26
27
|
return this._config;
|
|
@@ -43,7 +44,7 @@ var l = class o {
|
|
|
43
44
|
async load(a) {
|
|
44
45
|
if (this.unload(), this._config = a, await i.init(a.theme), a.iconBasepath && r(a.iconBasepath), a.i18n) {
|
|
45
46
|
for (let e of a.i18n.plugins || []) t.use(e);
|
|
46
|
-
await t.init(a.i18n);
|
|
47
|
+
await t.init(a.i18n), this.syncLanguage();
|
|
47
48
|
}
|
|
48
49
|
if (a.auth) {
|
|
49
50
|
let e = a.root || document.body, t = () => {
|
|
@@ -88,8 +89,16 @@ var l = class o {
|
|
|
88
89
|
useIntercept: a.useIntercept
|
|
89
90
|
});
|
|
90
91
|
}
|
|
92
|
+
syncLanguage() {
|
|
93
|
+
let e = (e) => {
|
|
94
|
+
e && e !== "cimode" && (o.set(e), typeof document < "u" && (document.documentElement.lang = e));
|
|
95
|
+
};
|
|
96
|
+
e(t.resolvedLanguage ?? t.language);
|
|
97
|
+
let n = (n) => e(t.resolvedLanguage ?? n);
|
|
98
|
+
t.on("languageChanged", n), this._languageSync = () => t.off("languageChanged", n);
|
|
99
|
+
}
|
|
91
100
|
unload() {
|
|
92
|
-
this._gateTeardown &&= (this._gateTeardown(), void 0), this._user = void 0, this._screen &&= (this._screen.destroy(), void 0), this._layout &&= (this._layout.remove(), void 0), this._router &&= (this._router.destroy(), void 0), this._config &&= void 0;
|
|
101
|
+
this._languageSync?.(), this._languageSync = void 0, this._gateTeardown &&= (this._gateTeardown(), void 0), this._user = void 0, this._screen &&= (this._screen.destroy(), void 0), this._layout &&= (this._layout.remove(), void 0), this._router &&= (this._router.destroy(), void 0), this._config &&= void 0;
|
|
93
102
|
}
|
|
94
103
|
navigate(e) {
|
|
95
104
|
this._router?.go(e);
|
|
@@ -116,7 +125,7 @@ var l = class o {
|
|
|
116
125
|
await a.error(e, { ...t });
|
|
117
126
|
}
|
|
118
127
|
async createLayout(e, t) {
|
|
119
|
-
e === document.body &&
|
|
128
|
+
e === document.body && l();
|
|
120
129
|
let n;
|
|
121
130
|
if (t.type === "sidebar") {
|
|
122
131
|
let { SidebarLayout: e } = await import("./layouts/SidebarLayout.js"), r = new e();
|
|
@@ -126,4 +135,4 @@ var l = class o {
|
|
|
126
135
|
}
|
|
127
136
|
}.instance;
|
|
128
137
|
//#endregion
|
|
129
|
-
export {
|
|
138
|
+
export { u as app };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/modern-app",
|
|
3
3
|
"description": "web-framework by iyulab based on lit-element",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.40.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iyulab",
|
|
7
7
|
"web-framework",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"lit": "^3.3.3"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
|
-
"@iyulab/components": ">=2.
|
|
68
|
+
"@iyulab/components": ">=2.8.0",
|
|
69
69
|
"@lit/react": "^1.0.8",
|
|
70
70
|
"react": "^18.0.0 || ^19.0.0"
|
|
71
71
|
},
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@iyulab/components": ">=2.
|
|
81
|
+
"@iyulab/components": ">=2.8.0",
|
|
82
82
|
"@lit/react": "^1.0.8",
|
|
83
83
|
"@types/node": "^26.1.1",
|
|
84
84
|
"@types/react": "^19.2.14",
|