Skip to content

Commit 3eb1eac

Browse files
Copilotpylapp
andauthored
feat: use of LocalizedStringKey and Bundle for all text-bearing components (#1366) (#1369)
Add initiatilizers with LocalizedStringKey and Bundle as parameters to load wordings for displayed texts or accessibility labels, wherever are the localizables Closes #1366 Suggested-by: François Suc <francois.suc@orange.com> Reviewed-by: Ludovic Pinel <ludovic.pinel@orange.com> Reviewed-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com> Co-authored-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com> Signed-off-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com>
1 parent c8cfc9d commit 3eb1eac

File tree

22 files changed

+1025
-5
lines changed

22 files changed

+1025
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Added
1010

11+
- `LocalizedStringKey` and `Bundle` initializers for components using `String` for texts and accessibility labels (Orange-OpenSource/ouds-ios#1366)
1112
- `oudsTintColor` view modifier helper to apply tint color from a `MultipleColorSemanticToken` (Orange-OpenSource/ouds-ios#1370)
1213
- `verbose` flag on `OUDSLogger` to suppress debug and log messages by default (Orange-OpenSource/ouds-ios#1365)
1314

1415
### Changed
1516

17+
- Update illustrations in documentation for `alert message` component (Orange-OpenSource/ouds-ios#1359)
1618
- View modifiers and methods prefixed by `ouds` are replaced by same names without such `ouds` (Orange-OpenSource/ouds-ios#1346)
1719
- Move from Xcode 26.2 to Xcode 26.3 (Orange-OpenSource/ouds-ios#1375)
18-
### Changed
19-
20-
- Update illustrations in documentation for `alert message` component (Orange-OpenSource/ouds-ios#1359)
2120

2221
## [1.3.0](https://github.com/Orange-OpenSource/ouds-ios/compare/1.2.0...1.3.0) - 2026-03-26
2322

OUDS/Core/Components/Sources/Actions/Button/OUDSButton.swift

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ import SwiftUI
5959
///
6060
/// // Text and icon with strong appearance and button taking full width
6161
/// OUDSButton(text: "Validate", icon: Image("ic_heart"), appearance: .strong, isFullWidth: true) { /* the action to process */ }
62+
///
63+
/// // Localizable from bundle can also be used
64+
/// OUDSButton(LocalizedStringKey("validate_button"), bundle: Bundle.module, appearance: .strong) { }
6265
/// ```
6366
///
6467
/// If you need to flip your icon depending to the layout direction or not (e.g. if RTL mode lose semantics / meanings):
@@ -173,6 +176,41 @@ public struct OUDSButton: View {
173176

174177
// MARK: Initializers
175178

179+
// swiftlint:disable function_default_parameter_at_end
180+
/// Creates a button with a localized text and icon, looking up the key in the given bundle..
181+
/// A raw string can also be given to be displayed.
182+
///
183+
/// ```swift
184+
/// // Use localizable
185+
/// OUDSButton(LocalizedStringKey("validate_button"), bundle: Bundle.module, icon: Image("ic_checkmark"), appearance: .strong) { }
186+
/// ```
187+
///
188+
/// - Parameters:
189+
/// - key: A `LocalizedStringKey` used to look up the text in the given bundle, or a raw `String` to display
190+
/// - tableName: The name of the `.strings` file, or `nil` for the default
191+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
192+
/// - icon: An image which shoud contains an icon
193+
/// - flipIcon: Default set to `false`, set to `true` to reverse the image (i.e. flip vertically)
194+
/// - appearance: The button appearance, default set to `.default`
195+
/// - style: The button style, default set to `.default`
196+
/// - isFullWidth: Flag to let button take all the screen width, set to *false* by default.
197+
/// - action: The action to perform when the user triggers the button
198+
public init(_ key: LocalizedStringKey,
199+
tableName: String? = nil,
200+
bundle: Bundle = .main,
201+
icon: Image,
202+
flipIcon: Bool = false,
203+
appearance: Appearance = .default,
204+
style: Style = .default,
205+
isFullWidth: Bool = false,
206+
action: @escaping () -> Void)
207+
{
208+
let resolvedText = key.resolved(tableName: tableName, bundle: bundle)
209+
self.init(text: resolvedText, icon: icon, flipIcon: flipIcon, style: style, isFullWidth: isFullWidth, action: action)
210+
}
211+
212+
// swiftlint:enable function_default_parameter_at_end
213+
176214
/// Creates a button with text and icon.
177215
///
178216
/// - Parameters:
@@ -196,10 +234,35 @@ public struct OUDSButton: View {
196234
self.style = style
197235
self.isFullWidth = isFullWidth
198236
self.action = action
199-
200237
isHover = false
201238
}
202239

240+
/// Creates a button with an icon only.
241+
///
242+
/// - Parameters:
243+
/// - icon: An image which shoud contains an icon
244+
/// - key: The text to vocalize with *Voice Over* describing the button action, as as `LocalizedStringKey` for the given `Bundle`
245+
/// - tableName: The name of the `.strings` file, or `nil` for the default
246+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
247+
/// - flipIcon: Default set to `false`, set to `true` to reverse the image (i.e. flip vertically)
248+
/// - appearance: The button appearance, default set to `.default`
249+
/// - style: The button style, default set to `.default`
250+
/// - isFullWidth: Flag to let button take all the screen width, set to *false* by default.
251+
/// - action: The action to perform when the user triggers the button
252+
public init(icon: Image,
253+
accessibilityLabel key: LocalizedStringKey,
254+
tableName: String? = nil,
255+
bundle: Bundle = .main,
256+
flipIcon: Bool = false,
257+
appearance: Appearance = .default,
258+
style: Style = .default,
259+
isFullWidth: Bool = false,
260+
action: @escaping () -> Void)
261+
{
262+
let resolvedText = key.resolved(tableName: tableName, bundle: bundle)
263+
self.init(icon: icon, accessibilityLabel: resolvedText, flipIcon: flipIcon, appearance: appearance, style: style, isFullWidth: isFullWidth, action: action)
264+
}
265+
203266
/// Creates a button with an icon only.
204267
///
205268
/// - Parameters:
@@ -226,6 +289,32 @@ public struct OUDSButton: View {
226289
isHover = false
227290
}
228291

292+
/// Creates a button with a localized text only, looking up the key in the given bundle.
293+
///
294+
/// ```swift
295+
/// OUDSButton(LocalizedStringKey("delete_button"), bundle: Bundle.module, appearance: .negative) { }
296+
/// ```
297+
///
298+
/// - Parameters:
299+
/// - key: A `LocalizedStringKey` used to look up the text in the given bundle
300+
/// - tableName: The name of the `.strings` file, or `nil` for the default
301+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
302+
/// - appearance: The button appearance, default set to `.default`
303+
/// - style: The button style, default set to `.default`
304+
/// - isFullWidth: Flag to let button take all the screen width, set to *false* by default.
305+
/// - action: The action to perform when the user triggers the button
306+
public init(_ key: LocalizedStringKey,
307+
tableName: String? = nil,
308+
bundle: Bundle = .main,
309+
appearance: Appearance = .default,
310+
style: Style = .default,
311+
isFullWidth: Bool = false,
312+
action: @escaping () -> Void)
313+
{
314+
let resolvedText = key.resolved(tableName: tableName, bundle: bundle)
315+
self.init(text: resolvedText, appearance: appearance, style: style, isFullWidth: isFullWidth, action: action)
316+
}
317+
229318
/// Create a button with a text only.
230319
///
231320
/// - Parameters:

OUDS/Core/Components/Sources/ContentDisplay/BulletList/OUDSBulletList.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,38 @@ public struct OUDSBulletList: View {
195195
self.subListHasBoldText = subListHasBoldText
196196
self.subItems = subItems()
197197
}
198+
199+
/// Creates a bullet list item with a localized text, looking up the key in the given bundle.
200+
///
201+
/// ```swift
202+
/// OUDSBulletList.Item(LocalizedStringKey("item_label"), bundle: Bundle.module)
203+
/// ```
204+
///
205+
/// - Parameters:
206+
/// - key: A `LocalizedStringKey` used to look up the text in the given bundle
207+
/// - tableName: The name of the `.strings` file, or `nil` for the default
208+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
209+
/// - subListType: The specific `OUDSBulletList.Type` for the nested sub-list, if any. If `nil`,
210+
/// the type is inherited from the parent list.
211+
/// - subListTextStyle: The specific `OUDSBulletList.TextStyle` for the nested sub-list, if any. If
212+
/// `nil`, the text style is inherited from the parent list.
213+
/// - subListHasBoldText: Whether the text of the nested sub-list should be bold. If `nil`, the bold
214+
/// setting is inherited from the parent list.
215+
/// - subItems: The sub items builder to add to the current item. **Remark** only three levels are allowed.
216+
public init(_ key: LocalizedStringKey,
217+
tableName: String? = nil,
218+
bundle: Bundle = .main,
219+
subListType: OUDSBulletList.`Type`? = nil,
220+
subListTextStyle: OUDSBulletList.TextStyle? = nil,
221+
subListHasBoldText: Bool? = nil,
222+
@OUDSBulletListItemBuilder subItems: () -> [OUDSBulletList.Item] = { [] })
223+
{
224+
text = key.resolved(tableName: tableName, bundle: bundle)
225+
self.subListType = subListType
226+
self.subListTextStyle = subListTextStyle
227+
self.subListHasBoldText = subListHasBoldText
228+
self.subItems = subItems()
229+
}
198230
}
199231

200232
// swiftlint:enable discouraged_optional_boolean

OUDS/Core/Components/Sources/Controls/Checkbox/OUDSCheckbox.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,28 @@ public struct OUDSCheckbox: View {
105105

106106
// MARK: Initializers
107107

108+
/// Creates a checkbox with only an indicator.
109+
///
110+
/// **The design system does not allow to have both an error or read only situation and a disabled state for the component.**
111+
///
112+
/// - Parameters:
113+
/// - isOn: A binding to a property that determines whether the indicator is ticked (selected) or not (not selected)
114+
/// - key: The text to vocalize with *Voice Over* the component must have, as as `LocalizedStringKey` for the given `Bundle`
115+
/// - tableName: The name of the `.strings` file, or `nil` for the default
116+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
117+
/// - isError: True if the look and feel of the component must reflect an error state, default set to `false`
118+
/// - isReadOnly: True if the look and feel of the component must reflect a read only state, default set to `false`
119+
public init(isOn: Binding<Bool>,
120+
accessibilityLabel key: LocalizedStringKey,
121+
tableName: String? = nil,
122+
bundle: Bundle = .main,
123+
isError: Bool = false,
124+
isReadOnly: Bool = false)
125+
{
126+
let resolvedText = key.resolved(tableName: tableName, bundle: bundle)
127+
self.init(isOn: isOn, accessibilityLabel: resolvedText, isError: isError, isReadOnly: isReadOnly)
128+
}
129+
108130
/// Creates a checkbox with only an indicator.
109131
///
110132
/// **The design system does not allow to have both an error or read only situation and a disabled state for the component.**

OUDS/Core/Components/Sources/Controls/Checkbox/OUDSCheckboxIndeterminate.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,28 @@ public struct OUDSCheckboxIndeterminate: View {
105105

106106
// MARK: - Initializers
107107

108+
/// Creates a checkbox with only an indicator.
109+
///
110+
/// **The design system does not allow to have both an error situation and a disabled state for the component.**
111+
///
112+
/// - Parameters:
113+
/// - selection: A binding to a property that determines whether the indicator is ticked, unticked or preticked.
114+
/// - key: The text to vocalize with *Voice Over* the component must have, as as `LocalizedStringKey` for the given `Bundle`
115+
/// - tableName: The name of the `.strings` file, or `nil` for the default
116+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
117+
/// - isError: True if the look and feel of the component must reflect an error state, default set to `false`
118+
/// - isReadOnly: True if the look and feel of the component must reflect a read only state, default set to `false`
119+
public init(selection: Binding<OUDSCheckboxIndicatorState>,
120+
accessibilityLabel key: LocalizedStringKey,
121+
tableName: String? = nil,
122+
bundle: Bundle = .main,
123+
isError: Bool = false,
124+
isReadOnly: Bool = false)
125+
{
126+
let resolvedText = key.resolved(tableName: tableName, bundle: bundle)
127+
self.init(selection: selection, accessibilityLabel: resolvedText, isError: isError, isReadOnly: isReadOnly)
128+
}
129+
108130
/// Creates a checkbox with only an indicator.
109131
///
110132
/// **The design system does not allow to have both an error situation and a disabled state for the component.**

OUDS/Core/Components/Sources/Controls/Checkbox/OUDSCheckboxItem.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ import SwiftUI
7070
/// // The default layout will be used here.
7171
/// OUDSCheckboxItem("Hello world", isOn: $isOn)
7272
///
73+
/// // Localizable from bundle can also be used
74+
/// OUDSCheckboxItem(LocalizedStringKey("agree_terms"), bundle: Bundle.module, isOn: $isOn)
75+
///
7376
/// // A leading checkbox with a label, but in read only mode (user cannot interact yet, but not disabled).
7477
/// // The default layout will be used here.
7578
/// OUDSCheckboxItem("Hello world", isOn: $isOn, isReadOnly: true)
@@ -294,6 +297,61 @@ public struct OUDSCheckboxItem: View {
294297
self.action = action
295298
}
296299

300+
// swiftlint:disable function_default_parameter_at_end
301+
/// Creates a checkbox with a localized label, looking up the key in the given bundle.
302+
///
303+
/// ```swift
304+
/// OUDSCheckboxItem(LocalizedStringKey("agree_terms"), bundle: Bundle.module, isOn: $isOn)
305+
/// ```
306+
///
307+
/// **The design system does not allow to have both an error situation and a read only mode for the component.**
308+
///
309+
/// - Parameters:
310+
/// - key: A `LocalizedStringKey` used to look up the label in the given bundle
311+
/// - tableName: The name of the `.strings` file, or `nil` for the default
312+
/// - bundle: The bundle in which to look up the localized string. Defaults to `Bundle.main`.
313+
/// - isOn: A binding to a property that determines whether the indicator is ticked (selected) or not (unselected)
314+
/// - description: An additional helper text, a description, which should not be empty, default set to `nil`
315+
/// - icon: An optional icon, default set to `nil`
316+
/// - flipIcon: Default set to `false`, set to `true` to reverse the image (i.e. flip vertically)
317+
/// - isReversed: `true` if the checkbox indicator must be in trailing position, `false` otherwise. Default to `false`
318+
/// - isError: `true` if the look and feel of the component must reflect an error state, default set to `false`
319+
/// - errorText: An optional error message to display at the bottom. This message is ignored if `isError` is `false`.
320+
/// - isReadOnly: True if component is in read only, default set to `false`
321+
/// - hasDivider: If `true` a divider is added at the bottom of the view, by default set to `false`
322+
/// - constrainedMaxWidth: When `true`, the item width is constrained to a maximum value defined by the design system.
323+
/// - action: An additional action to trigger when the checkbox has been pressed
324+
public init(_ key: LocalizedStringKey,
325+
tableName: String? = nil,
326+
bundle: Bundle = .main,
327+
isOn: Binding<Bool>,
328+
description: String? = nil,
329+
icon: Image? = nil,
330+
flipIcon: Bool = false,
331+
isReversed: Bool = false,
332+
isError: Bool = false,
333+
errorText: String? = nil,
334+
isReadOnly: Bool = false,
335+
hasDivider: Bool = false,
336+
constrainedMaxWidth: Bool = false,
337+
action: (() -> Void)? = nil)
338+
{
339+
self.init(key.resolved(tableName: tableName, bundle: bundle),
340+
isOn: isOn,
341+
description: description,
342+
icon: icon,
343+
flipIcon: flipIcon,
344+
isReversed: isReversed,
345+
isError: isError,
346+
errorText: errorText,
347+
isReadOnly: isReadOnly,
348+
hasDivider: hasDivider,
349+
constrainedMaxWidth: constrainedMaxWidth,
350+
action: action)
351+
}
352+
353+
// swiftlint:enable function_default_parameter_at_end
354+
297355
// MARK: Body
298356

299357
public var body: some View {

0 commit comments

Comments
 (0)