From a9afca67ba942afa287be3507eb225e0a7b954e6 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 28 May 2013 12:00:15 +0300 Subject: [PATCH] Moved Locale data handling to LocaleService (#11378) The locale data is now tracked per UI instance and no longer sent in every request. Change-Id: I4bebd00327da6f8d812181fd76a85eb6196d0010 --- .../vaadin/client/ApplicationConnection.java | 21 +- .../src/com/vaadin/client/LocaleService.java | 54 ++--- .../com/vaadin/server/JsonPaintTarget.java | 4 - .../server/LegacyCommunicationManager.java | 61 ----- .../src/com/vaadin/server/LocaleService.java | 211 ++++++++++++++++++ .../server/communication/LocaleWriter.java | 204 ----------------- .../server/communication/UidlWriter.java | 4 - .../src/com/vaadin/ui/AbstractComponent.java | 9 +- server/src/com/vaadin/ui/UI.java | 17 ++ .../src/com/vaadin/shared/ui/ui/UIState.java | 28 +++ .../components/datefield/DateFieldLocale.java | 2 +- 11 files changed, 300 insertions(+), 315 deletions(-) create mode 100644 server/src/com/vaadin/server/LocaleService.java delete mode 100644 server/src/com/vaadin/server/communication/LocaleWriter.java diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 087ee87262..24275dadb9 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -1350,16 +1350,6 @@ public class ApplicationConnection { handleUIDLDuration.logDuration(" * Loading widgets completed", 10); - Profiler.enter("Handling locales"); - if (json.containsKey("locales")) { - VConsole.log(" * Handling locales"); - // Store locale data - JsArray valueMapArray = json - .getJSValueMapArray("locales"); - LocaleService.addLocales(valueMapArray); - } - Profiler.leave("Handling locales"); - Profiler.enter("Handling meta information"); ValueMap meta = null; if (json.containsKey("meta")) { @@ -1399,6 +1389,17 @@ public class ApplicationConnection { JsArrayObject pendingStateChangeEvents = updateConnectorState( json, createdConnectorIds); + /* + * Doing this here so that locales are available also to the + * connectors which get a state change event before the UI. + */ + Profiler.enter("Handling locales"); + VConsole.log(" * Handling locales"); + // Store locale data + LocaleService + .addLocales(getUIConnector().getState().localeServiceState.localeData); + Profiler.leave("Handling locales"); + // Update hierarchy, do not fire events ConnectorHierarchyUpdateResult connectorHierarchyUpdateResult = updateConnectorHierarchy(json); diff --git a/client/src/com/vaadin/client/LocaleService.java b/client/src/com/vaadin/client/LocaleService.java index 4009c95531..69345d7174 100644 --- a/client/src/com/vaadin/client/LocaleService.java +++ b/client/src/com/vaadin/client/LocaleService.java @@ -17,10 +17,12 @@ package com.vaadin.client; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; -import com.google.gwt.core.client.JsArray; +import com.vaadin.shared.ui.ui.UIState.LocaleData; /** * Date / time etc. localisation service for all widgets. Caches all loaded @@ -31,16 +33,17 @@ import com.google.gwt.core.client.JsArray; */ public class LocaleService { - private static Map cache = new HashMap(); - private static String defaultLocale; + private static Map cache = new HashMap(); - public static void addLocale(ValueMap valueMap) { + private static String defaultLocale; - final String key = valueMap.getString("name"); + public static void addLocale(LocaleData localeData) { + final String key = localeData.name; if (cache.containsKey(key)) { cache.remove(key); } - cache.put(key, valueMap); + getLogger().fine("Received locale data for " + localeData.name); + cache.put(key, localeData); if (cache.size() == 1) { setDefaultLocale(key); } @@ -61,8 +64,7 @@ public class LocaleService { public static String[] getMonthNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("mn"); + return cache.get(locale).monthNames; } else { throw new LocaleNotLoadedException(locale); } @@ -71,8 +73,7 @@ public class LocaleService { public static String[] getShortMonthNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("smn"); + return cache.get(locale).shortMonthNames; } else { throw new LocaleNotLoadedException(locale); } @@ -81,8 +82,7 @@ public class LocaleService { public static String[] getDayNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("dn"); + return cache.get(locale).dayNames; } else { throw new LocaleNotLoadedException(locale); } @@ -91,8 +91,7 @@ public class LocaleService { public static String[] getShortDayNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("sdn"); + return cache.get(locale).shortDayNames; } else { throw new LocaleNotLoadedException(locale); } @@ -101,8 +100,7 @@ public class LocaleService { public static int getFirstDayOfWeek(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getInt("fdow"); + return cache.get(locale).firstDayOfWeek; } else { throw new LocaleNotLoadedException(locale); } @@ -111,8 +109,7 @@ public class LocaleService { public static String getDateFormat(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getString("df"); + return cache.get(locale).dateFormat; } else { throw new LocaleNotLoadedException(locale); } @@ -121,8 +118,7 @@ public class LocaleService { public static boolean isTwelveHourClock(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getBoolean("thc"); + return cache.get(locale).twelveHourClock; } else { throw new LocaleNotLoadedException(locale); } @@ -131,8 +127,7 @@ public class LocaleService { public static String getClockDelimiter(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getString("hmd"); + return cache.get(locale).hourMinuteDelimiter; } else { throw new LocaleNotLoadedException(locale); } @@ -141,20 +136,19 @@ public class LocaleService { public static String[] getAmPmStrings(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("ampm"); + return new String[] { cache.get(locale).am, cache.get(locale).pm }; } else { throw new LocaleNotLoadedException(locale); } - } - public static void addLocales(JsArray valueMapArray) { - for (int i = 0; i < valueMapArray.length(); i++) { - addLocale(valueMapArray.get(i)); - + public static void addLocales(List localeDatas) { + for (LocaleData localeData : localeDatas) { + addLocale(localeData); } - } + private static Logger getLogger() { + return Logger.getLogger(LocaleService.class.getName()); + } } diff --git a/server/src/com/vaadin/server/JsonPaintTarget.java b/server/src/com/vaadin/server/JsonPaintTarget.java index ca70391f64..cd09b2a44b 100644 --- a/server/src/com/vaadin/server/JsonPaintTarget.java +++ b/server/src/com/vaadin/server/JsonPaintTarget.java @@ -388,10 +388,6 @@ public class JsonPaintTarget implements PaintTarget { getUsedResources().add("layouts/" + value + ".html"); } - if (name.equals("locale")) { - manager.requireLocale(value); - } - } @Override diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java index c0194db243..ad662cf6df 100644 --- a/server/src/com/vaadin/server/LegacyCommunicationManager.java +++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java @@ -16,18 +16,12 @@ package com.vaadin.server; -import java.io.IOException; -import java.io.PrintWriter; import java.io.Serializable; -import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.security.GeneralSecurityException; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.logging.Level; @@ -37,7 +31,6 @@ import org.json.JSONException; import org.json.JSONObject; import com.vaadin.server.ClientConnector.ConnectorErrorEvent; -import com.vaadin.server.communication.LocaleWriter; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JavaScriptConnectorState; import com.vaadin.shared.communication.SharedState; @@ -69,9 +62,6 @@ public class LegacyCommunicationManager implements Serializable { */ private final VaadinSession session; - // TODO Refactor to UI shared state (#11378) - private List locales; - // TODO Move to VaadinSession (#11409) private DragAndDropService dragAndDropService; @@ -88,7 +78,6 @@ public class LegacyCommunicationManager implements Serializable { */ public LegacyCommunicationManager(VaadinSession session) { this.session = session; - requireLocale(session.getLocale().toString()); } protected VaadinSession getSession() { @@ -312,52 +301,6 @@ public class LegacyCommunicationManager implements Serializable { return dragAndDropService; } - /** - * Prints the queued (pending) locale definitions to a {@link PrintWriter} - * in a (UIDL) format that can be sent to the client and used there in - * formatting dates, times etc. - * - * @deprecated As of 7.1. See #11378. - * - * @param outWriter - */ - @Deprecated - public void printLocaleDeclarations(Writer writer) throws IOException { - new LocaleWriter().write(locales, writer); - } - - /** - * Queues a locale to be sent to the client (browser) for date and time - * entry etc. All locale specific information is derived from server-side - * {@link Locale} instances and sent to the client when needed, eliminating - * the need to use the {@link Locale} class and all the framework behind it - * on the client. - * - * @deprecated As of 7.1. See #11378. - * - * @see Locale#toString() - * - * @param value - */ - @Deprecated - public void requireLocale(String value) { - if (locales == null) { - locales = new ArrayList(); - locales.add(session.getLocale().toString()); - } - if (!locales.contains(value)) { - locales.add(value); - } - } - - /** - * @deprecated As of 7.1. See #11378. - */ - @Deprecated - public void resetLocales() { - locales = null; - } - /** * @deprecated As of 7.1. Will be removed in the future. */ @@ -486,10 +429,6 @@ public class LegacyCommunicationManager implements Serializable { getClientCache(ui).clear(); ui.getConnectorTracker().markAllConnectorsDirty(); ui.getConnectorTracker().markAllClientSidesUninitialized(); - - // Reset sent locales - resetLocales(); - requireLocale(session.getLocale().toString()); } private static final Logger getLogger() { diff --git a/server/src/com/vaadin/server/LocaleService.java b/server/src/com/vaadin/server/LocaleService.java new file mode 100644 index 0000000000..347c4da5c6 --- /dev/null +++ b/server/src/com/vaadin/server/LocaleService.java @@ -0,0 +1,211 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed 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 com.vaadin.server; + +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.logging.Logger; + +import com.vaadin.shared.ui.ui.UIState.LocaleData; +import com.vaadin.shared.ui.ui.UIState.LocaleServiceState; +import com.vaadin.ui.UI; + +/** + * Server side service which handles locale and the transmission of locale date + * to the client side LocaleService. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class LocaleService { + + private UI ui; + + private LocaleServiceState state; + + /** + * Creates a LocaleService bound to the given UI + * + * @since 7.1 + * @param ui + * The UI which owns the LocaleService + */ + public LocaleService(UI ui, LocaleServiceState state) { + this.ui = ui; + this.state = state; + } + + /** + * Retrieves the UI this service is bound to + * + * @since 7.1 + * @return the UI for this service + */ + public UI getUI() { + return ui; + } + + /** + * Adds a locale to be sent to the client (browser) for date and time entry + * etc. All locale specific information is derived from server-side + * {@link Locale} instances and sent to the client when needed, eliminating + * the need to use the {@link Locale} class and all the framework behind it + * on the client. + * + * @param locale + * The locale which is required on the client side + */ + public void addLocale(Locale locale) { + for (LocaleData data : getState(false).localeData) { + if (data.name.equals(locale.toString())) { + // Already there + return; + } + } + + getState(true).localeData.add(createLocaleData(locale)); + } + + /** + * Returns the state for this service + *

+ * The state is transmitted inside the UI state rather than as an individual + * entity. + *

+ * + * @since 7.1 + * @param markAsDirty + * true to mark the state as dirty + * @return a LocaleServiceState object that can be read in any case and + * modified if markAsDirty is true + */ + private LocaleServiceState getState(boolean markAsDirty) { + if (markAsDirty) { + getUI().markAsDirty(); + } + + return state; + } + + /** + * Creates a LocaleData instance for transportation to the client + * + * @since 7.1 + * @param locale + * The locale for which to create a LocaleData object + * @return A LocaleData object with information about the given locale + */ + protected LocaleData createLocaleData(Locale locale) { + LocaleData localeData = new LocaleData(); + localeData.name = locale.toString(); + + final DateFormatSymbols dfs = new DateFormatSymbols(locale); + localeData.shortMonthNames = dfs.getShortMonths(); + localeData.monthNames = dfs.getMonths(); + // Client expects 0 based indexing, DateFormatSymbols use 1 based + localeData.shortDayNames = new String[7]; + localeData.dayNames = new String[7]; + String[] sDayNames = dfs.getShortWeekdays(); + String[] lDayNames = dfs.getWeekdays(); + for (int i = 0; i < 7; i++) { + localeData.shortDayNames[i] = sDayNames[i + 1]; + localeData.dayNames[i] = lDayNames[i + 1]; + } + + /* + * First day of week (0 = sunday, 1 = monday) + */ + final java.util.Calendar cal = new GregorianCalendar(locale); + localeData.firstDayOfWeek = cal.getFirstDayOfWeek() - 1; + + /* + * Date formatting (MM/DD/YYYY etc.) + */ + + DateFormat dateFormat = DateFormat.getDateTimeInstance( + DateFormat.SHORT, DateFormat.SHORT, locale); + if (!(dateFormat instanceof SimpleDateFormat)) { + getLogger().warning( + "Unable to get default date pattern for locale " + + locale.toString()); + dateFormat = new SimpleDateFormat(); + } + final String df = ((SimpleDateFormat) dateFormat).toPattern(); + + int timeStart = df.indexOf("H"); + if (timeStart < 0) { + timeStart = df.indexOf("h"); + } + final int ampm_first = df.indexOf("a"); + // E.g. in Korean locale AM/PM is before h:mm + // TODO should take that into consideration on client-side as well, + // now always h:mm a + if (ampm_first > 0 && ampm_first < timeStart) { + timeStart = ampm_first; + } + // Hebrew locale has time before the date + final boolean timeFirst = timeStart == 0; + String dateformat; + if (timeFirst) { + int dateStart = df.indexOf(' '); + if (ampm_first > dateStart) { + dateStart = df.indexOf(' ', ampm_first); + } + dateformat = df.substring(dateStart + 1); + } else { + dateformat = df.substring(0, timeStart - 1); + } + + localeData.dateFormat = dateformat.trim(); + + /* + * Time formatting (24 or 12 hour clock and AM/PM suffixes) + */ + final String timeformat = df.substring(timeStart, df.length()); + /* + * Doesn't return second or milliseconds. + * + * We use timeformat to determine 12/24-hour clock + */ + final boolean twelve_hour_clock = timeformat.indexOf("a") > -1; + // TODO there are other possibilities as well, like 'h' in french + // (ignore them, too complicated) + final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." + : ":"; + // outWriter.print("\"tf\":\"" + timeformat + "\","); + localeData.twelveHourClock = twelve_hour_clock; + localeData.hourMinuteDelimiter = hour_min_delimiter; + if (twelve_hour_clock) { + final String[] ampm = dfs.getAmPmStrings(); + localeData.am = ampm[0]; + localeData.pm = ampm[1]; + } + + return localeData; + } + + private static Logger getLogger() { + return Logger.getLogger(LocaleService.class.getName()); + } + +} diff --git a/server/src/com/vaadin/server/communication/LocaleWriter.java b/server/src/com/vaadin/server/communication/LocaleWriter.java deleted file mode 100644 index c05649da19..0000000000 --- a/server/src/com/vaadin/server/communication/LocaleWriter.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2000-2013 Vaadin Ltd. - * - * Licensed 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 com.vaadin.server.communication; - -import java.io.IOException; -import java.io.Serializable; -import java.io.Writer; -import java.text.DateFormat; -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.Locale; -import java.util.logging.Logger; - -/** - * Serializes locale information to JSON. - * - * @author Vaadin Ltd - * @since 7.1 - * @deprecated See ticket - * #11378. - */ -@Deprecated -public class LocaleWriter implements Serializable { - - /** - * Writes a JSON object containing localized strings of the given locales. - * - * @param locales - * The list of {@link Locale}s to write. - * @param writer - * The {@link Writer} used to write the JSON. - * @throws IOException - * If the serialization fails. - * - */ - public void write(List locales, Writer writer) throws IOException { - - // Send locale informations to client - writer.write("["); - // TODO locales are currently sent on each request; this will be fixed - // by implementing #11378. - for (int pendingLocalesIndex = 0; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) { - - final Locale l = generateLocale(locales.get(pendingLocalesIndex)); - // Locale name - writer.write("{\"name\":\"" + l.toString() + "\","); - - /* - * Month names (both short and full) - */ - final DateFormatSymbols dfs = new DateFormatSymbols(l); - final String[] short_months = dfs.getShortMonths(); - final String[] months = dfs.getMonths(); - writer.write("\"smn\":[\"" - + // ShortMonthNames - short_months[0] + "\",\"" + short_months[1] + "\",\"" - + short_months[2] + "\",\"" + short_months[3] + "\",\"" - + short_months[4] + "\",\"" + short_months[5] + "\",\"" - + short_months[6] + "\",\"" + short_months[7] + "\",\"" - + short_months[8] + "\",\"" + short_months[9] + "\",\"" - + short_months[10] + "\",\"" + short_months[11] + "\"" - + "],"); - writer.write("\"mn\":[\"" - + // MonthNames - months[0] + "\",\"" + months[1] + "\",\"" + months[2] - + "\",\"" + months[3] + "\",\"" + months[4] + "\",\"" - + months[5] + "\",\"" + months[6] + "\",\"" + months[7] - + "\",\"" + months[8] + "\",\"" + months[9] + "\",\"" - + months[10] + "\",\"" + months[11] + "\"" + "],"); - - /* - * Weekday names (both short and full) - */ - final String[] short_days = dfs.getShortWeekdays(); - final String[] days = dfs.getWeekdays(); - writer.write("\"sdn\":[\"" - + // ShortDayNames - short_days[1] + "\",\"" + short_days[2] + "\",\"" - + short_days[3] + "\",\"" + short_days[4] + "\",\"" - + short_days[5] + "\",\"" + short_days[6] + "\",\"" - + short_days[7] + "\"" + "],"); - writer.write("\"dn\":[\"" - + // DayNames - days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\"" - + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\"" - + days[7] + "\"" + "],"); - - /* - * First day of week (0 = sunday, 1 = monday) - */ - final Calendar cal = new GregorianCalendar(l); - writer.write("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ","); - - /* - * Date formatting (MM/DD/YYYY etc.) - */ - - DateFormat dateFormat = DateFormat.getDateTimeInstance( - DateFormat.SHORT, DateFormat.SHORT, l); - if (!(dateFormat instanceof SimpleDateFormat)) { - getLogger().warning( - "Unable to get default date pattern for locale " - + l.toString()); - dateFormat = new SimpleDateFormat(); - } - final String df = ((SimpleDateFormat) dateFormat).toPattern(); - - int timeStart = df.indexOf("H"); - if (timeStart < 0) { - timeStart = df.indexOf("h"); - } - final int ampm_first = df.indexOf("a"); - // E.g. in Korean locale AM/PM is before h:mm - // TODO should take that into consideration on client-side as well, - // now always h:mm a - if (ampm_first > 0 && ampm_first < timeStart) { - timeStart = ampm_first; - } - // Hebrew locale has time before the date - final boolean timeFirst = timeStart == 0; - String dateformat; - if (timeFirst) { - int dateStart = df.indexOf(' '); - if (ampm_first > dateStart) { - dateStart = df.indexOf(' ', ampm_first); - } - dateformat = df.substring(dateStart + 1); - } else { - dateformat = df.substring(0, timeStart - 1); - } - - writer.write("\"df\":\"" + dateformat.trim() + "\","); - - /* - * Time formatting (24 or 12 hour clock and AM/PM suffixes) - */ - final String timeformat = df.substring(timeStart, df.length()); - /* - * Doesn't return second or milliseconds. - * - * We use timeformat to determine 12/24-hour clock - */ - final boolean twelve_hour_clock = timeformat.indexOf("a") > -1; - // TODO there are other possibilities as well, like 'h' in french - // (ignore them, too complicated) - final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." - : ":"; - // outWriter.print("\"tf\":\"" + timeformat + "\","); - writer.write("\"thc\":" + twelve_hour_clock + ","); - writer.write("\"hmd\":\"" + hour_min_delimiter + "\""); - if (twelve_hour_clock) { - final String[] ampm = dfs.getAmPmStrings(); - writer.write(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1] - + "\"]"); - } - writer.write("}"); - if (pendingLocalesIndex < locales.size() - 1) { - writer.write(","); - } - } - writer.write("]"); // Close locales - } - - /** - * Constructs a {@link Locale} instance to be sent to the client based on a - * short locale description string. - * - * @see #requireLocale(String) - * - * @param value - * @return - */ - private Locale generateLocale(String value) { - final String[] temp = value.split("_"); - if (temp.length == 1) { - return new Locale(temp[0]); - } else if (temp.length == 2) { - return new Locale(temp[0], temp[1]); - } else { - return new Locale(temp[0], temp[1], temp[2]); - } - } - - private static final Logger getLogger() { - return Logger.getLogger(LocaleWriter.class.getName()); - } -} diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java index 60a884a635..f715569424 100644 --- a/server/src/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/com/vaadin/server/communication/UidlWriter.java @@ -283,10 +283,6 @@ public class UidlWriter implements Serializable { + new JSONArray(styleDependencies).toString()); } - // add any pending locale definitions requested by the client - writer.write(", \"locales\": "); - manager.printLocaleDeclarations(writer); - if (manager.getDragAndDropService() != null) { manager.getDragAndDropService().printJSONResponse(writer); } diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index 06060dbf91..9ff36a42d2 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -291,7 +291,10 @@ public abstract class AbstractComponent extends AbstractClientConnector public void setLocale(Locale locale) { this.locale = locale; - // FIXME: Reload value if there is a converter + if (locale != null && isAttached()) { + getUI().getLocaleService().addLocale(locale); + } + markAsDirty(); } @@ -556,6 +559,10 @@ public abstract class AbstractComponent extends AbstractClientConnector focus(); } setActionManagerViewer(); + if (locale != null) { + getUI().getLocaleService().addLocale(locale); + } + } /* diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 545c2c7365..706f7c436b 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -30,6 +30,7 @@ import com.vaadin.event.ActionManager; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; import com.vaadin.navigator.Navigator; +import com.vaadin.server.LocaleService; import com.vaadin.server.Page; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; @@ -494,6 +495,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements private boolean hasPendingPush = false; + private LocaleService localeService = new LocaleService(this, + getState(false).localeServiceState); + /** * This method is used by Component.Focusable objects to request focus to * themselves. Focus renders must be handled at window level (instead of @@ -1052,6 +1056,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements @Override public void attach() { super.attach(); + getLocaleService().addLocale(getLocale()); } /** @@ -1428,4 +1433,16 @@ public abstract class UI extends AbstractSingleComponentContainer implements public void setOverlayContainerLabel(String overlayContainerLabel) { getState().overlayContainerLabel = overlayContainerLabel; } + + /** + * Returns the locale service which handles transmission of Locale data to + * the client. + * + * @since 7.1 + * @return The LocaleService for this UI + */ + public LocaleService getLocaleService() { + return localeService; + } + } diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java index 16c1ed16c7..f01d5d8100 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIState.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java @@ -16,7 +16,11 @@ package com.vaadin.shared.ui.ui; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import com.vaadin.server.LocaleService; +import com.vaadin.server.Page; import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.TabIndexState; @@ -50,10 +54,34 @@ public class UIState extends TabIndexState { * State related to the {@link Page} class. */ public PageState pageState = new PageState(); + /** + * State related to the {@link LocaleService} class. + */ + public LocaleServiceState localeServiceState = new LocaleServiceState(); { primaryStyleName = "v-ui"; // Default is 1 for legacy reasons tabIndex = 1; } + + public static class LocaleServiceState implements Serializable { + public List localeData = new ArrayList(); + } + + public static class LocaleData implements Serializable { + public String name; + public String[] monthNames; + public String[] shortMonthNames; + public String[] shortDayNames; + public String[] dayNames; + public int firstDayOfWeek; + public String dateFormat; + public boolean twelveHourClock; + public String hourMinuteDelimiter; + public String am; + public String pm; + + } + } diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java index 5d06895d11..a4fe2b0285 100644 --- a/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java @@ -16,7 +16,7 @@ public class DateFieldLocale extends TestBase { final DateField dateField = new DateField("DateField"); dateField.setLocale(new Locale("fi", "FI")); dateField.setCaption(dateField.getLocale().toString()); - dateField.setValue(new Date()); + dateField.setValue(new Date(2013 - 1900, 7 - 1, 27)); dateField.setResolution(DateField.RESOLUTION_DAY); addComponent(new Button("Change locale", new ClickListener() { -- 2.39.5