Skip to content

Commit d6a0be8

Browse files
Dropdown feature for Locale selection (#215)
* 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)
1 parent 79fb6e3 commit d6a0be8

File tree

6 files changed

+176
-6
lines changed

6 files changed

+176
-6
lines changed

src/main/java/hudson/plugins/locale/PluginImpl.java

+58-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@
77
import hudson.XmlFile;
88
import hudson.init.InitMilestone;
99
import hudson.init.Initializer;
10+
import hudson.util.ListBoxModel;
1011
import hudson.util.PluginServletFilter;
1112
import hudson.util.XStream2;
1213
import java.io.File;
14+
import java.util.Arrays;
15+
import java.util.HashSet;
16+
import java.util.List;
1317
import java.util.Locale;
18+
import java.util.Set;
19+
import java.util.stream.Collectors;
1420
import javax.servlet.ServletException;
1521
import jenkins.appearance.AppearanceCategory;
1622
import jenkins.model.GlobalConfiguration;
@@ -31,6 +37,14 @@ public class PluginImpl extends GlobalConfiguration {
3137
private String systemLocale;
3238
private boolean ignoreAcceptLanguage;
3339

40+
public static final String USE_BROWSER_LOCALE = "USE_BROWSER_LOCALE";
41+
42+
// Set of allowed locales
43+
private static final Set<String> ALLOWED_LOCALES = new HashSet<>(Arrays.asList(
44+
"bg", "ca", "cs", "da", "de", "el", "en_GB", "es", "es_AR", "et", "fi", "fr", "he", "hu", "it", "ja", "ko",
45+
"lt", "lv", "nb_NO", "nl", "pl", "pt_BR", "pt_PT", "ro", "ru", "sk", "sl", "sr", "sv_SE", "tr", "uk",
46+
"zh_CN", "zh_TW"));
47+
3448
/**
3549
* The value of {@link Locale#getDefault()} before we replace it.
3650
*/
@@ -74,7 +88,9 @@ public Locale get() {
7488
@Override
7589
public void load() {
7690
super.load();
77-
setSystemLocale(systemLocale); // make the loaded value take effect
91+
// make the loaded value take effect
92+
if (systemLocale == null || systemLocale.isEmpty()) setSystemLocale(USE_BROWSER_LOCALE);
93+
else setSystemLocale(systemLocale);
7894
}
7995

8096
@Override
@@ -94,8 +110,17 @@ public String getSystemLocale() {
94110

95111
public void setSystemLocale(String systemLocale) {
96112
systemLocale = Util.fixEmptyAndTrim(systemLocale);
97-
Locale.setDefault(systemLocale == null ? originalLocale : parse(systemLocale));
98-
this.systemLocale = systemLocale;
113+
if (USE_BROWSER_LOCALE.equals(systemLocale)) {
114+
Locale.setDefault(originalLocale);
115+
this.systemLocale = USE_BROWSER_LOCALE;
116+
} else {
117+
Locale.setDefault((systemLocale == null || systemLocale.isEmpty()) ? originalLocale : parse(systemLocale));
118+
this.systemLocale = systemLocale;
119+
}
120+
}
121+
122+
public String getUseBrowserLocale() {
123+
return USE_BROWSER_LOCALE;
99124
}
100125

101126
/**
@@ -134,6 +159,36 @@ public GlobalConfigurationCategory getCategory() {
134159
return GlobalConfigurationCategory.get(AppearanceCategory.class);
135160
}
136161

162+
/**
163+
* Retrieves a ListBoxModel containing the available system locales.
164+
* This method populates a ListBoxModel with the available system locales,
165+
* sorted lexicographically by their string representations. Each locale's
166+
* display name and string representation are added as options to the model.
167+
*
168+
* @return A ListBoxModel containing the available system locales.
169+
*/
170+
public ListBoxModel doFillSystemLocaleItems() {
171+
ListBoxModel items = new ListBoxModel();
172+
173+
// Use originalLocale to display the "Use Browser Locale" option
174+
String originalLocaleDisplay = String.format(
175+
"Use Browser Locale - %s (%s)", originalLocale.getDisplayName(), originalLocale.toString());
176+
items.add(new ListBoxModel.Option(originalLocaleDisplay, USE_BROWSER_LOCALE));
177+
178+
Locale[] availableLocales = Locale.getAvailableLocales();
179+
List<Locale> sortedLocales = Arrays.stream(availableLocales)
180+
.filter(locale -> ALLOWED_LOCALES.contains(locale.toString())) // Ensure no empty or null locale strings
181+
.sorted((locale1, locale2) -> locale1.getDisplayName().compareTo(locale2.getDisplayName()))
182+
.collect(Collectors.toList());
183+
184+
for (Locale locale : sortedLocales) {
185+
String displayText = String.format("%s - %s", locale.getDisplayName(), locale.toString());
186+
items.add(new ListBoxModel.Option(displayText, locale.toString()));
187+
}
188+
189+
return items;
190+
}
191+
137192
private static final XStream XSTREAM = new XStream2();
138193

139194
static {

src/main/resources/hudson/plugins/locale/PluginImpl/config.jelly

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?jelly escape-by-default='true'?>
22
<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">
3-
<f:section title="${%Locale}">
4-
<f:entry title="${%Default Language}" field="systemLocale">
5-
<f:textbox />
3+
<f:section>
4+
<f:entry title="${%Default Language}" help="/plugin/locale/help/help-systemLocale.html">
5+
<f:select field="systemLocale"/>
66
</f:entry>
77
<f:entry>
88
<f:checkbox field="ignoreAcceptLanguage" title="${%description}" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div>
2+
<p>Only a limited number of locales are available due to project scope.</p>
3+
</div>

src/test/java/hudson/plugins/locale/MigrationTest.java

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package hudson.plugins.locale;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
45

56
import jenkins.model.Jenkins;
67
import org.junit.Rule;
@@ -24,4 +25,14 @@ public void dataMigration_13() {
2425
assertEquals("en-US", plugin.getSystemLocale());
2526
assertEquals(true, plugin.isIgnoreAcceptLanguage());
2627
}
28+
29+
@LocalData
30+
@Test
31+
public void dataMigration_UnsetLocale() {
32+
PluginImpl plugin = Jenkins.get().getExtensionList(PluginImpl.class).get(0);
33+
34+
// Assuming the default behavior if systemLocale is unset
35+
assertEquals(PluginImpl.USE_BROWSER_LOCALE, plugin.getSystemLocale());
36+
assertFalse(plugin.isIgnoreAcceptLanguage());
37+
}
2738
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package hudson.plugins.locale;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNull;
5+
6+
import hudson.util.ListBoxModel;
7+
import java.util.Arrays;
8+
import java.util.HashSet;
9+
import java.util.Locale;
10+
import java.util.Set;
11+
import jenkins.model.Jenkins;
12+
import org.junit.Before;
13+
import org.junit.Rule;
14+
import org.junit.Test;
15+
import org.jvnet.hudson.test.JenkinsRule;
16+
17+
public class PluginImplTest {
18+
19+
@Rule
20+
public JenkinsRule j = new JenkinsRule();
21+
22+
private PluginImpl plugin;
23+
24+
@Before
25+
public void setUp() {
26+
plugin = Jenkins.get().getExtensionList(PluginImpl.class).get(0);
27+
}
28+
29+
// Set of allowed locales for the test
30+
private static final Set<String> ALLOWED_LOCALES = new HashSet<>(Arrays.asList(
31+
"bg", "ca", "cs", "da", "de", "el", "en_GB", "es", "es_AR", "et", "fi", "fr", "he", "hu", "it", "ja", "ko",
32+
"lt", "lv", "nb_NO", "nl", "pl", "pt_BR", "pt_PT", "ro", "ru", "sk", "sl", "sr", "sv_SE", "tr", "uk",
33+
"zh_CN", "zh_TW"));
34+
35+
@Test
36+
public void testDoFillSystemLocaleItems() {
37+
// Invoke the method
38+
ListBoxModel model = plugin.doFillSystemLocaleItems();
39+
40+
// Expected size of the ListBoxModel
41+
int expectedSize = ALLOWED_LOCALES.size() + 1; // +1 for the "Use Browser Locale" option
42+
43+
// Verify the returned ListBoxModel size
44+
assertEquals("The returned ListBoxModel size is not as expected", expectedSize, model.size());
45+
46+
// Verify that the first option is "Use Browser Locale"
47+
String expectedFirstOption = String.format(
48+
"Use Browser Locale - %s (%s)",
49+
Locale.getDefault().getDisplayName(), Locale.getDefault().toString());
50+
assertEquals("The first option should be 'Use Browser Locale'", expectedFirstOption, model.get(0).name);
51+
52+
// Verify that the allowed locales are correctly added to the ListBoxModel, excluding the first option
53+
for (String localeStr : ALLOWED_LOCALES) {
54+
Locale locale = Locale.forLanguageTag(localeStr.replace('_', '-'));
55+
String expectedOption = String.format("%s - %s", locale.getDisplayName(), locale.toString());
56+
57+
boolean found = false;
58+
for (int i = 1; i < model.size(); i++) { // Start from 1 to skip the "Use Browser Locale" option
59+
if (model.get(i).name.equals(expectedOption)) {
60+
found = true;
61+
break;
62+
}
63+
}
64+
assertEquals("The ListBoxModel does not contain the expected locale: " + locale, true, found);
65+
}
66+
}
67+
68+
@Test
69+
public void testSetSystemLocale() {
70+
// Test setting systemLocale
71+
String systemLocale = "en_US";
72+
plugin.setSystemLocale(systemLocale);
73+
assertEquals(systemLocale, plugin.getSystemLocale());
74+
}
75+
76+
@Test
77+
public void testSetIgnoreAcceptLanguage() {
78+
// Test setting ignoreAcceptLanguage
79+
boolean ignoreAcceptLanguage = true;
80+
plugin.setIgnoreAcceptLanguage(ignoreAcceptLanguage);
81+
assertEquals(ignoreAcceptLanguage, plugin.isIgnoreAcceptLanguage());
82+
}
83+
84+
@Test
85+
public void testNullSystemLocale() {
86+
// Test setting systemLocale to null
87+
plugin.setSystemLocale(null);
88+
assertNull("System locale should be null", plugin.getSystemLocale());
89+
}
90+
91+
@Test
92+
public void testEmptySystemLocale() {
93+
// Test setting systemLocale to empty string
94+
plugin.setSystemLocale("");
95+
assertNull("System locale should be empty", plugin.getSystemLocale());
96+
}
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<locale plugin="[email protected]">
3+
<ignoreAcceptLanguage>true</ignoreAcceptLanguage>
4+
</locale>

0 commit comments

Comments
 (0)