From 6c8ba8b5bbfb36298c2198bf5f9d001a2dd82b47 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 11 Mar 2018 13:41:53 -0400 Subject: [PATCH 1/4] Define TranslatedInternalString --- src/Internat.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Internat.h b/src/Internat.h index 732db661d..21c90c6cc 100644 --- a/src/Internat.h +++ b/src/Internat.h @@ -184,4 +184,36 @@ inline wxArrayString LocalizedStrings(const wxArrayString &strings) return LocalizedStrings( &strings[0], strings.size() ); } +// This object pairs an internal string, maybe empty, with a translated string. +// Any internal string may be written to configuration or other files and, +// for compatibility, should not vary between Audacity versions. +// The translated string may be shown to users and may vary with locale, and +// Audacity version if it is decided to use a different user-visible message. +// Sometimes the translated string is derived from a msgid identical +// to the internal string. The translated string is not meant to persist. +class TranslatedInternalString +{ +public: + + TranslatedInternalString() = default; + + // One-argument constructor from a msgid + explicit TranslatedInternalString( const wxString &internal ) + : mInternal{ internal }, mTranslated{ GetCustomTranslation( internal ) } + {} + + // Two-argument version, when translated does not derive from internal + TranslatedInternalString( const wxString &internal, + const wxString &translated ) + : mInternal{ internal }, mTranslated{ translated } + {} + + const wxString &Internal() const { return mInternal; } + const wxString &Translated() const { return mTranslated; } + +private: + wxString mInternal; + wxString mTranslated; +}; + #endif From d258385e3afe10c1af8e28f8127a0a618640035c Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 15 Mar 2018 19:06:30 -0400 Subject: [PATCH 2/4] Use TranslatedInternalString in MacroCommandsCatalog --- src/BatchCommandDialog.cpp | 15 ++++++++------- src/BatchCommands.cpp | 28 ++++++++++++++++------------ src/BatchCommands.h | 3 +-- src/BatchProcessDialog.cpp | 2 +- src/commands/BatchEvalCommand.cpp | 2 +- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/BatchCommandDialog.cpp b/src/BatchCommandDialog.cpp index 2947903df..8651c936f 100644 --- a/src/BatchCommandDialog.cpp +++ b/src/BatchCommandDialog.cpp @@ -128,7 +128,7 @@ void MacroCommandDialog::PopulateCommandList() long ii = 0; for ( const auto &entry : mCatalog ) // insert the user-facing string - mChoices->InsertItem( ii++, entry.friendly /* .Translation() */ ); + mChoices->InsertItem( ii++, entry.name.Translated() ); } void MacroCommandDialog::ValidateChoices() @@ -162,18 +162,19 @@ void MacroCommandDialog::OnItemSelected(wxListEvent &event) const auto &command = mCatalog[ event.GetIndex() ]; EffectManager & em = EffectManager::Get(); - PluginID ID = em.GetEffectByIdentifier( command.internal ); + PluginID ID = em.GetEffectByIdentifier( command.name.Internal() ); // If ID is empty, then the effect wasn't found, in which case, the user must have // selected one of the "special" commands. mEditParams->Enable(!ID.IsEmpty()); mUsePreset->Enable(em.HasPresets(ID)); - if ( command.friendly == mCommand->GetValue() ) + if ( command.name.Translated() == mCommand->GetValue() ) + // This uses the assumption of uniqueness of translated names! return; - mCommand->SetValue(command.friendly); - mInternalCommandName = command.internal; + mCommand->SetValue(command.name.Translated()); + mInternalCommandName = command.name.Internal(); wxString params = MacroCommands::GetCurrentParamsFor(mInternalCommandName); if (params.IsEmpty()) @@ -221,8 +222,8 @@ void MacroCommandDialog::SetCommandAndParams(const wxString &Command, const wxSt // -- AVOID THIS! mCommand->SetValue( Command ); else { - mCommand->SetValue( iter->friendly /* .Translation() */ ); - mDetails->SetValue( iter->internal + "\r\n" + iter->category ); + mCommand->SetValue( iter->name.Translated() ); + mDetails->SetValue( iter->name.Internal() + "\r\n" + iter->category ); mChoices->SetItemState(iter - mCatalog.begin(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); diff --git a/src/BatchCommands.cpp b/src/BatchCommands.cpp index b37527785..22fa5df53 100644 --- a/src/BatchCommands.cpp +++ b/src/BatchCommands.cpp @@ -289,8 +289,7 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project ) Entries commands; for( const auto &command : SpecialCommands ) commands.push_back( { - GetCustomTranslation( command.first ), - command.second, + { command.second, GetCustomTranslation( command.first ) }, _("Special Command") } ); @@ -305,8 +304,7 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project ) auto command = em.GetCommandIdentifier(plug->GetID()); if (!command.IsEmpty()) commands.push_back( { - plug->GetTranslatedName(), - command, + { command, plug->GetTranslatedName() }, plug->GetPluginType() == PluginTypeEffect ? _("Effect") : _("Menu Command (With Parameters)") } ); @@ -350,8 +348,10 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project ) commands.push_back( { - label, // User readable name - mNames[i], // Internal name. + { + mNames[i], // Internal name. + label // User readable name + }, _("Menu Command (No Parameters)") } ); @@ -363,12 +363,14 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project ) // I'm not sure, but at least I can sort stably for a better defined result, // keeping specials before effects and menu items, and lastly commands. auto less = - [](const Entry &a, const Entry &b) { return a.friendly < b.friendly; }; + [](const Entry &a, const Entry &b) + { return a.name.Translated() < b.name.Translated(); }; std::stable_sort(commands.begin(), commands.end(), less); // Now uniquify by friendly name auto equal = - [](const Entry &a, const Entry &b) { return a.friendly == b.friendly; }; + [](const Entry &a, const Entry &b) + { return a.name.Translated() == b.name.Translated(); }; std::unique_copy( commands.begin(), commands.end(), std::back_inserter(mCommands), equal); } @@ -378,9 +380,10 @@ auto MacroCommandsCatalog::ByFriendlyName( const wxString &friendlyName ) const -> Entries::const_iterator { const auto less = [](const Entry &entryA, const Entry &entryB) - { return entryA.friendly < entryB.friendly; }; + { return entryA.name.Translated() < entryB.name.Translated(); }; auto range = std::equal_range( - begin(), end(), Entry{ friendlyName, {}, {} }, less); + begin(), end(), Entry{ { {}, friendlyName }, {} }, less + ); if (range.first != range.second) { wxASSERT_MSG( range.first + 1 == range.second, "Non-unique user-visible command name" ); @@ -396,7 +399,8 @@ auto MacroCommandsCatalog::ByCommandId( const wxString &commandId ) const { // Maybe this too should have a uniqueness check? return std::find_if( begin(), end(), - [&](const Entry &entry){ return entry.internal == commandId; }); + [&](const Entry &entry) + { return entry.name.Internal() == commandId; }); } @@ -839,7 +843,7 @@ bool MacroCommands::ApplyMacro( auto iter = catalog.ByCommandId(command); auto friendly = (iter == catalog.end()) ? command // Expose internal name to user, in default of a better one! - : iter->friendly; + : iter->name.Translated(); if (!ApplyCommandInBatchMode(friendly, command, mParamsMacro[i]) || mAbort) break; } diff --git a/src/BatchCommands.h b/src/BatchCommands.h index 76a5a6079..87eb2c7ca 100644 --- a/src/BatchCommands.h +++ b/src/BatchCommands.h @@ -25,8 +25,7 @@ class MacroCommandsCatalog { public: // A triple of user-visible name, internal string identifier and type/help string. struct Entry { - wxString friendly; - wxString internal; + TranslatedInternalString name; wxString category; }; using Entries = std::vector; diff --git a/src/BatchProcessDialog.cpp b/src/BatchProcessDialog.cpp index 58df46984..f3f034fb2 100644 --- a/src/BatchProcessDialog.cpp +++ b/src/BatchProcessDialog.cpp @@ -686,7 +686,7 @@ void MacrosWindow::AddItem(const wxString &Action, const wxString &Params) { auto entry = mCatalog.ByCommandId(Action); auto friendlyName = entry != mCatalog.end() - ? entry->friendly /* .Translation() */ + ? entry->name.Translated() : // Expose an internal name to the user in default of any friendly name // -- AVOID THIS! diff --git a/src/commands/BatchEvalCommand.cpp b/src/commands/BatchEvalCommand.cpp index 9787619a1..f5b4569d9 100644 --- a/src/commands/BatchEvalCommand.cpp +++ b/src/commands/BatchEvalCommand.cpp @@ -57,7 +57,7 @@ bool BatchEvalCommand::Apply(const CommandContext & context) auto iter = catalog.ByCommandId(cmdName); const wxString &friendly = (iter == catalog.end()) ? cmdName // Expose internal name to user, in default of a better one! - : iter->friendly; + : iter->name.Translated(); // Create a Batch that will have just one command in it... MacroCommands Batch; From 9b7ccc4dff20f91a428d6c47d76278f24a281291 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 15 Mar 2018 19:26:20 -0400 Subject: [PATCH 3/4] Use TranslatedInternalString for tips of toolbar buttons --- src/commands/CommandManager.cpp | 9 +++---- src/commands/CommandManager.h | 11 ++++----- src/toolbars/ControlToolBar.cpp | 24 +++++++++---------- src/toolbars/EditToolBar.cpp | 7 +++--- src/toolbars/ScrubbingToolBar.cpp | 6 ++--- src/toolbars/ToolBar.cpp | 4 ++-- src/toolbars/ToolBar.h | 10 +++----- src/toolbars/ToolsToolBar.cpp | 6 ++--- src/toolbars/TranscriptionToolBar.cpp | 14 ++++------- .../ui/PlayableTrackButtonHandles.cpp | 10 ++++---- src/tracks/ui/TrackButtonHandles.cpp | 10 ++++---- src/widgets/Ruler.cpp | 5 ++-- 12 files changed, 50 insertions(+), 66 deletions(-) diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index 3a797bc5b..ea910e982 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -1353,7 +1353,7 @@ void CommandManager::TellUserWhyDisallowed( const wxString & Name, CommandFlag f } wxString CommandManager::DescribeCommandsAndShortcuts -(const LocalizedCommandNameVector &commands) const +(const TranslatedInternalString commands[], size_t nCommands) const { wxString mark; // This depends on the language setting and may change in-session after @@ -1364,15 +1364,16 @@ wxString CommandManager::DescribeCommandsAndShortcuts static const wxString &separatorFormat = wxT("%s / %s"); wxString result; - for (const auto &pair : commands) { + for (size_t ii = 0; ii < nCommands; ++ii) { + const auto &pair = commands[ii]; // If RTL, then the control character forces right-to-left sequencing of // "/" -separated command names, and puts any "(...)" shortcuts to the // left, consistently with accelerators in menus (assuming matching // operating system prefernces for language), even if the command name // was missing from the translation file and defaulted to the English. - auto piece = wxString::Format(wxT("%s%s"), mark, pair.first); + auto piece = wxString::Format(wxT("%s%s"), mark, pair.Translated()); - wxString name{ pair.second }; + wxString name{ pair.Internal() }; if (!name.empty()) { auto keyStr = GetKeyFromName(name); if (!keyStr.empty()){ diff --git a/src/commands/CommandManager.h b/src/commands/CommandManager.h index 7668506f2..b3a7370b5 100644 --- a/src/commands/CommandManager.h +++ b/src/commands/CommandManager.h @@ -313,14 +313,11 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler /// /// Formatting summaries that include shortcut keys /// - using LocalizedCommandName = std::pair; - using LocalizedCommandNameVector = std::vector; wxString DescribeCommandsAndShortcuts - (// An array of paired user-visible strings, and - // non-user-visible command names. If a shortcut key is defined - // for the command, then it is appended, parenthesized, after the - // user-visible string. - const LocalizedCommandNameVector &commands) const; + ( + // If a shortcut key is defined for the command, then it is appended, + // parenthesized, after the translated name. + const TranslatedInternalString commands[], size_t nCommands) const; // Sorted list of the shortcut keys to be exluded from the standard defaults static const std::vector &ExcludedList(); diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 6eae03426..8897c6640 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -249,27 +249,27 @@ void ControlToolBar::RegenerateTooltips() name = wxT("CursProjectStart"); break; } - LocalizedCommandNameVector commands( 1u, { pCtrl->GetLabel(), name } ); + std::vector commands( + 1u, { name, pCtrl->GetLabel() } ); // Some have a second switch (iWinID) { case ID_PLAY_BUTTON: // With shift - commands.push_back( - LocalizedCommandName( _("Loop Play"), wxT("PlayLooped") ) ); + commands.push_back( { wxT("PlayLooped"), _("Loop Play") } ); break; case ID_RECORD_BUTTON: // With shift { bool bPreferNewTrack; gPrefs->Read("/GUI/PreferNewTrackRecord",&bPreferNewTrack, false); // For the shortcut tooltip. - commands.push_back( LocalizedCommandName( + commands.push_back( { + wxT("Record2ndChoice"), !bPreferNewTrack ? _("Record New Track") - : _("Append Record"), - wxT("Record2ndChoice") - )); + : _("Append Record") + } ); } break; case ID_PAUSE_BUTTON: @@ -278,16 +278,16 @@ void ControlToolBar::RegenerateTooltips() break; case ID_FF_BUTTON: // With shift - commands.push_back( LocalizedCommandName( - _("Select to End"), wxT("SelEnd") ) ); + commands.push_back( { + wxT("SelEnd"), _("Select to End") } ); break; case ID_REW_BUTTON: // With shift - commands.push_back( LocalizedCommandName( - _("Select to Start"), wxT("SelStart") ) ); + commands.push_back( { + wxT("SelStart"), _("Select to Start") } ); break; } - ToolBar::SetButtonToolTip(*pCtrl, commands); + ToolBar::SetButtonToolTip(*pCtrl, commands.data(), commands.size()); } #endif } diff --git a/src/toolbars/EditToolBar.cpp b/src/toolbars/EditToolBar.cpp index 0c0024965..622082902 100644 --- a/src/toolbars/EditToolBar.cpp +++ b/src/toolbars/EditToolBar.cpp @@ -277,10 +277,9 @@ void EditToolBar::ForAllButtons(int Action) for (const auto &entry : EditToolbarButtonList) { #if wxUSE_TOOLTIPS if( Action & ETBActTooltips ){ - LocalizedCommandNameVector commands( 1u, - { wxGetTranslation(entry.untranslatedLabel), entry.commandName } - ); - ToolBar::SetButtonToolTip(*mButtons[entry.tool], commands); + TranslatedInternalString command{ + entry.commandName, wxGetTranslation(entry.untranslatedLabel) }; + ToolBar::SetButtonToolTip( *mButtons[entry.tool], &command, 1u ); } #endif if (cm) { diff --git a/src/toolbars/ScrubbingToolBar.cpp b/src/toolbars/ScrubbingToolBar.cpp index 141005e92..4b54ee059 100644 --- a/src/toolbars/ScrubbingToolBar.cpp +++ b/src/toolbars/ScrubbingToolBar.cpp @@ -136,10 +136,10 @@ void ScrubbingToolBar::RegenerateTooltips() { #if wxUSE_TOOLTIPS auto fn = [&] - (AButton &button, const wxString &label, const wxString &command) + (AButton &button, const wxString &label, const wxString &cmd) { - LocalizedCommandNameVector commands( 1u, { label, command } ); - ToolBar::SetButtonToolTip(button, commands); + TranslatedInternalString command{ cmd, label }; + ToolBar::SetButtonToolTip( button, &command, 1u ); }; auto project = GetActiveProject(); diff --git a/src/toolbars/ToolBar.cpp b/src/toolbars/ToolBar.cpp index 3ebeb4e33..f026df7a2 100644 --- a/src/toolbars/ToolBar.cpp +++ b/src/toolbars/ToolBar.cpp @@ -825,7 +825,7 @@ void ToolBar::MakeAlternateImages(AButton &button, int idx, } void ToolBar::SetButtonToolTip -(AButton &button, const LocalizedCommandNameVector &commands) +(AButton &button, const TranslatedInternalString commands[], size_t nCommands) { wxString result; const auto project = GetActiveProject(); @@ -833,7 +833,7 @@ void ToolBar::SetButtonToolTip project ? project->GetCommandManager() : nullptr; if (commandManager) result = - commandManager->DescribeCommandsAndShortcuts(commands); + commandManager->DescribeCommandsAndShortcuts(commands, nCommands); button.SetToolTip(result); } diff --git a/src/toolbars/ToolBar.h b/src/toolbars/ToolBar.h index 4e34463cb..34ebf3a13 100644 --- a/src/toolbars/ToolBar.h +++ b/src/toolbars/ToolBar.h @@ -156,16 +156,12 @@ class ToolBar /* not final */ : public wxPanelWrapper teBmps eDisabled, wxSize size); - using LocalizedCommandName = std::pair; - using LocalizedCommandNameVector = std::vector; static void SetButtonToolTip (AButton &button, - // An array of paired user-visible strings, and - // non-user-visible command names. If a shortcut key is defined - // for the command, then it is appended, parenthesized, after the - // user-visible string. - const LocalizedCommandNameVector &commands); + // If a shortcut key is defined for the command, then it is appended, + // parenthesized, after the translated name. + const TranslatedInternalString commands[], size_t nCommands); protected: void SetButton(bool down, AButton *button); diff --git a/src/toolbars/ToolsToolBar.cpp b/src/toolbars/ToolsToolBar.cpp index f59e73a5e..4c612e758 100644 --- a/src/toolbars/ToolsToolBar.cpp +++ b/src/toolbars/ToolsToolBar.cpp @@ -138,9 +138,9 @@ void ToolsToolBar::RegenerateTooltips() }; for (const auto &entry : table) { - LocalizedCommandNameVector commands( 1u, - { wxGetTranslation(entry.untranslatedLabel), entry.commandName } ); - ToolBar::SetButtonToolTip(*mTool[entry.tool], commands); + TranslatedInternalString command{ + entry.commandName, wxGetTranslation(entry.untranslatedLabel) }; + ToolBar::SetButtonToolTip( *mTool[entry.tool], &command, 1u ); } #endif diff --git a/src/toolbars/TranscriptionToolBar.cpp b/src/toolbars/TranscriptionToolBar.cpp index cabf46b08..1917894f6 100644 --- a/src/toolbars/TranscriptionToolBar.cpp +++ b/src/toolbars/TranscriptionToolBar.cpp @@ -312,16 +312,12 @@ void TranscriptionToolBar::RegenerateTooltips() }, }; - LocalizedCommandNameVector commands; for (const auto &entry : table) { - commands.clear(); - commands.push_back( LocalizedCommandName( - wxGetTranslation(entry.untranslatedLabel), entry.commandName - ) ); - commands.push_back( LocalizedCommandName( - wxGetTranslation(entry.untranslatedLabel2), entry.commandName2 - ) ); - ToolBar::SetButtonToolTip(*mButtons[entry.tool], commands); + TranslatedInternalString commands[] = { + { entry.commandName, wxGetTranslation(entry.untranslatedLabel) }, + { entry.commandName2, wxGetTranslation(entry.untranslatedLabel2) }, + }; + ToolBar::SetButtonToolTip( *mButtons[entry.tool], commands, 2u ); } diff --git a/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp b/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp index 5efafe48e..136fe9209 100644 --- a/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp +++ b/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp @@ -48,9 +48,8 @@ wxString MuteButtonHandle::Tip(const wxMouseState &) const return name; auto commandManager = project->GetCommandManager(); - CommandManager::LocalizedCommandNameVector commands( 1u, - { name, wxT("TrackMute") } ); - return commandManager->DescribeCommandsAndShortcuts(commands); + TranslatedInternalString command{ wxT("TrackMute"), name }; + return commandManager->DescribeCommandsAndShortcuts(&command, 1u); } UIHandlePtr MuteButtonHandle::HitTest @@ -105,9 +104,8 @@ wxString SoloButtonHandle::Tip(const wxMouseState &) const return name; auto commandManager = project->GetCommandManager(); - CommandManager::LocalizedCommandNameVector commands( 1u, - { name, wxT("TrackSolo") } ); - return commandManager->DescribeCommandsAndShortcuts(commands); + TranslatedInternalString command{ wxT("TrackSolo"), name }; + return commandManager->DescribeCommandsAndShortcuts( &command, 1u ); } UIHandlePtr SoloButtonHandle::HitTest diff --git a/src/tracks/ui/TrackButtonHandles.cpp b/src/tracks/ui/TrackButtonHandles.cpp index d11e4409f..caa8265e2 100644 --- a/src/tracks/ui/TrackButtonHandles.cpp +++ b/src/tracks/ui/TrackButtonHandles.cpp @@ -115,9 +115,8 @@ wxString CloseButtonHandle::Tip(const wxMouseState &) const return name; auto commandManager = project->GetCommandManager(); - CommandManager::LocalizedCommandNameVector commands( 1u, - { name, wxT("TrackClose") } ); - return commandManager->DescribeCommandsAndShortcuts(commands); + TranslatedInternalString command{ wxT("TrackClose"), name }; + return commandManager->DescribeCommandsAndShortcuts( &command, 1u ); } UIHandlePtr CloseButtonHandle::HitTest @@ -175,9 +174,8 @@ wxString MenuButtonHandle::Tip(const wxMouseState &) const return name; auto commandManager = project->GetCommandManager(); - CommandManager::LocalizedCommandNameVector commands( 1u, - { name, wxT("TrackMenu") } ); - return commandManager->DescribeCommandsAndShortcuts(commands); + TranslatedInternalString command{ wxT("TrackMenu"), name }; + return commandManager->DescribeCommandsAndShortcuts( &command, 1u ); } UIHandlePtr MenuButtonHandle::HitTest diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 3895bfe36..1a64190b1 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -2897,9 +2897,8 @@ void AdornedRulerPanel::UpdateButtonStates() { auto common = [this] (AButton &button, const wxString &commandName, const wxString &label) { - CommandManager::LocalizedCommandNameVector commands( 1u, - { label, commandName } ); - ToolBar::SetButtonToolTip(button, commands); + TranslatedInternalString command{ commandName, label }; + ToolBar::SetButtonToolTip( button, &command, 1u ); button.SetLabel(button.GetToolTipText()); button.UpdateStatus(); From 9780c148826a2b08de7faa70a9201aab0cbe9cb1 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 15 Mar 2018 19:39:25 -0400 Subject: [PATCH 4/4] Fix mix of internal and translated strings naming Align commands... ... Revert commit 357b05efd29366b3b5b18202ea317d4e90ee9b80, and use Ukrainian, and open Select Commands in Macros, to see the problem --- src/Menus.cpp | 28 +++++++++++++++------------- src/commands/CommandManager.cpp | 26 ++++++++++++++------------ src/commands/CommandManager.h | 8 +++++--- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/Menus.cpp b/src/Menus.cpp index 97bc6557c..35f07ac33 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -1020,17 +1020,19 @@ void AudacityProject::CreateMenusAndCommands() ////////////////////////////////////////////////////////////////////////// - wxArrayString alignLabelsNoSync; - alignLabelsNoSync.Add(_("&Align End to End")); - alignLabelsNoSync.Add(_("Align &Together")); + const TranslatedInternalString alignLabelsNoSync[] = { + { wxT("EndToEnd"), _("&Align End to End") }, + { wxT("Together"), _("Align &Together") }, + }; - wxArrayString alignLabels; - alignLabels.Add(_("Start to &Zero")); - alignLabels.Add(_("Start to &Cursor/Selection Start")); - alignLabels.Add(_("Start to Selection &End")); - alignLabels.Add(_("End to Cu&rsor/Selection Start")); - alignLabels.Add(_("End to Selection En&d")); - mAlignLabelsCount = alignLabels.GetCount(); + const TranslatedInternalString alignLabels[] = { + { wxT("StartToZero"), _("Start to &Zero") }, + { wxT("StartToSelStart"), _("Start to &Cursor/Selection Start") }, + { wxT("StartToSelEnd"), _("Start to Selection &End") }, + { wxT("EndToSelStart"), _("End to Cu&rsor/Selection Start") }, + { wxT("EndToSelEnd"), _("End to Selection En&d") }, + }; + mAlignLabelsCount = sizeof(alignLabels) / sizeof(alignLabels[0]); // Calling c->SetCommandFlags() after AddItemList for "Align" and "AlignMove" // does not correctly set flags for submenus, so do it this way. @@ -1040,9 +1042,9 @@ void AudacityProject::CreateMenusAndCommands() c->BeginSubMenu(_("&Align Tracks")); //c->BeginSubMenu(_("Just Move Tracks")); - c->AddItemList(wxT("Align"), alignLabelsNoSync, FN(OnAlignNoSync)); + c->AddItemList(wxT("Align"), alignLabelsNoSync, 2u, FN(OnAlignNoSync)); c->AddSeparator(); - c->AddItemList(wxT("Align"), alignLabels, FN(OnAlign)); + c->AddItemList(wxT("Align"), alignLabels, mAlignLabelsCount, FN(OnAlign)); c->AddSeparator(); c->AddCheck(wxT("MoveSelectionWithTracks"), _("&Move Selection with Tracks (on/off)"), FN(OnMoveSelectionWithTracks), @@ -1054,7 +1056,7 @@ void AudacityProject::CreateMenusAndCommands() // TODO: Can these labels be made clearer? Do we need this sub-menu at all? c->BeginSubMenu(_("Move Sele&ction and Tracks")); - c->AddItemList(wxT("AlignMove"), alignLabels, FN(OnAlignMoveSel)); + c->AddItemList(wxT("AlignMove"), alignLabels, mAlignLabelsCount, FN(OnAlignMoveSel)); c->SetCommandFlags(wxT("AlignMove"), AudioIONotBusyFlag | TracksSelectedFlag, AudioIONotBusyFlag | TracksSelectedFlag); diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index ea910e982..ce5ae549b 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -760,7 +760,7 @@ void CommandManager::InsertItem(const wxString & name, } } - CommandListEntry *entry = NewIdentifier(name, label_in, menu, finder, callback, false, 0, 0, false); + CommandListEntry *entry = NewIdentifier(name, label_in, menu, finder, callback, {}, 0, 0, false); int ID = entry->id; wxString label = GetLabel(entry); @@ -828,7 +828,7 @@ void CommandManager::AddItem(const wxChar *name, cookedParameter = parameter; CommandListEntry *entry = NewIdentifier(name, label_in, accel, CurrentMenu(), finder, callback, - false, 0, 0, bIsEffect, cookedParameter); + {}, 0, 0, bIsEffect, cookedParameter); int ID = entry->id; wxString label = GetLabelWithDisabledAccel(entry); @@ -855,18 +855,19 @@ void CommandManager::AddItem(const wxChar *name, /// When you call Enable on this command name, it will enable or disable /// all of the items at once. void CommandManager::AddItemList(const wxString & name, - const wxArrayString & labels, + const TranslatedInternalString items[], + size_t nItems, CommandHandlerFinder finder, CommandFunctorPointer callback, bool bIsEffect) { - for (size_t i = 0, cnt = labels.GetCount(); i < cnt; i++) { + for (size_t i = 0, cnt = nItems; i < cnt; i++) { CommandListEntry *entry = NewIdentifier(name, - labels[i], + items[i].Translated(), CurrentMenu(), finder, callback, - true, + items[i].Internal(), i, cnt, bIsEffect); @@ -896,7 +897,7 @@ void CommandManager::AddCommand(const wxChar *name, CommandFlag flags, CommandMask mask) { - NewIdentifier(name, label_in, accel, NULL, finder, callback, false, 0, 0, false, {}); + NewIdentifier(name, label_in, accel, NULL, finder, callback, {}, 0, 0, false, {}); if (flags != NoFlagsSpecifed || mask != NoFlagsSpecifed) { SetCommandFlags(name, flags, mask); @@ -911,7 +912,7 @@ void CommandManager::AddGlobalCommand(const wxChar *name, { CommandListEntry *entry = NewIdentifier(name, label_in, accel, NULL, finder, callback, - false, 0, 0, false, {}); + {}, 0, 0, false, {}); entry->enabled = false; entry->isGlobal = true; @@ -947,7 +948,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name, wxMenu *menu, CommandHandlerFinder finder, CommandFunctorPointer callback, - bool multi, + const wxString &nameSuffix, int index, int count, bool bIsEffect) @@ -958,7 +959,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name, menu, finder, callback, - multi, + nameSuffix, index, count, bIsEffect, @@ -971,12 +972,13 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn, wxMenu *menu, CommandHandlerFinder finder, CommandFunctorPointer callback, - bool multi, + const wxString &nameSuffix, int index, int count, bool bIsEffect, const CommandParameter ¶meter) { + const bool multi = !nameSuffix.empty(); wxString name = nameIn; // If we have the identifier already, reuse it. @@ -1001,7 +1003,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn, // This feature is not used for built-in effects. if (multi) { // The name needs to be clean for use by automation. - wxString cleanedName = wxString::Format(wxT("%s_%s"), name, label); + wxString cleanedName = wxString::Format(wxT("%s_%s"), name, nameSuffix); cleanedName.Replace( "/", "" ); cleanedName.Replace( "&", "" ); cleanedName.Replace( " ", "" ); diff --git a/src/commands/CommandManager.h b/src/commands/CommandManager.h index b3a7370b5..b4ab77809 100644 --- a/src/commands/CommandManager.h +++ b/src/commands/CommandManager.h @@ -33,6 +33,7 @@ #endif using CommandParameter = wxString; +class TranslatedInternalString; struct MenuBarListEntry { @@ -161,7 +162,8 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler int checkmark = -1); void AddItemList(const wxString & name, - const wxArrayString & labels, + const TranslatedInternalString items[], + size_t nItems, CommandHandlerFinder finder, CommandFunctorPointer callback, bool bIsEffect = false); @@ -334,7 +336,7 @@ protected: wxMenu *menu, CommandHandlerFinder finder, CommandFunctorPointer callback, - bool multi, + const wxString &nameSuffix, int index, int count, bool bIsEffect); @@ -344,7 +346,7 @@ protected: wxMenu *menu, CommandHandlerFinder finder, CommandFunctorPointer callback, - bool multi, + const wxString &nameSuffix, int index, int count, bool bIsEffect,