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.

181 lines
7.3KB

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