Skip to content

Commit

Permalink
Dropdown feature for Locale selection (#215)
Browse files Browse the repository at this point in the history
* Add getLocales method to return locales list in PluginImpl (#211)

* Update textbox to dropdown for locale selection (#211)

* Add unit tests for PluginImpl (#211)

* Add comments to getLocales() method (#211)

* Use `f:select` and implement doFillSystemLocaleItems for better UI (#211)

* Add `Use Browser Default` Locale option (#211)

* Add `Use Browser Default` Locale option (#211)

* Fix Unit tests and bug to handle empty systemLocale (#211)

* Fix and Add Unit tests (#211)

* Fix bug in PluginImpl - MigrationTest is failing (#211)

* Add Jenkins supported Locales (#211)

* Update test for doFillSystemLocaleItems() method (#211)

* Fix the code using Spotless code style run (#211)

* Add helper text to locale limit (#211)

* Add test for systemLocale empty (#211)

* remove ionicons-api dependency (#211)
  • Loading branch information
ganesh-sadanala authored Jun 3, 2024
1 parent 79fb6e3 commit d6a0be8
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 6 deletions.
61 changes: 58 additions & 3 deletions src/main/java/hudson/plugins/locale/PluginImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@
import hudson.XmlFile;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.util.ListBoxModel;
import hudson.util.PluginServletFilter;
import hudson.util.XStream2;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.ServletException;
import jenkins.appearance.AppearanceCategory;
import jenkins.model.GlobalConfiguration;
Expand All @@ -31,6 +37,14 @@ public class PluginImpl extends GlobalConfiguration {
private String systemLocale;
private boolean ignoreAcceptLanguage;

public static final String USE_BROWSER_LOCALE = "USE_BROWSER_LOCALE";

// Set of allowed locales
private static final Set<String> ALLOWED_LOCALES = new HashSet<>(Arrays.asList(
"bg", "ca", "cs", "da", "de", "el", "en_GB", "es", "es_AR", "et", "fi", "fr", "he", "hu", "it", "ja", "ko",
"lt", "lv", "nb_NO", "nl", "pl", "pt_BR", "pt_PT", "ro", "ru", "sk", "sl", "sr", "sv_SE", "tr", "uk",
"zh_CN", "zh_TW"));

/**
* The value of {@link Locale#getDefault()} before we replace it.
*/
Expand Down Expand Up @@ -74,7 +88,9 @@ public Locale get() {
@Override
public void load() {
super.load();
setSystemLocale(systemLocale); // make the loaded value take effect
// make the loaded value take effect
if (systemLocale == null || systemLocale.isEmpty()) setSystemLocale(USE_BROWSER_LOCALE);

Check warning on line 92 in src/main/java/hudson/plugins/locale/PluginImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 92 is only partially covered, one branch is missing
else setSystemLocale(systemLocale);
}

@Override
Expand All @@ -94,8 +110,17 @@ public String getSystemLocale() {

public void setSystemLocale(String systemLocale) {
systemLocale = Util.fixEmptyAndTrim(systemLocale);
Locale.setDefault(systemLocale == null ? originalLocale : parse(systemLocale));
this.systemLocale = systemLocale;
if (USE_BROWSER_LOCALE.equals(systemLocale)) {
Locale.setDefault(originalLocale);
this.systemLocale = USE_BROWSER_LOCALE;
} else {
Locale.setDefault((systemLocale == null || systemLocale.isEmpty()) ? originalLocale : parse(systemLocale));

Check warning on line 117 in src/main/java/hudson/plugins/locale/PluginImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 117 is only partially covered, one branch is missing
this.systemLocale = systemLocale;
}
}

public String getUseBrowserLocale() {
return USE_BROWSER_LOCALE;

Check warning on line 123 in src/main/java/hudson/plugins/locale/PluginImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 123 is not covered by tests
}

/**
Expand Down Expand Up @@ -134,6 +159,36 @@ public GlobalConfigurationCategory getCategory() {
return GlobalConfigurationCategory.get(AppearanceCategory.class);
}

/**
* Retrieves a ListBoxModel containing the available system locales.
* This method populates a ListBoxModel with the available system locales,
* sorted lexicographically by their string representations. Each locale's
* display name and string representation are added as options to the model.
*
* @return A ListBoxModel containing the available system locales.
*/
public ListBoxModel doFillSystemLocaleItems() {
ListBoxModel items = new ListBoxModel();

// Use originalLocale to display the "Use Browser Locale" option
String originalLocaleDisplay = String.format(
"Use Browser Locale - %s (%s)", originalLocale.getDisplayName(), originalLocale.toString());
items.add(new ListBoxModel.Option(originalLocaleDisplay, USE_BROWSER_LOCALE));

Locale[] availableLocales = Locale.getAvailableLocales();
List<Locale> sortedLocales = Arrays.stream(availableLocales)
.filter(locale -> ALLOWED_LOCALES.contains(locale.toString())) // Ensure no empty or null locale strings
.sorted((locale1, locale2) -> locale1.getDisplayName().compareTo(locale2.getDisplayName()))
.collect(Collectors.toList());

for (Locale locale : sortedLocales) {
String displayText = String.format("%s - %s", locale.getDisplayName(), locale.toString());
items.add(new ListBoxModel.Option(displayText, locale.toString()));
}

return items;
}

private static final XStream XSTREAM = new XStream2();

static {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<f:section title="${%Locale}">
<f:entry title="${%Default Language}" field="systemLocale">
<f:textbox />
<f:section>
<f:entry title="${%Default Language}" help="/plugin/locale/help/help-systemLocale.html">
<f:select field="systemLocale"/>
</f:entry>
<f:entry>
<f:checkbox field="ignoreAcceptLanguage" title="${%description}" />
Expand Down
3 changes: 3 additions & 0 deletions src/main/webapp/help/help-systemLocale.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
<p>Only a limited number of locales are available due to project scope.</p>
</div>
11 changes: 11 additions & 0 deletions src/test/java/hudson/plugins/locale/MigrationTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hudson.plugins.locale;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import jenkins.model.Jenkins;
import org.junit.Rule;
Expand All @@ -24,4 +25,14 @@ public void dataMigration_13() {
assertEquals("en-US", plugin.getSystemLocale());
assertEquals(true, plugin.isIgnoreAcceptLanguage());
}

@LocalData
@Test
public void dataMigration_UnsetLocale() {
PluginImpl plugin = Jenkins.get().getExtensionList(PluginImpl.class).get(0);

// Assuming the default behavior if systemLocale is unset
assertEquals(PluginImpl.USE_BROWSER_LOCALE, plugin.getSystemLocale());
assertFalse(plugin.isIgnoreAcceptLanguage());
}
}
97 changes: 97 additions & 0 deletions src/test/java/hudson/plugins/locale/PluginImplTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package hudson.plugins.locale;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import hudson.util.ListBoxModel;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import jenkins.model.Jenkins;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

public class PluginImplTest {

@Rule
public JenkinsRule j = new JenkinsRule();

private PluginImpl plugin;

@Before
public void setUp() {
plugin = Jenkins.get().getExtensionList(PluginImpl.class).get(0);
}

// Set of allowed locales for the test
private static final Set<String> ALLOWED_LOCALES = new HashSet<>(Arrays.asList(
"bg", "ca", "cs", "da", "de", "el", "en_GB", "es", "es_AR", "et", "fi", "fr", "he", "hu", "it", "ja", "ko",
"lt", "lv", "nb_NO", "nl", "pl", "pt_BR", "pt_PT", "ro", "ru", "sk", "sl", "sr", "sv_SE", "tr", "uk",
"zh_CN", "zh_TW"));

@Test
public void testDoFillSystemLocaleItems() {
// Invoke the method
ListBoxModel model = plugin.doFillSystemLocaleItems();

// Expected size of the ListBoxModel
int expectedSize = ALLOWED_LOCALES.size() + 1; // +1 for the "Use Browser Locale" option

// Verify the returned ListBoxModel size
assertEquals("The returned ListBoxModel size is not as expected", expectedSize, model.size());

// Verify that the first option is "Use Browser Locale"
String expectedFirstOption = String.format(
"Use Browser Locale - %s (%s)",
Locale.getDefault().getDisplayName(), Locale.getDefault().toString());
assertEquals("The first option should be 'Use Browser Locale'", expectedFirstOption, model.get(0).name);

// Verify that the allowed locales are correctly added to the ListBoxModel, excluding the first option
for (String localeStr : ALLOWED_LOCALES) {
Locale locale = Locale.forLanguageTag(localeStr.replace('_', '-'));
String expectedOption = String.format("%s - %s", locale.getDisplayName(), locale.toString());

boolean found = false;
for (int i = 1; i < model.size(); i++) { // Start from 1 to skip the "Use Browser Locale" option
if (model.get(i).name.equals(expectedOption)) {
found = true;
break;
}
}
assertEquals("The ListBoxModel does not contain the expected locale: " + locale, true, found);
}
}

@Test
public void testSetSystemLocale() {
// Test setting systemLocale
String systemLocale = "en_US";
plugin.setSystemLocale(systemLocale);
assertEquals(systemLocale, plugin.getSystemLocale());
}

@Test
public void testSetIgnoreAcceptLanguage() {
// Test setting ignoreAcceptLanguage
boolean ignoreAcceptLanguage = true;
plugin.setIgnoreAcceptLanguage(ignoreAcceptLanguage);
assertEquals(ignoreAcceptLanguage, plugin.isIgnoreAcceptLanguage());
}

@Test
public void testNullSystemLocale() {
// Test setting systemLocale to null
plugin.setSystemLocale(null);
assertNull("System locale should be null", plugin.getSystemLocale());
}

@Test
public void testEmptySystemLocale() {
// Test setting systemLocale to empty string
plugin.setSystemLocale("");
assertNull("System locale should be empty", plugin.getSystemLocale());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version='1.0' encoding='UTF-8'?>
<locale plugin="[email protected]">
<ignoreAcceptLanguage>true</ignoreAcceptLanguage>
</locale>

0 comments on commit d6a0be8

Please sign in to comment.