SE-0278: Package Manager Localized Resources

Hello Swift community,

The review of SE-0278 “Package Manager Localized Resources" begins now and runs through February 26, 2020.

Reviews are an important part of the Swift evolution process. All reviews should be made in this thread on the Swift forums or, if you would like to keep your feedback private, directly in email to me as the review manager.

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to the Swift Package Manager?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages, libraries, or package managers with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available on the Swift Evolution website.

As always, thank you for participating in Swift Evolution.

Boris Buegling
Review Manager

14 Likes

EDIT: I'm now +0.75 on this, after @GetSwifty's clarification on Foundation's localization rules

I would still like to see defaultLocalization become required, rather than be optional as I haven't seen a strong argument why it would be optional and leave the possibility of compile errors.

Original Post:

I'm +0.5 on this.

Add a new optional defaultLocalization parameter to the Package initializer to define the default localization for the resource bundle. The default localization will be used as a fallback when no other localization for a resource fits the runtime environment. SwiftPM will require that parameter be set if the package contains localized resources.

I find it awkward that we are using Swift as the language of our Package manifest, which gives a ton of compile-time guarantees, but we having a runtime enforcement of an optional parameter if a parameter is provided elsewhere in the Package definition (any Target).

If, as I mentioned in the pitch thread, we always require the defaultLocalization, every developer building their first project with resources won't encounter that error.

It also provides the added benefit of communicating to other developers what the primary development language of a package is.

This leads to a large question I have with how Package dependencies will work together through this feature. (Perhaps these are answered by well-defined practices in the Foundation Bundle APIs that I lack experience with)

How do package dependencies work together for resolving a localization request based on their independent defaultLocalization?

Given:

Package A: defaultLocalization = "de" // also supports 'en'
Package B: defaultLocalization = "fr" // also supports 'en'
Root Project C: defaultLocalization = "en"
B depends on A
C depends on B
// none support 'ru' localization

a. If the root project calls code from 'B' for ru localization, will de or fr be the fallback?
b. If, during the call of 'B' code for ru, 'B' also calls 'A', which will be the fallback? en, fr, or de?

Is the problem being addressed significant enough to warrant a change to the Swift Package Manager?

Yes, this is a large piece of support Package resources - especially in user-facing applications.

Does this proposal fit well with the feel and direction of Swift?

Given that SE-0271 has already been accepted as part of the Swift project, this feels like a natural evolution (aside from the point I made above).

If you have used other languages, libraries, or package managers with a similar feature, how do you feel that this proposal compares to those?

The proposed solution is an automated implementation of standard practices I've seen in other ecosystems.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I followed the proposal during the pitch phase, but have not used the provided implementation.

2 Likes

Mostly positive with a question that I wish were clarified in the proposal text, namely the issue mentioned above:


Yes, absolutely. Lack of it currently prevents me from using SwiftPM in some of my projects.

In general yes, but I dislike the fact that the proposal relies too much on patterns already implemented in the closed-source version of Foundation. Foundation doesn't feel "Swifty" enough to me, especially with the use of NSLocalizedString. As a side note, I wish the community had at least some impact on the development of Foundation so that these localization APIs could be reviewed and cleaned up appropriately (obviously not as a part of this proposal, but separately).

I have not used package managers which support anything similar.

I've read the proposal twice and had a quick look at the implementation PR diff.

4 Likes

Linking related discussion about this: Package Manager Localized Resources - #22 by SDGGiesbrecht

TLDR the behavior is defined, and can be changed, by the top-level Application. It can choose whether to use it's own default, or mix the defaults.

Then if the Package doesn't support either, my understanding is when a localized-resource is accessed without the needed localization, it would default to that Bundle's defaultLocalization.

Ah, thanks for clarifying. I must've missed or forgotten that part of the pitch discussion.

I've updated my original post.

Thanks @hartbit for iterating on this! I'm +1 on the general idea, the naming, and the syntax.

My main concern is (I think) similar to @Mordil. It seems like defaultLocalization should either be required, or not throw errors when it doesn't exist, e.g. missing-default-localization. I'm all for errors when a user indicates they want to do something and it's done incorrectly. However failing to compile because the PM thinks you want localized resources seems like a bad UX. At the very least it should only be a warning, but more generally I think the localization checks should be opt-in based on whether or not defaultLocalization is defined.

My other question:how does this effect or work with non-Apple platforms? The PM Resources structure (necessarily) is heavily influenced by Apple's platforms, which I'm familiar with. But the (simplified) run-time logic for resources amounts to "is it there". My expectation is an application's Localization takes into consideration the User/Platform settings. Will this work with that aspect of Linux/Windows/Android/etc? Is this approach (at both compile-time and run-time) expected to work with, or be independent of the localization systems that already exist in other environments?

1 Like
  • What is your evaluation of the proposal?

+1 overall, minus the LanguageTag type.

If we want to use it to make the API self-documenting, a typealias would be a better fit than a wrapper. I can't think of any useful APIs we would add, either. IETF language tags are 25 years old and the technology is well understood: if there truly are useful APIs to expose and which are appropriate to use in a declarative manifest, the proposal should be able to give an example.

  • Is the problem being addressed significant enough to warrant a change to the Swift Package Manager?

Absolutely. I think we all agree that localisation is incredibly important, and it is very valuable for packages to support localised resources in a cross-platform way. Foundation's Bundle API and spec already support localised resources, and the additional diagnostics which are part of this proposal are very useful.

  • Does this proposal fit well with the feel and direction of Swift?

It does appear to align well with the recent SwiftPM resources proposal. I don't really like the ".lproj" extensions in directory names, but that's part of the Bundle spec that we've already adopted and it is likely easier for tooling to keep the two aligned for now. I think we should also be investigating more modern-looking alternative structures, but that doesn't preclude accepting the existing system.

  • If you have used other languages, libraries, or package managers with a similar feature, how do you feel that this proposal compares to those?

I've used Foundation's localisation support in Obj-C. This one feels kind of familiar, for some reason...

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Read the proposal and participated in the pitch thread.


Because many packages don't have localised resources at all. For example, what should the default localisation for swift-numerics be? "English" would be incorrect, and could lead to bogus warnings/errors for packages that depend on it.

Accessing a localised resource (including which particular localisation gets selected, and how user/platform settings influence that) is Foundation's job. This is just about packaging resources up so that whatever logic Foundation uses will work with SwiftPM's resource bundles.

Some points regarding the missing-default-localization error:

  1. Resources themselves are optional and it does not make sense for a package to have a default localization if it does not contain any resources.
  2. This would happen as part of evaluating the manifest, not as an error during build time. So there isn't actually a difference in terms of when the error happens compared to a non-optional parameter, because compiling and evaluating the manifest appear as a single step to users.
1 Like

I want to interject briefly on the subject of bundles.

In preparation for needs such as these, we set up an idiomatic way to produce bundles for Linux. The relevant documentation is in the Foundation repository and it applies to all systems that use the FHS specification, such as Linux.

tl;dr: On Linux, you are supposed, modulo any bugs, to be already able to create an /some/path/<executable name>.resources directory besides /some/path/<executable name> and access those resources through e.g. Bundle.main's methods, and similar for secondary bundles. (If you need to pass a path to create a bundle, pass the path to the .resources directory.)

7 Likes

The review of SE-0278: Package Manager Localized Resources ran from February 19th through February 26th, 2020. The proposal is accepted. Thanks to everyone who participated!

Boris Buegling
Review Manager

3 Likes