| @@ -43,7 +43,18 @@ namespace widget { | |||
| struct Widget; | |||
| /** Returns the name of a GLFW key macro. | |||
| Printable keys return the key string such as "Q", "=", "\t", etc. | |||
| Letters are capitalized. | |||
| Does not remap keys based on keyboard layout, so GLFW_KEY_Q always returns "Q". | |||
| GLFW_KEY_SPACE returns "Space" translated to the current language. | |||
| Non-printable characters return the name of the key in the current language. | |||
| Key 0 returns "". | |||
| */ | |||
| std::string getKeyName(int key); | |||
| /** Returns the name of a key command/chord/combo. | |||
| For example, getKeyCommandName(GLFW_KEY_Q, GLFW_MOD_CONTROL) == "Ctrl+Q" translated to the current language. | |||
| */ | |||
| std::string getKeyCommandName(int key, int mods = 0); | |||
| @@ -82,7 +82,7 @@ static ModuleWidget* chooseModel(plugin::Model* model) { | |||
| mi.lastAdded = system::getUnixTime(); | |||
| history::ComplexAction* h = new history::ComplexAction; | |||
| h->name = "add module"; | |||
| h->name = string::translate("Browser.history.addModule"); | |||
| // Create Module and ModuleWidget | |||
| INFO("Creating module %s", model->getFullName().c_str()); | |||
| @@ -306,7 +306,8 @@ struct ModelBox : widget::OpaqueWidget { | |||
| text += "\n" + model->description; | |||
| } | |||
| // Tags | |||
| text += "\n\nTags: "; | |||
| text += "\n\n"; | |||
| text += string::translate("Browser.tooltipTags"); | |||
| std::vector<std::string> tags; | |||
| for (int tagId : model->tagIds) { | |||
| tags.push_back(tag::getTag(tagId)); | |||
| @@ -411,13 +412,15 @@ struct TagButton : ui::ChoiceButton { | |||
| }; | |||
| static const std::string sortNames[] = { | |||
| "Last updated", | |||
| "Last used", | |||
| "Most used", | |||
| "Brand", | |||
| "Module name", | |||
| "Random", | |||
| static std::vector<std::string> getSortNames() { | |||
| return { | |||
| string::translate("Browser.sort.lastUpdated"), | |||
| string::translate("Browser.sort.lastUsed"), | |||
| string::translate("Browser.sort.mostUsed"), | |||
| string::translate("Browser.sort.brand"), | |||
| string::translate("Browser.sort.moduleName"), | |||
| string::translate("Browser.sort.random"), | |||
| }; | |||
| }; | |||
| @@ -427,8 +430,8 @@ struct SortButton : ui::ChoiceButton { | |||
| void onAction(const ActionEvent& e) override; | |||
| void step() override { | |||
| text = "Sort: "; | |||
| text += sortNames[settings::browserSort]; | |||
| text = string::translate("Browser.sort"); | |||
| text += getSortNames()[settings::browserSort]; | |||
| ChoiceButton::step(); | |||
| } | |||
| }; | |||
| @@ -440,7 +443,7 @@ struct ZoomButton : ui::ChoiceButton { | |||
| void onAction(const ActionEvent& e) override; | |||
| void step() override { | |||
| text = "Zoom: "; | |||
| text = string::translate("Browser.zoom"); | |||
| text += string::f("%.0f%%", std::pow(2.f, settings::browserZoom) * 100.f); | |||
| ChoiceButton::step(); | |||
| } | |||
| @@ -492,7 +495,7 @@ struct Browser : widget::OpaqueWidget { | |||
| searchField = new BrowserSearchField; | |||
| searchField->box.size.x = 150; | |||
| searchField->placeholder = "Search modules"; | |||
| searchField->placeholder = string::translate("Browser.searchModules"); | |||
| searchField->browser = this; | |||
| headerLayout->addChild(searchField); | |||
| @@ -511,13 +514,13 @@ struct Browser : widget::OpaqueWidget { | |||
| favoriteButton = new ui::OptionButton; | |||
| favoriteButton->quantity = favoriteQuantity; | |||
| favoriteButton->text = "Favorites"; | |||
| favoriteButton->text = string::translate("Browser.favorites"); | |||
| favoriteButton->box.size.x = 70; | |||
| headerLayout->addChild(favoriteButton); | |||
| clearButton = new ClearButton; | |||
| clearButton->box.size.x = 100; | |||
| clearButton->text = "Reset filters"; | |||
| clearButton->text = string::translate("Browser.resetFilters"); | |||
| clearButton->browser = this; | |||
| headerLayout->addChild(clearButton); | |||
| @@ -537,7 +540,7 @@ struct Browser : widget::OpaqueWidget { | |||
| UrlButton* libraryButton = new UrlButton; | |||
| libraryButton->box.size.x = 150; | |||
| libraryButton->text = "Browse VCV Library"; | |||
| libraryButton->text = string::translate("Browser.browseLibrary"); | |||
| libraryButton->url = "https://library.vcvrack.com/"; | |||
| headerLayout->addChild(libraryButton); | |||
| @@ -776,7 +779,7 @@ struct Browser : widget::OpaqueWidget { | |||
| if (w->isVisible()) | |||
| count++; | |||
| } | |||
| countLabel->text = string::f("%d %s", count, (count == 1) ? "module" : "modules"); | |||
| countLabel->text = (count == 1) ? string::translate("Browser.modulesOne") : string::f(string::translate("Browser.modulesMany"), count); | |||
| } | |||
| void clear() { | |||
| @@ -892,7 +895,7 @@ inline void BrandButton::onAction(const ActionEvent& e) { | |||
| menu->box.size.x = box.size.x; | |||
| BrandItem* noneItem = new BrandItem; | |||
| noneItem->text = "All brands"; | |||
| noneItem->text = string::translate("Browser.allBrands"); | |||
| noneItem->brand = ""; | |||
| noneItem->browser = browser; | |||
| menu->addChild(noneItem); | |||
| @@ -916,7 +919,7 @@ inline void BrandButton::onAction(const ActionEvent& e) { | |||
| } | |||
| inline void BrandButton::step() { | |||
| text = "Brand"; | |||
| text = string::translate("Browser.brand"); | |||
| if (!browser->brand.empty()) { | |||
| text += ": "; | |||
| text += browser->brand; | |||
| @@ -975,12 +978,12 @@ inline void TagButton::onAction(const ActionEvent& e) { | |||
| menu->box.size.x = box.size.x; | |||
| TagItem* noneItem = new TagItem; | |||
| noneItem->text = "All tags"; | |||
| noneItem->text = string::translate("Browser.allTags"); | |||
| noneItem->tagId = -1; | |||
| noneItem->browser = browser; | |||
| menu->addChild(noneItem); | |||
| menu->addChild(createMenuLabel(RACK_MOD_CTRL_NAME "+click to select multiple")); | |||
| menu->addChild(createMenuLabel(widget::getKeyCommandName(0, RACK_MOD_CTRL) + string::translate("Browser.tagsSelectMultiple"))); | |||
| menu->addChild(new ui::MenuSeparator); | |||
| for (int tagId = 0; tagId < (int) tag::tagAliases.size(); tagId++) { | |||
| @@ -994,7 +997,7 @@ inline void TagButton::onAction(const ActionEvent& e) { | |||
| } | |||
| inline void TagButton::step() { | |||
| text = "Tags"; | |||
| text = string::translate("Browser.tags"); | |||
| if (!browser->tagIds.empty()) { | |||
| text += ": "; | |||
| bool firstTag = true; | |||
| @@ -1015,7 +1018,7 @@ inline void SortButton::onAction(const ActionEvent& e) { | |||
| menu->box.size.x = box.size.x; | |||
| for (int sortId = 0; sortId <= settings::BROWSER_SORT_RANDOM; sortId++) { | |||
| menu->addChild(createCheckMenuItem(sortNames[sortId], "", | |||
| menu->addChild(createCheckMenuItem(getSortNames()[sortId], "", | |||
| [=]() {return settings::browserSort == sortId;}, | |||
| [=]() { | |||
| settings::browserSort = (settings::BrowserSort) sortId; | |||
| @@ -1094,7 +1094,7 @@ struct InfoLabel : ui::Label { | |||
| double fps = std::isfinite(frameDurationAvg) ? 1.0 / frameDurationAvg : 0.0; | |||
| double meterAverage = APP->engine->getMeterAverage(); | |||
| double meterMax = APP->engine->getMeterMax(); | |||
| text += string::f("%.1f fps %.1f%% avg %.1f%% max", fps, meterAverage * 100, meterMax * 100); | |||
| text += string::f(string::translate("MenuBar.infoLabel"), fps, meterAverage * 100, meterMax * 100); | |||
| text += " "; | |||
| } | |||
| @@ -76,7 +76,7 @@ struct ParamValueItem : ui::MenuItem { | |||
| if (oldValue != newValue) { | |||
| // Push ParamChange history action | |||
| history::ParamChange* h = new history::ParamChange; | |||
| h->name = "set parameter"; | |||
| h->name = string::translate("ParamWidget.history.setParam"); | |||
| h->moduleId = paramWidget->module->id; | |||
| h->paramId = paramWidget->paramId; | |||
| h->oldValue = oldValue; | |||
| @@ -274,20 +274,20 @@ void ParamWidget::createContextMenu() { | |||
| // Initialize | |||
| if (pq && pq->resetEnabled && pq->isBounded()) { | |||
| menu->addChild(createMenuItem("Initialize", switchQuantity ? "" : "Double-click", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("ParamWidget.initialize"), switchQuantity ? "" : string::translate("ParamWidget.doubleClick"), [=]() { | |||
| this->resetAction(); | |||
| })); | |||
| } | |||
| // Fine | |||
| if (!switchQuantity) { | |||
| menu->addChild(createMenuItem("Fine adjust", RACK_MOD_CTRL_NAME "+drag", NULL, true)); | |||
| menu->addChild(createMenuItem(string::translate("ParamWidget.fine"), widget::getKeyCommandName(0, RACK_MOD_CTRL) + string::translate("ParamWidget.fineDrag"), NULL, true)); | |||
| } | |||
| // Unmap | |||
| engine::ParamHandle* paramHandle = module ? APP->engine->getParamHandle(module->id, paramId) : NULL; | |||
| if (paramHandle) { | |||
| menu->addChild(createMenuItem("Unmap", paramHandle->text, [=]() { | |||
| menu->addChild(createMenuItem(string::translate("ParamWidget.unmap"), paramHandle->text, [=]() { | |||
| APP->engine->updateParamHandle(paramHandle, -1, 0); | |||
| })); | |||
| } | |||
| @@ -306,7 +306,7 @@ void ParamWidget::resetAction() { | |||
| if (oldValue != newValue) { | |||
| // Push ParamChange history action | |||
| history::ParamChange* h = new history::ParamChange; | |||
| h->name = "reset parameter"; | |||
| h->name = string::translate("ParamWidget.history.reset"); | |||
| h->moduleId = module->id; | |||
| h->paramId = paramId; | |||
| h->oldValue = oldValue; | |||
| @@ -61,14 +61,14 @@ struct PortTooltip : ui::Tooltip { | |||
| continue; | |||
| text += "\n"; | |||
| if (portWidget->type == engine::Port::INPUT) | |||
| text += "From "; | |||
| text += string::translate("PortWidget.from"); | |||
| else | |||
| text += "To "; | |||
| text += string::translate("PortWidget.to"); | |||
| text += otherPw->module->model->getFullName(); | |||
| text += ": "; | |||
| text += otherPw->getPortInfo()->getName(); | |||
| text += " "; | |||
| text += (otherPw->type == engine::Port::INPUT) ? "input" : "output"; | |||
| text += (otherPw->type == engine::Port::INPUT) ? string::translate("PortWidget.input") : string::translate("PortWidget.output"); | |||
| } | |||
| } | |||
| Tooltip::step(); | |||
| @@ -140,11 +140,11 @@ struct PortCableItem : ui::ColorDotMenuItem { | |||
| ui::Menu* createChildMenu() override { | |||
| ui::Menu* menu = new ui::Menu; | |||
| // menu->addChild(createMenuLabel(string::f("ID: %ld", cw->cable->id))); | |||
| // menu->addChild(createMenuLabel(string::f(string::translate("PortWidget.cableId"), cw->cable->id))); | |||
| for (NVGcolor color : settings::cableColors) { | |||
| // Include extra leading spaces for the color circle | |||
| CableColorItem* item = createMenuItem<CableColorItem>("Set color"); | |||
| CableColorItem* item = createMenuItem<CableColorItem>(string::translate("PortWidget.setColor")); | |||
| item->disabled = color::isEqual(color, cw->color); | |||
| item->cw = cw; | |||
| item->color = color; | |||
| @@ -286,7 +286,7 @@ void PortWidget::createContextMenu() { | |||
| std::vector<CableWidget*> cws = APP->scene->rack->getCompleteCablesOnPort(this); | |||
| CableWidget* topCw = cws.empty() ? NULL : cws.back(); | |||
| menu->addChild(createMenuItem("Delete top cable", RACK_MOD_SHIFT_NAME "+click", | |||
| menu->addChild(createMenuItem(string::translate("PortWidget.deleteTopCable"), widget::getKeyCommandName(0, RACK_MOD_SHIFT) + string::translate("PortWidget.click"), | |||
| [=]() { | |||
| if (!weakThis) | |||
| return; | |||
| @@ -296,7 +296,7 @@ void PortWidget::createContextMenu() { | |||
| )); | |||
| { | |||
| PortCloneCableItem* item = createMenuItem<PortCloneCableItem>("Duplicate top cable", RACK_MOD_CTRL_NAME "+Shift+drag"); | |||
| PortCloneCableItem* item = createMenuItem<PortCloneCableItem>(string::translate("PortWidget.cloneTopCable"), widget::getKeyCommandName(0, RACK_MOD_CTRL) + string::translate("PortWidget.drag")); | |||
| item->disabled = !topCw; | |||
| item->pw = this; | |||
| item->cw = topCw; | |||
| @@ -304,7 +304,7 @@ void PortWidget::createContextMenu() { | |||
| } | |||
| { | |||
| PortCreateCableItem* item = createMenuItem<PortCreateCableItem>("Create cable on top", RACK_MOD_CTRL_NAME "+drag"); | |||
| PortCreateCableItem* item = createMenuItem<PortCreateCableItem>(string::translate("PortWidget.createCableTop"), widget::getKeyCommandName(0, RACK_MOD_CTRL) + string::translate("PortWidget.drag")); | |||
| item->pw = this; | |||
| menu->addChild(item); | |||
| } | |||
| @@ -317,7 +317,7 @@ void PortWidget::createContextMenu() { | |||
| std::string label = get(settings::cableLabels, colorId); | |||
| if (label == "") | |||
| label = string::f("#%lld", (long long) (colorId + 1)); | |||
| PortCreateCableColorItem* item = createMenuItem<PortCreateCableColorItem>("Create cable: " + label); | |||
| PortCreateCableColorItem* item = createMenuItem<PortCreateCableColorItem>(string::translate("PortWidget.createCable") + label); | |||
| item->pw = this; | |||
| item->color = color; | |||
| item->colorId = colorId; | |||
| @@ -326,7 +326,7 @@ void PortWidget::createContextMenu() { | |||
| if (!cws.empty()) { | |||
| menu->addChild(new ui::MenuSeparator); | |||
| menu->addChild(createMenuLabel("Click+drag to grab cable")); | |||
| menu->addChild(createMenuLabel(string::translate("PortWidget.clickDrag") + string::translate("PortWidget.grabCable"))); | |||
| // Cable items | |||
| for (auto it = cws.rbegin(); it != cws.rend(); it++) { | |||
| @@ -342,7 +342,7 @@ void PortWidget::createContextMenu() { | |||
| } | |||
| if (cws.size() > 1) { | |||
| PortAllCablesItem* item = createMenuItem<PortAllCablesItem>("All cables"); | |||
| PortAllCablesItem* item = createMenuItem<PortAllCablesItem>(string::translate("PortWidget.allCables")); | |||
| item->pw = this; | |||
| item->cws = cws; | |||
| menu->addChild(item); | |||
| @@ -431,7 +431,7 @@ void PortWidget::onDragStart(const DragStartEvent& e) { | |||
| internal->history = NULL; | |||
| } | |||
| internal->history = new history::ComplexAction; | |||
| internal->history->name = "move cable"; | |||
| internal->history->name = string::translate("PortWidget.history.moveCable"); | |||
| std::vector<CableWidget*> cws; | |||
| int mods = APP->window->getMods(); | |||
| @@ -106,16 +106,16 @@ std::string Model::getManualUrl() { | |||
| void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) { | |||
| // plugin | |||
| menu->addChild(createMenuItem("Plugin: " + plugin->name, "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.plugin") + plugin->name, "", [=]() { | |||
| system::openBrowser(plugin->pluginUrl); | |||
| }, plugin->pluginUrl == "")); | |||
| // version | |||
| menu->addChild(createMenuLabel("Version: " + plugin->version)); | |||
| menu->addChild(createMenuLabel(string::translate("Model.version") + plugin->version)); | |||
| // author | |||
| if (plugin->author != "") { | |||
| menu->addChild(createMenuItem("Author: " + plugin->author, "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.author") + plugin->author, "", [=]() { | |||
| system::openBrowser(plugin->authorUrl); | |||
| }, plugin->authorUrl.empty())); | |||
| } | |||
| @@ -123,17 +123,17 @@ void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) { | |||
| // license | |||
| std::string license = plugin->license; | |||
| if (string::startsWith(license, "https://") || string::startsWith(license, "http://")) { | |||
| menu->addChild(createMenuItem("License: Open in browser", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.licenseBrowser"), "", [=]() { | |||
| system::openBrowser(license); | |||
| })); | |||
| } | |||
| else if (license != "") { | |||
| menu->addChild(createMenuLabel("License: " + license)); | |||
| menu->addChild(createMenuLabel(string::translate("Model.license") + license)); | |||
| } | |||
| // tags | |||
| if (!tagIds.empty()) { | |||
| menu->addChild(createMenuLabel("Tags:")); | |||
| menu->addChild(createMenuLabel(string::translate("Model.tags"))); | |||
| for (int tagId : tagIds) { | |||
| menu->addChild(createMenuLabel("• " + tag::getTag(tagId))); | |||
| } | |||
| @@ -142,13 +142,13 @@ void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) { | |||
| menu->addChild(new ui::MenuSeparator); | |||
| // VCV Library page | |||
| menu->addChild(createMenuItem("VCV Library page", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.library"), "", [=]() { | |||
| system::openBrowser("https://library.vcvrack.com/" + plugin->slug + "/" + slug); | |||
| })); | |||
| // modularGridUrl | |||
| if (modularGridUrl != "") { | |||
| menu->addChild(createMenuItem("ModularGrid page", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.modularGrid"), "", [=]() { | |||
| system::openBrowser(modularGridUrl); | |||
| })); | |||
| } | |||
| @@ -156,42 +156,42 @@ void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) { | |||
| // manual | |||
| std::string manualUrl = getManualUrl(); | |||
| if (manualUrl != "") { | |||
| menu->addChild(createMenuItem("User manual", widget::getKeyCommandName(GLFW_KEY_F1, RACK_MOD_CTRL), [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.manual"), widget::getKeyCommandName(GLFW_KEY_F1, RACK_MOD_CTRL), [=]() { | |||
| system::openBrowser(manualUrl); | |||
| })); | |||
| } | |||
| // donate | |||
| if (plugin->donateUrl != "") { | |||
| menu->addChild(createMenuItem("Donate", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.donate"), "", [=]() { | |||
| system::openBrowser(plugin->donateUrl); | |||
| })); | |||
| } | |||
| // source code | |||
| if (plugin->sourceUrl != "") { | |||
| menu->addChild(createMenuItem("Source code", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.source"), "", [=]() { | |||
| system::openBrowser(plugin->sourceUrl); | |||
| })); | |||
| } | |||
| // changelog | |||
| if (plugin->changelogUrl != "") { | |||
| menu->addChild(createMenuItem("Changelog", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.changelog"), "", [=]() { | |||
| system::openBrowser(plugin->changelogUrl); | |||
| })); | |||
| } | |||
| // author email | |||
| if (plugin->authorEmail != "") { | |||
| menu->addChild(createMenuItem("Author email", "Copy to clipboard", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.authorEmail"), string::translate("Model.authorEmailCopy"), [=]() { | |||
| glfwSetClipboardString(APP->window->win, plugin->authorEmail.c_str()); | |||
| })); | |||
| } | |||
| // plugin folder | |||
| if (plugin->path != "") { | |||
| menu->addChild(createMenuItem("Open plugin folder", "", [=]() { | |||
| menu->addChild(createMenuItem(string::translate("Model.pluginDir"), "", [=]() { | |||
| system::openDirectory(plugin->path); | |||
| })); | |||
| } | |||
| @@ -200,7 +200,7 @@ void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) { | |||
| std::string favoriteRightText = inBrowser ? (RACK_MOD_CTRL_NAME "+click") : ""; | |||
| if (isFavorite()) | |||
| favoriteRightText += " " CHECKMARK_STRING; | |||
| menu->addChild(createMenuItem("Favorite", favoriteRightText, | |||
| menu->addChild(createMenuItem(string::translate("Model.favorite"), favoriteRightText, | |||
| [=]() { | |||
| setFavorite(!isFavorite()); | |||
| } | |||
| @@ -3,6 +3,7 @@ | |||
| #include <context.hpp> | |||
| #include <window/Window.hpp> | |||
| #include <system.hpp> | |||
| #include <string.hpp> | |||
| namespace rack { | |||
| @@ -10,9 +11,12 @@ namespace widget { | |||
| std::string getKeyName(int key) { | |||
| if (key < 32) | |||
| return ""; | |||
| // glfwGetKeyName overrides | |||
| switch (key) { | |||
| case GLFW_KEY_SPACE: return "Space"; | |||
| case GLFW_KEY_SPACE: return string::translate("key.space"); | |||
| } | |||
| // Printable characters | |||
| @@ -22,21 +26,21 @@ std::string getKeyName(int key) { | |||
| // Unprintable keys with names | |||
| switch (key) { | |||
| case GLFW_KEY_ESCAPE: return "Escape"; | |||
| case GLFW_KEY_ENTER: return "Enter"; | |||
| case GLFW_KEY_TAB: return "Tab"; | |||
| case GLFW_KEY_BACKSPACE: return "Backspace"; | |||
| case GLFW_KEY_INSERT: return "Insert"; | |||
| case GLFW_KEY_DELETE: return "Delete"; | |||
| case GLFW_KEY_RIGHT: return "Right"; | |||
| case GLFW_KEY_LEFT: return "Left"; | |||
| case GLFW_KEY_DOWN: return "Down"; | |||
| case GLFW_KEY_UP: return "Up"; | |||
| case GLFW_KEY_PAGE_UP: return "Page Up"; | |||
| case GLFW_KEY_PAGE_DOWN: return "Page Down"; | |||
| case GLFW_KEY_HOME: return "Home"; | |||
| case GLFW_KEY_END: return "End"; | |||
| case GLFW_KEY_KP_ENTER: return "Enter"; | |||
| case GLFW_KEY_ESCAPE: return string::translate("key.escape"); | |||
| case GLFW_KEY_ENTER: return string::translate("key.enter"); | |||
| case GLFW_KEY_TAB: return string::translate("key.tab"); | |||
| case GLFW_KEY_BACKSPACE: return string::translate("key.backspace"); | |||
| case GLFW_KEY_INSERT: return string::translate("key.insert"); | |||
| case GLFW_KEY_DELETE: return string::translate("key.delete"); | |||
| case GLFW_KEY_RIGHT: return string::translate("key.right"); | |||
| case GLFW_KEY_LEFT: return string::translate("key.left"); | |||
| case GLFW_KEY_DOWN: return string::translate("key.down"); | |||
| case GLFW_KEY_UP: return string::translate("key.up"); | |||
| case GLFW_KEY_PAGE_UP: return string::translate("key.pageUp"); | |||
| case GLFW_KEY_PAGE_DOWN: return string::translate("key.pageDown"); | |||
| case GLFW_KEY_HOME: return string::translate("key.home"); | |||
| case GLFW_KEY_END: return string::translate("key.end"); | |||
| case GLFW_KEY_KP_ENTER: return string::translate("key.enter"); | |||
| } | |||
| if (GLFW_KEY_F1 <= key && key <= GLFW_KEY_F25) | |||
| @@ -49,13 +53,20 @@ std::string getKeyName(int key) { | |||
| std::string getKeyCommandName(int key, int mods) { | |||
| std::string modsName; | |||
| if (mods & RACK_MOD_CTRL) { | |||
| modsName += RACK_MOD_CTRL_NAME "+"; | |||
| #if defined ARCH_MAC | |||
| modsName += "⌘"; | |||
| #else | |||
| modsName += string::translate("key.ctrl"); | |||
| #endif | |||
| modsName += "+"; | |||
| } | |||
| if (mods & GLFW_MOD_SHIFT) { | |||
| modsName += RACK_MOD_SHIFT_NAME "+"; | |||
| modsName += string::translate("key.shift"); | |||
| modsName += "+"; | |||
| } | |||
| if (mods & GLFW_MOD_ALT) { | |||
| modsName += RACK_MOD_ALT_NAME "+"; | |||
| modsName += string::translate("key.alt"); | |||
| modsName += "+"; | |||
| } | |||
| return modsName + getKeyName(key); | |||
| } | |||
| @@ -1,5 +1,25 @@ | |||
| { | |||
| "language": "English", | |||
| "translators": "", | |||
| "key.space": "Space", | |||
| "key.escape": "Escape", | |||
| "key.enter": "Enter", | |||
| "key.tab": "Tab", | |||
| "key.backspace": "Backspace", | |||
| "key.insert": "Insert", | |||
| "key.delete": "Delete", | |||
| "key.right": "Right", | |||
| "key.left": "Left", | |||
| "key.down": "Down", | |||
| "key.up": "Up", | |||
| "key.pageUp": "Page Up", | |||
| "key.pageDown": "Page Down", | |||
| "key.home": "Home", | |||
| "key.end": "End", | |||
| "key.ctrl": "Ctrl", | |||
| "key.shift": "Shift", | |||
| "key.alt": "Alt", | |||
| "MenuBar.infoLabel": "%.1f fps %.1f%% avg %.1f%% max", | |||
| "MenuBar.file": "File", | |||
| "MenuBar.file.new": "New", | |||
| "MenuBar.file.open": "Open", | |||
| @@ -146,5 +166,65 @@ | |||
| "RackWidget.duplicate": "Duplicate", | |||
| "RackWidget.duplicateWithCables": "with cables", | |||
| "RackWidget.delete": "Delete", | |||
| "RackWidget.history.clearCables": "clear cables" | |||
| "RackWidget.history.clearCables": "clear cables", | |||
| "Model.plugin": "Plugin: ", | |||
| "Model.version": "Version: ", | |||
| "Model.author": "Author: ", | |||
| "Model.licenseBrowser": "License: Open in browser", | |||
| "Model.license": "License: ", | |||
| "Model.tags": "Tags:", | |||
| "Model.library": "VCV Library page", | |||
| "Model.modularGrid": "ModularGrid page", | |||
| "Model.manual": "User manual", | |||
| "Model.donate": "Donate", | |||
| "Model.source": "Source code", | |||
| "Model.changelog": "Changelog", | |||
| "Model.authorEmail": "Author email", | |||
| "Model.authorEmailCopy": "Copy to clipboard", | |||
| "Model.pluginDir": "Open plugin folder", | |||
| "Model.favorite": "Favorite", | |||
| "Browser.history.addModule": "add module", | |||
| "Browser.tooltipTags": "Tags: ", | |||
| "Browser.sort.lastUpdated": "Last updated", | |||
| "Browser.sort.lastUsed": "Last used", | |||
| "Browser.sort.mostUsed": "Most used", | |||
| "Browser.sort.brand": "Brand", | |||
| "Browser.sort.moduleName": "Module name", | |||
| "Browser.sort.random": "Random", | |||
| "Browser.sort": "Sort: ", | |||
| "Browser.zoom": "Zoom: ", | |||
| "Browser.searchModules": "Search modules", | |||
| "Browser.favorites": "Favorites", | |||
| "Browser.resetFilters": "Reset filters", | |||
| "Browser.browseLibrary": "Browse VCV Library", | |||
| "Browser.modulesOne": "1 module", | |||
| "Browser.modulesMany": "%d modules", | |||
| "Browser.allBrands": "All brands", | |||
| "Browser.brand": "Brand", | |||
| "Browser.allTags": "All tags", | |||
| "Browser.tagsSelectMultiple": "click to select multiple", | |||
| "Browser.tags": "Tags", | |||
| "ParamWidget.history.setParam": "set parameter", | |||
| "ParamWidget.initialize": "Initialize", | |||
| "ParamWidget.doubleClick": "Double-click", | |||
| "ParamWidget.fine": "Fine adjust", | |||
| "ParamWidget.fineDrag": "drag", | |||
| "ParamWidget.unmap": "Unmap", | |||
| "ParamWidget.history.reset": "reset parameter", | |||
| "PortWidget.from": "From ", | |||
| "PortWidget.to": "To ", | |||
| "PortWidget.input": "input", | |||
| "PortWidget.output": "output", | |||
| "PortWidget.cableId": "ID: %ld", | |||
| "PortWidget.setColor": "Set color", | |||
| "PortWidget.deleteTopCable": "Delete top cable", | |||
| "PortWidget.click": "click", | |||
| "PortWidget.cloneTopCable": "Duplicate top cable", | |||
| "PortWidget.createCableTop": "Create cable on top", | |||
| "PortWidget.drag": "drag", | |||
| "PortWidget.createCable": "Create cable: ", | |||
| "PortWidget.clickDrag": "Click+drag", | |||
| "PortWidget.grabCable": " to grab cable", | |||
| "PortWidget.allCables": "All cables", | |||
| "PortWidget.history.moveCable": "move cable" | |||
| } | |||