Feat: Phase 2 i18n Core API - LocalizedString View and Language Management

- Add LocalizedString View component for displaying localized strings
- Add Text(localized:) convenience initializer for Text views
- Add AppState.setLanguage(_:) method for runtime language switching
- Add AppState.currentLanguage computed property
- Integrate LocalizationService into RenderLoop environment
- Remove duplicate LocalizedString function (View takes precedence)
- All 1069 tests pass

Core i18n functionality complete. Ready for Phase 3 (String Replacement)
This commit is contained in:
phranck
2026-02-14 18:28:54 +01:00
parent 978c15993e
commit f54816d099
4 changed files with 92 additions and 8 deletions
+1
View File
@@ -351,6 +351,7 @@ extension RenderLoop {
environment.keyEventDispatcher = tuiContext.keyEventDispatcher
environment.renderCache = tuiContext.renderCache
environment.preferenceStorage = tuiContext.preferences
environment.localizationService = LocalizationService.shared
return environment
}
@@ -0,0 +1,52 @@
// 🖥 TUIKit Terminal UI Kit for Swift
// LocalizationExtensions.swift
//
// Created by LAYERED.work
// License: MIT
// MARK: - Text Localization Convenience
extension Text {
/// Creates a text view with a localized string using a dot-notation key.
///
/// # Example
///
/// ```swift
/// Text(localized: "button.ok")
/// ```
///
/// This is an alternative to `LocalizedString("button.ok")` for cases where
/// you need a `Text` view directly (e.g., as a return value from a computed property).
///
/// - Parameter key: The dot-notation key for the localized string.
public init(localized key: String) {
let localizedValue = LocalizationService.shared.string(for: key)
self.init(localizedValue)
}
}
// MARK: - AppState Language Convenience
extension AppState {
/// Gets the currently active language.
public var currentLanguage: LocalizationService.Language {
LocalizationService.shared.currentLanguage
}
/// Changes the active language and triggers a re-render.
///
/// The language preference is persisted to disk and will survive app restarts.
/// The UI automatically re-renders with the new language strings.
///
/// # Example
///
/// ```swift
/// AppState.shared.setLanguage(.german)
/// ```
///
/// - Parameter language: The language to activate.
public func setLanguage(_ language: LocalizationService.Language) {
LocalizationService.shared.setLanguage(language)
setNeedsRender()
}
}
@@ -228,11 +228,3 @@ public final class LocalizationService: @unchecked Sendable {
}
}
// MARK: - Convenience
/// A localized string retrieved using a dot-notation key.
///
/// Example: `LocalizedString("button.ok")`
public func LocalizedString(_ key: String) -> String {
LocalizationService.shared.string(for: key)
}
@@ -0,0 +1,39 @@
// 🖥 TUIKit Terminal UI Kit for Swift
// LocalizedString.swift
//
// Created by LAYERED.work
// License: MIT
// MARK: - Localized String View
/// A view that displays a localized string using a dot-notation key.
///
/// The string is looked up in the current language from the localization service.
/// If the key is missing, falls back to English, then to the key itself.
///
/// # Example
///
/// ```swift
/// VStack {
/// LocalizedString("button.ok")
/// LocalizedString("error.invalid_input")
/// }
/// ```
///
/// Use this for all UI strings that need localization.
public struct LocalizedString: View {
/// The dot-notation key for the string to display.
private let key: String
/// Creates a localized string view.
///
/// - Parameter key: The dot-notation key (e.g., "button.ok", "error.invalid_input")
public init(_ key: String) {
self.key = key
}
public var body: some View {
Text(LocalizationService.shared.string(for: key))
}
}