Repository: primefaces/primefaces
Pull request #12218 (2024-06-29 15:28:11)

Sonar JS fixes for Core
Fix https://github.com/primefaces/primefaces/issues/11863

Addresses the Sonar issues on in the `/core` package only

tandraschko: Need to think about it, im not that happy with it right now
tandraschko: what about external JS? are the filtered out somehow?
https://sonarcloud.io/project/issues?impactSoftwareQualities=RELIABILITY&issueStatuses=OPEN%2CCONFIRMED&id=org.primefaces%3Aprimefaces&open=AY8u9KHvLK6QkKtQMXzo

i would like to not scan it
Rapster: I just added the exclusion (there might be still a few left)

Patch:
diff --git a/docs/15_0_0/core/localization.md b/docs/15_0_0/core/localization.md
index bc0b84bc21..85f25e47e5 100644
--- a/docs/15_0_0/core/localization.md
+++ b/docs/15_0_0/core/localization.md
@@ -14,6 +14,16 @@ Source code bundles:  [GitHub Server Message Bundle Files](https://github.com/pr
 ### Default Messages.properties
 
 ```
+primefaces.FileValidator.ALLOW_TYPES = Invalid file type.
+primefaces.FileValidator.ALLOW_TYPES_detail = Invalid file type: ''{0}''. Allowed types: ''{1}''.
+primefaces.FileValidator.FILENAME_EMPTY=Filename cannot be empty or null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Invalid filename: {0} contains invalid character: {1}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Invalid Linux filename: {0}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Invalid Windows filename: {0}
+primefaces.FileValidator.FILE_LIMIT = Maximum number of files exceeded.
+primefaces.FileValidator.FILE_LIMIT_detail = Maximum number: {0}.
+primefaces.FileValidator.SIZE_LIMIT = Invalid file size.
+primefaces.FileValidator.SIZE_LIMIT_detail = File ''{0}'' must not be larger than {1}.
 primefaces.calendar.DATE_INVALID_RANGE_MESSAGE_ID = {0}: Validation Error: Start date is greater than the end date.
 primefaces.calendar.INVALID = {0}: Validation Error: Value is not valid.
 primefaces.calendar.MAX_DATE = {0}: Validation Error: Value must be {2} or before.
@@ -32,7 +42,6 @@ primefaces.password.INVALID_MATCH_detail = {0} should match with {1}.
 primefaces.slider.OUT_OF_RANGE = {0}: Validation Error: Value is out of range.
 primefaces.tree.REQUIRED = {0}: Validation Error.
 primefaces.tree.REQUIRED_detail = Selection is required.
-
 ```
 
 ## Client Localization
diff --git a/docs/15_0_0/gettingstarted/whatsnew.md b/docs/15_0_0/gettingstarted/whatsnew.md
index 8af5122ea6..ec6779d5d6 100644
--- a/docs/15_0_0/gettingstarted/whatsnew.md
+++ b/docs/15_0_0/gettingstarted/whatsnew.md
@@ -43,9 +43,15 @@ Look into [migration guide](https://primefaces.github.io/primefaces/15_0_0/#/../
     * Added ability to pick weeks by view="week"
 
 * FeedReader
-
     * Added `podcast="true"` property if [Apple Itunes Podcast](https://help.apple.com/itc/podcasts_connect/#/itcb54353390) parsing and specific tags 
 
+* FileUpload
+    * Added new messages to support localization
+        * `primefaces.FileValidator.FILENAME_INVALID_CHAR=Invalid filename: {0} contains invalid character: {1}`
+        * `primefaces.FileValidator.FILENAME_INVALID_LINUX=Invalid Linux filename: {0}`
+        * `primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Invalid Windows filename: {0}`
+        * `primefaces.FileValidator.FILENAME_EMPTY=Filename cannot be empty or null`
+
 * InputNumber
     * Added `modifyValueOnUpDownArrow` which allows the user to increment or decrement the element value with the up and down arrow keys. Default is true.
 
diff --git a/primefaces-showcase/pom.xml b/primefaces-showcase/pom.xml
index eb5286d511..a02cb6949f 100644
--- a/primefaces-showcase/pom.xml
+++ b/primefaces-showcase/pom.xml
@@ -148,7 +148,7 @@
         <dependency>
            <groupId>software.xdev</groupId>
            <artifactId>chartjs-java-model</artifactId>
-           <version>2.3.1</version>
+           <version>2.5.0</version>
         </dependency>
 
         <!-- Conflict with resteasy-jackson2-provider -->
diff --git a/primefaces-showcase/src/main/java/org/primefaces/showcase/service/CountryService.java b/primefaces-showcase/src/main/java/org/primefaces/showcase/service/CountryService.java
index 3f280e31cb..bd92126916 100644
--- a/primefaces-showcase/src/main/java/org/primefaces/showcase/service/CountryService.java
+++ b/primefaces-showcase/src/main/java/org/primefaces/showcase/service/CountryService.java
@@ -87,6 +87,7 @@ public class CountryService {
         locales.add(CountryService.toCountry(new Locale("ar", "TN"), true));
         locales.add(CountryService.toCountry(new Locale("bg", "BG")));
         locales.add(CountryService.toCountry(new Locale("bn", "BD")));
+        locales.add(CountryService.toCountry(new Locale("bs", "BA")));
         locales.add(CountryService.toCountry(new Locale("cs", "CZ")));
         locales.add(CountryService.toCountry(new Locale("el", "GR")));
         locales.add(CountryService.toCountry(new Locale("fa", "IR"), true));
diff --git a/primefaces/pom.xml b/primefaces/pom.xml
index 16735fe30c..3e3f8242b2 100644
--- a/primefaces/pom.xml
+++ b/primefaces/pom.xml
@@ -1003,6 +1003,9 @@
                                         <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                             <resource>META-INF/resources/primefaces/locales/locale-bn.js</resource>
                                         </transformer>
+                                        <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                            <resource>META-INF/resources/primefaces/locales/locale-bs.js</resource>
+                                        </transformer>
                                         <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                             <resource>META-INF/resources/primefaces/locales/locale-ca.js</resource>
                                         </transformer>
diff --git a/primefaces/src/main/java/org/primefaces/component/api/UICalendar.java b/primefaces/src/main/java/org/primefaces/component/api/UICalendar.java
index d02c2b79fa..3febc5ce67 100644
--- a/primefaces/src/main/java/org/primefaces/component/api/UICalendar.java
+++ b/primefaces/src/main/java/org/primefaces/component/api/UICalendar.java
@@ -376,19 +376,19 @@ public abstract class UICalendar extends AbstractPrimeHtmlInputText implements I
                 case OK:
                     break;
                 case INVALID_DISABLED_DATE:
-                    msg = MessageFactory.getFacesMessage(DATE_INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, DATE_INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
                     break;
                 case INVALID_RANGE_DATES_SEQUENTIAL:
-                    msg = MessageFactory.getFacesMessage(DATE_INVALID_RANGE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, DATE_INVALID_RANGE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
                     break;
                 case INVALID_MIN_DATE:
-                    msg = MessageFactory.getFacesMessage(DATE_MIN_DATE_ID, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, DATE_MIN_DATE_ID, FacesMessage.SEVERITY_ERROR, params);
                     break;
                 case INVALID_MAX_DATE:
-                    msg = MessageFactory.getFacesMessage(DATE_MAX_DATE_ID, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, DATE_MAX_DATE_ID, FacesMessage.SEVERITY_ERROR, params);
                     break;
                 case INVALID_OUT_OF_RANGE:
-                    msg = MessageFactory.getFacesMessage(DATE_OUT_OF_RANGE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, DATE_OUT_OF_RANGE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
                     break;
             }
         }
diff --git a/primefaces/src/main/java/org/primefaces/component/api/UIPageableData.java b/primefaces/src/main/java/org/primefaces/component/api/UIPageableData.java
index 8e63cb5b1b..8cdf227ef3 100644
--- a/primefaces/src/main/java/org/primefaces/component/api/UIPageableData.java
+++ b/primefaces/src/main/java/org/primefaces/component/api/UIPageableData.java
@@ -81,7 +81,7 @@ public class UIPageableData extends PrimeUIData implements Pageable, TouchAware
     }
 
     public String getEmptyMessage() {
-        return (String) getStateHelper().eval(PropertyKeys.emptyMessage, MessageFactory.getMessage(EMPTY_MESSAGE));
+        return (String) getStateHelper().eval(PropertyKeys.emptyMessage, MessageFactory.getMessage(getFacesContext(), EMPTY_MESSAGE));
     }
 
     public void setEmptyMessage(String emptyMessage) {
diff --git a/primefaces/src/main/java/org/primefaces/component/api/UITree.java b/primefaces/src/main/java/org/primefaces/component/api/UITree.java
index 9b490a3f0e..6e2379df08 100644
--- a/primefaces/src/main/java/org/primefaces/component/api/UITree.java
+++ b/primefaces/src/main/java/org/primefaces/component/api/UITree.java
@@ -558,7 +558,7 @@ public abstract class UITree extends UIComponentBase implements NamingContainer
                     msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, requiredMessage, requiredMessage);
                 }
                 else {
-                    msg = MessageFactory.getFacesMessage(REQUIRED_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, getClientId(context));
+                    msg = MessageFactory.getFacesMessage(context, REQUIRED_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, getClientId(context));
                 }
 
                 context.addMessage(getClientId(context), msg);
diff --git a/primefaces/src/main/java/org/primefaces/component/autocomplete/AutoCompleteRenderer.java b/primefaces/src/main/java/org/primefaces/component/autocomplete/AutoCompleteRenderer.java
index 8354623a70..956f459467 100644
--- a/primefaces/src/main/java/org/primefaces/component/autocomplete/AutoCompleteRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/autocomplete/AutoCompleteRenderer.java
@@ -554,6 +554,7 @@ public class AutoCompleteRenderer extends InputRenderer {
 
         writer.startElement("table", ac);
         writer.writeAttribute("class", AutoComplete.TABLE_CLASS, null);
+        writer.writeAttribute("role", HTML.ARIA_ROLE_LISTBOX, null);
 
         if (hasHeader) {
             writer.startElement("thead", ac);
diff --git a/primefaces/src/main/java/org/primefaces/component/calendar/BaseCalendarRenderer.java b/primefaces/src/main/java/org/primefaces/component/calendar/BaseCalendarRenderer.java
index 9731c0b709..6d64235563 100644
--- a/primefaces/src/main/java/org/primefaces/component/calendar/BaseCalendarRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/calendar/BaseCalendarRenderer.java
@@ -282,13 +282,13 @@ public abstract class BaseCalendarRenderer extends InputRenderer {
         params[2] = ComponentUtils.getLabel(context, calendar);
 
         if (calendar.isTimeOnly()) {
-            message = MessageFactory.getFacesMessage("javax.faces.converter.DateTimeConverter.TIME", FacesMessage.SEVERITY_ERROR, params);
+            message = MessageFactory.getFacesMessage(context, "javax.faces.converter.DateTimeConverter.TIME", FacesMessage.SEVERITY_ERROR, params);
         }
         else if (calendar.hasTime()) {
-            message = MessageFactory.getFacesMessage("javax.faces.converter.DateTimeConverter.DATETIME", FacesMessage.SEVERITY_ERROR, params);
+            message = MessageFactory.getFacesMessage(context, "javax.faces.converter.DateTimeConverter.DATETIME", FacesMessage.SEVERITY_ERROR, params);
         }
         else {
-            message = MessageFactory.getFacesMessage("javax.faces.converter.DateTimeConverter.DATE", FacesMessage.SEVERITY_ERROR, params);
+            message = MessageFactory.getFacesMessage(context, "javax.faces.converter.DateTimeConverter.DATE", FacesMessage.SEVERITY_ERROR, params);
         }
 
         return new ConverterException(message);
diff --git a/primefaces/src/main/java/org/primefaces/component/captcha/Captcha.java b/primefaces/src/main/java/org/primefaces/component/captcha/Captcha.java
index 9b02f88c43..d15821048c 100644
--- a/primefaces/src/main/java/org/primefaces/component/captcha/Captcha.java
+++ b/primefaces/src/main/java/org/primefaces/component/captcha/Captcha.java
@@ -122,7 +122,7 @@ public class Captcha extends CaptchaBase {
                     params[0] = ComponentUtils.getLabel(context, this);
                     params[1] = value;
 
-                    msg = MessageFactory.getFacesMessage(Captcha.INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, Captcha.INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, params);
                 }
 
                 context.addMessage(getClientId(context), msg);
diff --git a/primefaces/src/main/java/org/primefaces/component/datatable/DataTableRenderer.java b/primefaces/src/main/java/org/primefaces/component/datatable/DataTableRenderer.java
index 43d4a34d84..dcc8bf97a7 100644
--- a/primefaces/src/main/java/org/primefaces/component/datatable/DataTableRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/datatable/DataTableRenderer.java
@@ -767,6 +767,10 @@ public class DataTableRenderer extends DataRenderer {
             header.encodeAll(context);
         }
         else if (headerText != null) {
+            String title = column.getTitle();
+            if (LangUtils.isNotBlank(title)) {
+                writer.writeAttribute("title", title, null);
+            }
             if (table.isEscapeText()) {
                 writer.writeText(headerText, "headerText");
             }
@@ -1649,7 +1653,7 @@ public class DataTableRenderer extends DataRenderer {
             writer.writeAttribute("id", reflowId + "_label", null);
             writer.writeAttribute("for", reflowId, null);
             writer.writeAttribute("class", "ui-reflow-label", null);
-            writer.writeText(MessageFactory.getMessage(DataTable.SORT_LABEL), null);
+            writer.writeText(MessageFactory.getMessage(context, DataTable.SORT_LABEL), null);
             writer.endElement("label");
 
             writer.startElement("select", null);
@@ -1661,8 +1665,8 @@ public class DataTableRenderer extends DataRenderer {
             for (Map.Entry<SortMeta, String> header : headers.entrySet()) {
                 for (int sortOrder = 0; sortOrder < 2; sortOrder++) {
                     String sortOrderLabel = (sortOrder == 0)
-                                      ? MessageFactory.getMessage(DataTable.SORT_ASC)
-                                      : MessageFactory.getMessage(DataTable.SORT_DESC);
+                                      ? MessageFactory.getMessage(context, DataTable.SORT_ASC)
+                                      : MessageFactory.getMessage(context, DataTable.SORT_DESC);
 
                     writer.startElement("option", null);
                     writer.writeAttribute("value", header.getKey().getColumnKey() + "_" + sortOrder, null);
diff --git a/primefaces/src/main/java/org/primefaces/component/fileupload/FileUpload.java b/primefaces/src/main/java/org/primefaces/component/fileupload/FileUpload.java
index 9cfb0bf1d0..7f0bc838fb 100644
--- a/primefaces/src/main/java/org/primefaces/component/fileupload/FileUpload.java
+++ b/primefaces/src/main/java/org/primefaces/component/fileupload/FileUpload.java
@@ -28,6 +28,7 @@ import org.primefaces.event.FilesUploadEvent;
 import org.primefaces.model.file.UploadedFile;
 import org.primefaces.model.file.UploadedFiles;
 import org.primefaces.util.ComponentUtils;
+import org.primefaces.util.FileUploadUtils;
 import org.primefaces.validate.FileValidator;
 
 import java.util.Arrays;
@@ -38,6 +39,7 @@ import javax.faces.application.ResourceDependency;
 import javax.faces.context.FacesContext;
 import javax.faces.event.AbortProcessingException;
 import javax.faces.event.FacesEvent;
+import javax.faces.validator.ValidatorException;
 
 @ResourceDependency(library = "primefaces", name = "components.css")
 @ResourceDependency(library = "primefaces", name = "fileupload/fileupload.css")
@@ -80,19 +82,41 @@ public class FileUpload extends FileUploadBase {
     protected void validateValue(FacesContext context, Object newValue) {
         super.validateValue(context, newValue);
 
-        if (isValid() && ComponentUtils.isRequestSource(this, context)) {
-            if (newValue instanceof UploadedFile) {
-                int totalFilesCount = 0;
-                if ("advanced".equals(getMode())) {
-                    Map<String, String> params = context.getExternalContext().getRequestParameterMap();
-                    totalFilesCount = Integer.parseInt(params.get(this.getClientId(context) + "_totalFilesCount"));
-                }
+        if (isValid()) {
 
-                queueEvent(new FileUploadEvent(this, (UploadedFile) newValue, totalFilesCount));
+            if (newValue instanceof UploadedFile) {
+                validateFilename(context, (UploadedFile) newValue);
             }
             else if (newValue instanceof UploadedFiles) {
-                queueEvent(new FilesUploadEvent(this, (UploadedFiles) newValue));
+                for (UploadedFile uploadedFile : ((UploadedFiles) newValue).getFiles()) {
+                    validateFilename(context, uploadedFile);
+                }
             }
+
+            if (isValid()  && ComponentUtils.isRequestSource(this, context)) {
+                if (newValue instanceof UploadedFile) {
+                    int totalFilesCount = 0;
+                    if ("advanced".equals(getMode())) {
+                        Map<String, String> params = context.getExternalContext().getRequestParameterMap();
+                        totalFilesCount = Integer.parseInt(params.get(this.getClientId(context) + "_totalFilesCount"));
+                    }
+
+                    queueEvent(new FileUploadEvent(this, (UploadedFile) newValue, totalFilesCount));
+                }
+                else if (newValue instanceof UploadedFiles) {
+                    queueEvent(new FilesUploadEvent(this, (UploadedFiles) newValue));
+                }
+            }
+        }
+    }
+
+    public void validateFilename(FacesContext context, UploadedFile file) {
+        try {
+            FileUploadUtils.requireValidFilename(context, file.getFileName());
+        }
+        catch (ValidatorException ve) {
+            setValid(false);
+            context.addMessage(getClientId(context), ve.getFacesMessage());
         }
     }
 
@@ -107,4 +131,4 @@ public class FileUpload extends FileUploadBase {
         FileValidator fileValidator = getFileValidator();
         return fileValidator == null ? null : fileValidator.getSizeLimit();
     }
-}
+}
\ No newline at end of file
diff --git a/primefaces/src/main/java/org/primefaces/component/inputtext/InputTextRenderer.java b/primefaces/src/main/java/org/primefaces/component/inputtext/InputTextRenderer.java
index 399929961b..d63f3a038a 100644
--- a/primefaces/src/main/java/org/primefaces/component/inputtext/InputTextRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/inputtext/InputTextRenderer.java
@@ -84,8 +84,6 @@ public class InputTextRenderer extends InputRenderer {
             }
         }
 
-        encodeClientBehaviors(context, inputText);
-
         wb.finish();
     }
 
diff --git a/primefaces/src/main/java/org/primefaces/component/password/Password.java b/primefaces/src/main/java/org/primefaces/component/password/Password.java
index 6fc36f22a8..91beb90edb 100644
--- a/primefaces/src/main/java/org/primefaces/component/password/Password.java
+++ b/primefaces/src/main/java/org/primefaces/component/password/Password.java
@@ -74,7 +74,7 @@ public class Password extends PasswordBase {
                     params[0] = ComponentUtils.getLabel(context, this);
                     params[1] = ComponentUtils.getLabel(context, matchWith);
 
-                    msg = MessageFactory.getFacesMessage(Password.INVALID_MATCH_KEY, FacesMessage.SEVERITY_ERROR, params);
+                    msg = MessageFactory.getFacesMessage(context, Password.INVALID_MATCH_KEY, FacesMessage.SEVERITY_ERROR, params);
                 }
 
                 context.addMessage(getClientId(context), msg);
diff --git a/primefaces/src/main/java/org/primefaces/component/picklist/PickList.java b/primefaces/src/main/java/org/primefaces/component/picklist/PickList.java
index c53fdc5be5..b3135fdef1 100644
--- a/primefaces/src/main/java/org/primefaces/component/picklist/PickList.java
+++ b/primefaces/src/main/java/org/primefaces/component/picklist/PickList.java
@@ -139,7 +139,7 @@ public class PickList extends PickListBase {
                 message = new FacesMessage(FacesMessage.SEVERITY_ERROR, requiredMessage, requiredMessage);
             }
             else {
-                message = MessageFactory.getFacesMessage(REQUIRED_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, label);
+                message = MessageFactory.getFacesMessage(facesContext, REQUIRED_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, label);
             }
             facesContext.addMessage(clientId, message);
             setValid(false);
@@ -173,7 +173,7 @@ public class PickList extends PickListBase {
             Object targetItem = targetEntries.get(i);
             // Check if target item exists in source list
             if (!oldSource.contains(targetItem) && !oldTarget.contains(targetItem)) {
-                FacesMessage message = MessageFactory.getFacesMessage(UPDATE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, label);
+                FacesMessage message = MessageFactory.getFacesMessage(facesContext, UPDATE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, label);
                 facesContext.addMessage(clientId, message);
                 setValid(false);
                 break;
@@ -207,7 +207,7 @@ public class PickList extends PickListBase {
             boolean itemDisabled = isItemDisabled();
             // Check if disabled item has been moved from its former/original list
             if (itemDisabled && !oldEntries.contains(item)) {
-                FacesMessage message = MessageFactory.getFacesMessage(UPDATE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, label);
+                FacesMessage message = MessageFactory.getFacesMessage(facesContext, UPDATE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, label);
                 facesContext.addMessage(clientId, message);
                 setValid(false);
                 break;
diff --git a/primefaces/src/main/java/org/primefaces/component/selectonemenu/SelectOneMenu.java b/primefaces/src/main/java/org/primefaces/component/selectonemenu/SelectOneMenu.java
index 375713fd5e..8f25becd12 100644
--- a/primefaces/src/main/java/org/primefaces/component/selectonemenu/SelectOneMenu.java
+++ b/primefaces/src/main/java/org/primefaces/component/selectonemenu/SelectOneMenu.java
@@ -149,7 +149,7 @@ public class SelectOneMenu extends SelectOneMenuBase {
                             requiredMessageStr);
                 }
                 else {
-                    message = MessageFactory.getFacesMessage(REQUIRED_MESSAGE_ID,
+                    message = MessageFactory.getFacesMessage(context, REQUIRED_MESSAGE_ID,
                             FacesMessage.SEVERITY_ERROR,
                             ComponentUtils.getLabel(context, this));
                 }
diff --git a/primefaces/src/main/java/org/primefaces/component/slider/Slider.java b/primefaces/src/main/java/org/primefaces/component/slider/Slider.java
index 3ed4589ac4..50050c4963 100644
--- a/primefaces/src/main/java/org/primefaces/component/slider/Slider.java
+++ b/primefaces/src/main/java/org/primefaces/component/slider/Slider.java
@@ -156,7 +156,7 @@ public class Slider extends SliderBase {
             }
             else {
                 Object params = ComponentUtils.getLabel(context, this);
-                msg = MessageFactory.getFacesMessage(VALUE_OUT_OF_RANGE, FacesMessage.SEVERITY_ERROR, params);
+                msg = MessageFactory.getFacesMessage(context, VALUE_OUT_OF_RANGE, FacesMessage.SEVERITY_ERROR, params);
             }
             context.addMessage(getClientId(context), msg);
         }
diff --git a/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableBase.java b/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableBase.java
index b8886533fe..34a8d8d693 100644
--- a/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableBase.java
+++ b/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableBase.java
@@ -178,7 +178,7 @@ public abstract class TreeTableBase extends UITree implements Widget, ClientBeha
     }
 
     public String getEmptyMessage() {
-        return (String) getStateHelper().eval(PropertyKeys.emptyMessage, MessageFactory.getMessage(UIPageableData.EMPTY_MESSAGE));
+        return (String) getStateHelper().eval(PropertyKeys.emptyMessage, MessageFactory.getMessage(getFacesContext(), UIPageableData.EMPTY_MESSAGE));
     }
 
     public void setEmptyMessage(String emptyMessage) {
diff --git a/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableRenderer.java b/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableRenderer.java
index eed3fc0c84..568ea1bf2c 100644
--- a/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/treetable/TreeTableRenderer.java
@@ -629,6 +629,7 @@ public class TreeTableRenderer extends DataRenderer {
         ResponseWriter writer = context.getResponseWriter();
         UIComponent header = column.getFacet("header");
         String headerText = column.getHeaderText();
+        String title = column.getTitle();
         String ariaHeaderText = column.getAriaHeaderText();
         headerText = LangUtils.isNotBlank(headerText) ? headerText : ariaHeaderText;
 
@@ -707,6 +708,9 @@ public class TreeTableRenderer extends DataRenderer {
         }
         else if (headerText != null) {
             writer.writeText(headerText, "headerText");
+            if (LangUtils.isNotBlank(title)) {
+                writer.writeAttribute("title", title, null);
+            }
         }
 
         writer.endElement("span");
diff --git a/primefaces/src/main/java/org/primefaces/csp/CspPhaseListener.java b/primefaces/src/main/java/org/primefaces/csp/CspPhaseListener.java
index 8d12f56ba4..9225805616 100644
--- a/primefaces/src/main/java/org/primefaces/csp/CspPhaseListener.java
+++ b/primefaces/src/main/java/org/primefaces/csp/CspPhaseListener.java
@@ -29,6 +29,7 @@ import org.primefaces.context.PrimeFacesContext;
 import org.primefaces.util.LangUtils;
 import org.primefaces.util.Lazy;
 
+import javax.faces.application.ProjectStage;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PhaseEvent;
@@ -96,7 +97,10 @@ public class CspPhaseListener implements PhaseListener {
             externalContext.addResponseHeader("Content-Security-Policy", policy);
         }
 
-        String init = "if(window.PrimeFaces){PrimeFaces.csp.init('" + Encode.forJavaScript(state.getNonce()) + "');};";
+        String init = "if(window.PrimeFaces){PrimeFaces.csp.init('" + Encode.forJavaScript(state.getNonce()) + "');}";
+        if (context.isProjectStage(ProjectStage.Development)) {
+            init += "else{console.log('CSP active but PrimeFaces not included in current view!');}";
+        }
         PrimeFaces.current().executeInitScript(init);
     }
 
diff --git a/primefaces/src/main/java/org/primefaces/csp/CspState.java b/primefaces/src/main/java/org/primefaces/csp/CspState.java
index cbdc221eef..64ee159838 100644
--- a/primefaces/src/main/java/org/primefaces/csp/CspState.java
+++ b/primefaces/src/main/java/org/primefaces/csp/CspState.java
@@ -34,7 +34,17 @@ import java.util.Objects;
 import java.util.UUID;
 
 import javax.faces.context.FacesContext;
-
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Manages Content Security Policy (CSP) state for PrimeFaces applications.
+ * <p>
+ * This class handles nonce generation and validation for CSP headers, as well as tracking event handlers.
+ * The nonce is a cryptographically secure random value used to whitelist inline scripts.
+ * </p>
+ *
+ * @since 7.0
+ */
 public class CspState {
 
     private FacesContext context;
@@ -84,11 +94,17 @@ public class CspState {
                 // always prefer nonceViewState over nonceRequest
                 nonce = LangUtils.isNotBlank(nonceViewState) ? nonceViewState : nonceRequest;
 
+                // in case of a forward, we might create a new nonce here
+                // but it also means that the request had NO CSP request param... is this valid?
+                if (LangUtils.isBlank(nonce) && isForward(context)) {
+                    nonce = generateNonce();
+                }
+
                 validate(nonce);
             }
             // otherwise create a new nonce
             else {
-                nonce = Base64.getEncoder().encodeToString(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
+                nonce = generateNonce();
                 if (!context.getViewRoot().isTransient()) {
                     context.getViewRoot().getViewMap(true).put(Constants.RequestParams.NONCE_PARAM, nonce);
                 }
@@ -98,6 +114,31 @@ public class CspState {
         return nonce;
     }
 
+    /**
+     * Generates a random nonce value for Content Security Policy.
+     * Creates a UUID, converts it to a string, gets its bytes in UTF-8 encoding,
+     * and encodes those bytes as a Base64 string.
+     *
+     * @return Base64 encoded nonce string
+     */
+    public String generateNonce() {
+        return Base64.getEncoder().encodeToString(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
+    }
+
+    /**
+     * Checks if the current request is a forward.
+     *
+     * @param context The FacesContext
+     * @return true if request is forwarded, false otherwise
+     */
+    protected boolean isForward(FacesContext context) {
+        Object request = context.getExternalContext().getRequest();
+        if (request instanceof HttpServletRequest) {
+            return ((HttpServletRequest) request).getAttribute("javax.servlet.forward.request_uri") != null;
+        }
+        return false;
+    }
+
     /**
      * Currently the script nonce is user-supplied input, so we have to validate it to prevent header/XSS injections.
      *
diff --git a/primefaces/src/main/java/org/primefaces/model/file/AbstractUploadedFile.java b/primefaces/src/main/java/org/primefaces/model/file/AbstractUploadedFile.java
index 3d10caeaf2..e642e7da5a 100644
--- a/primefaces/src/main/java/org/primefaces/model/file/AbstractUploadedFile.java
+++ b/primefaces/src/main/java/org/primefaces/model/file/AbstractUploadedFile.java
@@ -49,7 +49,7 @@ public abstract class AbstractUploadedFile<T> implements UploadedFile, Serializa
 
     protected AbstractUploadedFile(T source, String filename, Long sizeLimit, String webKitRelativePath) {
         this.source = source;
-        this.filename = FileUploadUtils.requireValidFilename(filename);
+        this.filename = filename;
         this.sizeLimit = sizeLimit;
         this.webKitRelativePath = webKitRelativePath;
     }
diff --git a/primefaces/src/main/java/org/primefaces/renderkit/BodyRenderer.java b/primefaces/src/main/java/org/primefaces/renderkit/BodyRenderer.java
index dbbd190d82..86db2b38be 100644
--- a/primefaces/src/main/java/org/primefaces/renderkit/BodyRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/renderkit/BodyRenderer.java
@@ -75,14 +75,17 @@ public class BodyRenderer extends CoreRenderer {
             writer.startElement("script", null);
             RendererUtils.encodeScriptTypeIfNecessary(context);
 
-            writer.write("$(function(){");
+            writer.write("(function(){const pfLoad=() => {");
 
             for (int i = 0; i < scripts.size(); i++) {
                 writer.write(scripts.get(i));
                 writer.write(';');
             }
 
-            writer.write("});");
+            writer.write("};if(window.$){$(function(){pfLoad()})}");
+            writer.write("else if(document.readyState==='complete'){pfLoad()}");
+            writer.write("else{document.addEventListener('DOMContentLoaded', pfLoad)}})();");
+
             writer.endElement("script");
         }
     }
diff --git a/primefaces/src/main/java/org/primefaces/renderkit/HeadRenderer.java b/primefaces/src/main/java/org/primefaces/renderkit/HeadRenderer.java
index 31f7f819b3..7bcbf549c8 100644
--- a/primefaces/src/main/java/org/primefaces/renderkit/HeadRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/renderkit/HeadRenderer.java
@@ -292,16 +292,22 @@ public class HeadRenderer extends Renderer {
             boolean moveScriptsToBottom = PrimeRequestContext.getCurrentInstance().getApplicationContext().getConfig().isMoveScriptsToBottom();
 
             if (!moveScriptsToBottom) {
-                writer.write("$(function(){");
-            }
+                writer.write("(function(){const pfInit=() => {");
 
-            for (int i = 0; i < scripts.size(); i++) {
-                writer.write(scripts.get(i));
-                writer.write(';');
-            }
+                for (int i = 0; i < scripts.size(); i++) {
+                    writer.write(scripts.get(i));
+                    writer.write(';');
+                }
 
-            if (!moveScriptsToBottom) {
-                writer.write("});");
+                writer.write("};if(window.$){$(function(){pfInit()})}");
+                writer.write("else if(document.readyState==='complete'){pfInit()}");
+                writer.write("else{document.addEventListener('DOMContentLoaded', pfInit)}})();");
+            }
+            else {
+                for (int i = 0; i < scripts.size(); i++) {
+                    writer.write(scripts.get(i));
+                    writer.write(';');
+                }
             }
 
             writer.endElement("script");
diff --git a/primefaces/src/main/java/org/primefaces/util/FileUploadUtils.java b/primefaces/src/main/java/org/primefaces/util/FileUploadUtils.java
index 18ebe5c7c3..088ae62d7e 100644
--- a/primefaces/src/main/java/org/primefaces/util/FileUploadUtils.java
+++ b/primefaces/src/main/java/org/primefaces/util/FileUploadUtils.java
@@ -69,6 +69,12 @@ public class FileUploadUtils {
 
     private static final Logger LOGGER = Logger.getLogger(FileUploadUtils.class.getName());
 
+    // Message keys
+    private static final String FILENAME_EMPTY = "primefaces.FileValidator.FILENAME_EMPTY";
+    private static final String FILENAME_INVALID_CHAR = "primefaces.FileValidator.FILENAME_INVALID_CHAR";
+    private static final String FILENAME_INVALID_WINDOWS = "primefaces.FileValidator.FILENAME_INVALID_WINDOWS";
+    private static final String FILENAME_INVALID_LINUX = "primefaces.FileValidator.FILENAME_INVALID_LINUX";
+
     // https://owasp.org/www-community/OWASP_Validation_Regex_Repository
     private static final Pattern INVALID_FILENAME_WINDOWS =
             Pattern.compile("^(?!^(PRN|AUX|CLOCK\\$|NUL|CON|COM\\d|LPT\\d|\\..*)(\\..+)?$)[^\\x00-\\x1f\\\\?*:\\\";|/<>]+$");
@@ -84,31 +90,31 @@ public class FileUploadUtils {
      * @param filename the name of the file to check
      * @return the extracted file name
      */
-    public static String requireValidFilename(String filename) {
+    public static String requireValidFilename(FacesContext context, String filename) {
         if (LangUtils.isBlank(filename)) {
-            throw validationError("Filename cannot be empty or null");
+            throw validationError(MessageFactory.getMessage(context, FILENAME_EMPTY));
         }
 
         // use java.nio Paths to detect a bad character
         Character ch = containsInvalidCharacters(filename);
         if (ch != null) {
-            throw validationError("Invalid filename: (" + filename + ") contains invalid character: " + ch);
+            throw validationError(MessageFactory.getMessage(context, FILENAME_INVALID_CHAR, filename, ch));
         }
 
         // Windows and Linux have different allowed characters
         if (isSystemWindows()) {
             if (!INVALID_FILENAME_WINDOWS.matcher(filename).find()) {
-                throw validationError("Invalid Windows filename: " + filename);
+                throw validationError(MessageFactory.getMessage(context, FILENAME_INVALID_WINDOWS, filename));
             }
         }
         else if (INVALID_FILENAME_LINUX.matcher(filename).find()) {
-            throw validationError("Invalid Linux filename: " + filename);
+            throw validationError(MessageFactory.getMessage(context, FILENAME_INVALID_LINUX, filename));
         }
 
         // URL encoded characters like %20 are invalid
         Matcher encodedMatcher = ENCODED_CHARS_PAT.matcher(filename);
         if (encodedMatcher.find() ) {
-            throw validationError( "Invalid filename: (" + filename + ") contains invalid character: " + encodedMatcher.group());
+            throw validationError(MessageFactory.getMessage(context, FILENAME_INVALID_CHAR, filename, encodedMatcher.group()));
         }
 
         return FilenameUtils.getName(filename);
diff --git a/primefaces/src/main/java/org/primefaces/util/MessageFactory.java b/primefaces/src/main/java/org/primefaces/util/MessageFactory.java
index 28fbd359d9..aeb91b4cdd 100644
--- a/primefaces/src/main/java/org/primefaces/util/MessageFactory.java
+++ b/primefaces/src/main/java/org/primefaces/util/MessageFactory.java
@@ -55,16 +55,15 @@ public class MessageFactory {
         // NOOP
     }
 
-    public static FacesMessage getFacesMessage(String messageId, FacesMessage.Severity severity, Object... params) {
-        FacesMessage facesMessage = getFacesMessage(LocaleUtils.getCurrentLocale(), messageId, params);
+    public static FacesMessage getFacesMessage(FacesContext context, String messageId, FacesMessage.Severity severity, Object... params) {
+        FacesMessage facesMessage = getFacesMessage(context, LocaleUtils.getCurrentLocale(context), messageId, params);
         facesMessage.setSeverity(severity);
         return facesMessage;
     }
 
-    public static FacesMessage getFacesMessage(Locale locale, String messageId, Object... params) {
+    public static FacesMessage getFacesMessage(FacesContext facesContext, Locale locale, String messageId, Object... params) {
         String summary = null;
         String detail = null;
-        FacesContext facesContext = FacesContext.getCurrentInstance();
         Application application = facesContext.getApplication();
         String userBundleName = application.getMessageBundle();
         ResourceBundle bundle = null;
@@ -132,13 +131,12 @@ public class MessageFactory {
         return new FacesMessage(summary, detail);
     }
 
-    public static String getMessage(String messageId, Object... params) {
-        return getMessage(LocaleUtils.getCurrentLocale(), messageId, params);
+    public static String getMessage(FacesContext facesContext, String messageId, Object... params) {
+        return getMessage(facesContext, LocaleUtils.getCurrentLocale(facesContext), messageId, params);
     }
 
-    public static String getMessage(Locale locale, String messageId, Object... params) {
+    public static String getMessage(FacesContext facesContext, Locale locale, String messageId, Object... params) {
         String summary = null;
-        FacesContext facesContext = FacesContext.getCurrentInstance();
         Application application = facesContext.getApplication();
         String userBundleName = application.getMessageBundle();
         ResourceBundle bundle = null;
diff --git a/primefaces/src/main/java/org/primefaces/validate/FileValidator.java b/primefaces/src/main/java/org/primefaces/validate/FileValidator.java
index 65b865875b..8227f6c1f1 100644
--- a/primefaces/src/main/java/org/primefaces/validate/FileValidator.java
+++ b/primefaces/src/main/java/org/primefaces/validate/FileValidator.java
@@ -108,7 +108,7 @@ public class FileValidator extends AbstractPrimeValidator implements ClientValid
         Integer fileLimit = getFileLimit();
         if (fileLimit != null && uploadedFiles.getFiles().size() > fileLimit) {
             throw new ValidatorException(
-                    MessageFactory.getFacesMessage(FILE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, fileLimit));
+                    MessageFactory.getFacesMessage(context, FILE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, fileLimit));
         }
 
         long totalSize = 0;
@@ -120,7 +120,7 @@ public class FileValidator extends AbstractPrimeValidator implements ClientValid
         Long sizeLimit = getSizeLimit();
         if (sizeLimit != null && totalSize > sizeLimit) {
             throw new ValidatorException(
-                    MessageFactory.getFacesMessage(SIZE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR,
+                    MessageFactory.getFacesMessage(context, SIZE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR,
                             "*", FileUploadUtils.formatBytes(sizeLimit, LocaleUtils.getCurrentLocale(context))));
         }
     }
@@ -131,14 +131,14 @@ public class FileValidator extends AbstractPrimeValidator implements ClientValid
         Long sizeLimit = getSizeLimit();
         if (sizeLimit != null && uploadedFile.getSize() > sizeLimit) {
             throw new ValidatorException(
-                    MessageFactory.getFacesMessage(SIZE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR,
+                    MessageFactory.getFacesMessage(context, SIZE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR,
                             uploadedFile.getFileName(), FileUploadUtils.formatBytes(sizeLimit, LocaleUtils.getCurrentLocale(context))));
         }
 
         String allowTypes = getAllowTypes();
         if (!FileUploadUtils.isValidType(applicationContext, uploadedFile, allowTypes, accept)) {
             throw new ValidatorException(
-                    MessageFactory.getFacesMessage(ALLOW_TYPES_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, uploadedFile.getFileName(),
+                    MessageFactory.getFacesMessage(context, ALLOW_TYPES_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, uploadedFile.getFileName(),
                             FileUploadUtils.formatAllowTypes(allowTypes)));
         }
 
diff --git a/primefaces/src/main/java/org/primefaces/virusscan/impl/ClamDaemonScanner.java b/primefaces/src/main/java/org/primefaces/virusscan/impl/ClamDaemonScanner.java
index ad706ff96f..16e8122b24 100644
--- a/primefaces/src/main/java/org/primefaces/virusscan/impl/ClamDaemonScanner.java
+++ b/primefaces/src/main/java/org/primefaces/virusscan/impl/ClamDaemonScanner.java
@@ -116,7 +116,7 @@ public class ClamDaemonScanner implements VirusScanner {
     }
 
     protected String createErrorMessage(UploadedFile file, String response) {
-        return MessageFactory.getMessage("primefaces.fileupload.CLAM_AV_FILE", file.getFileName(), response);
+        return MessageFactory.getMessage(FacesContext.getCurrentInstance(), "primefaces.fileupload.CLAM_AV_FILE", file.getFileName(), response);
     }
 
     /**
diff --git a/primefaces/src/main/java/org/primefaces/virusscan/impl/VirusTotalReportScanner.java b/primefaces/src/main/java/org/primefaces/virusscan/impl/VirusTotalReportScanner.java
index 0e6a4eee37..58e6057096 100644
--- a/primefaces/src/main/java/org/primefaces/virusscan/impl/VirusTotalReportScanner.java
+++ b/primefaces/src/main/java/org/primefaces/virusscan/impl/VirusTotalReportScanner.java
@@ -107,7 +107,7 @@ public class VirusTotalReportScanner implements VirusScanner {
     }
 
     protected String createErrorMessage(UploadedFile file, JSONObject json) {
-        return MessageFactory.getMessage("primefaces.fileupload.VIRUS_TOTAL_FILE", file.getFileName());
+        return MessageFactory.getMessage(FacesContext.getCurrentInstance(), "primefaces.fileupload.VIRUS_TOTAL_FILE", file.getFileName());
     }
 
     protected URLConnection openConnection(UploadedFile file) throws IOException {
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.ajax.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.ajax.js
index 9deab29a97..d91d875c8b 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.ajax.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.ajax.js
@@ -44,25 +44,25 @@ if (!PrimeFaces.ajax) {
          * @type {string}
          * @readonly
          */
-        VIEW_HEAD : "javax.faces.ViewHead",
+        VIEW_HEAD: "javax.faces.ViewHead",
         /**
          * Name for the ID of the BODY element, used in AJAX requests.
          * @type {string}
          * @readonly
          */
-        VIEW_BODY : "javax.faces.ViewBody",
+        VIEW_BODY: "javax.faces.ViewBody",
         /**
          * Name for the ID of a resource entry, used in AJAX requests.
          * @type {string}
          * @readonly
          */
-        RESOURCE : "javax.faces.Resource",
+        RESOURCE: "javax.faces.Resource",
 
         /**
          * Parameter shortcut mapping for the method `PrimeFaces.ab`.
          * @type {Record<string, string>}
          */
-        CFG_SHORTCUTS : {
+        CFG_SHORTCUTS: {
             's': 'source',
             'f': 'formId',
             'p': 'process',
@@ -90,7 +90,7 @@ if (!PrimeFaces.ajax) {
          * Minimum number of milliseconds to show inline Ajax load animations.
          * @type {number}
          */
-        minLoadAnimation : 500,
+        minLoadAnimation: 500,
 
         /**
          * This object contains utility methods for AJAX requests, primarily used internally.
@@ -111,8 +111,8 @@ if (!PrimeFaces.ajax) {
             getContent: function(node) {
                 var content = '';
 
-                for(var i = 0; i < node.childNodes.length; i++) {
-                    content += node.childNodes[i].nodeValue;
+                for (const child of node.childNodes) {
+                    content += child.nodeValue;
                 }
 
                 return content;
@@ -204,7 +204,7 @@ if (!PrimeFaces.ajax) {
 
                 return $.inArray(sourceId, triggers) !== -1;
             },
-            
+
             /**
              * Is this script an AJAX request?
              * @param {string} script the JS script to check
@@ -302,7 +302,7 @@ if (!PrimeFaces.ajax) {
                 var cache = $.ajaxSetup()['cache'];
                 $.ajaxSetup()['cache'] = true;
 
-                var headStartTag = new RegExp("<head[^>]*>", "gi").exec(content)[0];
+                var headStartTag = /<head[^>]*>/gi.exec(content)[0];
                 var headStartIndex = content.indexOf(headStartTag) + headStartTag.length;
                 $('head').html(content.substring(headStartIndex, content.lastIndexOf("</head>")));
 
@@ -314,7 +314,7 @@ if (!PrimeFaces.ajax) {
              * @param {string} content The content of the changeset that was returned by an AJAX request.
              */
             updateBody: function(content) {
-                var bodyStartTag = new RegExp("<body[^>]*>", "gi").exec(content)[0];
+                var bodyStartTag = /<body[^>]*>/gi.exec(content)[0];
                 var bodyStartIndex = content.indexOf(bodyStartTag) + bodyStartTag.length;
                 $('body').html(content.substring(bodyStartIndex, content.lastIndexOf("</body>")));
             },
@@ -412,21 +412,20 @@ if (!PrimeFaces.ajax) {
              * @param {Partial<PrimeFaces.ajax.Configuration>} request The request to send.
              */
             offer: function(request) {
-                if(request.delay) {
-                    var sourceId = null,
-                    $this = this,
-                    sourceId = (typeof(request.source) === 'string') ? request.source: $(request.source).attr('id'),
-                    createTimeout = function() {
+                if (request.delay) {
+                    var $this = this,
+                        sourceId = (typeof (request.source) === 'string') ? request.source : $(request.source).attr('id'),
+                        createTimeout = function() {
                             return PrimeFaces.queueTask(function() {
                                 $this.requests.push(request);
 
-                                if($this.requests.length === 1) {
+                                if ($this.requests.length === 1) {
                                     PrimeFaces.ajax.Request.send(request);
                                 }
                             }, request.delay);
-                    };
+                        };
 
-                    if(this.delays[sourceId]) {
+                    if (this.delays[sourceId]) {
                         clearTimeout(this.delays[sourceId].timeout);
                         this.delays[sourceId].timeout = createTimeout();
                     }
@@ -439,7 +438,7 @@ if (!PrimeFaces.ajax) {
                 else {
                     this.requests.push(request);
 
-                    if(this.requests.length === 1) {
+                    if (this.requests.length === 1) {
                         PrimeFaces.ajax.Request.send(request);
                     }
                 }
@@ -452,14 +451,14 @@ if (!PrimeFaces.ajax) {
              * is empty.
              */
             poll: function() {
-                if(this.isEmpty()) {
+                if (this.isEmpty()) {
                     return null;
                 }
 
                 var processed = this.requests.shift(),
-                next = this.peek();
+                    next = this.peek();
 
-                if(next) {
+                if (next) {
                     PrimeFaces.ajax.Request.send(next);
                 }
 
@@ -472,7 +471,7 @@ if (!PrimeFaces.ajax) {
              * or `null` when this queue is empty.
              */
             peek: function() {
-                if(this.isEmpty()) {
+                if (this.isEmpty()) {
                     return null;
                 }
 
@@ -502,7 +501,7 @@ if (!PrimeFaces.ajax) {
              */
             removeXHR: function(xhr) {
                 var index = $.inArray(xhr, this.xhrs);
-                if(index > -1) {
+                if (index > -1) {
                     this.xhrs.splice(index, 1);
                 }
             },
@@ -516,8 +515,7 @@ if (!PrimeFaces.ajax) {
                 this.requests = new Array();
 
                 // abort any in-flight that are not DONE(4)
-                for(var i = 0; i < this.xhrs.length; i++) {
-                    var xhr = this.xhrs[i];
+                for (const xhr of this.xhrs) {
                     if (xhr.readyState !== 4) {
                         xhr.abort();
                     }
@@ -557,7 +555,7 @@ if (!PrimeFaces.ajax) {
                     cfg.earlyPostParams = PrimeFaces.ajax.Request.collectEarlyPostParams(cfg);
                 }
 
-                if(cfg.async) {
+                if (cfg.async) {
                     PrimeFaces.ajax.Request.send(cfg);
                 }
                 else {
@@ -580,7 +578,7 @@ if (!PrimeFaces.ajax) {
                 var earlyPostParams;
 
                 var sourceElement;
-                if (typeof(cfg.source) === 'string') {
+                if (typeof (cfg.source) === 'string') {
                     sourceElement = $(PrimeFaces.escapeClientId(cfg.source));
                 }
                 else {
@@ -621,23 +619,23 @@ if (!PrimeFaces.ajax) {
 
                 PrimeFaces.customFocus = false;
 
-                var global = (cfg.global === true || cfg.global === undefined) ? true : false,
-                form = null,
-                sourceId = null,
-                retVal = null;
+                var global = cfg.global !== false,
+                    form = null,
+                    sourceId = null,
+                    retVal = null;
 
-                if(cfg.onstart) {
+                if (cfg.onstart) {
                     retVal = cfg.onstart.call(this, cfg);
                 }
-                if(cfg.ext && cfg.ext.onstart) {
+                if (cfg.ext && cfg.ext.onstart) {
                     retVal = cfg.ext.onstart.call(this, cfg);
                 }
 
-                if(retVal === false) {
+                if (retVal === false) {
                     PrimeFaces.debug('AJAX request cancelled by onstart callback.');
 
                     //remove from queue
-                    if(!cfg.async) {
+                    if (!cfg.async) {
                         PrimeFaces.ajax.Queue.poll();
                     }
 
@@ -648,12 +646,12 @@ if (!PrimeFaces.ajax) {
                     return false;  //cancel request
                 }
 
-                if(global) {
+                if (global) {
                     $(document).trigger('pfAjaxStart');
                 }
 
                 //source can be a client id or an element defined by this keyword
-                if(typeof(cfg.source) === 'string') {
+                if (typeof (cfg.source) === 'string') {
                     sourceId = cfg.source;
                 } else {
                     sourceId = $(cfg.source).attr('id');
@@ -661,7 +659,7 @@ if (!PrimeFaces.ajax) {
 
                 var $source = $(PrimeFaces.escapeClientId(sourceId));
 
-                if(cfg.formId) {
+                if (cfg.formId) {
                     //Explicit form is defined
                     form = PrimeFaces.expressions.SearchExpressionFacade.resolveComponentsAsSelector($source, cfg.formId);
                 }
@@ -716,7 +714,7 @@ if (!PrimeFaces.ajax) {
 
                 //process
                 var processArray = PrimeFaces.ajax.Request.resolveComponentsForAjaxCall($source, cfg, 'process');
-                if(cfg.fragmentProcess) {
+                if (cfg.fragmentProcess) {
                     processArray.push(cfg.fragmentProcess);
                 }
                 // default == @none
@@ -738,22 +736,22 @@ if (!PrimeFaces.ajax) {
 
                 //update
                 var updateArray = PrimeFaces.ajax.Request.resolveComponentsForAjaxCall($source, cfg, 'update');
-                if(cfg.fragmentUpdate) {
+                if (cfg.fragmentUpdate) {
                     updateArray.push(cfg.fragmentUpdate);
                 }
-                if(updateArray.length > 0) {
+                if (updateArray.length > 0) {
                     PrimeFaces.ajax.Request.addParam(postParams, PrimeFaces.PARTIAL_UPDATE_PARAM, updateArray.join(' '), parameterPrefix);
                 }
 
                 //behavior event
-                if(cfg.event) {
+                if (cfg.event) {
                     PrimeFaces.ajax.Request.addParam(postParams, PrimeFaces.BEHAVIOR_EVENT_PARAM, cfg.event, parameterPrefix);
 
                     var domEvent = cfg.event;
 
-                    if(cfg.event === 'valueChange')
+                    if (cfg.event === 'valueChange')
                         domEvent = 'change';
-                    else if(cfg.event === 'action')
+                    else if (cfg.event === 'action')
                         domEvent = 'click';
 
                     PrimeFaces.ajax.Request.addParam(postParams, PrimeFaces.PARTIAL_EVENT_PARAM, domEvent, parameterPrefix);
@@ -763,10 +761,10 @@ if (!PrimeFaces.ajax) {
                 }
 
                 //params
-                if(cfg.params) {
+                if (cfg.params) {
                     PrimeFaces.ajax.Request.addParams(postParams, cfg.params, parameterPrefix);
                 }
-                if(cfg.ext && cfg.ext.params) {
+                if (cfg.ext && cfg.ext.params) {
                     PrimeFaces.ajax.Request.addParams(postParams, cfg.ext.params, parameterPrefix);
                 }
 
@@ -783,23 +781,23 @@ if (!PrimeFaces.ajax) {
                  * Only add params of process components and their children
                  * if partial submit is enabled and there are components to process partially
                  */
-                if(cfg.partialSubmit && processIds.indexOf('@all') === -1) {
+                if (cfg.partialSubmit && processIds.indexOf('@all') === -1) {
                     var formProcessed = false;
 
                     if (processIds.indexOf('@none') === -1) {
-                        var partialSubmitFilter = cfg.partialSubmitFilter||':input';
-                        for (var i = 0; i < processArray.length; i++) {
-                            var jqProcess = $(PrimeFaces.escapeClientId(processArray[i]));
+                        var partialSubmitFilter = cfg.partialSubmitFilter || ':input';
+                        for (const processId of processArray) {
+                            var jqProcess = $(PrimeFaces.escapeClientId(processId));
                             var componentPostParams = null;
 
-                            if(jqProcess.is('form')) {
+                            if (jqProcess.is('form')) {
                                 componentPostParams = jqProcess.serializeArray();
                                 formProcessed = true;
                                 if (multipart) {
                                     scanForFiles = scanForFiles.add(jqProcess);
                                 }
                             }
-                            else if(jqProcess.is(':input')) {
+                            else if (jqProcess.is(':input')) {
                                 componentPostParams = jqProcess.serializeArray();
                                 if (multipart) {
                                     scanForFiles = scanForFiles.add(jqProcess);
@@ -869,17 +867,17 @@ if (!PrimeFaces.ajax) {
                     });
 
                     fileInputs.each(function(index, value) {
-                        for (var i = 0; i < value.files.length; i++) {
-                            formData.append(value.id, value.files[i]);
+                        for (const file of value.files) {
+                            formData.append(value.id, file);
                         }
                     });
                 }
 
                 var xhrOptions = {
-                    url : postURL,
-                    type : "POST",
-                    cache : false,
-                    dataType : "xml",
+                    url: postURL,
+                    type: "POST",
+                    cache: false,
+                    dataType: "xml",
                     portletForms: PrimeFaces.ajax.Utils.getPorletForms(form, parameterPrefix),
                     source: cfg.source,
                     global: false,
@@ -888,7 +886,7 @@ if (!PrimeFaces.ajax) {
                         xhr.pfSettings = settings;
                         xhr.pfArgs = {}; // default should be an empty object
 
-                        if(global) {
+                        if (global) {
                             $(document).trigger('pfAjaxSend', [xhr, this]);
                         }
                     }
@@ -925,7 +923,7 @@ if (!PrimeFaces.ajax) {
                 var jqXhr = $.ajax(xhrOptions)
                     .fail(function(xhr, status, errorThrown) {
                         if (cfg.promise) {
-                            cfg.promise.reject({jqXHR: xhr, textStatus: status, errorThrown: errorThrown});
+                            cfg.promise.reject({ jqXHR: xhr, textStatus: status, errorThrown: errorThrown });
                         }
 
                         var location = xhr.getResponseHeader("Location");
@@ -934,10 +932,10 @@ if (!PrimeFaces.ajax) {
                             window.location = location;
                             return;
                         }
-                        if(cfg.onerror) {
+                        if (cfg.onerror) {
                             cfg.onerror.call(this, xhr, status, errorThrown);
                         }
-                        if(cfg.ext && cfg.ext.onerror) {
+                        if (cfg.ext && cfg.ext.onerror) {
                             cfg.ext.onerror.call(this, xhr, status, errorThrown);
                         }
 
@@ -953,36 +951,36 @@ if (!PrimeFaces.ajax) {
                             // Resolve promise for custom JavaScript handler
                             // Promise handlers are called asynchronously so they are run after the response was handled
                             if (cfg.promise) {
-                                cfg.promise.resolve({document: data, textStatus: status, jqXHR: xhr});
+                                cfg.promise.resolve({ document: data, textStatus: status, jqXHR: xhr });
                             }
 
                             //call user callback
-                            if(cfg.onsuccess) {
+                            if (cfg.onsuccess) {
                                 parsed = cfg.onsuccess.call(this, data, status, xhr);
                             }
 
                             //extension callback that might parse response
-                            if(cfg.ext && cfg.ext.onsuccess && !parsed) {
+                            if (cfg.ext && cfg.ext.onsuccess && !parsed) {
                                 parsed = cfg.ext.onsuccess.call(this, data, status, xhr);
                             }
 
-                            if(global) {
+                            if (global) {
                                 $(document).trigger('pfAjaxSuccess', [xhr, this]);
                             }
 
                             //do not execute default handler as response already has been parsed
-                            if(parsed) {
+                            if (parsed) {
                                 return;
                             }
                             else {
                                 PrimeFaces.ajax.Response.handle(data, status, xhr);
                             }
                         }
-                        catch(err) {
+                        catch (err) {
                             PrimeFaces.error(err);
                         }
 
-                        if(global) {
+                        if (global) {
                             $(document).trigger('pfAjaxUpdated', [xhr, this, xhr.pfArgs]);
                         }
 
@@ -990,16 +988,16 @@ if (!PrimeFaces.ajax) {
                     })
                     .always(function(data, status, xhr) {
                         // first call the extension callback (e.g. datatable paging)
-                        if(cfg.ext && cfg.ext.oncomplete) {
+                        if (cfg.ext && cfg.ext.oncomplete) {
                             cfg.ext.oncomplete.call(this, xhr, status, xhr.pfArgs, data);
                         }
 
                         // after that, call the end user's callback, which should be called when everything is ready
-                        if(cfg.oncomplete) {
+                        if (cfg.oncomplete) {
                             cfg.oncomplete.call(this, xhr, status, xhr.pfArgs, data);
                         }
 
-                        if(global) {
+                        if (global) {
                             $(document).trigger('pfAjaxComplete', [xhr, this, xhr.pfArgs]);
                         }
 
@@ -1007,7 +1005,7 @@ if (!PrimeFaces.ajax) {
 
                         PrimeFaces.ajax.Queue.removeXHR(xhr);
 
-                        if(!cfg.async) {
+                        if (!cfg.async) {
                             PrimeFaces.ajax.Queue.poll();
                         }
                     });
@@ -1064,10 +1062,10 @@ if (!PrimeFaces.ajax) {
             addParam: function(params, name, value, parameterPrefix) {
                 // add namespace if not available
                 if (parameterPrefix || !name.indexOf(parameterPrefix) === 0) {
-                    params.push({ name:parameterPrefix + name, value:value });
+                    params.push({ name: parameterPrefix + name, value: value });
                 }
                 else {
-                    params.push({ name:name, value:value });
+                    params.push({ name: name, value: value });
                 }
 
             },
@@ -1103,8 +1101,7 @@ if (!PrimeFaces.ajax) {
              */
             addParams: function(params, paramsToAdd, parameterPrefix) {
 
-                for (var i = 0; i < paramsToAdd.length; i++) {
-                    var param = paramsToAdd[i];
+                for (const param of paramsToAdd) {
                     // add namespace if not available
                     if (parameterPrefix && !param.name.indexOf(parameterPrefix) === 0) {
                         param.name = parameterPrefix + param.name;
@@ -1201,10 +1198,7 @@ if (!PrimeFaces.ajax) {
                 $.each(arr1, function(index1, param1) {
                     // loop arr2 params and remove it, if it's the same param as the arr1 param
                     arr2 = $.grep(arr2, function(param2, index2) {
-                        if (param2.name === param1.name) {
-                            return false;
-                        }
-                        return true;
+                        return param2.name !== param1.name;
                     });
                 });
 
@@ -1280,8 +1274,7 @@ if (!PrimeFaces.ajax) {
 
                 var partialResponseNode = xml.getElementsByTagName("partial-response")[0];
 
-                for (var i = 0; i < partialResponseNode.childNodes.length; i++) {
-                    var currentNode = partialResponseNode.childNodes[i];
+                for (const currentNode of partialResponseNode.childNodes) {
 
                     switch (currentNode.nodeName) {
                         case "redirect":
@@ -1297,8 +1290,7 @@ if (!PrimeFaces.ajax) {
                                 activeElementSelection = activeElement.getSelection();
                             }
 
-                            for (var j = 0; j < currentNode.childNodes.length; j++) {
-                                var currentChangeNode = currentNode.childNodes[j];
+                            for (const currentChangeNode of currentNode.childNodes) {
                                 switch (currentChangeNode.nodeName) {
                                     case "update":
                                         PrimeFaces.ajax.ResponseProcessor.doUpdate(currentChangeNode, xhr, updateHandler);
@@ -1346,7 +1338,7 @@ if (!PrimeFaces.ajax) {
              * @param {PrimeFaces.ajax.ActiveElementSelection} [activeElementSelection] The range to select, for INPUT
              * and TEXTAREA elements.
              */
-            handleReFocus : function(activeElementId, activeElementSelection) {
+            handleReFocus: function(activeElementId, activeElementSelection) {
                 // skip when customFocus is active
                 if (PrimeFaces.customFocus === true) {
                     PrimeFaces.customFocus = false;
@@ -1382,11 +1374,9 @@ if (!PrimeFaces.ajax) {
              * Destroys all widgets that are not part of the DOM anymore, usually because they were removed by an AJAX
              * update. Calls the `destroy` method on the widget and removes the widget from the global widget registry.
              */
-            destroyDetachedWidgets : function() {
+            destroyDetachedWidgets: function() {
                 // destroy detached widgets
-                for (var i = 0; i < PrimeFaces.detachedWidgets.length; i++) {
-                    var widgetVar = PrimeFaces.detachedWidgets[i];
-
+                for (const widgetVar of PrimeFaces.detachedWidgets) {
                     var widget = PF(widgetVar);
                     if (widget && widget.isDetached() === true) {
                         try {
@@ -1415,7 +1405,7 @@ if (!PrimeFaces.ajax) {
              * Handles a `redirect` AJAX action by performing a redirect to the target URL.
              * @param {Node} node The XML node of the `redirect` action.
              */
-            doRedirect : function(node) {
+            doRedirect: function(node) {
                 try {
                     window.location.assign(node.getAttribute('url'));
                 } catch (error) {
@@ -1432,9 +1422,9 @@ if (!PrimeFaces.ajax) {
              * @param {PrimeFaces.ajax.pfXHR} xhr The XHR request to which a response was received.
              * @param {PrimeFaces.ajax.UpdateHandler<TWidget>} [updateHandler] Optional handler for the update.
              */
-            doUpdate : function(node, xhr, updateHandler) {
+            doUpdate: function(node, xhr, updateHandler) {
                 var id = node.getAttribute('id'),
-                content = PrimeFaces.ajax.Utils.getContent(node);
+                    content = PrimeFaces.ajax.Utils.getContent(node);
 
                 if (updateHandler && updateHandler.widget && updateHandler.widget.id === id) {
                     updateHandler.handle.call(updateHandler.widget, content);
@@ -1448,7 +1438,7 @@ if (!PrimeFaces.ajax) {
              * @param {Node} node The XML node of the `eval` action.
              * @param {PrimeFaces.ajax.pfXHR} xhr The XHR request to which a response was received.
              */
-            doEval : function(node, xhr) {
+            doEval: function(node, xhr) {
                 var textContent = node.textContent || node.innerText || node.text;
 
                 var nonce;
@@ -1463,7 +1453,7 @@ if (!PrimeFaces.ajax) {
              * @param {Node} node The XML node of the `extension` action.
              * @param {PrimeFaces.ajax.pfXHR} xhr The XHR request to which a response was received.
              */
-            doExtension : function(node, xhr) {
+            doExtension: function(node, xhr) {
                 if (xhr) {
                     if (node.getAttribute("ln") === "primefaces" && node.getAttribute("type") === "args") {
                         var textContent = node.textContent || node.innerText || node.text;
@@ -1489,7 +1479,7 @@ if (!PrimeFaces.ajax) {
              * @param {Node} node The XML node of the `error` action.
              * @param {PrimeFaces.ajax.pfXHR} xhr The XHR request to which a response was received.
              */
-            doError : function(node, xhr) {
+            doError: function(node, xhr) {
                 // currently nothing...
             },
 
@@ -1497,7 +1487,7 @@ if (!PrimeFaces.ajax) {
              * Handles a `delete` AJAX action by remove the DOM element.
              * @param {Node} node The XML node of the `delete` action.
              */
-            doDelete : function(node) {
+            doDelete: function(node) {
                 var id = node.getAttribute('id');
                 $(PrimeFaces.escapeClientId(id)).remove();
             },
@@ -1508,13 +1498,12 @@ if (!PrimeFaces.ajax) {
              * @return {boolean | undefined} `false` if the AJAX action could not be performed, `true` or `undefined`
              * otherwise.
              */
-            doInsert : function(node) {
+            doInsert: function(node) {
                 if (!node.childNodes) {
                     return false;
                 }
 
-                for (var i = 0; i < node.childNodes.length; i++) {
-                    var childNode = node.childNodes[i];
+                for (const childNode of node.childNodes) {
                     var id = childNode.getAttribute('id');
                     var jq = $(PrimeFaces.escapeClientId(id));
                     var content = PrimeFaces.ajax.Utils.getContent(childNode);
@@ -1534,7 +1523,7 @@ if (!PrimeFaces.ajax) {
              * @return {boolean | undefined} `false` if the AJAX action could not be performed, `true` or `undefined`
              * otherwise.
              */
-            doAttributes : function(node) {
+            doAttributes: function(node) {
                 if (!node.childNodes) {
                     return false;
                 }
@@ -1542,8 +1531,7 @@ if (!PrimeFaces.ajax) {
                 var id = node.getAttribute('id');
                 var jq = $(PrimeFaces.escapeClientId(id));
 
-                for (var i = 0; i < node.childNodes.length; i++) {
-                    var attrNode = node.childNodes[i];
+                for (const attrNode of node.childNodes) {
                     var attrName = attrNode.getAttribute("name");
                     var attrValue = attrNode.getAttribute("value");
 
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.clientwindow.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.clientwindow.js
index 5d09284370..57a6933c71 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.clientwindow.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.clientwindow.js
@@ -106,20 +106,18 @@ if (!PrimeFaces.clientwindow) {
                     this.requestNewClientWindowId();
                 }
             }
-            else {
+            else if (sessionStorageClientWindowId === this.TEMP_CLIENT_WINDOW_ID) {
                 // we triggered the windowId recreation last request
-                if (sessionStorageClientWindowId === this.TEMP_CLIENT_WINDOW_ID) {
-                    sessionStorage.setItem(this.CLIENT_WINDOW_SESSION_STORAGE, this.clientWindowId);
-                }
+                sessionStorage.setItem(this.CLIENT_WINDOW_SESSION_STORAGE, this.clientWindowId);
+            }
+            else if (sessionStorageClientWindowId.length !== this.LENGTH_CLIENT_WINDOW_ID) {
                 // security check length
-                else if (sessionStorageClientWindowId.length !== this.LENGTH_CLIENT_WINDOW_ID) {
-                    this.requestNewClientWindowId();
-                }
+                this.requestNewClientWindowId();
+            }
+            else if (sessionStorageClientWindowId !== urlClientWindowId || sessionStorageClientWindowId !== this.clientWindowId) {
                 // session storage windowId doesn't match requested windowId
                 // -> redirect to the same view with current windowId from the window name
-                else if (sessionStorageClientWindowId !== urlClientWindowId || sessionStorageClientWindowId !== this.clientWindowId) {
-                    window.location = this.replaceUrlParam(window.location.href, this.CLIENT_WINDOW_URL_PARAM, sessionStorageClientWindowId);
-                }
+                window.location = this.replaceUrlParam(window.location.href, this.CLIENT_WINDOW_URL_PARAM, sessionStorageClientWindowId);
             }
         },
         
@@ -152,8 +150,8 @@ if (!PrimeFaces.clientwindow) {
              if (queryString && queryString.length > 0) {
                  // create an array of query parameters - substring(1) removes the ? at the beginning of the query
                  var queryParameters = queryString.substring(1).split("&");
-                 for (var i = 0; i < queryParameters.length; i++) {
-                     var queryParameter = queryParameters[i].split("=");
+                 for (const queryParameterString of queryParameters) {
+                     const queryParameter = queryParameterString.split("=");
                      if (queryParameter[0] === name) {
                          return queryParameter.length > 1 ? decodeURIComponent(queryParameter[1]) : "";
                      }
@@ -203,9 +201,7 @@ if (!PrimeFaces.clientwindow) {
             newParameters.push(parameterName + "=" + encodeURIComponent(parameterValue));
 
             // loop old parameters, remove empty ones and remove the parameter with the same name as the new one
-            for (var i = 0; i < oldParameters.length; i++) {
-                var oldParameterPair = oldParameters[i];
-
+            for (const oldParameterPair of oldParameters) {
                 if (oldParameterPair.length > 0) {
                     var oldParameterName = oldParameterPair.split('=')[0];
                     var oldParameterValue = oldParameterPair.split('=')[1];
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.csp.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.csp.js
index 93e090912a..6b2fcdec74 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.csp.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.csp.js
@@ -35,8 +35,7 @@ if (!PrimeFaces.csp) {
             PrimeFaces.csp.NONCE_VALUE = nonce;
 
             var forms = document.getElementsByTagName("form");
-            for (var i = 0; i < forms.length; i++) {
-                var form = forms[i];
+            for (const form of forms) {
                 if (!PrimeFaces.csp.isFacesForm(form)) {
                     continue;
                 }
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.dialog.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.dialog.js
index 8c872b49a3..a3c9cce07d 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.dialog.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.dialog.js
@@ -137,9 +137,9 @@ if (!PrimeFaces.dialog) {
                             pieces.unshift(classSelector);
                         } else {
                             // Without classes, we try to work with :eq and the tag name
-                            var elems = $(e.parentNode).find(e.tagName);
-                            if (elems.length > 1) {
-                                pieces.unshift(":eq(" + elems.index(e) + ")");
+                            var tagElems = $(e.parentNode).find(e.tagName);
+                            if (tagElems.length > 1) {
+                                pieces.unshift(":eq(" + tagElems.index(e) + ")");
                             }
                             pieces.unshift(e.tagName);
                         }
@@ -340,17 +340,16 @@ if (!PrimeFaces.dialog) {
             dlg.attr('data-queuedforremoval', true);
 
             if(parentDlg) {
-                var parentDlgFrame = parentDlg.find('> .ui-dialog-content > iframe').get(0),
+                var parentDlgFrame = parentDlg.find('> .ui-dialog-content > iframe').get(0);
                 windowContext = parentDlgFrame.contentWindow||parentDlgFrame;
-                sourceWidget = windowContext.PF(sourceWidgetVar);
             }
             else {
                 // We have to resolve the frames from the root window to the source widget to invoke the dialog return behavior
                 // Each source frame element is a selector. We step into every nested frame until we are in the source widget frame.
                 windowContext = rootWindow;
                 var frames = dlgWidget.cfg.sourceFrames;
-                for (var i = 0; i < frames.length; i++) {
-                    windowContext = $(windowContext.document).find(frames[i]).get(0).contentWindow;
+                for (const frame of frames) {
+                    windowContext = $(windowContext.document).find(frame).get(0).contentWindow;
                 }
             }
 
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.expressions.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.expressions.js
index c7919cef90..cf6592e477 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.expressions.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.expressions.js
@@ -36,8 +36,8 @@ if (!PrimeFaces.expressions) {
             var elements = $();
 
             if (splittedExpressions) {
-                for (var i = 0; i < splittedExpressions.length; ++i) {
-                    var expression =  PrimeFaces.trim(splittedExpressions[i]);
+                for (const splittedExpression of splittedExpressions) {
+                    var expression = PrimeFaces.trim(splittedExpression);
                     if (expression.length > 0) {
 
                         // skip unresolvable keywords
@@ -97,8 +97,8 @@ if (!PrimeFaces.expressions) {
             ids = [];
 
             if (splittedExpressions) {
-                for (var i = 0; i < splittedExpressions.length; ++i) {
-                    var expression =  PrimeFaces.trim(splittedExpressions[i]);
+                for (const splittedExpression of splittedExpressions) {
+                    var expression = PrimeFaces.trim(splittedExpression);
                     if (expression.length > 0) {
 
                         // just a id or passtrough keywords
@@ -126,9 +126,9 @@ if (!PrimeFaces.expressions) {
                             //converts pfs to jq selector e.g. @(div.mystyle :input) to div.mystyle :input
                             var elements = $(expression.substring(2, expression.length - 1));
 
-                            for (var j = 0; j < elements.length; j++) {
-                                var element = $(elements[j]),
-                                clientId = element.data(PrimeFaces.CLIENT_ID_DATA) || element.attr('id');
+                            for (const element of elements) {
+                                var $element = $(element);
+                                var clientId = $element.data(PrimeFaces.CLIENT_ID_DATA) || $element.attr('id');
 
                                 if (clientId && !PrimeFaces.inArray(ids, clientId)) {
                                     ids.push(clientId);
@@ -141,9 +141,9 @@ if (!PrimeFaces.expressions) {
                                 PrimeFaces.error("Could not resolve @form for source '" + source.attr('id') + "'");
                             }
                             else {
-                                var clientId = form.data(PrimeFaces.CLIENT_ID_DATA) || form.attr('id');
-                                if (!PrimeFaces.inArray(ids, clientId)) {
-                                    ids.push(clientId);
+                                var formClientId = form.data(PrimeFaces.CLIENT_ID_DATA) || form.attr('id');
+                                if (!PrimeFaces.inArray(ids, formClientId)) {
+                                    ids.push(formClientId);
                                 }
                             }
                         }
@@ -175,9 +175,7 @@ if (!PrimeFaces.expressions) {
             var parenthesesCounter = 0;
 
             if (!expression) {return expressions;}
-
-            for (var i = 0; i < expression.length; i++) {
-                var c = expression[i];
+            for (const c of expression) {
 
                 if (c === '(') {
                     parenthesesCounter++;
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.js
index e17c1f519a..398baeab0f 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.js
@@ -646,7 +646,7 @@
          * @return {string} The given value, escaped to be used as a text-literal within an HTML document.
          */
         escapeHTML: function(value, preventDoubleEscaping) {
-            var regex = preventDoubleEscaping ? /[<>"'`=\/]/g : /[&<>"'`=\/]/g;
+            var regex = preventDoubleEscaping ? /[<>"'`=/]/g : /[&<>"'`=/]/g;
             return String(value).replace(regex, function (s) {
                 return PrimeFaces.entityMap[s];
             });
@@ -774,13 +774,7 @@
          * @return {boolean} `true` if the given item is in the given array, `false` otherwise.
          */
         inArray: function(arr, item) {
-            for(var i = 0; i < arr.length; i++) {
-                if(arr[i] === item) {
-                    return true;
-                }
-            }
-
-            return false;
+            return arr.includes(item);
         },
 
         /**
@@ -1013,8 +1007,8 @@
          */
         bcn: function(element, event, functions) {
             if(functions) {
-                for(var i = 0; i < functions.length; i++) {
-                    var retVal = functions[i].call(element, event);
+                for(const fn of functions) {
+                    var retVal = fn.call(element, event);
                     if(retVal === false) {
                         if(event.preventDefault) {
                             event.preventDefault();
@@ -1039,10 +1033,9 @@
          * A list of callback functions. If any returns `false`, the other callbacks are not invoked.
          */
         bcnu: function(ext, event, fns) {
-            if(fns) {
-                for(var i = 0; i < fns.length; i++) {
-                    var retVal = fns[i].call(this, ext, event);
-                    if(retVal === false) {
+            if (fns) {
+                for (const fn of fns) {
+                    if (fn.call(this, ext, event) === false) {
                         break;
                     }
                 }
@@ -1170,8 +1163,7 @@
          */
         invokeDeferredRenders: function(containerId) {
             var widgetsToRemove = [];
-            for(var i = 0; i < this.deferredRenders.length; i++) {
-                var deferredRender = this.deferredRenders[i];
+            for (const deferredRender of this.deferredRenders) {
 
                 if(deferredRender.container === containerId) {
                     var rendered = deferredRender.callback.call();
@@ -1181,8 +1173,8 @@
                 }
             }
 
-            for(var j = 0; j < widgetsToRemove.length; j++) {
-                this.removeDeferredRenders(widgetsToRemove[j]);
+            for (const widget of widgetsToRemove) {
+                this.removeDeferredRenders(widget);
             }
         },
         
@@ -1209,10 +1201,10 @@
 
             // try and strip specific language from nl_BE to just nl
             if (!locale) {
-                var localeKey = cfgLocale ? cfgLocale : PrimeFaces.settings.locale;
-                var strippedLocaleKey = localeKey ? localeKey.split('_')[0] : null;
-                if (strippedLocaleKey) {
-                    locale = PrimeFaces.locales[strippedLocaleKey];
+                var fullLocaleKey = cfgLocale || PrimeFaces.settings.locale;
+                var splitLocaleKey = fullLocaleKey ? fullLocaleKey.split('_')[0] : null;
+                if (splitLocaleKey) {
+                    locale = PrimeFaces.locales[splitLocaleKey];
                 }
             }
 
@@ -1273,11 +1265,10 @@
                     if (typeof locale[key] === 'object') {
                         // If the value is an object, call the function recursively
                         iterateLocale(locale[key], lkey, lvalue);
-                    } else {
-                        // Otherwise, set the new value if found
-                        if (key === lkey) {
-                            locale[key] = lvalue;
-                        }
+                    } 
+                    // Otherwise, set the new value if found
+                    else if (key === lkey) {
+                        locale[key] = lvalue;
                     }
                 }
             }
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js
index 459b38ecfe..c1786d5db1 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js
@@ -32,7 +32,7 @@ if (!PrimeFaces.resources) {
              scriptURI = scriptURI.replace(scriptName, name);
 
              // find the library like ln=primefaces
-             var libraryRegex = new RegExp('[?&]([^&=]*)ln=(.*?)(&|$)');
+             var libraryRegex = /[?&]([^&=]*)ln=(.*?)(&|$)/;
 
              // find library to replace e.g. 'ln=primefaces'
              var currentLibraryName = 'ln=' + libraryRegex.exec(scriptURI)[2];
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js
index e44afad51f..8cab6201e4 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js
@@ -197,17 +197,15 @@ if (!PrimeFaces.utils) {
                             }
                         }
 
-                        if(target.is(document.body)) {
-                            first.focus(1);
-                            event.preventDefault();
-                        }
-                        else if(event.target === last[0] && !event.shiftKey) {
-                            first.focus(1);
-                            event.preventDefault();
-                        }
-                        else if (event.target === first[0] && event.shiftKey) {
-                            last.focus(1);
+                        const focusElement = (element) => {
+                            element.focus(1);
                             event.preventDefault();
+                        };
+
+                        if (target.is(document.body) || (event.target === last[0] && !event.shiftKey)) {
+                            focusElement(first);
+                        } else if (event.target === first[0] && event.shiftKey) {
+                            focusElement(last);
                         }
                     }
                 }
@@ -451,22 +449,24 @@ if (!PrimeFaces.utils) {
         registerConnectedOverlayScrollHandler: function(widget, scrollNamespace, element, scrollCallback) {
             var scrollableParents = PrimeFaces.utils.getScrollableParents((element || widget.getJQ()).get(0));
 
-            for (var i = 0; i < scrollableParents.length; i++) {
-                var scrollParent = $(scrollableParents[i]);
+            const scrollHandler = function(e) {
+                scrollCallback(e);
+            };
 
-                widget.addDestroyListener(function() {
-                    scrollParent.off(scrollNamespace);
-                });
+            for (const scrollParent of scrollableParents) {
+                var $scrollParent = $(scrollParent);
 
-                scrollParent.off(scrollNamespace).on(scrollNamespace, function(e) {
-                    scrollCallback(e);
+                widget.addDestroyListener(() => {
+                    $scrollParent.off(scrollNamespace, scrollHandler);
                 });
+
+                $scrollParent.off(scrollNamespace, scrollHandler).on(scrollNamespace, scrollHandler);
             }
 
             return {
                 unbind: function() {
-                    for (var i = 0; i < scrollableParents.length; i++) {
-                        $(scrollableParents[i]).off(scrollNamespace);
+                    for (const scrollParent of scrollableParents) {
+                        $(scrollParent).off(scrollNamespace, scrollHandler);
                     }
                 }
             };
@@ -499,13 +499,11 @@ if (!PrimeFaces.utils) {
                     return overflowRegex.test(styleDeclaration.getPropertyValue('overflow')) || overflowRegex.test(styleDeclaration.getPropertyValue('overflowX')) || overflowRegex.test(styleDeclaration.getPropertyValue('overflowY'));
                 };
 
-                for (var i = 0; i < parents.length; i++) {
-                    var parent = parents[i];
+                for (const parent of parents) {
                     var scrollSelectors = parent.nodeType === 1 && parent.dataset['scrollselectors'];
                     if (scrollSelectors) {
                         var selectors = scrollSelectors.split(',');
-                        for (var j = 0; j < selectors.length; j++) {
-                            var selector = selectors[j];
+                        for (const selector of selectors) {
                             var el = parent.querySelector(selector);
                             if (el && overflowCheck(el)) {
                                 addScrollableParent(el);
@@ -932,8 +930,7 @@ if (!PrimeFaces.utils) {
             if (args) {
                 var classes = [];
 
-                for (var i = 0; i < args.length; i++) {
-                    var className = args[i];
+                for (const className of args) {
 
                     if (!className) continue;
 
@@ -943,7 +940,7 @@ if (!PrimeFaces.utils) {
                         classes.push(className);
                     }
                     else if (type === 'object') {
-                        var _classes = Array.isArray(className) ? className : Object.keys(className).map(function(key) { return !!className[key] ? key : null });
+                        var _classes = Array.isArray(className) ? className : Object.keys(className).map(function(key) { return className[key] ? key : null });
 
                         classes = _classes.length ? classes.concat(_classes.filter(function(c) { return !!c })) : classes;
                     }
@@ -996,6 +993,7 @@ if (!PrimeFaces.utils) {
             }
 
             var isEmpty = true;
+            var value = null;
             inputs.each(function() {
                 var input = $(this);
                 if (input.is('select')) {
@@ -1003,12 +1001,12 @@ if (!PrimeFaces.utils) {
                         isEmpty = input.find('option:selected').length === 0;
                     }
                     else {
-                        var value = input.find('option:selected').attr('value');
+                        value = input.find('option:selected').attr('value');
                         isEmpty = value === null || value === '';
                     }
                 }
                 else {
-                    var value = input.val();
+                    value = input.val();
                     isEmpty = value === null || value === '';
                 }
 
@@ -1135,8 +1133,8 @@ if (!PrimeFaces.utils) {
             }
             // Remove inline event attributes
             var attributes = jq[0].attributes;
-            for (var i = 0; i < attributes.length; i++) {
-                var attributeName = attributes[i].name;
+            for (const attribute of attributes) {
+                const attributeName = attribute.name;
                 if (attributeName.startsWith("on")) {
                     jq.removeAttr(attributeName);
                 }
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.widget.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.widget.js
index c7cee1d762..51d563a6c7 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.widget.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.widget.js
@@ -364,8 +364,7 @@ if (!PrimeFaces.widget) {
             this.destroyListeners = [];
 
             if (this.refreshListeners) {
-                for (var i = 0; i < this.refreshListeners.length; i++) {
-                    var refreshListener = this.refreshListeners[i];
+                for (const refreshListener of this.refreshListeners) {
                     refreshListener.call(this, this);
                 }
             }
@@ -396,8 +395,7 @@ if (!PrimeFaces.widget) {
             PrimeFaces.debug("Destroyed detached widget: " + this.widgetVar);
 
             if (this.destroyListeners) {
-                for (var i = 0; i < this.destroyListeners.length; i++) {
-                    var destroyListener = this.destroyListeners[i];
+                for (const destroyListener of this.destroyListeners) {
                     destroyListener.call(this, this);
                 }
             }
@@ -425,12 +423,7 @@ if (!PrimeFaces.widget) {
          * @return {boolean} `true` if this widget is currently detached, or `false` otherwise.
          */
         isDetached: function() {
-            var element = document.getElementById(this.id);
-            if (typeof(element) !== 'undefined' && element !== null) {
-                return false;
-            }
-
-            return true;
+            return document.getElementById(this.id) === null;
         },
 
         /**
@@ -505,6 +498,10 @@ if (!PrimeFaces.widget) {
             if(this.hasBehavior(event)) {
                 this.cfg.behaviors[event].call(this, ext);
             }
+            else if (this.cfg.behaviors === undefined && this.jq.length > 0) {
+                // #12887 if no behavior is defined, try to call the DOM event
+                this.jq.trigger(event, ext);
+            }
         },
 
         /**
@@ -849,7 +846,7 @@ if (!PrimeFaces.widget) {
          * @protected
          */
         _render: function() {
-            throw 'Unsupported Operation';
+            throw new Error("Unsupported Operation");
         },
 
         /**
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/datatable/datatable.css b/primefaces/src/main/resources/META-INF/resources/primefaces/datatable/datatable.css
index 5e8a8ee067..5fc262e397 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/datatable/datatable.css
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/datatable/datatable.css
@@ -1,6 +1,7 @@
 .ui-datatable table {
     width: 100%;
     table-layout: fixed;
+    border-collapse: collapse;
 }
 
 .ui-datatable-tablewrapper {
@@ -130,7 +131,7 @@
 }
 
 .ui-datatable-scrollable-theadclone th.ui-state-default {
-    height:0px;
+    height:0px !important; /* #12908 */
     border-bottom-width: 0px;
     border-top-width: 0px;
     padding-top: 0px;
@@ -160,9 +161,8 @@
 /** Accessibility **/
 .ui-datatable-data td[role="gridcell"]:focus,
 .ui-datatable-data td[role="grid"] [tabindex="0"]:focus {
-  outline: var(--primary-color, #90caf9);
-  outline-style: solid;
-  outline-width: 2px;
+  outline: 2px solid var(--primary-color, #90caf9);
+  outline-offset: -2px;
   border: none;
 }
 
@@ -388,4 +388,4 @@
         display: block;
         border: 0 none;
     }
-}
\ No newline at end of file
+}
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/locales/locale-bs.js b/primefaces/src/main/resources/META-INF/resources/primefaces/locales/locale-bs.js
new file mode 100644
index 0000000000..a05ce3b92c
--- /dev/null
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/locales/locale-bs.js
@@ -0,0 +1,258 @@
+if (window.PrimeFaces) {
+  /** Bosnian (from PrimeLocale)*/
+  PrimeFaces.locales["bs"] = {
+    accept: "Da",
+    addRule: "Dodaj pravilo",
+    am: "AM",
+    apply: "Potvrdi",
+    cancel: "Odustani",
+    choose: "Odaberi",
+    chooseDate: "Odaberi datum",
+    chooseMonth: "Odaberi mjesec",
+    chooseYear: "Odaberi godinu",
+    clear: "Poništi",
+    completed: "Zabršen",
+    contains: "Sadrzi",
+    custom: "Prilagođen",
+    dateAfter: "Datum je poslije",
+    dateBefore: "Datum je prije",
+    dateFormat: "dd.mm.yy",
+    dateIs: "Datum je",
+    dateIsNot: "Datum nije",
+    dayNames: ["Nedjelja", "Ponedljak", "Utorak", "Srijeda", "četvrtak", "Petak", "Subota"],
+    dayNamesMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su"],
+    dayNamesShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+    emptyFilterMessage: "Nema pronađenih rezultata",
+    emptyMessage: "Nema dostupnih opcija",
+    emptySearchMessage: "Nema pronađenih rezultata",
+    emptySelectionMessage: "Element nije selektovan",
+    endsWith: "Završava sa",
+    equals: "Jednako",
+    fileSizeTypes: ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
+    filter: "Filter",
+    firstDayOfWeek: 0,
+    gt: "Veći nego",
+    gte: "Veći nego ili jednak",
+    lt: "Manji nego",
+    lte: "Manji nego ili jednak",
+    matchAll: "Podudara sa svim",
+    matchAny: "Podudara sa nekim",
+    medium: "Medium",
+    monthNames: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "August", "Septembar", "Oktobar", "Novembar", "Decembar"],
+    monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
+    nextDecade: "Sljedeća decenija",
+    nextHour: "Sljedeći sat",
+    nextMinute: "Sljedeća minuta",
+    nextMonth: "Sljedeći mjesec",
+    nextSecond: "Sljedeća sekunda",
+    nextYear: "Sljedeća godina",
+    noFilter: "Bez filtera",
+    notContains: "Ne sadrži",
+    notEquals: "Nije jednako",
+    now: "Sada",
+    passwordPrompt: "Unesite šifru",
+    pending: "Na čekanju",
+    pm: "PM",
+    prevDecade: "Prethodna decenija",
+    prevHour: "Prošli sat",
+    prevMinute: "Prošla minuta",
+    prevMonth: "Prošli mjesec",
+    prevSecond: "Prošla sekunda",
+    prevYear: "Prošla godina",
+    reject: "Odbaci",
+    removeRule: "Ukloni pravilo",
+    searchMessage: "{0} rezultata pretrage",
+    selectionMessage: "Broj selektovanih {0}",
+    showMonthAfterYear: false,
+    startsWith: "Počinje sa",
+    strong: "Jak",
+    today: "Danas",
+    upload: "Učitaj",
+    weak: "Slab",
+    weekHeader: "Sd",
+    aria: {
+      cancelEdit: "Otkaži uređivanje",
+      close: "Zatvori",
+      collapseLabel: "Smanji",
+      collapseRow: "Red smanjen",
+      editRow: "Uredi red",
+      expandLabel: "Proširi",
+      expandRow: "Red proširen",
+      falseLabel: "Netačno",
+      filterConstraint: "Ograničenje filtera",
+      filterOperator: "Operator filtera",
+      firstPageLabel: "Prva stranica",
+      gridView: "Grid pregled",
+      hideFilterMenu: "Sakrij meni filtera",
+      jumpToPageDropdownLabel: "Navigiraj na stranicu Dropdown",
+      jumpToPageInputLabel: "Navigiraj na stranicu Input",
+      lastPageLabel: "Zadnja stranica",
+      listView: "List pregled",
+      moveAllToSource: "Pomjeri sve na izvor",
+      moveAllToTarget: "Pomjeri sve na cilj",
+      moveBottom: "Pomjeri na dno",
+      moveDown: "Pomjeri dole",
+      moveToSource: "Pomjeri na izvor",
+      moveToTarget: "Pomjeri na cilj",
+      moveTop: "Pomjeri na vrh",
+      moveUp: "Pomjeri gore",
+      navigation: "Navigacija",
+      next: "Sljedeći",
+      nextPageLabel: "Sljedeća stranica",
+      nullLabel: "Ništa nije odabrano",
+      otpLabel: "Unesite karakter jednokratne šifre {0}",
+      pageLabel: "Stranica {page}",
+      passwordHide: "Sakrij šifru",
+      passwordShow: "Prikaži šifru",
+      previous: "Prethodni",
+      previousPageLabel: "Prethodna stranica",
+      removeLabel: "Ukloni",
+      rotateLeft: "Rotiraj ulijevo",
+      rotateRight: "Rotiraj udesno",
+      rowsPerPageLabel: "Redova po stranici",
+      saveEdit: "Sačuvaj uređivanje",
+      scrollTop: "Navigiraj na vrh",
+      selectAll: "Svi elementi odabrani",
+      selectLabel: "Odaber",
+      selectRow: "Red odabran",
+      showFilterMenu: "Prikaži filter meni",
+      slide: "Povuci",
+      slideNumber: "{slideNumber}",
+      star: "1 zvijezdica",
+      stars: "{star} zvijezdica",
+      trueLabel: "Tačno",
+      unselectAll: "Nijedan element nije odabran",
+      unselectLabel: "Poništi odabir",
+      unselectRow: "Red nije odabran",
+      zoomImage: "Približi sliku",
+      zoomIn: "Približi",
+      zoomOut: "Udalji"
+    }
+  };
+
+  // custom PF labels
+  PrimeFaces.locales["bs"] = $.extend(true, {}, PrimeFaces.locales["bs"], {
+    weekNumberTitle: "W",
+    isRTL: false,
+    yearSuffix: "",
+    timeOnlyTitle: "Samo vrijeme",
+    timeText: "Vrijeme",
+    hourText: "Sat",
+    minuteText: "Minuta",
+    secondText: "Sekunda",
+    millisecondText: "Milisekunda",
+    year: "Godina",
+    month: "Mjesec",
+    week: "Sedmica",
+    day: "Dan",
+    list: "Agenda",
+    allDayText: "Cijeli dan",
+    moreLinkText: "Više...",
+    noEventsText: "Nema događaja",
+    unexpectedError: "Neočekivana greška",
+    aria: {
+      "datatable.sort.ASC": "aktiviraj za sortiranje kolone uzlazno",
+      "datatable.sort.DESC": "aktiviraj za sortiranje kolone silazno",
+      "datatable.sort.NONE": "aktiviraj za uklanjanje sortiranja kolone",
+      "colorpicker.OPEN": "Otvori birač boja",
+      "colorpicker.CLOSE": "Zatvori birač boja",
+      "colorpicker.CLEAR": "Očisti odabranu boju",
+      "colorpicker.MARKER": "Zasićenje: {s}. Svjetlina: {v}.",
+      "colorpicker.HUESLIDER": "Klizač nijanse",
+      "colorpicker.ALPHASLIDER": "Klizač providnosti",
+      "colorpicker.INPUT": "Polje vrijednosti boje",
+      "colorpicker.FORMAT": "Format boje",
+      "colorpicker.SWATCH": "Uzorak boje",
+      "colorpicker.INSTRUCTION": "Selektor zasićenja i svjetline. Koristite strelice gore, dolje, lijevo i desno za odabir.",
+      "spinner.INCREASE": "Povećaj vrijednost",
+      "spinner.DECREASE": "Smanji vrijednost",
+      "switch.ON": "Uključeno",
+      "switch.OFF": "Isključeno",
+      "messages.ERROR": "Greška",
+      "messages.FATAL": "Fatalna greška",
+      "messages.INFO": "Informacija",
+      "messages.WARN": "Upozorenje",
+    },
+    messages: {
+      "javax.faces.component.UIInput.REQUIRED": "{0}: Greška validacije: Vrijednost je obavezna.",
+      "javax.faces.converter.IntegerConverter.INTEGER": "{2}: '{0}' mora biti broj koji se sastoji od jedne ili više cifara.",
+      "javax.faces.converter.IntegerConverter.INTEGER_detail": "{2}: '{0}' mora biti broj između -2147483648 i 2147483647. Primjer: {1}.",
+      "javax.faces.converter.DoubleConverter.DOUBLE": "{2}: '{0}' mora biti broj koji se sastoji od jedne ili više cifara.",
+      "javax.faces.converter.DoubleConverter.DOUBLE_detail": "{2}: '{0}' mora biti broj između 4.9E-324 i 1.7976931348623157E308. Primjer: {1}.",
+      "javax.faces.converter.BigDecimalConverter.DECIMAL": "{2}: '{0}' mora biti decimalni broj sa predznakom.",
+      "javax.faces.converter.BigDecimalConverter.DECIMAL_detail": "{2}: '{0}' mora biti decimalni broj sa predznakom koji se sastoji od nula ili više cifara, nakon čega može slijediti decimalna tačka i razlomak. Primjer: {1}.",
+      "javax.faces.converter.BigIntegerConverter.BIGINTEGER": "{2}: '{0}' mora biti broj koji se sastoji od jedne ili više cifara.",
+      "javax.faces.converter.BigIntegerConverter.BIGINTEGER_detail": "{2}: '{0}' mora biti broj koji se sastoji od jedne ili više cifara. Primjer: {1}.",
+      "javax.faces.converter.ByteConverter.BYTE": "{2}: '{0}' mora biti broj između 0 i 255.",
+      "javax.faces.converter.ByteConverter.BYTE_detail": "{2}: '{0}' mora biti broj između 0 i 255. Primjer: {1}.",
+      "javax.faces.converter.CharacterConverter.CHARACTER": "{1}: '{0}' mora biti validan znak.",
+      "javax.faces.converter.CharacterConverter.CHARACTER_detail": "{1}: '{0}' mora biti validan ASCII znak.",
+      "javax.faces.converter.ShortConverter.SHORT": "{2}: '{0}' mora biti broj koji se sastoji od jedne ili više cifara.",
+      "javax.faces.converter.ShortConverter.SHORT_detail": "{2}: '{0}' mora biti broj između -32768 i 32767. Primjer: {1}.",
+      "javax.faces.converter.BooleanConverter.BOOLEAN": "{1}: '{0}' mora biti 'tačno' ili 'netačno'.",
+      "javax.faces.converter.BooleanConverter.BOOLEAN_detail": "{1}: '{0}' mora biti 'tačno' ili 'netačno'. Svaka vrijednost osim 'tačno' će biti evaluirana kao 'netačno'.",
+      "javax.faces.validator.LongRangeValidator.MAXIMUM": "{1}: Greška validacije: Vrijednost je veća od dozvoljenog maksimuma '{0}'.",
+      "javax.faces.validator.LongRangeValidator.MINIMUM": "{1}: Greška validacije: Vrijednost je manja od dozvoljenog minimuma '{0}'.",
+      "javax.faces.validator.LongRangeValidator.NOT_IN_RANGE": "{2}: Greška validacije: Navedeni atribut nije između očekivanih vrijednosti {0} i {1}.",
+      "javax.faces.validator.LongRangeValidator.TYPE": "{0}: Greška validacije: Vrijednost nije odgovarajućeg tipa.",
+      "javax.faces.validator.DoubleRangeValidator.MAXIMUM": "{1}: Greška validacije: Vrijednost je veća od dozvoljenog maksimuma '{0}'.",
+      "javax.faces.validator.DoubleRangeValidator.MINIMUM": "{1}: Greška validacije: Vrijednost je manja od dozvoljenog minimuma '{0}'.",
+      "javax.faces.validator.DoubleRangeValidator.NOT_IN_RANGE": "{2}: Greška validacije: Navedeni atribut nije između očekivanih vrijednosti {0} i {1}.",
+      "javax.faces.validator.DoubleRangeValidator.TYPE": "{0}: Greška validacije: Vrijednost nije odgovarajućeg tipa.",
+      "javax.faces.converter.FloatConverter.FLOAT": "{2}: '{0}' mora biti broj koji se sastoji od jedne ili više cifara.",
+      "javax.faces.converter.FloatConverter.FLOAT_detail": "{2}: '{0}' mora biti broj između 1.4E-45 i 3.4028235E38 Primjer: {1}.",
+      "javax.faces.converter.DateTimeConverter.DATE": "{2}: '{0}' nije prepoznat kao datum.",
+      "javax.faces.converter.DateTimeConverter.DATE_detail": "{2}: '{0}' nije prepoznat kao datum. Primjer: {1}.",
+      "javax.faces.converter.DateTimeConverter.TIME": "{2}: '{0}' nije prepoznat kao vrijeme.",
+      "javax.faces.converter.DateTimeConverter.TIME_detail": "{2}: '{0}' nije prepoznat kao vrijeme. Primjer: {1}.",
+      "javax.faces.converter.DateTimeConverter.DATETIME": "{2}: '{0}' nije prepoznat kao datum i vrijeme.",
+      "javax.faces.converter.DateTimeConverter.DATETIME_detail": "{2}: '{0}' nije prepoznat kao datum i vrijeme. Primjer: {1}.",
+      "javax.faces.converter.DateTimeConverter.PATTERN_TYPE": "{1}: 'pattern' ili 'type' atribut mora biti naveden za konverziju vrijednosti '{0}'.",
+      "javax.faces.converter.NumberConverter.CURRENCY": "{2}: '{0}' nije prepoznat kao valutna vrijednost.",
+      "javax.faces.converter.NumberConverter.CURRENCY_detail": "{2}: '{0}' nije prepoznat kao valutna vrijednost. Primjer: {1}.",
+      "javax.faces.converter.NumberConverter.PERCENT": "{2}: '{0}' nije prepoznat kao procenat.",
+      "javax.faces.converter.NumberConverter.PERCENT_detail": "{2}: '{0}' nije prepoznat kao procenat. Primjer: {1}.",
+      "javax.faces.converter.NumberConverter.NUMBER": "{2}: '{0}' nije prepoznat kao broj.",
+      "javax.faces.converter.NumberConverter.NUMBER_detail": "{2}: '{0}' nije prepoznat kao broj. Primjer: {1}.",
+      "javax.faces.converter.NumberConverter.PATTERN": "{2}: '{0}' nije prepoznat kao brojčani obrazac.",
+      "javax.faces.converter.NumberConverter.PATTERN_detail": "{2}: '{0}' nije prepoznat kao brojčani obrazac. Primjer: {1}.",
+      "javax.faces.validator.LengthValidator.MINIMUM": "{1}: Greška validacije: Dužina je manja od dozvoljenog minimuma '{0}'.",
+      "javax.faces.validator.LengthValidator.MAXIMUM": "{1}: Greška validacije: Dužina je veća od dozvoljenog maksimuma '{0}'.",
+      "javax.faces.validator.RegexValidator.PATTERN_NOT_SET": "Regex obrazac mora biti postavljen.",
+      "javax.faces.validator.RegexValidator.PATTERN_NOT_SET_detail": "Regex obrazac mora biti postavljen na nepraznu vrijednost.",
+      "javax.faces.validator.RegexValidator.NOT_MATCHED": "Regex obrazac se ne podudara.",
+      "javax.faces.validator.RegexValidator.NOT_MATCHED_detail": "Regex obrazac '{0}' se ne podudara.",
+      "javax.faces.validator.RegexValidator.MATCH_EXCEPTION": "Greška u regularnom izrazu.",
+      "javax.faces.validator.RegexValidator.MATCH_EXCEPTION_detail": "Greška u regularnom izrazu, '{0}'.",
+      "primefaces.FileValidator.FILE_LIMIT": "Prekoračen maksimalan broj datoteka.",
+      "primefaces.FileValidator.FILE_LIMIT_detail": "Maksimalan broj: {0}.",
+      "primefaces.FileValidator.ALLOW_TYPES": "Nevažeći tip datoteke.",
+      "primefaces.FileValidator.ALLOW_TYPES_detail": "Nevažeći tip datoteke: '{0}'. Dozvoljeni tipovi: '{1}'.",
+      "primefaces.FileValidator.SIZE_LIMIT": "Nevažeća veličina datoteke.",
+      "primefaces.FileValidator.SIZE_LIMIT_detail": "Datoteka '{0}' ne smije biti veća od {1}.",
+      "javax.faces.validator.BeanValidator.MESSAGE": "{0}",
+      "javax.validation.constraints.AssertFalse.message": "mora biti netačno.",
+      "javax.validation.constraints.AssertTrue.message": "mora biti tačno.",
+      "javax.validation.constraints.DecimalMax.message": "mora biti manje ili jednako {0}.",
+      "javax.validation.constraints.DecimalMin.message": "mora biti veće ili jednako {0}.",
+      "javax.validation.constraints.Digits.message": "numerička vrijednost izvan granica (očekivano: &lt;{0} cifara&gt;.&lt;{1} cifara&gt;).",
+      "javax.validation.constraints.Email.message": "mora biti ispravno formatirana email adresa.",
+      "javax.validation.constraints.Future.message": "mora biti datum u budućnosti.",
+      "javax.validation.constraints.FutureOrPresent.message": "mora biti datum u sadašnjosti ili budućnosti.",
+      "javax.validation.constraints.Max.message": "mora biti manje ili jednako {0}.",
+      "javax.validation.constraints.Min.message": "mora biti veće ili jednako {0}.",
+      "javax.validation.constraints.Negative.message": "mora biti manje od 0.",
+      "javax.validation.constraints.NegativeOrZero.message": "mora biti manje ili jednako 0.",
+      "javax.validation.constraints.NotBlank.message": "ne smije biti prazno.",
+      "javax.validation.constraints.NotEmpty.message": "ne smije biti prazno.",
+      "javax.validation.constraints.NotNull.message": "ne smije biti null.",
+      "javax.validation.constraints.Null.message": "mora biti null.",
+      "javax.validation.constraints.Past.message": "mora biti datum u prošlosti.",
+      "javax.validation.constraints.PastOrPresent.message": "mora biti datum u prošlosti ili sadašnjosti.",
+      "javax.validation.constraints.Pattern.message": "mora se podudarati sa '{0}'.",
+      "javax.validation.constraints.Positive.message": "mora biti veće od 0.",
+      "javax.validation.constraints.PositiveOrZero.message": "mora biti veće ili jednako 0.",
+      "javax.validation.constraints.Size.message": "veličina mora biti između {0} i {1}.",
+    },
+  });
+}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages.properties b/primefaces/src/main/resources/org/primefaces/Messages.properties
index 05289a27f5..cf0de3140a 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages.properties
@@ -17,9 +17,13 @@ primefaces.slider.OUT_OF_RANGE = {0}: Validation Error: Value is out of range.
 primefaces.tree.REQUIRED = {0}: Validation Error.
 primefaces.tree.REQUIRED_detail = Selection is required.
 
-primefaces.FileValidator.FILE_LIMIT = Maximum number of files exceeded.
-primefaces.FileValidator.FILE_LIMIT_detail = Maximum number: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Invalid file type.
 primefaces.FileValidator.ALLOW_TYPES_detail = Invalid file type: ''{0}''. Allowed types: ''{1}''.
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Invalid filename: {0} contains invalid character: {1}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Invalid Linux filename: {0}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Invalid Windows filename: {0}
+primefaces.FileValidator.FILENAME_EMPTY=Filename cannot be empty or null
+primefaces.FileValidator.FILE_LIMIT = Maximum number of files exceeded.
+primefaces.FileValidator.FILE_LIMIT_detail = Maximum number: {0}.
 primefaces.FileValidator.SIZE_LIMIT = Invalid file size.
 primefaces.FileValidator.SIZE_LIMIT_detail = File ''{0}'' must not be larger than {1}.
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_cs.properties b/primefaces/src/main/resources/org/primefaces/Messages_cs.properties
index 42e527323f..93f3aee387 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_cs.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_cs.properties
@@ -16,9 +16,13 @@ primefaces.password.INVALID_MATCH_detail = {0} musí odpovidat {1}.
 primefaces.slider.OUT_OF_RANGE = {0}: Chyba při validaci: Hodnota je mimo rozsah.
 primefaces.tree.REQUIRED = {0}: Chyba při validaci.
 primefaces.tree.REQUIRED_detail = Výběr je povinný.
-primefaces.FileValidator.FILE_LIMIT = Byl překročen maximální počet souborů.
-primefaces.FileValidator.FILE_LIMIT_detail = Maximální počet: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Neplatný typ souboru.
 primefaces.FileValidator.ALLOW_TYPES_detail = Neplatný typ souboru: ''{0}''. Povolené typy: ''{1}''.
+primefaces.FileValidator.FILENAME_EMPTY=Název souboru nesmí být prázdný nebo nulový
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Neplatný název souboru: {0} obsahuje neplatný znak: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nesprávný název souboru systému Windows: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nesprávný název souboru v systému Linux: {0}
+primefaces.FileValidator.FILE_LIMIT = Byl překročen maximální počet souborů.
+primefaces.FileValidator.FILE_LIMIT_detail = Maximální počet: {0}.
 primefaces.FileValidator.SIZE_LIMIT = Neplatná velikost souboru.
 primefaces.FileValidator.SIZE_LIMIT_detail = Soubor ''{0}'' nesmí být větší než {1}.
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_de.properties b/primefaces/src/main/resources/org/primefaces/Messages_de.properties
index d7ef3222f4..6f7ef152fa 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_de.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_de.properties
@@ -17,9 +17,14 @@ primefaces.slider.OUT_OF_RANGE = {0}: Validierungsfehler: Wert liegt außerhalb
 primefaces.tree.REQUIRED = {0}: Überprüfungsfehler.
 primefaces.tree.REQUIRED_detail = Auswahl ist zwingend erforderlich.
 
-primefaces.FileValidator.FILE_LIMIT = Maximale Anzahl an Dateien überschritten.
-primefaces.FileValidator.FILE_LIMIT_detail = Maximale Anzahl: {0}.
+
 primefaces.FileValidator.ALLOW_TYPES = Invalider Dateityp.
 primefaces.FileValidator.ALLOW_TYPES_detail = Invalider Dateityp: ''{0}''. Erlaubte Dateitypen: ''{1}''.
+primefaces.FileValidator.FILENAME_EMPTY=Dateiname darf nicht leer oder null sein
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Ungültiger Dateiname: {0} enthält ungültige Zeichen: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Ungültiger Windows-Dateiname: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Ungültiger Linux-Dateiname: {0}
+primefaces.FileValidator.FILE_LIMIT = Maximale Anzahl an Dateien überschritten.
+primefaces.FileValidator.FILE_LIMIT_detail = Maximale Anzahl: {0}.
 primefaces.FileValidator.SIZE_LIMIT = Invalide Dateigröße.
-primefaces.FileValidator.SIZE_LIMIT_detail = Datei ''{0}'' darf nicht größer als {1} sein.
+primefaces.FileValidator.SIZE_LIMIT_detail = Datei ''{0}'' darf nicht größer als {1} sein.
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_el.properties b/primefaces/src/main/resources/org/primefaces/Messages_el.properties
index 4fac267804..ac66443f8b 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_el.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_el.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Μέγιστος αριθμός: {0
 primefaces.FileValidator.ALLOW_TYPES = Μη έγκυρος τύπος αρχείου.
 primefaces.FileValidator.ALLOW_TYPES_detail = Μη έγκυρος τύπος αρχείου: ''{0}''. Επιτρεπόμενοι τύποι: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Μη έγκυρο μέγεθος αρχείου.
-primefaces.FileValidator.SIZE_LIMIT_detail = Το αρχείο ''{0}'' δεν πρέπει να είναι μεγαλύτερο από {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Το αρχείο ''{0}'' δεν πρέπει να είναι μεγαλύτερο από {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Το όνομα αρχείου δεν μπορεί να είναι κενό ή null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Μη έγκυρο όνομα αρχείου: {0} περιέχει μη έγκυρο χαρακτήρα: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Μη έγκυρο όνομα αρχείου των Windows: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Μη έγκυρο όνομα αρχείου Linux: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_en.properties b/primefaces/src/main/resources/org/primefaces/Messages_en.properties
index 3e1660f465..db9dab5f67 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_en.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_en.properties
@@ -17,10 +17,14 @@ primefaces.slider.OUT_OF_RANGE = {0}: Validation Error: Value is out of range.
 primefaces.tree.REQUIRED = {0}: Validation Error.
 primefaces.tree.REQUIRED_detail = Selection is required.
 
-primefaces.FileValidator.FILE_LIMIT = Maximum number of files exceeded.
-primefaces.FileValidator.FILE_LIMIT_detail = Maximum number: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Invalid file type.
 primefaces.FileValidator.ALLOW_TYPES_detail = Invalid file type: ''{0}''. Allowed types: ''{1}''.
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Invalid filename: {0} contains invalid character: {1}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Invalid Linux filename: {0}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Invalid Windows filename: {0}
+primefaces.FileValidator.FILENAME_EMPTY=Filename cannot be empty or null
+primefaces.FileValidator.FILE_LIMIT = Maximum number of files exceeded.
+primefaces.FileValidator.FILE_LIMIT_detail = Maximum number: {0}.
 primefaces.FileValidator.SIZE_LIMIT = Invalid file size.
 primefaces.FileValidator.SIZE_LIMIT_detail = File ''{0}'' must not be larger than {1}.
 
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_es.properties b/primefaces/src/main/resources/org/primefaces/Messages_es.properties
index 6a2f2bec02..f9a65ab05d 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_es.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_es.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Número máximo: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Tipo de archivo no válido.
 primefaces.FileValidator.ALLOW_TYPES_detail = Tipo de archivo no válido: ''{0}''. Tipos permitidos: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Tamaño de archivo no válido.
-primefaces.FileValidator.SIZE_LIMIT_detail = El archivo ''{0}'' no debe ser mayor que {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = El archivo ''{0}'' no debe ser mayor que {1}.
+primefaces.FileValidator.FILENAME_EMPTY=El nombre del archivo no puede estar vacío o ser nulo
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nombre de archivo no válido: {0} contiene un carácter no válido: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nombre de archivo de Windows no válido: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nombre de archivo Linux no válido: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_fa.properties b/primefaces/src/main/resources/org/primefaces/Messages_fa.properties
index 40a0aeeea0..c52ae5dbee 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_fa.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_fa.properties
@@ -16,3 +16,7 @@ primefaces.password.INVALID_MATCH_detail = {0} باید با {1} مطابقت د
 primefaces.slider.OUT_OF_RANGE = {0}: خطای اعتبارسنجی: مقدار خارج از بازه است.
 primefaces.tree.REQUIRED = {0}: خطای اعتبار سنجی.
 primefaces.tree.REQUIRED_detail = انتخاب الزامیست.
+primefaces.FileValidator.FILENAME_EMPTY=نام فایل نمی تواند خالی یا پوچ باشد
+primefaces.FileValidator.FILENAME_INVALID_CHAR=نام فایل نامعتبر: {0} حاوی نویسه نامعتبر است: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=نام فایل ویندوز نامعتبر: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=نام فایل لینوکس نامعتبر است: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_fr.properties b/primefaces/src/main/resources/org/primefaces/Messages_fr.properties
index 299d16b60d..1878ae6949 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_fr.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_fr.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Nombre maximum : {0}.
 primefaces.FileValidator.ALLOW_TYPES = Type de fichier invalide.
 primefaces.FileValidator.ALLOW_TYPES_detail = Type de fichier invalide : ''{0}''. Types autorisés : ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Taille de fichier invalide.
-primefaces.FileValidator.SIZE_LIMIT_detail = Le fichier ''{0}'' ne doit pas être plus grand que {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Le fichier ''{0}'' ne doit pas être plus grand que {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Le nom de fichier ne peut être vide ou nul
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nom de fichier non valide : {0} contient un caractère non valide : {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nom de fichier Windows non valide : {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nom de fichier Linux non valide : {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_hi.properties b/primefaces/src/main/resources/org/primefaces/Messages_hi.properties
index f3b69415a2..a15eb04806 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_hi.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_hi.properties
@@ -16,3 +16,7 @@ primefaces.password.INVALID_MATCH_detail = {0} को {1} से मेल ख
 primefaces.slider.OUT_OF_RANGE = {0}: सत्यापन त्रुटि: मान सीमा से बाहर है।
 primefaces.tree.REQUIRED = {0}: सत्यापन त्रुटि।
 primefaces.tree.REQUIRED_detail = चयन आवश्यक है।
+primefaces.FileValidator.FILENAME_EMPTY=फ़ाइल नाम खाली या शून्य नहीं हो सकता
+primefaces.FileValidator.FILENAME_INVALID_CHAR=अमान्य फ़ाइल नाम: {0} इसमें अमान्य वर्ण है: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=अमान्य विंडोज़ फ़ाइल नाम: {0} 
+primefaces.FileValidator.FILENAME_INVALID_LINUX=अमान्य लिनक्स फ़ाइल नाम: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_hr.properties b/primefaces/src/main/resources/org/primefaces/Messages_hr.properties
index ce6af821b8..bd6c0e17e0 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_hr.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_hr.properties
@@ -22,3 +22,7 @@ primefaces.FileValidator.ALLOW_TYPES = Érvénytelen fájltípus.
 primefaces.FileValidator.ALLOW_TYPES_detail = Érvénytelen fájltípus: ''{0}''. Engedélyezett típusok: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Érvénytelen fájlméret.
 primefaces.FileValidator.SIZE_LIMIT_detail = A(z) ''{0}'' fájl nem lehet nagyobb, mint {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Naziv datoteke ne može biti prazan ili null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nevažeći naziv datoteke: {0} sadrži nevažeći znak: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nevažeći Windows naziv datoteke: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nevažeći naziv Linux datoteke: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_in.properties b/primefaces/src/main/resources/org/primefaces/Messages_in.properties
index 10aed9e0b7..e11823934f 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_in.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_in.properties
@@ -21,3 +21,7 @@ primefaces.FileValidator.ALLOW_TYPES = Jenis file tidak valid.
 primefaces.FileValidator.ALLOW_TYPES_detail = Jenis berkas tidak valid: ''{0}''. Jenis yang diperbolehkan: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Ukuran file tidak valid.
 primefaces.FileValidator.SIZE_LIMIT_detail = File ''{0}'' tidak boleh lebih besar dari {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Nama file tidak boleh kosong atau null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nama file tidak valid: {0} berisi karakter yang tidak valid: {1} 
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nama file Windows tidak valid: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nama file Linux tidak valid: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_it.properties b/primefaces/src/main/resources/org/primefaces/Messages_it.properties
index 076ee633c9..10c624b2b3 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_it.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_it.properties
@@ -22,3 +22,7 @@ primefaces.FileValidator.ALLOW_TYPES = Tipo di file non valido.
 primefaces.FileValidator.ALLOW_TYPES_detail = Tipo di file non valido: ''{0}''. Tipi consentiti: ''{1}'.
 primefaces.FileValidator.SIZE_LIMIT = Dimensione file non valida.
 primefaces.FileValidator.SIZE_LIMIT_detail = Il file ''{0}'' non deve essere più grande di {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Il nome del file non può essere vuoto o nullo
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nome file non valido:{0} contiene un carattere non valido: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nome file Windows non valido: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nome file Linux non valido: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_ja.properties b/primefaces/src/main/resources/org/primefaces/Messages_ja.properties
index 1950170d7e..0ddc8952bb 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_ja.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_ja.properties
@@ -16,3 +16,7 @@ primefaces.password.INVALID_MATCH_detail = {0}\u304C{1}\u3068\u4E00\u81F4\u3057\
 primefaces.slider.OUT_OF_RANGE = {0}: \u691C\u8A3C\u30A8\u30E9\u30FC: \u7BC4\u56F2\u5916\u306E\u5024\u3067\u3059\u3002
 primefaces.tree.REQUIRED = {0}: \u691C\u8A3C\u30A8\u30E9\u30FC.
 primefaces.tree.REQUIRED_detail = \u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+primefaces.FileValidator.FILENAME_EMPTY=ファイル名は空またはNULLにはできない
+primefaces.FileValidator.FILENAME_INVALID_CHAR=無効なファイル名： {0} 無効な文字が含まれています： {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=無効な Windows ファイル名です： {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=無効な Linux ファイル名です： {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_ka.properties b/primefaces/src/main/resources/org/primefaces/Messages_ka.properties
index 3846d77556..d1e09263a3 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_ka.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_ka.properties
@@ -15,4 +15,8 @@ primefaces.password.INVALID_MATCH = {0}: შემოწმებისას 
 primefaces.password.INVALID_MATCH_detail = {0} უნდა ემთხვეოდეს {1}.
 primefaces.slider.OUT_OF_RANGE = {0}: შემოწმებისას მოხდა შეცდომა: მნიშვნელობა საზღვრებს მიღმაა.
 primefaces.tree.REQUIRED = {0}: შემოწმებისას მოხდა შეცდომა.
-primefaces.tree.REQUIRED_detail = მონიშვნა აუცილებელია.
\ No newline at end of file
+primefaces.tree.REQUIRED_detail = მონიშვნა აუცილებელია.
+primefaces.FileValidator.FILENAME_EMPTY=ფაილის სახელი არ შეიძლება იყოს ცარიელი ან null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=ფაილის სახელი არასწორია: {0} შეიცავს არასწორ სიმბოლოს: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Windows ფაილის არასწორი სახელი: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Linux ფაილის არასწორი სახელი: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_ko.properties b/primefaces/src/main/resources/org/primefaces/Messages_ko.properties
index 3142ee02f6..ba11b2739b 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_ko.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_ko.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = 최대 개수: {0}.
 primefaces.FileValidator.ALLOW_TYPES = 파일 형식이 잘못되었습니다.
 primefaces.FileValidator.ALLOW_TYPES_detail = 잘못된 파일 형식: ''{0}''. 허용되는 유형: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = 파일 크기가 잘못되었습니다.
-primefaces.FileValidator.SIZE_LIMIT_detail = 파일 ''{0}''은(는) {1}보다 클 수 없습니다.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = 파일 ''{0}''은(는) {1}보다 클 수 없습니다.
+primefaces.FileValidator.FILENAME_EMPTY=파일 이름은 비어 있거나 널일 수 없습니다.
+primefaces.FileValidator.FILENAME_INVALID_CHAR=잘못된 파일 이름: {0} 잘못된 문자가 포함되어 있습니다: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=잘못된 Windows 파일 이름입니다: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=잘못된 Linux 파일 이름입니다: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_lt.properties b/primefaces/src/main/resources/org/primefaces/Messages_lt.properties
index 2da26d75d2..6a7493408c 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_lt.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_lt.properties
@@ -15,4 +15,8 @@ primefaces.password.INVALID_MATCH = {0}: Patikros klaida.
 primefaces.password.INVALID_MATCH_detail = {0} turėtų derėti su {1}.
 primefaces.slider.OUT_OF_RANGE = {0}: Patikros klaida: Reikšmė už leistinų ribų.
 primefaces.tree.REQUIRED = {0}: Patikros klaida.
-primefaces.tree.REQUIRED_detail = Būtina pasirinkti.
\ No newline at end of file
+primefaces.tree.REQUIRED_detail = Būtina pasirinkti.
+primefaces.FileValidator.FILENAME_EMPTY=Failo pavadinimas negali būti tuščias arba nulinis
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Neteisingas failo pavadinimas: {0} jame yra neteisingas simbolis: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Netinkamas Windows failo pavadinimas: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Netinkamas Linux failo vardas: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_lv.properties b/primefaces/src/main/resources/org/primefaces/Messages_lv.properties
index 9048dd2642..fe4a4239f4 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_lv.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_lv.properties
@@ -15,4 +15,8 @@ primefaces.password.INVALID_MATCH = {0}: Validācijas kļūda.
 primefaces.password.INVALID_MATCH_detail = {0} jāsakrīt ar {1}.
 primefaces.slider.OUT_OF_RANGE = {0}: Validācijas kļūda: vērtība ir ārpus diapazona.
 primefaces.tree.REQUIRED = {0}: Validācijas kļūda.
-primefaces.tree.REQUIRED_detail = Ir nepieciešama atlase.
\ No newline at end of file
+primefaces.tree.REQUIRED_detail = Ir nepieciešama atlase.
+primefaces.FileValidator.FILENAME_EMPTY=Datnes nosaukums nedrīkst būt tukšs vai nulle
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nederīgs faila nosaukums: {0} satur nederīgu rakstzīmi: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nederīgs Windows faila nosaukums: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nederīgs Linux faila nosaukums: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_nl.properties b/primefaces/src/main/resources/org/primefaces/Messages_nl.properties
index 058daa26f6..9e40473d47 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_nl.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_nl.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Maximaal aantal: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Ongeldig bestandstype.
 primefaces.FileValidator.ALLOW_TYPES_detail = Ongeldig bestandstype: ''{0}''. Toegestane typen: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Ongeldige bestandsgrootte.
-primefaces.FileValidator.SIZE_LIMIT_detail = Bestand ''{0}'' mag niet groter zijn dan {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Bestand ''{0}'' mag niet groter zijn dan {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Bestandsnaam kan niet leeg of nul zijn
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Ongeldige bestandsnaam: {0} bevat ongeldig teken: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Ongeldige Windows bestandsnaam: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Ongeldige Linux bestandsnaam: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_no.properties b/primefaces/src/main/resources/org/primefaces/Messages_no.properties
index ef658415ac..3b7b78509d 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_no.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_no.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Maksimalt antall: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Ugyldig filtype.
 primefaces.FileValidator.ALLOW_TYPES_detail = Ugyldig filtype: ''{0}''. Tillatte typer: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Ugyldig filstørrelse.
-primefaces.FileValidator.SIZE_LIMIT_detail = Fil ''{0}'' må ikke være større enn {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Fil ''{0}'' må ikke være større enn {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Filnavnet kan ikke være tomt eller null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Ugyldig filnavn: {0} inneholder ugyldige tegn: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Ugyldig Windows-filnavn: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Ugyldig Linux-filnavn: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_pl.properties b/primefaces/src/main/resources/org/primefaces/Messages_pl.properties
index 5748b9c41b..105e4686bb 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_pl.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_pl.properties
@@ -24,3 +24,7 @@ primefaces.FileValidator.ALLOW_TYPES = Nieprawidłowy typ pliku.
 primefaces.FileValidator.ALLOW_TYPES_detail = Nieprawidłowy typ pliku: ''{0}''. Dozwolone typy: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Nieprawidłowy rozmiar pliku.
 primefaces.FileValidator.SIZE_LIMIT_detail = Plik „{0}” nie może być większy niż {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Nazwa pliku nie może być pusta lub null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nieprawidłowa nazwa pliku: {0} zawiera nieprawidłowy znak: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nieprawidłowa nazwa pliku Windows: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nieprawidłowa nazwa pliku Linux: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_pt.properties b/primefaces/src/main/resources/org/primefaces/Messages_pt.properties
index 0403bb4ff1..0fc04939ef 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_pt.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_pt.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Número máximo: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Tipo de arquivo inválido.
 primefaces.FileValidator.ALLOW_TYPES_detail = Tipo de arquivo inválido: ''{0}''. Tipos permitidos: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Tamanho de arquivo inválido.
-primefaces.FileValidator.SIZE_LIMIT_detail = O arquivo ''{0}'' não deve ser maior que {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = O arquivo ''{0}'' não deve ser maior que {1}.
+primefaces.FileValidator.FILENAME_EMPTY=O nome do ficheiro não pode estar vazio ou ser nulo
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nome de ficheiro inválido: {0} contém um carácter inválido: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nome de ficheiro do Windows inválido: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nome de ficheiro Linux inválido: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_ro.properties b/primefaces/src/main/resources/org/primefaces/Messages_ro.properties
index bbdcc94465..948974d637 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_ro.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_ro.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Număr maxim: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Tip de fişier nevalid.
 primefaces.FileValidator.ALLOW_TYPES_detail = Tip de fișier nevalid: ''{0}''. Tipuri permise: „{1}”.
 primefaces.FileValidator.SIZE_LIMIT = Dimensiunea fișierului nevalidă.
-primefaces.FileValidator.SIZE_LIMIT_detail = Fișierul „{0}” nu trebuie să fie mai mare de {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Fișierul „{0}” nu trebuie să fie mai mare de {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Numele fișierului nu poate fi gol sau nul
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nume fișier invalid: {0} conține un caracter invalid: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nume de fișier Windows invalid: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Nume de fișier Linux invalid: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_ru.properties b/primefaces/src/main/resources/org/primefaces/Messages_ru.properties
index 44cfb38c9f..241212600c 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_ru.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_ru.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Максимальное колич
 primefaces.FileValidator.ALLOW_TYPES = Неверный тип файла.
 primefaces.FileValidator.ALLOW_TYPES_detail = Неверный тип файла: ''{0}''. Разрешенные типы: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT=Неверный размер файла.
-primefaces.FileValidator.SIZE_LIMIT_detail = Файл ''{0}'' не должен быть больше {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Файл ''{0}'' не должен быть больше {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Имя файла не может быть пустым или null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Недопустимое имя файла: {0} содержит недопустимый символ: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Недопустимое имя файла Windows: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Недопустимое имя файла Linux: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_sk.properties b/primefaces/src/main/resources/org/primefaces/Messages_sk.properties
index 6f3f5db657..a03cb29133 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_sk.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_sk.properties
@@ -20,4 +20,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Maximálny počet: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Neplatný typ súboru.
 primefaces.FileValidator.ALLOW_TYPES_detail = Neplatný typ súboru: ''{0}''. Povolené typy: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Neplatná veľkosť súboru.
-primefaces.FileValidator.SIZE_LIMIT_detail = Súbor ''{0}'' nesmie byť väčší ako {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Súbor ''{0}'' nesmie byť väčší ako {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Názov súboru nemôže byť prázdny alebo nulový
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Nesprávny názov súboru: {0} obsahuje nesprávny znak: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Nesprávny názov súboru systému Windows: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Neplatný názov súboru Linux: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_sv.properties b/primefaces/src/main/resources/org/primefaces/Messages_sv.properties
index 1c95485c37..75e1affb18 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_sv.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_sv.properties
@@ -21,4 +21,8 @@ primefaces.FileValidator.FILE_LIMIT_detail = Maximalt antal: {0}.
 primefaces.FileValidator.ALLOW_TYPES = Ogiltig filtyp.
 primefaces.FileValidator.ALLOW_TYPES_detail = Ogiltig filtyp: ''{0}''. Tillåtna typer: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Ogiltig filstorlek.
-primefaces.FileValidator.SIZE_LIMIT_detail = Filen ''{0}'' får inte vara större än {1}.
\ No newline at end of file
+primefaces.FileValidator.SIZE_LIMIT_detail = Filen ''{0}'' får inte vara större än {1}.
+primefaces.FileValidator.FILENAME_EMPTY=Filnamnet kan inte vara tomt eller null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Ogiltigt filnamn: {0} innehåller ogiltigt tecken: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Ogiltigt Windows-filnamn: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Ogiltigt Linux-filnamn: {0}
\ No newline at end of file
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_tr.properties b/primefaces/src/main/resources/org/primefaces/Messages_tr.properties
index 5d758b53a3..c4f8694ea3 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_tr.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_tr.properties
@@ -23,3 +23,7 @@ primefaces.FileValidator.ALLOW_TYPES = Geçersiz dosya türü.
 primefaces.FileValidator.ALLOW_TYPES_detail = Geçersiz dosya türü: ''{0}''. Geçerli türler: ''{1}''.
 primefaces.FileValidator.SIZE_LIMIT = Geçersiz dosya boyutu.
 primefaces.FileValidator.SIZE_LIMIT_detail = Dosya ''{0}'' {1}'den daha büyük olmamalıdır.
+primefaces.FileValidator.FILENAME_EMPTY=Dosya adı boş veya null olamaz
+primefaces.FileValidator.FILENAME_INVALID_CHAR=Geçersiz dosya adı: {0} geçersiz karakter içeriyor: {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Geçersiz Windows dosya adı: {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Geçersiz Linux dosya adı: {0}
diff --git a/primefaces/src/main/resources/org/primefaces/Messages_zh.properties b/primefaces/src/main/resources/org/primefaces/Messages_zh.properties
index 1d50f2b9df..6cc768b1b8 100644
--- a/primefaces/src/main/resources/org/primefaces/Messages_zh.properties
+++ b/primefaces/src/main/resources/org/primefaces/Messages_zh.properties
@@ -22,3 +22,7 @@ primefaces.FileValidator.ALLOW_TYPES = 文件类型无效。
 primefaces.FileValidator.ALLOW_TYPES_detail = 无效文件类型：“{0}”。 允许的类型：“{1}”。
 primefaces.FileValidator.SIZE_LIMIT = 文件大小无效。
 primefaces.FileValidator.SIZE_LIMIT_detail = 文件“{0}”不得大于 {1}。
+primefaces.FileValidator.FILENAME_EMPTY=文件名不能为空或 null
+primefaces.FileValidator.FILENAME_INVALID_CHAR=无效文件名： {0} 包含无效字符： {1}
+primefaces.FileValidator.FILENAME_INVALID_WINDOWS=Windows 文件名无效： {0}
+primefaces.FileValidator.FILENAME_INVALID_LINUX=Linux 文件名无效： {0}
diff --git a/primefaces/src/main/type-definitions/blocklist.txt b/primefaces/src/main/type-definitions/blocklist.txt
index be791b8f7e..df5eb07348 100644
--- a/primefaces/src/main/type-definitions/blocklist.txt
+++ b/primefaces/src/main/type-definitions/blocklist.txt
@@ -15,6 +15,7 @@ touch/touchswipe.js
 locales/locale-ar.js
 locales/locale-bg.js
 locales/locale-bn.js
+locales/locale-bs.js
 locales/locale-ca.js
 locales/locale-ckb.js
 locales/locale-cs.js


Test patch:
diff --git a/primefaces-integration-tests-jakarta/pom.xml b/primefaces-integration-tests-jakarta/pom.xml
index af32aa2d39..6d43fec167 100644
--- a/primefaces-integration-tests-jakarta/pom.xml
+++ b/primefaces-integration-tests-jakarta/pom.xml
@@ -29,7 +29,7 @@
         <jakarta.faces.STATE_SAVING_METHOD>server</jakarta.faces.STATE_SAVING_METHOD>
 
         <!-- dependency versions -->
-        <lombok.version>1.18.34</lombok.version>
+        <lombok.version>1.18.36</lombok.version>
         <tomcat.version>10.1.31</tomcat.version>
         <jetty.version>9.4.56.v20240826</jetty.version>
     </properties>
diff --git a/primefaces-integration-tests/pom.xml b/primefaces-integration-tests/pom.xml
index a3986de0c9..79a70434b4 100644
--- a/primefaces-integration-tests/pom.xml
+++ b/primefaces-integration-tests/pom.xml
@@ -29,7 +29,7 @@
 
         <!-- dependency versions -->
         <hibernate-validator.version>6.2.4.Final</hibernate-validator.version>
-        <lombok.version>1.18.34</lombok.version>
+        <lombok.version>1.18.36</lombok.version>
         <myfaces.version>2.3.10</myfaces.version>
         <myfaces-next.version>2.3-next-M8</myfaces-next.version>
         <tomcat.version>9.0.97</tomcat.version>
diff --git a/primefaces-integration-tests/src/main/java/org/primefaces/integrationtests/core/csp/CoreCsp001.java b/primefaces-integration-tests/src/main/java/org/primefaces/integrationtests/core/csp/CoreCsp001.java
index fd046a4bd9..67deecb260 100644
--- a/primefaces-integration-tests/src/main/java/org/primefaces/integrationtests/core/csp/CoreCsp001.java
+++ b/primefaces-integration-tests/src/main/java/org/primefaces/integrationtests/core/csp/CoreCsp001.java
@@ -51,4 +51,9 @@ public class CoreCsp001 implements Serializable {
                 new FacesMessage("Welcome " + firstname + " " + lastname));
     }
 
+    public void action() {
+        FacesContext.getCurrentInstance().addMessage(null,
+                new FacesMessage("Action method called"));
+    }
+
 }
diff --git a/primefaces-integration-tests/src/main/webapp/core/csp/coreCsp002.xhtml b/primefaces-integration-tests/src/main/webapp/core/csp/coreCsp002.xhtml
new file mode 100644
index 0000000000..d959e67765
--- /dev/null
+++ b/primefaces-integration-tests/src/main/webapp/core/csp/coreCsp002.xhtml
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:h="http://xmlns.jcp.org/jsf/html"
+      xmlns:f="http://xmlns.jcp.org/jsf/core"
+      xmlns:p="http://primefaces.org/ui">
+
+<f:view contentType="text/html;charset=UTF-8" encoding="UTF-8">
+    <h:head>
+
+    </h:head>
+
+    <h:body>
+
+        <h2>No PrimeFaces components on page fails initScripts() because jQuery is not loaded</h2>
+        <h:form id="form">
+            <h:messages id="msgs" />
+            <h:commandButton id="submit" action="#{coreCsp001.action()}" value="POST" />
+        </h:form>
+
+    </h:body>
+</f:view>
+
+</html>
\ No newline at end of file
diff --git a/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/core/csp/CoreCsp002Test.java b/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/core/csp/CoreCsp002Test.java
new file mode 100644
index 0000000000..6124ad0d91
--- /dev/null
+++ b/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/core/csp/CoreCsp002Test.java
@@ -0,0 +1,61 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2009-2024 PrimeTek Informatics
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.primefaces.integrationtests.core.csp;
+
+import org.primefaces.selenium.AbstractPrimePage;
+import org.primefaces.selenium.AbstractPrimePageTest;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+
+public class CoreCsp002Test  extends AbstractPrimePageTest {
+
+    @Test
+    @Order(1)
+    @DisplayName("Core-CSP: #12901 No PrimeFaces components on page fails initScripts() because jQuery is not loaded")
+    void cspInNewPage(Page page) {
+        // Arrange
+        assertNoJavascriptErrors();
+
+        // Act
+        page.submit.click();
+
+        // Assert
+        assertNoJavascriptErrors();
+    }
+
+    public static class Page extends AbstractPrimePage {
+
+        @FindBy(id = "form:submit")
+        WebElement submit;
+
+        @Override
+        public String getLocation() {
+            return "core/csp/coreCsp002.xhtml";
+        }
+    }
+}
diff --git a/primefaces/src/test/java/org/primefaces/util/FileUploadUtilsTest.java b/primefaces/src/test/java/org/primefaces/util/FileUploadUtilsTest.java
index 1aba0609c5..8fc5651c1c 100644
--- a/primefaces/src/test/java/org/primefaces/util/FileUploadUtilsTest.java
+++ b/primefaces/src/test/java/org/primefaces/util/FileUploadUtilsTest.java
@@ -46,7 +46,12 @@ import org.junit.jupiter.api.Test;
 import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -55,13 +60,15 @@ class FileUploadUtilsTest {
     private FileUpload fileUpload;
     private InputStream inputStream;
     private PrimeApplicationContext appContext;
+    private FacesContext context;
 
     @BeforeEach
     void setup() {
         fileUpload = mock(FileUpload.class);
         inputStream = mock(InputStream.class);
-        FacesContext context = mock(FacesContext.class);
+        context = mock(FacesContext.class);
         Application app = mock(Application.class);
+        when(app.getDefaultLocale()).thenReturn(Locale.US);
         when(context.getApplication()).thenReturn(app);
         ExternalContext externalContext = mock(ExternalContext.class);
         when(context.getExternalContext()).thenReturn(externalContext);
@@ -309,7 +316,7 @@ class FileUploadUtilsTest {
         String filename = "~myfile.txt";
 
         // Act
-        String result = FileUploadUtils.requireValidFilename(filename);
+        String result = FileUploadUtils.requireValidFilename(context, filename);
 
         // Assert
         assertEquals(filename, result);
@@ -318,10 +325,10 @@ class FileUploadUtilsTest {
     @Test
     void requireValidFilename_Valid() {
         // valid files
-        assertEquals("someFileWithUmlautsßöäü.txt", FileUploadUtils.requireValidFilename("someFileWithUmlautsßöäü.txt"));
-        assertEquals("StringFinder.exe", FileUploadUtils.requireValidFilename("StringFinder.exe"));
-        assertEquals("January.xlsx", FileUploadUtils.requireValidFilename("January.xlsx"));
-        assertEquals("TravelBrochure.pdf", FileUploadUtils.requireValidFilename("TravelBrochure.pdf"));
+        assertEquals("someFileWithUmlautsßöäü.txt", FileUploadUtils.requireValidFilename(context, "someFileWithUmlautsßöäü.txt"));
+        assertEquals("StringFinder.exe", FileUploadUtils.requireValidFilename(context, "StringFinder.exe"));
+        assertEquals("January.xlsx", FileUploadUtils.requireValidFilename(context, "January.xlsx"));
+        assertEquals("TravelBrochure.pdf", FileUploadUtils.requireValidFilename(context, "TravelBrochure.pdf"));
     }
 
     @Test
@@ -333,7 +340,7 @@ class FileUploadUtilsTest {
             String[] invalidCharacters = {"/", "\0", ":", "*", "?", "\"", "<", ">", "|"};
             for (String character : invalidCharacters) {
                 String invalidFileName = "filename_with_" + character;
-                assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(invalidFileName));
+                assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(context, invalidFileName));
             }
         }
     }
@@ -348,14 +355,14 @@ class FileUploadUtilsTest {
             String[] invalidCharacters = {"/", "\\\\", ":", "*", "?", "\"", "<", ">", "|"};
             for (String character : invalidCharacters) {
                 String invalidFileName = "filename_with_" + character;
-                assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(invalidFileName));
+                assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(context, invalidFileName));
             }
 
             // Add reserved device names as invalid filenames
             String[] reservedDeviceNames = {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2",
                 "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };
             for (String deviceName : reservedDeviceNames) {
-                assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(deviceName));
+                assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(context, deviceName));
             }
         }
     }
@@ -369,8 +376,8 @@ class FileUploadUtilsTest {
             String[] invalidCharacters = {"%20", "%21"};
             for (String ch : invalidCharacters) {
                 String invalidFileName = "filename_with_" + ch;
-                ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(invalidFileName));
-                assertEquals("Invalid filename: (filename_with_" + ch + ") contains invalid character: " + ch, ex.getFacesMessage().getDetail());
+                ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(context, invalidFileName));
+                assertEquals("Invalid filename: filename_with_" + ch + " contains invalid character: " + ch, ex.getFacesMessage().getDetail());
             }
         }
     }
@@ -381,7 +388,7 @@ class FileUploadUtilsTest {
         String invalidFileName = null;
 
         // Act
-        ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(invalidFileName));
+        ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(context, invalidFileName));
 
         // Assert
         assertEquals("Filename cannot be empty or null", ex.getFacesMessage().getDetail());
@@ -393,7 +400,7 @@ class FileUploadUtilsTest {
         String invalidFileName = " ";
 
         // Act
-        ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(invalidFileName));
+        ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(context, invalidFileName));
 
         // Assert
         assertEquals("Filename cannot be empty or null", ex.getFacesMessage().getDetail());
@@ -406,11 +413,11 @@ class FileUploadUtilsTest {
         String os = System.getProperty("os.name").toLowerCase();
 
         // Act
-        ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(invalidFileName));
+        ValidatorException ex = assertThrows(ValidatorException.class, () -> FileUploadUtils.requireValidFilename(context, invalidFileName));
 
         // Assert
         if (os.contains("win")) {
-            assertEquals("Invalid filename: (file:*) contains invalid character: :", ex.getFacesMessage().getDetail());
+            assertEquals("Invalid filename: file:* contains invalid character: :", ex.getFacesMessage().getDetail());
         }
         else {
             assertEquals("Invalid Linux filename: file:*", ex.getFacesMessage().getDetail());
@@ -425,11 +432,11 @@ class FileUploadUtilsTest {
 
     @Test
     void requireValidFilename() {
-        assertDoesNotThrow(() -> FileUploadUtils.requireValidFilename("someFileWithUmlautsßöäü.txt"));
+        assertDoesNotThrow(() -> FileUploadUtils.requireValidFilename(context, "someFileWithUmlautsßöäü.txt"));
         // validate fileName which contains /, which is invalid in a filename
-        assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename("someFil/eWithUmlautsßöäü.txt"));
+        assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(context, "someFil/eWithUmlautsßöäü.txt"));
         // validate fileName which contains <, which is invalid in a filename
-        assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename("someFil<eWithUmlautsßöäü.txt"));
+        assertThrows(FacesException.class, () -> FileUploadUtils.requireValidFilename(context, "someFil<eWithUmlautsßöäü.txt"));
     }
 
-}
+}
\ No newline at end of file