Skip to content

Commit 5797314

Browse files
committed
Adapted Documentation
1 parent 0e49dfc commit 5797314

File tree

1 file changed

+170
-2
lines changed

1 file changed

+170
-2
lines changed

modules/cui-jsf-api/doc/message-i18n-handling.adoc

Lines changed: 170 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,178 @@
66

77
link:../README.adoc[Back to README]
88

9-
This document describes the message internationalization (i18n) handling in the CUI JSF API, which relies on `de.cuioss.portal.common.bundle.ResourceBundleLocator` with `de.cuioss.jsf.api.application.message.MessageProducer` as the central aspect.
10-
119
toc::[]
1210

11+
== LabelProvider Pattern: Component-Level Internationalization
12+
13+
A central aspect of CUI JSF is promoting internationalization (i18n) through the `LabelProvider` pattern. This pattern is used extensively throughout the framework to provide consistent, internationalized labels for components.
14+
15+
=== Overview of the LabelProvider Pattern
16+
17+
The `LabelProvider` pattern consists of several key components:
18+
19+
1. **LabelProvider Class**: Manages the state and resolving of label strings for components
20+
2. **LabelResolver Class**: Resolves labels based on either a key (for resource bundle lookup) or a direct value
21+
3. **ComponentBridge Interface**: Connects partial implementations to their owning UIComponent
22+
4. **ResourceBundleWrapper**: Provides access to internationalized messages
23+
24+
=== LabelProvider Implementation
25+
26+
The `LabelProvider` class (`de.cuioss.jsf.api.components.partial.LabelProvider`) implements a consistent approach to handling internationalized labels with the following key attributes:
27+
28+
* **labelKey**: The key for looking up text in a resource bundle
29+
* **labelValue**: A direct value to use as the label (takes precedence over labelKey)
30+
* **labelConverter**: Optional converter for non-string labelValue objects
31+
* **labelEscape**: Controls whether the label should be HTML-escaped (default: true)
32+
33+
[source,java]
34+
----
35+
public class LabelProvider {
36+
// State management for label attributes
37+
private final CuiState state;
38+
private final ComponentBridge componentBridge;
39+
40+
// Constructor requires a bridge to the owning component
41+
public LabelProvider(@NonNull ComponentBridge bridge) {
42+
state = new CuiState(bridge.stateHelper());
43+
componentBridge = bridge;
44+
}
45+
46+
// Getters and setters for label attributes
47+
public String getLabelKey() { /* implementation */ }
48+
public void setLabelKey(String labelKey) { /* implementation */ }
49+
public Serializable getLabelValue() { /* implementation */ }
50+
public void setLabelValue(Serializable labelValue) { /* implementation */ }
51+
public Object getLabelConverter() { /* implementation */ }
52+
public void setLabelConverter(Object labelConverter) { /* implementation */ }
53+
public boolean isLabelEscape() { /* implementation */ }
54+
public void setLabelEscape(boolean labelEscape) { /* implementation */ }
55+
56+
// Resolves the label based on the configured attributes
57+
public String resolveLabel() {
58+
final var labelValue = getLabelValue();
59+
final var labelKey = getLabelKey();
60+
if (labelValue == null && MoreStrings.isEmpty(labelKey)) {
61+
return null;
62+
}
63+
return LabelResolver.builder()
64+
.withConverter(getLabelConverter())
65+
.withLabelKey(labelKey)
66+
.withEscape(isLabelEscape())
67+
.withLabelValue(labelValue)
68+
.build()
69+
.resolve(componentBridge.facesContext());
70+
}
71+
}
72+
----
73+
74+
=== LabelResolver: The Resolution Engine
75+
76+
The `LabelResolver` class handles the actual resolution of labels following this algorithm:
77+
78+
1. If `labelValue` is provided, it's converted to a string using the specified converter
79+
2. If `labelKey` is provided, it's looked up in the appropriate resource bundle
80+
3. If neither is available, it returns null (or throws an exception in strict mode)
81+
82+
[source,java]
83+
----
84+
@Builder(setterPrefix = "with")
85+
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
86+
public class LabelResolver {
87+
private final String labelKey;
88+
private final Serializable labelValue;
89+
private final Object converter;
90+
private final Boolean strictMode;
91+
92+
@Builder.Default
93+
private final boolean escape = true;
94+
95+
public String resolve(final FacesContext context) {
96+
// Resolution logic
97+
if (null != labelValue) {
98+
// Convert labelValue to string using appropriate converter
99+
// Code to resolve and use converter omitted for brevity
100+
return "converted value";
101+
}
102+
if (!MoreStrings.isEmpty(labelKey)) {
103+
// Look up labelKey in resource bundle
104+
return PortalBeanManager.resolveRequiredBean(ResourceBundleWrapper.class).getString(labelKey);
105+
}
106+
return null;
107+
}
108+
}
109+
----
110+
111+
=== Integration with Component Architecture
112+
113+
The `LabelProvider` integrates with the CUI JSF component architecture through the partial implementation pattern. Components that need internationalized labels:
114+
115+
1. Implement the `ComponentBridge` interface
116+
2. Create an instance of `LabelProvider`
117+
3. Delegate label-related methods to the provider
118+
119+
[source,java]
120+
----
121+
public class Button extends HtmlOutcomeTargetButton implements ComponentBridge {
122+
123+
@Delegate
124+
private final LabelProvider labelProvider;
125+
126+
public Button() {
127+
labelProvider = new LabelProvider(this);
128+
}
129+
130+
@Override
131+
public StateHelper stateHelper() {
132+
return getStateHelper();
133+
}
134+
135+
@Override
136+
public FacesContext facesContext() {
137+
return getFacesContext();
138+
}
139+
}
140+
----
141+
142+
=== Benefits of the LabelProvider Pattern
143+
144+
1. **Consistency**: Provides a uniform approach to internationalization across all components
145+
2. **Flexibility**: Supports both resource bundle keys and direct values
146+
3. **Separation of Concerns**: Isolates i18n logic from other component functionality
147+
4. **Reusability**: Can be easily added to any component through composition
148+
5. **Maintainability**: Centralizes i18n handling logic for easier updates and bug fixes
149+
150+
=== Usage Examples
151+
152+
==== Basic Usage with Resource Bundle Key
153+
154+
[source,xml]
155+
----
156+
<cui:button labelKey="button.save" />
157+
----
158+
159+
==== Direct Value with Converter
160+
161+
[source,xml]
162+
----
163+
<cui:outputLabel labelValue="#{bean.dateValue}" labelConverter="javax.faces.DateTime" />
164+
----
165+
166+
==== Combining with Other Attributes
167+
168+
[source,xml]
169+
----
170+
<cui:labeledContainer labelKey="form.address"
171+
labelEscape="false"
172+
styleClass="address-container">
173+
<!-- Container content -->
174+
</cui:labeledContainer>
175+
----
176+
177+
== Message Internationalization Framework
178+
179+
This document also describes the message internationalization (i18n) handling in the CUI JSF API, which relies on `de.cuioss.portal.common.bundle.ResourceBundleLocator` with `de.cuioss.jsf.api.application.message.MessageProducer` as the central aspect.
180+
13181
== Overview
14182

15183
The CUI JSF API provides a comprehensive framework for handling internationalized messages in JSF applications. The system is designed to simplify the creation and management of `FacesMessage` objects while ensuring proper resource bundle resolution and message formatting.

0 commit comments

Comments
 (0)