@groovy.transform.CompileStatic final class I18nBundleIndex extends java.lang.Object implements java.io.Serializable
The set of message-bundle base names and locales a Grails artifact contributes, resolved once at
build time from the file names under grails-app/i18n.
Spring Boot's ResourceBundleMessageSource is configured with base names, not files, so
the split between a base name and its locale suffix has to happen somewhere. Doing it here means
malformed names fail the build, no runtime consumer re-parses file names, and the base-name list,
the available-locale list and the native-image resource hints cannot drift apart.
Splitting at the first underscore is wrong: applications may use any base name, so
api_errors.properties would be misread as base name api with the malformed locale
errors. But file names alone are genuinely ambiguous — api_fr.properties could be
base name api in French, or an unsuffixed base name api_fr. Unrestricted base
names, automatic locale inference and rejection of every malformed suffix cannot all hold at once,
so the convention is stated rather than guessed:
A trailing valid locale identifier is a locale suffix. Application base names are otherwise unrestricted, but base names ending in a valid locale identifier are reserved, because they are ambiguous under Java java.util.ResourceBundle conventions.
Where that convention gets it wrong, declare the base name explicitly:
grails {
i18n {
basenames = ['api', 'api_errors']
}
}
Worked examples:
| Files | Result |
|---|---|
messages, messages_de | base name messages, locale de |
api_errors, api_errors_fr | base name api_errors, locale fr |
api_fr alone | base name api, locale fr — then fails, no api.properties |
messages, messages_dee | build failure — dee looks like a mistyped locale |
api, api_errors | build failure unless api_errors is declared |
| Type | Name and description |
|---|---|
static java.lang.String |
PROPERTIES_SUFFIXBundle file extension; the only extension ResourceBundleMessageSource reads from the classpath. |
static java.lang.String |
UPGRADE_REFERENCEAppended to every failure so the reader can find the full rationale rather than re-deriving the naming rules from a one-line error. |
java.util.List<java.lang.String> |
basenamesBase names, in stable alphabetical order. |
java.util.List<java.lang.String> |
localesLocale identifiers ( de, pt_BR), in stable alphabetical order. |
| Type Params | Return Type | Name and description |
|---|---|---|
|
static I18nBundleIndex |
from(java.util.Collection<java.lang.String> fileNames, java.util.Collection<java.lang.String> declaredBasenames)Resolves the index for one artifact. |
|
boolean |
isEmpty()true when this artifact contributes no message bundles at all. |
| Methods inherited from class | Name |
|---|---|
class java.lang.Object |
java.lang.Object#equals(java.lang.Object), java.lang.Object#getClass(), java.lang.Object#hashCode(), java.lang.Object#notify(), java.lang.Object#notifyAll(), java.lang.Object#toString(), java.lang.Object#wait(), java.lang.Object#wait(long), java.lang.Object#wait(long, int) |
Bundle file extension; the only extension ResourceBundleMessageSource reads from the classpath.
Appended to every failure so the reader can find the full rationale rather than re-deriving the naming rules from a one-line error.
Base names, in stable alphabetical order.
Locale identifiers (de, pt_BR), in stable alphabetical order.
Resolves the index for one artifact.
fileNames - bundle file names, with or without the .properties extensiondeclaredBasenames - base names declared through grails { i18n { basenames }}true when this artifact contributes no message bundles at all.