diff --git a/packages/cli/src/i18n/index.ts b/packages/cli/src/i18n/index.ts index 2bcc4223b..1338fb571 100644 --- a/packages/cli/src/i18n/index.ts +++ b/packages/cli/src/i18n/index.ts @@ -18,10 +18,11 @@ export { getLanguageNameFromLocale }; // State let currentLanguage: SupportedLanguage = 'en'; -let translations: Record = {}; +let translations: Record = {}; // Cache -type TranslationDict = Record; +type TranslationValue = string | string[]; +type TranslationDict = Record; const translationCache: Record = {}; const loadingPromises: Record> = {}; @@ -231,9 +232,25 @@ export function getCurrentLanguage(): SupportedLanguage { export function t(key: string, params?: Record): string { const translation = translations[key] ?? key; + if (Array.isArray(translation)) { + return key; + } return interpolate(translation, params); } +/** + * Get a translation that is an array of strings. + * @param key The translation key + * @returns The array of strings, or an empty array if not found or not an array + */ +export function ta(key: string): string[] { + const translation = translations[key]; + if (Array.isArray(translation)) { + return translation; + } + return []; +} + export async function initializeI18n( lang?: SupportedLanguage | 'auto', ): Promise { diff --git a/packages/cli/src/i18n/locales/en.js b/packages/cli/src/i18n/locales/en.js index 2682c8fcb..a57839484 100644 --- a/packages/cli/src/i18n/locales/en.js +++ b/packages/cli/src/i18n/locales/en.js @@ -927,192 +927,138 @@ export default { // ============================================================================ '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)...": + + // ============================================================================ + // Loading Phrases + // ============================================================================ + WITTY_LOADING_PHRASES: [ + "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...', + 'Asking the magic conch shell...', + 'Generating witty retort...', + 'Polishing the algorithms...', "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...': + 'Brewing fresh bytes...', + 'Counting electrons...', + 'Engaging cognitive processors...', '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...": + 'One moment, optimizing humor...', + 'Shuffling punchlines...', + 'Untangling neural nets...', + 'Compiling brilliance...', + 'Loading wit.exe...', + 'Summoning the cloud of wisdom...', + 'Preparing a witty response...', "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...': + 'Confuzzling the options...', + 'Tuning the cosmic frequencies...', 'Crafting a response worthy of your patience...', - 'Compiling the 1s and 0s...': 'Compiling the 1s and 0s...', - 'Resolving dependencies... and existential crises...': + 'Compiling the 1s and 0s...', '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)...': + 'Rebooting the humor module...', 'Caching the essentials (mostly cat memes)...', - 'Optimizing for ludicrous speed': 'Optimizing for ludicrous speed', - "Swapping bits... don't tell the bytes...": + 'Optimizing for ludicrous speed', "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...': + '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...": "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...': + "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...': '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...': + '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...": "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...': + 'Warp speed engaged...', '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...': + "Don't panic...", + 'Following the white rabbit...', '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...': + 'Blowing on the cartridge...', + 'Loading... Do a barrel roll!', + 'Waiting for the respawn...', '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...': + "Pressing 'A' to continue...", + 'Herding digital cats...', + 'Polishing the pixels...', '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...': + 'Almost there... probably...', '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...': + 'Giving Cloudy a pat on the head...', + 'Petting the cat...', + 'Rickrolling my boss...', '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...": + 'Slapping the bass...', + 'Tasting the snozberries...', "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...': + 'Poking the bear...', '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...': + '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 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...': + 'Applying percussive maintenance...', '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...": + 'Trying to exit Vim...', + 'Spinning up the hamster wheel...', "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...': + 'Engage.', + "I'll be back... with an answer.", + 'My other process is a TARDIS...', 'Communing with the machine spirit...', - 'Letting the thoughts marinate...': 'Letting the thoughts marinate...', - 'Just remembered where I put my keys...': + 'Letting the thoughts marinate...', '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.": + 'Pondering the orb...', "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.": + 'Initiating thoughtful gaze...', "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.': + 'Charging the laser... pew pew!', + 'Dividing by zero... just kidding!', '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.': + 'Making it go beep boop.', '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.': + 'Recalibrating the humor-o-meter.', '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...', + 'Constructing additional pylons...', + ], }; diff --git a/packages/cli/src/i18n/locales/ru.js b/packages/cli/src/i18n/locales/ru.js index 279c92542..a35f06e48 100644 --- a/packages/cli/src/i18n/locales/ru.js +++ b/packages/cli/src/i18n/locales/ru.js @@ -945,179 +945,140 @@ export default { '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...': 'Разогреваем ИИ-хомячков...', - 'Asking the magic conch shell...': 'Спрашиваем волшебную ракушку...', - 'Generating witty retort...': 'Генерируем остроумный ответ...', - 'Polishing the algorithms...': 'Полируем алгоритмы...', - "Don't rush perfection (or my code)...": + + // ============================================================================ + + // ============================================================================ + // Loading Phrases + // ============================================================================ + WITTY_LOADING_PHRASES: [ + 'Мне повезёт!', + 'Доставляем крутизну... ', + 'Рисуем засечки на буквах...', + 'Пробираемся через слизевиков..', + 'Советуемся с цифровыми духами...', + 'Сглаживание сплайнов...', + 'Разогреваем ИИ-хомячков...', + 'Спрашиваем волшебную ракушку...', + 'Генерируем остроумный ответ...', + 'Полируем алгоритмы...', 'Не торопите совершенство (или мой код)...', - '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...': 'Загружаем yumor.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...': + 'Секундочку, оптимизируем юмор...', + 'Перетасовываем панчлайны...', + 'Распутаваем нейросети...', + 'Компилируем гениальность...', + 'Загружаем yumor.exe...', + 'Призываем облако мудрости...', + 'Готовим остроумный ответ...', + 'Секунду, идёт отладка реальности...', + 'Запутываем варианты...', + 'Настраиваем космические частоты...', 'Создаем ответ, достойный вашего терпения...', - 'Compiling the 1s and 0s...': 'Компилируем единички и нолики...', - 'Resolving dependencies... and existential crises...': + 'Компилируем единички и нолики...', 'Разрешаем зависимости... и экзистенциальные кризисы...', - 'Defragmenting memories... both RAM and personal...': 'Дефрагментация памяти... и оперативной, и личной...', - '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...': + "Нажимаем 'A' для продолжения...", + 'Пасём цифровых котов...', + 'Полируем пиксели...', 'Ищем подходящий каламбур для экрана загрузки...', - '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...': 'Гладим Облачко по голове...', - 'Petting the cat...': 'Гладим кота...', - '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...': 'Лабаем бас-гитару...', - 'Tasting the snozberries...': 'Пробуем снузберри на вкус...', - "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...": 'У меня хорошее предчувствие...', - '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...': + 'Провожу настройку методом тыка...', 'Ищем, какой стороной вставлять флешку...', - '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...': 'Мой другой процесс — это ТАРДИС...', - 'Communing with the machine spirit...': 'Общаемся с духом машины...', - 'Letting the thoughts marinate...': 'Даем мыслям замариноваться...', - 'Just remembered where I put my keys...': + 'Пытаемся выйти из Vim...', + 'Раскручиваем колесо для хомяка...', + 'Это не баг, а фича...', + 'Поехали!', + 'Я вернусь... с ответом.', + 'Мой другой процесс — это ТАРДИС...', + 'Общаемся с духом машины...', + 'Даем мыслям замариноваться...', 'Только что вспомнил, куда положил ключи...', - '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-разработчики не убираются дома? Они ждут сборщик мусора...', - '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.': + 'Делаем бип-буп.', 'Буферизация... даже ИИ нужно время подумать.', - '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...': 'Ждем, пока закончится звук dial-up модема...', - '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...': 'Нужно построить больше пилонов...', + 'Нужно построить больше пилонов...', + ], }; diff --git a/packages/cli/src/i18n/locales/zh.js b/packages/cli/src/i18n/locales/zh.js index b8f49a776..f78d94e43 100644 --- a/packages/cli/src/i18n/locales/zh.js +++ b/packages/cli/src/i18n/locales/zh.js @@ -880,165 +880,39 @@ export default { // ============================================================================ '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...': '正在建造额外的能量塔...', + WITTY_LOADING_PHRASES: [ + // --- 职场搬砖系列 --- + '正在努力搬砖,请稍候...', + '老板在身后,快加载啊!', + '头发掉光前,一定能加载完...', + '服务器正在深呼吸,准备放大招...', + '正在向服务器投喂咖啡...', + + // --- 大厂黑话系列 --- + '正在赋能全链路,寻找关键抓手...', + '正在降本增效,优化加载路径...', + '正在打破部门壁垒,沉淀方法论...', + '正在拥抱变化,迭代核心价值...', + '正在对齐颗粒度,打磨底层逻辑...', + '大力出奇迹,正在强行加载...', + + // --- 程序员自嘲系列 --- + '只要我不写代码,代码就没有 Bug...', + '正在把 Bug 转化为 Feature...', + '只要我不尴尬,Bug 就追不上我...', + '正在试图理解去年的自己写了什么...', + '正在猿力觉醒中,请耐心等待...', + + // --- 合作愉快系列 --- + '正在询问产品经理:这需求是真的吗?', + '正在给产品经理画饼,请稍等...', + + // --- 温暖治愈系列 --- + '每一行代码,都在努力让世界变得更好一点点...', + '每一个伟大的想法,都值得这份耐心的等待...', + '别急,美好的事物总是需要一点时间去酝酿...', + '愿你的代码永无 Bug,愿你的梦想终将成真...', + '哪怕只有 0.1% 的进度,也是在向目标靠近...', + '加载的是字节,承载的是对技术的热爱...', + ], }; diff --git a/packages/cli/src/ui/hooks/useLoadingIndicator.test.ts b/packages/cli/src/ui/hooks/useLoadingIndicator.test.ts index 734a92606..0845658ed 100644 --- a/packages/cli/src/ui/hooks/useLoadingIndicator.test.ts +++ b/packages/cli/src/ui/hooks/useLoadingIndicator.test.ts @@ -8,19 +8,22 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { renderHook, act } from '@testing-library/react'; import { useLoadingIndicator } from './useLoadingIndicator.js'; import { StreamingState } from '../types.js'; -import { - WITTY_LOADING_PHRASES, - PHRASE_CHANGE_INTERVAL_MS, -} from './usePhraseCycler.js'; +import { PHRASE_CHANGE_INTERVAL_MS } from './usePhraseCycler.js'; +import * as i18n from '../../i18n/index.js'; + +const MOCK_WITTY_PHRASES = ['Phrase 1', 'Phrase 2', 'Phrase 3']; describe('useLoadingIndicator', () => { beforeEach(() => { vi.useFakeTimers(); + vi.spyOn(i18n, 'ta').mockReturnValue(MOCK_WITTY_PHRASES); + vi.spyOn(i18n, 't').mockImplementation((key) => key); }); afterEach(() => { vi.useRealTimers(); // Restore real timers after each test act(() => vi.runOnlyPendingTimers); + vi.restoreAllMocks(); }); it('should initialize with default values when Idle', () => { @@ -28,9 +31,7 @@ describe('useLoadingIndicator', () => { useLoadingIndicator(StreamingState.Idle), ); expect(result.current.elapsedTime).toBe(0); - expect(WITTY_LOADING_PHRASES).toContain( - result.current.currentLoadingPhrase, - ); + expect(MOCK_WITTY_PHRASES).toContain(result.current.currentLoadingPhrase); }); it('should reflect values when Responding', async () => { @@ -40,18 +41,14 @@ describe('useLoadingIndicator', () => { // Initial state before timers advance expect(result.current.elapsedTime).toBe(0); - expect(WITTY_LOADING_PHRASES).toContain( - result.current.currentLoadingPhrase, - ); + expect(MOCK_WITTY_PHRASES).toContain(result.current.currentLoadingPhrase); await act(async () => { await vi.advanceTimersByTimeAsync(PHRASE_CHANGE_INTERVAL_MS + 1); }); // Phrase should cycle if PHRASE_CHANGE_INTERVAL_MS has passed - expect(WITTY_LOADING_PHRASES).toContain( - result.current.currentLoadingPhrase, - ); + expect(MOCK_WITTY_PHRASES).toContain(result.current.currentLoadingPhrase); }); it('should show waiting phrase and retain elapsedTime when WaitingForConfirmation', async () => { @@ -104,9 +101,7 @@ describe('useLoadingIndicator', () => { rerender({ streamingState: StreamingState.Responding }); }); expect(result.current.elapsedTime).toBe(0); // Should reset - expect(WITTY_LOADING_PHRASES).toContain( - result.current.currentLoadingPhrase, - ); + expect(MOCK_WITTY_PHRASES).toContain(result.current.currentLoadingPhrase); await act(async () => { await vi.advanceTimersByTimeAsync(1000); @@ -130,9 +125,7 @@ describe('useLoadingIndicator', () => { }); expect(result.current.elapsedTime).toBe(0); - expect(WITTY_LOADING_PHRASES).toContain( - result.current.currentLoadingPhrase, - ); + expect(MOCK_WITTY_PHRASES).toContain(result.current.currentLoadingPhrase); // Timer should not advance await act(async () => { diff --git a/packages/cli/src/ui/hooks/usePhraseCycler.test.ts b/packages/cli/src/ui/hooks/usePhraseCycler.test.ts index 88eed68c4..420851edb 100644 --- a/packages/cli/src/ui/hooks/usePhraseCycler.test.ts +++ b/packages/cli/src/ui/hooks/usePhraseCycler.test.ts @@ -8,13 +8,17 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { renderHook, act } from '@testing-library/react'; import { usePhraseCycler, - WITTY_LOADING_PHRASES, PHRASE_CHANGE_INTERVAL_MS, } from './usePhraseCycler.js'; +import * as i18n from '../../i18n/index.js'; + +const MOCK_WITTY_PHRASES = ['Phrase 1', 'Phrase 2', 'Phrase 3']; describe('usePhraseCycler', () => { beforeEach(() => { vi.useFakeTimers(); + vi.spyOn(i18n, 'ta').mockReturnValue(MOCK_WITTY_PHRASES); + vi.spyOn(i18n, 't').mockImplementation((key) => key); }); afterEach(() => { @@ -23,7 +27,7 @@ describe('usePhraseCycler', () => { it('should initialize with a witty phrase when not active and not waiting', () => { const { result } = renderHook(() => usePhraseCycler(false, false)); - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); }); it('should show "Waiting for user confirmation..." when isWaiting is true', () => { @@ -47,35 +51,30 @@ describe('usePhraseCycler', () => { it('should cycle through witty phrases when isActive is true and not waiting', () => { const { result } = renderHook(() => usePhraseCycler(true, false)); // Initial phrase should be one of the witty phrases - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); const _initialPhrase = result.current; act(() => { vi.advanceTimersByTime(PHRASE_CHANGE_INTERVAL_MS); }); // Phrase should change and be one of the witty phrases - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); const _secondPhrase = result.current; act(() => { vi.advanceTimersByTime(PHRASE_CHANGE_INTERVAL_MS); }); - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); }); it('should reset to a witty phrase when isActive becomes true after being false (and not waiting)', () => { - // Ensure there are at least two phrases for this test to be meaningful. - if (WITTY_LOADING_PHRASES.length < 2) { - return; - } - // Mock Math.random to make the test deterministic. let callCount = 0; vi.spyOn(Math, 'random').mockImplementation(() => { // Cycle through 0, 1, 0, 1, ... const val = callCount % 2; callCount++; - return val / WITTY_LOADING_PHRASES.length; + return val / MOCK_WITTY_PHRASES.length; }); const { result, rerender } = renderHook( @@ -86,9 +85,9 @@ describe('usePhraseCycler', () => { // Activate rerender({ isActive: true, isWaiting: false }); const firstActivePhrase = result.current; - expect(WITTY_LOADING_PHRASES).toContain(firstActivePhrase); + expect(MOCK_WITTY_PHRASES).toContain(firstActivePhrase); // With our mock, this should be the first phrase. - expect(firstActivePhrase).toBe(WITTY_LOADING_PHRASES[0]); + expect(firstActivePhrase).toBe(MOCK_WITTY_PHRASES[0]); act(() => { vi.advanceTimersByTime(PHRASE_CHANGE_INTERVAL_MS); @@ -96,18 +95,18 @@ describe('usePhraseCycler', () => { // Phrase should change to the second phrase. expect(result.current).not.toBe(firstActivePhrase); - expect(result.current).toBe(WITTY_LOADING_PHRASES[1]); + expect(result.current).toBe(MOCK_WITTY_PHRASES[1]); // Set to inactive - should reset to the default initial phrase rerender({ isActive: false, isWaiting: false }); - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); // Set back to active - should pick a random witty phrase (which our mock controls) act(() => { rerender({ isActive: true, isWaiting: false }); }); // The random mock will now return 0, so it should be the first phrase again. - expect(result.current).toBe(WITTY_LOADING_PHRASES[0]); + expect(result.current).toBe(MOCK_WITTY_PHRASES[0]); }); it('should clear phrase interval on unmount when active', () => { @@ -148,7 +147,7 @@ describe('usePhraseCycler', () => { rerender({ isActive: true, isWaiting: false, customPhrases: undefined }); - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); }); it('should fall back to witty phrases if custom phrases are an empty array', () => { @@ -164,7 +163,7 @@ describe('usePhraseCycler', () => { }, ); - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); }); it('should reset to a witty phrase when transitioning from waiting to active', () => { @@ -174,16 +173,13 @@ describe('usePhraseCycler', () => { ); const _initialPhrase = result.current; - expect(WITTY_LOADING_PHRASES).toContain(_initialPhrase); + expect(MOCK_WITTY_PHRASES).toContain(_initialPhrase); // Cycle to a different phrase (potentially) act(() => { vi.advanceTimersByTime(PHRASE_CHANGE_INTERVAL_MS); }); - if (WITTY_LOADING_PHRASES.length > 1) { - // This check is probabilistic with random selection - } - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); // Go to waiting state rerender({ isActive: false, isWaiting: true }); @@ -191,6 +187,6 @@ describe('usePhraseCycler', () => { // Go back to active cycling - should pick a random witty phrase rerender({ isActive: true, isWaiting: false }); - expect(WITTY_LOADING_PHRASES).toContain(result.current); + expect(MOCK_WITTY_PHRASES).toContain(result.current); }); }); diff --git a/packages/cli/src/ui/hooks/usePhraseCycler.ts b/packages/cli/src/ui/hooks/usePhraseCycler.ts index 8fa878b3a..4aa202e6c 100644 --- a/packages/cli/src/ui/hooks/usePhraseCycler.ts +++ b/packages/cli/src/ui/hooks/usePhraseCycler.ts @@ -5,139 +5,9 @@ */ import { useState, useEffect, useRef, useMemo } from 'react'; -import { t } from '../../i18n/index.js'; +import { t, ta } from '../../i18n/index.js'; -export const WITTY_LOADING_PHRASES = [ - "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...', - '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...', - '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...', - 'Resolving dependencies... and existential crises...', - 'Defragmenting memories... both RAM and personal...', - '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...', - "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...", - '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...', - 'Petting the cat...', - 'Rickrolling my boss...', - 'Never gonna give you up, never gonna let you down...', - 'Slapping the bass...', - 'Tasting the 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...', - 'Ensuring the magic smoke stays inside the wires...', - 'Rewriting in Rust for no particular reason...', - 'Trying to exit 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...', - '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#.", - '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.', - '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.', -]; +export const WITTY_LOADING_PHRASES: string[] = ["I'm Feeling Lucky"]; export const PHRASE_CHANGE_INTERVAL_MS = 15000; @@ -152,14 +22,16 @@ export const usePhraseCycler = ( isWaiting: boolean, customPhrases?: string[], ) => { - // 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], - ); + // Get phrases from translations if available + const loadingPhrases = useMemo(() => { + if (customPhrases && customPhrases.length > 0) { + return customPhrases; + } + const translatedPhrases = ta('WITTY_LOADING_PHRASES'); + return translatedPhrases.length > 0 + ? translatedPhrases + : WITTY_LOADING_PHRASES; + }, [customPhrases]); const [currentLoadingPhrase, setCurrentLoadingPhrase] = useState( loadingPhrases[0],