diff --git a/GliaWidgets.xcodeproj/project.pbxproj b/GliaWidgets.xcodeproj/project.pbxproj index d7852d6d6..fb08ad5f7 100644 --- a/GliaWidgets.xcodeproj/project.pbxproj +++ b/GliaWidgets.xcodeproj/project.pbxproj @@ -183,6 +183,8 @@ 311CAFCD29F8FAE20067B59F /* SecureConversations.TranscriptModel+CustomCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 311CAFCC29F8FAE20067B59F /* SecureConversations.TranscriptModel+CustomCard.swift */; }; 313EBD552943116E008E9597 /* SecureConversations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 313EBD542943116E008E9597 /* SecureConversations.swift */; }; 3142696A29FFB712003DF62E /* Interactor.Failing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3142696929FFB712003DF62E /* Interactor.Failing.swift */; }; + 3146C9432AB1851C0047D8CC /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3146C9422AB1851C0047D8CC /* LocalizationTests.swift */; }; + 3146C9492AB18AC70047D8CC /* Localization+StringProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3146C9482AB18AC70047D8CC /* Localization+StringProviding.swift */; }; 315BAB1A29ADFEBC00FF284B /* ConfirmationStyle+TitleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315BAB1929ADFEBC00FF284B /* ConfirmationStyle+TitleStyle.swift */; }; 315BAB1C29ADFEC800FF284B /* ConfirmationStyle+SubtitleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315BAB1B29ADFEC800FF284B /* ConfirmationStyle+SubtitleStyle.swift */; }; 315BAB1E29ADFED800FF284B /* ConfirmationStyle+CheckMessagesButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315BAB1D29ADFED800FF284B /* ConfirmationStyle+CheckMessagesButtonStyle.swift */; }; @@ -195,6 +197,7 @@ 3197F7B429F7C26A008EE9F7 /* SecureConversations.ChatWithTranscriptViewModel+Hashable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3197F7B329F7C26A008EE9F7 /* SecureConversations.ChatWithTranscriptViewModel+Hashable.swift */; }; 3197F7B629F7C2E5008EE9F7 /* SecureConversations.SecureChatModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3197F7B529F7C2E5008EE9F7 /* SecureConversations.SecureChatModel.swift */; }; 3197F7B829F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3197F7B729F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift */; }; + 31B1F8A92AB093ED009EC5AD /* StringProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B1F8A82AB093ED009EC5AD /* StringProviding.swift */; }; 31D286AD2A00DD2C009192A6 /* SecureConversations.ConfirmationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D286AC2A00DD2C009192A6 /* SecureConversations.ConfirmationViewModelTests.swift */; }; 31D286AF2A00DE2B009192A6 /* SecureConversations.ConfirmationViewModel.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D286AE2A00DE2B009192A6 /* SecureConversations.ConfirmationViewModel.Mock.swift */; }; 31DB0C01287C2EFC00FB288E /* StaticValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31DB0C00287C2EFC00FB288E /* StaticValues.swift */; }; @@ -915,6 +918,8 @@ 311CAFCC29F8FAE20067B59F /* SecureConversations.TranscriptModel+CustomCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SecureConversations.TranscriptModel+CustomCard.swift"; sourceTree = ""; }; 313EBD542943116E008E9597 /* SecureConversations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.swift; sourceTree = ""; }; 3142696929FFB712003DF62E /* Interactor.Failing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interactor.Failing.swift; sourceTree = ""; }; + 3146C9422AB1851C0047D8CC /* LocalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationTests.swift; sourceTree = ""; }; + 3146C9482AB18AC70047D8CC /* Localization+StringProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Localization+StringProviding.swift"; sourceTree = ""; }; 315BAB1929ADFEBC00FF284B /* ConfirmationStyle+TitleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfirmationStyle+TitleStyle.swift"; sourceTree = ""; }; 315BAB1B29ADFEC800FF284B /* ConfirmationStyle+SubtitleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfirmationStyle+SubtitleStyle.swift"; sourceTree = ""; }; 315BAB1D29ADFED800FF284B /* ConfirmationStyle+CheckMessagesButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfirmationStyle+CheckMessagesButtonStyle.swift"; sourceTree = ""; }; @@ -927,6 +932,7 @@ 3197F7B329F7C26A008EE9F7 /* SecureConversations.ChatWithTranscriptViewModel+Hashable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SecureConversations.ChatWithTranscriptViewModel+Hashable.swift"; sourceTree = ""; }; 3197F7B529F7C2E5008EE9F7 /* SecureConversations.SecureChatModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.SecureChatModel.swift; sourceTree = ""; }; 3197F7B729F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.CommonEngagementModel.swift; sourceTree = ""; }; + 31B1F8A82AB093ED009EC5AD /* StringProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringProviding.swift; sourceTree = ""; }; 31D286AC2A00DD2C009192A6 /* SecureConversations.ConfirmationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.ConfirmationViewModelTests.swift; sourceTree = ""; }; 31D286AE2A00DE2B009192A6 /* SecureConversations.ConfirmationViewModel.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.ConfirmationViewModel.Mock.swift; sourceTree = ""; }; 31DB0C00287C2EFC00FB288E /* StaticValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticValues.swift; sourceTree = ""; }; @@ -1657,7 +1663,9 @@ 1A205D5C25655CB1003AA3CD /* Info.plist */, 1A60AFAE256680EF00E53F53 /* L10n.swift */, 31E35AB92A8648E9006EC7FB /* Localization.swift */, + 3146C9482AB18AC70047D8CC /* Localization+StringProviding.swift */, 31882C9A2AA21B71009DE4BD /* Localization+Templates.swift */, + 31B1F8A82AB093ED009EC5AD /* StringProviding.swift */, 31DB0C00287C2EFC00FB288E /* StaticValues.swift */, ); path = GliaWidgets; @@ -1666,6 +1674,7 @@ 1A205D6525655CB2003AA3CD /* GliaWidgetsTests */ = { isa = PBXGroup; children = ( + 3146C9412AB1850A0047D8CC /* Resources */, 7552DFB22A6FBC6E0093519B /* CoreSdk */, 7552DFAF2A6FB37E0093519B /* ChatMessage */, 846A5C3729D18D220049B29F /* ScreenShareHandler */, @@ -2569,6 +2578,14 @@ path = ChatTranscript; sourceTree = ""; }; + 3146C9412AB1850A0047D8CC /* Resources */ = { + isa = PBXGroup; + children = ( + 3146C9422AB1851C0047D8CC /* LocalizationTests.swift */, + ); + path = Resources; + sourceTree = ""; + }; 315BAB1829ADFE9E00FF284B /* ConfirmationStyle */ = { isa = PBXGroup; children = ( @@ -4289,6 +4306,7 @@ 846A5C4029ED83C50049B29F /* CallVisualizer.Coordinator.DelegateEvent.swift in Sources */, 845876B4282AA296007AC3DF /* ButtonView.Props.Accessibility.swift in Sources */, 1A0C9AE025C9624500815406 /* ObservableValue.swift in Sources */, + 31B1F8A92AB093ED009EC5AD /* StringProviding.swift in Sources */, 75940962298D3889008B173A /* MessageMetadata.swift in Sources */, 7594094D298D37E8008B173A /* Glia.Environment.Mock.swift in Sources */, 1A60AFB9256682AF00E53F53 /* FlowCoordinator.swift in Sources */, @@ -4555,6 +4573,7 @@ 3100EEF2293E214B00D57F71 /* SecureConversations.Coordinator.swift in Sources */, 1AA738AE2578E0D500E1120F /* ConnectAnimationView.swift in Sources */, 754CC61627E2816F005676E9 /* Survey.InputQuestionView.swift in Sources */, + 3146C9492AB18AC70047D8CC /* Localization+StringProviding.swift in Sources */, 9A1992DF27D62C2E00161AAE /* ImageView.Cache.Mock.swift in Sources */, 8491AF0D2A7A9CB900CC3E72 /* Theme.VisitorChatMessageStyle.swift in Sources */, 1A2DA72D25EF9DD900032611 /* FileUpload.swift in Sources */, @@ -4788,6 +4807,7 @@ 84681A952A61844000DD7406 /* ChatViewModelTests+Gva.swift in Sources */, 847A7643285A1914004044D1 /* FileUploadListViewModelTests.swift in Sources */, 9A1992E727D66C7400161AAE /* UIKitBased.Failing.swift in Sources */, + 3146C9432AB1851C0047D8CC /* LocalizationTests.swift in Sources */, 846A5C3929D18D400049B29F /* ScreenShareHandlerTests.swift in Sources */, 9AE05CB62805D2CB00871321 /* Interactor.Environment.Failing.swift in Sources */, 846429862A45DB4100943BD6 /* AlertViewController.Kind+Mock.swift in Sources */, diff --git a/GliaWidgets/Localization+StringProviding.swift b/GliaWidgets/Localization+StringProviding.swift new file mode 100644 index 000000000..0e79e20c3 --- /dev/null +++ b/GliaWidgets/Localization+StringProviding.swift @@ -0,0 +1,22 @@ +import Foundation + +extension Localization { + static func tr( + _ table: String, + _ key: String, + _ args: CVarArg..., + fallback value: String, + stringProviding: StringProviding? = Glia.sharedInstance.stringProviding, + bundleManaging: BundleManaging = .live + ) -> String { + guard + let stringProviding, + let remoteString = stringProviding.getRemoteString(key) + else { + let format = bundleManaging.current().localizedString(forKey: key, value: value, table: table) + return String(format: format, locale: Locale.current, arguments: args) + } + + return remoteString + } +} diff --git a/GliaWidgets/Localization.swift b/GliaWidgets/Localization.swift index ae8e858d5..995ab6b96 100644 --- a/GliaWidgets/Localization.swift +++ b/GliaWidgets/Localization.swift @@ -640,25 +640,4 @@ internal enum Localization { // swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces -// MARK: - Implementation Details - -extension Localization { - private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String { - let format = BundleToken.bundle.localizedString(forKey: key, value: value, table: table) - return String(format: format, locale: Locale.current, arguments: args) - } -} - -// swiftlint:disable convenience_type -private final class BundleToken { - static let bundle: Bundle = { - #if SWIFT_PACKAGE - return Bundle.module - #else - return Bundle(for: BundleToken.self) - #endif - }() -} -// swiftlint:enable convenience_type - // swiftlint:enable all diff --git a/GliaWidgets/Public/Glia/Glia.swift b/GliaWidgets/Public/Glia/Glia.swift index 38d0efd25..8b543847e 100644 --- a/GliaWidgets/Public/Glia/Glia.swift +++ b/GliaWidgets/Public/Glia/Glia.swift @@ -57,6 +57,8 @@ public class Glia { /// Used to monitor engagement state changes. public var onEvent: ((GliaEvent) -> Void)? + var stringProviding: StringProviding? + public lazy var callVisualizer = CallVisualizer( environment: .init( data: environment.data, @@ -128,10 +130,14 @@ public class Glia { if let callback = completion { createdInteractor.withConfiguration { [weak createdInteractor] in guard let interactor = createdInteractor else { return } - interactor.state = GliaCore.sharedInstance - .getCurrentEngagement()?.engagedOperator - .map(InteractorState.engaged) ?? interactor.state - callback() + + // TODO: Configure string providing from Core SDK here. + + interactor.state = GliaCore.sharedInstance + .getCurrentEngagement()?.engagedOperator + .map(InteractorState.engaged) ?? interactor.state + + callback() } } diff --git a/GliaWidgets/StringProviding.swift b/GliaWidgets/StringProviding.swift new file mode 100644 index 000000000..cf21cda81 --- /dev/null +++ b/GliaWidgets/StringProviding.swift @@ -0,0 +1,5 @@ +import Foundation + +struct StringProviding { + var getRemoteString: ((String) -> String?) +} diff --git a/GliaWidgetsTests/Resources/LocalizationTests.swift b/GliaWidgetsTests/Resources/LocalizationTests.swift new file mode 100644 index 000000000..14a08f0c2 --- /dev/null +++ b/GliaWidgetsTests/Resources/LocalizationTests.swift @@ -0,0 +1,66 @@ +import Foundation +import XCTest +@testable import GliaWidgets + +final class LocalizationTests: XCTestCase { + let testString = "Glia" + + func test_stringProvider() { + let stringProviding = StringProviding(getRemoteString: { _ in self.testString }) + + let localizationString = Localization.tr( + "", + "", + fallback: "", + stringProviding: stringProviding + ) + + XCTAssertEqual(localizationString, testString) + } + + func test_fallback() { + let localizationString = Localization.tr( + "", + "", + fallback: testString + ) + + XCTAssertEqual(localizationString, testString) + } + + func test_fallbackWhenStringProvidingReturnsNil() { + let stringProviding = StringProviding(getRemoteString: { _ in nil }) + + let localizationString = Localization.tr( + "", + "", + fallback: testString, + stringProviding: stringProviding + ) + + XCTAssertEqual(localizationString, testString) + } + + func test_fileFromString() { + let localizationString = Localization.tr( + "Localizable", + "alert.action.settings", + fallback: "" + ) + + XCTAssertEqual(localizationString, "Settings") + } + + func test_fileFromStringWhenStringProvidingReturnsNil() { + let stringProviding = StringProviding(getRemoteString: { _ in nil }) + + let localizationString = Localization.tr( + "Localizable", + "alert.action.settings", + fallback: "", + stringProviding: stringProviding + ) + + XCTAssertEqual(localizationString, "Settings") + } +} diff --git a/swiftgen-strings.stencil b/swiftgen-strings.stencil index 62c97052d..3a56d2857 100644 --- a/swiftgen-strings.stencil +++ b/swiftgen-strings.stencil @@ -79,33 +79,6 @@ import Foundation } // swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces - -// MARK: - Implementation Details - -extension {{enumName}} { - private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String { - {% if param.lookupFunction %} - let format = {{ param.lookupFunction }}(key, table, value) - {% else %} - let format = {{param.bundle|default:"BundleToken.bundle"}}.localizedString(forKey: key, value: value, table: table) - {% endif %} - return String(format: format, locale: Locale.current, arguments: args) - } -} -{% if not param.bundle and not param.lookupFunction %} - -// swiftlint:disable convenience_type -private final class BundleToken { - static let bundle: Bundle = { - #if SWIFT_PACKAGE - return Bundle.module - #else - return Bundle(for: BundleToken.self) - #endif - }() -} -// swiftlint:enable convenience_type -{% endif %} {% else %} // No string found {% endif %}