-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[embedder][glfw] Add support for locales to glfw shell #22657
Conversation
The other linux shell (and all the other embedding) have support for getting the locales from the system and sending them over the flutter/localization channel. The glfw shell does not have that which is causing us to crash on an assert now that Locale is no longer nullable in Platform. This adds a similar approach to what is going on over in the other linux shell to this one. I haven't added tests or anything yet, just wanted to get this out there to see if this is reasonable.
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat. Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good; some small comments. Thanks for setting up the unit tests target!
shell/platform/glfw/flutter_glfw.cc
Outdated
const char* locale_string, | ||
std::list<std::string>& locale_storage) { | ||
if (!locale_string || locale_string[0] == '\0') { | ||
locale_string = "C"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why "C"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found somewhere in some posix docs about locales that "ISO C says that all programs start by default in the standard ‘C’ locale." And looking around at other things that parse these strings, they use "C" as the fallback.
shell/platform/glfw/flutter_glfw.cc
Outdated
// Passes locale information to the Flutter engine. | ||
static void SetUpLocales(FlutterDesktopEngineState* state) { | ||
// Helper to extend lifetime of the strings passed to Flutter. | ||
std::list<std::string> locale_storage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This construction seems more confusing than just inlining the conversion to C strings (as we do on other platforms IIRC).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need something to extend the lifetimes based on the calling convention, and this is basically how the other linux shell does it. I didn't think to look at the windows code, that is a much better way to handle it, I will mirror that over here.
std::vector<std::unique_ptr<FlutterLocale>> GetLocales( | ||
const char* locale_string, | ||
std::list<std::string>& locale_storage); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason there are multiple exposed helpers on Windows is that we can't easily mock out what the OS returns; that's not the case here, since you can easily set environment variables in tests, so I would expect there to only be one visible function for getting locales even if it has helper functions internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to not set environment variables in tests and instead make more pure functions for testability, but that is more noise than its worth here so I will collapse things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks!
if (lang_was_set) { | ||
setenv("LANG", old_lang.c_str(), 1); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional nit: it seems like you could simplify this code substantially by using a map of values to set, and a map of previous values, so that you wouldn't need four copies of all of the logic and could instead just iterate through maps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, done.
The other linux shell (and all the other embedding) have support for getting the locales from the system and sending them over the flutter/localization channel. The glfw shell does not have that which is causing a crash on an assert now that Locale is no longer nullable in Platform. This adds a similar approach to what is going on over in the other linux shell.
The other linux shell (and all the other embedding) have support for
getting the locales from the system and sending them over the
flutter/localization channel. The glfw shell does not have that which is
causing us to crash on an assert now that Locale is no longer nullable
in Platform.
This adds a similar approach to what is going on over in the other linux
shell to this one.
The GLFW shell also has no tests. I added tests for this change which required adding a new target and hooking that up where the other linux tests go. I took a bit of a guess at some of that because I'm not entirely sure what the build_glfw_shell configuration is used for. GLFW seems to be difficult to test so I added a private header to expose the functions for working with locales and tested those. Some of the code isn't tested because of environment variable things or calling into the engine, but those functions are small wrappers around the logic which is tested.
Related