You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2021/05/04 12:16:19 UTC

[lucenenet] branch master updated (fb04740 -> c15328f)

This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git.


    from fb04740  BREAKING: Changed all GetFilePointer() methods into properties named Position to match FileStream. Types affected: IndexInput, IndexOutput. Added obsolete extension methods for each type in Lucene.Net.Store, but do note this only works if the Lucene.Net.Store namespace is imported at the top of the file.
     new 528f262  BREAKING: Lucene.Net.QueryParser: Factored out NLS/IMessage/Message support and changed exceptions to use string messages so end users can elect whether to use .NET localization or not
     new 60d1b82  BREAKING: Lucene.Net.QueryParsers.Flexible.Messages: Removed entire namespace, as we have refactored to use .NET localization rather than NLS
     new b8f9d05  BREAKING: Lucene.Net.Util: Removed BundleResourceManagerFactory and IResourceManagerFactory, as these were only to support NLS
     new c15328f  Lucene.Net.QueryParsers.Flexible.Core.Messages: Redesigned QueryParserMessages.cs so that it is just a facade around a IResourceProvider implementation that provides the actual fallback logic. Added a QueryParserResourceProvider implementation that can be passed zero to many ResourceProvider instances to override and optionally localize the default resource messages.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../Flexible/Core/Builders/QueryTreeBuilder.cs     |   5 +-
 .../Flexible/Core/Messages/QueryParserMessages.cs  | 196 +++++++--
 ...essagesBundle.resx => QueryParserMessages.resx} |  13 +-
 .../Messages/QueryParserMessagesBundle.Designer.cs | 247 ------------
 .../Core/Messages/QueryParserResourceProvider.cs   | 191 +++++++++
 .../Flexible/Core/Messages/package.md              |   2 +-
 .../Flexible/Core/Nodes/BoostQueryNode.cs          |  11 +-
 .../Flexible/Core/Nodes/GroupQueryNode.cs          |  11 +-
 .../Flexible/Core/Nodes/ModifierQueryNode.cs       |  12 +-
 .../Flexible/Core/Nodes/PhraseSlopQueryNode.cs     |  11 +-
 .../Flexible/Core/Nodes/ProximityQueryNode.cs      |   8 +-
 .../Flexible/Core/Nodes/QueryNodeImpl.cs           |  26 +-
 .../Flexible/Core/Nodes/SlopQueryNode.cs           |  11 +-
 .../Flexible/Core/QueryNodeError.cs                |  92 +++--
 .../Flexible/Core/QueryNodeException.cs            |  81 ++--
 .../Flexible/Core/QueryNodeParseException.cs       |  51 +--
 .../Flexible/Messages/Message.cs                   |  65 +--
 .../Flexible/Messages/MessageImpl.cs               | 143 +++----
 .../Flexible/Messages/NLS.cs                       | 449 +++++++++++----------
 .../Flexible/Messages/NLSException.cs              |  71 ++--
 .../Standard/Builders/AnyQueryNodeBuilder.cs       |   7 +-
 .../Standard/Builders/BooleanQueryNodeBuilder.cs   |   4 +-
 .../Builders/MatchAllDocsQueryNodeBuilder.cs       |   4 +-
 .../Builders/MatchNoDocsQueryNodeBuilder.cs        |   4 +-
 .../Builders/NumericRangeQueryNodeBuilder.cs       |   4 +-
 .../Builders/StandardBooleanQueryNodeBuilder.cs    |   4 +-
 .../Standard/Nodes/NumericRangeQueryNode.cs        |   4 +-
 .../Standard/Parser/EscapeQuerySyntaxImpl.cs       |  14 +-
 .../Flexible/Standard/Parser/ParseException.cs     |  54 +--
 .../Standard/Parser/StandardSyntaxParser.cs        |  18 +-
 .../Processors/AllowLeadingWildcardProcessor.cs    |   4 +-
 .../Processors/NumericQueryNodeProcessor.cs        |   7 +-
 .../Processors/NumericRangeQueryNodeProcessor.cs   |   7 +-
 .../Lucene.Net.QueryParser.csproj                  |   8 +
 .../ExceptionHandling/ExceptionExtensions.cs       |   3 +-
 .../Flexible/Messages/MessagesTestBundle.cs        |  81 ++--
 .../Flexible/Messages/TestNLS.cs                   | 237 +++++------
 .../Spans/SpansValidatorQueryNodeProcessor.cs      |   5 +-
 .../Flexible/Standard/TestQPHelper.cs              |   6 +-
 .../Lucene.Net.Tests.QueryParser.csproj            |  29 +-
 .../Resources/LUCENE_NET_ICON_32x32.png            | Bin 0 -> 233 bytes
 .../Core/Messages/MessagesTest.Designer.cs         | 100 +++++
 .../Flexible/Core/Messages/MessagesTest.ja.resx}   |  29 +-
 .../Flexible/Core/Messages/MessagesTest.resx}      |  40 +-
 .../Messages/TestQueryParserMessagesDefault.cs     | 105 +++++
 .../Messages/TestQueryParserMessagesOverridden.cs  | 123 ++++++
 .../Messages/TestQueryParserResourceProvider.cs    | 113 ++++++
 .../Core/Messages}/lucene-net-icon-32x32.png       | Bin
 .../Support/TestApiConsistency.cs                  |   4 +-
 .../ExceptionHandling/ExceptionExtensions.cs       |   3 +-
 .../Support/Util/BundleResourceManagerFactory.cs   |  87 ----
 .../Support/Util/IResourceManagerFactory.cs        |  36 --
 src/Lucene.Net/Support/Util/IResourceProvider.cs   |  94 +++++
 53 files changed, 1718 insertions(+), 1216 deletions(-)
 rename src/Lucene.Net.QueryParser/Flexible/Core/Messages/{QueryParserMessagesBundle.resx => QueryParserMessages.resx} (95%)
 delete mode 100644 src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.Designer.cs
 create mode 100644 src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserResourceProvider.cs
 create mode 100644 src/Lucene.Net.Tests.QueryParser/Resources/LUCENE_NET_ICON_32x32.png
 create mode 100644 src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.Designer.cs
 copy src/Lucene.Net.Tests.QueryParser/{Flexible/Messages/MessagesTestBundleBundle.ja.resx => Support/Flexible/Core/Messages/MessagesTest.ja.resx} (85%)
 copy src/Lucene.Net.Tests.QueryParser/{Flexible/Messages/MessagesTestBundleBundle.resx => Support/Flexible/Core/Messages/MessagesTest.resx} (84%)
 create mode 100644 src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesDefault.cs
 create mode 100644 src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesOverridden.cs
 create mode 100644 src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserResourceProvider.cs
 copy {branding/logo => src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages}/lucene-net-icon-32x32.png (100%)
 delete mode 100644 src/Lucene.Net/Support/Util/BundleResourceManagerFactory.cs
 delete mode 100644 src/Lucene.Net/Support/Util/IResourceManagerFactory.cs
 create mode 100644 src/Lucene.Net/Support/Util/IResourceProvider.cs

[lucenenet] 02/04: BREAKING: Lucene.Net.QueryParsers.Flexible.Messages: Removed entire namespace, as we have refactored to use .NET localization rather than NLS

Posted by ni...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit 60d1b82832b0b8696e31576de3698730deb0cc11
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Sat May 1 06:32:57 2021 +0700

    BREAKING: Lucene.Net.QueryParsers.Flexible.Messages: Removed entire namespace, as we have refactored to use .NET localization rather than NLS
---
 .../Flexible/Messages/Message.cs                   |  65 +--
 .../Flexible/Messages/MessageImpl.cs               | 143 +++----
 .../Flexible/Messages/NLS.cs                       | 449 +++++++++++----------
 .../Flexible/Messages/NLSException.cs              |  71 ++--
 .../Flexible/Messages/MessagesTestBundle.cs        |  81 ++--
 .../Flexible/Messages/TestNLS.cs                   | 237 +++++------
 6 files changed, 532 insertions(+), 514 deletions(-)

diff --git a/src/Lucene.Net.QueryParser/Flexible/Messages/Message.cs b/src/Lucene.Net.QueryParser/Flexible/Messages/Message.cs
index fa9934d..e442f1c 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Messages/Message.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Messages/Message.cs
@@ -1,33 +1,36 @@
-using System.Globalization;
+// LUCENENET specific - Factored out NLS so end users can elect to use .NET localization or not
+// rather than forcing them to use it.
 
-namespace Lucene.Net.QueryParsers.Flexible.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
+//using System.Globalization;
 
-    /// <summary>
-    /// Message Interface for a lazy loading.
-    /// For Native Language Support (NLS), system of software internationalization.
-    /// </summary>
-    public interface IMessage
-    {
-        string Key { get; }
-        object[] GetArguments();
-        string GetLocalizedMessage();
-        string GetLocalizedMessage(CultureInfo locale);
-    }
-}
+//namespace Lucene.Net.QueryParsers.Flexible.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
+
+//    /// <summary>
+//    /// Message Interface for a lazy loading.
+//    /// For Native Language Support (NLS), system of software internationalization.
+//    /// </summary>
+//    public interface IMessage
+//    {
+//        string Key { get; }
+//        object[] GetArguments();
+//        string GetLocalizedMessage();
+//        string GetLocalizedMessage(CultureInfo locale);
+//    }
+//}
diff --git a/src/Lucene.Net.QueryParser/Flexible/Messages/MessageImpl.cs b/src/Lucene.Net.QueryParser/Flexible/Messages/MessageImpl.cs
index cd4a191..9033630 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Messages/MessageImpl.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Messages/MessageImpl.cs
@@ -1,81 +1,84 @@
-using Lucene.Net.Support;
-using System;
-using System.Globalization;
-using System.Text;
+// LUCENENET specific - Factored out NLS so end users can elect to use .NET localization or not
+// rather than forcing them to use it.
 
-namespace Lucene.Net.QueryParsers.Flexible.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
+//using Lucene.Net.Support;
+//using System;
+//using System.Globalization;
+//using System.Text;
 
-    /// <summary>
-    /// Default implementation of Message interface.
-    /// For Native Language Support (NLS), system of software internationalization.
-    /// </summary>
-#if FEATURE_SERIALIZABLE
-    [Serializable]
-#endif
-    public class Message : IMessage
-    {
-        private readonly string key; // LUCENENET: marked readonly
+//namespace Lucene.Net.QueryParsers.Flexible.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
 
-        private readonly object[] arguments = Arrays.Empty<object>(); // LUCENENET: marked readonly
+//    /// <summary>
+//    /// Default implementation of Message interface.
+//    /// For Native Language Support (NLS), system of software internationalization.
+//    /// </summary>
+//#if FEATURE_SERIALIZABLE
+//    [Serializable]
+//#endif
+//    public class Message : IMessage
+//    {
+//        private readonly string key; // LUCENENET: marked readonly
 
-        public Message(string key)
-        {
-            this.key = key;
+//        private readonly object[] arguments = Arrays.Empty<object>(); // LUCENENET: marked readonly
 
-        }
+//        public Message(string key)
+//        {
+//            this.key = key;
 
-        public Message(string key, params object[] args)
-            : this(key)
-        {
-            this.arguments = args;
-        }
+//        }
 
-        public virtual object[] GetArguments()
-        {
-            return (object[])this.arguments.Clone(); // LUCENENET specific: These are obviously not meant to be written to, so cloning the result
-        }
+//        public Message(string key, params object[] args)
+//            : this(key)
+//        {
+//            this.arguments = args;
+//        }
 
-        public virtual string Key => this.key;
+//        public virtual object[] GetArguments()
+//        {
+//            return (object[])this.arguments.Clone(); // LUCENENET specific: These are obviously not meant to be written to, so cloning the result
+//        }
 
-        public virtual string GetLocalizedMessage()
-        {
-            return GetLocalizedMessage(CultureInfo.CurrentUICulture);
-        }
+//        public virtual string Key => this.key;
 
-        public virtual string GetLocalizedMessage(CultureInfo locale)
-        {
-            return NLS.GetLocalizedMessage(Key, locale, GetArguments());
-        }
+//        public virtual string GetLocalizedMessage()
+//        {
+//            return GetLocalizedMessage(CultureInfo.CurrentUICulture);
+//        }
 
-        public override string ToString()
-        {
-            object[] args = GetArguments();
-            StringBuilder sb = new StringBuilder(Key);
-            if (args != null)
-            {
-                for (int i = 0; i < args.Length; i++)
-                {
-                    sb.Append(i == 0 ? " " : ", ").Append(args[i]);
-                }
-            }
-            return sb.ToString();
-        }
-    }
-}
+//        public virtual string GetLocalizedMessage(CultureInfo locale)
+//        {
+//            return NLS.GetLocalizedMessage(Key, locale, GetArguments());
+//        }
+
+//        public override string ToString()
+//        {
+//            object[] args = GetArguments();
+//            StringBuilder sb = new StringBuilder(Key);
+//            if (args != null)
+//            {
+//                for (int i = 0; i < args.Length; i++)
+//                {
+//                    sb.Append(i == 0 ? " " : ", ").Append(args[i]);
+//                }
+//            }
+//            return sb.ToString();
+//        }
+//    }
+//}
diff --git a/src/Lucene.Net.QueryParser/Flexible/Messages/NLS.cs b/src/Lucene.Net.QueryParser/Flexible/Messages/NLS.cs
index 2bd901b..31b808d 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Messages/NLS.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Messages/NLS.cs
@@ -1,223 +1,226 @@
-using Lucene.Net.Support;
-using Lucene.Net.Util;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Reflection;
-using System.Resources;
-
-namespace Lucene.Net.QueryParsers.Flexible.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    /// <summary>
-    /// MessageBundles classes extend this class, to implement a bundle.
-    /// 
-    /// For Native Language Support (NLS), system of software internationalization.
-    /// 
-    /// This interface is similar to the NLS class in eclipse.osgi.util.NLS class -
-    /// initializeMessages() method resets the values of all static strings, should
-    /// only be called by classes that extend from NLS (see TestMessages.java for
-    /// reference) - performs validation of all message in a bundle, at class load
-    /// time - performs per message validation at runtime - see NLSTest.java for
-    /// usage reference
-    /// 
-    /// MessageBundle classes may subclass this type.
-    /// </summary>
-    public abstract class NLS // LUCENENET specific: CA1052 Static holder types should be Static or NotInheritable
-    {
-        /// <summary>
-        /// LUCENENET specific factory reference to inject instances of <see cref="ResourceManager"/>
-        /// into this class.
-        /// </summary>
-        private static IResourceManagerFactory resourceManagerFactory = new BundleResourceManagerFactory();
-        private static readonly IDictionary<string, Type> bundles = new Dictionary<string, Type>(0); // LUCENENET: marked readonly
-
-        protected NLS()
-        {
-            // Do not instantiate
-        }
-
-        /// <summary>
-        /// Gets the static <see cref="IResourceManagerFactory"/> instance responsible
-        /// for creating <see cref="ResourceManager"/> instances in this class. LUCENENET specific.
-        /// </summary>
-        // LUCENENET NOTE: Don't make this into a property in case we need to make it into an extension method
-        // in a centralized DI configuration builder.
-        public static IResourceManagerFactory GetResourceManagerFactory()
-        {
-            return resourceManagerFactory;
-        }
-
-        /// <summary>
-        /// Sets the <see cref="IResourceManagerFactory"/> used to create instances of <see cref="ResourceManager"/>
-        /// for retrieving localized resources. Defaults to <see cref="BundleResourceManagerFactory"/> if not set. LUCENENET specific.
-        /// </summary>
-        /// <param name="resourceManagerFactory">The <see cref="IResourceManagerFactory"/> instance. Cannot be <c>null</c>.</param>
-        // LUCENENET NOTE: Don't make this into a property in case we need to make it into an extension method
-        // in a centralized DI configuration builder.
-        public static void SetResourceManagerFactory(IResourceManagerFactory resourceManagerFactory)
-        {
-            NLS.resourceManagerFactory = resourceManagerFactory ?? throw new ArgumentNullException(nameof(resourceManagerFactory));
-        }
-
-        public static string GetLocalizedMessage(string key)
-        {
-            return GetLocalizedMessage(key, CultureInfo.InvariantCulture);
-        }
-
-        public static string GetLocalizedMessage(string key, CultureInfo locale)
-        {
-            string message = GetResourceBundleObject(key, locale);
-            if (message == null)
-            {
-                return "Message with key:" + key + " and locale: " + locale
-                    + " not found.";
-            }
-            return message;
-        }
-
-        public static string GetLocalizedMessage(string key, CultureInfo locale,
-            params object[] args)
-        {
-            string str = GetLocalizedMessage(key, locale);
-
-            if (args.Length > 0)
-            {
-                str = string.Format(locale, str, args);
-            }
-
-            return str;
-        }
-
-        public static string GetLocalizedMessage(string key, params object[] args)
-        {
-            return GetLocalizedMessage(key, CultureInfo.CurrentUICulture, args);
-        }
-
-        /// <summary>
-        /// Initialize a given class with the message bundle Keys Should be called from
-        /// a class that extends NLS in a static block at class load time.
-        /// </summary>
-        /// <param name="bundleName">Property file with that contains the message bundle</param>
-        /// <param name="clazz">where constants will reside</param>
-        protected static void InitializeMessages(string bundleName, Type clazz)
-        {
-            try
-            {
-                Load(clazz);
-                if (!bundles.ContainsKey(bundleName))
-                    bundles[bundleName] = clazz;
-            }
-            catch (Exception e) when (e.IsThrowable())
-            {
-                // ignore all errors and exceptions
-                // because this function is supposed to be called at class load time.
-            }
-        }
-
-        private static string GetResourceBundleObject(string messageKey, CultureInfo locale)
-        {
-            // slow resource checking
-            // need to loop thru all registered resource bundles
-            foreach(var key in bundles.Keys)
-            {
-                Type clazz = bundles[key];
-                ResourceManager resourceBundle = resourceManagerFactory.Create(clazz);
-                if (resourceBundle != null)
-                {
-                    try
-                    {
-                        string obj = resourceBundle.GetString(messageKey, locale);
-                        if (obj != null)
-                            return obj;
-                    }
-                    catch (Exception e) when (e.IsMissingResourceException())
-                    {
-                        // just continue it might be on the next resource bundle
-                    }
-                    finally
-                    {
-                        resourceManagerFactory.Release(resourceBundle);
-                    }
-                }
-            }
-            // if resource is not found
-            return null;
-        }
-
-        private static void Load(Type clazz)
-        {
-            FieldInfo[] fieldArray = clazz.GetFields();
-
-            // build a map of field names to Field objects
-            int len = fieldArray.Length;
-            IDictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>(len * 2);
-            for (int i = 0; i < len; i++)
-            {
-                fields[fieldArray[i].Name] = fieldArray[i];
-                LoadFieldValue(fieldArray[i], clazz);
-            }
-        }
-
-        private static void LoadFieldValue(FieldInfo field, Type clazz)
-        {
-            field.SetValue(null, field.Name);
-            ValidateMessage(field.Name, clazz);
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="key">Message Key</param>
-        /// <param name="clazz"></param>
-        private static void ValidateMessage(string key, Type clazz)
-        {
-            // Test if the message is present in the resource bundle
-            try
-            {
-                ResourceManager resourceBundle = resourceManagerFactory.Create(clazz);
-                if (resourceBundle != null)
-                {
-                    try
-                    {
-                        string obj = resourceBundle.GetString(key);
-                        //if (obj == null)
-                        //  System.err.println("WARN: Message with key:" + key + " and locale: "
-                        //      + Locale.getDefault() + " not found.");
-                    }
-                    finally
-                    {
-                        resourceManagerFactory.Release(resourceBundle);
-                    }
-                }
-            }
-            catch (Exception e) when (e.IsMissingResourceException())
-            {
-                //System.err.println("WARN: Message with key:" + key + " and locale: "
-                //    + Locale.getDefault() + " not found.");
-            }
-            catch (Exception e) when (e.IsThrowable())
-            {
-                // ignore all other errors and exceptions
-                // since this code is just a test to see if the message is present on the
-                // system
-            }
-        }
-    }
-}
+// LUCENENET specific - Factored out NLS so end users can elect to use .NET localization or not
+// rather than forcing them to use it.
+
+//using Lucene.Net.Support;
+//using Lucene.Net.Util;
+//using System;
+//using System.Collections.Generic;
+//using System.Globalization;
+//using System.Reflection;
+//using System.Resources;
+
+//namespace Lucene.Net.QueryParsers.Flexible.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
+
+//    /// <summary>
+//    /// MessageBundles classes extend this class, to implement a bundle.
+//    /// 
+//    /// For Native Language Support (NLS), system of software internationalization.
+//    /// 
+//    /// This interface is similar to the NLS class in eclipse.osgi.util.NLS class -
+//    /// initializeMessages() method resets the values of all static strings, should
+//    /// only be called by classes that extend from NLS (see TestMessages.java for
+//    /// reference) - performs validation of all message in a bundle, at class load
+//    /// time - performs per message validation at runtime - see NLSTest.java for
+//    /// usage reference
+//    /// 
+//    /// MessageBundle classes may subclass this type.
+//    /// </summary>
+//    public abstract class NLS // LUCENENET specific: CA1052 Static holder types should be Static or NotInheritable
+//    {
+//        /// <summary>
+//        /// LUCENENET specific factory reference to inject instances of <see cref="ResourceManager"/>
+//        /// into this class.
+//        /// </summary>
+//        private static IResourceManagerFactory resourceManagerFactory = new BundleResourceManagerFactory();
+//        private static readonly IDictionary<string, Type> bundles = new Dictionary<string, Type>(0); // LUCENENET: marked readonly
+
+//        protected NLS()
+//        {
+//            // Do not instantiate
+//        }
+
+//        /// <summary>
+//        /// Gets the static <see cref="IResourceManagerFactory"/> instance responsible
+//        /// for creating <see cref="ResourceManager"/> instances in this class. LUCENENET specific.
+//        /// </summary>
+//        // LUCENENET NOTE: Don't make this into a property in case we need to make it into an extension method
+//        // in a centralized DI configuration builder.
+//        public static IResourceManagerFactory GetResourceManagerFactory()
+//        {
+//            return resourceManagerFactory;
+//        }
+
+//        /// <summary>
+//        /// Sets the <see cref="IResourceManagerFactory"/> used to create instances of <see cref="ResourceManager"/>
+//        /// for retrieving localized resources. Defaults to <see cref="BundleResourceManagerFactory"/> if not set. LUCENENET specific.
+//        /// </summary>
+//        /// <param name="resourceManagerFactory">The <see cref="IResourceManagerFactory"/> instance. Cannot be <c>null</c>.</param>
+//        // LUCENENET NOTE: Don't make this into a property in case we need to make it into an extension method
+//        // in a centralized DI configuration builder.
+//        public static void SetResourceManagerFactory(IResourceManagerFactory resourceManagerFactory)
+//        {
+//            NLS.resourceManagerFactory = resourceManagerFactory ?? throw new ArgumentNullException(nameof(resourceManagerFactory));
+//        }
+
+//        public static string GetLocalizedMessage(string key)
+//        {
+//            return GetLocalizedMessage(key, CultureInfo.InvariantCulture);
+//        }
+
+//        public static string GetLocalizedMessage(string key, CultureInfo locale)
+//        {
+//            string message = GetResourceBundleObject(key, locale);
+//            if (message == null)
+//            {
+//                return "Message with key:" + key + " and locale: " + locale
+//                    + " not found.";
+//            }
+//            return message;
+//        }
+
+//        public static string GetLocalizedMessage(string key, CultureInfo locale,
+//            params object[] args)
+//        {
+//            string str = GetLocalizedMessage(key, locale);
+
+//            if (args.Length > 0)
+//            {
+//                str = string.Format(locale, str, args);
+//            }
+
+//            return str;
+//        }
+
+//        public static string GetLocalizedMessage(string key, params object[] args)
+//        {
+//            return GetLocalizedMessage(key, CultureInfo.CurrentUICulture, args);
+//        }
+
+//        /// <summary>
+//        /// Initialize a given class with the message bundle Keys Should be called from
+//        /// a class that extends NLS in a static block at class load time.
+//        /// </summary>
+//        /// <param name="bundleName">Property file with that contains the message bundle</param>
+//        /// <param name="clazz">where constants will reside</param>
+//        protected static void InitializeMessages(string bundleName, Type clazz)
+//        {
+//            try
+//            {
+//                Load(clazz);
+//                if (!bundles.ContainsKey(bundleName))
+//                    bundles[bundleName] = clazz;
+//            }
+//            catch (Exception e) when (e.IsThrowable())
+//            {
+//                // ignore all errors and exceptions
+//                // because this function is supposed to be called at class load time.
+//            }
+//        }
+
+//        private static string GetResourceBundleObject(string messageKey, CultureInfo locale)
+//        {
+//            // slow resource checking
+//            // need to loop thru all registered resource bundles
+//            foreach(var key in bundles.Keys)
+//            {
+//                Type clazz = bundles[key];
+//                ResourceManager resourceBundle = resourceManagerFactory.Create(clazz);
+//                if (resourceBundle != null)
+//                {
+//                    try
+//                    {
+//                        string obj = resourceBundle.GetString(messageKey, locale);
+//                        if (obj != null)
+//                            return obj;
+//                    }
+//                    catch (Exception e) when (e.IsMissingResourceException())
+//                    {
+//                        // just continue it might be on the next resource bundle
+//                    }
+//                    finally
+//                    {
+//                        resourceManagerFactory.Release(resourceBundle);
+//                    }
+//                }
+//            }
+//            // if resource is not found
+//            return null;
+//        }
+
+//        private static void Load(Type clazz)
+//        {
+//            FieldInfo[] fieldArray = clazz.GetFields();
+
+//            // build a map of field names to Field objects
+//            int len = fieldArray.Length;
+//            IDictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>(len * 2);
+//            for (int i = 0; i < len; i++)
+//            {
+//                fields[fieldArray[i].Name] = fieldArray[i];
+//                LoadFieldValue(fieldArray[i], clazz);
+//            }
+//        }
+
+//        private static void LoadFieldValue(FieldInfo field, Type clazz)
+//        {
+//            field.SetValue(null, field.Name);
+//            ValidateMessage(field.Name, clazz);
+//        }
+
+//        /// <summary>
+//        /// 
+//        /// </summary>
+//        /// <param name="key">Message Key</param>
+//        /// <param name="clazz"></param>
+//        private static void ValidateMessage(string key, Type clazz)
+//        {
+//            // Test if the message is present in the resource bundle
+//            try
+//            {
+//                ResourceManager resourceBundle = resourceManagerFactory.Create(clazz);
+//                if (resourceBundle != null)
+//                {
+//                    try
+//                    {
+//                        string obj = resourceBundle.GetString(key);
+//                        //if (obj == null)
+//                        //  System.err.println("WARN: Message with key:" + key + " and locale: "
+//                        //      + Locale.getDefault() + " not found.");
+//                    }
+//                    finally
+//                    {
+//                        resourceManagerFactory.Release(resourceBundle);
+//                    }
+//                }
+//            }
+//            catch (Exception e) when (e.IsMissingResourceException())
+//            {
+//                //System.err.println("WARN: Message with key:" + key + " and locale: "
+//                //    + Locale.getDefault() + " not found.");
+//            }
+//            catch (Exception e) when (e.IsThrowable())
+//            {
+//                // ignore all other errors and exceptions
+//                // since this code is just a test to see if the message is present on the
+//                // system
+//            }
+//        }
+//    }
+//}
diff --git a/src/Lucene.Net.QueryParser/Flexible/Messages/NLSException.cs b/src/Lucene.Net.QueryParser/Flexible/Messages/NLSException.cs
index 22c77df..154a1e1 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Messages/NLSException.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Messages/NLSException.cs
@@ -1,35 +1,38 @@
-namespace Lucene.Net.QueryParsers.Flexible.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
+// LUCENENET specific - Factored out NLS so end users can elect to use .NET localization or not
+// rather than forcing them to use it.
 
-    /// <summary>
-    /// Interface that exceptions should implement to support lazy loading of messages.
-    /// 
-    /// For Native Language Support (NLS), system of software internationalization.
-    /// 
-    /// This Interface should be implemented by all exceptions that require
-    /// translation
-    /// </summary>
-    public interface INLSException
-    {
-        /// <summary>
-        /// an instance of a class that implements the Message interface
-        /// </summary>
-        IMessage MessageObject { get; }
-    }
-}
+//namespace Lucene.Net.QueryParsers.Flexible.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
+
+//    /// <summary>
+//    /// Interface that exceptions should implement to support lazy loading of messages.
+//    /// 
+//    /// For Native Language Support (NLS), system of software internationalization.
+//    /// 
+//    /// This Interface should be implemented by all exceptions that require
+//    /// translation
+//    /// </summary>
+//    public interface INLSException
+//    {
+//        /// <summary>
+//        /// an instance of a class that implements the Message interface
+//        /// </summary>
+//        IMessage MessageObject { get; }
+//    }
+//}
diff --git a/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/MessagesTestBundle.cs b/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/MessagesTestBundle.cs
index 748a60a..d27d761 100644
--- a/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/MessagesTestBundle.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/MessagesTestBundle.cs
@@ -1,45 +1,48 @@
-using System;
+// LUCENENET specific - Factored out NLS so end users can elect to use .NET localization or not
+// rather than forcing them to use it.
 
-namespace Lucene.Net.QueryParsers.Flexible.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
+//using System;
 
-    public class MessagesTestBundle : NLS
-    {
-        private static readonly string BUNDLE_NAME = typeof(MessagesTestBundle).Name;
+//namespace Lucene.Net.QueryParsers.Flexible.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
 
-        private MessagesTestBundle()
-        {
-            // should never be instantiated
-        }
+//    public class MessagesTestBundle : NLS
+//    {
+//        private static readonly string BUNDLE_NAME = typeof(MessagesTestBundle).Name;
 
-        static MessagesTestBundle()
-        {
-            // register all string ids with NLS class and initialize static string
-            // values
-            NLS.InitializeMessages(BUNDLE_NAME, typeof(MessagesTestBundle));
-        }
+//        private MessagesTestBundle()
+//        {
+//            // should never be instantiated
+//        }
 
-        // static string must match the strings in the property files.
-        public static String Q0001E_INVALID_SYNTAX;
-        public static String Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+//        static MessagesTestBundle()
+//        {
+//            // register all string ids with NLS class and initialize static string
+//            // values
+//            NLS.InitializeMessages(BUNDLE_NAME, typeof(MessagesTestBundle));
+//        }
 
-        // this message is missing from the properties file
-        public static String Q0005E_MESSAGE_NOT_IN_BUNDLE;
-    }
-}
+//        // static string must match the strings in the property files.
+//        public static String Q0001E_INVALID_SYNTAX;
+//        public static String Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+//        // this message is missing from the properties file
+//        public static String Q0005E_MESSAGE_NOT_IN_BUNDLE;
+//    }
+//}
diff --git a/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/TestNLS.cs b/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/TestNLS.cs
index 2e31669..8f9bf46 100644
--- a/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/TestNLS.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Flexible/Messages/TestNLS.cs
@@ -1,129 +1,132 @@
-using Lucene.Net.Util;
-using NUnit.Framework;
-using System;
-using System.Globalization;
+// LUCENENET specific - Factored out NLS so end users can elect to use .NET localization or not
+// rather than forcing them to use it.
 
-namespace Lucene.Net.QueryParsers.Flexible.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
+//using Lucene.Net.Util;
+//using NUnit.Framework;
+//using System;
+//using System.Globalization;
 
-    public class TestNLS : LuceneTestCase
-    {
-        [Test]
-        public void TestMessageLoading()
-        {
-            IMessage invalidSyntax = new Message(
-                MessagesTestBundle.Q0001E_INVALID_SYNTAX, "XXX");
-            /* 
-             * if the default locale is ja, you get ja as a fallback:
-             * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
-             */
-            if (!CultureInfo.CurrentUICulture.Equals(new CultureInfo("ja")))
-                assertEquals("Syntax Error: XXX", invalidSyntax.GetLocalizedMessage(new CultureInfo("en")));
-        }
+//namespace Lucene.Net.QueryParsers.Flexible.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
 
-        [Test]
-        public void TestMessageLoading_ja()
-        {
-            IMessage invalidSyntax = new Message(
-                MessagesTestBundle.Q0001E_INVALID_SYNTAX, "XXX");
-            assertEquals("構文エラー: XXX", invalidSyntax
-                .GetLocalizedMessage(new CultureInfo("ja")));
-        }
+//    public class TestNLS : LuceneTestCase
+//    {
+//        [Test]
+//        public void TestMessageLoading()
+//        {
+//            IMessage invalidSyntax = new Message(
+//                MessagesTestBundle.Q0001E_INVALID_SYNTAX, "XXX");
+//            /* 
+//             * if the default locale is ja, you get ja as a fallback:
+//             * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+//             */
+//            if (!CultureInfo.CurrentUICulture.Equals(new CultureInfo("ja")))
+//                assertEquals("Syntax Error: XXX", invalidSyntax.GetLocalizedMessage(new CultureInfo("en")));
+//        }
 
-        [Test]
-        public void TestNLSLoading()
-        {
-            String message = NLS
-                .GetLocalizedMessage(MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION, new CultureInfo("en"));
-            /* 
-             * if the default locale is ja, you get ja as a fallback:
-             * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
-             */
-            if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
-                assertEquals("Truncated unicode escape sequence.", message);
+//        [Test]
+//        public void TestMessageLoading_ja()
+//        {
+//            IMessage invalidSyntax = new Message(
+//                MessagesTestBundle.Q0001E_INVALID_SYNTAX, "XXX");
+//            assertEquals("構文エラー: XXX", invalidSyntax
+//                .GetLocalizedMessage(new CultureInfo("ja")));
+//        }
 
-            message = NLS.GetLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX, new CultureInfo("en"),
-                "XXX");
-            /* 
-             * if the default locale is ja, you get ja as a fallback:
-             * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
-             */
-            if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
-                assertEquals("Syntax Error: XXX", message);
-        }
+//        [Test]
+//        public void TestNLSLoading()
+//        {
+//            String message = NLS
+//                .GetLocalizedMessage(MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION, new CultureInfo("en"));
+//            /* 
+//             * if the default locale is ja, you get ja as a fallback:
+//             * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+//             */
+//            if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
+//                assertEquals("Truncated unicode escape sequence.", message);
 
-        [Test]
-        public void TestNLSLoading_ja()
-        {
-            String message = NLS.GetLocalizedMessage(
-                MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION,
-                new CultureInfo("ja-JP"));
-            assertEquals("切り捨てられたユニコード・エスケープ・シーケンス。", message);
+//            message = NLS.GetLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX, new CultureInfo("en"),
+//                "XXX");
+//            /* 
+//             * if the default locale is ja, you get ja as a fallback:
+//             * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+//             */
+//            if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
+//                assertEquals("Syntax Error: XXX", message);
+//        }
 
-            message = NLS.GetLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
-                new CultureInfo("ja-JP"), "XXX");
-            assertEquals("構文エラー: XXX", message);
-        }
+//        [Test]
+//        public void TestNLSLoading_ja()
+//        {
+//            String message = NLS.GetLocalizedMessage(
+//                MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION,
+//                new CultureInfo("ja-JP"));
+//            assertEquals("切り捨てられたユニコード・エスケープ・シーケンス。", message);
 
-        [Test]
-        public void TestNLSLoading_xx_XX()
-        {
-            try
-            {
-                CultureInfo locale = new CultureInfo("xx-XX");
-                String message = NLS.GetLocalizedMessage(
-                    MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION,
-                    locale);
-                /* 
-                 * if the default locale is ja, you get ja as a fallback:
-                 * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
-                 */
-                if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
-                    assertEquals("Truncated unicode escape sequence.", message);
+//            message = NLS.GetLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
+//                new CultureInfo("ja-JP"), "XXX");
+//            assertEquals("構文エラー: XXX", message);
+//        }
 
-                message = NLS.GetLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
-                    locale, "XXX");
-                /* 
-                 * if the default locale is ja, you get ja as a fallback:
-                 * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
-                 */
-                if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
-                    assertEquals("Syntax Error: XXX", message);
-            }
-            catch (CultureNotFoundException)
-            {
-                // ignore
+//        [Test]
+//        public void TestNLSLoading_xx_XX()
+//        {
+//            try
+//            {
+//                CultureInfo locale = new CultureInfo("xx-XX");
+//                String message = NLS.GetLocalizedMessage(
+//                    MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION,
+//                    locale);
+//                /* 
+//                 * if the default locale is ja, you get ja as a fallback:
+//                 * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+//                 */
+//                if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
+//                    assertEquals("Truncated unicode escape sequence.", message);
 
-                // LUCENENET NOTE: .NET Core throws a CultureNotFoundException in this case.
-                // There doesn't seem to be a reasonable way to test this as a result.
-            }
-        }
+//                message = NLS.GetLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
+//                    locale, "XXX");
+//                /* 
+//                 * if the default locale is ja, you get ja as a fallback:
+//                 * see ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)
+//                 */
+//                if (!CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("ja", StringComparison.OrdinalIgnoreCase))
+//                    assertEquals("Syntax Error: XXX", message);
+//            }
+//            catch (CultureNotFoundException)
+//            {
+//                // ignore
 
-        [Test]
-        public void TestMissingMessage()
-        {
-            CultureInfo locale = new CultureInfo("en");
-            String message = NLS.GetLocalizedMessage(
-                MessagesTestBundle.Q0005E_MESSAGE_NOT_IN_BUNDLE, locale);
+//                // LUCENENET NOTE: .NET Core throws a CultureNotFoundException in this case.
+//                // There doesn't seem to be a reasonable way to test this as a result.
+//            }
+//        }
 
-            assertEquals("Message with key:Q0005E_MESSAGE_NOT_IN_BUNDLE and locale: "
-                + locale.toString() + " not found.", message);
-        }
-    }
-}
+//        [Test]
+//        public void TestMissingMessage()
+//        {
+//            CultureInfo locale = new CultureInfo("en");
+//            String message = NLS.GetLocalizedMessage(
+//                MessagesTestBundle.Q0005E_MESSAGE_NOT_IN_BUNDLE, locale);
+
+//            assertEquals("Message with key:Q0005E_MESSAGE_NOT_IN_BUNDLE and locale: "
+//                + locale.toString() + " not found.", message);
+//        }
+//    }
+//}

[lucenenet] 03/04: BREAKING: Lucene.Net.Util: Removed BundleResourceManagerFactory and IResourceManagerFactory, as these were only to support NLS

Posted by ni...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit b8f9d05d52b4a18105e3ac3271141dbe00558ec4
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Sat May 1 06:35:09 2021 +0700

    BREAKING: Lucene.Net.Util: Removed BundleResourceManagerFactory and IResourceManagerFactory, as these were only to support NLS
---
 .../Support/Util/BundleResourceManagerFactory.cs   | 87 ----------------------
 .../Support/Util/IResourceManagerFactory.cs        | 36 ---------
 2 files changed, 123 deletions(-)

diff --git a/src/Lucene.Net/Support/Util/BundleResourceManagerFactory.cs b/src/Lucene.Net/Support/Util/BundleResourceManagerFactory.cs
deleted file mode 100644
index 2464c0f..0000000
--- a/src/Lucene.Net/Support/Util/BundleResourceManagerFactory.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using J2N;
-using System;
-using System.Reflection;
-using System.Resources;
-
-namespace Lucene.Net.Util
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    /// <summary>
-    /// This implementation of <see cref="IResourceManagerFactory"/> uses a convention
-    /// to retrieve resources. In Java NLS, the convention is to use the same name for the
-    /// resource key propeties and for the resource file names. This presents a problem
-    /// for .NET because the resource generator already creates an internal class with the
-    /// same name as the <c>.resx</c> file.
-    /// <para/>
-    /// To work around this, we use the convention of appending the suffix "Bundle" to 
-    /// the end of the type the resource key propeties are stored in. For example,
-    /// if our constants are stored in a class named ErrorMessages, the type
-    /// that will be looked up by this factory will be ErrorMessagesBundle (which is the
-    /// name of the <c>.resx</c> file that should be added to your project).
-    /// <para/>
-    /// This implementation can be inherited to use a different convention or can be replaced
-    /// to get the resources from an external source.
-    /// </summary>
-    public class BundleResourceManagerFactory : IResourceManagerFactory
-    {
-        /// <summary>
-        /// Creates a <see cref="ResourceManager"/> instance using the specified <paramref name="resourceSource"/>.
-        /// </summary>
-        /// <param name="resourceSource">The type representing the resource to retrieve.</param>
-        /// <returns>A new <see cref="ResourceManager"/> instance.</returns>
-        public virtual ResourceManager Create(Type resourceSource)
-        {
-            return new ResourceManager(GetResourceName(resourceSource), resourceSource.Assembly);
-        }
-
-        /// <summary>
-        /// Releases the <see cref="ResourceManager"/> instance including any disposable dependencies.
-        /// </summary>
-        /// <param name="manager">The <see cref="ResourceManager"/> to release.</param>
-        public virtual void Release(ResourceManager manager)
-        {
-            if (manager is IDisposable disposable)
-            {
-                disposable.Dispose();
-            }
-        }
-
-        /// <summary>
-        /// Gets the fully-qualified name of the bundle as it would appear
-        /// using <see cref="Assembly.GetManifestResourceNames()"/>, without the
-        /// <c>.resources</c> extension. This is the name that is passed to the
-        /// <c>baseName</c> parameter of
-        /// <see cref="ResourceManager.ResourceManager(string, Assembly)"/>.
-        /// </summary>
-        /// <param name="clazz">The type of the NLS-derived class where the field strings are located that identify resources.</param>
-        /// <returns>The resource name.</returns>
-        protected virtual string GetResourceName(Type clazz)
-        {
-            string resource = clazz.FindResource(string.Concat(clazz.Name, ResourceSuffix, ".resources"));
-            return !string.IsNullOrEmpty(resource)
-                ? resource.Substring(0, resource.Length - 10)
-                : null;
-        }
-
-        /// <summary>
-        /// The suffix to append to the resource key class name to locate the embedded resource.
-        /// </summary>
-        protected virtual string ResourceSuffix => "Bundle";
-    }
-}
diff --git a/src/Lucene.Net/Support/Util/IResourceManagerFactory.cs b/src/Lucene.Net/Support/Util/IResourceManagerFactory.cs
deleted file mode 100644
index e54708f..0000000
--- a/src/Lucene.Net/Support/Util/IResourceManagerFactory.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Resources;
-
-namespace Lucene.Net.Util
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    /// <summary>
-    /// LUCENENET specific interface used to inject instances of
-    /// <see cref="ResourceManager"/>. This
-    /// extension point can be used to override the default behavior
-    /// to, for example, retrieve resources from a persistent data store,
-    /// rather than getting them from resource files.
-    /// </summary>
-    public interface IResourceManagerFactory
-    {
-        ResourceManager Create(Type resourceSource);
-
-        void Release(ResourceManager manager);
-    }
-}

[lucenenet] 04/04: Lucene.Net.QueryParsers.Flexible.Core.Messages: Redesigned QueryParserMessages.cs so that it is just a facade around a IResourceProvider implementation that provides the actual fallback logic. Added a QueryParserResourceProvider implementation that can be passed zero to many ResourceProvider instances to override and optionally localize the default resource messages.

Posted by ni...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit c15328f68ef46503d96f3f011f9ab2a3001acc24
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Tue May 4 06:44:36 2021 +0700

    Lucene.Net.QueryParsers.Flexible.Core.Messages: Redesigned QueryParserMessages.cs so that it is just a facade around a IResourceProvider implementation that provides the actual fallback logic. Added a QueryParserResourceProvider implementation that can be passed zero to many ResourceProvider instances to override and optionally localize the default resource messages.
---
 .../Core/Messages/QueryParserMessages.Designer.cs  | 243 -------------------
 .../Flexible/Core/Messages/QueryParserMessages.cs  | 263 ++++++++++++++++-----
 .../Core/Messages/QueryParserResourceProvider.cs   | 191 +++++++++++++++
 .../Lucene.Net.QueryParser.csproj                  |  13 +-
 .../Lucene.Net.Tests.QueryParser.csproj            |  29 ++-
 .../Resources/LUCENE_NET_ICON_32x32.png            | Bin 0 -> 233 bytes
 .../Core/Messages/MessagesTest.Designer.cs         | 100 ++++++++
 .../Flexible/Core/Messages/MessagesTest.ja.resx    | 126 ++++++++++
 .../Flexible/Core/Messages/MessagesTest.resx       | 133 +++++++++++
 .../Messages/TestQueryParserMessagesDefault.cs     | 105 ++++++++
 .../Messages/TestQueryParserMessagesOverridden.cs  | 123 ++++++++++
 .../Messages/TestQueryParserResourceProvider.cs    | 113 +++++++++
 .../Core/Messages/lucene-net-icon-32x32.png        | Bin 0 -> 1136 bytes
 src/Lucene.Net/Support/Util/IResourceProvider.cs   |  94 ++++++++
 14 files changed, 1214 insertions(+), 319 deletions(-)

diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.Designer.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.Designer.cs
deleted file mode 100644
index 1275ba0..0000000
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.Designer.cs
+++ /dev/null
@@ -1,243 +0,0 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.42000
-//
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace Lucene.Net.QueryParsers.Flexible.Core.Messages {
-    using System;
-    
-    
-    /// <summary>
-    ///   A strongly-typed resource class, for looking up localized strings, etc.
-    /// </summary>
-    // This class was auto-generated by the StronglyTypedResourceBuilder
-    // class via a tool like ResGen or Visual Studio.
-    // To add or remove a member, edit your .ResX file then rerun ResGen
-    // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    internal class QueryParserMessages {
-        
-        private static global::System.Resources.ResourceManager resourceMan;
-        
-        private static global::System.Globalization.CultureInfo resourceCulture;
-        
-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        internal QueryParserMessages() {
-        }
-        
-        /// <summary>
-        ///   Returns the cached ResourceManager instance used by this class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Resources.ResourceManager ResourceManager {
-            get {
-                if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lucene.Net.QueryParsers.Flexible.Core.Messages.QueryParserMessages", typeof(QueryParserMessages).Assembly);
-                    resourceMan = temp;
-                }
-                return resourceMan;
-            }
-        }
-        
-        /// <summary>
-        ///   Overrides the current thread's CurrentUICulture property for all
-        ///   resource lookups using this strongly typed resource class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Globalization.CultureInfo Culture {
-            get {
-                return resourceCulture;
-            }
-            set {
-                resourceCulture = value;
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Value cannot be null..
-        /// </summary>
-        internal static string ARGUMENT_CANNOT_BE_NULL {
-            get {
-                return ResourceManager.GetString("ARGUMENT_CANNOT_BE_NULL", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Could not parse text &quot;{0}&quot; using {1}.
-        /// </summary>
-        internal static string COULD_NOT_PARSE_NUMBER {
-            get {
-                return ResourceManager.GetString("COULD_NOT_PARSE_NUMBER", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to .
-        /// </summary>
-        internal static string EMPTY_MESSAGE {
-            get {
-                return ResourceManager.GetString("EMPTY_MESSAGE", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Syntax Error: {0}.
-        /// </summary>
-        internal static string INVALID_SYNTAX {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Syntax Error, cannot parse {0}: {1}.
-        /// </summary>
-        internal static string INVALID_SYNTAX_CANNOT_PARSE {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX_CANNOT_PARSE", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Term can not end with escape character..
-        /// </summary>
-        internal static string INVALID_SYNTAX_ESCAPE_CHARACTER {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX_ESCAPE_CHARACTER", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Non-hex character in Unicode escape sequence: {0}.
-        /// </summary>
-        internal static string INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Truncated unicode escape sequence..
-        /// </summary>
-        internal static string INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Fractional edit distances are not allowed..
-        /// </summary>
-        internal static string INVALID_SYNTAX_FUZZY_EDITS {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX_FUZZY_EDITS", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The similarity value for a fuzzy search must be between 0.0 and 1.0..
-        /// </summary>
-        internal static string INVALID_SYNTAX_FUZZY_LIMITS {
-            get {
-                return ResourceManager.GetString("INVALID_SYNTAX_FUZZY_LIMITS", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Leading wildcard is not allowed: {0}.
-        /// </summary>
-        internal static string LEADING_WILDCARD_NOT_ALLOWED {
-            get {
-                return ResourceManager.GetString("LEADING_WILDCARD_NOT_ALLOWED", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Cannot convert query to lucene syntax: {0} error: {1}.
-        /// </summary>
-        internal static string LUCENE_QUERY_CONVERSION_ERROR {
-            get {
-                return ResourceManager.GetString("LUCENE_QUERY_CONVERSION_ERROR", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to This node does not support this action..
-        /// </summary>
-        internal static string NODE_ACTION_NOT_SUPPORTED {
-            get {
-                return ResourceManager.GetString("NODE_ACTION_NOT_SUPPORTED", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The parameter must be greater than or equal to zero..
-        /// </summary>
-        internal static string NUMBER_CANNOT_BE_NEGATIVE {
-            get {
-                return ResourceManager.GetString("NUMBER_CANNOT_BE_NEGATIVE", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Number class not supported by NumericRangeQueryNode: {0}.
-        /// </summary>
-        internal static string NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY {
-            get {
-                return ResourceManager.GetString("NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Field &quot;{0}&quot; is numeric and cannot have an empty value..
-        /// </summary>
-        internal static string NUMERIC_CANNOT_BE_EMPTY {
-            get {
-                return ResourceManager.GetString("NUMERIC_CANNOT_BE_EMPTY", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Parameter {1} with value {0} not supported..
-        /// </summary>
-        internal static string PARAMETER_VALUE_NOT_SUPPORTED {
-            get {
-                return ResourceManager.GetString("PARAMETER_VALUE_NOT_SUPPORTED", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Too many boolean clauses, the maximum supported is {0}: {1}.
-        /// </summary>
-        internal static string TOO_MANY_BOOLEAN_CLAUSES {
-            get {
-                return ResourceManager.GetString("TOO_MANY_BOOLEAN_CLAUSES", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Unsupported NumericField.DataType: {0}.
-        /// </summary>
-        internal static string UNSUPPORTED_NUMERIC_DATA_TYPE {
-            get {
-                return ResourceManager.GetString("UNSUPPORTED_NUMERIC_DATA_TYPE", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Wildcard is not supported for query: {0}.
-        /// </summary>
-        internal static string WILDCARD_NOT_SUPPORTED {
-            get {
-                return ResourceManager.GetString("WILDCARD_NOT_SUPPORTED", resourceCulture);
-            }
-        }
-    }
-}
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs
index 103b981..02f38f7 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs
@@ -1,64 +1,199 @@
-// LUCENENET specific - factored out this class to optionally use the built in .NET localization rather than
-// forcing the use of the oddly designed Message class with NLS.
-
-//using Lucene.Net.QueryParsers.Flexible.Messages;
-
-//namespace Lucene.Net.QueryParsers.Flexible.Core.Messages
-//{
-//    /*
-//     * Licensed to the Apache Software Foundation (ASF) under one or more
-//     * contributor license agreements.  See the NOTICE file distributed with
-//     * this work for additional information regarding copyright ownership.
-//     * The ASF licenses this file to You under the Apache License, Version 2.0
-//     * (the "License"); you may not use this file except in compliance with
-//     * the License.  You may obtain a copy of the License at
-//     *
-//     *     http://www.apache.org/licenses/LICENSE-2.0
-//     *
-//     * Unless required by applicable law or agreed to in writing, software
-//     * distributed under the License is distributed on an "AS IS" BASIS,
-//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//     * See the License for the specific language governing permissions and
-//     * limitations under the License.
-//     */
-
-//    /// <summary>
-//    /// Flexible Query Parser message bundle class
-//    /// </summary>
-//    public class QueryParserMessages : NLS
-//    {
-//        private static readonly string BUNDLE_NAME = typeof(QueryParserMessages).Name;
-
-//        private QueryParserMessages()
-//        {
-//            // Do not instantiate
-//        }
-
-//        static QueryParserMessages()
-//        {
-//            // register all string ids with NLS class and initialize static string
-//            // values
-//            NLS.InitializeMessages(BUNDLE_NAME, typeof(QueryParserMessages));
-//        }
-
-//        // static string must match the strings in the property files.
-//        public static string INVALID_SYNTAX;
-//        public static string INVALID_SYNTAX_CANNOT_PARSE;
-//        public static string INVALID_SYNTAX_FUZZY_LIMITS;
-//        public static string INVALID_SYNTAX_FUZZY_EDITS;
-//        public static string INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
-//        public static string INVALID_SYNTAX_ESCAPE_CHARACTER;
-//        public static string INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
-//        public static string NODE_ACTION_NOT_SUPPORTED;
-//        public static string PARAMETER_VALUE_NOT_SUPPORTED;
-//        public static string LUCENE_QUERY_CONVERSION_ERROR;
-//        public static string EMPTY_MESSAGE;
-//        public static string WILDCARD_NOT_SUPPORTED;
-//        public static string TOO_MANY_BOOLEAN_CLAUSES;
-//        public static string LEADING_WILDCARD_NOT_ALLOWED;
-//        public static string COULD_NOT_PARSE_NUMBER;
-//        public static string NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY;
-//        public static string UNSUPPORTED_NUMERIC_DATA_TYPE;
-//        public static string NUMERIC_CANNOT_BE_EMPTY;
-//    }
-//}
+// LUCENENET specific - This is the content of QueryParserMessages.Designer that was generated, with customizations.
+// The NLS derived class was replaced with this one to make interop with .NET resources easier.
+//
+// We turned off auto-generation of this file and added a SetResourceProvider() to supply a class that can supply string/object localized resources.
+// This allows end users to supply localized messages.
+//
+// 1. Add a Resource (.resx) to the project.
+// 2. Add any of the below properties as the resource names, and supply messages as desired.
+// 3. Call QueryParserMessages.SetResourceProvider(new QueryParserResourceProvider(SomeResource.ResourceManager)) at application startup and supply the ResourceManager of the custom Resource's designer.
+
+
+using Lucene.Net.Util;
+using System;
+using System.ComponentModel;
+using System.Globalization;
+#nullable enable
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Messages
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// A strongly-typed resource class, for looking up localized strings, etc.
+    /// <para/>
+    /// The localized resources can be replaced by end users by calling the <see cref="SetResourceProvider(IResourceProvider)"/>
+    /// method and supplying an instance of <see cref="QueryParserResourceProvider"/> with custom
+    /// <see cref="System.Resources.ResourceManager"/> instances provided in its constructor.
+    /// <code>
+    /// QueryParserMessages.SetResourceProvider(new QueryParserResourceProvider(SomeResource.ResourceManager, SomeOtherResource.ResourceManager));
+    /// </code>
+    /// <c>SomeResource</c> and <c>SomeOtherResource</c> are auto-generated designer classes which can be generated by Visual Studio when adding
+    /// resource files (.resx) to a project. These resources can optionally be localized in different cultures and optionally be distributed as satellite
+    /// assemblies. See the <see cref="System.Resources.ResourceManager"/> documentation for tips on how to get started, but do note this is a broad topic.
+    /// <para/>
+    /// <see cref="QueryParserResourceProvider"/> makes no assumptions on the method used to generate or deploy resources, the only requirement is that you provide
+    /// a <see cref="System.Resources.ResourceManager"/> that can find them. Note that it is also possible to subclass <see cref="QueryParserResourceProvider"/>
+    /// or implement <see cref="IResourceProvider"/> directly to provide resources from any source.
+    /// </summary>
+    // LUCENENET NOTE: Since we are not using a custom tool to generate this file, any additions/deletions to the
+    // QueryParserMessages.resx file must be done to this class manually.
+    public static class QueryParserMessages
+    {
+        private static CultureInfo? resourceCulture;
+        private static IResourceProvider resourceProvider = new QueryParserResourceProvider();
+
+        /// <summary>
+        /// Gets the associated resource provider.
+        /// </summary>
+        /// <returns>The current resource provider.</returns>
+        /// <seealso cref="SetResourceProvider(IResourceProvider)"/>
+        public static IResourceProvider GetResourceProvider()
+        {
+            return resourceProvider;
+        }
+
+        /// <summary>
+        /// Sets the <see cref="IResourceProvider"/> instance used to provide
+        /// localized <see cref="string"/>s and <see cref="object"/>s.
+        /// </summary>
+        /// <param name="provider">The new <see cref="IResourceProvider"/>.</param>
+        /// <exception cref="ArgumentNullException">The <paramref name="provider"/> parameter is <c>null</c>.</exception>
+        /// <seealso cref="GetResourceProvider()"/>
+        public static void SetResourceProvider(IResourceProvider provider)
+        {
+            resourceProvider = provider ?? throw new ArgumentNullException(nameof(provider));
+        }
+
+        private static string? GetString(string name, CultureInfo? culture)
+        {
+            return resourceProvider.GetString(name, culture);
+        }
+
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [EditorBrowsableAttribute(EditorBrowsableState.Advanced)]
+        public static CultureInfo? Culture
+        {
+            get => resourceCulture;
+            set => resourceCulture = value;
+        }
+
+        /// <summary>
+        ///   Looks up a localized string similar to Value cannot be null..
+        /// </summary>
+        public static string? ARGUMENT_CANNOT_BE_NULL => GetString("ARGUMENT_CANNOT_BE_NULL", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Could not parse text &quot;{0}&quot; using {1}.
+        /// </summary>
+        public static string? COULD_NOT_PARSE_NUMBER => GetString("COULD_NOT_PARSE_NUMBER", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to .
+        /// </summary>
+        public static string? EMPTY_MESSAGE => GetString("EMPTY_MESSAGE", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Syntax Error: {0}.
+        /// </summary>
+        public static string? INVALID_SYNTAX => GetString("INVALID_SYNTAX", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Syntax Error, cannot parse {0}: {1}.
+        /// </summary>
+        public static string? INVALID_SYNTAX_CANNOT_PARSE => GetString("INVALID_SYNTAX_CANNOT_PARSE", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Term can not end with escape character..
+        /// </summary>
+        public static string? INVALID_SYNTAX_ESCAPE_CHARACTER => GetString("INVALID_SYNTAX_ESCAPE_CHARACTER", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Non-hex character in Unicode escape sequence: {0}.
+        /// </summary>
+        public static string? INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE => GetString("INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Truncated unicode escape sequence..
+        /// </summary>
+        public static string? INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION => GetString("INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Fractional edit distances are not allowed..
+        /// </summary>
+        public static string? INVALID_SYNTAX_FUZZY_EDITS => GetString("INVALID_SYNTAX_FUZZY_EDITS", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to The similarity value for a fuzzy search must be between 0.0 and 1.0..
+        /// </summary>
+        public static string? INVALID_SYNTAX_FUZZY_LIMITS => GetString("INVALID_SYNTAX_FUZZY_LIMITS", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Leading wildcard is not allowed: {0}.
+        /// </summary>
+        public static string? LEADING_WILDCARD_NOT_ALLOWED => GetString("LEADING_WILDCARD_NOT_ALLOWED", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Cannot convert query to lucene syntax: {0} error: {1}.
+        /// </summary>
+        public static string? LUCENE_QUERY_CONVERSION_ERROR => GetString("LUCENE_QUERY_CONVERSION_ERROR", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to This node does not support this action..
+        /// </summary>
+        public static string? NODE_ACTION_NOT_SUPPORTED => GetString("NODE_ACTION_NOT_SUPPORTED", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to The parameter must be greater than or equal to zero..
+        /// </summary>
+        public static string? NUMBER_CANNOT_BE_NEGATIVE => GetString("NUMBER_CANNOT_BE_NEGATIVE", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Number class not supported by NumericRangeQueryNode: {0}.
+        /// </summary>
+        public static string? NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY => GetString("NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Field &quot;{0}&quot; is numeric and cannot have an empty value..
+        /// </summary>
+        public static string? NUMERIC_CANNOT_BE_EMPTY => GetString("NUMERIC_CANNOT_BE_EMPTY", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Parameter {1} with value {0} not supported..
+        /// </summary>
+        public static string? PARAMETER_VALUE_NOT_SUPPORTED => GetString("PARAMETER_VALUE_NOT_SUPPORTED", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Too many boolean clauses, the maximum supported is {0}: {1}.
+        /// </summary>
+        public static string? TOO_MANY_BOOLEAN_CLAUSES => GetString("TOO_MANY_BOOLEAN_CLAUSES", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Unsupported NumericField.DataType: {0}.
+        /// </summary>
+        public static string? UNSUPPORTED_NUMERIC_DATA_TYPE => GetString("UNSUPPORTED_NUMERIC_DATA_TYPE", resourceCulture);
+
+        /// <summary>
+        ///   Looks up a localized string similar to Wildcard is not supported for query: {0}.
+        /// </summary>
+        public static string? WILDCARD_NOT_SUPPORTED => GetString("WILDCARD_NOT_SUPPORTED", resourceCulture);
+    }
+}
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserResourceProvider.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserResourceProvider.cs
new file mode 100644
index 0000000..0a9633f
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserResourceProvider.cs
@@ -0,0 +1,191 @@
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.IO;
+using System.Resources;
+using System.Threading;
+#nullable enable
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Messages
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// The default <see cref="IResourceProvider"/> implementation for the <see cref="QueryParserMessages"/> class.
+    /// This class can be set in the <see cref="QueryParserMessages.SetResourceProvider(IResourceProvider)"/> method
+    /// and supplied with one or more <see cref="ResourceManager"/> instances that can override the default query parser
+    /// messages (generally, they are exception messages).
+    /// <para/>
+    /// Alternatively, this class may be overridden to provide either a custom <see cref="FallbackResourceManager"/> or
+    /// to alter the fallback logic in either <see cref="GetString(string, CultureInfo?)"/> or <see cref="GetObject(string, CultureInfo?)"/>.
+    /// The performance of this class may be improved significantly by specifying the <see cref="ResourceManager"/> that a specific resource
+    /// can be found in rather than attempting all of them.
+    /// </summary>
+    public class QueryParserResourceProvider : IResourceProvider
+    {
+        private ResourceManager? fallbackResourceManager;
+        private readonly IList<ResourceManager> resourceManagers;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="QueryParserResourceProvider"/> class with default values.
+        /// </summary>
+        public QueryParserResourceProvider()
+            : this((IList<ResourceManager>)Arrays.Empty<ResourceManager>())
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="QueryParserResourceProvider"/> class with the specified
+        /// <paramref name="resourceManagers"/>. The <paramref name="resourceManagers"/> may override resources
+        /// in the <see cref="FallbackResourceManager"/>, provided they have the same names.
+        /// <para/>
+        /// Note that not all of the resources are required to be provided and if the name doesn't exist it will
+        /// fall back to the next <see cref="ResourceManager"/> that is provided and ultimately will try the
+        /// <see cref="FallbackResourceManager"/> if the resource is not found.
+        /// </summary>
+        /// <param name="resourceManagers">One or more <see cref="ResourceManager"/> instances that provide
+        /// localized resources. The <paramref name="resourceManagers"/> are used in the order they are specified, and the first one
+        /// that provides a non-<c>null</c> value for a given resource name wins.</param>
+        /// <exception cref="ArgumentNullException">If <paramref name="resourceManagers"/> is <c>null</c>.</exception>
+        public QueryParserResourceProvider(params ResourceManager[] resourceManagers)
+            : this((IList<ResourceManager>)resourceManagers)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="QueryParserResourceProvider"/> class with the specified
+        /// <paramref name="resourceManagers"/>. The <paramref name="resourceManagers"/> may override resources
+        /// in the <see cref="FallbackResourceManager"/>, provided they have the same names.
+        /// <para/>
+        /// Note that not all of the resources are required to be provided and if the name doesn't exist it will
+        /// fall back to the next <see cref="ResourceManager"/> that is provided and ultimately will try the
+        /// <see cref="FallbackResourceManager"/> if the resource is not found.
+        /// </summary>
+        /// <param name="resourceManagers">One or more <see cref="ResourceManager"/> instances that provide
+        /// localized resources. The <paramref name="resourceManagers"/> are used in the order they are specified, and the first one
+        /// that provides a non-<c>null</c> value for a given resource name wins.</param>
+        /// <exception cref="ArgumentNullException">If <paramref name="resourceManagers"/> is <c>null</c>.</exception>
+        public QueryParserResourceProvider(IList<ResourceManager> resourceManagers)
+        {
+            this.resourceManagers = resourceManagers ?? throw new ArgumentNullException(nameof(resourceManagers));
+        }
+
+        /// <summary>
+        /// Gets the cached <see cref="ResourceManager"/> instance used as the fallback by this class.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Advanced)]
+        public virtual ResourceManager FallbackResourceManager
+        {
+            get
+            {
+                return LazyInitializer.EnsureInitialized(ref fallbackResourceManager,
+                    () => new ResourceManager("Lucene.Net.QueryParsers.Flexible.Core.Messages.QueryParserMessages", typeof(QueryParserMessages).Assembly))!;
+            }
+        }
+
+        /// <summary>Returns the value of the string resource localized for the specified <paramref name="culture"/>.
+        /// <para/>
+        /// The resource is searched for
+        /// first in the <see cref="ResourceManager"/> instances passed in the <see cref="QueryParserResourceProvider(IList{ResourceManager})"/>
+        /// or <see cref="QueryParserResourceProvider(ResourceManager[])"/> constructor, in the order they are specified. If not found, the
+        /// <see cref="FallbackResourceManager"/> is used. This method may return <c>null</c> if the resource with the given name is not found.</summary>
+        /// <inheritdoc/>
+        public virtual string? GetString(string name, CultureInfo? culture)
+        {
+            if (resourceManagers.Count > 0)
+            {
+                foreach (var resourceManager in resourceManagers)
+                {
+                    // LUCENENET NOTE: MissingManifestResourceException or MissingSatelliteAssemblyException
+                    // can be thrown here, but these indicate that there is a misconfigured setup (missing resource file,
+                    // missing assembly, etc.) We intentionally let these errors propagate to ensure the developer who
+                    // is creating resources is aware of these problems before the app is deployed (provided they test it).
+                    // However, if the resource simply doesn't have an entry, we get a null return value instead and handle
+                    // the fallback accordingly.
+                    var result = resourceManager.GetString(name, culture);
+                    if (result is null)
+                        continue;
+                    return result;
+                }
+            }
+
+            return FallbackResourceManager.GetString(name, culture);
+        }
+
+        /// <summary>Gets the value of the specified non-string resource localized for the specified <paramref name="culture"/>.
+        /// <para/>
+        /// The resource is searched for
+        /// first in the <see cref="ResourceManager"/> instances passed in the <see cref="QueryParserResourceProvider(IList{ResourceManager})"/>
+        /// or <see cref="QueryParserResourceProvider(ResourceManager[])"/> constructor, in the order they are specified. If not found, the
+        /// <see cref="FallbackResourceManager"/> is used. This method may return <c>null</c> if the resource with the given name is not found.</summary>
+        /// <inheritdoc/>
+        public virtual object? GetObject(string name, CultureInfo? culture)
+        {
+            if (resourceManagers.Count > 0)
+            {
+                foreach (var resourceManager in resourceManagers)
+                {
+                    // LUCENENET NOTE: MissingManifestResourceException or MissingSatelliteAssemblyException
+                    // can be thrown here, but these indicate that there is a misconfigured setup (missing resource file,
+                    // missing assembly, etc.) We intentionally let these errors propagate to ensure the developer who
+                    // is creating resources is aware of these problems before the app is deployed (provided they test it).
+                    // However, if the resource simply doesn't have an entry, we get a null return value instead and handle
+                    // the fallback accordingly.
+                    var result = resourceManager.GetObject(name, culture);
+                    if (result is null)
+                        continue;
+                    return result;
+                }
+            }
+
+            return FallbackResourceManager.GetObject(name, culture);
+        }
+
+        /// <summary>Returns an unmanaged memory stream object from the specified resource, using the specified <paramref name="culture"/>.
+        /// <para/>
+        /// The resource is searched for
+        /// first in the <see cref="ResourceManager"/> instances passed in the <see cref="QueryParserResourceProvider(IList{ResourceManager})"/>
+        /// or <see cref="QueryParserResourceProvider(ResourceManager[])"/> constructor, in the order they are specified. If not found, the
+        /// <see cref="FallbackResourceManager"/> is used. This method may return <c>null</c> if the resource with the given name is not found.</summary>
+        /// <inheritdoc/>
+        public Stream? GetStream(string name, CultureInfo? culture)
+        {
+            if (resourceManagers.Count > 0)
+            {
+                foreach (var resourceManager in resourceManagers)
+                {
+                    // LUCENENET NOTE: MissingManifestResourceException or MissingSatelliteAssemblyException
+                    // can be thrown here, but these indicate that there is a misconfigured setup (missing resource file,
+                    // missing assembly, etc.) We intentionally let these errors propagate to ensure the developer who
+                    // is creating resources is aware of these problems before the app is deployed (provided they test it).
+                    // However, if the resource simply doesn't have an entry, we get a null return value instead and handle
+                    // the fallback accordingly.
+                    var result = resourceManager.GetStream(name, culture);
+                    if (result is null)
+                        continue;
+                    return result;
+                }
+            }
+
+            return FallbackResourceManager.GetStream(name, culture);
+        }
+    }
+}
diff --git a/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj b/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
index 20f51fe..4d287a7 100644
--- a/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
+++ b/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
@@ -53,17 +53,8 @@
   </ItemGroup>
 
   <ItemGroup>
-    <Compile Update="Flexible\Core\Messages\QueryParserMessages.Designer.cs">
-      <DesignTime>True</DesignTime>
-      <AutoGen>True</AutoGen>
-      <DependentUpon>QueryParserMessages.resx</DependentUpon>
-    </Compile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <EmbeddedResource Update="Flexible\Core\Messages\QueryParserMessages.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>QueryParserMessages.Designer.cs</LastGenOutput>
+    <EmbeddedResource Update="Flexible\Core\Messages\QueryParserMessages.resx" >
+      <Generator Label="No generator used - we update manually."></Generator>
     </EmbeddedResource>
   </ItemGroup>
 
diff --git a/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj b/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
index 603bbf2..52d4966 100644
--- a/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
+++ b/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
@@ -25,9 +25,17 @@
 
   <PropertyGroup>
     <AssemblyTitle>Lucene.Net.Tests.QueryParser</AssemblyTitle>
+
+    <RootNamespace>Lucene.Net.QueryParsers</RootNamespace>
   </PropertyGroup>
 
   <ItemGroup>
+    <None Remove="Support\Flexible\Core\Messages\lucene-net-icon-32x32.png" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <!-- For testing whether we can get an image from a localized resource -->
+    <EmbeddedResource Include="Support\Flexible\Core\Messages\lucene-net-icon-32x32.png" />
     <EmbeddedResource Include="Xml\albumBooleanQuery.xsl;Xml\albumFilteredQuery.xsl;Xml\albumLuceneClassicQuery.xsl;Xml\BooleanFilter.xml;Xml\BooleanQuery.xml;Xml\BoostingQuery.xml;Xml\BoostingTermQuery.xml;Xml\CachedFilter.xml;Xml\ConstantScoreQuery.xml;Xml\DisjunctionMaxQuery.xml;Xml\DuplicateFilterQuery.xml;Xml\FuzzyLikeThisQuery.xml;Xml\LikeThisQuery.xml;Xml\MatchAllDocsQuery.xml;Xml\NestedBooleanQuery.xml;Xml\NumericRangeFilterQuery.xml;Xml\NumericRangeQueryQuery.xml;Xml\RangeFilter [...]
   </ItemGroup>
 
@@ -40,7 +48,26 @@
   <Import Project="$(SolutionDir)build/TestReferences.Common.targets" />
 
   <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
-    <PackageReference Include="System.Net.Primitives" Version="$(SystemNetPrimitivesPackageVersion)"/>
+    <PackageReference Include="System.Net.Primitives" Version="$(SystemNetPrimitivesPackageVersion)" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Support\Flexible\Core\Messages\MessagesTest.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>MessagesTest.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Support\Flexible\Core\Messages\MessagesTest.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>MessagesTest.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Resources\" />
   </ItemGroup>
 
 </Project>
diff --git a/src/Lucene.Net.Tests.QueryParser/Resources/LUCENE_NET_ICON_32x32.png b/src/Lucene.Net.Tests.QueryParser/Resources/LUCENE_NET_ICON_32x32.png
new file mode 100644
index 0000000..3e9d6ed
Binary files /dev/null and b/src/Lucene.Net.Tests.QueryParser/Resources/LUCENE_NET_ICON_32x32.png differ
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.Designer.cs b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.Designer.cs
new file mode 100644
index 0000000..67dc83d
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.Designer.cs
@@ -0,0 +1,100 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Lucene.Net.QueryParsers.Support.Flexible.Core.Messages {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class MessagesTest {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal MessagesTest() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lucene.Net.QueryParsers.Support.Flexible.Core.Messages.MessagesTest", typeof(MessagesTest).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Syntax Error: {0} (TEST).
+        /// </summary>
+        internal static string INVALID_SYNTAX {
+            get {
+                return ResourceManager.GetString("INVALID_SYNTAX", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Non-hex character in Unicode escape sequence: {0} (TEST).
+        /// </summary>
+        internal static string INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE {
+            get {
+                return ResourceManager.GetString("INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Truncated unicode escape sequence. (TEST) .
+        /// </summary>
+        internal static string INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION {
+            get {
+                return ResourceManager.GetString("INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Byte[].
+        /// </summary>
+        internal static byte[] LUCENE_NET_ICON_32x32 {
+            get {
+                object obj = ResourceManager.GetObject("LUCENE_NET_ICON_32x32", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+    }
+}
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.ja.resx b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.ja.resx
new file mode 100644
index 0000000..230b8a6
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.ja.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="INVALID_SYNTAX" xml:space="preserve">
+    <value>構文エラー: {0}</value>
+  </data>
+  <data name="INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION" xml:space="preserve">
+    <value>切り捨てられたユニコード・エスケープ・シーケンス。</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.resx b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.resx
new file mode 100644
index 0000000..549d008
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/MessagesTest.resx
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="INVALID_SYNTAX" xml:space="preserve">
+    <value>Syntax Error: {0} (TEST)</value>
+  </data>
+  <data name="INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE" xml:space="preserve">
+    <value>Non-hex character in Unicode escape sequence: {0} (TEST)</value>
+  </data>
+  <data name="INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION" xml:space="preserve">
+    <value>Truncated unicode escape sequence. (TEST) </value>
+  </data>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="LUCENE_NET_ICON_32x32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>lucene-net-icon-32x32.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesDefault.cs b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesDefault.cs
new file mode 100644
index 0000000..361ae08
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesDefault.cs
@@ -0,0 +1,105 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using NUnit.Framework;
+using System.Globalization;
+using Assert = Lucene.Net.TestFramework.Assert;
+
+namespace Lucene.Net.QueryParsers.Support.Flexible.Core.Messages
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public class TestQueryParserMessagesDefault
+    {
+        [Test]
+        public void TestOverrideResourceStrings()
+        {
+            QueryParserMessages.Culture = null;
+
+            var actual = QueryParserMessages.INVALID_SYNTAX;
+
+            Assert.AreEqual("Syntax Error: {0}", actual);
+
+            actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+            Assert.AreEqual("Truncated unicode escape sequence.", actual);
+
+            actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+
+            Assert.AreEqual("Non-hex character in Unicode escape sequence: {0}", actual);
+
+            actual = QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS;
+
+            Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual);
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings_ja()
+        {
+            QueryParserMessages.Culture = new CultureInfo("ja");
+            try
+            {
+                var actual = QueryParserMessages.INVALID_SYNTAX;
+
+                Assert.AreEqual("Syntax Error: {0}", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+                Assert.AreEqual("Truncated unicode escape sequence.", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+
+                Assert.AreEqual("Non-hex character in Unicode escape sequence: {0}", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS;
+
+                Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual);
+            }
+            finally
+            {
+                QueryParserMessages.Culture = null;
+            }
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings_ja_JP()
+        {
+            QueryParserMessages.Culture = new CultureInfo("ja-JP");
+            try
+            {
+                var actual = QueryParserMessages.INVALID_SYNTAX;
+
+                Assert.AreEqual("Syntax Error: {0}", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+                Assert.AreEqual("Truncated unicode escape sequence.", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+
+                Assert.AreEqual("Non-hex character in Unicode escape sequence: {0}", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS;
+
+                Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual);
+            }
+            finally
+            {
+                QueryParserMessages.Culture = null;
+            }
+        }
+    }
+}
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesOverridden.cs b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesOverridden.cs
new file mode 100644
index 0000000..f80a8e8
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserMessagesOverridden.cs
@@ -0,0 +1,123 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System.Globalization;
+using Assert = Lucene.Net.TestFramework.Assert;
+
+namespace Lucene.Net.QueryParsers.Support.Flexible.Core.Messages
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public class TestQueryParserMessagesOverridden : LuceneTestCase
+    {
+        public override void BeforeClass()
+        {
+            base.BeforeClass();
+
+            var provider = new QueryParserResourceProvider(MessagesTest.ResourceManager);
+            QueryParserMessages.SetResourceProvider(provider);
+        }
+
+        public override void AfterClass()
+        {
+            // Return to the default
+            var provider = new QueryParserResourceProvider();
+            QueryParserMessages.SetResourceProvider(provider);
+
+            base.AfterClass();
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings()
+        {
+            QueryParserMessages.Culture = null;
+
+            var actual = QueryParserMessages.INVALID_SYNTAX;
+
+            Assert.IsTrue(actual.Contains("(TEST)"));
+
+            actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+            Assert.IsTrue(actual.Contains("(TEST)"));
+
+            actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+
+            Assert.IsTrue(actual.Contains("(TEST)"));
+
+            actual = QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS;
+
+            Assert.IsFalse(actual.Contains("(TEST)")); // Fallback to default ResourceManager
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings_ja()
+        {
+            QueryParserMessages.Culture = new CultureInfo("ja");
+            try
+            {
+                var actual = QueryParserMessages.INVALID_SYNTAX;
+
+                Assert.AreEqual("構文エラー: {0}", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+                Assert.AreEqual("切り捨てられたユニコード・エスケープ・シーケンス。", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+
+                Assert.AreEqual("Non-hex character in Unicode escape sequence: {0} (TEST)", actual); // Fallback to non-localized test
+
+                actual = QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS;
+
+                Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual); // Fallback to default ResourceManager
+            }
+            finally
+            {
+                QueryParserMessages.Culture = null;
+            }
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings_ja_JP()
+        {
+            QueryParserMessages.Culture = new CultureInfo("ja-JP");
+            try
+            {
+                var actual = QueryParserMessages.INVALID_SYNTAX;
+
+                Assert.AreEqual("構文エラー: {0}", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+                Assert.AreEqual("切り捨てられたユニコード・エスケープ・シーケンス。", actual);
+
+                actual = QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+
+                Assert.AreEqual("Non-hex character in Unicode escape sequence: {0} (TEST)", actual); // Fallback to non-localized test
+
+                actual = QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS;
+
+                Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual); // Fallback to default ResourceManager
+            }
+            finally
+            {
+                QueryParserMessages.Culture = null;
+            }
+        }
+    }
+}
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserResourceProvider.cs b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserResourceProvider.cs
new file mode 100644
index 0000000..6979df4
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/TestQueryParserResourceProvider.cs
@@ -0,0 +1,113 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System.Globalization;
+using Assert = Lucene.Net.TestFramework.Assert;
+
+namespace Lucene.Net.QueryParsers.Support.Flexible.Core.Messages // LUCENENET: There is no control over the namespace for code generation other than the folder, so we must use this namespace
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public class TestQueryParserResourceProvider : LuceneTestCase
+    {
+        [Test]
+        public void TestOverrideResourceStrings()
+        {
+            var provider = new QueryParserResourceProvider(MessagesTest.ResourceManager);
+
+            var actual = provider.GetString("INVALID_SYNTAX", null);
+
+            Assert.IsTrue(actual.Contains("(TEST)"));
+
+            actual = provider.GetString("INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION", null);
+
+            Assert.IsTrue(actual.Contains("(TEST)"));
+
+            actual = provider.GetString("INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE", null);
+
+            Assert.IsTrue(actual.Contains("(TEST)"));
+
+            actual = provider.GetString("INVALID_SYNTAX_FUZZY_LIMITS", null);
+
+            Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual); // Fallback to default ResourceManager
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings_ja()
+        {
+            var provider = new QueryParserResourceProvider(MessagesTest.ResourceManager);
+
+            var actual = provider.GetString("INVALID_SYNTAX", new CultureInfo("ja"));
+
+            Assert.AreEqual("構文エラー: {0}", actual);
+
+            actual = provider.GetString("INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION", new CultureInfo("ja"));
+
+            Assert.AreEqual("切り捨てられたユニコード・エスケープ・シーケンス。", actual);
+
+            actual = provider.GetString("INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE", new CultureInfo("ja"));
+
+            Assert.AreEqual("Non-hex character in Unicode escape sequence: {0} (TEST)", actual); // Fallback to non-localized test
+
+            actual = provider.GetString("INVALID_SYNTAX_FUZZY_LIMITS", new CultureInfo("ja"));
+
+            Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual); // Fallback to default ResourceManager
+        }
+
+        [Test]
+        public void TestOverrideResourceStrings_ja_JP()
+        {
+            var provider = new QueryParserResourceProvider(MessagesTest.ResourceManager);
+
+            var actual = provider.GetString("INVALID_SYNTAX", new CultureInfo("ja-JP"));
+
+            Assert.AreEqual("構文エラー: {0}", actual);
+
+            actual = provider.GetString("INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION", new CultureInfo("ja-JP"));
+
+            Assert.AreEqual("切り捨てられたユニコード・エスケープ・シーケンス。", actual);
+
+            actual = provider.GetString("INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE", new CultureInfo("ja-JP"));
+
+            Assert.AreEqual("Non-hex character in Unicode escape sequence: {0} (TEST)", actual); // Fallback to non-localized test
+
+            actual = provider.GetString("INVALID_SYNTAX_FUZZY_LIMITS", new CultureInfo("ja-JP"));
+
+            Assert.AreEqual("The similarity value for a fuzzy search must be between 0.0 and 1.0.", actual); // Fallback to default ResourceManager
+        }
+
+        [Test]
+        public void TestGetImageAsObject()
+        {
+            // Get the expected bytes
+            using var expectedStream = GetType().Assembly.GetManifestResourceStream("Lucene.Net.QueryParsers.Support.Flexible.Core.Messages.lucene-net-icon-32x32.png");
+            byte[] expectedBytes = new byte[expectedStream.Length];
+            expectedStream.Read(expectedBytes, 0, (int)expectedStream.Length);
+
+            // Check the wrapper to ensure we can read the bytes
+            Assert.AreEqual(expectedBytes, MessagesTest.LUCENE_NET_ICON_32x32);
+
+
+            var provider = new QueryParserResourceProvider(MessagesTest.ResourceManager);
+
+            byte[] actualBytes = (byte[])provider.GetObject("LUCENE_NET_ICON_32x32", null);
+
+            Assert.AreEqual(expectedBytes, actualBytes);
+        }
+    }
+}
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/lucene-net-icon-32x32.png b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/lucene-net-icon-32x32.png
new file mode 100644
index 0000000..227b7ce
Binary files /dev/null and b/src/Lucene.Net.Tests.QueryParser/Support/Flexible/Core/Messages/lucene-net-icon-32x32.png differ
diff --git a/src/Lucene.Net/Support/Util/IResourceProvider.cs b/src/Lucene.Net/Support/Util/IResourceProvider.cs
new file mode 100644
index 0000000..034da27
--- /dev/null
+++ b/src/Lucene.Net/Support/Util/IResourceProvider.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+using System.Globalization;
+using System.Resources;
+#nullable enable
+
+namespace Lucene.Net.Util
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Contract for a set of localized resources. Generally, this is an abstraction over one or
+    /// more <see cref="ResourceManager"/> instances.
+    /// </summary>
+    public interface IResourceProvider
+    {
+        /// <summary>
+        /// Returns the value of the string resource localized for the specified <paramref name="culture"/>.
+        /// </summary>
+        /// <param name="name">The name of the resource to retrieve.</param>
+        /// <param name="culture">An object that represents the culture for which the resource is localized.</param>
+        /// <returns>The value of the resource localized for the specified <paramref name="culture"/>, or <c>null</c>
+        /// if <paramref name="name"/> cannot be found in a resource set.</returns>
+        /// <exception cref="ArgumentNullException">The <paramref name="name"/> parameter is <c>null</c>.</exception>
+        /// <exception cref="InvalidOperationException">The value of the specified resource is not a string.</exception>
+        /// <exception cref="MissingManifestResourceException">No usable set of resources has been found, and there are
+        /// no resources for a default culture. For information about how to handle this exception, see the
+        /// "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section
+        /// in the <see cref="ResourceManager"/> class topic.</exception>
+        /// <exception cref="MissingSatelliteAssemblyException">The default culture's resources reside in a satellite
+        /// assembly that could not be found. For information about how to handle this exception, see the
+        /// "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section
+        /// in the <see cref="ResourceManager"/> class topic.</exception>
+        string? GetString(string name, CultureInfo? culture);
+
+        /// <summary>
+        /// Gets the value of the specified non-string resource localized for the specified <paramref name="culture"/>.
+        /// </summary>
+        /// <param name="name">The name of the resource to get.</param>
+        /// <param name="culture">The culture for which the resource is localized. If the resource is not
+        /// localized for this culture, the resource manager uses fallback rules to locate an appropriate resource.
+        /// <para/>
+        /// If this value is <c>null</c>, the <see cref="CultureInfo"/> object is obtained by using the
+        /// <see cref="CultureInfo.CurrentUICulture"/> property.
+        /// </param>
+        /// <returns>The value of the resource, localized for the specified culture. If an appropriate resource
+        /// set exists but <paramref name="name"/> cannot be found, the method returns <c>null</c>.</returns>
+        /// <exception cref="ArgumentNullException">The <paramref name="name"/> parameter is <c>null</c>.</exception>
+        /// <exception cref="MissingManifestResourceException">No usable set of resources has been found, and there are
+        /// no resources for a default culture. For information about how to handle this exception, see the
+        /// "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section
+        /// in the <see cref="ResourceManager"/> class topic.</exception>
+        /// <exception cref="MissingSatelliteAssemblyException">The default culture's resources reside in a satellite
+        /// assembly that could not be found. For information about how to handle this exception, see the
+        /// "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section
+        /// in the <see cref="ResourceManager"/> class topic.</exception>
+        object? GetObject(string name, CultureInfo? culture);
+
+
+        /// <summary>
+        /// Returns an unmanaged memory stream object from the specified resource, using the specified <paramref name="culture"/>.
+        /// </summary>
+        /// <param name="name">The name of a resource.</param>
+        /// <param name="culture">An object that specifies the culture to use for the resource lookup. If <paramref name="culture"/>
+        /// is <c>null</c>, the culture for the current thread is used.</param>
+        /// <returns>An unmanaged memory stream object that represents a resource.</returns>
+        /// <exception cref="ArgumentNullException">The <paramref name="name"/> parameter is <c>null</c>.</exception>
+        /// <exception cref="InvalidOperationException">The value of the specified resource is not a <see cref="MemoryStream"/> object.</exception>
+        /// <exception cref="MissingManifestResourceException">No usable set of resources has been found, and there are
+        /// no resources for a default culture. For information about how to handle this exception, see the
+        /// "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section
+        /// in the <see cref="ResourceManager"/> class topic.</exception>
+        /// <exception cref="MissingSatelliteAssemblyException">The default culture's resources reside in a satellite
+        /// assembly that could not be found. For information about how to handle this exception, see the
+        /// "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section
+        /// in the <see cref="ResourceManager"/> class topic.</exception>
+        Stream? GetStream(string name, CultureInfo? culture);
+    }
+}

[lucenenet] 01/04: BREAKING: Lucene.Net.QueryParser: Factored out NLS/IMessage/Message support and changed exceptions to use string messages so end users can elect whether to use .NET localization or not

Posted by ni...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit 528f262346f881ded280c978f9bf516eb1b7bc2c
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Sat May 1 05:40:02 2021 +0700

    BREAKING: Lucene.Net.QueryParser: Factored out NLS/IMessage/Message support and changed exceptions to use string messages so end users can elect whether to use .NET localization or not
---
 .../Flexible/Core/Builders/QueryTreeBuilder.cs     |   5 +-
 ...Designer.cs => QueryParserMessages.Designer.cs} |  54 +++++-----
 .../Flexible/Core/Messages/QueryParserMessages.cs  | 115 +++++++++++----------
 ...essagesBundle.resx => QueryParserMessages.resx} |  13 ++-
 .../Flexible/Core/Messages/package.md              |   2 +-
 .../Flexible/Core/Nodes/BoostQueryNode.cs          |  11 +-
 .../Flexible/Core/Nodes/GroupQueryNode.cs          |  11 +-
 .../Flexible/Core/Nodes/ModifierQueryNode.cs       |  12 +--
 .../Flexible/Core/Nodes/PhraseSlopQueryNode.cs     |  11 +-
 .../Flexible/Core/Nodes/ProximityQueryNode.cs      |   8 +-
 .../Flexible/Core/Nodes/QueryNodeImpl.cs           |  26 ++---
 .../Flexible/Core/Nodes/SlopQueryNode.cs           |  11 +-
 .../Flexible/Core/QueryNodeError.cs                |  92 +++++++++--------
 .../Flexible/Core/QueryNodeException.cs            |  81 +++++----------
 .../Flexible/Core/QueryNodeParseException.cs       |  51 ++++-----
 .../Standard/Builders/AnyQueryNodeBuilder.cs       |   7 +-
 .../Standard/Builders/BooleanQueryNodeBuilder.cs   |   4 +-
 .../Builders/MatchAllDocsQueryNodeBuilder.cs       |   4 +-
 .../Builders/MatchNoDocsQueryNodeBuilder.cs        |   4 +-
 .../Builders/NumericRangeQueryNodeBuilder.cs       |   4 +-
 .../Builders/StandardBooleanQueryNodeBuilder.cs    |   4 +-
 .../Standard/Nodes/NumericRangeQueryNode.cs        |   4 +-
 .../Standard/Parser/EscapeQuerySyntaxImpl.cs       |  14 +--
 .../Flexible/Standard/Parser/ParseException.cs     |  54 +++++-----
 .../Standard/Parser/StandardSyntaxParser.cs        |  18 ++--
 .../Processors/AllowLeadingWildcardProcessor.cs    |   4 +-
 .../Processors/NumericQueryNodeProcessor.cs        |   7 +-
 .../Processors/NumericRangeQueryNodeProcessor.cs   |   7 +-
 .../Lucene.Net.QueryParser.csproj                  |  17 +++
 .../ExceptionHandling/ExceptionExtensions.cs       |   3 +-
 .../Spans/SpansValidatorQueryNodeProcessor.cs      |   5 +-
 .../Flexible/Standard/TestQPHelper.cs              |   6 +-
 .../Support/TestApiConsistency.cs                  |   4 +-
 .../ExceptionHandling/ExceptionExtensions.cs       |   3 +-
 34 files changed, 341 insertions(+), 335 deletions(-)

diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Builders/QueryTreeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Builders/QueryTreeBuilder.cs
index d8d69a3..3dbca49 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Builders/QueryTreeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Builders/QueryTreeBuilder.cs
@@ -1,10 +1,8 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Parser;
 using System;
 using System.Collections.Generic;
-using System.Reflection;
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Builders
 {
@@ -164,7 +162,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Builders
         {
             if (builder == null)
             {
-                throw new QueryNodeException(new Message(
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new QueryNodeException(string.Format(
                     QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, node
                         .ToQueryString(new EscapeQuerySyntax()), node.GetType()
                         .Name));
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.Designer.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.Designer.cs
similarity index 88%
rename from src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.Designer.cs
rename to src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.Designer.cs
index 6a9698a..1275ba0 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.Designer.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.Designer.cs
@@ -1,25 +1,4 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
 //     Runtime Version:4.0.30319.42000
@@ -31,9 +10,8 @@
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Messages {
     using System;
-    using System.Reflection;
-
-
+    
+    
     /// <summary>
     ///   A strongly-typed resource class, for looking up localized strings, etc.
     /// </summary>
@@ -41,17 +19,17 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Messages {
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    internal class QueryParserMessagesBundle {
+    internal class QueryParserMessages {
         
         private static global::System.Resources.ResourceManager resourceMan;
         
         private static global::System.Globalization.CultureInfo resourceCulture;
         
         [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        internal QueryParserMessagesBundle() {
+        internal QueryParserMessages() {
         }
         
         /// <summary>
@@ -61,7 +39,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Messages {
         internal static global::System.Resources.ResourceManager ResourceManager {
             get {
                 if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lucene.Net.QueryParsers.Flexible.Core.Messages.QueryParserMessagesBundle", typeof(QueryParserMessagesBundle).GetTypeInfo().Assembly);
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lucene.Net.QueryParsers.Flexible.Core.Messages.QueryParserMessages", typeof(QueryParserMessages).Assembly);
                     resourceMan = temp;
                 }
                 return resourceMan;
@@ -83,6 +61,15 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Messages {
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Value cannot be null..
+        /// </summary>
+        internal static string ARGUMENT_CANNOT_BE_NULL {
+            get {
+                return ResourceManager.GetString("ARGUMENT_CANNOT_BE_NULL", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Could not parse text &quot;{0}&quot; using {1}.
         /// </summary>
         internal static string COULD_NOT_PARSE_NUMBER {
@@ -191,6 +178,15 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Messages {
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to The parameter must be greater than or equal to zero..
+        /// </summary>
+        internal static string NUMBER_CANNOT_BE_NEGATIVE {
+            get {
+                return ResourceManager.GetString("NUMBER_CANNOT_BE_NEGATIVE", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Number class not supported by NumericRangeQueryNode: {0}.
         /// </summary>
         internal static string NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY {
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs
index 6a31e4c..103b981 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.cs
@@ -1,61 +1,64 @@
-using Lucene.Net.QueryParsers.Flexible.Messages;
+// LUCENENET specific - factored out this class to optionally use the built in .NET localization rather than
+// forcing the use of the oddly designed Message class with NLS.
 
-namespace Lucene.Net.QueryParsers.Flexible.Core.Messages
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
+//using Lucene.Net.QueryParsers.Flexible.Messages;
 
-    /// <summary>
-    /// Flexible Query Parser message bundle class
-    /// </summary>
-    public class QueryParserMessages : NLS
-    {
-        private static readonly string BUNDLE_NAME = typeof(QueryParserMessages).Name;
+//namespace Lucene.Net.QueryParsers.Flexible.Core.Messages
+//{
+//    /*
+//     * Licensed to the Apache Software Foundation (ASF) under one or more
+//     * contributor license agreements.  See the NOTICE file distributed with
+//     * this work for additional information regarding copyright ownership.
+//     * The ASF licenses this file to You under the Apache License, Version 2.0
+//     * (the "License"); you may not use this file except in compliance with
+//     * the License.  You may obtain a copy of the License at
+//     *
+//     *     http://www.apache.org/licenses/LICENSE-2.0
+//     *
+//     * Unless required by applicable law or agreed to in writing, software
+//     * distributed under the License is distributed on an "AS IS" BASIS,
+//     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     * See the License for the specific language governing permissions and
+//     * limitations under the License.
+//     */
 
-        private QueryParserMessages()
-        {
-            // Do not instantiate
-        }
+//    /// <summary>
+//    /// Flexible Query Parser message bundle class
+//    /// </summary>
+//    public class QueryParserMessages : NLS
+//    {
+//        private static readonly string BUNDLE_NAME = typeof(QueryParserMessages).Name;
 
-        static QueryParserMessages()
-        {
-            // register all string ids with NLS class and initialize static string
-            // values
-            NLS.InitializeMessages(BUNDLE_NAME, typeof(QueryParserMessages));
-        }
+//        private QueryParserMessages()
+//        {
+//            // Do not instantiate
+//        }
 
-        // static string must match the strings in the property files.
-        public static string INVALID_SYNTAX;
-        public static string INVALID_SYNTAX_CANNOT_PARSE;
-        public static string INVALID_SYNTAX_FUZZY_LIMITS;
-        public static string INVALID_SYNTAX_FUZZY_EDITS;
-        public static string INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
-        public static string INVALID_SYNTAX_ESCAPE_CHARACTER;
-        public static string INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
-        public static string NODE_ACTION_NOT_SUPPORTED;
-        public static string PARAMETER_VALUE_NOT_SUPPORTED;
-        public static string LUCENE_QUERY_CONVERSION_ERROR;
-        public static string EMPTY_MESSAGE;
-        public static string WILDCARD_NOT_SUPPORTED;
-        public static string TOO_MANY_BOOLEAN_CLAUSES;
-        public static string LEADING_WILDCARD_NOT_ALLOWED;
-        public static string COULD_NOT_PARSE_NUMBER;
-        public static string NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY;
-        public static string UNSUPPORTED_NUMERIC_DATA_TYPE;
-        public static string NUMERIC_CANNOT_BE_EMPTY;
-    }
-}
+//        static QueryParserMessages()
+//        {
+//            // register all string ids with NLS class and initialize static string
+//            // values
+//            NLS.InitializeMessages(BUNDLE_NAME, typeof(QueryParserMessages));
+//        }
+
+//        // static string must match the strings in the property files.
+//        public static string INVALID_SYNTAX;
+//        public static string INVALID_SYNTAX_CANNOT_PARSE;
+//        public static string INVALID_SYNTAX_FUZZY_LIMITS;
+//        public static string INVALID_SYNTAX_FUZZY_EDITS;
+//        public static string INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+//        public static string INVALID_SYNTAX_ESCAPE_CHARACTER;
+//        public static string INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+//        public static string NODE_ACTION_NOT_SUPPORTED;
+//        public static string PARAMETER_VALUE_NOT_SUPPORTED;
+//        public static string LUCENE_QUERY_CONVERSION_ERROR;
+//        public static string EMPTY_MESSAGE;
+//        public static string WILDCARD_NOT_SUPPORTED;
+//        public static string TOO_MANY_BOOLEAN_CLAUSES;
+//        public static string LEADING_WILDCARD_NOT_ALLOWED;
+//        public static string COULD_NOT_PARSE_NUMBER;
+//        public static string NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY;
+//        public static string UNSUPPORTED_NUMERIC_DATA_TYPE;
+//        public static string NUMERIC_CANNOT_BE_EMPTY;
+//    }
+//}
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.resx b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.resx
similarity index 95%
rename from src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.resx
rename to src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.resx
index de6a680..83f4fab 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessagesBundle.resx
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/QueryParserMessages.resx
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <!--
 
  Licensed to the Apache Software Foundation (ASF) under one
@@ -19,7 +19,6 @@
  under the License.
 
 -->
-
 <root>
   <!-- 
     Microsoft ResX Schema 
@@ -138,6 +137,10 @@
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
+  <data name="ARGUMENT_CANNOT_BE_NULL" xml:space="preserve">
+    <value>Value cannot be null.</value>
+    <comment>LUCENENET: Added to make the message more specific</comment>
+  </data>
   <data name="COULD_NOT_PARSE_NUMBER" xml:space="preserve">
     <value>Could not parse text "{0}" using {1}</value>
   </data>
@@ -177,6 +180,10 @@
   <data name="NODE_ACTION_NOT_SUPPORTED" xml:space="preserve">
     <value>This node does not support this action.</value>
   </data>
+  <data name="NUMBER_CANNOT_BE_NEGATIVE" xml:space="preserve">
+    <value>The parameter must be greater than or equal to zero.</value>
+    <comment>LUCENENET: Added to make the message more specific</comment>
+  </data>
   <data name="NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY" xml:space="preserve">
     <value>Number class not supported by NumericRangeQueryNode: {0}</value>
   </data>
@@ -195,4 +202,4 @@
   <data name="WILDCARD_NOT_SUPPORTED" xml:space="preserve">
     <value>Wildcard is not supported for query: {0}</value>
   </data>
-</root>
+</root>
\ No newline at end of file
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/package.md b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/package.md
index 8f315a0..2b80db4 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Messages/package.md
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Messages/package.md
@@ -26,4 +26,4 @@ Messages usually used by query parser implementations.
 ## Query Parser Messages
 
 
-Messages for the Flexible Query Parser use [Lucene.Net.QueryParsers.Flexible.Messages.NLS](xref:Lucene.Net.QueryParsers.Flexible.Messages.NLS) API.
\ No newline at end of file
+Messages for the Flexible Query Parser use .NET Resources. See [How to create user-defined exceptions with localized exception messages](https://docs.microsoft.com/en-us/dotnet/standard/exceptions/how-to-create-localized-exception-messages).
\ No newline at end of file
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/BoostQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/BoostQueryNode.cs
index 0384a5f..d993112 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/BoostQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/BoostQueryNode.cs
@@ -1,6 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using System.Collections.Generic;
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
@@ -39,11 +38,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         /// <param name="value">the boost value, it may vary from 0.0 to 1.0</param>
         public BoostQueryNode(IQueryNode query, float value)
         {
-            if (query == null)
-            {
-                throw new QueryNodeError(new Message(
-                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
-            }
+            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+            // LUCENENET: Added paramName parameter and changed to the same error message as the default of ArgumentNullException.
+            // However, we still need this to be an error type so it is not caught in StandardSyntaxParser.
+            if (query is null)
+                throw new QueryNodeError(QueryParserMessages.ARGUMENT_CANNOT_BE_NULL, nameof(query));
 
             this.value = value;
             IsLeaf = false;
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/GroupQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/GroupQueryNode.cs
index d5c5691..9504e0b 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/GroupQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/GroupQueryNode.cs
@@ -1,6 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using System.Collections.Generic;
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
@@ -36,11 +35,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         /// </summary>
         public GroupQueryNode(IQueryNode query)
         {
-            if (query == null)
-            {
-                throw new QueryNodeError(new Message(
-                    QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "query", "null"));
-            }
+            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+            // LUCENENET: Added paramName parameter and changed to the same error message as the default of ArgumentNullException.
+            // However, we still need this to be an error type so it is not caught in StandardSyntaxParser.
+            if (query is null)
+                throw new QueryNodeError(QueryParserMessages.ARGUMENT_CANNOT_BE_NULL, nameof(query));
 
             Allocate();
             IsLeaf = false;
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ModifierQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ModifierQueryNode.cs
index a2c810c..7b22dcb 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ModifierQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ModifierQueryNode.cs
@@ -1,7 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
-using System;
 using System.Collections.Generic;
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
@@ -45,11 +43,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         /// <param name="mod">Modifier Value</param>
         public ModifierQueryNode(IQueryNode query, Modifier mod)
         {
-            if (query == null)
-            {
-                throw new QueryNodeError(new Message(
-                    QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "query", "null"));
-            }
+            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+            // LUCENENET: Added paramName parameter and changed to the same error message as the default of ArgumentNullException.
+            // However, we still need this to be an error type so it is not caught in StandardSyntaxParser.
+            if (query is null)
+                throw new QueryNodeError(QueryParserMessages.ARGUMENT_CANNOT_BE_NULL, nameof(query));
 
             Allocate();
             IsLeaf = false;
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs
index 2a7cd60..0560cc0 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs
@@ -1,6 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
 {
@@ -36,11 +35,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         /// <exception cref="QueryNodeError">throw in overridden method to disallow</exception>
         public PhraseSlopQueryNode(IQueryNode query, int value)
         {
-            if (query == null)
-            {
-                throw new QueryNodeError(new Message(
-                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
-            }
+            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+            // LUCENENET: Added paramName parameter and changed to the same error message as the default of ArgumentNullException.
+            // However, we still need this to be an error type so it is not caught in StandardSyntaxParser.
+            if (query is null)
+                throw new QueryNodeError(QueryParserMessages.ARGUMENT_CANNOT_BE_NULL, nameof(query));
 
             this.value = value;
             IsLeaf = false;
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs
index 40fa7ba..45fe048 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs
@@ -1,6 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using System;
 using System.Collections.Generic;
 using System.Text;
@@ -71,9 +70,10 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
             {
                 if (distance <= 0)
                 {
-                    throw new QueryNodeError(new Message(
-                        QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "distance",
-                        distance));
+                    // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                    // LUCENENET: Added paramName parameter and changed the error message.
+                    // However, we still need this to be an error type so it is not caught in StandardSyntaxParser.
+                    throw new QueryNodeError(QueryParserMessages.NUMBER_CANNOT_BE_NEGATIVE, nameof(distance));
                 }
                 else
                 {
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs
index 37de4e2..be6599d 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs
@@ -1,7 +1,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
 using Lucene.Net.QueryParsers.Flexible.Core.Util;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -60,8 +59,9 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         {
             if (IsLeaf || this.clauses == null || child == null)
             {
-                throw new ArgumentException(NLS
-                    .GetLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new ArgumentException(
+                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED);
             }
 
             this.clauses.Add(child);
@@ -72,8 +72,9 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         {
             if (IsLeaf || this.clauses == null)
             {
-                throw new ArgumentException(NLS
-                    .GetLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new ArgumentException(
+                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED);
             }
 
             foreach (IQueryNode child in children)
@@ -92,19 +93,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         {
             if (IsLeaf || this.clauses == null)
             {
-                var factory = NLS.GetResourceManagerFactory();
-                ResourceManager bundle = factory.Create(typeof(QueryParserMessages));
-                string message;
-                try
-                {
-                    message = bundle.GetString(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED);
-                }
-                finally
-                {
-                    factory.Release(bundle);
-                }
-
-                throw new ArgumentException(message);
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new ArgumentException(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED);
             }
 
             // reset parent value
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs
index 664cc1d..71f0c7e 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs
@@ -1,6 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 
 namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
 {
@@ -42,11 +41,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
         /// <param name="value">slop value</param>
         public SlopQueryNode(IQueryNode query, int value)
         {
-            if (query == null)
-            {
-                throw new QueryNodeError(new Message(
-                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
-            }
+            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+            // LUCENENET: Added paramName parameter and changed to the same error message as the default of ArgumentNullException.
+            // However, we still need this to be an error type so it is not caught in StandardSyntaxParser.
+            if (query is null)
+                throw new QueryNodeError(QueryParserMessages.ARGUMENT_CANNOT_BE_NULL, nameof(query));
 
             this.value = value;
             IsLeaf = false;
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs
index 329d306..b02e2d1 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs
@@ -1,9 +1,8 @@
-using Lucene.Net.QueryParsers.Flexible.Messages;
-using System;
+using System;
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
 using System.Runtime.Serialization;
-using System.Security.Permissions;
 #endif
+#nullable enable
 
 namespace Lucene.Net.QueryParsers.Flexible.Core
 {
@@ -25,54 +24,78 @@ namespace Lucene.Net.QueryParsers.Flexible.Core
      */
 
     /// <summary>
-    /// Error class with NLS support
+    /// A query node error.
     /// </summary>
-    /// <seealso cref="NLS"/>
-    /// <seealso cref="IMessage"/>
     // LUCENENET: It is no longer good practice to use binary serialization. 
     // See: https://github.com/dotnet/corefx/issues/23584#issuecomment-325724568
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
     [Serializable]
 #endif
-    public class QueryNodeError : Exception, INLSException, IError // LUCENENET specific: Added IError for identification of the Java superclass in .NET
+    // LUCENENET specific: Added IError for identification of the Java superclass in .NET.
+    // LUCENENET specific: Subclassed ArgumentException, since in all cases, we are validating arguments. However, this exception is also filtered using the IsException() extension method in catch blocks.
+    // LUCENENET specific: Refactored constructors to be more like a .NET type and eliminated IMessage/NLS support.
+    public class QueryNodeError : ArgumentException, IError
     {
-        private readonly IMessage message; // LUCENENET: marked readonly
-
         /// <summary>
-        /// 
+        /// Initializes a new instance of <see cref="QueryNodeError"/>
+        /// with the specified <paramref name="message"/> and <paramref name="paramName"/>.
         /// </summary>
-        /// <param name="message">NLS Message Object</param>
-        public QueryNodeError(IMessage message)
-            : base(message.Key)
+        /// <param name="paramName">The name of the parameter that caused the current error.</param>
+        /// <param name="message">The message that describes the error.</param>
+        public QueryNodeError(string? message, string? paramName)
+            : base(message, paramName)
         {
-            this.message = message;
+        }
 
+        /// <summary>
+        /// Initializes a new instance of <see cref="QueryNodeError"/>
+        /// with the specified <paramref name="message"/>, <paramref name="paramName"/> and <paramref name="innerException"/>.
+        /// </summary>
+        /// <param name="paramName">The name of the parameter that caused the current error.</param>
+        /// <param name="message">The message that describes the error.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception.
+        /// If the <paramref name="innerException"/> parameter is not a <c>null</c> reference, the
+        /// current exception is raised in a catch block that handles the inner exception.</param>
+        public QueryNodeError(string? message, string? paramName, Exception? innerException)
+            : base(message, paramName, innerException)
+        {
         }
 
         /// <summary>
-        /// 
+        /// Initializes a new instance of <see cref="QueryNodeError"/>
+        /// with the specified <paramref name="message"/>.
         /// </summary>
-        /// <param name="throwable">An exception instance to wrap</param>
-        public QueryNodeError(Exception throwable)
-            : base(throwable.Message, throwable)
+        /// <param name="message">The message that describes the error.</param>
+        public QueryNodeError(string? message)
+            : base(message)
         {
         }
 
         /// <summary>
-        /// 
+        /// Initializes a new instance of <see cref="QueryNodeError"/>
+        /// with a specified inner exception that is the cause of this exception.
         /// </summary>
-        /// <param name="message">NLS Message Object</param>
-        /// <param name="throwable">An exception instance to wrap</param>
-        public QueryNodeError(IMessage message, Exception throwable)
-            : base(message.Key, throwable)
+        /// <param name="innerException">The exception that is the cause of the current exception.
+        /// If the <paramref name="innerException"/> parameter is not a <c>null</c> reference, the
+        /// current exception is raised in a catch block that handles the inner exception.</param>
+        public QueryNodeError(Exception? innerException)
+            : base(innerException?.Message, innerException)
         {
-            this.message = message;
         }
 
-        // LUCENENET: For testing purposes
-        internal QueryNodeError(string message)
-            : base(message)
-        { }
+        /// <summary>
+        /// Initializes a new instance of <see cref="QueryNodeError"/>
+        /// with a specified error message and a reference to the inner exception
+        /// that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The message that describes the error.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception.
+        /// If the <paramref name="innerException"/> parameter is not a <c>null</c> reference, the
+        /// current exception is raised in a catch block that handles the inner exception.</param>
+        public QueryNodeError(string? message, Exception? innerException)
+            : base(message, innerException)
+        {
+        }
 
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
         /// <summary>
@@ -83,20 +106,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Core
         protected QueryNodeError(SerializationInfo info, StreamingContext context)
             : base(info, context)
         {
-            message = (IMessage)info.GetValue("message", typeof(IMessage));
-        }
-
-        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
-        public override void GetObjectData(SerializationInfo info, StreamingContext context)
-        {
-            base.GetObjectData(info, context);
-            info.AddValue("message", message, typeof(IMessage));
         }
 #endif
-
-        /// <summary>
-        /// <see cref="INLSException.MessageObject"/> 
-        /// </summary>
-        public virtual IMessage MessageObject => this.message;
     }
 }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs
index 29b9080..fec0003 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs
@@ -1,11 +1,8 @@
-using Lucene.Net.QueryParsers.Flexible.Core.Messages;
-using Lucene.Net.QueryParsers.Flexible.Messages;
-using System;
-using System.Globalization;
+using System;
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
 using System.Runtime.Serialization;
-using System.Security.Permissions;
 #endif
+#nullable enable
 
 namespace Lucene.Net.QueryParsers.Flexible.Core
 {
@@ -29,44 +26,49 @@ namespace Lucene.Net.QueryParsers.Flexible.Core
     /// <summary>
     /// This exception should be thrown if something wrong happens when dealing with
     /// <see cref="Nodes.IQueryNode"/>s.
-    /// <para>
-    /// It also supports NLS messages.
-    /// </para>
     /// </summary>
-    /// <seealso cref="IMessage"/>
-    /// <seealso cref="NLS"/>
-    /// <seealso cref="INLSException"/>
     /// <seealso cref="Nodes.IQueryNode"/>
     // LUCENENET: It is no longer good practice to use binary serialization. 
     // See: https://github.com/dotnet/corefx/issues/23584#issuecomment-325724568
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
     [Serializable]
 #endif
-    public class QueryNodeException : Exception, INLSException
+    // LUCENENET specific: Refactored constructors to be more like a .NET type and eliminated IMessage/NLS support.
+    public class QueryNodeException : Exception
     {
-        protected IMessage m_message = new Message(QueryParserMessages.EMPTY_MESSAGE);
-
-        public QueryNodeException(IMessage message)
-            : base(message.Key)
+        /// <summary>
+        /// Initializes a new instance of <see cref="QueryNodeException"/>
+        /// with the specified <paramref name="message"/>.
+        /// </summary>
+        /// <param name="message">The message that describes the error.</param>
+        public QueryNodeException(string? message)
+            : base(message)
         {
-            this.m_message = message;
         }
 
-        public QueryNodeException(Exception throwable)
-            : base(throwable.Message, throwable)
+        /// <summary>
+        /// Initializes a new instance of <see cref="QueryNodeException"/>
+        /// with a specified inner exception
+        /// that is the cause of this exception.
+        /// </summary>
+        /// <param name="cause">An exception instance to wrap</param>
+        public QueryNodeException(Exception? cause)
+            : base(cause?.Message, cause)
         {
         }
 
-        public QueryNodeException(IMessage message, Exception throwable)
-            : base(message.Key, throwable)
+        /// <summary>
+        /// Initializes a new instance of <see cref="QueryNodeException"/>
+        /// with a specified error message and a reference to the inner exception
+        /// that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The message that describes the error.</param>
+        /// <param name="innerException">An exception instance to wrap</param>
+        public QueryNodeException(string? message, Exception? innerException)
+            : base(message, innerException)
         {
-            this.m_message = message;
         }
 
-        // LUCENENET: For testing purposes
-        internal QueryNodeException(string message)
-            : base(message)
-        { }
 
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
         /// <summary>
@@ -77,34 +79,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Core
         protected QueryNodeException(SerializationInfo info, StreamingContext context)
             : base(info, context)
         {
-            m_message = (IMessage)info.GetValue("m_message", typeof(IMessage));
-        }
-
-        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
-        public override void GetObjectData(SerializationInfo info, StreamingContext context)
-        {
-            base.GetObjectData(info, context);
-            info.AddValue("m_message", m_message, typeof(IMessage));
         }
 #endif
-
-        public virtual IMessage MessageObject => this.m_message;
-
-        public override string Message => GetLocalizedMessage();
-
-        public virtual string GetLocalizedMessage()
-        {
-            return GetLocalizedMessage(CultureInfo.InvariantCulture);
-        }
-
-        public virtual string GetLocalizedMessage(CultureInfo locale)
-        {
-            return this.m_message.GetLocalizedMessage(locale);
-        }
-
-        public override string ToString()
-        {
-            return this.m_message.Key + ": " + GetLocalizedMessage();
-        }
     }
 }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs
index 8b9f615..df3faf7 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs
@@ -1,10 +1,9 @@
-using Lucene.Net.QueryParsers.Flexible.Core.Messages;
-using Lucene.Net.QueryParsers.Flexible.Messages;
-using System;
+using System;
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
 using System.Runtime.Serialization;
 using System.Security.Permissions;
 #endif
+#nullable enable
 
 namespace Lucene.Net.QueryParsers.Flexible.Core
 {
@@ -37,36 +36,44 @@ namespace Lucene.Net.QueryParsers.Flexible.Core
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
     [Serializable]
 #endif
+    // LUCENENET specific: Refactored constructors to be more like a .NET type and eliminated IMessage/NLS support.
     public class QueryNodeParseException : QueryNodeException
     {
-        private string query;
+#if FEATURE_SERIALIZABLE_EXCEPTIONS
+        [NonSerialized]
+#endif
+        private string? query;
 
+#if FEATURE_SERIALIZABLE_EXCEPTIONS
+        [NonSerialized]
+#endif
         private int beginColumn = -1;
 
+#if FEATURE_SERIALIZABLE_EXCEPTIONS
+        [NonSerialized]
+#endif
         private int beginLine = -1;
 
+#if FEATURE_SERIALIZABLE_EXCEPTIONS
+        [NonSerialized]
+#endif
         private string errorToken = "";
 
-        public QueryNodeParseException(IMessage message)
+        public QueryNodeParseException(string? message)
             : base(message)
         {
         }
 
-        public QueryNodeParseException(Exception throwable)
-            : base(throwable)
+        public QueryNodeParseException(Exception? cause)
+            : base(cause)
         {
         }
 
-        public QueryNodeParseException(IMessage message, Exception throwable)
-            : base(message, throwable)
+        public QueryNodeParseException(string? message, Exception? innerException)
+            : base(message, innerException)
         {
         }
 
-        // LUCENENET: For testing purposes
-        internal QueryNodeParseException(string message)
-            : base(message)
-        { }
-
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
         /// <summary>
         /// Initializes a new instance of this class with serialized data.
@@ -93,28 +100,22 @@ namespace Lucene.Net.QueryParsers.Flexible.Core
         }
 #endif
 
-        public virtual void SetQuery(string query)
+        public virtual string? Query
         {
-            this.query = query;
-            this.m_message = new Message(
-                QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, "");
+            get => this.query;
+            set => this.query = value; // LUCENENET specific - set the message only in the constructor
         }
 
-        public virtual string Query => this.query;
-
         /// <summary>
         /// The errorToken in the query
         /// </summary>
         public virtual string ErrorToken
         {
             get => this.errorToken;
-            protected set => this.errorToken = value;
+            protected set => this.errorToken = value ?? throw new ArgumentNullException(nameof(ErrorToken)); // LUCENENET specific - added null guard clause
         }
 
-        public virtual void SetNonLocalizedMessage(IMessage message)
-        {
-            this.m_message = message;
-        }
+        // LUCENENET specific - removed SetNonLocalizedMessage() because we only set the message in the constructor
 
         /// <summary>
         /// For EndOfLine and EndOfFile ("&lt;EOF&gt;") parsing problems the last char in the
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/AnyQueryNodeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/AnyQueryNodeBuilder.cs
index 339cb09..1ed4d46 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/AnyQueryNodeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/AnyQueryNodeBuilder.cs
@@ -2,7 +2,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Builders;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.Search;
 using System.Collections.Generic;
 
@@ -59,11 +58,13 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Builders
                         }
                         catch (BooleanQuery.TooManyClausesException ex)
                         {
-                            throw new QueryNodeException(new Message(
+                            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                            throw new QueryNodeException(
                                 /*
                                  * IQQQ.Q0028E_TOO_MANY_BOOLEAN_CLAUSES,
                                  * BooleanQuery.getMaxClauseCount()
-                                 */QueryParserMessages.EMPTY_MESSAGE), ex);
+                                 */
+                                QueryParserMessages.EMPTY_MESSAGE, ex);
                         }
                     }
                 }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/BooleanQueryNodeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/BooleanQueryNodeBuilder.cs
index 8385685..64f19c3 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/BooleanQueryNodeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/BooleanQueryNodeBuilder.cs
@@ -2,7 +2,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Builders;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Parser;
 using Lucene.Net.Search;
 using System.Collections.Generic;
@@ -66,7 +65,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Builders
                         }
                         catch (BooleanQuery.TooManyClausesException ex)
                         {
-                            throw new QueryNodeException(new Message(
+                            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                            throw new QueryNodeException(string.Format(
                                 QueryParserMessages.TOO_MANY_BOOLEAN_CLAUSES, BooleanQuery
                                     .MaxClauseCount, queryNode
                                     .ToQueryString(new EscapeQuerySyntax())), ex);
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchAllDocsQueryNodeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchAllDocsQueryNodeBuilder.cs
index 791b23e..79e5cd7 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchAllDocsQueryNodeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchAllDocsQueryNodeBuilder.cs
@@ -1,7 +1,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Parser;
 using Lucene.Net.Search;
 
@@ -40,7 +39,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Builders
             // validates node
             if (!(queryNode is MatchAllDocsQueryNode))
             {
-                throw new QueryNodeException(new Message(
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new QueryNodeException(string.Format(
                     QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, queryNode
                         .ToQueryString(new EscapeQuerySyntax()), queryNode.GetType()
                         .Name));
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchNoDocsQueryNodeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchNoDocsQueryNodeBuilder.cs
index 8da02f7..67ce7bd 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchNoDocsQueryNodeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/MatchNoDocsQueryNodeBuilder.cs
@@ -1,7 +1,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Parser;
 using Lucene.Net.Search;
 
@@ -40,7 +39,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Builders
             // validates node
             if (!(queryNode is MatchNoDocsQueryNode))
             {
-                throw new QueryNodeException(new Message(
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new QueryNodeException(string.Format(
                     QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, queryNode
                         .ToQueryString(new EscapeQuerySyntax()), queryNode.GetType()
                         .Name));
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/NumericRangeQueryNodeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/NumericRangeQueryNodeBuilder.cs
index ae8197a..37b4e48 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/NumericRangeQueryNodeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/NumericRangeQueryNodeBuilder.cs
@@ -3,7 +3,6 @@ using Lucene.Net.QueryParsers.Flexible.Core;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Core.Util;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Config;
 using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
 using Lucene.Net.Search;
@@ -83,7 +82,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Builders
                         maxInclusive);
 
                 default:
-                    throw new QueryNodeException(new Message(
+                    // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                    throw new QueryNodeException(string.Format(
                       QueryParserMessages.UNSUPPORTED_NUMERIC_DATA_TYPE, numberType));
             }
         }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/StandardBooleanQueryNodeBuilder.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/StandardBooleanQueryNodeBuilder.cs
index d30e03f..8d93f16 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/StandardBooleanQueryNodeBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Builders/StandardBooleanQueryNodeBuilder.cs
@@ -2,7 +2,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Builders;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Standard.Parser;
 using Lucene.Net.Search;
@@ -65,7 +64,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Builders
                         }
                         catch (BooleanQuery.TooManyClausesException ex)
                         {
-                            throw new QueryNodeException(new Message(
+                            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                            throw new QueryNodeException(string.Format(
                                 QueryParserMessages.TOO_MANY_BOOLEAN_CLAUSES, BooleanQuery
                                     .MaxClauseCount, queryNode
                                     .ToQueryString(new EscapeQuerySyntax())), ex);
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Nodes/NumericRangeQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Nodes/NumericRangeQueryNode.cs
index 34e4d33..71b3d00 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Nodes/NumericRangeQueryNode.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Nodes/NumericRangeQueryNode.cs
@@ -1,6 +1,5 @@
 using Lucene.Net.QueryParsers.Flexible.Core;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Config;
 using System;
 using System.Text;
@@ -71,8 +70,9 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Nodes
             }
             else
             {
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
                 throw new QueryNodeException(
-                    new Message(
+                    string.Format(
                         QueryParserMessages.NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY,
                         number.GetType()));
             }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs
index 315e32b..a478fa3 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/EscapeQuerySyntaxImpl.cs
@@ -3,7 +3,6 @@ using J2N.Text;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
 using Lucene.Net.QueryParsers.Flexible.Core.Util;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using System;
 using System.Globalization;
 using System.Text;
@@ -323,14 +322,16 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
 
             if (codePointMultiplier > 0)
             {
-                throw new ParseException(new Message(
-                    QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION));
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new ParseException(
+                    QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION);
             }
 
             if (lastCharWasEscapeChar)
             {
-                throw new ParseException(new Message(
-                    QueryParserMessages.INVALID_SYNTAX_ESCAPE_CHARACTER));
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new ParseException(
+                    QueryParserMessages.INVALID_SYNTAX_ESCAPE_CHARACTER);
             }
 
             return new UnescapedCharSequence(output, wasEscaped, 0, length);
@@ -357,7 +358,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
             }
             else
             {
-                throw new ParseException(new Message(
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new ParseException(string.Format(
                     QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE, c));
             }
         }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/ParseException.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/ParseException.cs
index 609cb55..519645d 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/ParseException.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/ParseException.cs
@@ -1,14 +1,15 @@
 using Lucene.Net.QueryParsers.Flexible.Core;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.Support;
 using System;
+using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
 using System.Runtime.Serialization;
 using System.Security.Permissions;
 #endif
 using System.Text;
+#nullable enable
 
 namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
 {
@@ -43,22 +44,23 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
     [Serializable]
 #endif
+    // LUCENENET specific: Refactored constructors to be more like a .NET type and eliminated IMessage/NLS support.
     public class ParseException : QueryNodeParseException
     {
         /// <summary>
-        /// This constructor is used by the method "generateParseException"
+        /// This constructor is used by the method "GenerateParseException"
         /// in the generated parser.  Calling this constructor generates
-        /// a new object of this type with the fields "currentToken",
-        /// "expectedTokenSequences", and "tokenImage" set.
+        /// a new object of this type with the fields <see cref="CurrentToken"/>,
+        /// <see cref="ExpectedTokenSequences"/>, and <see cref="TokenImage"/> set.
         /// </summary>
-        public ParseException(Token currentTokenVal,
-            int[][] expectedTokenSequencesVal, string[] tokenImageVal)
-            : base(new Message(QueryParserMessages.INVALID_SYNTAX, Initialize(
-                currentTokenVal, expectedTokenSequencesVal, tokenImageVal)))
+        public ParseException(Token currentToken,
+            int[][] expectedTokenSequences, string[] tokenImage)
+            : base(string.Format(QueryParserMessages.INVALID_SYNTAX, Initialize(
+                currentToken, expectedTokenSequences, tokenImage)))
         {
-            this.CurrentToken = currentTokenVal;
-            this.ExpectedTokenSequences = expectedTokenSequencesVal;
-            this.TokenImage = tokenImageVal;
+            this.CurrentToken = currentToken;
+            this.ExpectedTokenSequences = expectedTokenSequences;
+            this.TokenImage = tokenImage;
         }
 
         /// <summary>
@@ -71,18 +73,27 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
         /// these constructors.
         /// </summary>
         public ParseException()
-            : base(new Message(QueryParserMessages.INVALID_SYNTAX, "Error"))
+            : base(string.Format(QueryParserMessages.INVALID_SYNTAX, "Error"))
         {
         }
 
         /// <summary>
         /// Constructor with message.
         /// </summary>
-        public ParseException(IMessage message)
+        public ParseException(string? message)
             : base(message)
         {
         }
 
+        /// <summary>
+        /// Constructor with message and inner exception.
+        /// </summary>
+        // LUCENENET specific - to allow inner exception to be added to the stack trace.
+        public ParseException(string? message, Exception? innerException)
+            : base(message, innerException)
+        {
+        }
+
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
         /// <summary>
         /// Initializes a new instance of this class with serialized data.
@@ -112,7 +123,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
         /// this object has been created due to a parse error, the token
         /// followng this token will (therefore) be the first error token.
         /// </summary>
-        public Token CurrentToken { get; set; }
+        public Token? CurrentToken { get; private set; }
 
         /// <summary>
         /// Each entry in this array is an array of integers.  Each array
@@ -121,7 +132,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
         /// </summary>
         [WritableArray]
         [SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
-        public int[][] ExpectedTokenSequences { get; set; }
+        public int[][]? ExpectedTokenSequences { get; private set; }
 
         /// <summary>
         /// This is a reference to the "tokenImage" array of the generated
@@ -130,7 +141,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
         /// </summary>
         [WritableArray]
         [SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
-        public string[] TokenImage { get; set; }
+        public string[]? TokenImage { get; private set; }
 
         /// <summary>
         /// It uses <paramref name="currentToken"/> and <paramref name="expectedTokenSequences"/> to generate a parse
@@ -144,13 +155,13 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
         /// <param name="tokenImage"></param>
         /// <returns></returns>
         private static string Initialize(Token currentToken,
-                                 int[][] expectedTokenSequences,
+                                 IList<int[]> expectedTokenSequences,
                                  string[] tokenImage)
         {
             string eol = Environment.NewLine;
             StringBuilder expected = new StringBuilder();
             int maxSize = 0;
-            for (int i = 0; i < expectedTokenSequences.Length; i++)
+            for (int i = 0; i < expectedTokenSequences.Count; i++)
             {
                 if (maxSize < expectedTokenSequences[i].Length)
                 {
@@ -184,7 +195,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
             }
             retval += "\" at line " + currentToken.Next.BeginLine + ", column " + currentToken.Next.BeginColumn;
             retval += "." + eol;
-            if (expectedTokenSequences.Length == 1)
+            if (expectedTokenSequences.Count == 1)
             {
                 retval += "Was expecting:" + eol + "    ";
             }
@@ -196,10 +207,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
             return retval;
         }
 
-        /// <summary>
-        /// The end of line string for this machine.
-        /// </summary>
-        protected string m_eol = Environment.NewLine;
+        // LUCENENET: Removed eol field, since this is available on Environment.NewLine;
 
         /// <summary>
         /// Used to convert raw characters to their escaped version
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs
index 43af963..ca61adb 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Parser/StandardSyntaxParser.cs
@@ -2,7 +2,6 @@
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Core.Parser;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
 using System;
 using System.Collections.Generic;
@@ -69,16 +68,15 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
             }
             catch (Lucene.Net.QueryParsers.Flexible.Standard.Parser.ParseException tme) // LUCENENET: Flexible QueryParser has its own ParseException that is different than the one in Support
             {
-                tme.SetQuery(query);
-                throw; // LUCENENET: CA2200: Rethrow to preserve stack details (https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2200-rethrow-to-preserve-stack-details)
+                // LUCENENET specific - removed NLS support (since .NET already has localization) so we need to re-throw the exception here with a different message. However,
+                // unlike the original Lucene code we also preserve the original message in the InnerException.
+                throw new Lucene.Net.QueryParsers.Flexible.Standard.Parser.ParseException(string.Format(QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, string.Empty), tme) { Query = query };
             }
             catch (Exception tme) when (tme.IsError())
             {
-                IMessage message = new Message(QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, tme.Message);
-                QueryNodeParseException e = new QueryNodeParseException(tme);
-                e.SetQuery(query);
-                e.SetNonLocalizedMessage(message);
-                throw e;
+                // LUCENENET specific - removed NLS support (since .NET already has localization) so we pass everything through the constructor of the
+                // exception.
+                throw new QueryNodeParseException(string.Format(QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, tme.Message), tme) { Query = query };
             }
         }
 
@@ -637,11 +635,11 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Parser
                         float fms = float.TryParse(fuzzySlop.Image.Substring(1), NumberStyles.Float, CultureInfo.InvariantCulture, out float temp) ? temp : defaultMinSimilarity;
                         if (fms < 0.0f)
                         {
-                            { if (true) throw new ParseException(new Message(QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS)); }
+                            { if (true) throw new ParseException(QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS); }
                         }
                         else if (fms >= 1.0f && fms != (int)fms)
                         {
-                            { if (true) throw new ParseException(new Message(QueryParserMessages.INVALID_SYNTAX_FUZZY_EDITS)); }
+                            { if (true) throw new ParseException(QueryParserMessages.INVALID_SYNTAX_FUZZY_EDITS); }
                         }
                         q = new FuzzyQueryNode(field, EscapeQuerySyntax.DiscardEscapeChar(term.Image), fms, term.BeginColumn, term.EndColumn);
                     }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/AllowLeadingWildcardProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/AllowLeadingWildcardProcessor.cs
index 253a51e..3ce4f55 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/AllowLeadingWildcardProcessor.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/AllowLeadingWildcardProcessor.cs
@@ -3,7 +3,6 @@ using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Core.Processors;
 using Lucene.Net.QueryParsers.Flexible.Core.Util;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Config;
 using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Standard.Parser;
@@ -72,7 +71,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
                     {
                         case '*':
                         case '?':
-                            throw new QueryNodeException(new Message(
+                            // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                            throw new QueryNodeException(string.Format(
                                 QueryParserMessages.LEADING_WILDCARD_NOT_ALLOWED, node
                                     .ToQueryString(new EscapeQuerySyntax())));
                     }
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs
index 8475cd7..861db16 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs
@@ -4,7 +4,6 @@ using Lucene.Net.QueryParsers.Flexible.Core.Config;
 using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Core.Processors;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Config;
 using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
 using Lucene.Net.Util;
@@ -91,7 +90,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
                                 }
                                 catch (FormatException e) // LUCENENET: In .NET we are expecting the framework to throw FormatException, not ParseException
                                 {
-                                    throw new QueryNodeParseException(new Message(
+                                    // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                                    throw new QueryNodeParseException(string.Format(
                                         QueryParserMessages.COULD_NOT_PARSE_NUMBER, fieldNode
                                             .GetTextAsString(), numberFormat.GetType()
                                             .AssemblyQualifiedName), e);
@@ -116,7 +116,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
                             }
                             else
                             {
-                                throw new QueryNodeParseException(new Message(
+                                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                                throw new QueryNodeParseException(string.Format(
                                     QueryParserMessages.NUMERIC_CANNOT_BE_EMPTY, fieldNode.GetFieldAsString()));
                             }
 
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs
index c1e2dda..2f89e68 100644
--- a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs
@@ -5,7 +5,6 @@ using Lucene.Net.QueryParsers.Flexible.Core.Messages;
 using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
 using Lucene.Net.QueryParsers.Flexible.Core.Processors;
 using Lucene.Net.QueryParsers.Flexible.Core.Util;
-using Lucene.Net.QueryParsers.Flexible.Messages;
 using Lucene.Net.QueryParsers.Flexible.Standard.Config;
 using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
 using Lucene.Net.Util;
@@ -89,7 +88,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
                                 }
                                 catch (FormatException e) // LUCENENET: In .NET we are expecting the framework to throw FormatException, not ParseException
                                 {
-                                    throw new QueryNodeParseException(new Message(
+                                    // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                                    throw new QueryNodeParseException(string.Format(
                                         QueryParserMessages.COULD_NOT_PARSE_NUMBER, lower
                                             .GetTextAsString(), numberFormat.ToString()), e);
                                 }
@@ -103,7 +103,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
                                 }
                                 catch (FormatException e) // LUCENENET: In .NET we are expecting the framework to throw FormatException, not ParseException
                                 {
-                                    throw new QueryNodeParseException(new Message(
+                                    // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                                    throw new QueryNodeParseException(string.Format(
                                         QueryParserMessages.COULD_NOT_PARSE_NUMBER, upper
                                             .GetTextAsString(), numberFormat.ToString()), e);
                                 }
diff --git a/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj b/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
index de5097b..20f51fe 100644
--- a/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
+++ b/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
@@ -27,6 +27,8 @@
     <TargetFrameworks>netstandard2.1;netstandard2.0</TargetFrameworks>
     <TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
 
+    <RootNamespace>Lucene.Net.QueryParsers</RootNamespace>
+    
     <AssemblyTitle>Lucene.Net.QueryParser</AssemblyTitle>
     <Description>Query parsers and parsing framework for the Lucene.Net full-text search engine library from The Apache Software Foundation.</Description>
     <PackageTags>$(PackageTags);query;queryparser</PackageTags>
@@ -50,4 +52,19 @@
     <InternalsVisibleTo Include="Lucene.Net.Tests.QueryParser" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Compile Update="Flexible\Core\Messages\QueryParserMessages.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>QueryParserMessages.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Flexible\Core\Messages\QueryParserMessages.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>QueryParserMessages.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
 </Project>
diff --git a/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs b/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs
index f4fdd2c..e31d55d 100644
--- a/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs
+++ b/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs
@@ -53,7 +53,8 @@ namespace Lucene.Net
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool IsIllegalArgumentException(this Exception e)
         {
-            if (e is null || e.IsAlwaysIgnored()) return false;
+            // If our exception implements IError and subclasses ArgumentException, we will ignore it.
+            if (e is null || e.IsError() || e.IsAlwaysIgnored()) return false;
 
             return e is ArgumentException &&
                 !(e is ArgumentNullException) &&     // Corresponds to NullPointerException, so we don't catch it here.
diff --git a/src/Lucene.Net.Tests.QueryParser/Flexible/Spans/SpansValidatorQueryNodeProcessor.cs b/src/Lucene.Net.Tests.QueryParser/Flexible/Spans/SpansValidatorQueryNodeProcessor.cs
index 5b69a8a..79b8327 100644
--- a/src/Lucene.Net.Tests.QueryParser/Flexible/Spans/SpansValidatorQueryNodeProcessor.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Flexible/Spans/SpansValidatorQueryNodeProcessor.cs
@@ -45,8 +45,9 @@ namespace Lucene.Net.QueryParsers.Flexible.Spans
             if (!((node is BooleanQueryNode && !(node is AndQueryNode)) || node
                 .GetType() == typeof(FieldQueryNode)))
             {
-                throw new QueryNodeException(new Message(
-                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+                // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                throw new QueryNodeException(
+                    QueryParserMessages.NODE_ACTION_NOT_SUPPORTED);
             }
 
             return node;
diff --git a/src/Lucene.Net.Tests.QueryParser/Flexible/Standard/TestQPHelper.cs b/src/Lucene.Net.Tests.QueryParser/Flexible/Standard/TestQPHelper.cs
index dd3e9b5..7174662 100644
--- a/src/Lucene.Net.Tests.QueryParser/Flexible/Standard/TestQPHelper.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Flexible/Standard/TestQPHelper.cs
@@ -163,9 +163,9 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard
 
                     if (node is WildcardQueryNode || node is FuzzyQueryNode)
                     {
-
-                        throw new QueryNodeException(new Message(
-                            QueryParserMessages.EMPTY_MESSAGE));
+                        // LUCENENET: Factored out NLS/Message/IMessage so end users can optionally utilize the built-in .NET localization.
+                        throw new QueryNodeException(
+                            QueryParserMessages.EMPTY_MESSAGE);
 
                     }
 
diff --git a/src/Lucene.Net.Tests.QueryParser/Support/TestApiConsistency.cs b/src/Lucene.Net.Tests.QueryParser/Support/TestApiConsistency.cs
index 28639b1..e6b625e 100644
--- a/src/Lucene.Net.Tests.QueryParser/Support/TestApiConsistency.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Support/TestApiConsistency.cs
@@ -1,4 +1,4 @@
-using Lucene.Net.Attributes;
+using Lucene.Net.Attributes;
 using Lucene.Net.Util;
 using NUnit.Framework;
 using System;
@@ -45,7 +45,7 @@ namespace Lucene.Net.QueryParsers
         [TestCase(typeof(Lucene.Net.QueryParsers.Classic.ICharStream))]
         public override void TestPublicFields(Type typeFromTargetAssembly)
         {
-            base.TestPublicFields(typeFromTargetAssembly);
+            base.TestPublicFields(typeFromTargetAssembly, @"^System\.Runtime\.CompilerServices");
         }
 
         [Test, LuceneNetSpecific]
diff --git a/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs b/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs
index eef397c..3795b7a 100644
--- a/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs
+++ b/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs
@@ -358,7 +358,8 @@ namespace Lucene
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool IsIllegalArgumentException(this Exception e)
         {
-            if (e is null || e.IsAlwaysIgnored()) return false;
+            // If our exception implements IError and subclasses ArgumentException, we will ignore it.
+            if (e is null || e.IsError() || e.IsAlwaysIgnored()) return false;
 
             // LUCENENET: In production, there is a chance that we will upgrade to ArgumentNullExcpetion or ArgumentOutOfRangeException
             // and it is still important that those are caught. However, we have a copy of this method in the test environment