-
Notifications
You must be signed in to change notification settings - Fork 185
[Proposal]: #bundle
macro
#1251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@swift-ci please test |
Proposals/NNNN-CurrentBundle.md
Outdated
# Introduce `#bundle` | ||
|
||
|
||
* Proposal: [SF-NNNN](NNNN-filename.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Proposal: [SF-NNNN](NNNN-filename.md) | |
* Proposal: [SF-0024](NNNN-filename.md) |
@swift-ci please test |
|
||
API which loads localized strings assumes `Bundle.main` by default. This works for apps, but code that runs in a framework, or was defined in a Swift package, needs to specify a different bundle. The ultimate goal is to remove this requirement in the future. One step towards that goal is to provide an easy accessor to the bundle that stores localized resources: `#bundle`. | ||
|
||
## Motivation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example of localized resources in a framework or library is a solid motivator for this feature. But if you're interested in citing other motivators, I have one to suggest:
Swift Testing allows and recommends using structs (value types) instead of classes for grouping related test functions. Often, test authors need to reference resources in their test bundle for things like fixture data files. Historically it has been straightforward to use Bundle(forClass:)
and pass the XCTestCase subclass in the current file to accomplish this. But when using Swift Testing idiomatically, users may not have a class in the test bundle module which can conveniently serve this purpose. And of course, as its name implies, Bundle(forClass:)
does require a class meta type and doesn't accept the type of a struct. So this feature will benefit Swift Testing users and allow them to use value types for suites even more easily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I mean Bundle.init(for:)
which accepts AnyClass
, but you get the idea.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great example, I haven't thought about Swift Testing!
extension LocalizedStringResource { | ||
@_alwaysEmitIntoClient | ||
@_disfavoredOverload | ||
public init(_ keyAndValue: String.LocalizationValue, table: String? = nil, locale: Locale = .current, bundle: Bundle, comment: StaticString? = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason these couldn't declare a default value of #bundle
for the bundle:
parameter now, in this proposal, leveraging SE-0422 immediately? I see that mentioned in Alternatives Considered, but it's unclear why it couldn't or shouldn't be done now when this new extension is being introduced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bringing this up!
The other existing, similar initializer to this one is this:
LocalizedStringResource(
_ keyAndValue: String.LocalizationValue,
table: String? = nil,
locale: Locale = .current,
bundle: LocalizedStringResource.BundleDescription = .main,
comment: StaticString? = nil
)
If our new initializer only took parameters with default values, one had to be marked as disfavored, probably the new one:
@_disfavoredOverload
LocalizedStringResource(
_ keyAndValue: String.LocalizationValue,
table: String? = nil,
locale: Locale = .current,
bundle: Bundle = #bundle,
comment: StaticString? = nil
)
With the new initializer being disfavored, its default value would never take effect: LocalizedStringResource("Hello")
always uses the existing initializer, and its default values, but never the new initializer (with its default values).
To use the new initializer, one has to write LocalizedStringResource("Hello", bundle: <...>)
, in which case a default value for bundle
doesn't matter.
As eluded to in Future Directions, we can't change the default value for all bundle:
parameters this year. For consistency's sake, and because a default value here wouldn't apply anyway, I think it's better to not default anything to #bundle
for now.
This proposal adds a macro to find the bundle that contains resources useful for the current context:
#bundle
.