This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 953d1c02ea Search on EN properties too when using different language, 
fixes #2633 (#7375)
953d1c02ea is described below

commit 953d1c02ea76a986aac961e7b078dc0d314f2bf9
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Tue Jun 30 14:58:19 2026 +0200

    Search on EN properties too when using different language, fixes #2633 
(#7375)
---
 .../apache/hop/core/plugins/BasePluginType.java    | 184 ++++++++++++++++----
 .../java/org/apache/hop/core/plugins/IPlugin.java  |  21 +++
 .../java/org/apache/hop/core/plugins/Plugin.java   |  19 +++
 .../plugins/BasePluginTypeEnglishKeywordsTest.java | 187 +++++++++++++++++++++
 .../englishsearch/messages/messages.properties     |  19 +++
 .../messages/messages_fr_FR.properties             |  19 +++
 .../hopgui/file/pipeline/HopGuiPipelineGraph.java  |   2 +
 .../pipeline/context/HopGuiPipelineContext.java    |   4 +
 .../hopgui/file/workflow/HopGuiWorkflowGraph.java  |   2 +
 .../workflow/context/HopGuiWorkflowContext.java    |   2 +
 10 files changed, 423 insertions(+), 36 deletions(-)

diff --git a/core/src/main/java/org/apache/hop/core/plugins/BasePluginType.java 
b/core/src/main/java/org/apache/hop/core/plugins/BasePluginType.java
index c6e7e06562..4be3a06f31 100644
--- a/core/src/main/java/org/apache/hop/core/plugins/BasePluginType.java
+++ b/core/src/main/java/org/apache/hop/core/plugins/BasePluginType.java
@@ -31,12 +31,18 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.time.StopWatch;
@@ -49,6 +55,7 @@ import org.apache.hop.core.util.Utils;
 import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.i18n.BaseMessages;
 import org.apache.hop.i18n.GlobalMessageUtil;
+import org.apache.hop.i18n.LanguageChoice;
 import org.jboss.jandex.AnnotationInstance;
 import org.jboss.jandex.ClassInfo;
 import org.jboss.jandex.IndexView;
@@ -60,9 +67,9 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
 
   protected final PluginRegistry registry;
 
-  private String id;
+  @Setter private String id;
 
-  private String name;
+  @Setter private String name;
 
   private final LogChannel log;
 
@@ -70,7 +77,7 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
 
   private final Class<T> pluginClass;
 
-  private List<String> extraLibraryFolders;
+  @Setter @Getter private List<String> extraLibraryFolders;
 
   public BasePluginType(Class<T> pluginClazz) {
     this.log = new LogChannel("Plugin type");
@@ -187,13 +194,6 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
     return id;
   }
 
-  /**
-   * @param id the id to set
-   */
-  public void setId(String id) {
-    this.id = id;
-  }
-
   /**
    * @return the name
    */
@@ -202,13 +202,6 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
     return name;
   }
 
-  /**
-   * @param name the name to set
-   */
-  public void setName(String name) {
-    this.name = name;
-  }
-
   protected static String getCodedTranslation(String codedString) {
     if (codedString == null) {
       return null;
@@ -295,6 +288,134 @@ public abstract class BasePluginType<T extends 
Annotation> implements IPluginTyp
     }
   }
 
+  /**
+   * Builds the English-locale search aliases for a plugin: its name, category 
and keywords resolved
+   * against the English (failover) locale, with anything that already matches 
in the active locale
+   * removed. The context dialog adds these to a transform/action's searchable 
keywords so a user
+   * can find it by its English term even when the UI runs in another language 
(issue #2633).
+   *
+   * @return the deduplicated English aliases, or an empty array when the UI 
is already English
+   */
+  protected String[] extractEnglishSearchKeywords(
+      T annotation,
+      String packageName,
+      Class<?> clazz,
+      String localizedName,
+      String localizedCategory,
+      String[] localizedKeywords) {
+
+    // When the UI is already English the localized strings are the English 
strings: nothing to add.
+    //
+    Locale defaultLocale = LanguageChoice.getInstance().getDefaultLocale();
+    if (defaultLocale == null
+        || GlobalMessageUtil.FAILOVER_LOCALE
+            .getLanguage()
+            .equalsIgnoreCase(defaultLocale.getLanguage())) {
+      return new String[0];
+    }
+
+    // The terms we already match on in the active locale, used to avoid 
redundant aliases.
+    //
+    Set<String> alreadyMatched = new LinkedHashSet<>();
+    addSearchTerm(alreadyMatched, localizedName);
+    addSearchTerm(alreadyMatched, localizedCategory);
+    if (localizedKeywords != null) {
+      for (String keyword : localizedKeywords) {
+        addSearchTerm(alreadyMatched, keyword);
+      }
+    }
+
+    // Resolve the same annotation values against English and keep only the 
genuinely new terms.
+    //
+    Set<String> aliases = new LinkedHashSet<>();
+    collectEnglishAlias(
+        aliases,
+        alreadyMatched,
+        getEnglishTranslation(extractName(annotation), packageName, clazz));
+    collectEnglishAlias(
+        aliases,
+        alreadyMatched,
+        getEnglishTranslation(extractCategory(annotation), packageName, 
clazz));
+    String[] englishKeywords =
+        getEnglishTranslations(extractKeywords(annotation), packageName, 
clazz);
+    if (englishKeywords != null) {
+      for (String keyword : englishKeywords) {
+        collectEnglishAlias(aliases, alreadyMatched, keyword);
+      }
+    }
+
+    return aliases.toArray(new String[0]);
+  }
+
+  private static void addSearchTerm(Set<String> terms, String term) {
+    if (StringUtils.isNotEmpty(term)) {
+      terms.add(term.toLowerCase());
+    }
+  }
+
+  private static void collectEnglishAlias(
+      Set<String> aliases, Set<String> alreadyMatched, String englishTerm) {
+    if (StringUtils.isNotEmpty(englishTerm)
+        && !alreadyMatched.contains(englishTerm.toLowerCase())) {
+      aliases.add(englishTerm);
+    }
+  }
+
+  /** Mirrors {@link #getTranslations} but resolves every entry against the 
English locale. */
+  protected static String[] getEnglishTranslations(
+      String[] strings, String packageName, Class<?> resourceClass) {
+    if (strings == null) {
+      return null;
+    }
+    String[] translations = new String[strings.length];
+    for (int i = 0; i < translations.length; i++) {
+      translations[i] = getEnglishTranslation(strings[i], packageName, 
resourceClass);
+    }
+    return translations;
+  }
+
+  /**
+   * Resolves an annotation value against the English (failover) locale, 
mirroring {@link
+   * #getTranslation} but without consulting the active locale. Returns {@code 
null} when an
+   * i18n-coded key cannot be resolved so the raw {@code i18n:...} code never 
leaks into the search
+   * keywords.
+   */
+  protected static String getEnglishTranslation(
+      String string, String packageName, Class<?> resourceClass) {
+    if (string == null) {
+      return null;
+    }
+
+    if (string.startsWith(Const.I18N_PREFIX)) {
+      String[] parts = string.split(":");
+      if (parts.length != 3) {
+        return string;
+      }
+      String i18nPackage = StringUtils.isEmpty(parts[1]) ? packageName : 
parts[1];
+      return lookupEnglishString(i18nPackage, parts[2], resourceClass);
+    }
+
+    if (Utils.isEmpty(packageName)) {
+      // Translations are not supported, simply keep the original text.
+      return string;
+    }
+    String english = lookupEnglishString(packageName, string, resourceClass);
+    return english != null ? english : string;
+  }
+
+  private static String lookupEnglishString(
+      String i18nPackage, String key, Class<?> resourceClass) {
+    try {
+      ResourceBundle bundle =
+          GlobalMessageUtil.getBundle(
+              GlobalMessageUtil.FAILOVER_LOCALE, i18nPackage + 
".messages.messages", resourceClass);
+      return bundle.getString(key);
+    } catch (MissingResourceException e) {
+      // No English resource for this key: leave it to the caller to fall back.
+      return null;
+    }
+  }
+
   protected List<PluginClassFile> findAnnotatedClassFiles(String 
annotationClassName)
       throws HopPluginException {
     JarCache cache = JarCache.getInstance();
@@ -322,7 +443,7 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
                   new PluginClassFile(className, jarFile.toURI().toURL(), 
folder.toURI().toURL()));
 
             } catch (Exception e) {
-              System.out.println(
+              LogChannel.GENERAL.logError(
                   "Error searching annotation for " + pluginClass + " in " + 
jarFile);
             }
           }
@@ -395,7 +516,7 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
                   "jar", "JAR",
                 },
                 true);
-        jarFiles.stream().forEach(file -> files.add(file.getPath()));
+        jarFiles.forEach(file -> files.add(file.getPath()));
       }
     }
     return files;
@@ -421,7 +542,7 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
                     "jar", "JAR",
                   },
                   true);
-          jarFiles.stream().forEach(file -> files.add(file.getAbsolutePath()));
+          jarFiles.forEach(file -> files.add(file.getAbsolutePath()));
         }
       }
     }
@@ -752,6 +873,13 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
     plugin.setSupportedEngines(supportedEngines);
     plugin.setExcludedEngines(excludedEngines);
 
+    // English-locale search aliases so the context dialog finds a 
transform/action by its original
+    // English name, category or keywords even when the UI runs in another 
language (issue #2633).
+    //
+    plugin.setEnglishKeywords(
+        extractEnglishSearchKeywords(
+            annotation, packageName, clazz, pluginName, category, keywords));
+
     ParentFirst parentFirstAnnotation = clazz.getAnnotation(ParentFirst.class);
     if (parentFirstAnnotation != null) {
       registry.addParentClassLoaderPatterns(plugin, 
parentFirstAnnotation.patterns());
@@ -768,22 +896,6 @@ public abstract class BasePluginType<T extends Annotation> 
implements IPluginTyp
     }
   }
 
-  /**
-   * Gets extraLibraryFolders
-   *
-   * @return value of extraLibraryFolders
-   */
-  public List<String> getExtraLibraryFolders() {
-    return extraLibraryFolders;
-  }
-
-  /**
-   * @param extraLibraryFolders The extraLibraryFolders to set
-   */
-  public void setExtraLibraryFolders(List<String> extraLibraryFolders) {
-    this.extraLibraryFolders = extraLibraryFolders;
-  }
-
   /**
    * Register an extra plugin from the classpath. Useful for testing.
    *
diff --git a/core/src/main/java/org/apache/hop/core/plugins/IPlugin.java 
b/core/src/main/java/org/apache/hop/core/plugins/IPlugin.java
index 057b142cce..b2c0c5ee21 100644
--- a/core/src/main/java/org/apache/hop/core/plugins/IPlugin.java
+++ b/core/src/main/java/org/apache/hop/core/plugins/IPlugin.java
@@ -227,6 +227,27 @@ public interface IPlugin {
     // intentional no-op default
   }
 
+  /**
+   * English-locale aliases for this plugin's name, category and keywords. 
These let the context
+   * dialog match a transform/action by its original English term even when 
the UI runs in another
+   * language (issue #2633). Empty when the UI is already English (the 
localized values are the
+   * English ones) or for external implementations that don't participate.
+   *
+   * <p>Default returns an empty array so existing external {@link IPlugin} 
implementations stay
+   * binary-compatible.
+   */
+  default String[] getEnglishKeywords() {
+    return new String[0];
+  }
+
+  /**
+   * Setter counterpart to {@link #getEnglishKeywords()}. Default no-op so 
external {@link IPlugin}
+   * implementers don't have to participate — concrete plugins ({@link 
Plugin}) override this.
+   */
+  default void setEnglishKeywords(String[] englishKeywords) {
+    // intentional no-op default
+  }
+
   /**
    * A flag to indicate that the plugin needs libraries outside of the plugin 
folder
    *
diff --git a/core/src/main/java/org/apache/hop/core/plugins/Plugin.java 
b/core/src/main/java/org/apache/hop/core/plugins/Plugin.java
index 54f347fc43..e9c7b3c53d 100644
--- a/core/src/main/java/org/apache/hop/core/plugins/Plugin.java
+++ b/core/src/main/java/org/apache/hop/core/plugins/Plugin.java
@@ -62,6 +62,7 @@ public class Plugin implements IPlugin, Comparable<Plugin> {
 
   private String[] supportedEngines = new String[0];
   private String[] excludedEngines = new String[0];
+  private String[] englishKeywords = new String[0];
 
   public Plugin(
       String[] ids,
@@ -607,6 +608,24 @@ public class Plugin implements IPlugin, Comparable<Plugin> 
{
     this.keywords = keywords;
   }
 
+  /**
+   * Gets the English-locale search aliases (name, category and keywords).
+   *
+   * @return value of englishKeywords
+   */
+  @Override
+  public String[] getEnglishKeywords() {
+    return englishKeywords;
+  }
+
+  /**
+   * @param englishKeywords The English-locale search aliases to set
+   */
+  @Override
+  public void setEnglishKeywords(String[] englishKeywords) {
+    this.englishKeywords = englishKeywords;
+  }
+
   /**
    * Gets usingLibrariesOutsidePluginFolder
    *
diff --git 
a/engine/src/test/java/org/apache/hop/core/plugins/BasePluginTypeEnglishKeywordsTest.java
 
b/engine/src/test/java/org/apache/hop/core/plugins/BasePluginTypeEnglishKeywordsTest.java
new file mode 100644
index 0000000000..f2fb03801a
--- /dev/null
+++ 
b/engine/src/test/java/org/apache/hop/core/plugins/BasePluginTypeEnglishKeywordsTest.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.core.plugins;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import org.apache.hop.core.annotations.Transform;
+import org.apache.hop.i18n.LanguageChoice;
+import org.apache.hop.junit.rules.RestoreHopEnvironmentExtension;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ * Unit tests for the English-locale search aliases added by {@link 
BasePluginType} (issue #2633).
+ * When the UI runs in a non-English language, a transform/action must still 
be findable in the
+ * context dialog by its original English name, category and keywords.
+ *
+ * <p>The tests drive the real {@link TransformPluginType} (a {@link 
BasePluginType} subclass) with
+ * a synthetic {@code @Transform} fixture whose i18n keys point at the test 
bundle {@code
+ * org/apache/hop/core/plugins/englishsearch/messages/messages*.properties} 
(English base + {@code
+ * _fr_FR}).
+ */
+@ExtendWith(RestoreHopEnvironmentExtension.class)
+class BasePluginTypeEnglishKeywordsTest {
+
+  private static final String NAME_KEY =
+      "i18n:org.apache.hop.core.plugins.englishsearch:EnglishSearch.Name";
+  private static final String CATEGORY_KEY =
+      "i18n:org.apache.hop.core.plugins.englishsearch:EnglishSearch.Category";
+  private static final String KEYWORDS_KEY =
+      "i18n:org.apache.hop.core.plugins.englishsearch:EnglishSearch.Keywords";
+
+  private Locale originalLocale;
+
+  @BeforeEach
+  void rememberLocale() {
+    originalLocale = LanguageChoice.getInstance().getDefaultLocale();
+  }
+
+  @AfterEach
+  void restoreLocale() {
+    LanguageChoice.getInstance().setDefaultLocale(originalLocale);
+  }
+
+  @Test
+  void frenchLocaleAddsEnglishAliasesForNameCategoryAndKeywords() {
+    LanguageChoice.getInstance().setDefaultLocale(Locale.FRENCH);
+
+    // Localized terms differ from English, so all three English variants must 
be added as aliases.
+    List<String> aliases =
+        Arrays.asList(extractAliases("Génération de lignes", "Entrée", new 
String[] {"ligne"}));
+
+    assertTrue(aliases.contains("Generate rows"), "English name missing: " + 
aliases);
+    assertTrue(aliases.contains("Input"), "English category missing: " + 
aliases);
+    assertTrue(aliases.contains("row,generator"), "English keywords missing: " 
+ aliases);
+  }
+
+  @Test
+  void dedupSkipsTermsAlreadyMatchedInTheActiveLocale() {
+    LanguageChoice.getInstance().setDefaultLocale(Locale.FRENCH);
+
+    // The active-locale terms already equal their English counterparts: 
nothing new to add.
+    String[] aliases = extractAliases("Generate rows", "Input", new String[] 
{"row,generator"});
+
+    assertEquals(0, aliases.length, "Expected no aliases, got: " + 
Arrays.toString(aliases));
+  }
+
+  @Test
+  void englishLocaleAddsNoAliases() {
+    LanguageChoice.getInstance().setDefaultLocale(Locale.US);
+
+    String[] aliases = extractAliases("anything", "anything", new String[] 
{"anything"});
+
+    assertEquals(0, aliases.length, "Expected no aliases, got: " + 
Arrays.toString(aliases));
+  }
+
+  @Test
+  void getEnglishTranslationResolvesEnglishRegardlessOfActiveLocale() {
+    LanguageChoice.getInstance().setDefaultLocale(Locale.FRENCH);
+
+    assertEquals(
+        "Generate rows",
+        BasePluginType.getEnglishTranslation(NAME_KEY, packageName(), 
EnglishSearchFixture.class));
+    assertEquals(
+        "Input",
+        BasePluginType.getEnglishTranslation(
+            CATEGORY_KEY, packageName(), EnglishSearchFixture.class));
+  }
+
+  @Test
+  void getEnglishTranslationReturnsNullForUnresolvableI18nCode() {
+    // An i18n-coded key that has no entry must not leak the raw "i18n:..." 
code into the search
+    // set.
+    assertNull(
+        BasePluginType.getEnglishTranslation(
+            "i18n:org.apache.hop.core.plugins.englishsearch:No.Such.Key",
+            packageName(),
+            EnglishSearchFixture.class));
+  }
+
+  @Test
+  void getEnglishTranslationKeepsPlainStringWhenTranslationsUnsupported() {
+    assertEquals(
+        "PlainEnglish",
+        BasePluginType.getEnglishTranslation("PlainEnglish", "", 
EnglishSearchFixture.class));
+    assertNull(
+        BasePluginType.getEnglishTranslation(null, packageName(), 
EnglishSearchFixture.class));
+  }
+
+  @Test
+  void unresolvableI18nKeywordIsNotAddedAsAlias() {
+    LanguageChoice.getInstance().setDefaultLocale(Locale.FRENCH);
+
+    Transform annotation = 
UnresolvableKeywordFixture.class.getAnnotation(Transform.class);
+    String[] aliases =
+        TransformPluginType.getInstance()
+            .extractEnglishSearchKeywords(
+                annotation,
+                packageName(),
+                UnresolvableKeywordFixture.class,
+                "Nom",
+                "Catégorie",
+                new String[] {"motclef"});
+
+    assertFalse(
+        Arrays.stream(aliases).anyMatch(a -> a.startsWith("i18n:")),
+        "Raw i18n code leaked into search aliases: " + 
Arrays.toString(aliases));
+  }
+
+  // ---- helpers 
--------------------------------------------------------------------------------
+
+  private static String packageName() {
+    return EnglishSearchFixture.class.getPackage().getName();
+  }
+
+  private static String[] extractAliases(
+      String localizedName, String localizedCategory, String[] 
localizedKeywords) {
+    Transform annotation = 
EnglishSearchFixture.class.getAnnotation(Transform.class);
+    return TransformPluginType.getInstance()
+        .extractEnglishSearchKeywords(
+            annotation,
+            packageName(),
+            EnglishSearchFixture.class,
+            localizedName,
+            localizedCategory,
+            localizedKeywords);
+  }
+
+  // ---- fixture annotations 
--------------------------------------------------------------------
+
+  @Transform(
+      id = "EnglishSearchFixture",
+      name = NAME_KEY,
+      categoryDescription = CATEGORY_KEY,
+      keywords = {KEYWORDS_KEY})
+  private static final class EnglishSearchFixture {}
+
+  @Transform(
+      id = "UnresolvableKeywordFixture",
+      name = NAME_KEY,
+      categoryDescription = CATEGORY_KEY,
+      keywords = 
{"i18n:org.apache.hop.core.plugins.englishsearch:No.Such.Key"})
+  private static final class UnresolvableKeywordFixture {}
+}
diff --git 
a/engine/src/test/resources/org/apache/hop/core/plugins/englishsearch/messages/messages.properties
 
b/engine/src/test/resources/org/apache/hop/core/plugins/englishsearch/messages/messages.properties
new file mode 100644
index 0000000000..912c7c00f4
--- /dev/null
+++ 
b/engine/src/test/resources/org/apache/hop/core/plugins/englishsearch/messages/messages.properties
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EnglishSearch.Name=Generate rows
+EnglishSearch.Category=Input
+EnglishSearch.Keywords=row,generator
diff --git 
a/engine/src/test/resources/org/apache/hop/core/plugins/englishsearch/messages/messages_fr_FR.properties
 
b/engine/src/test/resources/org/apache/hop/core/plugins/englishsearch/messages/messages_fr_FR.properties
new file mode 100644
index 0000000000..097e43a61b
--- /dev/null
+++ 
b/engine/src/test/resources/org/apache/hop/core/plugins/englishsearch/messages/messages_fr_FR.properties
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EnglishSearch.Name=Génération de lignes
+EnglishSearch.Category=Entrée
+# EnglishSearch.Keywords intentionally left untranslated to exercise the en_US 
fallback
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index 42a074d570..695102723d 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -3319,6 +3319,8 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
                       context.getClick()));
       guiAction.getKeywords().addAll(Arrays.asList(plugin.getKeywords()));
       guiAction.getKeywords().add(plugin.getCategory());
+      // Also search on the English name/category/keywords for non-English 
locales (issue #2633)
+      
guiAction.getKeywords().addAll(Arrays.asList(plugin.getEnglishKeywords()));
       guiAction.setCategory(plugin.getCategory());
       guiAction.setCategoryOrder(plugin.getCategory());
       try {
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/context/HopGuiPipelineContext.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/context/HopGuiPipelineContext.java
index 69187f435f..8587dc92a7 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/context/HopGuiPipelineContext.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/context/HopGuiPipelineContext.java
@@ -103,6 +103,10 @@ public class HopGuiPipelineContext extends 
BaseGuiContextHandler implements IGui
                       true,
                       click));
       
createTransformAction.getKeywords().addAll(Arrays.asList(transformPlugin.getKeywords()));
+      // Also search on the English name/category/keywords for non-English 
locales (issue #2633)
+      createTransformAction
+          .getKeywords()
+          .addAll(Arrays.asList(transformPlugin.getEnglishKeywords()));
       createTransformAction.setCategory(transformPlugin.getCategory());
       createTransformAction.setCategoryOrder(
           "9999_" + transformPlugin.getCategory()); // sort alphabetically
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
index 7de1bd7f97..fc87bc46f9 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
@@ -2920,6 +2920,8 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
                       context.getClick()));
       guiAction.getKeywords().addAll(Arrays.asList(plugin.getKeywords()));
       guiAction.getKeywords().add(plugin.getCategory());
+      // Also search on the English name/category/keywords for non-English 
locales (issue #2633)
+      
guiAction.getKeywords().addAll(Arrays.asList(plugin.getEnglishKeywords()));
       guiAction.setCategory(plugin.getCategory());
       guiAction.setCategoryOrder(plugin.getCategory());
 
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/context/HopGuiWorkflowContext.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/context/HopGuiWorkflowContext.java
index 764a09c005..042eea05a5 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/context/HopGuiWorkflowContext.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/context/HopGuiWorkflowContext.java
@@ -102,6 +102,8 @@ public class HopGuiWorkflowContext extends 
BaseGuiContextHandler implements IGui
                       controlClicked,
                       click));
       
createActionGuiAction.getKeywords().addAll(Arrays.asList(actionPlugin.getKeywords()));
+      // Also search on the English name/category/keywords for non-English 
locales (issue #2633)
+      
createActionGuiAction.getKeywords().addAll(Arrays.asList(actionPlugin.getEnglishKeywords()));
       createActionGuiAction.setCategory(actionPlugin.getCategory());
       createActionGuiAction.setCategoryOrder(
           "9999_" + actionPlugin.getCategory()); // sort alphabetically

Reply via email to