Package Manager Localized Resources

For me it's a term I usually have to look up when I use it. Both because it's not something I have to work with regularly, (usually set up once per project), and because for me it's an unintuitive name so it's something I would have to memorize, rather than find by typing what I expect the name to be.

FWIW the key is CFBundle DevelopmentRegion :wink:. If the developmentRegion would end up in a target's bundle, why not start with it there?

This may be a question that can only be answered by Apple folk, but at runtime in e.g. an iOS app, wouldn't the app's default region be used when querying a package bundle's resources? I was thinking the package's localization priority would only be for executable and test targets.

1 Like

Whether or not embedded bundles should attempt to use the same localization as the main application is controlled by CFBundleAllowMixedLocalizations. Without it, the application tries to display everything uniformly according the top‐level localization. With it, each bundle is given freedom to choose something closer to the user’s preferences instead. Each mode has its tradeoffs.

But either way, CFBundleDevelopmentRegion only comes into play when the available localizations are completely disjoint with the set requested. If an underlying package provides Spanish (as dev), French and German, but the application provides Chinese (as dev), Japanese and Korean, and the user has configured Arabic, Urdu or Farsi, then the development region will cause the package to resolve to Spanish and the application to Chinese.

Ah that's not something I've had to deal with. The summary being that, correct me if I'm wrong, an application decides whether to use the default Localization in a package, or to override it with it's own.

So I know this only works for processed resources, but presumably copied resources with the correct structure will continue to work with the bundle localisation APIs; we just won't get validation by SwiftPM.

In that case, could we perhaps have a LocalizationType parameter on Resource.copy which allows us to opt-in to that validation? Just like we have for .process.

Also, it would be nice to include a link to the Bundle programming guide, which is as close as it gets to a Bundle "spec" AFAIK.

Yes, copied resources with the correct structure will continue to work with the bundle localisation APIs. I did not add a LocalizationType parameter to them because it exponentially complicates the logic for validating localization resources. If it is strongly requested, I can try to implement it, but I'm skeptical that it is worth the complexity.

You may have missed it, but I currently have a link to The Bundle Search Pattern in the proposal. Do you think the link to the Bundle Programming Guide is still useful?

IIRC, linux does not support .process resources. However, it does have APIs like NSLocalizedString, so a localised linux application would need to .copy its strings files in order to use those APIs, would it not?

If that's true, then I think it is important to allow validation for .copy resources.

I did miss it - thanks for pointing it out!

Linux does support .process resources. .process just means that resources are processed, if there is any processing that needs to be done to them, then copied to the root of the bundle. This proposal adds the ability for the processed resources to be copied to localisation specific sub-directories in the resource bundle. So there's no need to use .copy on Linux.

1 Like

I strongly recommend using defaultLocalization and not “validating” that the localization identifiers conform to any particular schema. There are both en-US and en_US style identifiers used in the wild for existing Xcode projects, and there are also the legacy identifiers like English.

As for LanguageTag it should really be Localization or something like that.

I guess what I’m saying is we should avoid “language” and “region” terminology here and just stick to “localization.”

3 Likes

Does Foundation support and recognize those identifiers?

Don't you think that its more important to recognize them as IETF language tags?

Some simple POSIX locale identifiers like en_US do appear to work, but not all of them. It could be Foundation trying to help you even if you are doing it wrong, or it could be an accident of code sharing between localization handling and Locale handling. A quick search did not uncover any official documentation demonstrating that they are intentionally supported.

English and similar legacy Apple identifiers have been deprecated for years. If I rename the en.lproj directory to English.lproj, it still works. But if I also open the .pbxproj in TextEdit in order to hack the development region identifier to match as English, Xcode displays “English, deprecated” and fails to recognize it as the same thing as the English.lproj directory, believing instead that there are two separate English localizations.

The package manager is the place to do it, IMO. Whilst the compiler knows how to turn source code in to object files, modern applications require so much more than that (dependencies, resources, etc).

If this wasn't in SwiftPM, it would be a diagnostic tool which you invoked beforehand. It would have to read and understand the Package.swift file to even find your resources in the first place, wouldn't be able to diagnose mismatches across dependencies (e.g. your app claims to supports French, but dependency XYZ is only localised for English and German), and it would require additional information such as the development region that this proposal would make part of the manifest.

That said, I agree that LanguageTag doesn't make a huge amount of sense. Since it just wraps a String and doesn't expose any domain-specific API, I suggest that it be made a typealias. Also, if it is worth adding this kind of semantic tagging for locale identifier strings, Foundation should define it. The Foundation library's description on GitHub reads: "The Foundation Project, providing core utilities, internationalization, and OS independence".

I suspect that the only reason it isn't part of Foundation is political. Foundation evolves via an Apple-internal process, not via the community. It's not SwiftPM's job to make a better localisation API because it's too difficult to make changes to Foundation, though.

2 Likes

Yes it's political, but probably not in the sense you mean. The question will always be which Locales to hardcode. Java's Locale only has a small percentage of the possibilities, and as @hartbit mentioned it's hard not to have a political bias toward which should be added. Also there are geo-political issues you will find when trying to name certain, more sensitive, countries/regions.

In that context I think it's better to avoid adding something as a constant in a core part of the language/ecosystem that is, by definition, a human construct with a mutable value.

In the fullness of time, we might want this setting at the target level, but right now we generally try to keep settings at the package level unless it is absolutely necessary to do otherwise. For example, the Swift language version is a package-level property in the manifest, even though technically, it is a module-level property and could therefore be declared per target.