From 1dce30b39f086a232704c64dad4eca6fea53c410 Mon Sep 17 00:00:00 2001 From: pomelo-nwu Date: Tue, 18 Nov 2025 10:07:55 +0800 Subject: [PATCH] feat(i18n): Add internationalization for loading phrases --- packages/cli/src/i18n/locales/en.js | 214 ++++++++++++++++++ packages/cli/src/i18n/locales/zh.js | 187 +++++++++++++++ packages/cli/src/ui/components/AboutBox.tsx | 3 +- .../src/ui/components/LoadingIndicator.tsx | 8 +- packages/cli/src/ui/hooks/usePhraseCycler.ts | 17 +- packages/cli/src/utils/systemInfoFields.ts | 29 +-- 6 files changed, 436 insertions(+), 22 deletions(-) diff --git a/packages/cli/src/i18n/locales/en.js b/packages/cli/src/i18n/locales/en.js index 3f23f6e5..03b3c438 100644 --- a/packages/cli/src/i18n/locales/en.js +++ b/packages/cli/src/i18n/locales/en.js @@ -53,6 +53,25 @@ export default { 'for help on Qwen Code': 'for help on Qwen Code', 'show version info': 'show version info', 'submit a bug report': 'submit a bug report', + 'About Qwen Code': 'About Qwen Code', + + // ============================================================================ + // System Information Fields + // ============================================================================ + 'CLI Version': 'CLI Version', + 'Git Commit': 'Git Commit', + Model: 'Model', + Sandbox: 'Sandbox', + 'OS Platform': 'OS Platform', + 'OS Arch': 'OS Arch', + 'OS Release': 'OS Release', + 'Node.js Version': 'Node.js Version', + 'NPM Version': 'NPM Version', + 'Session ID': 'Session ID', + 'Auth Method': 'Auth Method', + 'Base URL': 'Base URL', + 'Memory Usage': 'Memory Usage', + 'IDE Client': 'IDE Client', // ============================================================================ // Commands - General @@ -605,4 +624,199 @@ export default { 'of input tokens were served from the cache, reducing costs.', 'Tip: For a full token breakdown, run `/stats model`.': 'Tip: For a full token breakdown, run `/stats model`.', + + // ============================================================================ + // Loading Phrases + // ============================================================================ + 'Waiting for user confirmation...': 'Waiting for user confirmation...', + '(esc to cancel, {{time}})': '(esc to cancel, {{time}})', + "I'm Feeling Lucky": "I'm Feeling Lucky", + 'Shipping awesomeness... ': 'Shipping awesomeness... ', + 'Painting the serifs back on...': 'Painting the serifs back on...', + 'Navigating the slime mold...': 'Navigating the slime mold...', + 'Consulting the digital spirits...': 'Consulting the digital spirits...', + 'Reticulating splines...': 'Reticulating splines...', + 'Warming up the AI hamsters...': 'Warming up the AI hamsters...', + 'Asking the magic conch shell...': 'Asking the magic conch shell...', + 'Generating witty retort...': 'Generating witty retort...', + 'Polishing the algorithms...': 'Polishing the algorithms...', + "Don't rush perfection (or my code)...": + "Don't rush perfection (or my code)...", + 'Brewing fresh bytes...': 'Brewing fresh bytes...', + 'Counting electrons...': 'Counting electrons...', + 'Engaging cognitive processors...': 'Engaging cognitive processors...', + 'Checking for syntax errors in the universe...': + 'Checking for syntax errors in the universe...', + 'One moment, optimizing humor...': 'One moment, optimizing humor...', + 'Shuffling punchlines...': 'Shuffling punchlines...', + 'Untangling neural nets...': 'Untangling neural nets...', + 'Compiling brilliance...': 'Compiling brilliance...', + 'Loading wit.exe...': 'Loading wit.exe...', + 'Summoning the cloud of wisdom...': 'Summoning the cloud of wisdom...', + 'Preparing a witty response...': 'Preparing a witty response...', + "Just a sec, I'm debugging reality...": + "Just a sec, I'm debugging reality...", + 'Confuzzling the options...': 'Confuzzling the options...', + 'Tuning the cosmic frequencies...': 'Tuning the cosmic frequencies...', + 'Crafting a response worthy of your patience...': + 'Crafting a response worthy of your patience...', + 'Compiling the 1s and 0s...': 'Compiling the 1s and 0s...', + 'Resolving dependencies... and existential crises...': + 'Resolving dependencies... and existential crises...', + 'Defragmenting memories... both RAM and personal...': + 'Defragmenting memories... both RAM and personal...', + 'Rebooting the humor module...': 'Rebooting the humor module...', + 'Caching the essentials (mostly cat memes)...': + 'Caching the essentials (mostly cat memes)...', + 'Optimizing for ludicrous speed': 'Optimizing for ludicrous speed', + "Swapping bits... don't tell the bytes...": + "Swapping bits... don't tell the bytes...", + 'Garbage collecting... be right back...': + 'Garbage collecting... be right back...', + 'Assembling the interwebs...': 'Assembling the interwebs...', + 'Converting coffee into code...': 'Converting coffee into code...', + 'Updating the syntax for reality...': 'Updating the syntax for reality...', + 'Rewiring the synapses...': 'Rewiring the synapses...', + 'Looking for a misplaced semicolon...': + 'Looking for a misplaced semicolon...', + "Greasin' the cogs of the machine...": "Greasin' the cogs of the machine...", + 'Pre-heating the servers...': 'Pre-heating the servers...', + 'Calibrating the flux capacitor...': 'Calibrating the flux capacitor...', + 'Engaging the improbability drive...': 'Engaging the improbability drive...', + 'Channeling the Force...': 'Channeling the Force...', + 'Aligning the stars for optimal response...': + 'Aligning the stars for optimal response...', + 'So say we all...': 'So say we all...', + 'Loading the next great idea...': 'Loading the next great idea...', + "Just a moment, I'm in the zone...": "Just a moment, I'm in the zone...", + 'Preparing to dazzle you with brilliance...': + 'Preparing to dazzle you with brilliance...', + "Just a tick, I'm polishing my wit...": + "Just a tick, I'm polishing my wit...", + "Hold tight, I'm crafting a masterpiece...": + "Hold tight, I'm crafting a masterpiece...", + "Just a jiffy, I'm debugging the universe...": + "Just a jiffy, I'm debugging the universe...", + "Just a moment, I'm aligning the pixels...": + "Just a moment, I'm aligning the pixels...", + "Just a sec, I'm optimizing the humor...": + "Just a sec, I'm optimizing the humor...", + "Just a moment, I'm tuning the algorithms...": + "Just a moment, I'm tuning the algorithms...", + 'Warp speed engaged...': 'Warp speed engaged...', + 'Mining for more Dilithium crystals...': + 'Mining for more Dilithium crystals...', + "Don't panic...": "Don't panic...", + 'Following the white rabbit...': 'Following the white rabbit...', + 'The truth is in here... somewhere...': + 'The truth is in here... somewhere...', + 'Blowing on the cartridge...': 'Blowing on the cartridge...', + 'Loading... Do a barrel roll!': 'Loading... Do a barrel roll!', + 'Waiting for the respawn...': 'Waiting for the respawn...', + 'Finishing the Kessel Run in less than 12 parsecs...': + 'Finishing the Kessel Run in less than 12 parsecs...', + "The cake is not a lie, it's just still loading...": + "The cake is not a lie, it's just still loading...", + 'Fiddling with the character creation screen...': + 'Fiddling with the character creation screen...', + "Just a moment, I'm finding the right meme...": + "Just a moment, I'm finding the right meme...", + "Pressing 'A' to continue...": "Pressing 'A' to continue...", + 'Herding digital cats...': 'Herding digital cats...', + 'Polishing the pixels...': 'Polishing the pixels...', + 'Finding a suitable loading screen pun...': + 'Finding a suitable loading screen pun...', + 'Distracting you with this witty phrase...': + 'Distracting you with this witty phrase...', + 'Almost there... probably...': 'Almost there... probably...', + 'Our hamsters are working as fast as they can...': + 'Our hamsters are working as fast as they can...', + 'Giving Cloudy a pat on the head...': 'Giving Cloudy a pat on the head...', + 'Petting the cat...': 'Petting the cat...', + 'Rickrolling my boss...': 'Rickrolling my boss...', + 'Never gonna give you up, never gonna let you down...': + 'Never gonna give you up, never gonna let you down...', + 'Slapping the bass...': 'Slapping the bass...', + 'Tasting the snozberries...': 'Tasting the snozberries...', + "I'm going the distance, I'm going for speed...": + "I'm going the distance, I'm going for speed...", + 'Is this the real life? Is this just fantasy?...': + 'Is this the real life? Is this just fantasy?...', + "I've got a good feeling about this...": + "I've got a good feeling about this...", + 'Poking the bear...': 'Poking the bear...', + 'Doing research on the latest memes...': + 'Doing research on the latest memes...', + 'Figuring out how to make this more witty...': + 'Figuring out how to make this more witty...', + 'Hmmm... let me think...': 'Hmmm... let me think...', + 'What do you call a fish with no eyes? A fsh...': + 'What do you call a fish with no eyes? A fsh...', + 'Why did the computer go to therapy? It had too many bytes...': + 'Why did the computer go to therapy? It had too many bytes...', + "Why don't programmers like nature? It has too many bugs...": + "Why don't programmers like nature? It has too many bugs...", + 'Why do programmers prefer dark mode? Because light attracts bugs...': + 'Why do programmers prefer dark mode? Because light attracts bugs...', + 'Why did the developer go broke? Because they used up all their cache...': + 'Why did the developer go broke? Because they used up all their cache...', + "What can you do with a broken pencil? Nothing, it's pointless...": + "What can you do with a broken pencil? Nothing, it's pointless...", + 'Applying percussive maintenance...': 'Applying percussive maintenance...', + 'Searching for the correct USB orientation...': + 'Searching for the correct USB orientation...', + 'Ensuring the magic smoke stays inside the wires...': + 'Ensuring the magic smoke stays inside the wires...', + 'Rewriting in Rust for no particular reason...': + 'Rewriting in Rust for no particular reason...', + 'Trying to exit Vim...': 'Trying to exit Vim...', + 'Spinning up the hamster wheel...': 'Spinning up the hamster wheel...', + "That's not a bug, it's an undocumented feature...": + "That's not a bug, it's an undocumented feature...", + 'Engage.': 'Engage.', + "I'll be back... with an answer.": "I'll be back... with an answer.", + 'My other process is a TARDIS...': 'My other process is a TARDIS...', + 'Communing with the machine spirit...': + 'Communing with the machine spirit...', + 'Letting the thoughts marinate...': 'Letting the thoughts marinate...', + 'Just remembered where I put my keys...': + 'Just remembered where I put my keys...', + 'Pondering the orb...': 'Pondering the orb...', + "I've seen things you people wouldn't believe... like a user who reads loading messages.": + "I've seen things you people wouldn't believe... like a user who reads loading messages.", + 'Initiating thoughtful gaze...': 'Initiating thoughtful gaze...', + "What's a computer's favorite snack? Microchips.": + "What's a computer's favorite snack? Microchips.", + "Why do Java developers wear glasses? Because they don't C#.": + "Why do Java developers wear glasses? Because they don't C#.", + 'Charging the laser... pew pew!': 'Charging the laser... pew pew!', + 'Dividing by zero... just kidding!': 'Dividing by zero... just kidding!', + 'Looking for an adult superviso... I mean, processing.': + 'Looking for an adult superviso... I mean, processing.', + 'Making it go beep boop.': 'Making it go beep boop.', + 'Buffering... because even AIs need a moment.': + 'Buffering... because even AIs need a moment.', + 'Entangling quantum particles for a faster response...': + 'Entangling quantum particles for a faster response...', + 'Polishing the chrome... on the algorithms.': + 'Polishing the chrome... on the algorithms.', + 'Are you not entertained? (Working on it!)': + 'Are you not entertained? (Working on it!)', + 'Summoning the code gremlins... to help, of course.': + 'Summoning the code gremlins... to help, of course.', + 'Just waiting for the dial-up tone to finish...': + 'Just waiting for the dial-up tone to finish...', + 'Recalibrating the humor-o-meter.': 'Recalibrating the humor-o-meter.', + 'My other loading screen is even funnier.': + 'My other loading screen is even funnier.', + "Pretty sure there's a cat walking on the keyboard somewhere...": + "Pretty sure there's a cat walking on the keyboard somewhere...", + 'Enhancing... Enhancing... Still loading.': + 'Enhancing... Enhancing... Still loading.', + "It's not a bug, it's a feature... of this loading screen.": + "It's not a bug, it's a feature... of this loading screen.", + 'Have you tried turning it off and on again? (The loading screen, not me.)': + 'Have you tried turning it off and on again? (The loading screen, not me.)', + 'Constructing additional pylons...': 'Constructing additional pylons...', + "New line? That's Ctrl+J.": "New line? That's Ctrl+J.", }; diff --git a/packages/cli/src/i18n/locales/zh.js b/packages/cli/src/i18n/locales/zh.js index 986600cd..d2677704 100644 --- a/packages/cli/src/i18n/locales/zh.js +++ b/packages/cli/src/i18n/locales/zh.js @@ -52,6 +52,25 @@ export default { 'for help on Qwen Code': '获取 Qwen Code 帮助', 'show version info': '显示版本信息', 'submit a bug report': '提交错误报告', + 'About Qwen Code': '关于 Qwen Code', + + // ============================================================================ + // System Information Fields + // ============================================================================ + 'CLI Version': 'CLI 版本', + 'Git Commit': 'Git 提交', + Model: '模型', + Sandbox: '沙箱', + 'OS Platform': '操作系统平台', + 'OS Arch': '操作系统架构', + 'OS Release': '操作系统版本', + 'Node.js Version': 'Node.js 版本', + 'NPM Version': 'NPM 版本', + 'Session ID': '会话 ID', + 'Auth Method': '认证方式', + 'Base URL': '基础 URL', + 'Memory Usage': '内存使用', + 'IDE Client': 'IDE 客户端', // ============================================================================ // Commands - General @@ -566,4 +585,172 @@ export default { '的输入令牌来自缓存,降低了成本', 'Tip: For a full token breakdown, run `/stats model`.': '提示:要查看完整的令牌明细,请运行 `/stats model`', + + // ============================================================================ + // Loading Phrases + // ============================================================================ + 'Waiting for user confirmation...': '等待用户确认...', + '(esc to cancel, {{time}})': '(按 esc 取消,{{time}})', + "I'm Feeling Lucky": '我感觉很幸运', + 'Shipping awesomeness... ': '正在运送精彩内容... ', + 'Painting the serifs back on...': '正在重新绘制衬线...', + 'Navigating the slime mold...': '正在导航粘液霉菌...', + 'Consulting the digital spirits...': '正在咨询数字精灵...', + 'Reticulating splines...': '正在网格化样条曲线...', + 'Warming up the AI hamsters...': '正在预热 AI 仓鼠...', + 'Asking the magic conch shell...': '正在询问魔法海螺壳...', + 'Generating witty retort...': '正在生成机智的反驳...', + 'Polishing the algorithms...': '正在打磨算法...', + "Don't rush perfection (or my code)...": '不要急于追求完美(或我的代码)...', + 'Brewing fresh bytes...': '正在酿造新鲜字节...', + 'Counting electrons...': '正在计算电子...', + 'Engaging cognitive processors...': '正在启动认知处理器...', + 'Checking for syntax errors in the universe...': + '正在检查宇宙中的语法错误...', + 'One moment, optimizing humor...': '稍等片刻,正在优化幽默感...', + 'Shuffling punchlines...': '正在洗牌笑点...', + 'Untangling neural nets...': '正在解开神经网络...', + 'Compiling brilliance...': '正在编译智慧...', + 'Loading wit.exe...': '正在加载 wit.exe...', + 'Summoning the cloud of wisdom...': '正在召唤智慧云...', + 'Preparing a witty response...': '正在准备机智的回复...', + "Just a sec, I'm debugging reality...": '稍等片刻,我正在调试现实...', + 'Confuzzling the options...': '正在混淆选项...', + 'Tuning the cosmic frequencies...': '正在调谐宇宙频率...', + 'Crafting a response worthy of your patience...': + '正在制作值得您耐心等待的回复...', + 'Compiling the 1s and 0s...': '正在编译 1 和 0...', + 'Resolving dependencies... and existential crises...': + '正在解决依赖关系...和存在主义危机...', + 'Defragmenting memories... both RAM and personal...': + '正在整理记忆碎片...包括 RAM 和个人记忆...', + 'Rebooting the humor module...': '正在重启幽默模块...', + 'Caching the essentials (mostly cat memes)...': + '正在缓存必需品(主要是猫咪表情包)...', + 'Optimizing for ludicrous speed': '正在优化到荒谬的速度', + "Swapping bits... don't tell the bytes...": '正在交换位...不要告诉字节...', + 'Garbage collecting... be right back...': '正在垃圾回收...马上回来...', + 'Assembling the interwebs...': '正在组装互联网...', + 'Converting coffee into code...': '正在将咖啡转换为代码...', + 'Updating the syntax for reality...': '正在更新现实的语法...', + 'Rewiring the synapses...': '正在重新连接突触...', + 'Looking for a misplaced semicolon...': '正在寻找放错位置的分号...', + "Greasin' the cogs of the machine...": '正在给机器的齿轮上油...', + 'Pre-heating the servers...': '正在预热服务器...', + 'Calibrating the flux capacitor...': '正在校准通量电容器...', + 'Engaging the improbability drive...': '正在启动不可能性驱动器...', + 'Channeling the Force...': '正在引导原力...', + 'Aligning the stars for optimal response...': '正在对齐星星以获得最佳回复...', + 'So say we all...': '我们都说...', + 'Loading the next great idea...': '正在加载下一个伟大的想法...', + "Just a moment, I'm in the zone...": '稍等片刻,我正进入状态...', + 'Preparing to dazzle you with brilliance...': '正在准备用智慧让您眼花缭乱...', + "Just a tick, I'm polishing my wit...": '稍等片刻,我正在打磨我的智慧...', + "Hold tight, I'm crafting a masterpiece...": '请稍等,我正在制作杰作...', + "Just a jiffy, I'm debugging the universe...": '稍等片刻,我正在调试宇宙...', + "Just a moment, I'm aligning the pixels...": '稍等片刻,我正在对齐像素...', + "Just a sec, I'm optimizing the humor...": '稍等片刻,我正在优化幽默感...', + "Just a moment, I'm tuning the algorithms...": '稍等片刻,我正在调整算法...', + 'Warp speed engaged...': '曲速已启动...', + 'Mining for more Dilithium crystals...': '正在挖掘更多二锂晶体...', + "Don't panic...": '不要惊慌...', + 'Following the white rabbit...': '正在跟随白兔...', + 'The truth is in here... somewhere...': '真相在这里...某个地方...', + 'Blowing on the cartridge...': '正在吹卡带...', + 'Loading... Do a barrel roll!': '正在加载...做个桶滚!', + 'Waiting for the respawn...': '等待重生...', + 'Finishing the Kessel Run in less than 12 parsecs...': + '正在以不到 12 秒差距完成凯塞尔航线...', + "The cake is not a lie, it's just still loading...": + '蛋糕不是谎言,只是还在加载...', + 'Fiddling with the character creation screen...': '正在摆弄角色创建界面...', + "Just a moment, I'm finding the right meme...": + '稍等片刻,我正在寻找合适的表情包...', + "Pressing 'A' to continue...": "按 'A' 继续...", + 'Herding digital cats...': '正在放牧数字猫...', + 'Polishing the pixels...': '正在打磨像素...', + 'Finding a suitable loading screen pun...': '正在寻找合适的加载屏幕双关语...', + 'Distracting you with this witty phrase...': + '正在用这个机智的短语分散您的注意力...', + 'Almost there... probably...': '快到了...可能...', + 'Our hamsters are working as fast as they can...': + '我们的仓鼠正在尽可能快地工作...', + 'Giving Cloudy a pat on the head...': '正在拍拍 Cloudy 的头...', + 'Petting the cat...': '正在抚摸猫咪...', + 'Rickrolling my boss...': '正在 Rickroll 我的老板...', + 'Never gonna give you up, never gonna let you down...': + '永远不会放弃你,永远不会让你失望...', + 'Slapping the bass...': '正在拍打低音...', + 'Tasting the snozberries...': '正在品尝 snozberries...', + "I'm going the distance, I'm going for speed...": + '我要走得更远,我要追求速度...', + 'Is this the real life? Is this just fantasy?...': + '这是真实的生活吗?还是只是幻想?...', + "I've got a good feeling about this...": '我对这个感觉很好...', + 'Poking the bear...': '正在戳熊...', + 'Doing research on the latest memes...': '正在研究最新的表情包...', + 'Figuring out how to make this more witty...': '正在想办法让这更有趣...', + 'Hmmm... let me think...': '嗯...让我想想...', + 'What do you call a fish with no eyes? A fsh...': + '没有眼睛的鱼叫什么?一条鱼...', + 'Why did the computer go to therapy? It had too many bytes...': + '为什么电脑去看心理医生?因为它有太多字节...', + "Why don't programmers like nature? It has too many bugs...": + '为什么程序员不喜欢大自然?因为虫子太多了...', + 'Why do programmers prefer dark mode? Because light attracts bugs...': + '为什么程序员喜欢暗色模式?因为光会吸引虫子...', + 'Why did the developer go broke? Because they used up all their cache...': + '为什么开发者破产了?因为他们用完了所有缓存...', + "What can you do with a broken pencil? Nothing, it's pointless...": + '你能用断了的铅笔做什么?什么都不能,因为它没有笔尖...', + 'Applying percussive maintenance...': '正在应用敲击维护...', + 'Searching for the correct USB orientation...': '正在寻找正确的 USB 方向...', + 'Ensuring the magic smoke stays inside the wires...': + '确保魔法烟雾留在电线内...', + 'Rewriting in Rust for no particular reason...': + '正在用 Rust 重写,没有特别的原因...', + 'Trying to exit Vim...': '正在尝试退出 Vim...', + 'Spinning up the hamster wheel...': '正在启动仓鼠轮...', + "That's not a bug, it's an undocumented feature...": + '这不是一个错误,这是一个未记录的功能...', + 'Engage.': '启动。', + "I'll be back... with an answer.": '我会回来的...带着答案。', + 'My other process is a TARDIS...': '我的另一个进程是 TARDIS...', + 'Communing with the machine spirit...': '正在与机器精神交流...', + 'Letting the thoughts marinate...': '让想法慢慢酝酿...', + 'Just remembered where I put my keys...': '刚刚想起我把钥匙放在哪里了...', + 'Pondering the orb...': '正在思考球体...', + "I've seen things you people wouldn't believe... like a user who reads loading messages.": + '我见过你们不会相信的事情...比如一个阅读加载消息的用户。', + 'Initiating thoughtful gaze...': '正在启动深思凝视...', + "What's a computer's favorite snack? Microchips.": + '电脑最喜欢的零食是什么?微芯片。', + "Why do Java developers wear glasses? Because they don't C#.": + '为什么 Java 开发者戴眼镜?因为他们不会 C#。', + 'Charging the laser... pew pew!': '正在给激光充电...砰砰!', + 'Dividing by zero... just kidding!': '除以零...只是开玩笑!', + 'Looking for an adult superviso... I mean, processing.': + '正在寻找成人监督...我是说,处理中。', + 'Making it go beep boop.': '让它发出哔哔声。', + 'Buffering... because even AIs need a moment.': + '正在缓冲...因为即使是 AI 也需要片刻。', + 'Entangling quantum particles for a faster response...': + '正在纠缠量子粒子以获得更快的回复...', + 'Polishing the chrome... on the algorithms.': '正在打磨铬...在算法上。', + 'Are you not entertained? (Working on it!)': '你不觉得有趣吗?(正在努力!)', + 'Summoning the code gremlins... to help, of course.': + '正在召唤代码小精灵...当然是来帮忙的。', + 'Just waiting for the dial-up tone to finish...': '只是等待拨号音结束...', + 'Recalibrating the humor-o-meter.': '正在重新校准幽默计。', + 'My other loading screen is even funnier.': '我的另一个加载屏幕更有趣。', + "Pretty sure there's a cat walking on the keyboard somewhere...": + '很确定有只猫在某个地方键盘上走...', + 'Enhancing... Enhancing... Still loading.': + '正在增强...正在增强...仍在加载。', + "It's not a bug, it's a feature... of this loading screen.": + '这不是一个错误,这是一个功能...这个加载屏幕的功能。', + 'Have you tried turning it off and on again? (The loading screen, not me.)': + '你试过把它关掉再打开吗?(加载屏幕,不是我。)', + 'Constructing additional pylons...': '正在建造额外的能量塔...', + "New line? That's Ctrl+J.": '新行?那是 Ctrl+J。', }; diff --git a/packages/cli/src/ui/components/AboutBox.tsx b/packages/cli/src/ui/components/AboutBox.tsx index fba5fb13..e04fd42c 100644 --- a/packages/cli/src/ui/components/AboutBox.tsx +++ b/packages/cli/src/ui/components/AboutBox.tsx @@ -13,6 +13,7 @@ import { getFieldValue, type SystemInfoField, } from '../../utils/systemInfoFields.js'; +import { t } from '../../i18n/index.js'; type AboutBoxProps = ExtendedSystemInfo; @@ -30,7 +31,7 @@ export const AboutBox: React.FC = (props) => { > - About Qwen Code + {t('About Qwen Code')} {fields.map((field: SystemInfoField) => ( diff --git a/packages/cli/src/ui/components/LoadingIndicator.tsx b/packages/cli/src/ui/components/LoadingIndicator.tsx index a1a1694a..5fc2c20b 100644 --- a/packages/cli/src/ui/components/LoadingIndicator.tsx +++ b/packages/cli/src/ui/components/LoadingIndicator.tsx @@ -14,6 +14,7 @@ import { GeminiRespondingSpinner } from './GeminiRespondingSpinner.js'; import { formatDuration } from '../utils/formatters.js'; import { useTerminalSize } from '../hooks/useTerminalSize.js'; import { isNarrowWidth } from '../utils/isNarrowWidth.js'; +import { t } from '../../i18n/index.js'; interface LoadingIndicatorProps { currentLoadingPhrase?: string; @@ -40,7 +41,12 @@ export const LoadingIndicator: React.FC = ({ const cancelAndTimerContent = streamingState !== StreamingState.WaitingForConfirmation - ? `(esc to cancel, ${elapsedTime < 60 ? `${elapsedTime}s` : formatDuration(elapsedTime * 1000)})` + ? t('(esc to cancel, {{time}})', { + time: + elapsedTime < 60 + ? `${elapsedTime}s` + : formatDuration(elapsedTime * 1000), + }) : null; return ( diff --git a/packages/cli/src/ui/hooks/usePhraseCycler.ts b/packages/cli/src/ui/hooks/usePhraseCycler.ts index 57b83c68..8fa878b3 100644 --- a/packages/cli/src/ui/hooks/usePhraseCycler.ts +++ b/packages/cli/src/ui/hooks/usePhraseCycler.ts @@ -4,7 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, useMemo } from 'react'; +import { t } from '../../i18n/index.js'; export const WITTY_LOADING_PHRASES = [ "I'm Feeling Lucky", @@ -151,10 +152,14 @@ export const usePhraseCycler = ( isWaiting: boolean, customPhrases?: string[], ) => { - const loadingPhrases = - customPhrases && customPhrases.length > 0 - ? customPhrases - : WITTY_LOADING_PHRASES; + // Translate all phrases at once if using default phrases + const loadingPhrases = useMemo( + () => + customPhrases && customPhrases.length > 0 + ? customPhrases + : WITTY_LOADING_PHRASES.map((phrase) => t(phrase)), + [customPhrases], + ); const [currentLoadingPhrase, setCurrentLoadingPhrase] = useState( loadingPhrases[0], @@ -163,7 +168,7 @@ export const usePhraseCycler = ( useEffect(() => { if (isWaiting) { - setCurrentLoadingPhrase('Waiting for user confirmation...'); + setCurrentLoadingPhrase(t('Waiting for user confirmation...')); if (phraseIntervalRef.current) { clearInterval(phraseIntervalRef.current); phraseIntervalRef.current = null; diff --git a/packages/cli/src/utils/systemInfoFields.ts b/packages/cli/src/utils/systemInfoFields.ts index d4b959fb..66308ac2 100644 --- a/packages/cli/src/utils/systemInfoFields.ts +++ b/packages/cli/src/utils/systemInfoFields.ts @@ -5,6 +5,7 @@ */ import type { ExtendedSystemInfo } from './systemInfo.js'; +import { t } from '../i18n/index.js'; /** * Field configuration for system information display @@ -23,59 +24,59 @@ export function getSystemInfoFields( ): SystemInfoField[] { const allFields: SystemInfoField[] = [ { - label: 'CLI Version', + label: t('CLI Version'), key: 'cliVersion', }, { - label: 'Git Commit', + label: t('Git Commit'), key: 'gitCommit', }, { - label: 'Model', + label: t('Model'), key: 'modelVersion', }, { - label: 'Sandbox', + label: t('Sandbox'), key: 'sandboxEnv', }, { - label: 'OS Platform', + label: t('OS Platform'), key: 'osPlatform', }, { - label: 'OS Arch', + label: t('OS Arch'), key: 'osArch', }, { - label: 'OS Release', + label: t('OS Release'), key: 'osRelease', }, { - label: 'Node.js Version', + label: t('Node.js Version'), key: 'nodeVersion', }, { - label: 'NPM Version', + label: t('NPM Version'), key: 'npmVersion', }, { - label: 'Session ID', + label: t('Session ID'), key: 'sessionId', }, { - label: 'Auth Method', + label: t('Auth Method'), key: 'selectedAuthType', }, { - label: 'Base URL', + label: t('Base URL'), key: 'baseUrl', }, { - label: 'Memory Usage', + label: t('Memory Usage'), key: 'memoryUsage', }, { - label: 'IDE Client', + label: t('IDE Client'), key: 'ideClient', }, ];