@@ -148,13 +148,13 @@ const KEYPAD_ROWS = [
148148
149149// Each example carries both directions so a single click can populate either side.
150150const EXAMPLES = [
151- { label : 'em' , latin : 'em' , digits : '33 6' , note : 'ví dụ trong đề bài ' } ,
152- { label : 'hello' , latin : 'hello' , digits : '44 33 555 555 666' , note : 'Nokia cổ điển ' } ,
153- { label : 'abc' , latin : 'abc' , digits : '2 22 222' , note : 'lần lượt phím 2 ' } ,
154- { label : 'hi ok' , latin : 'hi ok' , digits : '44 444 0 666 5' , note : 'space dùng `0` (đứng riêng )' } ,
155- { label : 'can' , latin : 'can' , digits : '222266' , note : 'không quay vòng : 2222 -> ca, +66 -> n' } ,
156- { label : '2024' , latin : '2024' , digits : '2024' , note : 'cụm có `0` -> giữ nguyên số ' } ,
157- { label : 'mot ngay' , latin : 'mot ngay' , digits : '6 666 8 0 66 4 2 999' , note : 'chuỗi có dấu cách ' } ,
151+ { label : 'em' , latin : 'em' , digits : '33 6' , note : 'example from the prompt ' } ,
152+ { label : 'hello' , latin : 'hello' , digits : '44 33 555 555 666' , note : 'classic Nokia ' } ,
153+ { label : 'abc' , latin : 'abc' , digits : '2 22 222' , note : 'press 2 repeatedly ' } ,
154+ { label : 'hi ok' , latin : 'hi ok' , digits : '44 444 0 666 5' , note : 'space uses `0` (alone )' } ,
155+ { label : 'can' , latin : 'can' , digits : '222266' , note : 'no wrap : 2222 -> ca, +66 -> n' } ,
156+ { label : '2024' , latin : '2024' , digits : '2024' , note : 'cluster with `0` -> kept as number ' } ,
157+ { label : 'mot ngay' , latin : 'mot ngay' , digits : '6 666 8 0 66 4 2 999' , note : 'string with spaces ' } ,
158158] ;
159159
160160// ─── Component ───────────────────────────────────────────────────────────────
@@ -183,7 +183,7 @@ const T9Converter = () => {
183183 preview = { decoded }
184184 previewLabel = "Decode (T9 → Latin)"
185185 invalid = { t9Invalid }
186- invalidMsg = "Chỉ chấp nhận chữ số 0-9 và khoảng trắng ."
186+ invalidMsg = "Only digits 0-9 and whitespace are accepted ."
187187 showKeypad
188188 />
189189 < LatinPanel
@@ -192,7 +192,7 @@ const T9Converter = () => {
192192 preview = { encoded }
193193 previewLabel = "Encode (Latin → T9)"
194194 invalid = { latinInvalid }
195- invalidMsg = "Chỉ chấp nhận chữ cái a-z, chữ số 0-9 và khoảng trắng ."
195+ invalidMsg = "Only letters a-z, digits 0-9, and whitespace are accepted ."
196196 />
197197 </ div >
198198
@@ -235,7 +235,7 @@ const PanelShell = ({
235235 icon = { copied ? Check : Copy }
236236 className = "px-2 py-1"
237237 >
238- { copied ? 'Đã copy ' : 'Copy' }
238+ { copied ? 'Copied ' : 'Copy' }
239239 </ Button >
240240 ) }
241241 { onClear && (
@@ -246,7 +246,7 @@ const PanelShell = ({
246246 icon = { Trash2 }
247247 className = "px-2 py-1"
248248 >
249- Xóa
249+ Clear
250250 </ Button >
251251 ) }
252252 </ div >
@@ -310,16 +310,16 @@ const DigitPanel = ({ value, onChange, preview, previewLabel, invalid, invalidMs
310310 return (
311311 < div className = "flex flex-col gap-3 min-w-0" >
312312 < PanelShell
313- label = "Chuỗi phím T9 "
313+ label = "T9 key sequence "
314314 icon = { Hash }
315315 value = { value }
316316 onChange = { onChange }
317- placeholder = "Ví dụ : 33 6 hoặc 4433555 555666"
317+ placeholder = "Example : 33 6 or 4433555 555666"
318318 preview = { preview }
319319 previewLabel = { previewLabel }
320320 invalid = { invalid }
321321 invalidMsg = { invalidMsg }
322- charCount = { `${ value . length } ký tự ` }
322+ charCount = { `${ value . length } chars ` }
323323 onCopy = { handleCopy }
324324 onClear = { ( ) => onChange ( '' ) }
325325 copied = { copied }
@@ -333,10 +333,10 @@ const DigitPanel = ({ value, onChange, preview, previewLabel, invalid, invalidMs
333333 ) }
334334 { /* Decode cheat-sheet */ }
335335 < div className = "rounded-xl bg-slate-900/70 border border-slate-700/70 p-3 text-[11px] text-slate-500 leading-relaxed" >
336- < div > < span className = "font-mono text-slate-300" > 0</ span > đứng riêng (một mình) → space.</ div >
337- < div > Cụm chữ số có chứa < span className = "font-mono text-slate-300" > 0</ span > và dài hơn 1 ký tự → giữ nguyên số
338- (vd < span className = "font-mono text-slate-300" > 2024</ span > → < span className = "font-mono text-blue-300" > 2024</ span > ).</ div >
339- < div > Cụm không có < span className = "font-mono text-slate-300" > 0</ span > → decode T9 multi-tap.</ div >
336+ < div > < span className = "font-mono text-slate-300" > 0</ span > alone (by itself) - > space . </ div >
337+ < div > A digit cluster containing < span className = "font-mono text-slate-300" > 0</ span > and longer than 1 character - > kept as a number
338+ ( e . g . < span className = "font-mono text-slate-300" > 2024</ span > - > < span className = "font-mono text-blue-300" > 2024</ span > ).</ div >
339+ < div > Cluster without < span className = "font-mono text-slate-300" > 0</ span > - > T9 multi - tap decode . </ div >
340340 </ div >
341341 </ div >
342342 ) ;
@@ -364,25 +364,25 @@ const LatinPanel = ({ value, onChange, preview, previewLabel, invalid, invalidMs
364364 return (
365365 < div className = "flex flex-col gap-3 min-w-0" >
366366 < PanelShell
367- label = "Chuỗi Latin"
367+ label = "Latin string "
368368 icon = { Type }
369369 value = { value }
370370 onChange = { onChange }
371- placeholder = "Ví dụ : em hoặc hello"
371+ placeholder = "Example : em or hello"
372372 preview = { preview }
373373 previewLabel = { previewLabel }
374374 invalid = { invalid }
375375 invalidMsg = { invalidMsg }
376- charCount = { `${ value . length } ký tự ` }
376+ charCount = { `${ value . length } chars ` }
377377 onCopy = { handleCopy }
378378 onClear = { ( ) => onChange ( '' ) }
379379 copied = { copied }
380380 />
381381 { /* Encode cheat-sheet */ }
382382 < div className = "rounded-xl bg-slate-900/70 border border-slate-700/70 p-3 text-xs text-slate-500 leading-relaxed" >
383- Gõ < span className = "font-mono text-slate-300" > a-z</ span > , < span className = "font-mono text-slate-300" > 0-9</ span > và dấu cách; ký tự khác bị bỏ qua .
384- Chữ cái tách bằng khoảng trắng; cụm số giữ nguyên ,
385- ví dụ < span className = "font-mono text-slate-300" > hello 2024</ span > → < span className = "font-mono text-blue-300" > 44 33 555 555 666 0 2024</ span > .
383+ Type < span className = "font-mono text-slate-300" > a-z</ span > , < span className = "font-mono text-slate-300" > 0-9</ span > and whitespace; other characters are dropped .
384+ Letters are space-separated; number clusters pass through ,
385+ e.g. < span className = "font-mono text-slate-300" > hello 2024</ span > - > < span className = "font-mono text-blue-300" > 44 33 555 555 666 0 2024</ span > .
386386 </ div >
387387 </ div >
388388 ) ;
@@ -392,7 +392,7 @@ const Keypad = ({ onKey, onSpace, onBackspace }) => (
392392 < div className = "flex flex-col gap-2" >
393393 < label className = "text-xs font-bold text-slate-600 uppercase tracking-wider flex items-center gap-1.5" >
394394 < Keyboard size = { 11 } />
395- Bàn phím ảo
395+ Virtual keypad
396396 </ label >
397397 < div className = "rounded-xl bg-slate-900/70 border border-slate-700/70 p-3" >
398398 < div className = "grid grid-cols-3 gap-1.5 max-w-[200px] mx-auto" >
@@ -421,14 +421,14 @@ const Keypad = ({ onKey, onSpace, onBackspace }) => (
421421 className = "px-2 py-1.5 rounded-md bg-slate-800 hover:bg-slate-700 border border-slate-700 text-slate-300 text-[11px] font-medium flex items-center justify-center gap-1 transition-colors"
422422 >
423423 < Space size = { 11 } />
424- Tách nhóm
424+ Split group
425425 </ button >
426426 < button
427427 type = "button"
428428 onClick = { onBackspace }
429429 className = "px-2 py-1.5 rounded-md bg-slate-800 hover:bg-slate-700 border border-slate-700 text-slate-300 text-[11px] font-medium transition-colors"
430430 >
431- ⌫ Xóa 1 ký tự
431+ ⌫ Delete 1 char
432432 </ button >
433433 </ div >
434434 </ div >
@@ -438,7 +438,7 @@ const Keypad = ({ onKey, onSpace, onBackspace }) => (
438438const KeyMap = ( ) => (
439439 < div className = "flex flex-col gap-2" >
440440 < p className = "text-xs font-bold text-slate-600 uppercase tracking-wider" >
441- Bảng phím
441+ Key map
442442 </ p >
443443 < div className = "grid grid-cols-4 gap-2" >
444444 { Object . entries ( T9_KEYS ) . map ( ( [ digit , letters ] ) => (
@@ -456,7 +456,7 @@ const KeyMap = () => (
456456 ) ) }
457457 < div className = "flex items-center gap-3 px-3 py-2 rounded-lg bg-slate-800/50 border border-slate-700/50 col-span-4" >
458458 < span className = "font-mono text-base font-bold text-slate-200 w-5 text-center" > 0</ span >
459- < span className = "font-mono text-xs text-slate-400" > dấu cách ( space) </ span >
459+ < span className = "font-mono text-xs text-slate-400" > space character </ span >
460460 </ div >
461461 </ div >
462462 </ div >
@@ -466,7 +466,7 @@ const Examples = ({ onPickT9, onPickLatin }) => (
466466 < div className = "flex flex-col gap-2" >
467467 < p className = "text-xs font-bold text-slate-600 uppercase tracking-wider flex items-center gap-1.5" >
468468 < Lightbulb size = { 11 } />
469- Ví dụ nhanh
469+ Quick examples
470470 </ p >
471471 < div className = "flex flex-col gap-2" >
472472 { EXAMPLES . map ( ( ex ) => (
@@ -481,15 +481,15 @@ const Examples = ({ onPickT9, onPickLatin }) => (
481481 < div className = "flex items-center gap-1 shrink-0" >
482482 < button
483483 type = "button"
484- title = { `Nạp "${ ex . latin } " vào ô Latin` }
484+ title = { `Load "${ ex . latin } " into Latin box ` }
485485 onClick = { ( ) => onPickLatin ( ex . latin ) }
486486 className = "px-2 py-1 rounded text-[10px] font-mono bg-slate-900 hover:bg-slate-700 text-slate-300 border border-slate-700 transition-colors"
487487 >
488488 latin
489489 </ button >
490490 < button
491491 type = "button"
492- title = { `Nạp "${ ex . digits } " vào ô T9 ` }
492+ title = { `Load "${ ex . digits } " into T9 box ` }
493493 onClick = { ( ) => onPickT9 ( ex . digits ) }
494494 className = "px-2 py-1 rounded text-[10px] font-mono bg-slate-900 hover:bg-slate-700 text-slate-300 border border-slate-700 transition-colors"
495495 >
0 commit comments