From 0c79360793cbf5a0e36a4b77d589c66271cb9cf1 Mon Sep 17 00:00:00 2001 From: jack Date: Sat, 1 May 2004 18:59:13 +0000 Subject: changed chc.c to i18n version git-svn-id: http://opensvn.csie.org/pttbbs/branches/Jaky.i18n@1912 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- mbbsd/chat.c | 95 +++++++++++++++++++++---------------------- mbbsd/chc.c | 129 ++++++++++++++++++++++++----------------------------------- 2 files changed, 101 insertions(+), 123 deletions(-) (limited to 'mbbsd') diff --git a/mbbsd/chat.c b/mbbsd/chat.c index f94cfc5f..2c550820 100644 --- a/mbbsd/chat.c +++ b/mbbsd/chat.c @@ -18,7 +18,7 @@ printchatline(char *str) } outs(str); outc('\n'); - outs("→"); + outs(SHM->i18nstr[cuser.language][658]); if (flog) fprintf(flog, "%s\n", str); @@ -34,7 +34,7 @@ chat_clear() move(b_lines, 0); clrtoeol(); move(chatline = 2, 0); - outs("→"); + outs(SHM->i18nstr[cuser.language][659]); } static void @@ -92,7 +92,7 @@ chat_recv(int fd, char chatroom[IDLEN], char *chatid) case 't': move(0, 0); clrtoeol(); - prints("\033[1;37;46m 談天室 [%-12s] \033[45m 話題:%-48s\033[m", + prints(SHM->i18nstr[cuser.language][660], chatroom, bptr + 2); } } else @@ -131,7 +131,7 @@ printuserent(userinfo_t * uentp) uentp->invisible ? '#' : ' ', modestring(uentp, 1)); if (cnt < 2) - strcat(pline, "│"); + strcat(pline, SHM->i18nstr[cuser.language][661]); strcat(uline, pline); if (++cnt == 3) { printchatline(uline); @@ -154,30 +154,30 @@ static void chat_help(char *arg) { if (strstr(arg, " op")) { - printchatline("談天室管理員專用指令"); - chathelp("[/f]lag [+-][ls]", "設定鎖定、秘密狀態"); - chathelp("[/i]nvite ", "邀請 加入談天室"); - chathelp("[/k]ick ", "將 踢出談天室"); - chathelp("[/o]p ", "將 Op 的權力轉移給 "); - chathelp("[/t]opic ", "換個話題"); - chathelp("[/w]all", "廣播 (站長專用)"); + printchatline(SHM->i18nstr[cuser.language][662]); + chathelp("[/f]lag [+-][ls]", SHM->i18nstr[cuser.language][663]); + chathelp("[/i]nvite ", SHM->i18nstr[cuser.language][664]); + chathelp("[/k]ick ", SHM->i18nstr[cuser.language][665]); + chathelp("[/o]p ", SHM->i18nstr[cuser.language][666]); + chathelp("[/t]opic ", SHM->i18nstr[cuser.language][667]); + chathelp("[/w]all", SHM->i18nstr[cuser.language][668]); } else { - chathelp("[//]help", "MUD-like 社交動詞"); - chathelp("[/.]help", "chicken 鬥雞用指令"); - chathelp("[/h]elp op", "談天室管理員專用指令"); - chathelp("[/a]ct ", "做一個動作"); - chathelp("[/b]ye [msg]", "道別"); - chathelp("[/c]lear", "清除螢幕"); - chathelp("[/j]oin ", "建立或加入談天室"); - chathelp("[/l]ist [room]", "列出談天室使用者"); - chathelp("[/m]sg ", "跟 說悄悄話"); - chathelp("[/n]ick ", "將談天代號換成 "); - chathelp("[/p]ager", "切換呼叫器"); - chathelp("[/q]uery", "查詢網友"); - chathelp("[/r]oom", "列出一般談天室"); - chathelp("[/u]sers", "列出站上使用者"); - chathelp("[/w]ho", "列出本談天室使用者"); - chathelp("[/w]hoin ", "列出談天室 的使用者"); + chathelp("[//]help", SHM->i18nstr[cuser.language][669]); + chathelp("[/.]help", SHM->i18nstr[cuser.language][670]); + chathelp("[/h]elp op", SHM->i18nstr[cuser.language][671]); + chathelp("[/a]ct ", SHM->i18nstr[cuser.language][672]); + chathelp("[/b]ye [msg]", SHM->i18nstr[cuser.language][673]); + chathelp("[/c]lear", SHM->i18nstr[cuser.language][674]); + chathelp("[/j]oin ", SHM->i18nstr[cuser.language][675]); + chathelp("[/l]ist [room]", SHM->i18nstr[cuser.language][676]); + chathelp("[/m]sg ", SHM->i18nstr[cuser.language][677]); + chathelp("[/n]ick ", SHM->i18nstr[cuser.language][678]); + chathelp("[/p]ager", SHM->i18nstr[cuser.language][679]); + chathelp("[/q]uery", SHM->i18nstr[cuser.language][680]); + chathelp("[/r]oom", SHM->i18nstr[cuser.language][681]); + chathelp("[/u]sers", SHM->i18nstr[cuser.language][682]); + chathelp("[/w]ho", SHM->i18nstr[cuser.language][683]); + chathelp("[/w]hoin ", SHM->i18nstr[cuser.language][684]); } } @@ -187,7 +187,7 @@ chat_date() char genbuf[200]; snprintf(genbuf, sizeof(genbuf), - "◆ " BBSNAME "標準時間: %s", Cdate(&now)); + SHM->i18nstr[cuser.language][686], BBSNAME, Cdate(&now)); printchatline(genbuf); } @@ -196,8 +196,8 @@ chat_pager() { char genbuf[200]; - char *msgs[] = {"關閉", "打開", "拔掉", "防水", "好友"}; - snprintf(genbuf, sizeof(genbuf), "◆ 您的呼叫器:[%s]", + char *msgs[] = {SHM->i18nstr[cuser.language][687], SHM->i18nstr[cuser.language][688], SHM->i18nstr[cuser.language][689], SHM->i18nstr[cuser.language][690], SHM->i18nstr[cuser.language][691]}; + snprintf(genbuf, sizeof(genbuf), SHM->i18nstr[cuser.language][692], msgs[currutmp->pager = (currutmp->pager + 1) % 5]); printchatline(genbuf); } @@ -214,14 +214,14 @@ chat_query(char *arg) char buf[128], *ptr; FILE *fp; - snprintf(buf, sizeof(buf), "%s(%s) 共上站 %d 次,發表過 %d 篇文章", + snprintf(buf, sizeof(buf), SHM->i18nstr[cuser.language][693], xuser.userid, xuser.username, xuser.numlogins, xuser.numposts); printchatline(buf); snprintf(buf, sizeof(buf), - "最近(%s)從[%s]上站", Cdate(&xuser.lastlogin), - (xuser.lasthost[0] ? xuser.lasthost : "(不詳)")); + SHM->i18nstr[cuser.language][694], Cdate(&xuser.lastlogin), + (xuser.lasthost[0] ? xuser.lasthost : SHM->i18nstr[cuser.language][695])); printchatline(buf); sethomefile(buf, xuser.userid, fn_plans); @@ -241,12 +241,14 @@ chat_query(char *arg) static void chat_users() { + char buf[256]; + snprintf(buf, sizeof(buf), "%s%s%s", SHM->i18nstr[cuser.language][696], BBSNAME, SHM->i18nstr[cuser.language][697]); printchatline(""); - printchatline("【 " BBSNAME "的遊客列表 】"); + printchatline(buf); printchatline(msg_shortulist); if (apply_ulist(printuserent) == -1) - printchatline("空無一人"); + printchatline(SHM->i18nstr[cuser.language][698]); printuserent(NULL); } @@ -307,7 +309,7 @@ t_chat() int chatting = YEA; char fpath[80]; - outs(" 驅車前往 請梢候........ "); + outs(SHM->i18nstr[cuser.language][699]); if (!(h = gethostbyname("localhost"))) { perror("gethostbyname"); return -1; @@ -321,8 +323,7 @@ t_chat() sin.sin_port = htons(NEW_CHATPORT); cfd = socket(sin.sin_family, SOCK_STREAM, 0); if (connect(cfd, (struct sockaddr *) & sin, sizeof sin) != 0) { - outs("\n " - "哇! 沒人在那邊耶...要有那地方的人先去開門啦!..."); + outs(SHM->i18nstr[cuser.language][700]); system("bin/xchatd"); pressanykey(); close(cfd); @@ -330,7 +331,7 @@ t_chat() } while (1) { - getdata(b_lines - 1, 0, "請輸入聊天代號:", chatid, 9, DOECHO); + getdata(b_lines - 1, 0, SHM->i18nstr[cuser.language][701], chatid, 9, DOECHO); if(!chatid[0]) strlcpy(chatid, cuser.userid, sizeof(chatid)); chatid[8] = '\0'; @@ -347,11 +348,11 @@ t_chat() if (!strcmp(inbuf, CHAT_LOGIN_OK)) break; else if (!strcmp(inbuf, CHAT_LOGIN_EXISTS)) - ptr = "這個代號已經有人用了"; + ptr = SHM->i18nstr[cuser.language][702]; else if (!strcmp(inbuf, CHAT_LOGIN_INVALID)) - ptr = "這個代號是錯誤的"; + ptr = SHM->i18nstr[cuser.language][703]; else if (!strcmp(inbuf, CHAT_LOGIN_BOGUS)) - ptr = "請勿派遣分身進入聊天室 !!"; + ptr = SHM->i18nstr[cuser.language][704]; move(b_lines - 2, 0); outs(ptr); @@ -375,7 +376,7 @@ t_chat() move(STOP_LINE, 0); outs(msg_seperator); move(STOP_LINE, 60); - outs(" /help 查詢指令 "); + outs(SHM->i18nstr[cuser.language][705]); move(1, 0); outs(msg_seperator); print_chatid(chatid); @@ -412,7 +413,7 @@ t_chat() if (!newmail && currutmp->mailalert) { newmail = 1; - printchatline("◆ 噹!郵差又來了..."); + printchatline(SHM->i18nstr[cuser.language][706]); } if (ch == I_OTHERDATA) {/* incoming */ if (chat_recv(cfd, chatroom, chatid) == -1) { @@ -513,7 +514,7 @@ t_chat() fclose(flog); more(fpath, NA); - getdata(b_lines - 1, 0, "清除(C) 移至備忘錄(M) (C/M)?[C]", + getdata(b_lines - 1, 0, SHM->i18nstr[cuser.language][707], ans, sizeof(ans), LCECHO); if (*ans == 'm') { fileheader_t mymail; @@ -523,8 +524,8 @@ t_chat() sethomepath(genbuf, cuser.userid); stampfile(genbuf, &mymail); mymail.filemode = FILE_READ ; - strlcpy(mymail.owner, "[備.忘.錄]", sizeof(mymail.owner)); - strlcpy(mymail.title, "會議\033[1;33m記錄\033[m", sizeof(mymail.title)); + strlcpy(mymail.owner, SHM->i18nstr[cuser.language][708], sizeof(mymail.owner)); + strlcpy(mymail.title, SHM->i18nstr[cuser.language][709], sizeof(mymail.title)); sethomedir(title, cuser.userid); append_record(title, &mymail, sizeof(mymail)); Rename(fpath, genbuf); diff --git a/mbbsd/chc.c b/mbbsd/chc.c index 17cda17e..0788b96f 100644 --- a/mbbsd/chc.c +++ b/mbbsd/chc.c @@ -26,47 +26,12 @@ static chc_act_list *act_list = NULL; /* some constant variable definition */ -static const char *turn_str[2] = {"黑的", "紅的"}; - -static const char *num_str[10] = { - "", "一", "二", "三", "四", "五", "六", "七", "八", "九" -}; - -static const char *chess_str[2][8] = { - /* 0 1 2 3 4 5 6 7 */ - {" ", "將", "士", "象", "車", "馬", "包", "卒"}, - {" ", "帥", "仕", "相", "車", "傌", "炮", "兵"} -}; - -static const char *chess_brd[BRD_ROW * 2 - 1] = { - /* 0 1 2 3 4 5 6 7 8 */ - "┌─┬─┬─┬─┬─┬─┬─┬─┐", /* 0 */ - "│ │ │ │\│/│ │ │ │", - "├─┼─┼─┼─┼─┼─┼─┼─┤", /* 1 */ - "│ │ │ │/│\│ │ │ │", - "├─┼─┼─┼─┼─┼─┼─┼─┤", /* 2 */ - "│ │ │ │ │ │ │ │ │", - "├─┼─┼─┼─┼─┼─┼─┼─┤", /* 3 */ - "│ │ │ │ │ │ │ │ │", - "├─┴─┴─┴─┴─┴─┴─┴─┤", /* 4 */ - "│ 凱 達 格 藍 大 道 │", - "├─┬─┬─┬─┬─┬─┬─┬─┤", /* 5 */ - "│ │ │ │ │ │ │ │ │", - "├─┼─┼─┼─┼─┼─┼─┼─┤", /* 6 */ - "│ │ │ │ │ │ │ │ │", - "├─┼─┼─┼─┼─┼─┼─┼─┤", /* 7 */ - "│ │ │ │\│/│ │ │ │", - "├─┼─┼─┼─┼─┼─┼─┼─┤", /* 8 */ - "│ │ │ │/│\│ │ │ │", - "└─┴─┴─┴─┴─┴─┴─┴─┘" /* 9 */ -}; - -static char *hint_str[] = { - " q 認輸離開", - " p 要求和棋", - "方向鍵 移動遊標", - "Enter 選擇/移動" -}; +static char *num_str[10]; +static char *chess_str[2][8]; + +static char *chess_brd[BRD_ROW * 2 - 1]; + +static char *hint_str[4]; /* * Start of the network communication function. @@ -146,7 +111,7 @@ getstep(board_t board, rc_t *from, rc_t *to) fc = (turn == (chc_my ^ 1) ? from->c + 1 : 9 - from->c); tc = (turn == (chc_my ^ 1) ? to->c + 1 : 9 - to->c); if (from->r == to->r) - dir = "平"; + dir = SHM->i18nstr[cuser.language][758]; else { if (from->c == to->c) tc = from->r - to->r; @@ -155,9 +120,9 @@ getstep(board_t board, rc_t *from, rc_t *to) if ((turn == (chc_my ^ 1) && to->r > from->r) || (turn == chc_my && to->r < from->r)) - dir = "進"; + dir = SHM->i18nstr[cuser.language][759]; else - dir = "退"; + dir = SHM->i18nstr[cuser.language][760]; } sprintf(buf, "%s%s%s%s", chess_str[turn][CHE_P(board[from->r][from->c])], @@ -174,7 +139,7 @@ showstep(board_t board) eatten = board[chc_to.r][chc_to.c]; if (eatten) - prints(": %s%s", + prints(SHM->i18nstr[cuser.language][761], CHE_O(eatten) == 0 ? BLACK_COLOR : RED_COLOR, chess_str[CHE_O(eatten)][CHE_P(eatten)]); prints("\033[m"); @@ -188,8 +153,8 @@ chc_drawline(board_t board, chcusr_t *user1, chcusr_t *user2, int line) move(line, 0); clrtoeol(); if (line == 0) { - prints("\033[1;46m 象棋對戰 \033[45m%30s VS %-20s%10s\033[m", - user1->userid, user2->userid, chc_mode & CHC_WATCH ? "[觀棋模式]" : ""); + prints(SHM->i18nstr[cuser.language][762], + user1->userid, user2->userid, chc_mode & CHC_WATCH ? SHM->i18nstr[cuser.language][763] : ""); } else if (line >= 3 && line <= 21) { outs(" "); for (i = 0; i < 9; i++) { @@ -216,31 +181,25 @@ chc_drawline(board_t board, chcusr_t *user1, chcusr_t *user2, int line) if (line >= 3 && line < 3 + (int)dim(hint_str)) { outs(hint_str[line - 3]); } else if (line == SIDE_ROW) { - prints("\033[1m你是%s%s\033[m", + prints(SHM->i18nstr[cuser.language][764], chc_my == 0 ? BLACK_COLOR : RED_COLOR, - turn_str[chc_my]); + SHM->i18nstr[cuser.language][710 + chc_my]); } else if (line == TURN_ROW) { prints("%s%s\033[m", TURN_COLOR, - chc_my == chc_turn ? "輪到你下棋了" : "等待對方下棋"); + chc_my == chc_turn ? SHM->i18nstr[cuser.language][765] : SHM->i18nstr[cuser.language][766]); } else if (line == STEP_ROW && !chc_firststep) { showstep(board); } else if (line == TIME_ROW) { - prints("剩餘時間 %d:%02d", chc_lefttime / 60, chc_lefttime % 60); + prints(SHM->i18nstr[cuser.language][767], chc_lefttime / 60, chc_lefttime % 60); } else if (line == WARN_ROW) { outs(chc_warnmsg); } else if (line == MYWIN_ROW) { - prints("\033[1;33m%12.12s " - "\033[1;31m%2d\033[37m勝 " - "\033[34m%2d\033[37m敗 " - "\033[36m%2d\033[37m和\033[m", + prints(SHM->i18nstr[cuser.language][768], user1->userid, user1->win, user1->lose - 1, user1->tie); } else if (line == HISWIN_ROW) { - prints("\033[1;33m%12.12s " - "\033[1;31m%2d\033[37m勝 " - "\033[34m%2d\033[37m敗 " - "\033[36m%2d\033[37m和\033[m", + prints(SHM->i18nstr[cuser.language][769], user2->userid, user2->win, user2->lose - 1, user2->tie); } @@ -354,6 +313,7 @@ chc_log_poem(void) static void chc_init_board(board_t board) { + int i, j; memset(board, 0, sizeof(board_t)); board[0][4] = CHE(1, chc_my ^ 1); /* 將 */ board[0][3] = board[0][5] = CHE(2, chc_my ^ 1); /* 士 */ @@ -372,6 +332,23 @@ chc_init_board(board_t board) board[7][1] = board[7][7] = CHE(6, chc_my); /* 炮 */ board[6][0] = board[6][2] = board[6][4] = board[6][6] = board[6][8] = CHE(7, chc_my); /* 兵 */ + + for (i = 1; i < 10; i++) { + num_str[i] = SHM->i18nstr[cuser.language][711 + i]; + } + num_str[0] = ""; + + for (i = 0; i < 2; i++) + for (j = 1; j < 8; j++) { + chess_str[i][j] = SHM->i18nstr[cuser.language][720 + i * 7 + j]; + } + chess_str[0][0] = chess_str[1][0] = " "; + + for (i = 0; i < BRD_ROW * 2 - 1; i++) + chess_brd[i] = SHM->i18nstr[cuser.language][735 + i]; + + for (i = 0; i < 4; i++) + hint_str[i] = SHM->i18nstr[cuser.language][754 + i]; } static void @@ -602,7 +579,7 @@ hisplay(int s, chcusr_t *user1, chcusr_t *user2, board_t board, board_t tmpbrd) } else { if (chc_from.r == -1) { chc_hepass = 1; - strlcpy(chc_warnmsg, "\033[1;33m要求和局!\033[m", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][770], sizeof(chc_warnmsg)); chc_drawline(board, user1, user2, WARN_ROW); } else { /* 座標變換 @@ -695,7 +672,7 @@ myplay(int s, chcusr_t *user1, chcusr_t *user2, board_t board, board_t tmpbrd) chc_ipass = 1; chc_from.r = -1; chc_broadcast_send(act_list, board); - strlcpy(chc_warnmsg, "\033[1;33m要求和棋!\033[m", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][771], sizeof(chc_warnmsg)); chc_drawline(board, user1, user2, WARN_ROW); bell(); break; @@ -726,7 +703,7 @@ myplay(int s, chcusr_t *user1, chcusr_t *user2, board_t board, board_t tmpbrd) chc_drawline(board, user1, user2, LTR(chc_to.r)); endturn = 1; } else { - strlcpy(chc_warnmsg, "\033[1;33m不可以王見王\033[m", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][772], sizeof(chc_warnmsg)); bell(); chc_drawline(board, user1, user2, WARN_ROW); } @@ -756,7 +733,7 @@ mainloop(int s, chcusr_t *user1, chcusr_t *user2, board_t board, play_func_t pla chc_firststep = 0; chc_drawline(board, user1, user2, TURN_ROW); if (chc_ischeck(board, chc_turn)) { - strlcpy(chc_warnmsg, "\033[1;31m將軍!\033[m", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][773], sizeof(chc_warnmsg)); bell(); } else chc_warnmsg[0] = 0; @@ -766,15 +743,15 @@ mainloop(int s, chcusr_t *user1, chcusr_t *user2, board_t board, play_func_t pla if (chc_mode & CHC_VERSUS) { if (endgame == 1) { - strlcpy(chc_warnmsg, "對方認輸了!", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][774], sizeof(chc_warnmsg)); user1->win++; currutmp->chc_win++; } else if (endgame == 2) { - strlcpy(chc_warnmsg, "你認輸了!", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][775], sizeof(chc_warnmsg)); user1->lose++; currutmp->chc_lose++; } else { - strlcpy(chc_warnmsg, "和棋", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][776], sizeof(chc_warnmsg)); user1->tie++; currutmp->chc_tie++; } @@ -783,17 +760,17 @@ mainloop(int s, chcusr_t *user1, chcusr_t *user2, board_t board, play_func_t pla passwd_update(usernum, &cuser); } else if (chc_mode & CHC_WATCH) { - strlcpy(chc_warnmsg, "結束觀棋", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][777], sizeof(chc_warnmsg)); } else { - strlcpy(chc_warnmsg, "結束打譜", sizeof(chc_warnmsg)); + strlcpy(chc_warnmsg, SHM->i18nstr[cuser.language][778], sizeof(chc_warnmsg)); } chc_log("=> "); if (endgame == 3) - chc_log("和局"); + chc_log(SHM->i18nstr[cuser.language][779]); else{ - sprintf(buf, "%s勝\n", chc_my && endgame == 1 ? "紅" : "黑"); + sprintf(buf, SHM->i18nstr[cuser.language][780], chc_my && endgame == 1 ? SHM->i18nstr[cuser.language][781] : SHM->i18nstr[cuser.language][782]); chc_log(buf); } @@ -934,7 +911,7 @@ chc(int s, int mode) setuserfile(file, CHC_LOG); if (chc_log_open(&user1, &user2, file) < 0) - vmsg("無法紀錄棋局"); + vmsg(SHM->i18nstr[cuser.language][783]); mainloop(s, &user1, &user2, board, play_func); @@ -952,13 +929,13 @@ chc(int s, int mode) currutmp->mode = mode0; - if (getans("是否將棋譜寄回信箱?[N/y]") == 'y') { + if (getans(SHM->i18nstr[cuser.language][784]) == 'y') { char title[80]; sprintf(title, "%s V.S. %s", user1.userid, user2.userid); chc_log("\n--\n\n"); chc_log_poem(); chc_log_close(); - mail_id(cuser.userid, title, file, "[楚河漢界]"); + mail_id(cuser.userid, title, file, SHM->i18nstr[cuser.language][785]); } else chc_log_close(); @@ -971,7 +948,7 @@ chc_init_utmp(void) char uident[16]; userinfo_t *uin; - stand_title("楚河漢界之爭"); + stand_title(SHM->i18nstr[cuser.language][786]); generalnamecomplete(msg_uid, uident, sizeof(uident), SHM->UTMPnumber, completeutmp_compar, @@ -1022,11 +999,11 @@ chc_watch(void) if (uin->uid == currutmp->uid || uin->mode != CHC) return -1; - if (getans("是否進行觀棋? [N/y]") != 'y') + if (getans(SHM->i18nstr[cuser.language][787]) != 'y') return 0; if ((sock = make_connection_to_somebody(uin, 10)) < 0) { - vmsg("無法建立連線"); + vmsg(SHM->i18nstr[cuser.language][788]); return -1; } msgsock = accept(sock, (struct sockaddr *) 0, (socklen_t *) 0); -- cgit v1.2.3