From e9f9cd714ba9d30b58d6a716ce7859b04570c287 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Mon, 17 Jul 2023 21:55:19 +0200 Subject: [PATCH] OF-2624: Try to answer data forms in users' preferred language When a user is requesting a data form, try to localize the text in the form according to the user's preferred language. In this commit, the preferred language is being obtained from the session of a locally connected user. This will not work for federated users. As a fallback, the default langague as configured in Openfire is used (as is already the case prior to this commit). --- .../main/resources/openfire_i18n.properties | 2 + .../jivesoftware/openfire/PrivateStorage.java | 4 +- .../jivesoftware/openfire/SessionManager.java | 16 +- .../commands/admin/GetServerStats.java | 20 +- .../muc/spi/IQMUCRegisterHandler.java | 123 ++++---- .../openfire/muc/spi/IQOwnerHandler.java | 290 +++++++++--------- .../muc/spi/MultiUserChatServiceImpl.java | 18 +- .../openfire/pep/IQPEPHandler.java | 6 +- .../openfire/pubsub/CollectionNode.java | 50 ++- .../pubsub/DefaultNodeConfiguration.java | 42 +-- .../openfire/pubsub/LeafNode.java | 24 +- .../jivesoftware/openfire/pubsub/Node.java | 106 +++---- .../openfire/pubsub/NodeSubscription.java | 53 ++-- .../pubsub/PendingSubscriptionsCommand.java | 30 +- .../openfire/pubsub/PubSubEngine.java | 15 +- .../openfire/pubsub/PubSubModule.java | 10 +- .../org/jivesoftware/util/LocaleUtils.java | 66 +++- .../src/main/webapp/pubsub-node-edit.jsp | 2 +- 18 files changed, 465 insertions(+), 412 deletions(-) diff --git a/i18n/src/main/resources/openfire_i18n.properties b/i18n/src/main/resources/openfire_i18n.properties index 72394b226a..88d0b543b8 100644 --- a/i18n/src/main/resources/openfire_i18n.properties +++ b/i18n/src/main/resources/openfire_i18n.properties @@ -1103,6 +1103,8 @@ index.local=Locale / Timezone: index.process_owner=OS Process Owner: index.memory=Java Memory index.memory_usage_description={0} MB of {1} MB ({2}%) used +index.available_users=Available Users +index.available_users_sessions=Available Users Sessions index.update.alert=Update information index.update.info=Server version {0} is now available. Click {1}here{2} to download or read the \ {3}change log{4} for more information. diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/PrivateStorage.java b/xmppserver/src/main/java/org/jivesoftware/openfire/PrivateStorage.java index e2ec9c584f..fe8447639c 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/PrivateStorage.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/PrivateStorage.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Jive Software. All rights reserved. + * Copyright (C) 2004-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,7 +111,7 @@ public void add(String username, Element data) { Node node = pepService.getNode( data.getNamespaceURI() ); if ( node == null ) { - PubSubEngine.CreateNodeResponse response = PubSubEngine.createNodeHelper( pepService, owner, pepService.getDefaultNodeConfiguration( true ).getConfigurationForm().getElement(), data.getNamespaceURI(), PRIVATE_DATA_PUBLISHING_OPTIONS ); + PubSubEngine.CreateNodeResponse response = PubSubEngine.createNodeHelper( pepService, owner, pepService.getDefaultNodeConfiguration( true ).getConfigurationForm(null).getElement(), data.getNamespaceURI(), PRIVATE_DATA_PUBLISHING_OPTIONS ); node = response.newNode; if ( node == null ) diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/SessionManager.java b/xmppserver/src/main/java/org/jivesoftware/openfire/SessionManager.java index 567b812c05..92262c7354 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/SessionManager.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/SessionManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software, 2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2022-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1273,6 +1273,20 @@ public void setConflictKickLimit(int limit) { CONFLICT_LIMIT.setValue(limit); } + public Locale getLocaleForSession(JID address) + { + if (address == null || !XMPPServer.getInstance().isLocal(address)) { + return null; + } + + final ClientSession session = getSession(address); + if (session == null) { + return null; + } + + return session.getLanguage(); + } + private class ClientSessionListener implements ConnectionCloseListener { /** * Handle a session that just closed. diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/commands/admin/GetServerStats.java b/xmppserver/src/main/java/org/jivesoftware/openfire/commands/admin/GetServerStats.java index a2c6ce757f..16af84a58b 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/commands/admin/GetServerStats.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/commands/admin/GetServerStats.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,8 @@ protected void addStageInformation(SessionData data, Element command) { @Override public void execute(SessionData data, Element command) { + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(data.getOwner()); + DataForm form = new DataForm(DataForm.Type.result); FormField field = form.addField(); @@ -59,25 +61,25 @@ public void execute(SessionData data, Element command) { field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel(LocaleUtils.getLocalizedString("index.server_name")); + field.setLabel(LocaleUtils.getLocalizedString("index.server_name", preferredLocale)); field.setVariable("name"); field.addValue(AdminConsole.getAppName()); field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel(LocaleUtils.getLocalizedString("index.version")); + field.setLabel(LocaleUtils.getLocalizedString("index.version", preferredLocale)); field.setVariable("version"); field.addValue(AdminConsole.getVersionString()); field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel(LocaleUtils.getLocalizedString("index.domain_name")); + field.setLabel(LocaleUtils.getLocalizedString("index.domain_name", preferredLocale)); field.setVariable("domain"); field.addValue(XMPPServer.getInstance().getServerInfo().getXMPPDomain()); field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel(LocaleUtils.getLocalizedString("index.jvm")); + field.setLabel(LocaleUtils.getLocalizedString("index.jvm", preferredLocale)); field.setVariable("os"); String vmName = System.getProperty("java.vm.name"); if (vmName == null) { @@ -90,7 +92,7 @@ public void execute(SessionData data, Element command) { field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel(LocaleUtils.getLocalizedString("index.uptime")); + field.setLabel(LocaleUtils.getLocalizedString("index.uptime", preferredLocale)); field.setVariable("uptime"); field.addValue(XMPPDateTimeFormat.format(XMPPServer.getInstance().getServerInfo().getLastStarted())); @@ -105,7 +107,7 @@ public void execute(SessionData data, Element command) { double percentUsed = 100 - percentFree; field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel(LocaleUtils.getLocalizedString("index.memory")); + field.setLabel(LocaleUtils.getLocalizedString("index.memory", preferredLocale)); field.setVariable("memory"); field.addValue(mbFormat.format(usedMemory) + " MB of " + mbFormat.format(maxMemory) + " MB (" + percentFormat.format(percentUsed) + "%) used"); @@ -122,13 +124,13 @@ public void execute(SessionData data, Element command) { } field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel("Available Users"); + field.setLabel(LocaleUtils.getLocalizedString("index.available_users", preferredLocale)); field.setVariable("activeusersnum"); field.addValue(users.size()); field = form.addField(); field.setType(FormField.Type.text_single); - field.setLabel("Available Users Sessions"); + field.setLabel(LocaleUtils.getLocalizedString("index.available_users_sessions", preferredLocale)); field.setVariable("sessionsnum"); field.addValue(availableSessions); diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQMUCRegisterHandler.java b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQMUCRegisterHandler.java index 372af09bb3..6c5df361ff 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQMUCRegisterHandler.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQMUCRegisterHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Jive Software. All rights reserved. + * Copyright (C) 2004-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,18 +16,11 @@ package org.jivesoftware.openfire.muc.spi; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.locks.Lock; - import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.QName; -import org.jivesoftware.openfire.muc.ConflictException; -import org.jivesoftware.openfire.muc.ForbiddenException; -import org.jivesoftware.openfire.muc.MUCRole; -import org.jivesoftware.openfire.muc.MUCRoom; -import org.jivesoftware.openfire.muc.MultiUserChatService; +import org.jivesoftware.openfire.SessionManager; +import org.jivesoftware.openfire.muc.*; import org.jivesoftware.util.ElementUtil; import org.jivesoftware.util.LocaleUtils; import org.slf4j.Logger; @@ -38,6 +31,11 @@ import org.xmpp.packet.PacketError; import org.xmpp.packet.Presence; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.locks.Lock; + /** * This class is responsible for handling packets with namespace jabber:iq:register that were * sent to the MUC service. MultiUserChatServer will receive all the IQ packets and if the @@ -49,59 +47,6 @@ class IQMUCRegisterHandler { private static final Logger Log = LoggerFactory.getLogger(IQMUCRegisterHandler.class); - private static final Element probeResult; - - static { - // Create the registration form of the room which contains information - // such as: first name, last name and nickname. - final DataForm registrationForm = new DataForm(DataForm.Type.form); - registrationForm.setTitle(LocaleUtils.getLocalizedString("muc.form.reg.title")); - registrationForm.addInstruction(LocaleUtils - .getLocalizedString("muc.form.reg.instruction")); - - final FormField fieldForm = registrationForm.addField(); - fieldForm.setVariable("FORM_TYPE"); - fieldForm.setType(FormField.Type.hidden); - fieldForm.addValue("http://jabber.org/protocol/muc#register"); - - final FormField fieldReg = registrationForm.addField(); - fieldReg.setVariable("muc#register_first"); - fieldReg.setType(FormField.Type.text_single); - fieldReg.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.first-name")); - fieldReg.setRequired(true); - - final FormField fieldLast = registrationForm.addField(); - fieldLast.setVariable("muc#register_last"); - fieldLast.setType(FormField.Type.text_single); - fieldLast.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.last-name")); - fieldLast.setRequired(true); - - final FormField fieldNick = registrationForm.addField(); - fieldNick.setVariable("muc#register_roomnick"); - fieldNick.setType(FormField.Type.text_single); - fieldNick.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.nickname")); - fieldNick.setRequired(true); - - final FormField fieldUrl = registrationForm.addField(); - fieldUrl.setVariable("muc#register_url"); - fieldUrl.setType(FormField.Type.text_single); - fieldUrl.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.url")); - - final FormField fieldMail = registrationForm.addField(); - fieldMail.setVariable("muc#register_email"); - fieldMail.setType(FormField.Type.text_single); - fieldMail.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.email")); - - final FormField fieldFaq = registrationForm.addField(); - fieldFaq.setVariable("muc#register_faqentry"); - fieldFaq.setType(FormField.Type.text_single); - fieldFaq.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.faqentry")); - - // Create the probeResult and add the registration form - probeResult = DocumentHelper.createElement(QName.get("query", "jabber:iq:register")); - probeResult.add(registrationForm.getElement()); - } - private final MultiUserChatService mucService; public IQMUCRegisterHandler(MultiUserChatService mucService) { @@ -121,6 +66,8 @@ public IQ handleIQ(IQ packet) { return reply; } + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(packet.getFrom()); + final Lock lock = mucService.getChatRoomLock(name); lock.lock(); try { @@ -146,7 +93,55 @@ else if (!room.isRegistrationEnabled() || if (IQ.Type.get == packet.getType()) { reply = IQ.createResultIQ(packet); String nickname = room.getReservedNickname(packet.getFrom()); - Element currentRegistration = probeResult.createCopy(); + + // Create the registration form of the room which contains information + // such as: first name, last name and nickname. + final DataForm registrationForm = new DataForm(DataForm.Type.form); + registrationForm.setTitle(LocaleUtils.getLocalizedString("muc.form.reg.title", preferredLocale)); + registrationForm.addInstruction(LocaleUtils.getLocalizedString("muc.form.reg.instruction", preferredLocale)); + + final FormField fieldForm = registrationForm.addField(); + fieldForm.setVariable("FORM_TYPE"); + fieldForm.setType(FormField.Type.hidden); + fieldForm.addValue("http://jabber.org/protocol/muc#register"); + + final FormField fieldReg = registrationForm.addField(); + fieldReg.setVariable("muc#register_first"); + fieldReg.setType(FormField.Type.text_single); + fieldReg.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.first-name", preferredLocale)); + fieldReg.setRequired(true); + + final FormField fieldLast = registrationForm.addField(); + fieldLast.setVariable("muc#register_last"); + fieldLast.setType(FormField.Type.text_single); + fieldLast.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.last-name", preferredLocale)); + fieldLast.setRequired(true); + + final FormField fieldNick = registrationForm.addField(); + fieldNick.setVariable("muc#register_roomnick"); + fieldNick.setType(FormField.Type.text_single); + fieldNick.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.nickname", preferredLocale)); + fieldNick.setRequired(true); + + final FormField fieldUrl = registrationForm.addField(); + fieldUrl.setVariable("muc#register_url"); + fieldUrl.setType(FormField.Type.text_single); + fieldUrl.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.url", preferredLocale)); + + final FormField fieldMail = registrationForm.addField(); + fieldMail.setVariable("muc#register_email"); + fieldMail.setType(FormField.Type.text_single); + fieldMail.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.email", preferredLocale)); + + final FormField fieldFaq = registrationForm.addField(); + fieldFaq.setVariable("muc#register_faqentry"); + fieldFaq.setType(FormField.Type.text_single); + fieldFaq.setLabel(LocaleUtils.getLocalizedString("muc.form.reg.faqentry", preferredLocale)); + + // Create the probeResult and add the registration form + Element currentRegistration = DocumentHelper.createElement(QName.get("query", "jabber:iq:register")); + currentRegistration.add(registrationForm.getElement()); + if (nickname != null) { // The user is already registered with the room so answer a completed form ElementUtil.setProperty(currentRegistration, "query.registered", null); diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQOwnerHandler.java b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQOwnerHandler.java index 5ff89b73da..0b6d32a067 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQOwnerHandler.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/IQOwnerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Jive Software. All rights reserved. + * Copyright (C) 2004-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,10 @@ package org.jivesoftware.openfire.muc.spi; -import java.util.*; -import java.util.stream.Collectors; - import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.QName; +import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.group.Group; import org.jivesoftware.openfire.group.GroupJID; @@ -37,6 +35,9 @@ import org.xmpp.forms.FormField.Type; import org.xmpp.packet.*; +import java.util.*; +import java.util.stream.Collectors; + /** * A handler for the IQ packet with namespace http://jabber.org/protocol/muc#owner. This kind of * packets are usually sent by room owners. So this handler provides the necessary functionality @@ -50,17 +51,12 @@ public class IQOwnerHandler { private final MUCRoom room; - private DataForm configurationForm; - - private Element probeResult; - private final boolean skipInvite; public IQOwnerHandler(MUCRoom chatroom) { this.room = chatroom; this.skipInvite = JiveGlobals.getBooleanProperty( "xmpp.muc.skipInvite", false); - init(); } /** @@ -120,8 +116,8 @@ public void handleIQ(IQ packet, MUCRole role) throws ForbiddenException, Conflic // If no element was included in the query element then answer the // configuration form if (!element.elementIterator().hasNext()) { - refreshConfigurationFormValues(); - reply.setChildElement(probeResult.createCopy()); + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(packet.getFrom()); + reply.setChildElement(generateProbeResult(preferredLocale)); } // An unknown and possibly incorrect element was included in the query // element so answer a BAD_REQUEST error @@ -453,8 +449,8 @@ else if ( passwordChanged ) } // Send the updated presences to the room occupants - for (Object presence : presences) { - room.send((Presence) presence, room.getRole()); + for (Presence presence : presences) { + room.send(presence, room.getRole()); } // XEP-0045 section 10.2.1 "Notification of Configuration Changes: A room MUST send notification to all occupants @@ -472,6 +468,133 @@ else if ( passwordChanged ) } private void refreshConfigurationFormValues() { + } + + private Element generateProbeResult(Locale preferredLocale) { + final DataForm configurationForm = new DataForm(DataForm.Type.form); + configurationForm.setTitle(LocaleUtils.getLocalizedString("muc.form.conf.title", preferredLocale)); + List params = new ArrayList<>(); + params.add(room.getName()); + configurationForm.addInstruction(LocaleUtils.getLocalizedString("muc.form.conf.instruction", params, preferredLocale)); + + configurationForm.addField("FORM_TYPE", null, Type.hidden) + .addValue("http://jabber.org/protocol/muc#roomconfig"); + + configurationForm.addField("muc#roomconfig_roomname", + LocaleUtils.getLocalizedString("muc.form.conf.owner_roomname", preferredLocale), + Type.text_single); + + configurationForm.addField("muc#roomconfig_roomdesc", + LocaleUtils.getLocalizedString("muc.form.conf.owner_roomdesc", preferredLocale), + Type.text_single); + + configurationForm.addField("muc#roomconfig_changesubject", + LocaleUtils.getLocalizedString("muc.form.conf.owner_changesubject", preferredLocale), + Type.boolean_type); + + final FormField maxUsers = configurationForm.addField( + "muc#roomconfig_maxusers", + LocaleUtils.getLocalizedString("muc.form.conf.owner_maxusers", preferredLocale), + Type.list_single); + maxUsers.addOption("10", "10"); + maxUsers.addOption("20", "20"); + maxUsers.addOption("30", "30"); + maxUsers.addOption("40", "40"); + maxUsers.addOption("50", "50"); + maxUsers.addOption(LocaleUtils.getLocalizedString("muc.form.conf.none", preferredLocale), "0"); + + final FormField broadcast = configurationForm.addField( + "muc#roomconfig_presencebroadcast", + LocaleUtils.getLocalizedString("muc.form.conf.owner_presencebroadcast", preferredLocale), + Type.list_multi); + broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator", preferredLocale), "moderator"); + broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.participant", preferredLocale), "participant"); + broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.visitor", preferredLocale), "visitor"); + + configurationForm.addField("muc#roomconfig_publicroom", + LocaleUtils.getLocalizedString("muc.form.conf.owner_publicroom", preferredLocale), + Type.boolean_type); + + configurationForm.addField("muc#roomconfig_persistentroom", + LocaleUtils.getLocalizedString("muc.form.conf.owner_persistentroom", preferredLocale), + Type.boolean_type); + + configurationForm.addField("muc#roomconfig_moderatedroom", + LocaleUtils.getLocalizedString("muc.form.conf.owner_moderatedroom", preferredLocale), + Type.boolean_type); + + configurationForm.addField("muc#roomconfig_membersonly", + LocaleUtils.getLocalizedString("muc.form.conf.owner_membersonly", preferredLocale), + Type.boolean_type); + + configurationForm.addField(null, null, Type.fixed) + .addValue(LocaleUtils.getLocalizedString("muc.form.conf.allowinvitesfixed", preferredLocale)); + + configurationForm.addField("muc#roomconfig_allowinvites", + LocaleUtils.getLocalizedString("muc.form.conf.owner_allowinvites", preferredLocale), + Type.boolean_type); + + configurationForm.addField("muc#roomconfig_passwordprotectedroom", + LocaleUtils.getLocalizedString("muc.form.conf.owner_passwordprotectedroom", preferredLocale), + Type.boolean_type); + + configurationForm.addField(null, null, Type.fixed) + .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomsecretfixed", preferredLocale)); + + configurationForm.addField("muc#roomconfig_roomsecret", + LocaleUtils.getLocalizedString("muc.form.conf.owner_roomsecret", preferredLocale), + Type.text_private); + + final FormField whois = configurationForm.addField( + "muc#roomconfig_whois", + LocaleUtils.getLocalizedString("muc.form.conf.owner_whois", preferredLocale), + Type.list_single); + whois.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator", preferredLocale), "moderators"); + whois.addOption(LocaleUtils.getLocalizedString("muc.form.conf.anyone", preferredLocale), "anyone"); + + final FormField allowpm = configurationForm.addField( + "muc#roomconfig_allowpm", + LocaleUtils.getLocalizedString("muc.form.conf.owner_allowpm", preferredLocale), + Type.list_single); + allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.anyone", preferredLocale), "anyone"); + allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator", preferredLocale), "moderators"); + allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.participant", preferredLocale), "participants"); + allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.none", preferredLocale), "none"); + + configurationForm.addField("muc#roomconfig_enablelogging", + LocaleUtils.getLocalizedString("muc.form.conf.owner_enablelogging", preferredLocale), + Type.boolean_type); + + configurationForm.addField("x-muc#roomconfig_reservednick", + LocaleUtils.getLocalizedString("muc.form.conf.owner_reservednick", preferredLocale), + Type.boolean_type); + + configurationForm.addField("x-muc#roomconfig_canchangenick", + LocaleUtils.getLocalizedString("muc.form.conf.owner_canchangenick", preferredLocale), + Type.boolean_type); + + configurationForm.addField(null, null, Type.fixed) + .addValue(LocaleUtils.getLocalizedString("muc.form.conf.owner_registration", preferredLocale)); + + configurationForm.addField("x-muc#roomconfig_registration", + LocaleUtils.getLocalizedString("muc.form.conf.owner_registration", preferredLocale), + Type.boolean_type); + + configurationForm.addField(null, null, Type.fixed) + .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomadminsfixed", preferredLocale)); + + configurationForm.addField("muc#roomconfig_roomadmins", + LocaleUtils.getLocalizedString("muc.form.conf.owner_roomadmins", preferredLocale), + Type.jid_multi); + + configurationForm.addField(null, null, Type.fixed) + .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomownersfixed", preferredLocale)); + + configurationForm.addField("muc#roomconfig_roomowners", + LocaleUtils.getLocalizedString("muc.form.conf.owner_roomowners", preferredLocale), + Type.jid_multi); + + // Add room-specific data values to the form. synchronized (room) { FormField field = configurationForm.getField("muc#roomconfig_roomname"); field.clearValues(); @@ -582,145 +705,12 @@ private void refreshConfigurationFormValues() { field.addValue(jid.toString()); } } - - // Remove the old element - probeResult.remove(probeResult.element(QName.get("x", "jabber:x:data"))); - // Add the new representation of configurationForm as an element - probeResult.add(configurationForm.getElement()); - } - } - - private void init() { - Element element = DocumentHelper.createElement(QName.get("query", - "http://jabber.org/protocol/muc#owner")); - - configurationForm = new DataForm(DataForm.Type.form); - configurationForm.setTitle(LocaleUtils.getLocalizedString("muc.form.conf.title")); - List params = new ArrayList<>(); - params.add(room.getName()); - configurationForm.addInstruction(LocaleUtils.getLocalizedString("muc.form.conf.instruction", params)); - - configurationForm.addField("FORM_TYPE", null, Type.hidden) - .addValue("http://jabber.org/protocol/muc#roomconfig"); - - configurationForm.addField("muc#roomconfig_roomname", - LocaleUtils.getLocalizedString("muc.form.conf.owner_roomname"), - Type.text_single); - - configurationForm.addField("muc#roomconfig_roomdesc", - LocaleUtils.getLocalizedString("muc.form.conf.owner_roomdesc"), - Type.text_single); - - configurationForm.addField("muc#roomconfig_changesubject", - LocaleUtils.getLocalizedString("muc.form.conf.owner_changesubject"), - Type.boolean_type); - - final FormField maxUsers = configurationForm.addField( - "muc#roomconfig_maxusers", - LocaleUtils.getLocalizedString("muc.form.conf.owner_maxusers"), - Type.list_single); - maxUsers.addOption("10", "10"); - maxUsers.addOption("20", "20"); - maxUsers.addOption("30", "30"); - maxUsers.addOption("40", "40"); - maxUsers.addOption("50", "50"); - maxUsers.addOption(LocaleUtils.getLocalizedString("muc.form.conf.none"), "0"); - - final FormField broadcast = configurationForm.addField( - "muc#roomconfig_presencebroadcast", - LocaleUtils.getLocalizedString("muc.form.conf.owner_presencebroadcast"), - Type.list_multi); - broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator"), "moderator"); - broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.participant"), "participant"); - broadcast.addOption(LocaleUtils.getLocalizedString("muc.form.conf.visitor"), "visitor"); - - configurationForm.addField("muc#roomconfig_publicroom", - LocaleUtils.getLocalizedString("muc.form.conf.owner_publicroom"), - Type.boolean_type); - - configurationForm.addField("muc#roomconfig_persistentroom", - LocaleUtils.getLocalizedString("muc.form.conf.owner_persistentroom"), - Type.boolean_type); - - configurationForm.addField("muc#roomconfig_moderatedroom", - LocaleUtils.getLocalizedString("muc.form.conf.owner_moderatedroom"), - Type.boolean_type); - - configurationForm.addField("muc#roomconfig_membersonly", - LocaleUtils.getLocalizedString("muc.form.conf.owner_membersonly"), - Type.boolean_type); - - configurationForm.addField(null, null, Type.fixed) - .addValue(LocaleUtils.getLocalizedString("muc.form.conf.allowinvitesfixed")); - - configurationForm.addField("muc#roomconfig_allowinvites", - LocaleUtils.getLocalizedString("muc.form.conf.owner_allowinvites"), - Type.boolean_type); - - configurationForm.addField("muc#roomconfig_passwordprotectedroom", - LocaleUtils.getLocalizedString("muc.form.conf.owner_passwordprotectedroom"), - Type.boolean_type); - - configurationForm.addField(null, null, Type.fixed) - .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomsecretfixed")); - - configurationForm.addField("muc#roomconfig_roomsecret", - LocaleUtils.getLocalizedString("muc.form.conf.owner_roomsecret"), - Type.text_private); - - final FormField whois = configurationForm.addField( - "muc#roomconfig_whois", - LocaleUtils.getLocalizedString("muc.form.conf.owner_whois"), - Type.list_single); - whois.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator"), "moderators"); - whois.addOption(LocaleUtils.getLocalizedString("muc.form.conf.anyone"), "anyone"); - - final FormField allowpm = configurationForm.addField( - "muc#roomconfig_allowpm", - LocaleUtils.getLocalizedString("muc.form.conf.owner_allowpm"), - Type.list_single); - allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.anyone"), "anyone"); - allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.moderator"), "moderators"); - allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.participant"), "participants"); - allowpm.addOption(LocaleUtils.getLocalizedString("muc.form.conf.none"), "none"); - - configurationForm.addField("muc#roomconfig_enablelogging", - LocaleUtils.getLocalizedString("muc.form.conf.owner_enablelogging"), - Type.boolean_type); - - configurationForm.addField("x-muc#roomconfig_reservednick", - LocaleUtils.getLocalizedString("muc.form.conf.owner_reservednick"), - Type.boolean_type); - - configurationForm.addField("x-muc#roomconfig_canchangenick", - LocaleUtils.getLocalizedString("muc.form.conf.owner_canchangenick"), - Type.boolean_type); - - configurationForm.addField(null, null, Type.fixed) - .addValue(LocaleUtils.getLocalizedString("muc.form.conf.owner_registration")); - - configurationForm.addField("x-muc#roomconfig_registration", - LocaleUtils.getLocalizedString("muc.form.conf.owner_registration"), - Type.boolean_type); - - configurationForm.addField(null, null, Type.fixed) - .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomadminsfixed")); - - configurationForm.addField("muc#roomconfig_roomadmins", - LocaleUtils.getLocalizedString("muc.form.conf.owner_roomadmins"), - Type.jid_multi); - - configurationForm.addField(null, null, Type.fixed) - .addValue(LocaleUtils.getLocalizedString("muc.form.conf.roomownersfixed")); - - configurationForm.addField("muc#roomconfig_roomowners", - LocaleUtils.getLocalizedString("muc.form.conf.owner_roomowners"), - Type.jid_multi); - // Create the probeResult and add the basic info together with the configuration form - probeResult = element; - probeResult.add(configurationForm.getElement()); + final Element element = DocumentHelper.createElement(QName.get("query", + "http://jabber.org/protocol/muc#owner")); + element.add(configurationForm.getElement()); + return element; } /** diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java index ebad06ebb1..71e0628413 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Jive Software, 2021-2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2004-2008 Jive Software, 2021-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,7 @@ import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.QName; -import org.jivesoftware.openfire.PacketException; -import org.jivesoftware.openfire.RoutingTable; -import org.jivesoftware.openfire.XMPPServer; -import org.jivesoftware.openfire.XMPPServerListener; +import org.jivesoftware.openfire.*; import org.jivesoftware.openfire.archive.Archiver; import org.jivesoftware.openfire.auth.UnauthorizedException; import org.jivesoftware.openfire.cluster.ClusterEventListener; @@ -2969,6 +2966,9 @@ public Set getExtendedInfos(String name, String node, JID senderJID) { // Answer the extended info of a given room final MUCRoom room = getChatRoom(name); if (room != null) { + + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(senderJID); + final DataForm dataForm = new DataForm(Type.result); final FormField fieldType = dataForm.addField(); @@ -2979,19 +2979,19 @@ public Set getExtendedInfos(String name, String node, JID senderJID) { final FormField fieldDescr = dataForm.addField(); fieldDescr.setVariable("muc#roominfo_description"); fieldDescr.setType(FormField.Type.text_single); - fieldDescr.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.desc")); + fieldDescr.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.desc", preferredLocale)); fieldDescr.addValue(room.getDescription()); final FormField fieldSubj = dataForm.addField(); fieldSubj.setVariable("muc#roominfo_subject"); fieldSubj.setType(FormField.Type.text_single); - fieldSubj.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.subject")); + fieldSubj.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.subject", preferredLocale)); fieldSubj.addValue(room.getSubject()); final FormField fieldOcc = dataForm.addField(); fieldOcc.setVariable("muc#roominfo_occupants"); fieldOcc.setType(FormField.Type.text_single); - fieldOcc.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.occupants")); + fieldOcc.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.occupants", preferredLocale)); fieldOcc.addValue(Integer.toString(room.getOccupantsCount())); /*field = new XFormFieldImpl("muc#roominfo_lang"); @@ -3003,7 +3003,7 @@ public Set getExtendedInfos(String name, String node, JID senderJID) { final FormField fieldDate = dataForm.addField(); fieldDate.setVariable("x-muc#roominfo_creationdate"); fieldDate.setType(FormField.Type.text_single); - fieldDate.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.creationdate")); + fieldDate.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.creationdate", preferredLocale)); fieldDate.addValue(XMPPDateTimeFormat.format(room.getCreationDate())); final Set dataForms = new HashSet<>(); dataForms.add(dataForm); diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pep/IQPEPHandler.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pep/IQPEPHandler.java index 8014e3f748..4bf86ef364 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pep/IQPEPHandler.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pep/IQPEPHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software, 2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2022-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import org.dom4j.QName; import org.jivesoftware.openfire.IQHandlerInfo; import org.jivesoftware.openfire.JMXManager; +import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.disco.*; import org.jivesoftware.openfire.event.UserEventDispatcher; @@ -810,11 +811,12 @@ public Set getExtendedInfos(String name, String node, JID senderJID) { JID recipientJID = XMPPServer.getInstance().createJID(name, null, true).asBareJID(); PEPService pepService = pepServiceManager.getPEPService(recipientJID); if (node != null) { + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(senderJID); // Answer the extended info of a given node Node pubNode = pepService.getNode(node); // Get the metadata data form final Set dataForms = new HashSet<>(); - dataForms.add(pubNode.getMetadataForm()); + dataForms.add(pubNode.getMetadataForm(preferredLocale)); return dataForms; } return new HashSet<>(); diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/CollectionNode.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/CollectionNode.java index edb8a1de07..b701098352 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/CollectionNode.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/CollectionNode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,16 +16,6 @@ package org.jivesoftware.openfire.pubsub; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.dom4j.Element; import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.pep.PEPService; @@ -41,6 +31,12 @@ import org.xmpp.packet.JID; import org.xmpp.packet.Message; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + /** * A type of node that contains nodes and/or other collections but no published * items. Collections provide the foundation entity to provide a means of representing @@ -156,8 +152,8 @@ void postConfigure(DataForm completedForm) { } @Override - protected void addFormFields(DataForm form, boolean isEditing) { - super.addFormFields(form, isEditing); + protected void addFormFields(DataForm form, Locale preferredLocale, boolean isEditing) { + super.addFormFields(form, preferredLocale, isEditing); FormField typeField = form.getField("pubsub#node_type"); typeField.addValue("collection"); @@ -167,10 +163,10 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#leaf_node_association_policy"); if (isEditing) { formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy")); - formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.all"), LeafNodeAssociationPolicy.all.name()); - formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.owners"), LeafNodeAssociationPolicy.owners.name()); - formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.whitelist"), LeafNodeAssociationPolicy.whitelist.name()); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy", preferredLocale)); + formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.all", preferredLocale), LeafNodeAssociationPolicy.all.name()); + formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.owners", preferredLocale), LeafNodeAssociationPolicy.owners.name()); + formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.whitelist", preferredLocale), LeafNodeAssociationPolicy.whitelist.name()); } formField.addValue(associationPolicy.name()); @@ -178,10 +174,10 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#children_association_policy"); if (isEditing) { formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy")); - formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.all"), LeafNodeAssociationPolicy.all.name()); - formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.owners"), LeafNodeAssociationPolicy.owners.name()); - formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.whitelist"), LeafNodeAssociationPolicy.whitelist.name()); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy", preferredLocale)); + formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.all", preferredLocale), LeafNodeAssociationPolicy.all.name()); + formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.owners", preferredLocale), LeafNodeAssociationPolicy.owners.name()); + formField.addOption(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_policy.whitelist", preferredLocale), LeafNodeAssociationPolicy.whitelist.name()); } formField.addValue(associationPolicy.name()); @@ -190,7 +186,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#leaf_node_association_whitelist"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_whitelist")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_whitelist", preferredLocale)); } for (JID contact : associationTrusted) { formField.addValue(contact.toString()); @@ -200,7 +196,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#children_association_whitelist"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_whitelist")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_association_whitelist", preferredLocale)); } for (JID contact : associationTrusted) { formField.addValue(contact.toString()); @@ -210,7 +206,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#leaf_nodes_max"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_max")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_max", preferredLocale)); } formField.addValue(maxLeafNodes); @@ -218,7 +214,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#children_max"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_max")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children_max", preferredLocale)); } formField.addValue(maxLeafNodes); @@ -226,7 +222,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#children"); if (isEditing) { formField.setType(FormField.Type.text_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.children", preferredLocale)); } for (Node.UniqueIdentifier nodeId : nodes.keySet()) { formField.addValue(nodeId.getNodeId()); @@ -272,7 +268,7 @@ void childNodeAdded(Node child) { Element item = items.addElement("item"); item.addAttribute("id", child.getUniqueIdentifier().getNodeId()); if (deliverPayloads) { - item.add(child.getMetadataForm().getElement()); + item.add(child.getMetadataForm(null).getElement()); // FIXME: figure out a way to have proper localization. } // Broadcast event notification to subscribers broadcastCollectionNodeEvent(child, message); diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/DefaultNodeConfiguration.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/DefaultNodeConfiguration.java index d6d2674a24..67616e8f96 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/DefaultNodeConfiguration.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/DefaultNodeConfiguration.java @@ -16,15 +16,17 @@ package org.jivesoftware.openfire.pubsub; -import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.openfire.pubsub.models.AccessModel; import org.jivesoftware.openfire.pubsub.models.PublisherModel; +import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.cache.CacheSizes; import org.jivesoftware.util.cache.Cacheable; import org.jivesoftware.util.cache.CannotCalculateSizeException; import org.xmpp.forms.DataForm; import org.xmpp.forms.FormField; +import java.util.Locale; + /** * A DefaultNodeConfiguration keeps the default configuration values for leaf or collection * nodes of a particular publish-subscribe service. New nodes created for the service @@ -433,10 +435,10 @@ public void setMaxLeafNodes(int maxLeafNodes) { } - public DataForm getConfigurationForm() { + public DataForm getConfigurationForm(Locale preferredLocale) { DataForm form = new DataForm(DataForm.Type.form); - form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.default.title")); - form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.default.instruction")); + form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.default.title", preferredLocale)); + form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.default.instruction", preferredLocale)); // Add the form fields and configure them for edition FormField formField = form.addField(); @@ -447,37 +449,37 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#subscribe"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.subscribe")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.subscribe", preferredLocale)); formField.addValue(subscriptionEnabled); formField = form.addField(); formField.setVariable("pubsub#deliver_payloads"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.deliver_payloads")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.deliver_payloads", preferredLocale)); formField.addValue(deliverPayloads); formField = form.addField(); formField.setVariable("pubsub#notify_config"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_config")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_config", preferredLocale)); formField.addValue(notifyConfigChanges); formField = form.addField(); formField.setVariable("pubsub#notify_delete"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_delete")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_delete", preferredLocale)); formField.addValue(notifyDelete); formField = form.addField(); formField.setVariable("pubsub#notify_retract"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_retract")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_retract", preferredLocale)); formField.addValue(notifyRetract); formField = form.addField(); formField.setVariable("pubsub#presence_based_delivery"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.presence_based")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.presence_based", preferredLocale)); formField.addValue(presenceBasedDelivery); if (leaf) { @@ -485,32 +487,32 @@ public DataForm getConfigurationForm() { formField.setVariable("pubsub#send_item_subscribe"); formField.setType(FormField.Type.boolean_type); formField.setLabel( - LocaleUtils.getLocalizedString("pubsub.form.conf.send_item_subscribe")); + LocaleUtils.getLocalizedString("pubsub.form.conf.send_item_subscribe", preferredLocale)); formField.addValue(sendItemSubscribe); formField = form.addField(); formField.setVariable("pubsub#persist_items"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.persist_items")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.persist_items", preferredLocale)); formField.addValue(persistPublishedItems); formField = form.addField(); formField.setVariable("pubsub#max_items"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_items")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_items", preferredLocale)); formField.addValue(maxPublishedItems); formField = form.addField(); formField.setVariable("pubsub#max_payload_size"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_payload_size")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_payload_size", preferredLocale)); formField.addValue(maxPayloadSize); } formField = form.addField(); formField.setVariable("pubsub#access_model"); formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.access_model")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.access_model", preferredLocale)); formField.addOption(null, AccessModel.authorize.getName()); formField.addOption(null, AccessModel.open.getName()); formField.addOption(null, AccessModel.presence.getName()); @@ -521,7 +523,7 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#publish_model"); formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.publish_model")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.publish_model", preferredLocale)); formField.addOption(null, PublisherModel.publishers.getName()); formField.addOption(null, PublisherModel.subscribers.getName()); formField.addOption(null, PublisherModel.open.getName()); @@ -530,13 +532,13 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#language"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.language")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.language", preferredLocale)); formField.addValue(language); formField = form.addField(); formField.setVariable("pubsub#itemreply"); formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.itemreply")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.itemreply", preferredLocale)); if (replyPolicy != null) { formField.addValue(replyPolicy.name()); } @@ -545,7 +547,7 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#leaf_node_association_policy"); formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.leaf_node_association")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.leaf_node_association", preferredLocale)); formField.addOption(null, CollectionNode.LeafNodeAssociationPolicy.all.name()); formField.addOption(null, CollectionNode.LeafNodeAssociationPolicy.owners.name()); formField.addOption(null, CollectionNode.LeafNodeAssociationPolicy.whitelist.name()); @@ -554,7 +556,7 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#leaf_nodes_max"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.leaf_nodes_max")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.leaf_nodes_max", preferredLocale)); formField.addValue(maxLeafNodes); } diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/LeafNode.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/LeafNode.java index fda744cc2a..4ac9b46a9e 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/LeafNode.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/LeafNode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software, 2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2022-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,6 @@ package org.jivesoftware.openfire.pubsub; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.*; - import org.dom4j.Element; import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.XMPPServer; @@ -39,6 +34,11 @@ import org.xmpp.packet.JID; import org.xmpp.packet.Message; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.*; + import static org.jivesoftware.openfire.muc.spi.IQOwnerHandler.parseFirstValueAsBoolean; /** @@ -126,8 +126,8 @@ void postConfigure(DataForm completedForm) { } @Override - protected void addFormFields(DataForm form, boolean isEditing) { - super.addFormFields(form, isEditing); + protected void addFormFields(DataForm form, Locale preferredLocale, boolean isEditing) { + super.addFormFields(form, preferredLocale, isEditing); FormField typeField = form.getField("pubsub#node_type"); typeField.addValue("leaf"); @@ -137,7 +137,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { if (isEditing) { formField.setType(FormField.Type.boolean_type); formField.setLabel( - LocaleUtils.getLocalizedString("pubsub.form.conf.send_item_subscribe")); + LocaleUtils.getLocalizedString("pubsub.form.conf.send_item_subscribe", preferredLocale)); } formField.addValue(sendItemSubscribe); @@ -145,7 +145,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#persist_items"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.persist_items")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.persist_items", preferredLocale)); } formField.addValue(persistPublishedItems); @@ -153,7 +153,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#max_items"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_items")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_items", preferredLocale)); } formField.addValue(maxPublishedItems); @@ -161,7 +161,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#max_payload_size"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_payload_size")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.max_payload_size", preferredLocale)); } formField.addValue(maxPayloadSize); diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/Node.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/Node.java index 20078c6d2a..81130942c2 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/Node.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/Node.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,6 @@ package org.jivesoftware.openfire.pubsub; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.stream.Collectors; - import org.dom4j.Element; import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.XMPPServer; @@ -39,9 +34,13 @@ import org.xmpp.packet.Message; import org.xmpp.packet.PacketError; -import static org.jivesoftware.openfire.muc.spi.IQOwnerHandler.parseFirstValueAsBoolean; - import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; + +import static org.jivesoftware.openfire.muc.spi.IQOwnerHandler.parseFirstValueAsBoolean; /** * A virtual location to which information can be published and from which event @@ -781,7 +780,7 @@ private void nodeConfigurationChanged() { config.addAttribute("node", nodeID); if (deliverPayloads) { - config.add(getConfigurationChangeForm().getElement()); + config.add(getConfigurationChangeForm(null).getElement()); // FIXME localize this form for each recipient. } // Send notification that the node configuration has changed broadcastNodeEvent(message, false); @@ -800,11 +799,10 @@ private void nodeConfigurationChanged() { * @param subscription the new subscription that needs to be approved. * @return the data form to be included in the authorization request. */ - DataForm getAuthRequestForm(NodeSubscription subscription) { + DataForm getAuthRequestForm(NodeSubscription subscription, Locale preferredLocale) { DataForm form = new DataForm(DataForm.Type.form); - form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.authorization.title")); - form.addInstruction( - LocaleUtils.getLocalizedString("pubsub.form.authorization.instruction")); + form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.authorization.title", preferredLocale)); + form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.authorization.instruction", preferredLocale)); FormField formField = form.addField(); formField.setVariable("FORM_TYPE"); @@ -819,19 +817,19 @@ DataForm getAuthRequestForm(NodeSubscription subscription) { formField = form.addField(); formField.setVariable("pubsub#node"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.authorization.node")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.authorization.node", preferredLocale)); formField.addValue(nodeID); formField = form.addField(); formField.setVariable("pubsub#subscriber_jid"); formField.setType(FormField.Type.jid_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.authorization.subscriber")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.authorization.subscriber", preferredLocale)); formField.addValue(subscription.getJID().toString()); formField = form.addField(); formField.setVariable("pubsub#allow"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.authorization.allow")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.authorization.allow", preferredLocale)); formField.addValue(Boolean.FALSE); return form; @@ -841,14 +839,15 @@ DataForm getAuthRequestForm(NodeSubscription subscription) { /** * Returns a data form used by the owner to edit the node configuration. * + * @param preferredLocale The preferred locale to localize the form. * @return data form used by the owner to edit the node configuration. */ - public DataForm getConfigurationForm() { + public DataForm getConfigurationForm(Locale preferredLocale) { DataForm form = new DataForm(DataForm.Type.form); - form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.conf.title")); + form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.conf.title", preferredLocale)); List params = new ArrayList<>(); params.add(nodeID); - form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.conf.instruction", params)); + form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.conf.instruction", params, preferredLocale)); FormField formField = form.addField(); formField.setVariable("FORM_TYPE"); @@ -856,25 +855,26 @@ public DataForm getConfigurationForm() { formField.addValue("http://jabber.org/protocol/pubsub#node_config"); // Add the form fields and configure them for edition - addFormFields(form, true); + addFormFields(form, preferredLocale, true); return form; } /** * Adds the required form fields to the specified form. When editing is true the field type - * and a label is included in each fields. The form being completed will contain the current - * node configuration. This information can be used for editing the node or for notifing that + * and a label is included in each field. The form being completed will contain the current + * node configuration. This information can be used for editing the node or for notifying that * the node configuration has changed. * * @param form the form containing the node configuration. + * @param preferredLocale the preferred locale to localize the form. * @param isEditing true when the form will be used to edit the node configuration. */ - protected void addFormFields(DataForm form, boolean isEditing) { + protected void addFormFields(DataForm form, Locale preferredLocale, boolean isEditing) { FormField formField = form.addField(); formField.setVariable("pubsub#title"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.short_name")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.short_name", preferredLocale)); } formField.addValue(name); @@ -882,7 +882,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#description"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.description")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.description", preferredLocale)); } formField.addValue(description); @@ -890,14 +890,14 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#node_type"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.node_type")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.node_type", preferredLocale)); } formField = form.addField(); formField.setVariable("pubsub#collection"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.collection")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.collection", preferredLocale)); } final CollectionNode parent = getParent(); @@ -909,7 +909,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#subscribe"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.subscribe")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.subscribe", preferredLocale)); } formField.addValue(subscriptionEnabled); @@ -918,7 +918,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { // TODO Replace this variable for the one defined in the JEP (once one is defined) if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.subscription_required")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.subscription_required", preferredLocale)); } formField.addValue(subscriptionConfigurationRequired); @@ -926,7 +926,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#deliver_payloads"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.deliver_payloads")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.deliver_payloads", preferredLocale)); } formField.addValue(deliverPayloads); @@ -934,7 +934,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#notify_config"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_config")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_config", preferredLocale)); } formField.addValue(notifyConfigChanges); @@ -942,7 +942,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#notify_delete"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_delete")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_delete", preferredLocale)); } formField.addValue(notifyDelete); @@ -950,7 +950,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#notify_retract"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_retract")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.notify_retract", preferredLocale)); } formField.addValue(notifyRetract); @@ -958,7 +958,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#presence_based_delivery"); if (isEditing) { formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.presence_based")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.presence_based", preferredLocale)); } formField.addValue(presenceBasedDelivery); @@ -966,7 +966,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#type"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.type")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.type", preferredLocale)); } formField.addValue(payloadType); @@ -974,7 +974,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#body_xslt"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.body_xslt")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.body_xslt", preferredLocale)); } formField.addValue(bodyXSLT); @@ -982,7 +982,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#dataform_xslt"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.dataform_xslt")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.dataform_xslt", preferredLocale)); } formField.addValue(dataformXSLT); @@ -990,7 +990,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#access_model"); if (isEditing) { formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.access_model")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.access_model", preferredLocale)); formField.addOption(null, AccessModel.authorize.getName()); formField.addOption(null, AccessModel.open.getName()); formField.addOption(null, AccessModel.presence.getName()); @@ -1003,7 +1003,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#publish_model"); if (isEditing) { formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.publish_model")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.publish_model", preferredLocale)); formField.addOption(null, PublisherModel.publishers.getName()); formField.addOption(null, PublisherModel.subscribers.getName()); formField.addOption(null, PublisherModel.open.getName()); @@ -1014,7 +1014,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#roster_groups_allowed"); if (isEditing) { formField.setType(FormField.Type.list_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.roster_allowed")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.roster_allowed", preferredLocale)); } for (String group : rosterGroupsAllowed) { formField.addValue(group); @@ -1024,7 +1024,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#contact"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.contact")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.contact", preferredLocale)); } for (JID contact : contacts) { formField.addValue(contact.toString()); @@ -1034,7 +1034,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#language"); if (isEditing) { formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.language")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.language", preferredLocale)); } formField.addValue(language); @@ -1042,7 +1042,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#owner"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.owner")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.owner", preferredLocale)); } for (JID owner : getOwners()) { formField.addValue(owner.toString()); @@ -1052,7 +1052,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#publisher"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.publisher")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.publisher", preferredLocale)); } for (JID owner : getPublishers()) { formField.addValue(owner.toString()); @@ -1062,7 +1062,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#itemreply"); if (isEditing) { formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.itemreply")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.itemreply", preferredLocale)); formField.addOption(null, ItemReplyPolicy.owner.name()); formField.addOption(null, ItemReplyPolicy.publisher.name()); } @@ -1074,7 +1074,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#replyroom"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.replyroom")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.replyroom", preferredLocale)); } for (JID owner : getReplyRooms()) { formField.addValue(owner.toString()); @@ -1084,7 +1084,7 @@ protected void addFormFields(DataForm form, boolean isEditing) { formField.setVariable("pubsub#replyto"); if (isEditing) { formField.setType(FormField.Type.jid_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.replyto")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.conf.replyto", preferredLocale)); } for (JID owner : getReplyTo()) { formField.addValue(owner.toString()); @@ -1094,12 +1094,13 @@ protected void addFormFields(DataForm form, boolean isEditing) { /** * Returns a data form with the node configuration. The returned data form is used for * notifying node subscribers that the node configuration has changed. The data form is - * ony going to be included if node is configure to include payloads in event + * ony going to be included if node is configured to include payloads in event * notifications. * + * @param preferredLocale The preferred locale to localize the form * @return a data form with the node configuration. */ - private DataForm getConfigurationChangeForm() { + private DataForm getConfigurationChangeForm(Locale preferredLocale) { DataForm form = new DataForm(DataForm.Type.result); FormField formField = form.addField(); formField.setVariable("FORM_TYPE"); @@ -1107,7 +1108,7 @@ private DataForm getConfigurationChangeForm() { formField.addValue("http://jabber.org/protocol/pubsub#node_config"); // Add the form fields and configure them for notification // (i.e. no label or options are included) - addFormFields(form, false); + addFormFields(form, preferredLocale, false); return form; } @@ -1115,16 +1116,17 @@ private DataForm getConfigurationChangeForm() { * Returns a data form containing the node configuration that is going to be used for * service discovery. * + * @param preferredLocale The preferred locale to localize the form. * @return a data form with the node configuration. */ - public DataForm getMetadataForm() { + public DataForm getMetadataForm(Locale preferredLocale) { DataForm form = new DataForm(DataForm.Type.result); FormField formField = form.addField(); formField.setVariable("FORM_TYPE"); formField.setType(FormField.Type.hidden); formField.addValue("http://jabber.org/protocol/pubsub#meta-data"); // Add the form fields - addFormFields(form, true); + addFormFields(form, preferredLocale, true); return form; } diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/NodeSubscription.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/NodeSubscription.java index 54dc2dd3f1..8189bd2475 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/NodeSubscription.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/NodeSubscription.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,8 @@ package org.jivesoftware.openfire.pubsub; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; - import org.dom4j.Element; +import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.LocaleUtils; @@ -37,6 +31,9 @@ import org.xmpp.packet.Message; import org.xmpp.packet.Presence; +import java.text.ParseException; +import java.util.*; + import static org.jivesoftware.openfire.muc.spi.IQOwnerHandler.parseFirstValueAsBoolean; /** @@ -506,14 +503,15 @@ else if ("x-pubsub#keywords".equals(field.getVariable())) { * Returns a data form with the subscription configuration. The data form can be used to * edit the subscription configuration. * + * @param preferredLocale The preferred locale to localize the form. * @return data form used by the subscriber to edit the subscription configuration. */ - public DataForm getConfigurationForm() { + public DataForm getConfigurationForm(Locale preferredLocale) { DataForm form = new DataForm(DataForm.Type.form); - form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.subscription.title")); + form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.subscription.title", preferredLocale)); List params = new ArrayList<>(); params.add(node.getUniqueIdentifier().getNodeId()); - form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.subscription.instruction", params)); + form.addInstruction(LocaleUtils.getLocalizedString("pubsub.form.subscription.instruction", params, preferredLocale)); // Add the form fields and configure them for edition FormField formField = form.addField(); formField.setVariable("FORM_TYPE"); @@ -523,25 +521,25 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#deliver"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.deliver")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.deliver", preferredLocale)); formField.addValue(deliverNotifications); formField = form.addField(); formField.setVariable("pubsub#digest"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.digest")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.digest", preferredLocale)); formField.addValue(usingDigest); formField = form.addField(); formField.setVariable("pubsub#digest_frequency"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.digest_frequency")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.digest_frequency", preferredLocale)); formField.addValue(digestFrequency); formField = form.addField(); formField.setVariable("pubsub#expire"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.expire")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.expire", preferredLocale)); if (expire != null) { formField.addValue(XMPPDateTimeFormat.format(expire)); } @@ -549,13 +547,13 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#include_body"); formField.setType(FormField.Type.boolean_type); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.include_body")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.include_body", preferredLocale)); formField.addValue(includingBody); formField = form.addField(); formField.setVariable("pubsub#show-values"); formField.setType(FormField.Type.list_multi); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.show-values")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.show-values", preferredLocale)); formField.addOption(null, Presence.Show.away.name()); formField.addOption(null, Presence.Show.chat.name()); formField.addOption(null, Presence.Show.dnd.name()); @@ -569,7 +567,7 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#subscription_type"); formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.subscription_type")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.subscription_type", preferredLocale)); formField.addOption(null, Type.items.name()); formField.addOption(null, Type.nodes.name()); formField.addValue(type); @@ -577,7 +575,7 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("pubsub#subscription_depth"); formField.setType(FormField.Type.list_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.subscription_depth")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.subscription_depth", preferredLocale)); formField.addOption(null, "1"); formField.addOption(null, "all"); formField.addValue(depth == 1 ? "1" : "all"); @@ -587,7 +585,7 @@ public DataForm getConfigurationForm() { formField = form.addField(); formField.setVariable("x-pubsub#keywords"); formField.setType(FormField.Type.text_single); - formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.keywords")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.form.subscription.keywords", preferredLocale)); if (keyword != null) { formField.addValue(keyword); } @@ -812,7 +810,8 @@ void sendLastPublishedItem(PublishedItem publishedItem) { } // Add a message body (if required) if (isIncludingBody()) { - notification.setBody(LocaleUtils.getLocalizedString("pubsub.notification.message.body")); + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(jid); + notification.setBody(LocaleUtils.getLocalizedString("pubsub.notification.message.body", preferredLocale)); } // Include date when published item was created notification.getElement().addElement("delay", "urn:xmpp:delay") @@ -875,13 +874,14 @@ void approved() { } /** - * Sends an request to authorize the pending subscription to the specified owner. + * Sends a request to authorize the pending subscription to the specified owner. * * @param owner the JID of the user that will get the authorization request. */ public void sendAuthorizationRequest(JID owner) { + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(owner); Message authRequest = new Message(); - authRequest.addExtension(node.getAuthRequestForm(this)); + authRequest.addExtension(node.getAuthRequestForm(this, preferredLocale)); authRequest.setTo(owner); authRequest.setFrom(node.getService().getAddress()); // Send authentication request to node owners @@ -893,10 +893,9 @@ public void sendAuthorizationRequest(JID owner) { * answer sent by a owner will be processed. Rest of the answers will be discarded. */ public void sendAuthorizationRequest() { - Message authRequest = new Message(); - authRequest.addExtension(node.getAuthRequestForm(this)); - // Send authentication request to node owners - node.getService().broadcast(node, authRequest, node.getOwners()); + for (final JID owner : node.getOwners()) { + sendAuthorizationRequest(owner); + } } /** diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PendingSubscriptionsCommand.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PendingSubscriptionsCommand.java index 1f683ef5d0..91e38637c5 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PendingSubscriptionsCommand.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PendingSubscriptionsCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.jivesoftware.openfire.pubsub; import org.dom4j.Element; +import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.commands.AdHocCommand; import org.jivesoftware.openfire.commands.SessionData; import org.jivesoftware.util.LocaleUtils; @@ -26,6 +27,7 @@ import java.util.Collections; import java.util.List; +import java.util.Locale; /** * Ad-hoc command that sends pending subscriptions to node owners. @@ -42,16 +44,15 @@ public PendingSubscriptionsCommand(PubSubService service) { @Override protected void addStageInformation(SessionData data, Element command) { + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(data.getOwner()); DataForm form = new DataForm(DataForm.Type.form); - form.setTitle(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.title")); - form.addInstruction( - LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.instruction")); + form.setTitle(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.title", preferredLocale)); + form.addInstruction(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.instruction", preferredLocale)); FormField formField = form.addField(); formField.setVariable("pubsub#node"); formField.setType(FormField.Type.list_single); - formField.setLabel( - LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.node")); + formField.setLabel(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.node", preferredLocale)); for (Node node : service.getNodes()) { if (!node.isCollectionNode() && node.isAdmin(data.getOwner())) { formField.addOption(null, node.getUniqueIdentifier().getNodeId()); @@ -63,27 +64,26 @@ protected void addStageInformation(SessionData data, Element command) { @Override public void execute(SessionData data, Element command) { + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(data.getOwner()); + Element note = command.addElement("note"); List nodeIDs = data.getData().get("pubsub#node"); if (nodeIDs.isEmpty()) { // No nodeID was provided by the requester note.addAttribute("type", "error"); - note.setText(LocaleUtils.getLocalizedString( - "pubsub.command.pending-subscriptions.error.idrequired")); + note.setText(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.error.idrequired", preferredLocale)); } else if (nodeIDs.size() > 1) { // More than one nodeID was provided by the requester note.addAttribute("type", "error"); - note.setText(LocaleUtils.getLocalizedString( - "pubsub.command.pending-subscriptions.error.manyIDs")); + note.setText(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.error.manyIDs", preferredLocale)); } else { Node node = service.getNode(nodeIDs.get(0)); if (node != null) { if (node.isAdmin(data.getOwner())) { note.addAttribute("type", "info"); - note.setText(LocaleUtils.getLocalizedString( - "pubsub.command.pending-subscriptions.success")); + note.setText(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.success", preferredLocale)); for (NodeSubscription subscription : node.getPendingSubscriptions()) { subscription.sendAuthorizationRequest(data.getOwner()); @@ -92,15 +92,13 @@ else if (nodeIDs.size() > 1) { else { // Requester is not an admin of the specified node note.addAttribute("type", "error"); - note.setText(LocaleUtils.getLocalizedString( - "pubsub.command.pending-subscriptions.error.forbidden")); + note.setText(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.error.forbidden", preferredLocale)); } } else { // Node with the specified nodeID was not found note.addAttribute("type", "error"); - note.setText(LocaleUtils.getLocalizedString( - "pubsub.command.pending-subscriptions.error.badid")); + note.setText(LocaleUtils.getLocalizedString("pubsub.command.pending-subscriptions.error.badid", preferredLocale)); } } } diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java index 212ca74646..816db86d3a 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software, 2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2022-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -507,7 +507,7 @@ private boolean nodeMeetsPreconditions( Node node, DataForm preconditions ) return true; } - final DataForm conditions = node.getConfigurationForm(); + final DataForm conditions = node.getConfigurationForm(null); for ( final FormField precondition : preconditions.getFields() ) { if ( precondition.getVariable().equals( "FORM_TYPE" ) ) @@ -933,10 +933,11 @@ private void getSubscriptionConfiguration(PubSubService service, IQ iq, } // Return data form containing subscription configuration to the subscriber + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(iq.getFrom()); IQ reply = IQ.createResultIQ(iq); Element replyChildElement = childElement.createCopy(); reply.setChildElement(replyChildElement); - replyChildElement.element("options").add(subscription.getConfigurationForm().getElement()); + replyChildElement.element("options").add(subscription.getConfigurationForm(preferredLocale).getElement()); router.route(reply); } @@ -1467,10 +1468,12 @@ private void getNodeConfiguration(PubSubService service, IQ iq, Element childEle } // Return data form containing node configuration to the owner + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(iq.getFrom()); + IQ reply = IQ.createResultIQ(iq); Element replyChildElement = childElement.createCopy(); reply.setChildElement(replyChildElement); - replyChildElement.element("configure").add(node.getConfigurationForm().getElement()); + replyChildElement.element("configure").add(node.getConfigurationForm(preferredLocale).getElement()); router.route(reply); } @@ -1491,10 +1494,12 @@ private void getDefaultNodeConfiguration(PubSubService service, IQ iq, } // Return data form containing default node configuration + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(iq.getFrom()); + IQ reply = IQ.createResultIQ(iq); Element replyChildElement = childElement.createCopy(); reply.setChildElement(replyChildElement); - replyChildElement.element("default").add(config.getConfigurationForm().getElement()); + replyChildElement.element("default").add(config.getConfigurationForm(preferredLocale).getElement()); router.route(reply); } diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubModule.java b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubModule.java index e93e33eb9e..9874419f0e 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubModule.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Jive Software, 2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2005-2008 Jive Software, 2022-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,7 @@ import org.dom4j.DocumentHelper; import org.dom4j.Element; -import org.jivesoftware.openfire.PacketRouter; -import org.jivesoftware.openfire.RoutableChannelHandler; -import org.jivesoftware.openfire.RoutingTable; -import org.jivesoftware.openfire.XMPPServer; +import org.jivesoftware.openfire.*; import org.jivesoftware.openfire.commands.AdHocCommandManager; import org.jivesoftware.openfire.component.InternalComponentManager; import org.jivesoftware.openfire.container.BasicModule; @@ -685,7 +682,8 @@ public Set getExtendedInfos(String name, String node, JID senderJID) { Node pubNode = getNode(node); Set dataForms = new HashSet<>(); if (canDiscoverNode(pubNode)) { - dataForms.add(pubNode.getMetadataForm()); + final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(senderJID); + dataForms.add(pubNode.getMetadataForm(preferredLocale)); // Get the metadata data form return dataForms; } diff --git a/xmppserver/src/main/java/org/jivesoftware/util/LocaleUtils.java b/xmppserver/src/main/java/org/jivesoftware/util/LocaleUtils.java index 40e5b83721..2111aea543 100644 --- a/xmppserver/src/main/java/org/jivesoftware/util/LocaleUtils.java +++ b/xmppserver/src/main/java/org/jivesoftware/util/LocaleUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Jive Software, 2022 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2004-2008 Jive Software, 2022-2023 Ignite Realtime Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -369,6 +369,9 @@ public static String getLocalizedString(String key) { * Returns an internationalized string loaded from a resource bundle using * the passed in Locale. * + * If the passed in Locale cannot be used to retrieve a localized string, + * the locale specified by JiveGlobals.getLocale() will be used instead. + * * @param key the key to use for retrieving the string from the * appropriate resource bundle. * @param locale the locale to use for retrieving the appropriate @@ -376,9 +379,21 @@ public static String getLocalizedString(String key) { * @return the localized string. */ public static String getLocalizedString(String key, Locale locale) { - ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale); - - return getLocalizedString(key, locale, null, bundle); + if (locale == null) { + locale = JiveGlobals.getLocale(); + } + ResourceBundle bundle; + try { + bundle = ResourceBundle.getBundle(resourceBaseName, locale); + return getLocalizedString(key, locale, null, bundle); + } catch (MissingResourceException e) { + if (!locale.equals(JiveGlobals.getLocale())) { + return getLocalizedString(key); + } else { + Log.error(e.getMessage()); + return key; + } + } } /** @@ -432,6 +447,39 @@ public static String getLocalizedString(String key, List arguments) { return getLocalizedString(key, locale, arguments, bundle); } + /** + * Returns an internationalized string loaded from a resource bundle + * substituting the passed in arguments. Substitution is handled using + * the {@link java.text.MessageFormat} class. + * + * If the passed in Locale cannot be used to retrieve a localized string, + * the locale specified by JiveGlobals.getLocale() will be used instead. + * + * @param key the key to use for retrieving the string from the + * appropriate resource bundle. + * @param arguments a list of objects to use which are formatted, then + * inserted into the pattern at the appropriate places. + * @param locale the locale to use for retrieving the appropriate + * locale-specific string. + * @return the localized string. + */ + public static String getLocalizedString(String key, List arguments, Locale locale) { + if (locale == null) { + locale = JiveGlobals.getLocale(); + } + try { + ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale); + return getLocalizedString(key, locale, arguments, bundle); + } catch (MissingResourceException e) { + if (!locale.equals(JiveGlobals.getLocale())) { + return getLocalizedString(key, arguments, JiveGlobals.getLocale()); + } else { + Log.error(e.getMessage()); + return key; + } + } + } + /** * Returns an internationalized string loaded from a resource bundle from the passed * in plugin. If the plugin name is {@code null}, the key will be looked up using @@ -459,7 +507,7 @@ public static String getLocalizedString(String key, String pluginName) { * @return the localized string. */ public static String getLocalizedString(String key, String pluginName, List arguments) { - return getLocalizedString(key, pluginName, arguments, null, false); + return getLocalizedString(key, pluginName, arguments, null, true); } /** @@ -485,7 +533,7 @@ public static String getLocalizedString(String key, String pluginName, List argu * locale-specific string. * @param fallback * if {@code true}, the global locale used by Openfire will be - * used if the requested locale is not available) + * used if the requested locale is not available * @return the localized string. */ public static String getLocalizedString(String key, String pluginName, List arguments, Locale locale, boolean fallback) { @@ -515,7 +563,7 @@ public static String getLocalizedString(String key, String pluginName, List a Locale jivesLocale = JiveGlobals.getLocale(); if (fallback && !jivesLocale.equals(locale)) { Log.info("Could not find the requested locale. Falling back to default locale.", mre); - return getLocalizedString(key, pluginName, arguments, jivesLocale, false); + return getLocalizedString(key, pluginName, arguments, jivesLocale, true); } Log.error(mre.getMessage(), mre); @@ -562,7 +610,7 @@ private static String getI18nFile(String pluginName) { * locale-specific string. * @param arguments a list of objects to use which are formatted, then * inserted into the pattern at the appropriate places. - * @param bundle The resource bundle from which to return the localized + * @param bundle The resource bundle from which to return the localized * string. * @return the localized string. */ @@ -580,7 +628,7 @@ public static String getLocalizedString(String key, Locale locale, List argument // See if the bundle has a value try { - // The jdk caches resource bundles on it's own, so we won't bother. + // The jdk caches resource bundles on its own, so we won't bother. value = bundle.getString(key); // perform argument substitutions if (arguments != null) { diff --git a/xmppserver/src/main/webapp/pubsub-node-edit.jsp b/xmppserver/src/main/webapp/pubsub-node-edit.jsp index cbe8ca3439..0f7312be33 100644 --- a/xmppserver/src/main/webapp/pubsub-node-edit.jsp +++ b/xmppserver/src/main/webapp/pubsub-node-edit.jsp @@ -57,7 +57,7 @@ // Load the node object Node node = pubSubServiceInfo.getNode(nodeID); - DataForm form = node.getConfigurationForm(); + DataForm form = node.getConfigurationForm(null); //Field that will not be returned to the server, i.e. cannot be edited on this page ArrayList nonReturnFields = new ArrayList<>();