Hardcoded Label Instead Of A Resource Bundle Reference
ID |
html.labels_defined_resource_bundle |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Html |
Tags |
best-practice, reliability |
Description
Reports a template component whose label is hardcoded text where a resource-bundle reference belongs.
This rule ships disabled. Every finding it produces is true by the rule’s own definition, but on a project that has deliberately not internationalised its views it fires once per label — and whether to internationalise is the project’s decision, not this catalogue’s. Switch it on for a project that has committed to a resource bundle, where the findings are the labels that were missed.
Two guards keep it narrow when it is on.
It only looks at namespaced component elements. A literal in plain HTML — <label>Customer
name</label>, <img alt="Logo"> — is not evidence of anything, because the page may have no
bundle mechanism at all, and reporting it would fire on every static page ever written. A
namespaced element such as <h:outputLabel> or <p:tab> is different: the file demonstrably uses a
component library, so the machinery for externalising its text is present and the decision not to
use it is a decision. Elements in the logic, formatting and templating namespaces (c:, fn:,
fmt:, jsp:, sql:, ui:) are skipped, because their attributes carry configuration rather
than rendered text.
The value must read as human-readable text. Not reported are values carrying a template
expression in any dialect (that is the correct form), values shorter than three characters or with
fewer than two letters, values containing a character no label contains (< > { } = | \ / : ; # & $
* ~ ^ @), and single tokens carrying a dot or an underscore, which are filenames, identifiers or
bundle keys rather than prose.
At most one finding is emitted per element: once the author is looking at the tag, naming a second attribute on it adds nothing.
Rationale
<h:form>
<h:outputLabel for="customer" value="Customer name" />
<h:inputText id="customer" title="Enter the full legal name" />
<h:commandButton value="Place order" action="#{orderBean.place}" />
<h:outputLabel for="ref" value="#{msg.orderReference}" />
</h:form>
A label baked into the markup cannot be translated, and cannot be corrected without a redeploy — a typo in a button caption becomes a release.
The form above shows the failure that matters most, which is not the absence of translation but its
partiality. The page already resolves orderReference from a bundle, so it is a translated page;
three of its four strings are not. Rendered in another language it comes out half in the user’s
language and half in the developer’s. That state is invisible to everyone who reads the application
in its original language, including the author, the reviewer and the tests — the page looks correct
in development and is broken only for the users who cannot report it clearly.
The same text also tends to be duplicated. A caption written in four views diverges in three of them; a caption resolved from a bundle key is corrected once. And an untranslated string is untranslatable by the people equipped to do it: a translator works from the bundle, and never sees a string that is not in it.
Remediation
Move the text into the resource bundle and reference it by key.
<h:form>
<h:outputLabel for="customer" value="#{msg.customerName}" />
<h:inputText id="customer" title="#{msg.customerNameHint}" />
<h:commandButton value="#{msg.placeOrder}" action="#{orderBean.place}" />
<h:outputLabel for="ref" value="#{msg.orderReference}" />
</h:form>
With the bundle declared for the view — through <f:loadBundle>, a <resource-bundle> entry in
the faces configuration, or <fmt:setBundle> for a JSP page — and the strings in a properties file
per locale:
customerName=Customer name
customerNameHint=Enter the full legal name
placeOrder=Place order
orderReference=Order reference
Keep the keys named for what the text means rather than for what it currently says, so that rewording the caption does not require renaming the key.