-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathi18n.js
More file actions
385 lines (368 loc) · 28.8 KB
/
Copy pathi18n.js
File metadata and controls
385 lines (368 loc) · 28.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
const messages = {
ko: {
metaTitle: "맥락지혜 연구실 | Contextual Wisdom Lab",
metaDescription: "맥락지혜 연구실은 흩어진 기업 자료를 맥락 안에서 판단 가능한 구조로 바꾸는 AI 의사결정 지원 시스템을 연구하고 만듭니다.",
logoSrc: "assets/context-wisdom-lab-logo.svg",
logoAlt: "맥락지혜 연구실 · Contextual Wisdom Lab",
"nav.intro": "소개",
"nav.problem": "문제의식",
"nav.model": "연구모형",
"nav.evidence": "근거",
"nav.contextualWisdom": "이름 뜻",
"nav.principles": "원칙",
"nav.dikw": "DIKW",
"nav.logo": "로고",
"nav.naruon": "Naruon",
"nav.projects": "프로젝트",
"nav.forks": "Fork",
"nav.references": "참고문헌",
"nav.work": "작업",
"nav.skipToContent": "본문으로 건너뛰기",
"hero.title": "맥락지혜 연구실",
"hero.labName": "Contextual Wisdom Lab",
"hero.thesis": "구슬이 서 말이어도 꿰어야 보배이듯, 문서, 메일, 로그, 회의록을 맥락 안에서 엮어 사람이 무엇을 결정하고 무엇을 실행할지 보이게 하는 AI 의사결정 지원 시스템을 연구하고 만듭니다.",
"hero.primaryCta": "GitHub 보기",
"hero.secondaryCta": "DIKW 보기",
"ladder.data": "기록된 흔적 · 문서 · 메일 · 로그",
"ladder.information": "질문과 기준 안에서 해석된 자료",
"ladder.knowledge": "관계, 원인, 제약으로 설명되는 구조",
"ladder.wisdom": "판단과 실행으로 건너가기",
"principles.title": "맥락지혜는 맥락 안에서 판단을 세우는 방향입니다",
"principles.lead": "Contextual Wisdom은 많이 아는 상태가 아니라, 구체적인 맥락 안에서 판단과 실행으로 건너가는 과정을 뜻합니다. 메일, 문서, 로그, 일정 사이의 흩어진 맥락을 묶어 오늘 결정할 것과 다음 행동을 보이게 합니다.",
"principles.oneTitle": "앞뒤 사정 보기",
"principles.oneBody": "같은 말과 기록도 상황이 바뀌면 뜻이 달라집니다. 목적, 제약, 이해관계, 시간 압박을 함께 봅니다.",
"principles.purposeTitle": "목적",
"principles.purposeBody": "그 기록이 왜 생겼는지 봅니다. 고객 요청 처리, 장애 원인 확인, 일정 조율처럼 문제의 방향을 정합니다.",
"principles.constraintTitle": "제약",
"principles.constraintBody": "권한, 예산, 일정, 보안처럼 선택을 제한하는 조건을 따로 표시합니다.",
"principles.stakeholderTitle": "이해관계",
"principles.stakeholderBody": "고객, 담당자, 승인자, 운영자 중 누가 영향을 받는지 연결합니다.",
"principles.twoTitle": "종합은 요약이 아닙니다",
"principles.twoBody": "길이를 줄이는 데서 멈추지 않습니다. 증거, 맥락, 리스크, 선택지를 엮어 사람이 판단할 수 있는 구조를 만듭니다.",
"principles.evidenceTitle": "증거",
"principles.evidenceBody": "원문 메일, 회의록 문장, 로그, 첨부파일, VOC처럼 판단을 뒷받침하는 출처입니다.",
"principles.contextTitle": "맥락",
"principles.contextBody": "누가, 언제, 왜, 어떤 기준으로 남긴 기록인지 설명하는 주변 정보입니다.",
"principles.riskTitle": "리스크",
"principles.riskBody": "누락된 정보, 반례, 권한 충돌, 일정 지연처럼 결정을 틀리게 만들 수 있는 조건입니다.",
"principles.optionTitle": "선택지",
"principles.optionBody": "승인, 보류, 추가 확인, 위임, 일정 변경처럼 지금 실제로 고를 수 있는 행동입니다.",
"principles.threeTitle": "실행으로 이어가기",
"principles.threeBody": "좋은 구조는 읽고 끝나지 않습니다. 결정할 것, 확인할 가정, 다음 행동, 위임과 기록으로 이어져야 합니다.",
"principles.decisionTitle": "결정할 것",
"principles.decisionBody": "지금 사람이 선택해야 하는 항목입니다. 예를 들면 승인 여부, 우선순위, 대응 범위입니다.",
"principles.assumptionTitle": "확인할 가정",
"principles.assumptionBody": "틀리면 결론이 바뀌는 전제입니다. 고객 영향, 장애 원인, 비용 추정이 여기에 들어갑니다.",
"principles.actionTitle": "다음 행동",
"principles.actionBody": "담당자, 기한, 산출물, 남길 기록까지 붙은 실행 단위입니다.",
"problem.title": "시작점은 인지 부하입니다",
"problem.lead": "정보가 부족해서가 아니라, 판단해야 할 맥락이 흩어져 있어서 어렵습니다. 사람이 버거워지는 순간은 데이터가 많을 때가 아니라 맥락을 다시 조립해야 할 때입니다.",
"problem.oneTitle": "흩어진 자료",
"problem.oneBody": "메일에는 요청, 첨부에는 근거, 회의록에는 결정, 일정에는 기한이 따로 남습니다. 한 화면에 같이 있어야 판단할 수 있습니다.",
"problem.twoTitle": "사라지는 기준",
"problem.twoBody": "승인한 이유, 보류한 조건, 당시 제약, 빠진 반례가 시간이 지나면 흐려집니다.",
"problem.threeTitle": "필요한 구조",
"problem.threeBody": "오늘 결정할 것, 더 확인할 것, 맡을 사람, 기한, 남길 기록이 한 흐름으로 보여야 합니다.",
"dikw.title": "DIKW는 판단 흐름을 점검하는 질문입니다",
"dikw.lead": "PPTX의 흐름은 기업 자료, 맥락화, 판단 포인트, 실행 연결입니다. DIKW는 이 흐름을 자동 상승 위계로 보자는 말이 아니라, 자료가 판단 근거로 쓰일 준비가 되었는지 묻는 점검 질문입니다.",
"dikw.dataTitle": "기업 자료",
"dikw.dataBody": "메일 요청, 회의록 문장, 로그 오류, VOC, 일정 변경처럼 아직 서로 연결되지 않은 기록입니다.",
"dikw.infoTitle": "맥락화",
"dikw.infoBody": "작성자, 시점, 프로젝트, 고객, 권한, 의사결정 기준을 붙여 기록이 무엇을 뜻하는지 보이게 합니다.",
"dikw.knowledgeTitle": "판단 포인트",
"dikw.knowledgeBody": "반복되는 패턴, 예외, 원인 후보, 제약, 담당 절차를 묶어 무엇을 판단해야 하는지 드러냅니다.",
"dikw.wisdomTitle": "실행 연결",
"dikw.wisdomBody": "승인, 보류, 위임, 추가 확인처럼 가능한 선택을 비교하고 다음 담당자와 기한으로 연결합니다.",
"evidence.title": "그래서 화면은 이렇게 물어야 합니다",
"evidence.lead": "기록을 모았다고 판단이 끝나지는 않습니다. 화면은 원문, 맥락, 리스크, 선택지를 분리해서 보여주고, 마지막에는 사람이 고를 수 있는 행동으로 좁혀야 합니다.",
"evidence.dikwTitle": "원문을 남깁니다",
"evidence.dikwBody": "요약만 있으면 확인할 수 없습니다. 메일 원문, 회의록 문장, 로그 위치, 첨부파일을 함께 둡니다.",
"evidence.wisdomTitle": "맥락을 붙입니다",
"evidence.wisdomBody": "누가, 언제, 어떤 고객과 프로젝트에서, 어떤 권한과 기준으로 남긴 기록인지 같이 보여줍니다.",
"evidence.situatedTitle": "리스크를 숨기지 않습니다",
"evidence.situatedBody": "빠진 첨부, 다른 로그, 일정 충돌, 권한 충돌처럼 결론을 바꿀 수 있는 조건을 따로 표시합니다.",
"evidence.synthesisTitle": "행동으로 끝냅니다",
"evidence.synthesisBody": "승인, 보류, 위임, 추가 확인 중 지금 가능한 선택을 보여주고 담당자, 기한, 남길 기록으로 이어갑니다.",
"references.title": "참고문헌",
"references.lead": "DIKW를 그대로 믿지 않고 제품 원칙으로 옮기기 위해 참고한 자료입니다.",
"references.ackoff": "Ackoff, R. L. (1989). From data to wisdom. Journal of Applied Systems Analysis, 16(1), 3-9.",
"references.baskarada": "Baskarada, S., & Koronios, A. (2013). Data, information, knowledge, wisdom (DIKW): A semiotic theoretical and empirical exploration of the hierarchy and its quality dimension. Australasian Journal of Information Systems, 18(1).",
"references.fricke": "Frické, M. (2009). The knowledge pyramid: A critique of the DIKW hierarchy. Journal of Information Science, 35(2), 131-142.",
"references.brienza": "Brienza, J. P., Kung, F. Y. H., Santos, H. C., Bobocel, D. R., & Grossmann, I. (2018). Wisdom, bias, and balance: Toward a process-sensitive measurement of wisdom-related cognition. Journal of Personality and Social Psychology, 115(6), 1093-1126.",
"logo.title": "로고는 흩어진 기록을 하나의 흐름으로 묶습니다",
"logo.lead": "사각형은 문서, 메일, 로그처럼 따로 남은 기록입니다. 선은 그 기록을 한 질문 아래 연결하는 흐름입니다. 끝점은 정답이 아니라 다음으로 확인하거나 선택할 지점입니다.",
"logo.layerTitle": "흩어진 기록",
"logo.layerBody": "각 블록은 서로 다른 저장소에 남은 단서를 뜻합니다.",
"logo.pathTitle": "연결선",
"logo.pathBody": "선은 기록 사이의 관계를 따라가며 같은 사건, 같은 고객, 같은 결정으로 묶는 흐름입니다.",
"logo.colorTitle": "끝점",
"logo.colorBody": "마지막 점은 결론을 장식하는 표시가 아니라 사람이 다음 행동을 고르는 자리입니다.",
"naruon.title": "Naruon은 메일에서 시작하는 제품 실험입니다",
"naruon.lead": "메일함은 메시지 목록이 아니라 요청, 첨부, 일정, 관계, 책임이 흐르는 곳입니다. Naruon은 그 흐름을 모아 오늘 판단할 일과 다음 행동을 보이게 하는 AI 워크스페이스입니다.",
"naruon.oneTitle": "흐름 수집",
"naruon.oneBody": "메일, 첨부, 일정, 작업을 한 흐름으로 모읍니다.",
"naruon.twoTitle": "맥락 종합",
"naruon.twoBody": "보낸 사람, 프로젝트, 관계, 타임라인, 근거를 연결합니다.",
"naruon.threeTitle": "판단과 실행",
"naruon.threeBody": "대기 작업, 일정 충돌, 답장, 위임, 확인 요청으로 이어갑니다.",
"projects.title": "공개 프로젝트",
"projects.lead": "Fork가 아니면서 공개된 제품과 도구 저장소입니다. 홈페이지, 조직 프로필처럼 운영과 소개를 위한 내부 관리용 저장소는 제외했습니다.",
"projects.naruonTitle": "Naruon",
"projects.naruonBody": "메일, 첨부, 일정, 작업을 맥락으로 묶어 판단과 실행으로 연결하는 AI 이메일 워크스페이스입니다.",
"projects.pgErdTitle": "pg-erd-cloud",
"projects.pgErdBody": "PostgreSQL 스키마를 리버스 엔지니어링하고 ERD와 DDL 공유 흐름으로 관리하는 클라우드 MVP입니다.",
"projects.bandscopeTitle": "BandScope",
"projects.bandscopeBody": "곡을 섹션, 역할, 템포, 연습 우선순위로 분석하는 로컬 우선 리허설 앱입니다.",
"projects.codecCarverTitle": "codec-carver",
"projects.codecCarverBody": "긴 녹음을 메타데이터를 보존한 FLAC/Opus 조각으로 변환하는 Python CLI입니다.",
"projects.newsdomTitle": "newsdom-api",
"projects.newsdomBody": "스캔된 일본어 신문 PDF를 기사, 제목, 본문, 이미지 구조의 DOM형 JSON으로 파싱하는 API입니다.",
"projects.scopeweaveTitle": "scopeweave",
"projects.scopeweaveBody": "트리 편집, 진행률 계산, CSV/JSON, 주간 Gantt를 지원하는 정적 HTML/CSS/JS WBS 플래너입니다.",
"projects.vibesecTitle": "VibeSec",
"projects.vibesecBody": "바이브코딩 앱을 위한 보안 가드레일입니다. AI 개발 도구 규칙, 정적 점검, 리뷰와 수정 프롬프트를 다룹니다.",
"forks.title": "Fork 프로젝트는 따로 봅니다",
"forks.lead": "맥락지혜 연구실이 직접 만든 프로젝트와 구분해, 외부 upstream에서 출발해 조직 안에서 검토하거나 확장하는 저장소입니다.",
"forks.argosTitle": "argos",
"forks.argosBody": "Fork of vibemafiaclub/argos. Claude Code·Codex 팀의 토큰, 스킬, 세션 사용 패턴을 분석하는 애널리틱스입니다.",
"forks.voosterTitle": "vooster",
"forks.voosterBody": "Fork of vibemafiaclub/vooster. 사람과 AI가 함께 제품 행동과 유스케이스를 관리하는 vspec 도구입니다.",
"forks.voosterMvpTitle": "vooster-v2-mvp",
"forks.voosterMvpBody": "Fork of vibemafiaclub/vooster-v2-mvp. goals, features, specs 구조로 제품 행동 명세를 다루는 TypeScript CLI MVP입니다.",
"work.title": "연구에서 제품으로",
"work.lead": "맥락지혜 연구실은 한 문장으로 답하는 AI보다, 판단 전까지 사람이 손으로 하던 정리 일을 줄이는 시스템을 봅니다.",
"work.oneTitle": "맥락 구조",
"work.oneBody": "관계, 출처, 기준, 리스크를 함께 보존하는 지식 구조.",
"work.twoTitle": "판단 화면",
"work.twoBody": "오늘 결정할 것과 확인할 가정을 드러내는 화면.",
"work.threeTitle": "운영 기반",
"work.threeBody": "인증, 권한, 보안, 감사, 사용량 책임이 작동하는 운영 기반.",
"work.fourTitle": "작업 흐름",
"work.fourBody": "반복 탐색은 줄이고 근거 확인과 사람의 판단은 남기는 흐름.",
"footer.founded": "Founded by",
"footer.line": "Context into judgment. Judgment into action."
},
en: {
metaTitle: "Contextual Wisdom Lab",
metaDescription: "A research lab building AI decision support systems that connect scattered enterprise material into judgment inside concrete contexts.",
logoSrc: "assets/context-wisdom-lab-logo-en.svg",
logoAlt: "Contextual Wisdom Lab",
"nav.intro": "Intro",
"nav.problem": "Problem",
"nav.model": "Research Model",
"nav.evidence": "Evidence",
"nav.contextualWisdom": "Name",
"nav.principles": "Principles",
"nav.dikw": "DIKW",
"nav.logo": "Logo",
"nav.naruon": "Naruon",
"nav.projects": "Projects",
"nav.forks": "Forks",
"nav.references": "References",
"nav.work": "Work",
"nav.skipToContent": "Skip to main content",
"hero.title": "Contextual Wisdom Lab",
"hero.labName": "Research Lab",
"hero.thesis": "A research lab building AI decision support systems. Even a heap of beads becomes treasure only when threaded; we compose context across documents, mail, logs, and meeting notes so people can see what to decide and what to do next.",
"hero.primaryCta": "Explore GitHub",
"hero.secondaryCta": "Read DIKW",
"ladder.data": "Recorded traces · documents · mail · logs",
"ladder.information": "Material interpreted inside a question",
"ladder.knowledge": "Structure explained by relations and constraints",
"ladder.wisdom": "Crossing into judgment and action",
"principles.title": "Contextual Wisdom means judgment inside context",
"principles.lead": "Contextual Wisdom means crossing from scattered material into judgment and action inside a concrete context. The lab connects context across mail, documents, logs, and schedules so people can see what to decide today and what to do next.",
"principles.oneTitle": "See the circumstances",
"principles.oneBody": "The same words and records can mean different things in different situations. We look at purpose, constraints, stakeholders, and time pressure together.",
"principles.purposeTitle": "Purpose",
"principles.purposeBody": "Why the record exists: handling a customer request, checking an incident cause, or coordinating a schedule.",
"principles.constraintTitle": "Constraints",
"principles.constraintBody": "Conditions that limit choices, such as permission, budget, deadline, and security.",
"principles.stakeholderTitle": "Stakeholders",
"principles.stakeholderBody": "The customer, owner, approver, or operator affected by the decision.",
"principles.twoTitle": "Synthesis is not summary",
"principles.twoBody": "We do not stop at shortening text. We connect evidence, context, risk, and options into a structure people can judge with.",
"principles.evidenceTitle": "Evidence",
"principles.evidenceBody": "Source material that supports judgment: the original email, meeting-note sentence, log line, attachment, or VOC item.",
"principles.contextTitle": "Context",
"principles.contextBody": "The surrounding information that explains who wrote it, when, why, and under which standard.",
"principles.riskTitle": "Risk",
"principles.riskBody": "Conditions that can make a decision wrong: missing information, counterevidence, permission conflict, or delay.",
"principles.optionTitle": "Options",
"principles.optionBody": "Actions that can actually be chosen now, such as approve, hold, verify more, delegate, or reschedule.",
"principles.threeTitle": "Cross into action",
"principles.threeBody": "A good structure does not end at reading. It should lead to decisions, assumptions to verify, next actions, delegation, and records.",
"principles.decisionTitle": "Decision",
"principles.decisionBody": "The item a person must choose now: approval, priority, scope, or response direction.",
"principles.assumptionTitle": "Assumption",
"principles.assumptionBody": "A premise that would change the conclusion if wrong, such as customer impact, incident cause, or cost estimate.",
"principles.actionTitle": "Next action",
"principles.actionBody": "An executable unit with owner, deadline, expected output, and record to leave behind.",
"problem.title": "The starting point is cognitive load",
"problem.lead": "The hard part is not the lack of information. It is that the context needed for judgment is scattered. People become overloaded when they must rebuild context by hand.",
"problem.oneTitle": "Scattered material",
"problem.oneBody": "A request stays in email, evidence in an attachment, a decision in meeting notes, and a deadline in the calendar. They need to be seen together.",
"problem.twoTitle": "Fading criteria",
"problem.twoBody": "The reason for approval, the condition for holding, the constraint at the time, and the missing counterexample fade away.",
"problem.threeTitle": "Needed structure",
"problem.threeBody": "People need one flow that shows what to decide, what to verify, who owns it, when it is due, and what record remains.",
"dikw.title": "DIKW is not a hierarchy; it is a set of questions",
"dikw.lead": "The original frame offers useful distinctions, but later work warns about definitional confusion and linear conversion claims. We do not treat the pyramid as a factual model; we use it to ask whether material is ready to support judgment inside context.",
"dikw.dataTitle": "What was recorded?",
"dikw.dataBody": "Email requests, meeting-note sentences, log errors, VOC items, and schedule changes are records before they are connected.",
"dikw.infoTitle": "Which question does it answer?",
"dikw.infoBody": "Add author, timing, project, customer, permission, and decision criteria so the record has meaning.",
"dikw.knowledgeTitle": "What does it explain?",
"dikw.knowledgeBody": "Group repeated patterns, exceptions, possible causes, constraints, and owner procedures to reveal what needs judgment.",
"dikw.wisdomTitle": "What should be done in this context?",
"dikw.wisdomBody": "Compare practical choices such as approve, hold, delegate, or verify more, then connect the choice to an owner and deadline.",
"evidence.title": "So the interface should ask these questions",
"evidence.lead": "Collecting records is not enough. The interface should separate source, context, risk, and options, then narrow the work into actions a person can actually choose.",
"evidence.dikwTitle": "Keep the source",
"evidence.dikwBody": "A summary alone cannot be checked. Keep the original email, meeting-note sentence, log location, and attachment nearby.",
"evidence.wisdomTitle": "Attach context",
"evidence.wisdomBody": "Show who left the record, when, for which customer and project, and under which permission or criterion.",
"evidence.situatedTitle": "Expose risk",
"evidence.situatedBody": "Mark missing attachments, conflicting logs, schedule conflicts, and permission conflicts that could change the conclusion.",
"evidence.synthesisTitle": "End with action",
"evidence.synthesisBody": "Show the current choices, such as approve, hold, delegate, or verify more, then connect them to an owner, deadline, and record.",
"references.title": "References",
"references.lead": "Sources used to turn DIKW into product principles rather than a literal hierarchy.",
"references.ackoff": "Ackoff, R. L. (1989). From data to wisdom. Journal of Applied Systems Analysis, 16(1), 3-9.",
"references.baskarada": "Baskarada, S., & Koronios, A. (2013). Data, information, knowledge, wisdom (DIKW): A semiotic theoretical and empirical exploration of the hierarchy and its quality dimension. Australasian Journal of Information Systems, 18(1).",
"references.fricke": "Frické, M. (2009). The knowledge pyramid: A critique of the DIKW hierarchy. Journal of Information Science, 35(2), 131-142.",
"references.brienza": "Brienza, J. P., Kung, F. Y. H., Santos, H. C., Bobocel, D. R., & Grossmann, I. (2018). Wisdom, bias, and balance: Toward a process-sensitive measurement of wisdom-related cognition. Journal of Personality and Social Psychology, 115(6), 1093-1126.",
"logo.title": "The logo connects scattered records into one flow",
"logo.lead": "The blocks are records left in different places: documents, mail, and logs. The line is the flow that connects them under one question. The endpoint is not an answer; it is the next point to verify or choose.",
"logo.layerTitle": "Scattered records",
"logo.layerBody": "Each block stands for a clue left in a different system.",
"logo.pathTitle": "Connection line",
"logo.pathBody": "The line follows relationships across the same event, customer, or decision.",
"logo.colorTitle": "Endpoint",
"logo.colorBody": "The last point marks where a person chooses the next action.",
"naruon.title": "Naruon is the product experiment that starts in email",
"naruon.lead": "An inbox is not just a message list. It carries requests, attachments, schedules, relationships, and responsibility. Naruon collects that flow so people can see what to decide today and what to do next.",
"naruon.oneTitle": "Collect the flow",
"naruon.oneBody": "Bring mail, attachments, schedules, and tasks into one stream.",
"naruon.twoTitle": "Compose context",
"naruon.twoBody": "Connect sender, project, relationship, timeline, and evidence.",
"naruon.threeTitle": "Move to action",
"naruon.threeBody": "Surface pending work, schedule conflicts, replies, delegation, and verification requests.",
"projects.title": "Public projects",
"projects.lead": "These are public product and tool repositories that are not forks. Internal management repositories for the homepage and organization profile are excluded.",
"projects.naruonTitle": "Naruon",
"projects.naruonBody": "An AI email workspace that connects mail, attachments, schedules, and tasks into context for judgment and action.",
"projects.pgErdTitle": "pg-erd-cloud",
"projects.pgErdBody": "A cloud MVP for reverse-engineering PostgreSQL schemas and managing ERD and DDL sharing workflows.",
"projects.bandscopeTitle": "BandScope",
"projects.bandscopeBody": "A local-first rehearsal app that analyzes songs by section, role, tempo, and practice priority.",
"projects.codecCarverTitle": "codec-carver",
"projects.codecCarverBody": "A Python CLI that turns long recordings into metadata-preserving FLAC and Opus segments.",
"projects.newsdomTitle": "newsdom-api",
"projects.newsdomBody": "An API that parses scanned Japanese newspaper PDFs into article, title, body, and image JSON structures.",
"projects.scopeweaveTitle": "scopeweave",
"projects.scopeweaveBody": "A static HTML/CSS/JS WBS planner with tree editing, progress calculation, CSV/JSON, and weekly Gantt support.",
"projects.vibesecTitle": "VibeSec",
"projects.vibesecBody": "Security guardrails for vibe-coded apps, covering AI tool rules, static checks, and review and remediation prompts.",
"forks.title": "Forked projects are shown separately",
"forks.lead": "These repositories started from external upstream projects and are reviewed or extended inside the organization, separate from projects originated by the lab.",
"forks.argosTitle": "argos",
"forks.argosBody": "Fork of vibemafiaclub/argos. Analytics for Claude Code and Codex team token, skill, and session usage patterns.",
"forks.voosterTitle": "vooster",
"forks.voosterBody": "Fork of vibemafiaclub/vooster. A vspec tool for managing product behavior and use cases with human and AI contributors.",
"forks.voosterMvpTitle": "vooster-v2-mvp",
"forks.voosterMvpBody": "Fork of vibemafiaclub/vooster-v2-mvp. A TypeScript CLI MVP for product behavior specs organized by goals, features, and specs.",
"work.title": "From research to product",
"work.lead": "Contextual Wisdom Lab focuses less on one-shot answers and more on systems that reduce the manual work people do before they can judge.",
"work.oneTitle": "Context systems",
"work.oneBody": "Knowledge structures that preserve relationships, sources, criteria, and risk.",
"work.twoTitle": "Decision interfaces",
"work.twoBody": "Interfaces that reveal what to decide today and which assumptions need verification.",
"work.threeTitle": "Enterprise AI rails",
"work.threeBody": "Operational foundations for identity, authorization, security, audit, and usage accountability.",
"work.fourTitle": "Agentic workflows",
"work.fourBody": "Workflows that reduce repeated search while preserving evidence checks and human judgment.",
"footer.founded": "Founded by",
"footer.line": "Context into judgment. Judgment into action."
}
};
function preferredLanguage() {
const allowed = ["ko", "en"];
const query = new URLSearchParams(window.location.search).get("lang");
if (allowed.includes(query)) return query;
try {
const saved = localStorage.getItem("cwl-language");
if (allowed.includes(saved)) return saved;
} catch (error) {
// Fail securely: ignore localStorage errors in strict privacy modes
}
return navigator.language?.toLowerCase().startsWith("ko") ? "ko" : "en";
}
// ⚡ Bolt: Cache DOM queries and current state to prevent redundant lookups and layout thrashing
let i18nNodes = null;
let langButtons = null;
let metaDesc = null;
let ogDesc = null;
let footerLogo = null;
let currentLang = null;
function setLanguage(lang) {
if (currentLang === lang) return; // Skip if already in the requested language
const dict = messages[lang] || messages.ko;
if (!langButtons) {
langButtons = document.querySelectorAll("[data-lang]");
metaDesc = document.querySelector('meta[name="description"]');
ogDesc = document.querySelector('meta[property="og:description"]');
footerLogo = document.querySelector("#footer-logo");
}
if (document.documentElement.lang !== lang) {
document.documentElement.lang = lang;
}
if (document.title !== dict.metaTitle) {
document.title = dict.metaTitle;
}
if (metaDesc && metaDesc.getAttribute("content") !== dict.metaDescription) {
metaDesc.setAttribute("content", dict.metaDescription);
}
if (ogDesc && ogDesc.getAttribute("content") !== dict.metaDescription) {
ogDesc.setAttribute("content", dict.metaDescription);
}
if (footerLogo) {
if (footerLogo.getAttribute("src") !== dict.logoSrc) {
footerLogo.setAttribute("src", dict.logoSrc);
}
if (footerLogo.getAttribute("alt") !== dict.logoAlt) {
footerLogo.setAttribute("alt", dict.logoAlt);
}
}
// ⚡ Bolt: 기본 언어로 초기 로드 시 불필요한 DOM 텍스트 읽기 및 탐색 생략 (성능 개선)
const isInitialDefault = lang === "ko" && !i18nNodes;
if (!isInitialDefault) {
if (!i18nNodes) {
i18nNodes = document.querySelectorAll("[data-i18n]");
}
// Only update textContent if it actually changed to avoid layout recalculations
i18nNodes.forEach((node) => {
const newText = dict[node.dataset.i18n];
if (newText && node.textContent !== newText) {
node.textContent = newText;
}
});
}
langButtons.forEach((button) => {
const pressed = String(button.dataset.lang === lang);
if (button.getAttribute("aria-pressed") !== pressed) {
button.setAttribute("aria-pressed", pressed);
}
});
try {
localStorage.setItem("cwl-language", lang);
} catch (error) {
// Fail securely: ignore localStorage errors
}
currentLang = lang;
}
// Event listeners can just use the initial querySelectorAll
document.querySelectorAll("[data-lang]").forEach((button) => {
button.addEventListener("click", () => setLanguage(button.dataset.lang));
});
setLanguage(preferredLanguage());