diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index c5f5f374f2ffc..36b24f3424ddc 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -13,11 +13,30 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/embedder/embedder.h" +/** + * Constructs and returns a FlutterLocale struct corresponding to |locale|, which must outlive + * the returned struct. + */ +static FlutterLocale FlutterLocaleFromNSLocale(NSLocale* locale) { + FlutterLocale flutterLocale = {}; + flutterLocale.struct_size = sizeof(FlutterLocale); + flutterLocale.language_code = [[locale objectForKey:NSLocaleLanguageCode] UTF8String]; + flutterLocale.country_code = [[locale objectForKey:NSLocaleCountryCode] UTF8String]; + flutterLocale.script_code = [[locale objectForKey:NSLocaleScriptCode] UTF8String]; + flutterLocale.variant_code = [[locale objectForKey:NSLocaleVariantCode] UTF8String]; + return flutterLocale; +} + /** * Private interface declaration for FlutterEngine. */ @interface FlutterEngine () +/** + * Sends the list of user-preferred locales to the Flutter engine. + */ +- (void)sendUserLocales; + /** * Called by the engine to make the context the engine should draw into current. */ @@ -181,6 +200,12 @@ - (instancetype)initWithName:(NSString*)labelPrefix _textures = [[NSMutableDictionary alloc] init]; _allowHeadlessExecution = allowHeadlessExecution; + NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(sendUserLocales) + name:NSCurrentLocaleDidChangeNotification + object:nil]; + return self; } @@ -254,6 +279,7 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { return NO; } + [self sendUserLocales]; [self updateWindowMetrics]; return YES; } @@ -314,6 +340,29 @@ - (void)sendPointerEvent:(const FlutterPointerEvent&)event { #pragma mark - Private methods +- (void)sendUserLocales { + if (!self.running) { + return; + } + + // Create a list of FlutterLocales corresponding to the preferred languages. + NSMutableArray* locales = [NSMutableArray array]; + std::vector flutterLocales; + flutterLocales.reserve(locales.count); + for (NSString* localeID in [NSLocale preferredLanguages]) { + NSLocale* locale = [[NSLocale alloc] initWithLocaleIdentifier:localeID]; + [locales addObject:locale]; + flutterLocales.push_back(FlutterLocaleFromNSLocale(locale)); + } + // Convert to a list of pointers, and send to the engine. + std::vector flutterLocaleList; + flutterLocaleList.reserve(flutterLocales.size()); + std::transform( + flutterLocales.begin(), flutterLocales.end(), std::back_inserter(flutterLocaleList), + [](const auto& arg) -> const auto* { return &arg; }); + FlutterEngineUpdateLocales(_engine, flutterLocaleList.data(), flutterLocaleList.size()); +} + - (bool)engineCallbackOnMakeCurrent { if (!_mainOpenGLContext) { return false; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index bb928da63a79e..b1a6055e28f70 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -303,6 +303,7 @@ - (BOOL)launchEngine { } // Send the initial user settings such as brightness and text scale factor // to the engine. + // TODO(stuartmorgan): Move this logic to FlutterEngine. [self sendInitialSettings]; return YES; }