From d62e92bce17e7795bb49b0963eb0f5526ca09b37 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Wed, 7 Jan 2015 09:57:44 +0000 Subject: [PATCH] Made many more strings translatable. --- CONTRIBUTING.md | 7 ++--- resources/report/js/l10n.js | 28 +++++++++++++++---- resources/report/js/script.js | 30 ++++++++++---------- src/backend/game.cpp | 4 +-- src/backend/git.cpp | 34 +++++++++++++---------- src/gui/app.cpp | 4 +-- src/gui/handler.cpp | 52 +++++++++++++++++------------------ 7 files changed, 91 insertions(+), 68 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b26636a5..f870bbf5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,9 +51,8 @@ Some languages may use different words or phrases for different contexts where o Some strings to be translated may contain special characters. Different types of special character that may be encountered are: -* Backslashes (`\`) must be escaped using another backslash, so if you wanted to display a single backslash `\`, you would put `\\` in your translated string. -* Double-quotation marks (`"`) must be preceded by a backslash, ie. `\"`, or LOOT will crash when it tries to display the string. -* Formatting placeholders are used so that LOOT can substitute text or numbers that are generated at runtime into pre-made strings. They appear as a number surrounded by percentage signs, eg. `%1%`. If formatting placeholders are used in the untranslated string, they **must all** be present in the translated string, or LOOT will crash when it tries to display the translated string. Placeholders can be moved around so that the sentence makes grammatical sense in the target language. +* Backslashes (`\`). These are used to escape backslashes and double-quotation marks (`"`) in the C++ translation strings. Don't add new backslashes into translations, and make sure all backslashes in the original string are retained in the translation. +* Formatting placeholders are used so that LOOT can substitute text or numbers that are generated at runtime into pre-made strings. They appear as a number surrounded by percentage signs, eg. `%1%`, or as `%s`. If formatting placeholders are used in the untranslated string, they **must all** be present in the translated string, or LOOT will crash when it tries to display the translated string. Placeholders can be moved around so that the sentence makes grammatical sense in the target language. ### Adding A New Translation @@ -64,4 +63,4 @@ If you're adding a new translation, LOOT's source code must be updated to recogn * Add constants for the language in [api.h](src/api/api.h) and [api.cpp](src/api/api.cpp). * In [archive.py](src/archive.py), add the language folder to the inline list on line 68. * In [installer.nsi](src/installer.nsi), add entries for the language folder to the install and uninstall sections. -* In [LOOT Metadata Syntax.html](docs/LOOT%20Metadata%20Syntax.html), add a row for your language to the Language Codes table. \ No newline at end of file +* In [LOOT Metadata Syntax.html](docs/LOOT%20Metadata%20Syntax.html), add a row for your language to the Language Codes table. diff --git a/resources/report/js/l10n.js b/resources/report/js/l10n.js index 3929463d..fb2c5a6e 100644 --- a/resources/report/js/l10n.js +++ b/resources/report/js/l10n.js @@ -59,6 +59,7 @@ } pluginCard.getElementById('activeTick').label = l10n.translate("Active Plugin").fetch(); + pluginCard.getElementById('isMaster').label = l10n.translate("Master File").fetch(); pluginCard.getElementById('emptyPlugin').label = l10n.translate("Empty Plugin").fetch(); pluginCard.getElementById('loadsBSA').label = l10n.translate("Loads BSA").fetch(); pluginCard.getElementById('hasUserEdits').label = l10n.translate("Has User Metadata").fetch(); @@ -123,8 +124,8 @@ pluginEditor.getElementById('locations').querySelector('th:first-child').textContent = l10n.translate("URL").fetch(); pluginEditor.getElementById('locations').querySelector('th:nth-child(2)').textContent = l10n.translate("Version").fetch(); - pluginEditor.getElementById('accept').textContent = l10n.translate("Apply").fetch(); - pluginEditor.getElementById('cancel').textContent = l10n.translate("Cancel").fetch(); + pluginEditor.getElementById('accept').parentElement.label = l10n.translate("Apply").fetch(); + pluginEditor.getElementById('cancel').parentElement.label = l10n.translate("Cancel").fetch(); /* Plugin List Item Template */ var pluginItem = document.querySelector('link[rel="import"][href$="loot-plugin-item.html"]'); @@ -133,6 +134,7 @@ } else { pluginItem = document.querySelector('polymer-element[name="loot-plugin-item"]').querySelector('template').content; } + pluginItem.querySelector('#secondary core-tooltip').label = l10n.translate("Global Priority").fetch(); pluginItem.getElementById('loadsBSA').label = l10n.translate("Loads BSA").fetch(); pluginItem.getElementById('hasUserEdits').label = l10n.translate("Has User Metadata").fetch(); @@ -143,6 +145,7 @@ } else { fileRow = document.querySelector('#fileRow').content; } + fileRow.querySelector('loot-validated-input').error = l10n.translate("A filename is required.").fetch(); fileRow.querySelector('core-tooltip').label = l10n.translate("Delete Row").fetch(); /* Message row template */ @@ -155,6 +158,7 @@ messageRow.querySelector('.type').children[0].textContent = l10n.translate("Note").fetch(); messageRow.querySelector('.type').children[1].textContent = l10n.translate("Warning").fetch(); messageRow.querySelector('.type').children[2].textContent = l10n.translate("Error").fetch(); + messageRow.querySelector('loot-validated-input').error = l10n.translate("A content string is required.").fetch(); messageRow.querySelector('core-tooltip').label = l10n.translate("Delete Row").fetch(); /* Tag row template */ @@ -166,6 +170,7 @@ } tagRow.querySelector('.type').children[0].textContent = l10n.translate("Add").fetch(); tagRow.querySelector('.type').children[1].textContent = l10n.translate("Remove").fetch(); + tagRow.querySelector('loot-validated-input').error = l10n.translate("A name is required.").fetch(); tagRow.querySelector('core-tooltip').label = l10n.translate("Delete Row").fetch(); /* Dirty Info row template */ @@ -175,6 +180,11 @@ } else { dirtyInfoRow = document.querySelector('#dirtyInfoRow').content; } + dirtyInfoRow.querySelector('loot-validated-input.crc').error = l10n.translate("A CRC is required.").fetch(); + dirtyInfoRow.querySelector('loot-validated-input.itm').error = l10n.translate("Values must be integers.").fetch(); + dirtyInfoRow.querySelector('loot-validated-input.udr').error = l10n.translate("Values must be integers.").fetch(); + dirtyInfoRow.querySelector('loot-validated-input.nav').error = l10n.translate("Values must be integers.").fetch(); + dirtyInfoRow.querySelector('loot-validated-input.util').error = l10n.translate("A utility name is required.").fetch(); dirtyInfoRow.querySelector('core-tooltip').label = l10n.translate("Delete Row").fetch(); /* Location row template */ @@ -184,6 +194,7 @@ } else { locationRow = document.querySelector('#locationRow').content; } + locationRow.querySelector('loot-validated-input').error = l10n.translate("A link is required.").fetch(); locationRow.querySelector('core-tooltip').label = l10n.translate("Delete Row").fetch(); /* Game row template */ @@ -193,6 +204,8 @@ } else { gameRow = document.querySelector('#gameRow').content; } + gameRow.querySelector('loot-validated-input.name').error = l10n.translate("A name is required.").fetch(); + gameRow.querySelector('loot-validated-input.folder').error = l10n.translate("A folder is required.").fetch(); gameRow.querySelector('core-tooltip').label = l10n.translate("Delete Row").fetch(); /* New row template */ @@ -204,6 +217,13 @@ } newRow.querySelector('core-tooltip').label = l10n.translate("Add New Row").fetch(); + /* Main toolbar */ + document.getElementById('jumpToGeneralInfo').parentElement.label = l10n.translate("Jump To General Information").fetch(); + document.getElementById('sortButton').parentElement.label = l10n.translate("Sort Plugins").fetch(); + document.getElementById('updateMasterlistButton').parentElement.label = l10n.translate("Update Masterlist").fetch(); + document.getElementById('applySortButton').textContent = l10n.translate("Apply").fetch(); + document.getElementById('cancelSortButton').textContent = l10n.translate("Cancel").fetch(); + /* Toolbar menu */ document.getElementById('redatePluginsButton').lastElementChild.textContent = l10n.translate("Redate Plugins").fetch(); document.getElementById('openLogButton').lastElementChild.textContent = l10n.translate("Open Debug Log Location").fetch(); @@ -214,8 +234,6 @@ document.getElementById('aboutButton').lastElementChild.textContent = l10n.translate("About").fetch(); document.getElementById('settingsButton').lastElementChild.textContent = l10n.translate("Settings").fetch(); document.getElementById('quitButton').lastElementChild.textContent = l10n.translate("Quit").fetch(); - document.getElementById('applySortButton').textContent = l10n.translate("Apply").fetch(); - document.getElementById('cancelSortButton').textContent = l10n.translate("Cancel").fetch(); /* Nav items */ document.getElementById('sidebarTabs').firstElementChild.textContent = l10n.translate("Plugins").fetch(); @@ -252,7 +270,7 @@ document.getElementById('defaultGameSelect').firstElementChild.textContent = l10n.translate("Autodetect").fetch(); document.getElementById('languageSelect').previousElementSibling.textContent = l10n.translate("Language").fetch(); - document.getElementById('languageSelect').parentElement.label = l10n.translate("Language changes will be applied after LOOT is restarted.").fetch(); + document.getElementById('languageSelect').previousElementSibling.label = l10n.translate("Language changes will be applied after LOOT is restarted.").fetch(); document.getElementById('enableDebugLogging').label = l10n.translate("Enable debug logging").fetch(); document.getElementById('enableDebugLogging').parentElement.label = l10n.translate("The output is logged to the LOOTDebugLog.txt file.").fetch(); diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 72076e78..eabff341 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -505,14 +505,14 @@ function updateMasterlistNoProgress() { /* Hack to stop cards overlapping. */ document.getElementById('main').lastElementChild.updateSize(); - toast('Masterlist updated to revision ' + loot.game.masterlist.revision + '.'); + toast(l10n.jed.translate('Masterlist updated to revision %s.').fetch(loot.game.masterlist.revision)); } else { - toast('No masterlist update was necessary.'); + toast(l10n.jed.translate('No masterlist update was necessary.').fetch()); } }).catch(processCefError); } function updateMasterlist(evt) { - showProgress('Updating masterlist...'); + showProgress(l10n.jed.translate('Updating masterlist...').fetch()); updateMasterlistNoProgress().then(function(result){ closeProgressDialog(); }).catch(processCefError); @@ -542,7 +542,7 @@ function sortPlugins(evt) { }); } mlistUpdate.then(function(){ - showProgress('Sorting plugins...'); + showProgress(l10n.jed.translate('Sorting plugins...').fetch()); loot.query('sortPlugins').then(JSON.parse).then(function(result){ if (result) { loot.game.oldLoadOrder = loot.game.plugins; @@ -644,7 +644,7 @@ function redatePlugins(evt) { return; } - showMessageDialog('Redate Plugins?', 'This feature is provided so that modders using the Creation Kit may set the load order it uses. A side-effect is that any subscribed Steam Workshop mods will be re-downloaded by Steam. Do you wish to continue?', l10n.jed.translate('Redate').fetch(), function(result){ + showMessageDialog(l10n.jed.translate('Redate Plugins?').fetch(), l10n.jed.translate('This feature is provided so that modders using the Creation Kit may set the load order it uses. A side-effect is that any subscribed Steam Workshop mods will be re-downloaded by Steam. Do you wish to continue?').fetch(), l10n.jed.translate('Redate').fetch(), function(result){ if (result) { loot.query('redatePlugins').then(function(response){ toast('Plugins were successfully redated.'); @@ -653,7 +653,7 @@ function redatePlugins(evt) { }); } function clearAllMetadata(evt) { - showMessageDialog('', 'Are you sure you want to clear all existing user-added metadata from all plugins?', l10n.jed.translate('Clear').fetch(), function(result){ + showMessageDialog('', l10n.jed.translate('Are you sure you want to clear all existing user-added metadata from all plugins?').fetch(), l10n.jed.translate('Clear').fetch(), function(result){ if (result) { loot.query('clearAllMetadata').then(JSON.parse).then(function(result){ if (result) { @@ -674,7 +674,7 @@ function clearAllMetadata(evt) { } }); - toast('All user-added metadata has been cleared.'); + toast(l10n.jed.translate('All user-added metadata has been cleared.').fetch()); } }).catch(processCefError); } @@ -731,7 +731,7 @@ function copyContent(evt) { }); loot.query(request).then(function(){ - toast("LOOT's content has been copied to the clipboard."); + toast(l10n.jed.translate("LOOT's content has been copied to the clipboard.").fetch()); }).catch(processCefError); } function areSettingsValid() { @@ -805,7 +805,7 @@ function focusSearch(evt) { } } function handleUnappliedChangesClose(change) { - showMessageDialog('', 'You have not yet applied or cancelled your ' + change + '. Are you sure you want to quit?', l10n.jed.translate('Quit').fetch(), function(result){ + showMessageDialog('', l10n.jed.translate('You have not yet applied or cancelled your %s. Are you sure you want to quit?').fetch(change), l10n.jed.translate('Quit').fetch(), function(result){ if (result) { /* Cancel any sorting and close any editors. Cheat by sending a cancelSort query for as many times as necessary. */ @@ -954,11 +954,11 @@ function handleCopyMetadata(evt) { }); loot.query(request).then(function(){ - toast('The metadata for ' + evt.target.getName() + ' has been copied to the clipboard.'); + toast(l10n.jed.translate('The metadata for "%s" has been copied to the clipboard.').fetch(evt.target.getName())); }).catch(processCefError); } function handleClearMetadata(evt) { - showMessageDialog('', 'Are you sure you want to clear all existing user-added metadata from "' + evt.target.getName() + '"?', l10n.jed.translate('Clear').fetch(), function(result){ + showMessageDialog('', l10n.jed.translate('Are you sure you want to clear all existing user-added metadata from "%s"?').fetch(evt.target.getName()), l10n.jed.translate('Clear').fetch(), function(result){ if (result) { var request = JSON.stringify({ name: 'clearPluginMetadata', @@ -983,7 +983,7 @@ function handleClearMetadata(evt) { break; } } - toast('The user-added metadata for ' + evt.target.getName() + ' has been cleared.'); + toast(l10n.jed.translate('The user-added metadata for "%s" has been cleared.').fetch(evt.target.getName())); } }).catch(processCefError); } @@ -1003,9 +1003,9 @@ function handleSidebarClick(evt) { } function handleQuit(evt) { if (!document.getElementById('applySortButton').classList.contains('hidden')) { - handleUnappliedChangesClose('sorted load order'); + handleUnappliedChangesClose(l10n.jed.translate('sorted load order').fetch()); } else if (document.body.hasAttribute('data-editors')) { - handleUnappliedChangesClose('metadata edits'); + handleUnappliedChangesClose(l10n.jed.translate('metadata edits').fetch()); } else { window.close(); } @@ -1212,7 +1212,7 @@ function initVars() { } function onContentRefresh(evt) { /* Send a query for updated load order and plugin header info. */ - showProgress('Refreshing data...'); + showProgress(l10n.jed.translate('Refreshing data...').fetch()); loot.query('getGameData').then(function(result){ /* Parse the data sent from C++. */ try { diff --git a/src/backend/game.cpp b/src/backend/game.cpp index fda6734f..f55c9aa6 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -784,7 +784,7 @@ namespace loot { //Create a plugin graph containing the plugin and masterlist data. loot::PluginGraph graph; - progressCallback("Building plugin graph..."); + progressCallback(lc::translate("Building plugin graph...")); BOOST_LOG_TRIVIAL(info) << "Merging masterlist, userlist into plugin list, evaluating conditions and checking for install validity."; for (const auto &plugin : this->plugins) { vertex_t v = boost::add_vertex(plugin.second, graph); @@ -820,7 +820,7 @@ namespace loot { } // Now add edges and sort. - progressCallback("Adding edges to plugin graph and performing topological sort..."); + progressCallback(lc::translate("Adding edges to plugin graph and performing topological sort...")); return loot::Sort(graph); } } diff --git a/src/backend/git.cpp b/src/backend/git.cpp index 20d010e4..3ae76475 100644 --- a/src/backend/git.cpp +++ b/src/backend/git.cpp @@ -175,16 +175,20 @@ namespace loot { bool IsMasterlistDifferent(git_handler& git, const std::string& filename) { if (git.obj) { - throw error(error::git_error, "Object memory already allocated!"); + BOOST_LOG_TRIVIAL(error) << "Object memory already allocated!"; + throw error(error::git_error, lc::translate("Object memory already allocated!")); } else if (git.tree) { - throw error(error::git_error, "Tree memory already allocated!"); + BOOST_LOG_TRIVIAL(error) << "Tree memory already allocated!"; + throw error(error::git_error, lc::translate("Tree memory already allocated!")); } else if (git.diff) { - throw error(error::git_error, "Diff memory already allocated!"); + BOOST_LOG_TRIVIAL(error) << "Diff memory already allocated!"; + throw error(error::git_error, lc::translate("Diff memory already allocated!")); } else if (!git.repo) { - throw error(error::git_error, "Repository handle not open!"); + BOOST_LOG_TRIVIAL(error) << "Repository handle not open!"; + throw error(error::git_error, lc::translate("Repository handle not open!")); } // Perform a git diff, then iterate the deltas to see if one exists for the masterlist. @@ -214,15 +218,17 @@ namespace loot { void Masterlist::GetGitInfo(const boost::filesystem::path& path, bool shortID) { if (!isRepository(path.parent_path())) { - throw error(error::ok, "Unknown: Git repository missing"); + BOOST_LOG_TRIVIAL(info) << "Unknown masterlist revision: Git repository missing."; + throw error(error::ok, lc::translate("Unknown: Git repository missing")); } else if (!fs::exists(path)) { - throw error(error::ok, "N/A: No masterlist present"); + BOOST_LOG_TRIVIAL(info) << "Unknown masterlist revision: No masterlist present."; + throw error(error::ok, lc::translate("N/A: No masterlist present")); } // Compare HEAD and working copy, and get revision info. git_handler git; - git.ui_message = "An error occurred while trying to read the local masterlist's version. If this error happens again, try deleting the \".git\" folder in " + path.parent_path().string() + "."; + git.ui_message = (boost::format(lc::translate("An error occurred while trying to read the local masterlist's version. If this error happens again, try deleting the \".git\" folder in %1%.")) % path.parent_path().string()).str(); BOOST_LOG_TRIVIAL(debug) << "Existing repository found, attempting to open it."; git.call(git_repository_open(&git.repo, path.parent_path().string().c_str())); @@ -255,8 +261,8 @@ namespace loot { BOOST_LOG_TRIVIAL(trace) << "Diffing masterlist HEAD and working copy."; if (IsMasterlistDifferent(git, path.filename().string())) { - revision += " (edited)"; - date += " (edited)"; + revision += string(" ") + lc::translate("(edited)").str(); + date += string(" ") + lc::translate("(edited)").str(); } } @@ -285,7 +291,7 @@ namespace loot { // Now try to access the repository if it exists, or clone one if it doesn't. BOOST_LOG_TRIVIAL(trace) << "Attempting to open the Git repository at: " << repo_path; if (!isRepository(repo_path)) { - git.ui_message = "An error occurred while trying to clone the remote masterlist repository."; + git.ui_message = lc::translate("An error occurred while trying to clone the remote masterlist repository."); // Clone the remote repository. BOOST_LOG_TRIVIAL(info) << "Repository doesn't exist, cloning the remote repository."; @@ -341,7 +347,7 @@ namespace loot { } else { // Repository exists: check settings are correct, then pull updates. - git.ui_message = "An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in " + repo_path.string() + "."; + git.ui_message = (boost::format(lc::translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repo_path.string()).str(); // Open the repository. BOOST_LOG_TRIVIAL(info) << "Existing repository found, attempting to open it."; @@ -365,7 +371,7 @@ namespace loot { // Now fetch updates from the remote. BOOST_LOG_TRIVIAL(trace) << "Fetching updates from remote."; - git.ui_message = "An error occurred while trying to update the masterlist. This could be due to a server-side error. Try again in a few minutes."; + git.ui_message = lc::translate("An error occurred while trying to update the masterlist. This could be due to a server-side error. Try again in a few minutes."); git.call(git_remote_fetch(git.remote, git.sig, nullptr)); @@ -374,7 +380,7 @@ namespace loot { BOOST_LOG_TRIVIAL(info) << "Received " << stats->indexed_objects << " of " << stats->total_objects << " objects in " << stats->received_bytes << " bytes."; // Check that a branch with the correct name exists. - git.ui_message = "An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in " + repo_path.string() + "\"."; + git.ui_message = (boost::format(lc::translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repo_path.string()).str(); int ret = git_branch_lookup(&git.ref, git.repo, repoBranch.c_str(), GIT_BRANCH_LOCAL); if (ret == GIT_ENOTFOUND) { // Branch doesn't exist. Create a new branch using the remote branch's latest commit. @@ -508,7 +514,7 @@ namespace loot { bool parsingFailed = false; std::string parsingError; - git.ui_message = "An error occurred while trying to read information on the updated masterlist. If this error happens again, try deleting the \".git\" folder in " + repo_path.string() + "\"."; + git.ui_message = (boost::format(lc::translate("An error occurred while trying to read information on the updated masterlist. If this error happens again, try deleting the \".git\" folder in %1%.")) % repo_path.string()).str(); do { // Get some descriptive info about what was checked out. diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 2b3b1165..17bba658 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -247,7 +247,6 @@ namespace loot { } catch (loot::error &e) { if (e.code() == loot::error::no_game_detected) { - BOOST_LOG_TRIVIAL(error) << e.what(); _initErrors.push_back(e.what()); } else { @@ -392,7 +391,8 @@ namespace loot { } } - throw error(error::no_game_detected, "None of the supported games were detected."); + BOOST_LOG_TRIVIAL(error) << "None of the supported games were detected."; + throw error(error::no_game_detected, translate("None of the supported games were detected.")); } bool LootState::AreSettingsValid() { diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 01cb276b..c9b16568 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -223,11 +223,11 @@ namespace loot { } catch (loot::error &e) { BOOST_LOG_TRIVIAL(error) << "Failed to change game. Details: " << e.what(); - callback->Failure(e.code(), string("Failed to change game. Details: ") + e.what()); + callback->Failure(e.code(), (boost::format(loc::translate("Failed to change game. Details: %1%")) % e.what()).str()); } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Failed to change game. Details: " << e.what(); - callback->Failure(-1, string("Failed to change game. Details: ") + e.what()); + callback->Failure(-1, (boost::format(loc::translate("Failed to change game. Details: %1%")) % e.what()).str()); } return true; } @@ -244,11 +244,11 @@ namespace loot { } catch (loot::error &e) { BOOST_LOG_TRIVIAL(error) << "Failed to copy plugin metadata. Details: " << e.what(); - callback->Failure(e.code(), string("Failed to copy plugin metadata. Details: ") + e.what()); + callback->Failure(e.code(), (boost::format(loc::translate("Failed to copy plugin metadata. Details: %1%")) % e.what()).str()); } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Failed to copy plugin metadata. Details: " << e.what(); - callback->Failure(-1, string("Failed to copy plugin metadata. Details: ") + e.what()); + callback->Failure(-1, (boost::format(loc::translate("Failed to copy plugin metadata. Details: %1%")) % e.what()).str()); } return true; } @@ -325,11 +325,11 @@ namespace loot { } catch (loot::error &e) { BOOST_LOG_TRIVIAL(error) << "Failed to copy plugin metadata. Details: " << e.what(); - callback->Failure(e.code(), string("Failed to copy plugin metadata. Details: ") + e.what()); + callback->Failure(e.code(), (boost::format(loc::translate("Failed to copy plugin metadata. Details: %1%")) % e.what()).str()); } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Failed to copy plugin metadata. Details: " << e.what(); - callback->Failure(-1, string("Failed to copy plugin metadata. Details: ") + e.what()); + callback->Failure(-1, (boost::format(loc::translate("Failed to copy plugin metadata. Details: %1%")) % e.what()).str()); } return true; } @@ -348,7 +348,7 @@ namespace loot { g_app_state.CurrentGame().LoadPlugins(false); } - SendProgressUpdate(frame, "Checking for conflicting plugins..."); + SendProgressUpdate(frame, loc::translate("Checking for conflicting plugins...")); YAML::Node node; for (const auto& pluginPair : g_app_state.CurrentGame().plugins) { YAML::Node pluginNode; @@ -515,7 +515,7 @@ namespace loot { // Open readme in default application. HINSTANCE ret = ShellExecute(0, NULL, ToWinWide(ToFileURL(g_path_readme)).c_str(), NULL, NULL, SW_SHOWNORMAL); if ((int)ret <= 32) - throw error(error::windows_error, "Shell execute failed."); + throw error(error::windows_error, loc::translate("Shell execute failed.")); } void Handler::OpenLogLocation() { @@ -523,7 +523,7 @@ namespace loot { //Open debug log folder. HINSTANCE ret = ShellExecute(NULL, L"open", ToWinWide(g_path_log.parent_path().string()).c_str(), NULL, NULL, SW_SHOWNORMAL); if ((int)ret <= 32) - throw error(error::windows_error, "Shell execute failed."); + throw error(error::windows_error, loc::translate("Shell execute failed.")); } std::string Handler::GetVersion() { @@ -581,7 +581,7 @@ namespace loot { BOOST_LOG_TRIVIAL(info) << "Getting data specific to LOOT's active game."; // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. - SendProgressUpdate(frame, "Loading plugin headers..."); + SendProgressUpdate(frame, loc::translate("Loading plugin headers...")); // First clear CRC and condition caches, otherwise they could lead to incorrect evaluations. g_app_state.CurrentGame().conditionCache.clear(); @@ -607,25 +607,25 @@ namespace loot { if (isFirstLoad) { //Parse masterlist, don't update it. if (fs::exists(g_app_state.CurrentGame().MasterlistPath())) { - SendProgressUpdate(frame, "Parsing masterlist..."); + SendProgressUpdate(frame, loc::translate("Parsing masterlist...")); BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; try { g_app_state.CurrentGame().masterlist.MetadataList::Load(g_app_state.CurrentGame().MasterlistPath()); } catch (exception &e) { - g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, string("An error occurred while parsing the masterlist: ") + e.what())); + g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (boost::format(loc::translate("An error occurred while parsing the masterlist: %1%")) % e.what()).str())); } } //Parse userlist. if (fs::exists(g_app_state.CurrentGame().UserlistPath())) { - SendProgressUpdate(frame, "Parsing userlist..."); + SendProgressUpdate(frame, loc::translate("Parsing userlist...")); BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; try { g_app_state.CurrentGame().userlist.Load(g_app_state.CurrentGame().UserlistPath()); } catch (exception &e) { - g_app_state.CurrentGame().userlist.messages.push_back(Message(Message::error, string("An error occurred while parsing the userlist: ") + e.what())); + g_app_state.CurrentGame().userlist.messages.push_back(Message(Message::error, (boost::format(loc::translate("An error occurred while parsing the userlist: %1%")) % e.what()).str())); } } } @@ -650,7 +650,7 @@ namespace loot { } // Now store plugin data. - SendProgressUpdate(frame, "Merging and evaluating plugin metadata..."); + SendProgressUpdate(frame, loc::translate("Merging and evaluating plugin metadata...")); for (const auto& plugin : installed) { /* Each plugin has members while hold its raw masterlist and userlist data for the editor, and also processed data for the main display. @@ -715,7 +715,7 @@ namespace loot { gameNode["plugins"].push_back(pluginNode); } - SendProgressUpdate(frame, "Loading general messages..."); + SendProgressUpdate(frame, loc::translate("Loading general messages...")); //Set language. unsigned int language; if (g_app_state.GetSettings()["language"]) @@ -749,11 +749,11 @@ namespace loot { } catch (loot::error &e) { BOOST_LOG_TRIVIAL(error) << "Failed to get game data. Details: " << e.what(); - callback->Failure(e.code(), string("Failed to get game data. Details: ") + e.what()); + callback->Failure(e.code(), (boost::format(loc::translate("Failed to get game data. Details: %1%")) % e.what()).str()); } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Failed to get game data. Details: " << e.what(); - callback->Failure(-1, string("Failed to get game data. Details: ") + e.what()); + callback->Failure(-1, (boost::format(loc::translate("Failed to get game data. Details: %1%")) % e.what()).str()); } } @@ -772,7 +772,7 @@ namespace loot { // Update / parse masterlist. bool wasChanged = true; try { - SendProgressUpdate(frame, "Updating and parsing masterlist..."); + SendProgressUpdate(frame, loc::translate("Updating and parsing masterlist...")); wasChanged = g_app_state.CurrentGame().masterlist.Load(g_app_state.CurrentGame(), language); } catch (loot::error &e) { @@ -788,7 +788,7 @@ namespace loot { } // Now regenerate the JS-side masterlist data if the masterlist was changed. - SendProgressUpdate(frame, "Regenerating displayed content..."); + SendProgressUpdate(frame, loc::translate("Regenerating displayed content...")); if (wasChanged) { // The data structure is to be set as 'loot.game'. YAML::Node gameNode; @@ -857,12 +857,12 @@ namespace loot { callback->Success("null"); } catch (error &e) { - BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what(); - callback->Failure(e.code(), e.what()); + BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. Details: " << e.what(); + callback->Failure(e.code(), (boost::format(loc::translate("Failed to update the masterlist. Details: %1%")) % e.what()).str()); } catch (exception &e) { - BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what(); - callback->Failure(-1, e.what()); + BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. Details: " << e.what(); + callback->Failure(-1, (boost::format(loc::translate("Failed to update the masterlist. Details: %1%")) % e.what()).str()); } } @@ -904,7 +904,7 @@ namespace loot { try { // Always reload all the plugins. - SendProgressUpdate(frame, "Loading plugin contents..."); + SendProgressUpdate(frame, loc::translate("Loading plugin contents...")); g_app_state.CurrentGame().LoadPlugins(false); //Sort plugins into their load order. @@ -938,7 +938,7 @@ namespace loot { } catch (loot::error& e) { BOOST_LOG_TRIVIAL(error) << "Failed to sort plugins. Details: " << e.what(); - callback->Failure(e.code(), e.what()); + callback->Failure(e.code(), (boost::format(loc::translate("Failed to sort plugins. Details: %1%")) % e.what()).str()); } }