From 804592815d8cb6020a3cc201eed3906499d079b2 Mon Sep 17 00:00:00 2001 From: Brad Baker Date: Fri, 2 Dec 2022 14:53:51 +1100 Subject: [PATCH] use class loader in getResource (#3038) --- src/main/java/graphql/i18n/I18n.java | 4 +- src/test/groovy/graphql/i18n/I18nTest.groovy | 84 ++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/main/java/graphql/i18n/I18n.java b/src/main/java/graphql/i18n/I18n.java index dd9efae54..9ae105faf 100644 --- a/src/main/java/graphql/i18n/I18n.java +++ b/src/main/java/graphql/i18n/I18n.java @@ -35,7 +35,9 @@ public enum BundleType { protected I18n(BundleType bundleType, Locale locale) { assertNotNull(bundleType); assertNotNull(locale); - this.resourceBundle = ResourceBundle.getBundle(bundleType.baseName, locale); + // load the resource bundle with this classes class loader - to help avoid confusion in complicated worlds + // like OSGI + this.resourceBundle = ResourceBundle.getBundle(bundleType.baseName, locale, I18n.class.getClassLoader()); } public ResourceBundle getResourceBundle() { diff --git a/src/test/groovy/graphql/i18n/I18nTest.groovy b/src/test/groovy/graphql/i18n/I18nTest.groovy index 7abe1346a..d8c26b221 100644 --- a/src/test/groovy/graphql/i18n/I18nTest.groovy +++ b/src/test/groovy/graphql/i18n/I18nTest.groovy @@ -1,6 +1,8 @@ package graphql.i18n import graphql.AssertException +import graphql.ExecutionInput +import graphql.TestUtil import graphql.i18n.I18n.BundleType import spock.lang.Specification @@ -26,6 +28,88 @@ class I18nTest extends Specification { } } + + def "missing resource bundles default to a base version"() { + // see https://saimana.com/list-of-country-locale-code/ + + def expected = "Validation error ({0}) : Type '{1}' definition is not executable" + + when: + def i18n = I18n.i18n(BundleType.Validation, Locale.ENGLISH) + def msg = i18n.msg("ExecutableDefinitions.notExecutableType") + + then: + msg == expected + + when: + i18n = I18n.i18n(BundleType.Validation, Locale.CHINESE) + msg = i18n.msg("ExecutableDefinitions.notExecutableType") + then: + msg == expected + + when: + i18n = I18n.i18n(BundleType.Validation, new Locale("en", "IN")) // India + msg = i18n.msg("ExecutableDefinitions.notExecutableType") + then: + msg == expected + + when: + i18n = I18n.i18n(BundleType.Validation, new Locale("en", "FJ")) // Fiji + msg = i18n.msg("ExecutableDefinitions.notExecutableType") + then: + msg == expected + + when: + i18n = I18n.i18n(BundleType.Validation, new Locale("")) // Nothing + msg = i18n.msg("ExecutableDefinitions.notExecutableType") + then: + msg == expected + } + + def "integration test of valid messages"() { + def sdl = """ + type Query { + field(arg : Int) : Subselection + } + + type Subselection { + name : String + } + """ + def graphQL = TestUtil.graphQL(sdl).build() + + + when: + def locale = new Locale("en", "IN") + def ei = ExecutionInput.newExecutionInput().query("query missingSubselectionQ { field(arg : 1) }") + .locale(locale) + .build() + def er = graphQL.execute(ei) + then: + !er.errors.isEmpty() + er.errors[0].message == "Validation error (SubselectionRequired@[field]) : Subselection required for type 'Subselection' of field 'field'" + + + when: + locale = Locale.getDefault() + ei = ExecutionInput.newExecutionInput().query("query missingSubselectionQ { field(arg : 1) }") + .locale(locale) + .build() + er = graphQL.execute(ei) + then: + !er.errors.isEmpty() + er.errors[0].message == "Validation error (SubselectionRequired@[field]) : Subselection required for type 'Subselection' of field 'field'" + + when: + // no locale - it should default + ei = ExecutionInput.newExecutionInput().query("query missingSubselectionQ { field(arg : 1) }") + .build() + er = graphQL.execute(ei) + then: + !er.errors.isEmpty() + er.errors[0].message == "Validation error (SubselectionRequired@[field]) : Subselection required for type 'Subselection' of field 'field'" + } + static def assertBundleStaticShape(ResourceBundle bundle) { def enumeration = bundle.getKeys() while (enumeration.hasMoreElements()) {