Tuesday, May 7, 2019

Tying the Locale to the Localization


The locale is formed from the settings for the current user’s chosen system locale overlaid with any custom settings the user has specified.

However, it doesn’t work that way anymore on macOS 10.14. (And I think this was documented or explained at WWDC, but I can’t seem to find it in the release notes or video.)

Peter N Lewis:

So basically there is no way an OSX application in 10.14 can display the time according to the user’s settings unless it is localised in the user’s language? That is severely messed up.


NSLocale currentLocale returns english (if you are localized in english) regardless of the user language. And there does not appear to be any way to read the 24 hour setting, or even just change a date formatter to a specific 24 hour setting.

I think the reasoning was to make the display within the app consistent, which kind of makes sense, though I think many users would rather see consistent dates (that follow their preferences) across all apps. But then there are cases like Lewis’s where the formatted text is not even necessarily displayed in the app; it’s just produced by it:

Keyboard Maestro generates dates based on the “current” locale. Pre-10.14, that was your locale as you define. In 10.14, they change it so that it is the locale of the localization of the app. So since Keyboard Maestro is English-only, you get an English locale regardless.

Previously: +[NSLocale preferredLanguages] vs -[NSBundle preferredLocalizations].

Update (2019-06-20): Karan:

For apps whose content is derived primarily from Locale, Formatter, etc., those apps can be opted into CFBundleAllowMixedLocalizations (see here), which will return the behaviour of currentLocale to ignoring the loaded bundle.

Peter N Lewis:

Unfortunately there is no way for a user to “opt back out” for an application in Mojave that worked properly in every previous version. No “default write” or the like, only a plist change will allow it. Also no way to control it for date formatting etc without mixing the UI.

5 Comments RSS · Twitter

Maybe this explains why I've been noticing that various apps don't seem to follow the date formatting I've had set for years in the Language & Region prefs. I thought it was app developers hardcoding US-style dates, but sounds like a change in 10.14 instead.

I'd always hoped that the Mac's well-thought-out customizability in region settings would come to the iPhone, because mm/dd/yyyy has always been nonsensical to me (not to mention it's incompatible with every country outside of the US). Sounds like instead the iPhone's simple-but-very-limited model is headed to the Mac?

Since Region (where the date format is set) and Language are distinct settings (and always have been) it makes a little sense to me to force Language over Region. That's not the first thing, and at this point, I'm not sure if iOS/macOS is tested with anything else than "California" settings.

I reported this behaviour on iOS as a bug in currentLocale in 2017. Here's what I got back from Apple:

"In iOS 11 and macOS High Sierra, the notion of “current locale” has changed such that, instead of always returning a locale that corresponds to the first language in Locale.preferredLanguages, it will instead match the language corresponding to Bundle.main.preferred. This is to ensure that dates, times, numbers, and other localized content that is driven by the locale is shown in a language consistent with the localization that the app is launched in. This new behavior will only take effect if Locale.preferredLanguages contains more than 1 language."

As a developer, you can set the `CFBundleAllowMixedLocalizations` plist flag to YES. This will tell the system to honor the formatted dates according to the locale. Unfortunately, it will then also partially localize your menu items (eg in the Windows menu), which is not really ideal, but better than the current alternatives.

Sadly there is no `defaults write` option or other setting (that Apple will admit to) that would allow a user to turn this on either in general or on a per-application basis to allow existing applications broken by the change to have their functionality restored.

Leave a Comment