The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
8.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #ifndef JUCER_TRANSLATIONTOOLCOMPONENT_H_INCLUDED
  18. #define JUCER_TRANSLATIONTOOLCOMPONENT_H_INCLUDED
  19. #include "jucer_TranslationHelpers.h"
  20. //==============================================================================
  21. class TranslationToolComponent : public Component,
  22. public ButtonListener
  23. {
  24. public:
  25. TranslationToolComponent()
  26. : editorOriginal (documentOriginal, nullptr),
  27. editorPre (documentPre, nullptr),
  28. editorPost (documentPost, nullptr),
  29. editorResult (documentResult, nullptr)
  30. {
  31. instructionsLabel.setText (
  32. "This utility converts translation files to/from a format that can be passed to automatic translation tools."
  33. "\n\n"
  34. "First, choose whether to scan the current project for all TRANS() macros, or "
  35. "pick an existing translation file to load:", dontSendNotification);
  36. addAndMakeVisible (instructionsLabel);
  37. label1.setText ("..then copy-and-paste this annotated text into Google Translate or some other translator:", dontSendNotification);
  38. addAndMakeVisible (label1);
  39. label2.setText ("...then, take the translated result and paste it into the box below:", dontSendNotification);
  40. addAndMakeVisible (label2);
  41. label3.setText ("Finally, click the 'Generate' button, and a translation file will be created below. "
  42. "Remember to update its language code at the top!", dontSendNotification);
  43. addAndMakeVisible (label3);
  44. label4.setText ("If you load an existing file the already translated strings will be removed. Ensure this box is empty to create a fresh translation", dontSendNotification);
  45. addAndMakeVisible (label4);
  46. addAndMakeVisible (editorOriginal);
  47. addAndMakeVisible (editorPre);
  48. addAndMakeVisible (editorPost);
  49. addAndMakeVisible (editorResult);
  50. generateButton.setButtonText (TRANS("Generate"));
  51. addAndMakeVisible (generateButton);
  52. scanProjectButton.setButtonText ("Scan Project for TRANS macros");
  53. addAndMakeVisible (scanProjectButton);
  54. scanFolderButton.setButtonText ("Scan Folder for TRANS macros");
  55. addAndMakeVisible (scanFolderButton);
  56. loadTranslationButton.setButtonText ("Load existing translation File...");
  57. addAndMakeVisible (loadTranslationButton);
  58. generateButton.addListener (this);
  59. scanProjectButton.addListener (this);
  60. scanFolderButton.addListener (this);
  61. loadTranslationButton.addListener (this);
  62. }
  63. void paint (Graphics& g) override
  64. {
  65. g.fillAll (findColour (backgroundColourId));
  66. }
  67. void resized() override
  68. {
  69. const int m = 6;
  70. const int textH = 44;
  71. const int extraH = (7 * textH);
  72. const int editorH = (getHeight() - extraH) / 4;
  73. const int numButtons = 3;
  74. Rectangle<int> r (getLocalBounds().withTrimmedBottom (m));
  75. const int buttonWidth = r.getWidth() / numButtons;
  76. instructionsLabel.setBounds (r.removeFromTop (textH * 2).reduced (m));
  77. r.removeFromTop (m);
  78. Rectangle<int> r2 (r.removeFromTop (textH - (2 * m)));
  79. scanProjectButton .setBounds (r2.removeFromLeft (buttonWidth).reduced (m, 0));
  80. scanFolderButton .setBounds (r2.removeFromLeft (buttonWidth).reduced (m, 0));
  81. loadTranslationButton.setBounds (r2.reduced (m, 0));
  82. label1 .setBounds (r.removeFromTop (textH) .reduced (m));
  83. editorPre.setBounds (r.removeFromTop (editorH).reduced (m, 0));
  84. label2 .setBounds (r.removeFromTop (textH) .reduced (m));
  85. editorPost.setBounds (r.removeFromTop (editorH).reduced (m, 0));
  86. r2 = r.removeFromTop (textH);
  87. generateButton.setBounds (r2.removeFromRight (152).reduced (m));
  88. label3 .setBounds (r2.reduced (m));
  89. editorResult .setBounds (r.removeFromTop (editorH).reduced (m, 0));
  90. label4 .setBounds (r.removeFromTop (textH).reduced (m));
  91. editorOriginal.setBounds (r.reduced (m, 0));
  92. }
  93. private:
  94. CodeDocument documentOriginal, documentPre, documentPost, documentResult;
  95. CodeEditorComponent editorOriginal, editorPre, editorPost, editorResult;
  96. Label label1, label2, label3, label4;
  97. TextButton generateButton;
  98. Label instructionsLabel;
  99. TextButton scanProjectButton;
  100. TextButton scanFolderButton;
  101. TextButton loadTranslationButton;
  102. void buttonClicked (Button* b) override
  103. {
  104. if (b == &generateButton) generate();
  105. else if (b == &scanProjectButton) scanProject();
  106. else if (b == &scanFolderButton) scanFolder();
  107. else if (b == &loadTranslationButton) loadFile();
  108. else
  109. jassertfalse;
  110. }
  111. void generate()
  112. {
  113. StringArray preStrings (TranslationHelpers::breakApart (documentPre.getAllContent()));
  114. StringArray postStrings (TranslationHelpers::breakApart (documentPost.getAllContent()));
  115. if (postStrings.size() != preStrings.size())
  116. {
  117. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  118. TRANS("Error"),
  119. TRANS("The pre- and post-translation text doesn't match!\n\n"
  120. "Perhaps it got mangled by the translator?"));
  121. return;
  122. }
  123. const LocalisedStrings originalTranslation (documentOriginal.getAllContent(), false);
  124. documentResult.replaceAllContent (TranslationHelpers::createFinishedTranslationFile (preStrings, postStrings, originalTranslation));
  125. }
  126. void scanProject()
  127. {
  128. if (Project* project = ProjucerApplication::getApp().mainWindowList.getFrontmostProject())
  129. setPreTranslationText (TranslationHelpers::getPreTranslationText (*project));
  130. else
  131. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Translation Tool",
  132. "This will only work when you have a project open!");
  133. }
  134. void scanFolder()
  135. {
  136. FileChooser fc ("Choose the root folder to search for the TRANS macros",
  137. File(), "*");
  138. if (fc.browseForDirectory())
  139. {
  140. StringArray strings;
  141. TranslationHelpers::scanFolderForTranslations (strings, fc.getResult());
  142. setPreTranslationText (TranslationHelpers::mungeStrings(strings));
  143. }
  144. }
  145. void loadFile()
  146. {
  147. FileChooser fc ("Choose a translation file to load",
  148. File(), "*");
  149. if (fc.browseForFileToOpen())
  150. {
  151. const LocalisedStrings loadedStrings (fc.getResult(), false);
  152. documentOriginal.replaceAllContent (fc.getResult().loadFileAsString().trim());
  153. setPreTranslationText (TranslationHelpers::getPreTranslationText (loadedStrings));
  154. }
  155. }
  156. void setPreTranslationText (const String& text)
  157. {
  158. documentPre.replaceAllContent (text);
  159. editorPre.grabKeyboardFocus();
  160. editorPre.selectAll();
  161. }
  162. };
  163. #endif // JUCER_TRANSLATIONTOOLCOMPONENT_H_INCLUDED