From 073492046136ecc131fa22efdb15bac5a3acde81 Mon Sep 17 00:00:00 2001 From: Carlos Jeurissen <1038267+carlosjeurissen@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:36:43 -0700 Subject: [PATCH] Implement i18n.getSystemUILanguage and i18n.getPreferredSystemLanguages. https://bugs.webkit.org/show_bug.cgi?id=280586 Reviewed by Brian Weinstein. WECG issue: https://github.com/w3c/webextensions/issues/252 WECG proposal: https://github.com/w3c/webextensions/pull/569 Also changed the i18n APIs to return `"und"` instead of `undefined` when there is no language code. * Source/WebKit/Platform/spi/Cocoa/FoundationSPI.h: * Source/WebKit/Shared/Extensions/WebExtensionUtilities.mm: (WebKit::toWebAPI): Return "und" where then is no language code. * Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPILocalizationCocoa.mm: (WebKit::WebExtensionAPILocalization::getPreferredSystemLanguages): (WebKit::WebExtensionAPILocalization::getSystemUILanguage): * Source/WebKit/WebProcess/Extensions/API/WebExtensionAPILocalization.h: * Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPILocalization.idl: * Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPILocalization.mm: (TestWebKitAPI::localeStringInWebExtensionFormat): Return "und". (TestWebKitAPI::TEST(WKWebExtensionAPILocalization, i18n)): (TestWebKitAPI::TEST(WKWebExtensionAPILocalization, i18nWithFallback)): (TestWebKitAPI::TEST(WKWebExtensionAPILocalization, i18nWithoutMessages)): (TestWebKitAPI::TEST(WKWebExtensionAPILocalization, i18nWithoutDefaultLocale)): Canonical link: https://commits.webkit.org/284637@main --- .../WebKit/Platform/spi/Cocoa/FoundationSPI.h | 5 +++ .../Extensions/WebExtensionUtilities.mm | 4 +- .../Cocoa/WebExtensionAPILocalizationCocoa.mm | 11 +++++ .../API/WebExtensionAPILocalization.h | 2 + .../WebExtensionAPILocalization.idl | 3 ++ .../WKWebExtensionAPILocalization.mm | 41 ++++++++++++++++++- 6 files changed, 62 insertions(+), 4 deletions(-) diff --git a/Source/WebKit/Platform/spi/Cocoa/FoundationSPI.h b/Source/WebKit/Platform/spi/Cocoa/FoundationSPI.h index 916b765e5f23a..3f19c074764ac 100644 --- a/Source/WebKit/Platform/spi/Cocoa/FoundationSPI.h +++ b/Source/WebKit/Platform/spi/Cocoa/FoundationSPI.h @@ -28,6 +28,7 @@ #if USE(APPLE_INTERNAL_SDK) #import +#import #import #if PLATFORM(IOS_FAMILY) @@ -59,6 +60,10 @@ NS_ASSUME_NONNULL_BEGIN @property (copy, NS_NONATOMIC_IOSONLY) void (^requestInterruptionBlock)(id ); @end +@interface NSLocale () ++ (NSString *)_deviceLanguage; +@end + NS_ASSUME_NONNULL_END #endif // USE(APPLE_INTERNAL_SDK) diff --git a/Source/WebKit/Shared/Extensions/WebExtensionUtilities.mm b/Source/WebKit/Shared/Extensions/WebExtensionUtilities.mm index 6ae2b572d1f8d..6cba68b6f9ec2 100644 --- a/Source/WebKit/Shared/Extensions/WebExtensionUtilities.mm +++ b/Source/WebKit/Shared/Extensions/WebExtensionUtilities.mm @@ -368,8 +368,8 @@ JSObjectRef toJSRejectedPromise(JSContextRef context, NSString *callingAPIName, NSString *toWebAPI(NSLocale *locale) { - if (!locale.languageCode) - return nil; + if (!locale.languageCode.length) + return @"und"; if (locale.countryCode.length) return [NSString stringWithFormat:@"%@-%@", locale.languageCode, locale.countryCode]; diff --git a/Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPILocalizationCocoa.mm b/Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPILocalizationCocoa.mm index 5e0545e08f613..c12f8bf09a0ab 100644 --- a/Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPILocalizationCocoa.mm +++ b/Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPILocalizationCocoa.mm @@ -31,6 +31,7 @@ #import "WebExtensionAPILocalization.h" #import "CocoaHelpers.h" +#import "FoundationSPI.h" #import "Logging.h" #import "MessageSenderInlines.h" #import "WebExtensionContextMessages.h" @@ -88,6 +89,16 @@ callback->call(acceptLanguages.array); } +void WebExtensionAPILocalization::getPreferredSystemLanguages(Ref&& callback) +{ + callback->call(NSLocale.preferredLanguages); +} + +void WebExtensionAPILocalization::getSystemUILanguage(Ref&& callback) +{ + callback->call(NSLocale._deviceLanguage); +} + } // namespace WebKit #endif // ENABLE(WK_WEB_EXTENSIONS) diff --git a/Source/WebKit/WebProcess/Extensions/API/WebExtensionAPILocalization.h b/Source/WebKit/WebProcess/Extensions/API/WebExtensionAPILocalization.h index 1d79ddbbc51c5..a7b16ff1a395c 100644 --- a/Source/WebKit/WebProcess/Extensions/API/WebExtensionAPILocalization.h +++ b/Source/WebKit/WebProcess/Extensions/API/WebExtensionAPILocalization.h @@ -39,6 +39,8 @@ class WebExtensionAPILocalization : public WebExtensionAPIObject, public JSWebEx NSString *getMessage(NSString* messageName, id substitutions); NSString *getUILanguage(); void getAcceptLanguages(Ref&&); + void getPreferredSystemLanguages(Ref&&); + void getSystemUILanguage(Ref&&); }; } // namespace WebKit diff --git a/Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPILocalization.idl b/Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPILocalization.idl index 7751018aac902..30d012f23b7d8 100644 --- a/Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPILocalization.idl +++ b/Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPILocalization.idl @@ -36,4 +36,7 @@ void getAcceptLanguages([Optional, CallbackHandler] function callback); + void getPreferredSystemLanguages([Optional, CallbackHandler] function callback); + + void getSystemUILanguage([Optional, CallbackHandler] function callback); }; diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPILocalization.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPILocalization.mm index 61dc6ce6f8bee..1c9bb5025ad5c 100644 --- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPILocalization.mm +++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPILocalization.mm @@ -34,6 +34,10 @@ #import "CocoaHelpers.h" #import "WebExtensionUtilities.h" +@interface NSLocale () ++ (NSString *)_deviceLanguage; +@end + static NSString * const messageKey = @"message"; static NSString * const placeholdersKey = @"placeholders"; static NSString * const placeholderDictionaryContentKey = @"content"; @@ -77,8 +81,8 @@ static NSString *localeStringInWebExtensionFormat(NSLocale *locale) { - if (!locale.languageCode) - return @""; + if (!locale.languageCode.length) + return @"und"; if (locale.countryCode.length) return [NSString stringWithFormat:@"%@-%@", locale.languageCode, locale.countryCode]; @@ -86,6 +90,7 @@ } static NSString *currentLocaleString = localeStringInWebExtensionFormat(currentLocale); +static NSString *currentSystemLocaleString = NSLocale._deviceLanguage; static auto *baseURLString = @"test-extension://76C788B8-3374-400D-8259-40E5B9DF79D3"; @@ -122,10 +127,13 @@ } auto *acceptedLanguagesString = Util::constructJSArrayOfStrings(acceptedLanguages.array); + auto *preferredLanguagesString = Util::constructJSArrayOfStrings(preferredLocaleIdentifiers); auto *backgroundScript = Util::constructScript(@[ [NSString stringWithFormat:@"const acceptedLanguages = %@", acceptedLanguagesString], + [NSString stringWithFormat:@"const preferredLanguages = %@", preferredLanguagesString], [NSString stringWithFormat:@"const currentUILanguage = '%@'", currentLocaleString], + [NSString stringWithFormat:@"const currentSystemUILanguage = '%@'", currentSystemLocaleString], [NSString stringWithFormat:@"const textDirection = '%@'", textDirection], [NSString stringWithFormat:@"const reversedTextDirection = '%@'", reversedTextDirection], [NSString stringWithFormat:@"const startEdge = '%@'", startEdge], @@ -140,9 +148,14 @@ @"browser.test.assertEq(browser.i18n.getMessage('@@bidi_end_edge'), endEdge)", @"browser.test.assertEq(browser.i18n.getMessage('unknown_message'), '')", + @"browser.test.assertFalse(currentUILanguage === 'und')", @"browser.test.assertEq(browser.i18n.getUILanguage(), currentUILanguage)", @"browser.test.assertDeepEq(await browser.i18n.getAcceptLanguages(), acceptedLanguages)", + @"browser.test.assertFalse(currentSystemUILanguage === 'und')", + @"browser.test.assertEq(await browser.i18n.getSystemUILanguage(), currentSystemUILanguage)", + @"browser.test.assertDeepEq(await browser.i18n.getPreferredSystemLanguages(), preferredLanguages)", + @"browser.test.notifyPass()", ]); @@ -166,10 +179,13 @@ } auto *acceptedLanguagesString = Util::constructJSArrayOfStrings(acceptedLanguages.array); + auto *preferredLanguagesString = Util::constructJSArrayOfStrings(preferredLocaleIdentifiers); auto *backgroundScript = Util::constructScript(@[ [NSString stringWithFormat:@"const acceptedLanguages = %@", acceptedLanguagesString], + [NSString stringWithFormat:@"const preferredLanguages = %@", preferredLanguagesString], [NSString stringWithFormat:@"const currentUILanguage = '%@'", currentLocaleString], + [NSString stringWithFormat:@"const currentSystemUILanguage = '%@'", currentSystemLocaleString], [NSString stringWithFormat:@"const textDirection = '%@'", textDirection], [NSString stringWithFormat:@"const reversedTextDirection = '%@'", reversedTextDirection], [NSString stringWithFormat:@"const startEdge = '%@'", startEdge], @@ -186,9 +202,14 @@ @"browser.test.assertEq(browser.i18n.getMessage('@@bidi_end_edge'), endEdge)", @"browser.test.assertEq(browser.i18n.getMessage('unknown_message'), '')", + @"browser.test.assertFalse(currentUILanguage === 'und')", @"browser.test.assertEq(browser.i18n.getUILanguage(), currentUILanguage)", @"browser.test.assertDeepEq(await browser.i18n.getAcceptLanguages(), acceptedLanguages)", + @"browser.test.assertFalse(currentSystemUILanguage === 'und')", + @"browser.test.assertEq(await browser.i18n.getSystemUILanguage(), currentSystemUILanguage)", + @"browser.test.assertDeepEq(await browser.i18n.getPreferredSystemLanguages(), preferredLanguages)", + @"browser.test.notifyPass()", ]); @@ -249,10 +270,13 @@ } auto *acceptedLanguagesString = Util::constructJSArrayOfStrings(acceptedLanguages.array); + auto *preferredLanguagesString = Util::constructJSArrayOfStrings(preferredLocaleIdentifiers); auto *backgroundScript = Util::constructScript(@[ [NSString stringWithFormat:@"const acceptedLanguages = %@", acceptedLanguagesString], + [NSString stringWithFormat:@"const preferredLanguages = %@", preferredLanguagesString], [NSString stringWithFormat:@"const currentUILanguage = '%@'", currentLocaleString], + [NSString stringWithFormat:@"const currentSystemUILanguage = '%@'", currentSystemLocaleString], @"browser.test.assertEq(browser.i18n.getMessage('@@extension_id'), '76C788B8-3374-400D-8259-40E5B9DF79D3')", @"browser.test.assertEq(browser.i18n.getMessage('@@ui_locale'), '')", @@ -262,9 +286,14 @@ @"browser.test.assertEq(browser.i18n.getMessage('@@bidi_end_edge'), '')", @"browser.test.assertEq(browser.i18n.getMessage('unknown_message'), '')", + @"browser.test.assertFalse(currentUILanguage === 'und')", @"browser.test.assertEq(browser.i18n.getUILanguage(), currentUILanguage)", @"browser.test.assertDeepEq(await browser.i18n.getAcceptLanguages(), acceptedLanguages)", + @"browser.test.assertFalse(currentSystemUILanguage === 'und')", + @"browser.test.assertEq(await browser.i18n.getSystemUILanguage(), currentSystemUILanguage)", + @"browser.test.assertDeepEq(await browser.i18n.getPreferredSystemLanguages(), preferredLanguages)", + @"browser.test.notifyPass()", ]); @@ -302,10 +331,13 @@ }; auto *acceptedLanguagesString = Util::constructJSArrayOfStrings(acceptedLanguages.array); + auto *preferredLanguagesString = Util::constructJSArrayOfStrings(preferredLocaleIdentifiers); auto *backgroundScript = Util::constructScript(@[ [NSString stringWithFormat:@"const acceptedLanguages = %@", acceptedLanguagesString], + [NSString stringWithFormat:@"const preferredLanguages = %@", preferredLanguagesString], [NSString stringWithFormat:@"const currentUILanguage = '%@'", currentLocaleString], + [NSString stringWithFormat:@"const currentSystemUILanguage = '%@'", currentSystemLocaleString], @"browser.test.assertEq(browser.i18n.getMessage('@@extension_id'), '76C788B8-3374-400D-8259-40E5B9DF79D3')", @"browser.test.assertEq(browser.i18n.getMessage('@@ui_locale'), '')", @@ -315,9 +347,14 @@ @"browser.test.assertEq(browser.i18n.getMessage('@@bidi_end_edge'), '')", @"browser.test.assertEq(browser.i18n.getMessage('unknown_message'), '')", + @"browser.test.assertFalse(currentUILanguage === 'und')", @"browser.test.assertEq(browser.i18n.getUILanguage(), currentUILanguage)", @"browser.test.assertDeepEq(await browser.i18n.getAcceptLanguages(), acceptedLanguages)", + @"browser.test.assertFalse(currentSystemUILanguage === 'und')", + @"browser.test.assertEq(await browser.i18n.getSystemUILanguage(), currentSystemUILanguage)", + @"browser.test.assertDeepEq(await browser.i18n.getPreferredSystemLanguages(), preferredLanguages)", + @"browser.test.notifyPass()", ]);