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.

204 lines
8.2KB

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