-
-
Notifications
You must be signed in to change notification settings - Fork 49
Description
The code generated by xcstrings-tool can be broken down into two categories:
- Definitions
- Helpers
Definitions
xcstrings-tool/Tests/XCStringsToolTests/__Snapshots__/GenerateTests/testGenerate.Localizable.swift
Lines 50 to 124 in ca65df3
| internal struct Localizable: Sendable { | |
| enum BundleDescription: Sendable { | |
| case main | |
| case atURL(URL) | |
| case forClass(AnyClass) | |
| #if !SWIFT_PACKAGE | |
| private class BundleLocator { | |
| } | |
| #endif | |
| static var current: BundleDescription { | |
| #if SWIFT_PACKAGE | |
| .atURL(Bundle.module.bundleURL) | |
| #else | |
| .forClass(BundleLocator.self) | |
| #endif | |
| } | |
| } | |
| enum Argument: Sendable { | |
| case int(Int) | |
| case uint(UInt) | |
| case float(Float) | |
| case double(Double) | |
| case object(String) | |
| var value: any CVarArg { | |
| switch self { | |
| case .int(let value): | |
| value | |
| case .uint(let value): | |
| value | |
| case .float(let value): | |
| value | |
| case .double(let value): | |
| value | |
| case .object(let value): | |
| value | |
| } | |
| } | |
| } | |
| let key: StaticString | |
| let arguments: [Argument] | |
| let table: String? | |
| let bundle: BundleDescription | |
| fileprivate init( | |
| key: StaticString, | |
| arguments: [Argument], | |
| table: String?, | |
| bundle: BundleDescription | |
| ) { | |
| self.key = key | |
| self.arguments = arguments | |
| self.table = table | |
| self.bundle = bundle | |
| } | |
| /// A key that conflicts with a keyword in swift that isn't suitable for a variable/method and should be backticked. | |
| /// | |
| /// ### Source Localization | |
| /// | |
| /// ``` | |
| /// Continue | |
| /// ``` | |
| internal static var `continue`: Localizable { | |
| Localizable( | |
| key: "continue", | |
| arguments: [], | |
| table: "Localizable", | |
| bundle: .current | |
| ) | |
| } |
Helpers
xcstrings-tool/Tests/XCStringsToolTests/__Snapshots__/GenerateTests/testGenerate.Localizable.swift
Lines 211 to 219 in ca65df3
| internal init(localizable: Localizable, locale: Locale? = nil) { | |
| let bundle: Bundle = .from(description: localizable.bundle) ?? .main | |
| let key = String(describing: localizable.key) | |
| self.init( | |
| format: bundle.localizedString(forKey: key, value: nil, table: localizable.table), | |
| locale: locale, | |
| arguments: localizable.arguments.map(\.value) | |
| ) | |
| } |
xcstrings-tool/Tests/XCStringsToolTests/__Snapshots__/GenerateTests/testGenerate.Localizable.swift
Lines 222 to 233 in ca65df3
| extension Bundle { | |
| static func from(description: String.Localizable.BundleDescription) -> Bundle? { | |
| switch description { | |
| case .main: | |
| Bundle.main | |
| case .atURL(let url): | |
| Bundle(url: url) | |
| case .forClass(let anyClass): | |
| Bundle(for: anyClass) | |
| } | |
| } | |
| } |
xcstrings-tool/Tests/XCStringsToolTests/__Snapshots__/GenerateTests/testGenerate.Localizable.swift
Lines 336 to 411 in ca65df3
| #if canImport(SwiftUI) | |
| import SwiftUI | |
| @available(macOS 10.5, iOS 13, tvOS 13, watchOS 6, *) | |
| extension Text { | |
| /// Creates a text view that displays a localized string defined in the ‘Localizable‘ strings table. | |
| internal init(localizable: String.Localizable) { | |
| if #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) { | |
| self.init(LocalizedStringResource(localizable: localizable)) | |
| return | |
| } | |
| var stringInterpolation = LocalizedStringKey.StringInterpolation(literalCapacity: 0, interpolationCount: localizable.arguments.count) | |
| for argument in localizable.arguments { | |
| switch argument { | |
| case .int(let value): | |
| stringInterpolation.appendInterpolation(value) | |
| case .uint(let value): | |
| stringInterpolation.appendInterpolation(value) | |
| case .float(let value): | |
| stringInterpolation.appendInterpolation(value) | |
| case .double(let value): | |
| stringInterpolation.appendInterpolation(value) | |
| case .object(let value): | |
| stringInterpolation.appendInterpolation(value) | |
| } | |
| } | |
| let makeKey = LocalizedStringKey.init(stringInterpolation:) | |
| var key = makeKey(stringInterpolation) | |
| key.overrideKeyForLookup(using: localizable.key) | |
| self.init(key, tableName: localizable.table, bundle: .from(description: localizable.bundle)) | |
| } | |
| } | |
| @available(macOS 10.5, iOS 13, tvOS 13, watchOS 6, *) | |
| extension LocalizedStringKey { | |
| /// Creates a localized string key that represents a localized value in the ‘Localizable‘ strings table. | |
| @available(macOS 11, iOS 14, tvOS 14, watchOS 7, *) | |
| internal init(localizable: String.Localizable) { | |
| var stringInterpolation = LocalizedStringKey.StringInterpolation(literalCapacity: 0, interpolationCount: 1) | |
| if #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) { | |
| stringInterpolation.appendInterpolation(LocalizedStringResource(localizable: localizable)) | |
| } else { | |
| stringInterpolation.appendInterpolation(Text(localizable: localizable)) | |
| } | |
| let makeKey = LocalizedStringKey.init(stringInterpolation:) | |
| self = makeKey(stringInterpolation) | |
| } | |
| /// Creates a `LocalizedStringKey` that represents a localized value in the ‘Localizable‘ strings table. | |
| @available(macOS 11, iOS 14, tvOS 14, watchOS 7, *) | |
| internal static func localizable(_ localizable: String.Localizable) -> LocalizedStringKey { | |
| LocalizedStringKey(localizable: localizable) | |
| } | |
| /// Updates the underlying `key` used when performing localization lookups. | |
| /// | |
| /// By default, an instance of `LocalizedStringKey` can only be created | |
| /// using string interpolation, so if arguments are included, the format | |
| /// specifiers make up part of the key. | |
| /// | |
| /// This method allows you to change the key after initialization in order | |
| /// to match the value that might be defined in the strings table. | |
| fileprivate mutating func overrideKeyForLookup(using key: StaticString) { | |
| withUnsafeMutablePointer(to: &self) { pointer in | |
| let raw = UnsafeMutableRawPointer(pointer) | |
| let bound = raw.assumingMemoryBound(to: String.self) | |
| bound.pointee = String(describing: key) | |
| } | |
| } | |
| } | |
| #endif |
While the helpers are helpful in getting you up and running in 95% of use cases, they are not always exactly what everybody wants. In my use case, I still have a UIKit application that does custom localizations, so the generated String.init(localizable:locale:) method is not actually useful to me because I need to resolve the language in a different way.
It would be good in my project if I could just generate the definitions, and then write my own String.init(localizable:) method that works exactly how I need it instead of using the generated one.
While I'm aware that I could still do this by just creating a method with a different name, the concern that I have with leaving the default String.init(localizable:) method is that it makes things confusing and risks potentially using the wrong method. It would be better to eliminate it entirely.