#include "i18n.h" #include static bool starts_with_lang(const char *value, const char *prefix) { if (!value || !prefix) return false; while (*prefix) { if (tolower((unsigned char)*value) != tolower((unsigned char)*prefix)) { return false; } value++; prefix++; } return *value == '\0' || *value == '_' || *value == '-' || *value == '.'; } bool i18n_try_parse_lang(const char *value, help_lang_t *lang) { if (!value || value[0] == '\0') { return false; } if (starts_with_lang(value, "zh") || starts_with_lang(value, "cn") || starts_with_lang(value, "chinese")) { if (lang) *lang = LANG_ZH; return true; } if (starts_with_lang(value, "en") || starts_with_lang(value, "c") || starts_with_lang(value, "posix")) { if (lang) *lang = LANG_EN; return true; } return false; } help_lang_t i18n_parse_lang(const char *value, help_lang_t fallback) { help_lang_t lang; if (i18n_try_parse_lang(value, &lang)) { return lang; } return fallback; } help_lang_t i18n_default_lang(void) { const char *explicit_lang = getenv("TNT_LANG"); if (explicit_lang && explicit_lang[0] != '\0') { return i18n_parse_lang(explicit_lang, LANG_EN); } const char *locale = getenv("LC_ALL"); if (!locale || locale[0] == '\0') { locale = getenv("LC_MESSAGES"); } if (!locale || locale[0] == '\0') { locale = getenv("LANG"); } return i18n_parse_lang(locale, LANG_EN); } const char *i18n_lang_code(help_lang_t lang) { return lang == LANG_ZH ? "zh" : "en"; } const char *i18n_text(help_lang_t lang, i18n_text_id_t id) { if (lang == LANG_ZH) { switch (id) { case I18N_USERNAME_PROMPT: return " 请输入用户名 (留空 anonymous): "; case I18N_INVALID_USERNAME: return "用户名无效,已改用 anonymous。\r\n"; case I18N_ROOM_FULL: return "房间已满\r\n"; case I18N_INSERT_HINT_WIDE: return "Enter 发送 · Esc 浏览 · :support"; case I18N_INSERT_HINT_NARROW: return "Enter · Esc · :support"; case I18N_NORMAL_LATEST: return "G 最新"; case I18N_NORMAL_NEW_MESSAGES: return "新消息"; case I18N_HELP_TITLE: return " 帮助 "; case I18N_HELP_STATUS_FORMAT: return "-- 帮助 -- (%d/%d) j/k:滚动 g/G:首尾 e/z:语言 q:关闭"; case I18N_COMMAND_OUTPUT_TITLE: return " 命令输出 "; case I18N_MOTD_TITLE: return " 公告 "; case I18N_MOTD_CONTINUE_HINT: return " 按任意键继续 "; case I18N_TITLE_ONLINE_FORMAT: return "在线 %d"; case I18N_TITLE_MUTED: return "静音"; case I18N_TITLE_HELP_HINT: return "? 帮助"; case I18N_SYSTEM_USERNAME: return "系统"; case I18N_SYSTEM_JOIN_FORMAT: return "%s 加入了聊天室"; case I18N_SYSTEM_LEAVE_FORMAT: return "%s 离开了聊天室"; case I18N_SYSTEM_NICK_FORMAT: return "%s 更名为 %s"; case I18N_USERS_TITLE: return "在线用户"; case I18N_MSG_USAGE: return "用法: msg <用户名> <消息>\n" " w <用户名> <消息>\n"; case I18N_MSG_SENT_FORMAT: return "悄悄话已发送给 %s\n"; case I18N_MSG_USER_NOT_FOUND_FORMAT: return "未找到用户 '%s'\n"; case I18N_INBOX_TITLE: return "悄悄话"; case I18N_INBOX_EMPTY: return "(空)"; case I18N_NICK_USAGE: return "用法: nick <新用户名>\n"; case I18N_NICK_INVALID: return "用户名无效\n"; case I18N_NICK_TAKEN_FORMAT: return "昵称 '%s' 已被使用\n"; case I18N_NICK_UNCHANGED: return "昵称未变化\n"; case I18N_NICK_CHANGED_FORMAT: return "昵称已修改: %s -> %s\n"; case I18N_LAST_USAGE: return "用法: last [N] (N: 1-50,默认 10)\n"; case I18N_LAST_HEADER_FORMAT: return "--- 最近 %d 条消息 ---\n"; case I18N_SEARCH_USAGE: return "用法: search <关键词>\n"; case I18N_SEARCH_HEADER_FORMAT: return "--- 搜索: \"%s\" (%d 条匹配) ---\n"; case I18N_MUTE_JOINS_FORMAT: return "加入/离开提示: %s\n"; case I18N_MUTE_JOINS_MUTED: return "已静音"; case I18N_MUTE_JOINS_UNMUTED: return "已开启"; case I18N_CLEAR_DONE: return "命令输出已清空\n"; } } switch (id) { case I18N_USERNAME_PROMPT: return " Enter display name (blank for anonymous): "; case I18N_INVALID_USERNAME: return "Invalid username. Using 'anonymous' instead.\r\n"; case I18N_ROOM_FULL: return "Room is full\r\n"; case I18N_INSERT_HINT_WIDE: return "Enter send · Esc browse · :support"; case I18N_INSERT_HINT_NARROW: return "Enter · Esc · :support"; case I18N_NORMAL_LATEST: return "G latest"; case I18N_NORMAL_NEW_MESSAGES: return "new"; case I18N_HELP_TITLE: return " HELP "; case I18N_HELP_STATUS_FORMAT: return "-- HELP -- (%d/%d) j/k:scroll g/G:top/bottom e/z:lang q:close"; case I18N_COMMAND_OUTPUT_TITLE: return " COMMAND OUTPUT "; case I18N_MOTD_TITLE: return " NOTICE "; case I18N_MOTD_CONTINUE_HINT: return " Press any key "; case I18N_TITLE_ONLINE_FORMAT: return "online %d"; case I18N_TITLE_MUTED: return "muted"; case I18N_TITLE_HELP_HINT: return "? help"; case I18N_SYSTEM_USERNAME: return "system"; case I18N_SYSTEM_JOIN_FORMAT: return "%s joined the room"; case I18N_SYSTEM_LEAVE_FORMAT: return "%s left the room"; case I18N_SYSTEM_NICK_FORMAT: return "%s renamed to %s"; case I18N_USERS_TITLE: return "Online users"; case I18N_MSG_USAGE: return "Usage: msg \n" " w \n"; case I18N_MSG_SENT_FORMAT: return "Whisper sent to %s\n"; case I18N_MSG_USER_NOT_FOUND_FORMAT: return "User '%s' not found\n"; case I18N_INBOX_TITLE: return "Whispers"; case I18N_INBOX_EMPTY: return "(empty)"; case I18N_NICK_USAGE: return "Usage: nick \n"; case I18N_NICK_INVALID: return "Invalid username\n"; case I18N_NICK_TAKEN_FORMAT: return "Nickname '%s' is already taken\n"; case I18N_NICK_UNCHANGED: return "Nickname unchanged\n"; case I18N_NICK_CHANGED_FORMAT: return "Nickname changed: %s -> %s\n"; case I18N_LAST_USAGE: return "Usage: last [N] (N: 1-50, default 10)\n"; case I18N_LAST_HEADER_FORMAT: return "--- Last %d message(s) ---\n"; case I18N_SEARCH_USAGE: return "Usage: search \n"; case I18N_SEARCH_HEADER_FORMAT: return "--- Search: \"%s\" (%d match(es)) ---\n"; case I18N_MUTE_JOINS_FORMAT: return "Join/leave notifications: %s\n"; case I18N_MUTE_JOINS_MUTED: return "muted"; case I18N_MUTE_JOINS_UNMUTED: return "unmuted"; case I18N_CLEAR_DONE: return "Command output cleared\n"; } return ""; }