feat(i18n): Korean/English support for the browser demo - #32
Merged
Conversation
- docs/i18n.js: dictionary-based i18n (t(), data-i18n, KO/EN toggle, localStorage persistence, browser-language default) - docs/index.html: data-i18n keys on all static text, lang toggle button - docs/game.js: dynamic messages via t(); win/lose overlay now keyed on winner index instead of Korean message substring
There was a problem hiding this comment.
Pull request overview
Adds lightweight KO/EN internationalization support for the browser demo by introducing a tiny dictionary-based i18n module, wiring static DOM strings via data-i18n, and switching dynamic game messages to t() lookups (including making the game-over overlay decision language-independent via winner).
Changes:
- Add
docs/i18n.jswith KO/EN dictionary,t()helper, language detection + toggle with persistence, and advc:langchangeevent. - Update
docs/index.htmlto tag static strings withdata-i18n, add a language toggle button, and loadi18n.js. - Update
docs/game.jsto use translated strings for dynamic messages and to usewinnerinstead of substring checks for win/lose UI.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| docs/index.html | Adds language toggle UI, tags static text with data-i18n, and loads i18n.js before game.js. |
| docs/i18n.js | Implements the KO/EN dictionary, translation function, language persistence, and DOM application logic. |
| docs/game.js | Replaces hard-coded messages with t() calls and switches game-over logic to winner-index based checks. |
Suppressed comments (1)
docs/game.js:1084
showDisconnectOverlay()already falls back tot('oppLeftMsg')for the overlay message, but it still callsshowMessage(message)with the raw (possibly missing) message from the event payload, which can display "undefined" in the main message area.
function showDisconnectOverlay(message) {
if (eventSource) { eventSource = null; }
elements.gameOverOverlay?.classList.remove('hidden');
elements.gameOverTitle.textContent = t('oppLeftTitle');
elements.gameOverTitle.style.color = '#ffc107';
elements.gameOverMessage.textContent = message || t('oppLeftMsg');
showMessage(message);
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+103
to
+107
| function detectLang() { | ||
| const saved = localStorage.getItem(STORAGE_KEY); | ||
| if (saved === 'ko' || saved === 'en') return saved; | ||
| return (navigator.language || '').toLowerCase().startsWith('ko') ? 'ko' : 'en'; | ||
| } |
Comment on lines
+132
to
+136
| function setLang(next) { | ||
| lang = next; | ||
| localStorage.setItem(STORAGE_KEY, lang); | ||
| applyI18n(); | ||
| window.dispatchEvent(new CustomEvent('dvc:langchange', { detail: { lang } })); |
Comment on lines
65
to
+66
| const DV = window.DVEngine; | ||
| const t = window.I18N.t; |
Comment on lines
1050
to
1075
| function showGameOver() { | ||
| elements.gameOverOverlay?.classList.remove('hidden'); | ||
| if (gameState.message?.includes('승리')) { | ||
| elements.gameOverTitle.textContent = '🎉 승리!'; | ||
| // winner is the player_index (0 = human) — language-independent, unlike | ||
| // the old message-substring check which broke under i18n. | ||
| if (gameState.winner === 0) { | ||
| elements.gameOverTitle.textContent = t('victory'); | ||
| elements.gameOverTitle.style.color = '#4ecca3'; | ||
| } else { | ||
| elements.gameOverTitle.textContent = '💀 패배'; | ||
| elements.gameOverTitle.textContent = t('defeat'); | ||
| elements.gameOverTitle.style.color = '#e94560'; | ||
| } | ||
| elements.gameOverMessage.textContent = gameState.message || '게임 종료'; | ||
| elements.gameOverMessage.textContent = gameState.message || t('gameOverTitle'); | ||
| } | ||
|
|
||
| function showGameOverWithData(data) { | ||
| elements.gameOverOverlay?.classList.remove('hidden'); | ||
| if (data.message?.includes('승리')) { | ||
| elements.gameOverTitle.textContent = '🎉 승리!'; | ||
| if (data.winner === 0) { | ||
| elements.gameOverTitle.textContent = t('victory'); | ||
| elements.gameOverTitle.style.color = '#4ecca3'; | ||
| } else { | ||
| elements.gameOverTitle.textContent = '💀 패배'; | ||
| elements.gameOverTitle.textContent = t('defeat'); | ||
| elements.gameOverTitle.style.color = '#e94560'; | ||
| } | ||
| elements.gameOverMessage.textContent = data.message || '게임 종료'; | ||
| elements.gameOverMessage.textContent = data.message || t('gameOverTitle'); | ||
| showMessage(data.message); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
데모 페이지 한국어/영어 지원.
docs/i18n.js신규 — 언어 사전 +t()+ KO/EN 토글(우상단 버튼, localStorage 저장, 브라우저 언어 자동 감지)docs/index.html— 정적 문구에data-i18n키 부착docs/game.js— 동적 메시지를t()호출로 교체. 승패 오버레이 판정을 메시지 문자열(승리포함 여부) 대신winner인덱스로 변경 (i18n에서 깨지는 버그 예방)문구 추가·수정은
docs/i18n.js사전만 편집하면 됩니다.