PageSourceSearch

https://claudetuner.com/dashboard/dashboard-i18n.js?v=20260930.1

js claudetuner.com collected 2026-10-01 14:02:57 UTC 63,518 bytes, 682 lines download raw bytes

1// dashboard-i18n.js — personal dashboard module (extracted from index.html inline script)
2// Classic global script. Load order matters; keep the <script src> sequence in index.html intact.
3// Section: i18n (T table, lang, escHtml, t/setLang/applyI18n)
4
5// === i18n ===
6var T = {
7  ko: {
8    nav_home: 'Home', nav_my_dash: '내 대시보드', nav_team: '팀', nav_insights: '인사이트', nav_feedback: '문의하기', btn_logout: '로그아웃',
9    login_title: 'Dashboard', login_desc: '로그인하여 사용량 데이터를 확인하세요.', login_demo_link: '또는 샘플 데이터로 데모 보기 →',
10    login_or: '또는', claude_login_toggle: '다른 방법으로 로그인', claude_login_btn: 'ClaudeTuner 확장으로 로그인', claude_login_hint: 'ClaudeTuner 확장 필요 (v1.12.8 이상)',
11    claude_login_loading: '로그인 중...', claude_login_not_logged_in: 'Claude.ai에 먼저 로그인해주세요', claude_login_no_data: '아직 수집된 데이터가 없습니다. 확장 설치 후 잠시 기다려주세요.', claude_login_failed: '로그인에 실패했습니다. 다시 시도해주세요.', claude_login_email_required: '이메일로 로그인해 주세요.', claude_login_not_installed: 'ClaudeTuner 확장이 설치되어 있지 않거나 비활성화되어 있습니다. 설치 후 다시 시도하거나 이메일로 로그인하세요.', claude_login_install: '설치하기',
12    email_login_toggle: '이메일로 로그인', email_login_send: '인증 코드 전송', email_verify_btn: '인증',
13    email_auth_invalid: '유효한 이메일 주소를 입력해주세요.', email_auth_rate_limit: '요청이 너무 많습니다. 잠시 후 다시 시도해주세요.', email_auth_send_error: '코드 전송에 실패했습니다.', email_auth_network_error: '서버에 연결하지 못했습니다. 네트워크(사내 방화벽/프록시) 연결을 확인 후 다시 시도해주세요.', email_verify_sent: '{email}로 코드를 전송했습니다.', email_verify_invalid: '6자리 코드를 입력해주세요.', email_verify_wrong: '잘못되었거나 만료된 코드입니다.', email_login_signing_in: '로그인 중…', email_login_link_expired: '로그인 링크가 만료되었습니다. 아래에서 새 코드를 요청해주세요.',
14    loading: '데이터를 불러오는 중...', loading_fail: '데이터 로딩 실패. 잠시 후 다시 시도해주세요.',
15    empty_title: '아직 수집된 데이터가 없습니다',
16    empty_desc: 'Chrome 확장 프로그램을 설치하고 Claude.ai에 로그인하면<br>사용량 데이터가 자동으로 수집됩니다.',
17    empty_link: 'Chrome Web Store에서 설치 →',
18    status_danger: '한도 임박', status_warn: '주의', status_ok: '여유',
19    rec_no_data: '데이터가 부족합니다.',
20    rec_data_growing: '데이터 수집 중입니다. 정확한 추천을 위해 3일 이상의 데이터가 필요합니다.',
21    rec_upgrade_max5x: 'Max 5x 업그레이드를 권장합니다. 사용 한도가 5배로 늘어납니다.',
22    rec_upgrade_max20x: 'Max 20x 업그레이드를 검토해보세요.',
23    rec_upgrade_general: '상위 플랜을 검토해보세요.',
24    rec_high_max20x: '최근 사용량이 높은 편입니다. 리셋 주기에 유의하세요.',
25    rec_high_max20x_critical: '사용량이 계속 높습니다. 최상위 플랜이므로 토큰 사용을 줄여 한도 내에서 유지하세요.',
26    rec_adequate: '사용량 중간 수준 — 추이를 주시하세요.',
27    rec_optimize_schedule: '업무 시간에 사용이 집중되고 있습니다. 야간/새벽에 작업을 분산하면 현재 플랜으로 충분할 수 있습니다.',
28    rec_upgrade_pro: 'Pro로 업그레이드를 권장합니다. 사용 한도에 자주 도달하고 있습니다.',
29    rec_downgrade_max5x: '사용량 대비 플랜이 높습니다. Max 5x로 다운그레이드를 고려해보세요.',
30    rec_downgrade_pro: '사용량 대비 플랜이 높습니다. Pro로 다운그레이드를 고려해보세요.',
31    rec_good: '현재 플랜이 적합합니다.',
32    rec_enterprise: '사용량 제한 없음',
33    rec_team_upgrade_premium: '한도 임박 — Premium 시트 검토',
34    rec_team_near_limit: '한도 임박 — 관리자 문의',
35    rec_team_downgrade_standard: 'Standard 시트 전환 가능',
36    rec_team_good: '현재 시트 적합',
37    // ChatGPT plan recommendation (v1, single-axis 14d windowed max 7d utilization).
38    // See docs/SPEC-chatgpt-plan-rec.md. insufficient_data renders 
38NO card, so
39    // rec_cg_insufficient_data is only a defensive fallback (team grid CSV).
40    rec_cg_insufficient_data: '데이터가 부족합니다.',
41    rec_cg_adequate: '현재 플랜이 사용량에 적합합니다.',
42    rec_cg_at_ceiling: '최근 사용량이 플랜 한도에 도달했습니다. 안내할 상위 플랜이 없어 사용 시점을 분산하는 편이 좋습니다.',
43    rec_cg_at_ceiling_seat: '최근 사용량이 시트 한도에 도달했습니다. 시트·플랜 변경은 워크스페이스 관리자에게 문의하세요.',
44    rec_cg_upgrade_go: 'Go 플랜 업그레이드를 검토해보세요. 한도에 자주 도달하고 있습니다.',
45    rec_cg_upgrade_plus: 'Plus 업그레이드를 권장합니다. 한도에 자주 도달하고 있습니다.',
46    rec_cg_upgrade_pro5x: 'Pro 100 업그레이드를 권장합니다. 주간 한도가 크게 늘어납니다.',
47    rec_cg_upgrade_pro20x: 'Pro 200 업그레이드를 검토해보세요.',
48    rec_cg_downgrade_free: '사용량이 적습니다. Free로 다운그레이드를 고려해보세요.',
49    rec_cg_downgrade_go: '사용량 대비 플랜이 높습니다. Go로 다운그레이드를 고려해보세요.',
50    rec_cg_downgrade_plus: '사용량 대비 플랜이 높습니다. Plus로 다운그레이드를 고려해보세요.',
51    rec_cg_downgrade_pro5x: '사용량 대비 플랜이 높습니다. Pro 100으로 다운그레이드를 고려해보세요.',
52    rec_cg_at_limit_headline: '플랜 한도 도달',
53    rec_cg_low_confidence: '이 플랜은 미보고 구간이 넓어 추정 신뢰도가 낮습니다.',
54    rec_cg_window_note: '최근 {0}일 최대 사용률 기준',
55    rec_cg_title: '플랜 추천',
56    rec_cg_change_plan: 'ChatGPT에서 플랜 변경 →',
57    rec_peak_recent: '최근 피크',
58    rec_avg_peak: '평균 피크',
59    rec_savings: '월 절약',
60    rec_month: '월',
61    rec_data_days: '수집 데이터:',
62    rec_days_unit: '일',
63    countdown_reset: '리셋됨', countdown_until: '리셋까지 ',
64    renewal_expired: '만료', renewal_days_left: '{0}일 남음',
65    pending_cancel_label: '해지', pending_cancel_scheduled: '해지 예정',
66    label_7d_util: '7일 사용률', label_5h_util: '5시간 사용률',
67    // ChatGPT only (#1209). Rendered into a title= attribute, so keep it free of double quotes.
68    gauge_note_chatgpt: '이 값에는 Codex 등 텍스트 채팅 외 사용이 포함됩니다. 텍스트 채팅은 2026년 8월부터 한도가 없어 이 수치에 잡히지 않습니다.',
69    no_7d_for_plan: '{0} 플랜은 7일 한도가 없습니다',
70    // 🔴 Used when the plan is UNKNOWN — never name a tier we did not read (#1434). Saying
71    // "Free 플랜은…" for a workspace whose plan was never observed asserts two things we do
72    // not know: the tier, and that the absence is a plan property rather than a read failure.
73    no_7d_unknown_plan: '이 워크스페이스의 플랜을 읽지 못해 7일 한도를 확인할 수 없습니다',
74    // 🔴 WORD-FOR-WORD the extension popup's usage_withheld / usage_withheld_plan
75    // (claude-tuner-extension/i18n.js). The popup and this page describe the SAME provider
76    // response; saying it in two different sentences is exactly what #1405 keeps catching. If one
77    // is reworded, reword both — test/dash-usage-withheld-guard.mjs compares the two files.
78    usage_withheld: 'Claude가 이 계정의 사용률을 제공하지 않습니다',
79    usage_withheld_plan: 'Claude가 {0} 플랜에 사용률을 제공하지 않습니다',
80    usage_withheld_free_tip: '2026년 8월 22일부터 Claude가 무료 플랜 계정에 사용량 수치를 제공하지 않습니다. Claude 설정 화면에서도 표시되지 않으며, 사용 한도는 그대로 적용됩니다. Claude가 다시 제공하면 자동으로 표시됩니다.',
81    acct_plan_unknown: '알 수 없음',
82    label_14d_avg: '7일 사용률 일평균 증가 (14일)', label_status: '상태',
83    label_7d_tokens: '7d 사용량', label_5h_tokens: '5h 사용량',
84    label_renewal: '구독 갱신일', label_pending: '변경 예정',
85    per_day: '%/일',
86    limit_alert_soon: '현재 속도로 약 {0} 후 한도 도달', limit_alert_safe: '현재 속도라면 한도ê¹
86Œì§€ 여유 있음', limit_alert_no_data: '현재 사용량이 적어 예측 불가', limit_alert_reached: '현재 7d 한도에 도달한 상태입니다',
87    summary_peak_5h: '오늘 5h 피크', summary_busiest: '가장 많이 쓴 시간', summary_limit_hits: '한도 근접 (≥80%)', summary_times: '회', summary_hours: '시간', summary_days: '일',
88    rec_title: '플랜 추천', rec_14d_avg: '14일 평균 일별 사용량',
89    tab_util: '사용률 추이 (3일)', tab_token: '추정 토큰 (3일)', tab_peak: '추정 토큰 (14일)', tab_activity: '시간대별 활동',
90    comp_title: '추정 방식 비교', comp_date: '날짜 (UTC)', comp_hourly: 'Hourly 합산', comp_daily: 'Daily (7d)', comp_server: '서버 피크', comp_method: '방식', comp_confidence: '신뢰도',
91    activity_title: '시간대별 활동', activity_sub: '5h/7d 윈도우 변화량 기반 추정 토큰', activity_disclaimer: '추정치이며 실제와 다를 수 있음', activity_today: '오늘', activity_this_week: '최근 1주', activity_daily: '일별', activity_weekly: '주별', activity_loading: '불러오는 중...', activity_no_data: '해당 기간에 수집된 데이터가 없습니다.', activity_tokens: '추정 토큰', heatmap_heavy: '많이 씀', heatmap_medium: '보통', heatmap_light: '적게 씀', heatmap_none: '안 씀', heatmap_nodata: '데이터 없음',
92    grove_title: '1년 사용량 잔디', grove_sub: 'GitHub 잔디처럼 매일의 추정 토큰 사용량을 한눈에', grove_loading: '불러오는 중...', grove_no_data: '아직 표시할 사용 기록이 없습니다.', grove_less: '적음', grove_more: '많음', grove_none: '사용 없음', grove_total: '최근 1년', grove_active_days: '일 사용',
93    // 이전 계정 구간(#1106). 「~하면 원래대로」류 안내를 넣지 말 것 — 사유는 site/shared/ext-detect.js
94    // CT_CLAIM_TEXT 위 주석. 문구는 결과를 먼저 말하고, 「전부/모든 기록」이라고 말하지 않는다.
95    grove_linked_legend: '이전 계정 기록', grove_linked_tip: '이전 계정 {0}',
96    grove_linked_seg: '{0} ~ {1} · 이전 계정 {2}',
97    grove_linked_stats: '{0} · {1}일',
98    grove_linked_hidden: '겹치는 {0}일은 이 계정 기록으로 표시됩니다',
99    grove_linked_all_hidden: '이 구간의 {0}일은 이 계정에도 기록이 있어, 잔디에 새로 채워진 날은 없습니다.',
100    grove_linked_empty: '이 기간에 남아 있는 일별 기록이 없습니다.',
101    grove_linked_unavailable: '이 구간을 불러오지 못했습니다. 기록이 없다는 뜻이 아니라 이번에 못 읽었다는 뜻입니다 — 새로고침해 주세요.',
102    grove_linked_org_note: 'org를 골라도 이전 계정 구간은 그대로 표시됩니다 — 이 구간은 org와 무관합니다.',
103    grove_linked_summary_note: '위 합계는 이 계정 기록만 셉니다. 이전 계정 구간은 아래에 따로 적었습니다.',
104    scale_raw: '수집', scale_hourly: '시간', scale_daily: '일', yaxis_fixed: 'Y축 100%', yaxis_auto: 'Y축 자동',
105    chart_5h_util: '5시간 사용률 추이', chart_7d_util: '7일 사용률 추이',
106    // Window captions derived from the span the provider reported, for plans whose window is
107    // not the slot's nominal length (ChatGPT Free/Go report 30 days in the 7d slot). The static
108    // chart_5h_util / chart_7d_util above stay as the fallback when no span was reported. #954
109    chart_window_util: '{0} 사용률 추이',
110    chart_window_util_sub: '{0} 윈도우 사용률(%) · 플랜별 한도 표시',
111    window_hours: '{0}시간', window_days: '{0}일',
112    chart_5h_util_sub: '5시간 윈도우 사용률(%) · 플랜별 한도 표시',
113    chart_7d_util_sub: '7일 윈도우 사용률(%) · 플랜별 한도 표시',
114    chart_spending: '추가 사용량 추이', chart_spending_sub: '월별 사용 금액($) · 한도 및 예산 페이스 표시',
115    chart_5h_token: '5h 추정 토큰 사용량', chart_7d_token: '7d 추정 토큰 사용량',
116    chart_token_sub: '사용률 기반 토큰 추정 · 플랜별 한도 표시',
117    chart_token_disclaimer: '* 커뮤니티 관측치 기반 추정 — Anthropic 미공개 수치',
118    chart_5h_peak: '5h 추정 토큰 (14일)', chart_7d_peak: '7d 추정 토큰 (14일)',
119    chart_peak_5h_sub: '5시간 윈도우별 추정 최대 토큰 · 플랜별 한도 표시',
120    chart_peak_7d_sub: '7일 윈도우별 추정 최대 토큰 · 플랜별 한도 표시',
121    sec_kpi: '현재 상태', sec_plan_compare: '플랜 비교',
122    ce_title: '비용 효율성', ce_tpd: 'tokens/$', ce_rank_label: '전체 순위', ce_top_pct: '상위 {0}%', ce_users: '명 중',
123    ce_desc: '월 구독료 $1당 실제 사용한 추정 토큰입니다. 수치가 낮다면 플랜 대비 사용량이 적다는 뜻으로, 더 저렴한 플랜으로 전환하거나 현재 플랜을 더 적극적으로 활용하는 것을 고려해 보세요.',
124    ce_avg: '평균', ce_top10: '상위 10%', ce_org: '우리 조직', ce_me: '나',
125    ce_vs_top10: '상위 10% 대비 {0}% 수준', ce_vs_org: '조직 평균보다 {0}% {1}',
126    ce_higher: '높습니다', ce_lower: '낮습니다',
127    account_title: '계정 정보',
128    ds_5h_window: '5시간 윈도우', ds_7d_window: '7일 윈도우', ds_budget: '균등 소비 기준',
129    ds_budget_pace: '예산 페이스', ds_spending: '사용 금액', ds_cap: '사용 한도',
130    ds_omelette_7d: 'Design 7일', ds_sonnet_7d: 'Sonnet 7일',
131    // Neutral label for the scoped weekly slot when the model name can't be stated for THIS
132    // account (different accounts carry different scoped models). See _scopedSlotLabel().
133    // Appended to the green series' name only when both scoped series resolved to the SAME
134    // string — ECharts merges same-named series into one legend item. See _scopedSlotNames().
135    sfx_green: '(녹색)',
136    // {0} = the model actually in that scoped slot, resolved exactly like the chart legend
137    // (_scopedSlotNames). Never hardcode a model name here — the slot's model rotates.
138    plus_scoped: ' + {0}(주황)', plus_scoped2: ' + {0}(녹색)',
139    // Per-feature limit card (#1150). Deliberately NOT next to the plan gauges' copy: this bucket
140    // has its own quota and its own clock, and the note is what stops a reader from comparing it
141    // to the plan windows above. The model name is supplied by the row, never hardcoded.
142    fl_window_weekly: '주간',
143    fl_note: '플랜 한도와 별개로 계산되는 기능별 한도입니다',
144    fl_reset: '{0} 초기화',
145    axis_5h_util: '5h 사용률 (%)', axis_7d_util: '7d 사용률 (%)',
146    axis_5h_token: '5h 추정 토큰', axis_7d_token: '7d 추정 토큰',
147    axis_5h_peak: '5h 추정 토큰 Peak', axis_7d_peak: '7d 추정 토큰 Peak',
148    ann_limit: '한도', ann_pro_limit: '한도', ann_max5x_limit: '한도',
149    pro_equiv: 'Pro 대비 ',
150    acct_email: '이메일', acct_plan: '플랜', acct_renewal: '갱신일',
151    acct_first_seen: '최초 수집', acct_last_seen: '최근 수집', acct_snapshots: '스냅샷',
152    acct_pending_change: '변경 예정', acct_recent: '개 (최근)',
153    grove_warning: '⚠ 학습 데이터 제공이 켜져 있습니다', grove_turn_off: '설정에서 끄기 →',
154    ds_5h_peak: '5h Peak', ds_7d_peak: '7d Peak',
155    ds_omelette_peak: 'Design Peak', ds_sonnet_peak: 'Sonnet Peak',
156    ds_5h_token: '5h 추정 토큰', ds_7d_token: '7d 추정 토큰',
157    caution_80: '주의 (80%)',
158    rec_action_upgrade: '업그레이드 권장',
159    rec_action_downgrade: '다운그레이드 가능',
160    rec_action_good: '현재 플랜 적합',
161    rec_method: '최근 14일 사용량 패턴(5시간·7일 사용률)을 분석한 결과입니다.',
162    rec_mode_current_label: '추천 성향',
163    rec_mode_v_cost: '비용 절감', rec_mode_v_balanced: '균형', rec_mode_v_convenience: '생산성 우선',
164    rec_mode_change: '설정에서 변경 →',
165    rec_action_high: '사용량 주의',
166    rec_action_collecting: '데이터 수집 중',
167    rec_btn_upgrade: '{0}(으)로 업그레이드',
168    rec_btn_downgrade: '{0}(으)로 다운그레이드',
169    rec_btn_dismiss: '지금은 괜찮아요',
170    rec_cost_up: '월 ${0} → ${1} (+${2})',
171    rec_cost_down: '월 ${0} → ${1} (${2} 절약)',
172    rec_reason_7d_high: '7일 사용률 평균 {0}% — 한도 초과 위험',
173    rec_reason_5h_limit: '5시간 한도 빈번 도달 ({0}%)',
174    rec_reason_7d_low: '7일 사용률 최대 {0}% — 과잉 지출',
175    rec_reason_urgent: '긴급 — 한도 초과 임박',
176    rec_reason_moderate: '평균 피크 {0}% — 업그레이드 검토',
177    rec_collecting_progress: '데이터 수집 중 ({0}/{1}일)',
178    view_as_banner: '{0} (으)로 조회 중',
179    view_as_back: '내 대시보드로 돌아가기',
180    fm_title: '플랜 적합도',
181    fm_col_plan: '플랜',
182    fm_col_cost: '비용',
183    fm_window_5h: '최근 5시간',
184    fm_window_24h: '최근 24시간',
185    fm_window_7d: '최근 7일',
186    fm_window_14d: '최근 14일',
187    fm_savings: '{0} 전환 시 월 ${1} 절약',
188    fm_upgrade_to: '{0}(으)로 업그레이드가 필요합니다',
189    fm_overspend_note: '현재 {0} 대비 용량을 대부분 사용하지 않고 있음',
190    fm_all_fit: '모든 기간에서 {0}으로 충분',
191    fm_bottleneck_5h: '단기간 집중 사용이 많음. 사용 패턴을 분산하면 하위 플랜으로 충분',
192    fm_bottleneck_7d: '전반적으로 사용량이 많음. 상위 플랜 필요',
193    fm_tip_exceeded: '5h {0}% / 7d {1}% — 한도(100%)를 넘어 사용이 어렵습니다',
194    fm_tip_tight: '5h {0}% / 7d {1}% — 한도까지 {2}% 여유로 빠듯합니다',
195    fm_tip_fit: '5h {0}% / 7d {1}% — 충분한 여유가 있습니다',
196    fm_tip_overspend: '5h {0}% / 7d {1}% — 용량의 대부분을 쓰지 않습니다',
197    fm_quality_low_coverage: '데이터 커버리지 {0}%로 부족',
198    fm_quality_gap: '최대 {0}시간 연속 공백',
199    fm_quality_collecting_days: '{0}일 후 판정 가능',
200    fm_quality_nodata: '이 기간의 데이터 없음',
201    fm_need_more_data: '데이터가 더 쌓이면 플랜 추천이 가능합니다',
202    fm_low_confidence: '(일부 기간 데이터 부족으로 참고용)',
203    fm_partial_tip: '제한된 데이터 기반 ({0}개 스냅샷)', fm_partial_note: '(일부 판정은 제한된 데이터 기반)',
204    fm_lv_exceeded: '부족', fm_lv_tight: '빠듯', fm_lv_fit: '적합', fm_lv_overspend: '과다', fm_lv_unknown: '판정 불가', fm_lv_partial: '제한된 데이터 기반',
205    fm_badge_current: '현재', fm_badge_rec: '추천',
206    fm_msg_upgrade: '{0} (${1}/{2})로 업그레이드를 추천합니다.',
207    fm_msg_downgrade: '{0} (${1}/{2})로 변경하면 월 ${3} 절약이 가능합니다.',
208    fm_per_seat: 'seat',
209    fm_group_consumer: '개인', fm_group_team: '팀',
210    fm_note_fitness_upgrade_rec_ok: '적합도 분석은 상위 플랜을 제안하지만, 최근 사용 패턴으로는 현재 플랜으로 충분합니다.',
211    fm_note_rec_upgrade_fitness_ok: '최근 단기간 집중 사용으로 업그레이드가 권장되지만, 장기 적합도 기준으로는 현재 플랜이 적합합니다.',
212    fm_note_rec_upgrade_fitness_down: '최근 사용 급증으로 업그레이드가 권장되지만, 장기 적합도 기준으로는 하위 플랜도 가능합니다. 일시적 급증일 수 있습니다.',
213    rt_title: '리셋 타이밍',
214    rt_next_7d: '다음 7일 리셋',
215    rt_next_5h: '다음 5시간 리셋',
216    rt_change_early: '예정보다 빠른 리셋 발생',
217    rt_change_early_desc: '{2}에 사용량이 예정({0})보다 일찍 초기화되어 새로운 7일 주기가 시작되었습니다. 다음 리셋은 {1} 예정입니다. 차트의 {0} 기준선은 변경 전 예정이었던 리셋 시점입니다.',
218    rt_change_5h_desc: '5시간 리셋이 {0}에서 {1}(으)로 변경되었습니다.',
219    sb_at_limit: '한도에 도달한 상태입니다', sb_at_limit_sub: '리셋까지 {0}',
220    sb_safe: '현재 속도라면 한도까지 여유 있음', sb_safe_sub: '예상 여유: {0}',
221    sb_tight: '빠듯함 — {0}부터 한도 대기 예상', sb_tight_sub: '리셋까지 약 {0} 대기',
222    sb_nodata: '예측 준비 중이에요', sb_nodata_sub: '데이터가 조금 더 쌓이면 5시간·주간 한도 도달 시점을 예측해드릴게요.',
223    sb_limit_at: '{0} 한도 도달 예상',
224    // Projected level without an arrival time — the projector is discount-only, so a window that
225    // will finish near the cap often never crosses it and has no honest hit time to show.
226    sb_projected: '{0} 리셋 시 ~{1}% 예상',
227    sb_reset_wait: '리셋: {0} (약 {1} 대기)',
228    predict_at_reset: '리셋 시 ~{0}% 예상',
229    predict_limit_at: '{0} 한도 도달 예상',
230    predict_basis: '시간당 +{0}% · 최근 {1} 기준',
231    limit_history_title: '최근 7일 한도 초과 이력',
232    limit_history_7d: '7d 한도 초과 {0}회 · 총 대기 약 {1}',
233    limit_history_5h: '5h 한도 초과 {0}회 · 총 대기 약 {1}',
234    limit_history_none: '최근 7일간 한도 초과 없음',
235    summary_today: '오늘 요약', ws_title: '최근 일주일 요약',
236    wait_time_title: '한도 제한 시간 (14일)', wait_time_limit: '한도', wait_time_total: '합계',
237    wait_time_note: '100% 도달 후 리셋까지의 시간 합산', min_short: '분',
238    stats_weekday_avg: '평일 평균', stats_weekend_avg: '주말 평균',
239    stats_wd_higher: '주말이 {0}% 더 높음', stats_wd_lower: '주말이 {0}% 더 낮음', stats_wd_same: '평일·주말 유사',
240    share_stats_title: '나의 공유 실적', share_stats_shares: '회 공유', share_stats_views: '회 조회',
241    dt_title: '일별 트렌드',
242    wt_title: '주별 트렌드', wt_this_week: '이번 주', wt_last_week: '지난 주', wt_change: '변화', wt_no_data: '지난 주 데이터 없음',
243    pr_title: '플랜 시뮬레이션', pr_period: '최근 {0}일', pr_current: '현재 플랜', pr_recommend_keep: '현재 플랜 유지', pr_recommend_switch: '{0} 전환 가능',
244    pr_exceed: '한도 초과 {0}/{1}일', pr_impossible: '사용 불가', pr_risky: '리스크 있음', pr_stable: '안정적', pr_acceptable: '전환 가능',
245    pr_unit_d: '일', pr_unit_mo: '월', pr_unit_seat_mo: '인/월', pr_limit: '한도', pr_far_exceeded: '대폭 초과', pr_slightly_exceeded: '소폭 초과',
246    pr_verdict_impossible: '사용 불가 — 한도 초과가 너무 잦아 정상 사용이 어렵습니다', pr_verdict_risky: '위험 — 자주 한도에 도달하여 작업 중단이 발생합니다', pr_verdict_acceptable: '적정 — 가끔 한도에 도달하지만 대체로 안정적입니다', pr_verdict_stable: '안정 — 한도 여유가 충분합니다',
247    pr_not_viable: '사용 불가', pr_interruption_cycle: '{0}일에 한 번 작업 중단', pr_exceeded_days_label: '플랜별 한도 초과일 ({0}일 기준)', pr_change_plan: 'Claude.ai에서 플랜 변경 →',
248    pr_why: '왜 다운그레이드가 어려운가?', pr_why_up: '업그레이드가 필요한 이유', pr_tip: '절약 팁', pr_tip_unused: '현재 한도의 {0}%를 사용하지 않고 있습니다', pr_tip_mid: '중간 티어(Max 10x 등)가 출시되면 비용 절감 가능', pr_pattern: '5h 일별 최대 사용률', pr_insufficient: '데이터가 충분하지 않습니다 ({0}일)',
249    pc_title: '같은 플랜 사용자와 비교', pc_peers: '{0}명 기준', pc_score: '활용도 점수', pc_plan_avg: '{0} 평균', pc_percentile: '백분위', pc_top: '상위 {0}%', pc_rank: '{0}명 중 {1}위',
250    wrapped_cta_title: '나의 Claude Tuner Wrapped', wrapped_cta_desc: '전체 사용 여정을 한눈에 — 토큰·연속 사용·활동 시간대·요일', wrapped_cta_btn: '내 Wrapped 보기', wrapped_title: '나의 Claude Tuner Wrapped', wrapped_top_pct: '상위 {0}%', wrapped_percentile_label: '같은 플랜 내 순위', wrapped_tokens_label: '이번 주 토큰', wrapped_eff_label: '활용도 점수', wrapped_7d_label: '7일 사용률', wrapped_peak_label: '가장 활발한 시간', wrapped_activity: '시간대별 활동', wrapped_no_data: '데이터를 더 모은 뒤 다시 시도해 주세요.',
251    wr_greet: '{0}님, 이만큼이나 함께했어요', wr_range_all: '전체', wr_range_180: '6M', wr_range_90: '3M', wr_range_30: '30d', wr_range_7: '7d', wr_pct_badge: '동일 {0} 플랜 상위 {1}%', wr_rank_of: '{0}명 중 {1}위', wr_close: '닫기', wr_loading: '불러오는 중…', wr_empty: '아직 보여드릴 사용 데이터가 충분하지 않아요.', wr_error: '데이터를 불러오지 못했어요.', wr_retry: '다시 시도',
252    wr_total_tokens: '총 토큰', wr_daily_avg: '일 평균 토큰', wr_active_days: '활성 일수', wr_peak_day: '최고 사용일', wr_cur_streak: '현재 연속 일수', wr_max_streak: '최장 연속 일수', wr_peak_hour: '최다 사용 시간', wr_busy_dow: '가장 활발한 요일', wr_unit_day: '일', wr_activity: '활동 히트맵', wr_hm_hint: '한 칸 = 하루 · 진할수록 사용량 ↑', wr_share: '이미지로 공유', wr_book_cmp: '{1}보다 약 {0}배 더 많은 토큰을 사용했어요', wr_none: '—', wr_prev_account_note: '이 카드는 이 계정 기록만 셉니다. 이전 계정 구간은 1년 사용량 잔디에서 볼 수 있습니다.',
253    pc_avg_title: '플랜 평균 대비', pc_7d_util: '7일 사용률', pc_daily_tokens: '일일 토큰', pc_limit_hits: '한도 초과/주', pc_cost_eff: '비용 효율성', pc_tokens_per_dollar: '토큰/$', pc_avg: '평균 {0}', pc_times: '회',
254    pc_my_position: '나의 위치', pc_cost_eff_score: '비용 효율', pc_see_insights: '인사이트에서 전체 순위 보기 →',
255    pc_dist_title: '사용량 분포', pc_dist_me: '나', pc_dist_users: '명',
256    pc_not_enough: '같은 플랜 사용자가 부족하여 비교할 수 없습니다',
257    pc_score_how: '산출 방식 보기',
258    pc_score_base: '기본 점수: 7일 평균 사용률 기반',
259    pc_score_base_desc: '0~40% → 0~80점 / 40~70% → 80~100점 / 70~90% → 100점(만점) / 90%+ → 감점(과사용)',
260    pc_score_active: '활동일 보정',
261    pc_score_active_desc: '최근 7일 중 실제 사용일이 많을수록 가산 (최대 ×1.0, 최소 ×0.7)',
262    pc_score_penalty: '한도 초과 감점',
263    pc_score_penalty_desc: '한도에 도달한 일수 × 3점 감점',
264    pc_score_formula: '최종 = 기본 점수 × 활동일 보정 - 한도 초과 감점 (0~100)',
265    // Review nudge
266    // ★ auto-move notice (#966). {0} = the org that went silent, {1} = the org ★ moved to.
267    pin_move_text: '{0} 조직이 수집을 멈춰서 대표 조직을 {1}(으)로 옮겼습니다. 요약 플랜과 기본 화면이 이 조직 기준으로 바뀝니다.',
268    pin_move_revert: '되돌리기',
269    pin_move_revert_unselected: '{0} 조직이 더 이상 수집 대상이 아니라 되돌릴 수 없습니다. 설정 > 활성 조직 관리에서 먼저 선택해주세요.',
270    pin_move_revert_failed: '되돌리지 못했습니다. 잠시 후 다시 시도해주세요.',
271    pin_move_revert_all_hidden: '선택한 조직이 모두 팀에서 숨김 처리되어 되돌릴 수 없습니다. 설정에서 조직 하나 이상을 팀에 공개해주세요.',
272    review_nudge_text: '여러분의 리뷰 하나가 1인 개발자 프로젝트에 큰 힘이 됩니다. 크롬 스토어에 별점과 리뷰 한 줄 남겨주시고, 주변에도 널리널리 알려주시면 정말 감사하겠습니다 🙏',
273    review_nudge_cta: '리뷰 남기기 ⭐',
274    org_all: '전체',
275    org_more: '더보기',
276    org_less: '접기',
277    org_stale_tooltip: '수집이 중단되었습니다. 클릭하여 다시 로그인하세요.',
278    org_stale_tooltip_noext: '데이터 수집이 중단되었습니다.',
279    stale_banner_text: '데이터 수집이 {0} 이상 중단되었습니다. 세션이 만료되었거나 확장 프로그램이 비활성화되었을 수 있습니다.',
280    stale_banner_cta: '다시 로그인 →',
281    // Blocked ≠ stale. The generic banner above blames an expired session or a disabled
282    // extension; for these accounts BOTH are wrong — the extension is running fine and sending,
283    // the server is refusing it. Telling them to re-login to Claude.ai wastes their time on the
284    // one screen where we can finally tell them the truth.
285    blocked_banner_title: '사용량이 서버에 저장되지 않고 있습니다',
286    blocked_banner_text: '확장 프로그램은 정상 작동 중이지만, 이 계정은 이제 로그인이 필요해서 서버가 데이터를 받지 못하고 있습니다. 아래 숫자는 {0} 전에 멈춘 값입니다.',
287    // Zero-snapshot variant. A blocked account can have NEVER stored anything (several such
288    // installs measured 2026-07-27), and then there is no "stopped N ago" to state — the elapsed
289    // time is Infinity and the duration sentence must be dropped entirely, not printed.
290    blocked_banner_text_nodata: '확장 프로그램은 정상 작동 중이지만, 이 계정은 이제 로그인이 필요해서 서버가 데이터를 받지 못하고 있습니다. 아직 저장된 사용량이 없습니다.',
291    blocked_banner_cta: '브라우저 툴바의 Claude Tuner 아이콘을 눌러 인증하세요',
292    // No-data banner: this account has zero snapshots (not a stale/expired session).
293    nodata_banner_text: '이 계정({0})에는 아직 수집된 데이터가 없습니다. 확장 프로그램이 다른 계정으로 수집 중일 수 있어요 — 확장 팝업 상단의 이메일을 확인해 주세요.',
294    nodata_pending_text: '수집을 방금 시작했어요. 잠시 후 사용량이 표시됩니다.',
295    // Account mismatch: the extension collects for a different account than the one signed in.
296    acct_mismatch_text: '확장 프로그램은 <strong>{0}</strong> 계정으로 수집 중입니다. 대시보드도 같은 계정으로 로그인해야 사용량이 보여요.',
297    acct_mismatch_cta: '이 계정으로 전환 →',
298    // Deselected-org banner: this org is intentionally excluded from the active-org cap,
299    // so re-login won't help — point the user at active-org settings instead.
300    deselected_banner_text: '이 조직은 활성 조직에서 제외되어 새 데이터가 수집되지 않습니다. 과거 데이터는 그대로 볼 수 있어요.',
301    deselected_banner_cta: '활성 조직 관리 →',
302    deselected_tooltip: '활성 조직에서 제외되어 수집이 중단되었습니다. 설정에서 다시 포함할 수 있어요.',
303    // 3-org cap drop: collection is silently stopped for orgs outside the active-org selection.
304    capdrop_banner_text: '계정 {0}개가 수집되지 않고 있습니다. 활성 조직 {1}개 한도가 찼습니다.',
305    capdrop_banner_room: '계정 {0}개가 수집되지 않고 있습니다. 활성 조직으로 선택하면 수집이 시작됩니다.',
306    capdrop_banner_cta: '수집할 조직 고르기 →',
307    shared_banner_text: '이 로그인에서 서로 다른 계정 {0}개가 감지되었습니다. 사용량이 하나로 합쳐져 보일 수 있어요.',
308    shared_banner_cta: '팀으로 나눠 보기 →',
309    org_not_supported: '이 조직 플랜에서는 아직 지원되지 않는 기능입니다.',
310    org_not_supported_detail: 'Enterprise 플랜은 사용량 구조가 달라 일부 분석을 아직 제공하지 못합니다. 추후 지원 예정입니다.',
311    // 3-org cap (active org selection). Distinct wording from the stale/login
312    // indicator so a deselected org doesn't read like a collection failure.
313    cap_chip_paused: '활성 제외',
314    cap_modal_title: '활성 조직 {cap}개를 선택해주세요',
315    cap_modal_desc: '활성 조직으로 선택한 조직만 새로운 사용량 데이터가 수집·저장됩니다. 안정적인 서비스 제공을 위해 한 계정당 최대 {cap}개까지 선택할 수 있어요. 지금 실제로 사용 중인 조직을 편하게 고르세요 — 선택하지 않은 조직의 과거 데이터는 그대로 유지되지만, 신규 데이터가 서버에 저장되지는 않습니다. 활성 조직은 언제든 옵션에서 다시 바꿀 수 있습니다.',
316    cap_modal_apply_default: '기본값(최근 활용 상위 {cap}개) 적용',
317    cap_modal_save: '저장',
318    cap_modal_count: '{n} / {cap} 선택됨',
319    cap_modal_min_one: '최소 1개는 선택해야 합니다.',
320    cap_settings_title: '활성 조직 관리',
321    cap_settings_desc: '수집 대상 조직을 최대 3개까지 선택합니다. 선택하지 않은 조직은 새 데이터가 수집되지 않습니다.',
322    cap_settings_saved: '저장되었습니다',
323    cap_settings_save_failed: '저장 실패',
324  },
325  en: {
326    nav_home: 'Home', nav_my_dash: 'My Dashboard', nav_team: 'Team', nav_insights: 'Insights', nav_feedback: 'Feedback', btn_logout: 'Logout',
327    login_title: 'Dashboard', login_desc: 'Sign in to view your usage data.', login_demo_link: 'Or try the demo with sample data →',
328    login_or: 'or', claude_login_toggle: 'Sign in another way', claude_login_btn: 'Sign in with the ClaudeTuner extension', claude_login_hint: 'Requires the ClaudeTuner extension (v1.12.8+)',
329    claude_login_loading: 'Signing in...', claude_login_not_logged_in: 'Please sign in to Claude.ai first', claude_login_no_data: 'No data yet. Please wait after installing the extension.', claude_login_failed: 'Sign in failed. Please try again.', claude_login_email_required: 'Please sign in with your email.', claude_login_not_installed: 'The ClaudeTuner extension is not installed or is disabled. Install it and try again, or sign in with email.', claude_login_install: 'Install',
330    email_login_toggle: 'Sign in with email', email_login_send: 'Send code', email_verify_btn: 'Verify',
331    email_auth_invalid: 'Please enter a valid email address.', email_auth_rate_limit: 'Too many requests. Please try again later.', email_auth_send_error: 'Failed to send code.', email_auth_network_error: 'Could not reach the server. Check your network (firewall/proxy) and try again.', email_verify_sent: 'Code sent to {email}.', email_verify_invalid: 'Please enter the 6-digit code.', email_verify_wrong: 'Invalid or expired code.', email_login_signing_in: 'Signing in…', email_login_link_expired: 'This sign-in link has expired. Please request a new code below.',
332    loading: 'Loading data...', loading_fail: 'Failed to load data. Please try again later.',
333    empty_title: 'No data collected yet',
334    empty_desc: 'Install the Chrome extension and sign in to Claude.ai<br>to start collecting usage data automatically.',
335    empty_link: 'Install from Chrome Web Store →',
336    status_danger: 'Near Limit', status_warn: 'Caution', status_ok: 'Normal',
337    rec_no_data: 'Insufficient data.',
338    rec_data_growing: 'Collecting data. At least 3 days of data needed for accurate recommendations.',
339    rec_upgrade_max5x: 'Upgrading to Max 5x is recommended. You\'ll get 5x more capacity.',
340    rec_upgrade_max20x: 'Consider upgrading to Max 20x.',
341    rec_upgrade_general: 'Consider a higher plan.',
342    rec_high_max20x: 'Your recent usage is high. Be mindful of the reset cycle.',
343    rec_high_max20x_critical: 'Consistently high usage. You\'re on the top plan — reduce token use to stay within limits.',
344    rec_adequate: 'Moderate usage — keep an eye on trends.',
345    rec_optimize_schedule: 'Your usage is concentrated during work hours. Spreading tasks to off-hours could make your current plan sufficient.',
346    rec_upgrade_pro: 'Pro upgrade recommended — you are frequently hitting your limits.',
347    rec_downgrade_max5x: 'Your usage is low for your plan. Consider downgrading to Max 5x.',
348    rec_downgrade_pro: 'Your usage is low for your plan. Consider downgrading to Pro.',
349    rec_good: 'Your current plan is a good fit.',
350    rec_enterprise: 'No usage limits',
351    rec_team_upgrade_premium: 'Near limit — consider Premium seat',
352    rec_team_near_limit: 'Near limit — contact admin',
353    rec_team_downgrade_standard: 'Standard seat may suffice',
354    rec_team_good: 'Current seat is a good fit',
355    // ChatGPT plan recommendation (v1) — see the ko block above and docs/SPEC-chatgpt-plan-rec.md.
356    rec_cg_insufficient_data: 'Insufficient data.',
357    rec_cg_adequate: 'Your current plan fits your usage.',
358    rec_cg_at_ceiling: 'Your recent usage reached your plan limit. There is no higher plan to recommend, so spreading usage over time is the practical lever.',
359    rec_cg_at_ceiling_seat: 'Your recent usage reached your seat limit. Seat and plan changes go through your workspace admin.',
360    rec_cg_upgrade_go: 'Consider upgrading to Go — you are often hitting your limits.',
361    rec_cg_upgrade_plus: 'Plus upgrade recommended — you are frequently hitting your limits.',
362    rec_cg_upgrade_pro5x: 'Pro 100 upgrade recommended — a much higher weekly limit.',
363    rec_cg_upgrade_pro20x: 'Consider upgrading to Pro 200.',
364    rec_cg_downgrade_free: 'Your usage is low. Consider downgrading to Free.',
365    rec_cg_downgrade_go: 'Your usage is low for your plan. Consider downgrading to Go.',
366    rec_cg_downgrade_plus: 'Your usage is low for your plan. Consider downgrading to Plus.',
367    rec_cg_downgrade_pro5x: 'Your usage is low for your plan. Consider downgrading to Pro 100.',
368    rec_cg_at_limit_headline: 'At your plan limit',
369    rec_cg_low_confidence: 'Confidence is low for this plan — reporting gaps are common.',
370    rec_cg_window_note: 'Based on peak utilization over the last {0} days',
371    rec_cg_title: 'Plan Recommendation',
372    rec_cg_change_plan: 'Change plan on ChatGPT →',
373    rec_peak_recent: 'Recent peak',
374    rec_avg_peak: 'Avg peak',
375    rec_savings: 'Monthly savings',
376    rec_month: 'mo',
377    rec_data_days: 'Data collected:',
378    rec_days_unit: ' days',
379    countdown_reset: 'Reset', countdown_until: 'Resets in ',
380    renewal_expired: 'Expired', renewal_days_left: '{0} days left',
381    pending_cancel_label: 'Cancel', pending_cancel_scheduled: 'Cancellation scheduled',
382    label_7d_util: '7-Day Usage', label_5h_util: '5-Hour Usage',
383    gauge_note_chatgpt: 'This includes usage outside text chat, such as Codex. Text chat has had no cap since August 2026, so it is not counted here.',
384    no_7d_for_plan: '{0} plan has no 7-day limit',
385    no_7d_unknown_plan: 'This workspace\'s plan could not be read, so its 7-day limit is unknown',
386    usage_withheld: 'Claude isn\'t providing usage for this account',
387    usage_withheld_plan: 'Claude isn\'t providing usage on the {0} plan',
388    usage_withheld_free_tip: "Since August 2026, Claude no longer provides usage figures for Free plan accounts — they don't appear in Claude's own settings either. Usage limits still apply. They'll reappear here automatically if Claude restores them.",
389    acct_plan_unknown: 'Unknown',
390    label_14d_avg: '7-Day Usage Avg Daily Rise (14d)', label_status: 'Status',
391    label_7d_tokens: '7d Usage', label_5h_tokens: '5h Usage',
392    label_renewal: 'Renewal Date', label_pending: 'Pending Change',
393    per_day: '%/day',
394    limit_alert_soon: 'At current rate, limit reached in ~{0}', limit_alert_safe: 'Plenty of room before limit at current rate', limit_alert_no_data: 'Usage too low to predict', limit_alert_reached: 'Currently at 7d usage limit',
395    summary_peak_5h: 'Today 5h Peak', summary_busiest: 'Busiest Hour', summary_limit_hits: 'Near Limit (≥80%)', summary_times: 'times', summary_hours: 'hours', summary_days: 'days',
396    rec_title: 'Plan Recommendation', rec_14d_avg: '14-day avg daily usage',
397    tab_util: 'Usage Trend (3 Days)', tab_token: 'Est. Tokens (3 Days)', tab_peak: 'Est. Tokens (14 Days)', tab_activity: 'Hourly Activity',
398    comp_title: 'Estimation Comparison', comp_date: 'Date (UTC)', comp_hourly: 'Hourly Sum', comp_daily: 'Daily (7d)', comp_server: 'Server Peak', comp_method: 'Method', comp_confidence: 'Confidence',
399    activity_title: 'Hourly Activity', activity_sub: 'Estimated tokens based on 5h/7d window delta', activity_disclaimer: 'Estimates may differ from actual usage', activity_today: 'Today', activity_this_week: 'Last 7 Days', activity_daily: 'Daily', activity_weekly: 'Weekly', activity_loading: 'Loading...', activity_no_data: 'No data collected for the selected period.', activity_tokens: 'Est. Tokens', heatmap_heavy: 'Heavy', heatmap_medium: 'Medium', heatmap_light: 'Light', heatmap_none: 'None', heatmap_nodata: 'No Data',
400    grove_title: 'Yearly Usage Grove', grove_sub: 'Your daily estimated-token usage at a glance, GitHub-style', grove_loading: 'Loading...', grove_no_data: 'No usage history to show yet.', grove_less: 'Less', grove_more: 'More', grove_none: 'No usage', grove_total: 'over the last year', grove_active_days: 'active days',
401    // Previous-account segments (#1106). Never offer "and it goes back" advice here — reasons are
402    // in the comment above CT_CLAIM_TEXT in site/shared/ext-detect.js. State the outcome first,
403    // and never claim a complete history: `snapshots` is on a 20-day retention.
404    grove_linked_legend: 'Previous account', grove_linked_tip: 'previous account {0}',
405    grove_linked_seg: '{0} – {1} · previous account {2}',
406    grove_linked_stats: '{0} · {1} days',
407    grove_linked_hidden: '{0} overlapping days show as this account\'s',
408    grove_linked_all_hidden: 'These {0} days are recorded under this account too, so no new day was added to the grove.',
409    grove_linked_empty: 'No daily records remain for this range.',
410    grove_linked_unavailable: 'This range could not be loaded. That does not mean there are no records — this attempt failed. Try reloading.',
411    grove_linked_org_note: 'Picking an org does not narrow a previous-account range — those ranges are org-independent.',
412    grove_linked_summary_note: 'The total above counts this account only. Previous-account ranges are listed below.',
413    scale_raw: 'Raw', scale_hourly: 'Hourly', scale_daily: 'Daily', yaxis_fixed: 'Y 100%', yaxis_auto: 'Y Auto',
414    chart_5h_util: '5-Hour Usage Trend', chart_7d_util: '7-Day Usage Trend',
415    chart_window_util: '{0} Usage Trend',
416    chart_window_util_sub: '{0} window usage (%) · Plan limits shown',
417    window_hours: '{0}-Hour', window_days: '{0}-Day',
418    chart_5h_util_sub: '5-hour window usage (%) · Plan limits shown',
419    chart_7d_util_sub: '7-day window usage (%) · Plan limits shown',
420    chart_spending: 'Extra Usage Trend', chart_spending_sub: 'Monthly spending ($) · Cap and budget pace shown',
421    chart_5h_token: '5h Est. Token Usage', chart_7d_token: '7d Est. Token Usage',
422    chart_token_sub: 'Token estimation based on usage · Plan limits shown',
423    chart_token_disclaimer: '* Community-observed estimates — Anthropic undisclosed figures',
424    chart_5h_peak: '5h Est. Tokens (14 Days)', chart_7d_peak: '7d Est. Tokens (14 Days)',
425    chart_peak_5h_sub: 'Max estimated tokens per 5h window · Plan limits shown',
426    chart_peak_7d_sub: 'Max estimated tokens per 7d window · Plan limits shown',
427    sec_kpi: 'Current Status', sec_plan_compare: 'Plan Comparison',
428    ce_title: 'Cost Efficiency', ce_tpd: 'tokens/$', ce_rank_label: 'Overall Rank', ce_top_pct: 'Top {0}%', ce_users: ' of',
429    ce_desc: 'Estimated tokens used per $1 of your monthly subscription. A low number means you\'re underutilizing your plan — consider switching to a cheaper plan or using Claude more actively.',
430    ce_avg: 'Avg', ce_top10: 'Top 10%', ce_org: 'My Org', ce_me: 'Me',
431    ce_vs_top10: '{0}% of top 10% level', ce_vs_org: '{0}% {1} than org average',
432    ce_higher: 'higher', ce_lower: 'lower',
433    account_title: 'Account Info',
434    ds_5h_window: '5-Hour Window', ds_7d_window: '7-Day Window', ds_budget: 'Budget Pace',
435    ds_budget_pace: 'Budget Pace', ds_spending: 'Spending', ds_cap: 'Spending Cap',
436    ds_omelette_7d: 'Design 7-Day', ds_sonnet_7d: 'Sonnet 7-Day',
437    sfx_green: '(green)',
438    plus_scoped: ' + {0} (orange)', plus_scoped2: ' + {0} (green)',
439    fl_window_weekly: 'weekly',
440    fl_note: 'A per-feature limit, counted separately from your plan limits',
441    fl_reset: 'resets {0}',
442    axis_5h_util: '5h Usage (%)', axis_7d_util: '7d Usage (%)',
443    axis_5h_token: '5h Est. Tokens', axis_7d_token: '7d Est. Tokens',
444    axis_5h_peak: '5h Est. Token Peak', axis_7d_peak: '7d Est. Token Peak',
445    ann_limit: 'Limit', ann_pro_limit: 'Limit', ann_max5x_limit: 'Limit',
446    pro_equiv: 'vs Pro ',
447    acct_email: 'Email', acct_plan: 'Plan', acct_renewal: 'Renewal',
448    acct_first_seen: 'First Seen', acct_last_seen: 'Last Seen', acct_snapshots: 'Snapshots',
449    acct_pending_change: 'Pending Change', acct_recent: ' recent',
450    grove_warning: '⚠ Training data sharing is ON', grove_turn_off: 'Turn off in settings →',
451    ds_5h_peak: '5h Peak', ds_7d_peak: '7d Peak',
452    ds_omelette_peak: 'Design Peak', ds_sonnet_peak: 'Sonnet Peak',
453    ds_5h_token: '5h Est. Tokens', ds_7d_token: '7d Est. Tokens',
454    caution_80: 'Caution (80%)',
455    rec_action_upgrade: 'Upgrade Recommended',
456    rec_action_downgrade: 'Downgrade Available',
457    rec_action_good: 'Current Plan Fits',
458    rec_method: 'Based on analysis of your last 14 days of usage (5h / 7d utilization patterns).',
459    rec_mode_current_label: 'Recommendation style',
460    rec_mode_v_cost: 'Cost saving', rec_mode_v_balanced: 'Balanced', rec_mode_v_convenience: 'Productivity first',
461    rec_mode_change: 'Change in settings →',
462    rec_action_high: 'High Usage',
463    rec_action_collecting: 'Collecting Data',
464    rec_btn_upgrade: 'Upgrade to {0}',
465    rec_btn_downgrade: 'Downgrade to {0}',
466    rec_btn_dismiss: 'Not now',
467    rec_cost_up: '${0}/mo → ${1}/mo (+${2})',
468    rec_cost_down: '${0}/mo → ${1}/mo (save ${2})',
469    rec_reason_7d_high: '7d usage avg {0}% — limit risk',
470    rec_reason_5h_limit: 'Hitting 5h limit frequently ({0}%)',
471    rec_reason_7d_low: '7d usage peak {0}% — overspending',
472    rec_reason_urgent: 'Urgent — approaching limit',
473    rec_reason_moderate: 'Avg peak {0}% — consider upgrade',
474    rec_collecting_progress: 'Collecting data ({0}/{1} days)',
475    view_as_banner: 'Viewing as {0}',
476    view_as_back: 'Back to my dashboard',
477    fm_title: 'Plan Fitness',
478    fm_col_plan: 'Plan',
479    fm_col_cost: 'Cost',
480    fm_window_5h: 'Last 5h',
481    fm_window_24h: 'Last 24h',
482    fm_window_7d: 'Last 7 Days',
483    fm_window_14d: 'Last 14 Days',
484    fm_savings: 'Save ${1}/mo by switching to {0}',
485    fm_upgrade_to: 'Upgrade to {0} recommended',
486    fm_overspend_note: 'Most of your {0} capacity is unused',
487    fm_all_fit: '{0} covers all periods',
488    fm_bottleneck_5h: 'Heavy burst usage. Spreading usage may allow a lower plan',
489    fm_bottleneck_7d: 'Consistently high usage. A higher plan is needed',
490    fm_tip_exceeded: '5h {0}% / 7d {1}% — Exceeds limit, not enough capacity',
491    fm_tip_tight: '5h {0}% / 7d {1}% — Only {2}% headroom before limit',
492    fm_tip_fit: '5h {0}% / 7d {1}% — Plenty of room',
493    fm_tip_overspend: '5h {0}% / 7d {1}% — Most capacity unused',
494    fm_quality_low_coverage: 'Data coverage only {0}%',
495    fm_quality_gap: 'Max {0}h consecutive gap',
496    fm_quality_collecting_days: 'Available in {0} day(s)',
497    fm_quality_nodata: 'No data for this period',
498    fm_need_more_data: 'More data needed for plan recommendation',
499    fm_low_confidence: '(Partial data — for reference only)',
500    fm_partial_tip: 'Based on limited data ({0} snapshots)', fm_partial_note: '(Some assessments based on limited data)',
501    fm_lv_exceeded: 'Insufficient', fm_lv_tight: 'Tight', fm_lv_fit: 'Good Fit', fm_lv_overspend: 'Overspend', fm_lv_unknown: 'N/A', fm_lv_partial: 'Limited data',
502    fm_badge_current: 'Current', fm_badge_rec: 'Rec',
503    fm_msg_upgrade: 'Upgrade to {0} (${1}/{2}) is recommended.',
504    fm_msg_downgrade: 'Switching to {0} (${1}/{2}) saves ${3}/mo.',
505    fm_per_seat: 'seat',
506    fm_group_consumer: 'Individual', fm_group_team: 'Team',
507    fm_note_fitness_upgrade_rec_ok: 'Fitness analysis suggests a higher plan, but recent usage patterns indicate the current plan is sufficient.',
508    fm_note_rec_upgrade_fitness_ok: 'An upgrade is recommended due to recent burst usage, but long-term fitness shows the current plan is adequate.',
509    fm_note_rec_upgrade_fitness_down: 'An upgrade is recommended due to a recent usage spike, but long-term fitness suggests even a lower plan may suffice. This may be a temporary spike.',
510    rt_title: 'Reset Timing',
511    rt_next_7d: 'Next 7-day reset',
512    rt_next_5h: 'Next 5-hour reset',
513    rt_change_early: 'Early reset detected',
514    rt_change_early_desc: 'Your usage was reset early at {2}, ahead of the scheduled {0}. A new 7-day cycle has started, with the next reset at {1}. The {0} line on the chart marks the originally scheduled reset.',
515    rt_change_5h_desc: 'The 5-hour reset was moved from {0} to {1}.',
516    sb_at_limit: 'You have reached the usage limit', sb_at_limit_sub: 'Resets in {0}',
517    sb_safe: 'Plenty of room at current rate', sb_safe_sub: 'Est. margin: {0}',
518    sb_tight: 'Tight — rate limit expected from {0}', sb_tight_sub: '~{0} wait until reset',
519    sb_nodata: 'Building your forecast', sb_nodata_sub: 'As a bit more data is collected, we\'ll predict when you\'ll hit your 5-hour & weekly limits.',
520    sb_limit_at: 'Limit expected at {0}',
521    sb_projected: '{0}: ~{1}% projected at reset',
522    sb_reset_wait: 'Reset: {0} (~{1} wait)',
523    predict_at_reset: '~{0}% at reset',
524    predict_limit_at: 'Limit expected at {0}',
525    predict_basis: '+{0}%/h · last {1}',
526    limit_history_title: 'Limit History (7 Days)',
527    limit_history_7d: '7d limit hit {0}x · ~{1} waiting',
528    limit_history_5h: '5h limit hit {0}x · ~{1} waiting',
529    limit_history_none: 'No limit hits in last 7 days',
530    summary_today: 'Today', ws_title: 'Last 7 Days',
531    wait_time_title: 'Limit Wait Time (14d)', wait_time_limit: 'limit', wait_time_total: 'Total',
532    wait_time_note: 'Cumulative time from hitting 100% to reset', min_short: 'm',
533    stats_weekday_avg: 'Weekday Avg', stats_weekend_avg: 'Weekend Avg',
534    stats_wd_higher: 'Weekend {0}% higher', stats_wd_lower: 'Weekend {0}% lower', stats_wd_same: 'Weekday·Weekend similar',
535    share_stats_title: 'My Share Stats', share_stats_shares: 'shares', share_stats_views: 'views',
536    dt_title: 'Daily Trend',
537    wt_title: 'Weekly Trend', wt_this_week: 'This Week', wt_last_week: 'Last Week', wt_change: 'Change', wt_no_data: 'No data last week',
538    pr_title: 'Plan Simulation', pr_period: 'Last {0} days', pr_current: 'Current Plan', pr_recommend_keep: 'Keep Current Plan', pr_recommend_switch: 'Can switch to {0}',
539    pr_exceed: 'Exceeded {0}/{1} days', pr_impossible: 'Not viable', pr_risky: 'Risky', pr_stable: 'Stable', pr_acceptable: 'Viable',
540    pr_unit_d: 'd', pr_unit_mo: 'mo', pr_unit_seat_mo: 'seat/mo', pr_limit: 'limit', pr_far_exceeded: 'far exceeded', pr_slightly_exceeded: 'slightly exceeded',
541    pr_verdict_impossible: 'Not viable — limit exceeded too frequently', pr_verdict_risky: 'Risky — frequent limit hits cause work interruptions', pr_verdict_acceptable: 'Acceptable — occasional limit hits but mostly stable', pr_verdict_stable: 'Stable — plenty of headroom',
542    pr_not_viable: 'Not viable', pr_interruption_cycle: '{0}d interruption cycle', pr_exceeded_days_label: 'Limit exceeded days per plan ({0}d)', pr_change_plan: 'Change plan on Claude.ai →',
543    pr_why: 'Why downgrade is difficult', pr_why_up: 'Why upgrade is needed', pr_tip: 'Saving Tips', pr_tip_unused: 'You are not using {0}% of your limit', pr_tip_mid: 'Consider switching if a mid-tier (e.g. Max 10x) becomes available', pr_pattern: '5h Daily Peak Usage', pr_insufficient: 'Not enough data ({0} days)',
544    pc_title: 'Compare with Same Plan Users', pc_peers: 'Based on {0} users', pc_score: 'Efficiency Score', pc_plan_avg: '{0} avg', pc_percentile: 'Percentile', pc_top: 'Top {0}%', pc_rank: '#{1} of {0}',
545    wrapped_cta_title: 'My Claude Tuner Wrapped', wrapped_cta_desc: 'Your whole journey at a glance — tokens, streaks, active hours & days', wrapped_cta_btn: 'View my Wrapped', wrapped_title: 'My Claude Tuner Wrapped', wrapped_top_pct: 'Top {0}%', wrapped_percentile_label: 'Rank in your plan', wrapped_tokens_label: 'Tokens this week', wrapped_eff_label: 'Efficiency score', wrapped_7d_label: '7-day usage', wrapped_peak_label: 'Peak hour', wrapped_activity: 'Hourly activity', wrapped_no_data: 'Collect a bit more data and try again.',
546    wr_greet: '{0}, look how far you\'ve come', wr_range_all: 'All', wr_range_180: '6M', wr_range_90: '3M', wr_range_30: '30d', wr_range_7: '7d', wr_pct_badge: 'Top {1}% among {0} plan users', wr_rank_of: '#{1} of {0}', wr_close: 'Close', wr_loading: 'Loading…', wr_empty: 'Not enough usage data to show yet.', wr_error: 'Couldn\'t load your data.', wr_retry: 'Retry',
547    wr_total_tokens: 'Total tokens', wr_daily_avg: 'Daily average', wr_active_days: 'Active days', wr_peak_day: 'Busiest day', wr_cur_streak: 'Current streak', wr_max_streak: 'Longest streak', wr_peak_hour: 'Peak hour', wr_busy_dow: 'Busiest weekday', wr_unit_day: 'd', wr_activity: 'Activity heatmap', wr_hm_hint: 'Each square = one day · darker = more usage', wr_share: 'Share as image', wr_book_cmp: 'You used about {0}× more tokens than {1}', wr_none: '—', wr_prev_account_note: 'This card counts this account only. Previous-account ranges appear in the yearly usage grove.',
548    pc_avg_title: 'vs Plan Average', pc_7d_util: '7-Day Usage', pc_daily_tokens: 'Daily Tokens', pc_limit_hits: 'Limit Hits/Week', pc_cost_eff: 'Cost Efficiency', pc_tokens_per_dollar: 'tokens/$', pc_avg: 'avg {0}', pc_times: 'times',
549    pc_my_position: 'My Position', pc_cost_eff_score: 'Cost Efficiency', pc_see_insights: 'See full rankings in Insights →',
550    pc_dist_title: 'Usage Distribution', pc_dist_me: 'Me', pc_dist_users: 'users',
551    pc_not_enough: 'Not enough users on the same plan for comparison',
552    pc_score_how: 'How is this calculated?',
553    pc_score_base: 'Base score: 7-day average utilization',
554    pc_score_base_desc: '0~40% → 0~80pts / 40~70% → 80~100pts / 70~90% → 100pts (max) / 90%+ → penalty (overuse)',
555    pc_score_active: 'Active days bonus',
556    pc_score_active_desc: 'More active days in the last 7 → higher multiplier (×0.7 min ~ ×1.0 max)',
557    pc_score_penalty: 'Limit hit penalty',
558    pc_score_penalty_desc: 'Days hitting the limit × 3 points deducted',
559    pc_score_formula: 'Final = Base × Active bonus - Limit penalty (0~100)',
560    // Review nudge
561    // ★ auto-move notice (#966). {0} = the org that went silent, {1} = the org ★ moved to.
562    pin_move_text: '{0} stopped collecting, so we moved your primary organization to {1}. Your headline plan and default view now follow that organization.',
563    pin_move_revert: 'Undo',
564    pin_move_revert_unselected: '{0} is no longer being collected, so this cannot be undone here. Select it again under Settings > Active organizations first.',
565    pin_move_revert_failed: "Couldn't undo that. Please try again in a moment.",
566    pin_move_revert_all_hidden: 'Every selected organization is hidden from your team, so this cannot be undone. Un-hide at least one in Settings first.',
567    review_nudge_text: "Your review means a lot to this solo developer project. A star rating and a short review on the Chrome Web Store — and if you're enjoying it, please spread the word! 🙏",
568    review_nudge_cta: 'Leave a review ⭐',
569    org_all: 'All',
570    org_more: 'More',
571    org_less: 'Less',
572    org_stale_tooltip: 'Collection interrupted. Click to sign in again.',
573    org_stale_tooltip_noext: 'Data collection has stopped.',
574    stale_banner_text: 'Data collection has been interrupted for {0}+. Your session may have expired or the extension may be disabled.',
575    stale_banner_cta: 'Sign in again →',
576    // Blocked ≠ stale. The generic banner above blames an expired session or a disabled
577    // extension; for these accounts BOTH are wrong — the extension is running fine and sending,
578    // the server is refusing it.
579    blocked_banner_title: 'Your usage is not reaching the server',
580    blocked_banner_text: 'The extension is running fine, but this account now requires a sign-in, so the server is refusing its data. The numbers below stopped {0} ago.',
581    // Zero-snapshot variant — see the ko note above.
582    blocked_banner_text_nodata: 'The extension is running fine, but this account now requires a sign-in, so the server is refusing its data. No usage has been stored yet.',
583    blocked_banner_cta: 'Click the Claude Tuner icon in your browser toolbar to verify',
584    // No-data banner: this account has zero snapshots (not a stale/expired session).
585    nodata_banner_text: 'No usage data has been collected for this account ({0}) yet. The extension may be collecting under a different account — check the email at the top of the extension popup.',
586    nodata_pending_text: 'Collection just started. Your usage will appear here shortly.',
587    // Account mismatch: the extension collects for a different account than the one signed in.
588    acct_mismatch_text: 'The extension is collecting usage for <strong>{0}</strong>. Sign in to the dashboard with that same account to see it.',
589    acct_mismatch_cta: 'Switch to this account →',
590    // Deselected-org banner: this org is intentionally excluded from the active-org cap,
591    // so re-login won't help — point the user at active-org settings instead.
592    deselected_banner_text: "This organization is excluded from your active orgs, so no new data is being collected. Past data is still available.",
593    deselected_banner_cta: 'Manage active orgs →',
594    deselected_tooltip: 'Excluded from active orgs, so collection has stopped. You can re-include it in settings.',
595    // 3-org cap drop: collection is silently stopped for orgs outside the active-org selection.
596    capdrop_banner_text: '{0} account(s) are not being collected — your {1} active-org limit is full.',
597    capdrop_banner_room: '{0} account(s) are not being collected — select them as active organizations to start.',
598    capdrop_banner_cta: 'Choose which to collect →',
599    shared_banner_text: '{0} different accounts were detected on this login, so their usage may appear merged.',
600    shared_banner_cta: 'Split them across a team →',
601    org_not_supported: 'This feature is not yet available for this organization plan.',
602    org_not_supported_detail: 'Some analytics are not yet supported for Enterprise plans due to different usage structures. Coming soon.',
603    // 3-org cap (active org selection)
604    cap_chip_paused: 'Excluded',
605    cap_modal_title: 'Choose your {cap} active organizations',
606    cap_modal_desc: 'Only organizations marked as active have new usage data collected and saved. To keep the service stable, each account can select up to {cap}. Just pick the ones you actually use right now — historical data for unselected orgs is preserved, but no new data is saved to the server for them. You can change your active organizations any time in options.',
607    cap_modal_apply_default: 'Apply default (top {cap} by recent usage)',
608    cap_modal_save: 'Save',
609    cap_modal_count: '{n} / {cap} selected',
610    cap_modal_min_one: 'At least 1 organization must be selected.',
611    cap_settings_title: 'Active organizations',
612    cap_settings_desc: 'Choose up to 3 organizations to collect data from. Unselected orgs will not receive new snapshots.',
613    cap_settings_saved: 'Saved',
614    cap_settings_save_failed: 'Save failed',
615  }
616};
617
618var _lang = localStorage.getItem('ct-lang') || ((navigator.language || '').toLowerCase().startsWith('ko') ? 'ko' : 'en');
619document.documentElement.lang = _lang;
620
621function escHtml(s) {
622  return (s || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
623}
624var _avatarCacheBuster = Math.floor(Date.now() / 86400000);
625function _bustAvatarCache(url) {
626  if (url && url.indexOf('/avatars/') >= 0) return url + '?v=' + _avatarCacheBuster;
627  return url;
628}
629
630// Substitute {0}, {1}, ... in ONE pass.
631//
632// Fixes two latent bugs in the previous per-arg `s.replace('{i}', a)` loop:
633//  1. Substituted text was rescanned by later args, so a value that happens to contain a
634//     placeholder ate the next one. Not merely theoretical: several messages interpolate an
635//     email address, and `{1}@corp.example` passes the project's address validation.
636//  2. `String.prototype.replace` with a STRING pattern replaces only the FIRST match, so a
637//     message reusing a placeholder would render a literal "{0}". No caller hits this today —
638//     rt_change_early_desc is the one template that reuses `{0}`, and dashboard-charts.js
639//     interpolates it with its own /g replaces instead of passing args to t() — but the next
640//     one to pass args would have silently shown braces to users.
641// A single regex pass with a callback fixes both: the callback's return value is never
642// rescanned, and /g covers repeats.
643function t(key) {
644  var args = Array.prototype.slice.call(arguments, 1);
645  var s = (T[_lang] || T.en)[key] || T.en[key] || key;
646  return s.replace(/\{(\d+)\}/g, function(match, idx) {
647    var v = args[Number(idx)];
648    return v === undefined ? match : String(v);
649  });
650}
651
652// Count + unit word ("3회" / "3 times"). Korean attaches the unit; English separates it with a
653// space and drops the plural "s" for exactly 1 ("1 time"). Unit keys hold the EN PLURAL form.
654// Concatenating `n + t('summary_times')` directly is what rendered "0times" (#1729).
655function fmtUnit(n, key) {
656  var unit = t(key);
657  if (_lang === 'ko') return n + unit;
658  if (String(n) === '1' && /s$/.test(unit)) unit = unit.slice(0, -1);
659  return n + ' ' + unit;
660}
661
662function setLang(lang) {
663  _lang = lang;
664  localStorage.setItem('ct-lang', lang);
665  document.documentElement.lang = lang;
666  applyI18n();
667  // The provider notice is built in JS and lives OUTSIDE #dashboard-content, so neither
668  // applyI18n() (it has no [data-i18n]) nor the re-render below would retranslate it — it would
669  // sit there in the previous language.
670  if (typeof _paintProviderConnectNotice === 'function') _paintProviderConnectNotice();
671  // re-render dashboard if loaded
672  if (_cachedData) {
673    document.getElementById('dashboard-content').innerHTML = '';
674    renderDetailDashboard(_cachedData.meData, _cachedData.usageData, _cachedData.snapshotsData, _cachedData.recData);
675  }
676}
677
678function applyI18n() {
679  document.querySelectorAll('[data-i18n]').forEach(function(el) { el.textContent = t(el.dataset.i18n); });
680  document.querySelectorAll('[data-i18n-html]').forEach(function(el) { el.innerHTML = t(el.dataset.i18nHtml); });
681}
682

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.