HLE: localize most - if not all - exposed strings

This commit is contained in:
Megamouse 2020-09-03 20:56:02 +02:00
parent d0ffbbfc4d
commit a2da187615
7 changed files with 289 additions and 108 deletions

View File

@ -1,4 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/localized_string.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/VFS.h" #include "Emu/VFS.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
@ -273,7 +274,7 @@ error_code cellHddGameSetSystemVer(vm::cptr<char> systemVersion)
error_code cellHddGameExitBroken() error_code cellHddGameExitBroken()
{ {
cellGame.warning("cellHddGameExitBroken()"); cellGame.warning("cellHddGameExitBroken()");
return open_exit_dialog("There has been an error!\n\nPlease reinstall the HDD boot game.", true); return open_exit_dialog(get_localized_string(localized_string_id::CELL_HDD_GAME_EXIT_BROKEN), true);
} }
error_code cellGameDataGetSizeKB(vm::ptr<u32> size) error_code cellGameDataGetSizeKB(vm::ptr<u32> size)
@ -321,7 +322,7 @@ error_code cellGameDataSetSystemVer(vm::cptr<char> systemVersion)
error_code cellGameDataExitBroken() error_code cellGameDataExitBroken()
{ {
cellGame.warning("cellGameDataExitBroken()"); cellGame.warning("cellGameDataExitBroken()");
return open_exit_dialog("There has been an error!\n\nPlease remove the game data for this title.", true); return open_exit_dialog(get_localized_string(localized_string_id::CELL_GAME_DATA_EXIT_BROKEN), true);
} }
error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGameContentSize> size, vm::ptr<char[CELL_GAME_DIRNAME_SIZE]> dirName) error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGameContentSize> size, vm::ptr<char[CELL_GAME_DIRNAME_SIZE]> dirName)
@ -1004,26 +1005,36 @@ error_code cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::cptr<char
{ {
cellGame.warning("cellGameContentErrorDialog(type=%d, errNeedSizeKB=%d, dirName=%s)", type, errNeedSizeKB, dirName); cellGame.warning("cellGameContentErrorDialog(type=%d, errNeedSizeKB=%d, dirName=%s)", type, errNeedSizeKB, dirName);
std::string errorName; std::string error_msg;
switch (type) switch (type)
{ {
case CELL_GAME_ERRDIALOG_BROKEN_GAMEDATA: errorName = "Game data is corrupted. The application will continue."; break; case CELL_GAME_ERRDIALOG_BROKEN_GAMEDATA:
case CELL_GAME_ERRDIALOG_BROKEN_HDDGAME: errorName = "HDD boot game is corrupted. The application will continue."; break; // Game data is corrupted. The application will continue.
case CELL_GAME_ERRDIALOG_NOSPACE: errorName = "Not enough available space. The application will continue."; break; error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_BROKEN_GAMEDATA);
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA: errorName = "Game data is corrupted. The application will be terminated."; break; break;
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_HDDGAME: errorName = "HDD boot game is corrupted. The application will be terminated."; break; case CELL_GAME_ERRDIALOG_BROKEN_HDDGAME:
case CELL_GAME_ERRDIALOG_NOSPACE_EXIT: errorName = "Not enough available space. The application will be terminated."; break; // HDD boot game is corrupted. The application will continue.
default: return CELL_GAME_ERROR_PARAM; error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_BROKEN_HDDGAME);
} break;
case CELL_GAME_ERRDIALOG_NOSPACE:
std::string errorMsg; // Not enough available space. The application will continue.
if (type == CELL_GAME_ERRDIALOG_NOSPACE || type == CELL_GAME_ERRDIALOG_NOSPACE_EXIT) error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_NOSPACE, fmt::format("%d", errNeedSizeKB).c_str());
{ break;
errorMsg = fmt::format("ERROR: %s\nSpace needed: %d KB", errorName, errNeedSizeKB); case CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA:
} // Game data is corrupted. The application will be terminated.
else error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_BROKEN_EXIT_GAMEDATA);
{ break;
errorMsg = fmt::format("ERROR: %s", errorName); case CELL_GAME_ERRDIALOG_BROKEN_EXIT_HDDGAME:
// HDD boot game is corrupted. The application will be terminated.
error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_BROKEN_EXIT_HDDGAME);
break;
case CELL_GAME_ERRDIALOG_NOSPACE_EXIT:
// Not enough available space. The application will be terminated.
error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_NOSPACE_EXIT, fmt::format("%d", errNeedSizeKB).c_str());
break;
default:
return CELL_GAME_ERROR_PARAM;
} }
if (dirName) if (dirName)
@ -1033,10 +1044,10 @@ error_code cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::cptr<char
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
} }
errorMsg += fmt::format("\nDirectory name: %s", dirName); error_msg += "\n" + get_localized_string(localized_string_id::CELL_GAME_ERROR_DIR_NAME, fmt::format("%s", dirName).c_str());
} }
return open_exit_dialog(errorMsg, type > CELL_GAME_ERRDIALOG_NOSPACE); return open_exit_dialog(error_msg, type > CELL_GAME_ERRDIALOG_NOSPACE);
} }
error_code cellGameThemeInstall(vm::cptr<char> usrdirPath, vm::cptr<char> fileName, u32 option) error_code cellGameThemeInstall(vm::cptr<char> usrdirPath, vm::cptr<char> fileName, u32 option)

View File

@ -349,75 +349,75 @@ error_code cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallba
{ {
cellSysutil.warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", errorCode, callback, userData, extParam); cellSysutil.warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", errorCode, callback, userData, extParam);
std::string error; localized_string_id string_id = localized_string_id::INVALID;
switch (errorCode) switch (errorCode)
{ {
case 0x80010001: error = "The resource is temporarily unavailable."; break; case 0x80010001: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010001; break; // The resource is temporarily unavailable.
case 0x80010002: error = "Invalid argument or flag."; break; case 0x80010002: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010002; break; // Invalid argument or flag.
case 0x80010003: error = "The feature is not yet implemented."; break; case 0x80010003: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010003; break; // The feature is not yet implemented.
case 0x80010004: error = "Memory allocation failed."; break; case 0x80010004: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010004; break; // Memory allocation failed.
case 0x80010005: error = "The resource with the specified identifier does not exist."; break; case 0x80010005: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010005; break; // The resource with the specified identifier does not exist.
case 0x80010006: error = "The file does not exist."; break; case 0x80010006: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010006; break; // The file does not exist.
case 0x80010007: error = "The file is in unrecognized format / The file is not a valid ELF file."; break; case 0x80010007: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010007; break; // The file is in unrecognized format / The file is not a valid ELF file.
case 0x80010008: error = "Resource deadlock is avoided."; break; case 0x80010008: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010008; break; // Resource deadlock is avoided.
case 0x80010009: error = "Operation not permitted."; break; case 0x80010009: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010009; break; // Operation not permitted.
case 0x8001000A: error = "The device or resource is busy."; break; case 0x8001000A: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001000A; break; // The device or resource is busy.
case 0x8001000B: error = "The operation is timed out."; break; case 0x8001000B: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001000B; break; // The operation is timed out.
case 0x8001000C: error = "The operation is aborted."; break; case 0x8001000C: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001000C; break; // The operation is aborted.
case 0x8001000D: error = "Invalid memory access."; break; case 0x8001000D: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001000D; break; // Invalid memory access.
case 0x8001000F: error = "State of the target thread is invalid."; break; case 0x8001000F: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001000F; break; // State of the target thread is invalid.
case 0x80010010: error = "Alignment is invalid."; break; case 0x80010010: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010010; break; // Alignment is invalid.
case 0x80010011: error = "Shortage of the kernel resources."; break; case 0x80010011: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010011; break; // Shortage of the kernel resources.
case 0x80010012: error = "The file is a directory."; break; case 0x80010012: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010012; break; // The file is a directory.
case 0x80010013: error = "Operation cancelled."; break; case 0x80010013: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010013; break; // Operation cancelled.
case 0x80010014: error = "Entry already exists."; break; case 0x80010014: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010014; break; // Entry already exists.
case 0x80010015: error = "Port is already connected."; break; case 0x80010015: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010015; break; // Port is already connected.
case 0x80010016: error = "Port is not connected."; break; case 0x80010016: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010016; break; // Port is not connected.
case 0x80010017: error = "Failure in authorizing SELF. Program authentication fail."; break; case 0x80010017: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010017; break; // Failure in authorizing SELF. Program authentication fail.
case 0x80010018: error = "The file is not MSELF."; break; case 0x80010018: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010018; break; // The file is not MSELF.
case 0x80010019: error = "System version error."; break; case 0x80010019: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010019; break; // System version error.
case 0x8001001A: error = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break; case 0x8001001A: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001001A; break; // Fatal system error occurred while authorizing SELF. SELF auth failure.
case 0x8001001B: error = "Math domain violation."; break; case 0x8001001B: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001001B; break; // Math domain violation.
case 0x8001001C: error = "Math range violation."; break; case 0x8001001C: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001001C; break; // Math range violation.
case 0x8001001D: error = "Illegal multi-byte sequence in input."; break; case 0x8001001D: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001001D; break; // Illegal multi-byte sequence in input.
case 0x8001001E: error = "File position error."; break; case 0x8001001E: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001001E; break; // File position error.
case 0x8001001F: error = "Syscall was interrupted."; break; case 0x8001001F: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001001F; break; // Syscall was interrupted.
case 0x80010020: error = "File too large."; break; case 0x80010020: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010020; break; // File too large.
case 0x80010021: error = "Too many links."; break; case 0x80010021: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010021; break; // Too many links.
case 0x80010022: error = "File table overflow."; break; case 0x80010022: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010022; break; // File table overflow.
case 0x80010023: error = "No space left on device."; break; case 0x80010023: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010023; break; // No space left on device.
case 0x80010024: error = "Not a TTY."; break; case 0x80010024: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010024; break; // Not a TTY.
case 0x80010025: error = "Broken pipe."; break; case 0x80010025: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010025; break; // Broken pipe.
case 0x80010026: error = "Read-only filesystem."; break; case 0x80010026: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010026; break; // Read-only filesystem.
case 0x80010027: error = "Illegal seek."; break; case 0x80010027: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010027; break; // Illegal seek.
case 0x80010028: error = "Arg list too long."; break; case 0x80010028: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010028; break; // Arg list too long.
case 0x80010029: error = "Access violation."; break; case 0x80010029: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010029; break; // Access violation.
case 0x8001002A: error = "Invalid file descriptor."; break; case 0x8001002A: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001002A; break; // Invalid file descriptor.
case 0x8001002B: error = "Filesystem mounting failed."; break; case 0x8001002B: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001002B; break; // Filesystem mounting failed.
case 0x8001002C: error = "Too many files open."; break; case 0x8001002C: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001002C; break; // Too many files open.
case 0x8001002D: error = "No device."; break; case 0x8001002D: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001002D; break; // No device.
case 0x8001002E: error = "Not a directory."; break; case 0x8001002E: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001002E; break; // Not a directory.
case 0x8001002F: error = "No such device or IO."; break; case 0x8001002F: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001002F; break; // No such device or IO.
case 0x80010030: error = "Cross-device link error."; break; case 0x80010030: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010030; break; // Cross-device link error.
case 0x80010031: error = "Bad Message."; break; case 0x80010031: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010031; break; // Bad Message.
case 0x80010032: error = "In progress."; break; case 0x80010032: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010032; break; // In progress.
case 0x80010033: error = "Message size error."; break; case 0x80010033: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010033; break; // Message size error.
case 0x80010034: error = "Name too long."; break; case 0x80010034: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010034; break; // Name too long.
case 0x80010035: error = "No lock."; break; case 0x80010035: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010035; break; // No lock.
case 0x80010036: error = "Not empty."; break; case 0x80010036: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010036; break; // Not empty.
case 0x80010037: error = "Not supported."; break; case 0x80010037: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010037; break; // Not supported.
case 0x80010038: error = "File-system specific error."; break; case 0x80010038: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010038; break; // File-system specific error.
case 0x80010039: error = "Overflow occured."; break; case 0x80010039: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_80010039; break; // Overflow occured.
case 0x8001003A: error = "Filesystem not mounted."; break; case 0x8001003A: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001003A; break; // Filesystem not mounted.
case 0x8001003B: error = "Not SData."; break; case 0x8001003B: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001003B; break; // Not SData.
case 0x8001003C: error = "Incorrect version in sys_load_param."; break; case 0x8001003C: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001003C; break; // Incorrect version in sys_load_param.
case 0x8001003D: error = "Pointer is null."; break; case 0x8001003D: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001003D; break; // Pointer is null.
case 0x8001003E: error = "Pointer is null."; break; case 0x8001003E: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_8001003E; break; // Pointer is null.
default: error = "An error has occurred."; break; default: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_DEFAULT; break; // An error has occurred.
} }
error.append(fmt::format("\n(%08x)", errorCode)); const std::string error = get_localized_string(string_id, fmt::format("%08x", errorCode).c_str());
return cellMsgDialogOpen2(CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK, vm::make_str(error), callback, userData, extParam); return cellMsgDialogOpen2(CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK, vm::make_str(error), callback, userData, extParam);
} }

View File

@ -244,7 +244,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
Emu.CallAfter([=, &result]() Emu.CallAfter([=, &result]()
{ {
osk->Create("On Screen Keyboard", message, osk->osk_text, maxLength, prohibitFlgs, allowOskPanelFlg, firstViewPanel); osk->Create(get_localized_string(localized_string_id::CELL_OSK_DIALOG_TITLE), message, osk->osk_text, maxLength, prohibitFlgs, allowOskPanelFlg, firstViewPanel);
result = true; result = true;
}); });

View File

@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/VFS.h" #include "Emu/VFS.h"
#include "Emu/localized_string.h"
#include "Emu/Cell/lv2/sys_fs.h" #include "Emu/Cell/lv2/sys_fs.h"
#include "Emu/Cell/lv2/sys_sync.h" #include "Emu/Cell/lv2/sys_sync.h"
#include "Emu/Cell/lv2/sys_process.h" #include "Emu/Cell/lv2/sys_process.h"
@ -199,7 +200,7 @@ static error_code select_and_delete(ppu_thread& ppu)
const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details; const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details;
// Reusable display message string // Reusable display message string
std::string msg = "Do you really want to delete this entry?\n\n" + info; std::string msg = get_localized_string(localized_string_id::CELL_SAVEDATA_DELETE_CONFIRMATION, info.c_str());
// Yield before a blocking dialog is being spawned // Yield before a blocking dialog is being spawned
lv2_obj::sleep(ppu); lv2_obj::sleep(ppu);
@ -235,7 +236,7 @@ static error_code select_and_delete(ppu_thread& ppu)
} }
// Update display message // Update display message
msg = "Successfully removed entry!\n\n" + info; msg = get_localized_string(localized_string_id::CELL_SAVEDATA_DELETE_SUCCESS, info.c_str());
cellSaveData.success("%s", msg); cellSaveData.success("%s", msg);
// Yield before blocking dialog is being spawned // Yield before blocking dialog is being spawned
@ -264,16 +265,16 @@ static error_code display_callback_result_error_message(ppu_thread& ppu, const C
switch (result.result) switch (result.result)
{ {
case CELL_SAVEDATA_CBRESULT_ERR_NOSPACE: case CELL_SAVEDATA_CBRESULT_ERR_NOSPACE:
msg = fmt::format("Error - Insufficient free space\n\nSpace needed: %d KB", result.errNeedSizeKB); msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_NO_SPACE, fmt::format("%d", result.errNeedSizeKB).c_str());
break; break;
case CELL_SAVEDATA_CBRESULT_ERR_FAILURE: case CELL_SAVEDATA_CBRESULT_ERR_FAILURE:
msg = "Error - Failed to save or load"; msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_FAILURE);
break; break;
case CELL_SAVEDATA_CBRESULT_ERR_BROKEN: case CELL_SAVEDATA_CBRESULT_ERR_BROKEN:
msg = "Error - Save data corrupted"; msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_BROKEN);
break; break;
case CELL_SAVEDATA_CBRESULT_ERR_NODATA: case CELL_SAVEDATA_CBRESULT_ERR_NODATA:
msg = "Error - Save data cannot be found"; msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_NO_DATA);
break; break;
case CELL_SAVEDATA_CBRESULT_ERR_INVALID: case CELL_SAVEDATA_CBRESULT_ERR_INVALID:
if (result.invalidMsg) if (result.invalidMsg)
@ -303,19 +304,21 @@ static error_code display_callback_result_error_message(ppu_thread& ppu, const C
return CELL_SAVEDATA_ERROR_CBRESULT; return CELL_SAVEDATA_ERROR_CBRESULT;
} }
static std::string get_confirmation_message(u32 operation) static std::string get_confirmation_message(u32 operation, const SaveDataEntry& entry)
{ {
const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details;
if (operation == SAVEDATA_OP_LIST_DELETE || operation == SAVEDATA_OP_FIXED_DELETE) if (operation == SAVEDATA_OP_LIST_DELETE || operation == SAVEDATA_OP_FIXED_DELETE)
{ {
return "Delete this entry?"; return get_localized_string(localized_string_id::CELL_SAVEDATA_DELETE, info.c_str());
} }
else if (operation == SAVEDATA_OP_LIST_LOAD || operation == SAVEDATA_OP_FIXED_LOAD) else if (operation == SAVEDATA_OP_LIST_LOAD || operation == SAVEDATA_OP_FIXED_LOAD)
{ {
return "Load this entry?"; return get_localized_string(localized_string_id::CELL_SAVEDATA_LOAD, info.c_str());
} }
else if (operation == SAVEDATA_OP_LIST_SAVE || operation == SAVEDATA_OP_FIXED_SAVE) else if (operation == SAVEDATA_OP_LIST_SAVE || operation == SAVEDATA_OP_FIXED_SAVE)
{ {
return "Overwrite this entry?"; return get_localized_string(localized_string_id::CELL_SAVEDATA_OVERWRITE, info.c_str());
} }
return ""; return "";
@ -1000,7 +1003,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
// UI returns -1 for new save games // UI returns -1 for new save games
if (selected == -1) if (selected == -1)
{ {
message = "Create new Save Data?"; message = get_localized_string(localized_string_id::CELL_SAVEDATA_CREATE_CONFIRMATION);
save_entry.dirName = listSet->newData->dirName.get_ptr(); save_entry.dirName = listSet->newData->dirName.get_ptr();
save_entry.escaped = vfs::escape(save_entry.dirName); save_entry.escaped = vfs::escape(save_entry.dirName);
} }
@ -1008,7 +1011,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
{ {
// Get information from the selected entry // Get information from the selected entry
SaveDataEntry entry = save_entries[selected]; SaveDataEntry entry = save_entries[selected];
message = get_confirmation_message(operation) + "\n\n" + entry.title + "\n" + entry.subtitle + "\n" + entry.details; message = get_confirmation_message(operation, entry);
} }
// Yield before a blocking dialog is being spawned // Yield before a blocking dialog is being spawned
@ -1128,13 +1131,13 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
if (selected == -1) if (selected == -1)
{ {
message = "Create new Save Data?"; message = get_localized_string(localized_string_id::CELL_SAVEDATA_CREATE_CONFIRMATION);
} }
else else
{ {
// Get information from the selected entry // Get information from the selected entry
SaveDataEntry entry = save_entries[selected]; SaveDataEntry entry = save_entries[selected];
message = get_confirmation_message(operation) + "\n\n" + entry.title + "\n" + entry.subtitle + "\n" + entry.details; message = get_confirmation_message(operation, entry);
} }
// Yield before a blocking dialog is being spawned // Yield before a blocking dialog is being spawned

View File

@ -446,8 +446,7 @@ namespace rsx
virtual void set_text(localized_string_id id) virtual void set_text(localized_string_id id)
{ {
this->text = get_localized_u32string(id); set_text(get_localized_u32string(id));
is_compiled = false;
} }
virtual void set_font(const char* font_name, u16 font_size) virtual void set_font(const char* font_name, u16 font_size)

View File

@ -28,6 +28,92 @@ enum class localized_string_id
RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD, RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD,
RSX_OVERLAYS_LIST_SELECT, RSX_OVERLAYS_LIST_SELECT,
RSX_OVERLAYS_LIST_CANCEL, RSX_OVERLAYS_LIST_CANCEL,
CELL_GAME_ERROR_BROKEN_GAMEDATA,
CELL_GAME_ERROR_BROKEN_HDDGAME,
CELL_GAME_ERROR_BROKEN_EXIT_GAMEDATA,
CELL_GAME_ERROR_BROKEN_EXIT_HDDGAME,
CELL_GAME_ERROR_NOSPACE,
CELL_GAME_ERROR_NOSPACE_EXIT,
CELL_GAME_ERROR_DIR_NAME,
CELL_GAME_DATA_EXIT_BROKEN,
CELL_HDD_GAME_EXIT_BROKEN,
CELL_MSG_DIALOG_ERROR_DEFAULT,
CELL_MSG_DIALOG_ERROR_80010001,
CELL_MSG_DIALOG_ERROR_80010002,
CELL_MSG_DIALOG_ERROR_80010003,
CELL_MSG_DIALOG_ERROR_80010004,
CELL_MSG_DIALOG_ERROR_80010005,
CELL_MSG_DIALOG_ERROR_80010006,
CELL_MSG_DIALOG_ERROR_80010007,
CELL_MSG_DIALOG_ERROR_80010008,
CELL_MSG_DIALOG_ERROR_80010009,
CELL_MSG_DIALOG_ERROR_8001000A,
CELL_MSG_DIALOG_ERROR_8001000B,
CELL_MSG_DIALOG_ERROR_8001000C,
CELL_MSG_DIALOG_ERROR_8001000D,
CELL_MSG_DIALOG_ERROR_8001000F,
CELL_MSG_DIALOG_ERROR_80010010,
CELL_MSG_DIALOG_ERROR_80010011,
CELL_MSG_DIALOG_ERROR_80010012,
CELL_MSG_DIALOG_ERROR_80010013,
CELL_MSG_DIALOG_ERROR_80010014,
CELL_MSG_DIALOG_ERROR_80010015,
CELL_MSG_DIALOG_ERROR_80010016,
CELL_MSG_DIALOG_ERROR_80010017,
CELL_MSG_DIALOG_ERROR_80010018,
CELL_MSG_DIALOG_ERROR_80010019,
CELL_MSG_DIALOG_ERROR_8001001A,
CELL_MSG_DIALOG_ERROR_8001001B,
CELL_MSG_DIALOG_ERROR_8001001C,
CELL_MSG_DIALOG_ERROR_8001001D,
CELL_MSG_DIALOG_ERROR_8001001E,
CELL_MSG_DIALOG_ERROR_8001001F,
CELL_MSG_DIALOG_ERROR_80010020,
CELL_MSG_DIALOG_ERROR_80010021,
CELL_MSG_DIALOG_ERROR_80010022,
CELL_MSG_DIALOG_ERROR_80010023,
CELL_MSG_DIALOG_ERROR_80010024,
CELL_MSG_DIALOG_ERROR_80010025,
CELL_MSG_DIALOG_ERROR_80010026,
CELL_MSG_DIALOG_ERROR_80010027,
CELL_MSG_DIALOG_ERROR_80010028,
CELL_MSG_DIALOG_ERROR_80010029,
CELL_MSG_DIALOG_ERROR_8001002A,
CELL_MSG_DIALOG_ERROR_8001002B,
CELL_MSG_DIALOG_ERROR_8001002C,
CELL_MSG_DIALOG_ERROR_8001002D,
CELL_MSG_DIALOG_ERROR_8001002E,
CELL_MSG_DIALOG_ERROR_8001002F,
CELL_MSG_DIALOG_ERROR_80010030,
CELL_MSG_DIALOG_ERROR_80010031,
CELL_MSG_DIALOG_ERROR_80010032,
CELL_MSG_DIALOG_ERROR_80010033,
CELL_MSG_DIALOG_ERROR_80010034,
CELL_MSG_DIALOG_ERROR_80010035,
CELL_MSG_DIALOG_ERROR_80010036,
CELL_MSG_DIALOG_ERROR_80010037,
CELL_MSG_DIALOG_ERROR_80010038,
CELL_MSG_DIALOG_ERROR_80010039,
CELL_MSG_DIALOG_ERROR_8001003A,
CELL_MSG_DIALOG_ERROR_8001003B,
CELL_MSG_DIALOG_ERROR_8001003C,
CELL_MSG_DIALOG_ERROR_8001003D,
CELL_MSG_DIALOG_ERROR_8001003E,
CELL_OSK_DIALOG_TITLE,
CELL_SAVEDATA_CB_BROKEN,
CELL_SAVEDATA_CB_FAILURE,
CELL_SAVEDATA_CB_NO_DATA,
CELL_SAVEDATA_CB_NO_SPACE,
CELL_SAVEDATA_CREATE_CONFIRMATION,
CELL_SAVEDATA_DELETE_CONFIRMATION,
CELL_SAVEDATA_DELETE_SUCCESS,
CELL_SAVEDATA_DELETE,
CELL_SAVEDATA_LOAD,
CELL_SAVEDATA_OVERWRITE,
}; };
std::string get_localized_string(localized_string_id id, const char* args = ""); std::string get_localized_string(localized_string_id id, const char* args = "");

View File

@ -34,10 +34,10 @@ private:
{ {
switch (id) switch (id)
{ {
case localized_string_id::RSX_OVERLAYS_TROPHY_BRONZE: return tr("You have earned the bronze trophy\n%0").arg(std::forward<Args>(args)...); case localized_string_id::RSX_OVERLAYS_TROPHY_BRONZE: return tr("You have earned the bronze trophy\n%0", "Trophy text").arg(std::forward<Args>(args)...);
case localized_string_id::RSX_OVERLAYS_TROPHY_SILVER: return tr("You have earned the silver trophy\n%0").arg(std::forward<Args>(args)...); case localized_string_id::RSX_OVERLAYS_TROPHY_SILVER: return tr("You have earned the silver trophy\n%0", "Trophy text").arg(std::forward<Args>(args)...);
case localized_string_id::RSX_OVERLAYS_TROPHY_GOLD: return tr("You have earned the gold trophy\n%0").arg(std::forward<Args>(args)...); case localized_string_id::RSX_OVERLAYS_TROPHY_GOLD: return tr("You have earned the gold trophy\n%0", "Trophy text").arg(std::forward<Args>(args)...);
case localized_string_id::RSX_OVERLAYS_TROPHY_PLATINUM: return tr("You have earned the platinum trophy\n%0").arg(std::forward<Args>(args)...); case localized_string_id::RSX_OVERLAYS_TROPHY_PLATINUM: return tr("You have earned the platinum trophy\n%0", "Trophy text").arg(std::forward<Args>(args)...);
case localized_string_id::RSX_OVERLAYS_COMPILING_SHADERS: return tr("Compiling shaders"); case localized_string_id::RSX_OVERLAYS_COMPILING_SHADERS: return tr("Compiling shaders");
case localized_string_id::RSX_OVERLAYS_MSG_DIALOG_YES: return tr("Yes"); case localized_string_id::RSX_OVERLAYS_MSG_DIALOG_YES: return tr("Yes");
case localized_string_id::RSX_OVERLAYS_MSG_DIALOG_NO: return tr("No"); case localized_string_id::RSX_OVERLAYS_MSG_DIALOG_NO: return tr("No");
@ -56,6 +56,88 @@ private:
case localized_string_id::RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD: return tr("[Enter Password]"); case localized_string_id::RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD: return tr("[Enter Password]");
case localized_string_id::RSX_OVERLAYS_LIST_SELECT: return tr("Select"); case localized_string_id::RSX_OVERLAYS_LIST_SELECT: return tr("Select");
case localized_string_id::RSX_OVERLAYS_LIST_CANCEL: return tr("Cancel"); case localized_string_id::RSX_OVERLAYS_LIST_CANCEL: return tr("Cancel");
case localized_string_id::CELL_GAME_ERROR_BROKEN_GAMEDATA: return tr("ERROR: Game data is corrupted. The application will continue.");
case localized_string_id::CELL_GAME_ERROR_BROKEN_HDDGAME: return tr("ERROR: HDD boot game is corrupted. The application will continue.");
case localized_string_id::CELL_GAME_ERROR_BROKEN_EXIT_GAMEDATA: return tr("ERROR: Game data is corrupted. The application will be terminated.");
case localized_string_id::CELL_GAME_ERROR_BROKEN_EXIT_HDDGAME: return tr("ERROR: HDD boot game is corrupted. The application will be terminated.");
case localized_string_id::CELL_GAME_ERROR_NOSPACE: return tr("ERROR: Not enough available space. The application will continue.\nSpace needed: %0 KB").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_GAME_ERROR_NOSPACE_EXIT: return tr("ERROR: Not enough available space. The application will be terminated.\nSpace needed: %0 KB").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_GAME_ERROR_DIR_NAME: return tr("Directory name: %0").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_GAME_DATA_EXIT_BROKEN: return tr("There has been an error!\n\nPlease remove the game data for this title.");
case localized_string_id::CELL_HDD_GAME_EXIT_BROKEN: return tr("There has been an error!\n\nPlease reinstall the HDD boot game.");
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010001: return tr("The resource is temporarily unavailable.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010002: return tr("Invalid argument or flag.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010003: return tr("The feature is not yet implemented.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010004: return tr("Memory allocation failed.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010005: return tr("The resource with the specified identifier does not exist.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010006: return tr("The file does not exist.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010007: return tr("The file is in unrecognized format / The file is not a valid ELF file.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010008: return tr("Resource deadlock is avoided.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010009: return tr("Operation not permitted.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001000A: return tr("The device or resource is busy.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001000B: return tr("The operation is timed out.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001000C: return tr("The operation is aborted.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001000D: return tr("Invalid memory access.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001000F: return tr("State of the target thread is invalid.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010010: return tr("Alignment is invalid.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010011: return tr("Shortage of the kernel resources.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010012: return tr("The file is a directory.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010013: return tr("Operation cancelled.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010014: return tr("Entry already exists.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010015: return tr("Port is already connected.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010016: return tr("Port is not connected.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010017: return tr("Failure in authorizing SELF. Program authentication fail.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010018: return tr("The file is not MSELF.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010019: return tr("System version error.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001001A: return tr("Fatal system error occurred while authorizing SELF. SELF auth failure.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001001B: return tr("Math domain violation.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001001C: return tr("Math range violation.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001001D: return tr("Illegal multi-byte sequence in input.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001001E: return tr("File position error.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001001F: return tr("Syscall was interrupted.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010020: return tr("File too large.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010021: return tr("Too many links.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010022: return tr("File table overflow.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010023: return tr("No space left on device.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010024: return tr("Not a TTY.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010025: return tr("Broken pipe.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010026: return tr("Read-only filesystem.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010027: return tr("Illegal seek.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010028: return tr("Arg list too long.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010029: return tr("Access violation.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001002A: return tr("Invalid file descriptor.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001002B: return tr("Filesystem mounting failed.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001002C: return tr("Too many files open.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001002D: return tr("No device.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001002E: return tr("Not a directory.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001002F: return tr("No such device or IO.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010030: return tr("Cross-device link error.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010031: return tr("Bad Message.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010032: return tr("In progress.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010033: return tr("Message size error.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010034: return tr("Name too long.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010035: return tr("No lock.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010036: return tr("Not empty.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010037: return tr("Not supported.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010038: return tr("File-system specific error.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_80010039: return tr("Overflow occured.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001003A: return tr("Filesystem not mounted.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001003B: return tr("Not SData.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001003C: return tr("Incorrect version in sys_load_param.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001003D: return tr("Pointer is null.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_8001003E: return tr("Pointer is null.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_MSG_DIALOG_ERROR_DEFAULT: return tr("An error has occurred.\n(%0)", "Error code").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_OSK_DIALOG_TITLE: return tr("On Screen Keyboard");
case localized_string_id::CELL_SAVEDATA_CB_BROKEN: return tr("Error - Save data corrupted");
case localized_string_id::CELL_SAVEDATA_CB_FAILURE: return tr("Error - Failed to save or load");
case localized_string_id::CELL_SAVEDATA_CB_NO_DATA: return tr("Error - Save data cannot be found");
case localized_string_id::CELL_SAVEDATA_CB_NO_SPACE: return tr("Error - Insufficient free space\n\nSpace needed: %0 KB").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_CREATE_CONFIRMATION: return tr("Create new Save Data?");
case localized_string_id::CELL_SAVEDATA_DELETE_CONFIRMATION: return tr("Do you really want to delete this entry?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_DELETE_SUCCESS: return tr("Successfully removed entry!\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_DELETE: return tr("Delete this entry?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_LOAD: return tr("Load this entry?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_OVERWRITE: return tr("Overwrite this entry?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::INVALID: return tr("Invalid"); case localized_string_id::INVALID: return tr("Invalid");
default: return tr("Unknown"); default: return tr("Unknown");