feat: always show language selector on /start, add change_language button in profile

- /start now always shows language picker (removed language_set check)
- Added 'Change Language' button in profile inline keyboard
- Added handleChangeLanguage callback handler
- Added profile.change_language locale key in en/es/de
- Registered change_language callback route
This commit is contained in:
NW
2026-06-25 23:06:58 +01:00
parent 3deddbc1b1
commit 7db7a20a1d
5 changed files with 32 additions and 25 deletions

View File

@@ -79,6 +79,7 @@ ${t('profile.member_since')}: ${new Date(userStats.created_at).toLocaleDateStrin
const keyboard = { const keyboard = {
inline_keyboard: [ inline_keyboard: [
[{text: t('profile.set_location'), callback_data: 'set_location'}], [{text: t('profile.set_location'), callback_data: 'set_location'}],
[{text: t('profile.change_language'), callback_data: 'change_language'}],
[{text: t('profile.delete_account'), callback_data: 'delete_account'}] [{text: t('profile.delete_account'), callback_data: 'delete_account'}]
] ]
}; };
@@ -104,33 +105,13 @@ ${t('profile.member_since')}: ${new Date(userStats.created_at).toLocaleDateStrin
username: username username: username
}); });
const user = await UserService.getUserByTelegramId(telegramId);
const lang = user?.language;
if (!user?.language_set) {
const keyboard = {
inline_keyboard: AVAILABLE_LANGUAGES.map(code => [{
text: LANGUAGE_NAMES[code],
callback_data: `set_language_${code}`
}])
};
await bot.sendMessage(chatId, tForUser('en')('bot.language_select'), { reply_markup: keyboard });
return;
}
const t = tForUser(lang);
const keyboard = { const keyboard = {
reply_markup: { inline_keyboard: AVAILABLE_LANGUAGES.map(code => [{
keyboard: [ text: LANGUAGE_NAMES[code],
[t('keyboard.products'), t('keyboard.profile')], callback_data: `set_language_${code}`
[t('keyboard.purchases'), t('keyboard.wallets')] }])
],
resize_keyboard: true
}
}; };
await bot.sendMessage(chatId, tForUser('en')('bot.language_select'), { reply_markup: keyboard });
await bot.sendMessage(chatId, t('bot.welcome'), keyboard);
} catch (error) { } catch (error) {
logger.error({ err: error }, 'Error in handleStart'); logger.error({ err: error }, 'Error in handleStart');
const fallbackT = tForUser('en'); const fallbackT = tForUser('en');
@@ -172,6 +153,25 @@ ${t('profile.member_since')}: ${new Date(userStats.created_at).toLocaleDateStrin
} }
} }
static async handleChangeLanguage(callbackQuery) {
const chatId = callbackQuery.message.chat.id;
const user = callbackQuery.message.__user || await UserService.getUserByTelegramId(callbackQuery.from.id);
const currentLang = user?.language || 'en';
const keyboard = {
inline_keyboard: AVAILABLE_LANGUAGES.map(code => [{
text: LANGUAGE_NAMES[code],
callback_data: `set_language_${code}`
}])
};
try {
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
} catch {}
await bot.sendMessage(chatId, tForUser(currentLang)('bot.language_select'), { reply_markup: keyboard });
}
static async handleLanguageCommand(msg) { static async handleLanguageCommand(msg) {
const chatId = msg.chat.id; const chatId = msg.chat.id;

View File

@@ -23,6 +23,7 @@
"available_balance": "Verfügbares Guthaben", "available_balance": "Verfügbares Guthaben",
"member_since": "📅 Mitglied seit", "member_since": "📅 Mitglied seit",
"set_location": "📍 Standort festlegen", "set_location": "📍 Standort festlegen",
"change_language": "🌐 Sprache ändern",
"delete_account": "❌ Konto löschen", "delete_account": "❌ Konto löschen",
"error_loading": "Fehler beim Laden des Profils. Bitte versuche es erneut." "error_loading": "Fehler beim Laden des Profils. Bitte versuche es erneut."
}, },

View File

@@ -23,6 +23,7 @@
"available_balance": "Available Balance", "available_balance": "Available Balance",
"member_since": "📅 Member since", "member_since": "📅 Member since",
"set_location": "📍 Set Location", "set_location": "📍 Set Location",
"change_language": "🌐 Change Language",
"delete_account": "❌ Delete Account", "delete_account": "❌ Delete Account",
"error_loading": "Error loading profile. Please try again." "error_loading": "Error loading profile. Please try again."
}, },

View File

@@ -23,6 +23,7 @@
"available_balance": "Saldo disponible", "available_balance": "Saldo disponible",
"member_since": "📅 Miembro desde", "member_since": "📅 Miembro desde",
"set_location": "📍 Establecer ubicación", "set_location": "📍 Establecer ubicación",
"change_language": "🌐 Cambiar idioma",
"delete_account": "❌ Eliminar cuenta", "delete_account": "❌ Eliminar cuenta",
"error_loading": "Error al cargar perfil. Inténtalo de nuevo." "error_loading": "Error al cargar perfil. Inténtalo de nuevo."
}, },

View File

@@ -86,6 +86,10 @@ export function registerRoutes() {
logDebug(cq.data, 'handleSetLocation'); logDebug(cq.data, 'handleSetLocation');
await userLocationHandler.handleSetLocation(cq); await userLocationHandler.handleSetLocation(cq);
}); });
callbackRouter.registerExact('change_language', async (cq) => {
logDebug(cq.data, 'handleChangeLanguage');
await userHandler.handleChangeLanguage(cq);
});
callbackRouter.registerExact('back_to_profile', async (cq) => { callbackRouter.registerExact('back_to_profile', async (cq) => {
logDebug(cq.data, 'handleBackToProfile'); logDebug(cq.data, 'handleBackToProfile');
await userHandler.handleBackToProfile(cq); await userHandler.handleBackToProfile(cq);