Skip to content

Commit

Permalink
Truncate legacy extension keys from default locale on iOS/Mac (#1141)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #1141

iOS can sometimes return a default locale identifier that contains
extensions in the legacy form. Ideally, we should convert these into
the new style and respect them, but that isn't trivial to do.

We could do also just use the iOS version of the locale without
converting it. But this is potentially confusing, since the locale
won't follow a format that we actually accept. So in something like:

```
Intl.Collator(Intl.Collator().resolvedOptions.locale)
```

the inner collator and outer collator will have inconsistent behaviour.

For now, truncate the extensions so we can at least parse the first
part of the identifier and honour it.

Closes #1140

Reviewed By: avp

Differential Revision: D49870526

fbshipit-source-id: 893c3e1d95009ab6b32b2e2c41ef84855cedf28a
  • Loading branch information
neildhar authored and facebook-github-bot committed Oct 3, 2023
1 parent eda3c08 commit 329430e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
21 changes: 15 additions & 6 deletions lib/Platform/Intl/PlatformIntlApple.mm
Expand Up @@ -42,6 +42,10 @@
std::replace(u16str.begin(), u16str.end(), u'_', u'-');
// Some locales may still not be properly canonicalized (e.g. en_US_POSIX
// should be en-US-posix).
// Note that we do not need to handle legacy extensions here (unlike
// getDefaultLocale), since the documentation for
// availableLocaleIdentifiers states that they will only contain a
// language, country, and script code.
if (auto parsed = ParsedLocaleIdentifier::parse(u16str))
vec->push_back(parsed->canonicalize());
}
Expand All @@ -53,12 +57,17 @@
static const std::u16string *defLocale = new std::u16string([] {
// Environment variable used for testing only
const char *testLocale = std::getenv("_HERMES_TEST_LOCALE");
if (testLocale) {
NSString *nsTestLocale = [NSString stringWithUTF8String:testLocale];
return nsStringToU16String(nsTestLocale);
}
NSString *nsDefLocale = [[NSLocale currentLocale] localeIdentifier];
auto defLocale = nsStringToU16String(nsDefLocale);
NSString *nsLocale = testLocale
? [NSString stringWithUTF8String:testLocale]
: [[NSLocale currentLocale] localeIdentifier];
auto defLocale = nsStringToU16String(nsLocale);

// The locale identifier may occasionally contain legacy style locale
// extensions. We cannot handle them so remove them before parsing the tag.
size_t delimIdx = defLocale.find(u'@');
if (delimIdx != std::u16string::npos)
defLocale.resize(delimIdx);

// See the comment in getAvailableLocales.
std::replace(defLocale.begin(), defLocale.end(), u'_', u'-');
if (auto parsed = ParsedLocaleIdentifier::parse(defLocale))
Expand Down
15 changes: 15 additions & 0 deletions test/hermes/intl/default-locale-legacy-extension.js
@@ -0,0 +1,15 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// RUN: _HERMES_TEST_LOCALE="en-GB@foo=bar" %hermes %s | %FileCheck --match-full-lines %s
// REQUIRES: intl

print(Intl.Collator().resolvedOptions().locale);
// CHECK: en-GB

print(Intl.DateTimeFormat().resolvedOptions().locale);
// CHECK-NEXT: en-GB

0 comments on commit 329430e

Please sign in to comment.