Browse Source

fix: set app locale after user's script is loaded (#26241)

Cheng Zhao 4 years ago
parent
commit
682b382aa3

+ 5 - 45
shell/app/electron_main_delegate.cc

@@ -8,10 +8,6 @@
 #include <memory>
 #include <string>
 
-#if defined(OS_LINUX)
-#include <glib.h>  // for g_setenv()
-#endif
-
 #include "base/command_line.h"
 #include "base/debug/stack_trace.h"
 #include "base/environment.h"
@@ -39,7 +35,6 @@
 #include "shell/renderer/electron_renderer_client.h"
 #include "shell/renderer/electron_sandboxed_renderer_client.h"
 #include "shell/utility/electron_content_utility_client.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_switches.h"
 
@@ -112,12 +107,8 @@ void InvalidParameterHandler(const wchar_t*,
 }
 #endif
 
-}  // namespace
-
 // TODO(nornagon): move path provider overriding to its own file in
 // shell/common
-namespace electron {
-
 bool GetDefaultCrashDumpsPath(base::FilePath* path) {
   base::FilePath cur;
   if (!base::PathService::Get(DIR_USER_DATA, &cur))
@@ -147,12 +138,11 @@ void RegisterPathProvider() {
                                       PATH_END);
 }
 
-}  // namespace electron
+}  // namespace
 
-void LoadResourceBundle(const std::string& locale) {
+std::string LoadResourceBundle(const std::string& locale) {
   const bool initialized = ui::ResourceBundle::HasSharedInstance();
-  if (initialized)
-    ui::ResourceBundle::CleanupSharedInstance();
+  DCHECK(!initialized);
 
   // Load other resource files.
   base::FilePath pak_dir;
@@ -163,12 +153,12 @@ void LoadResourceBundle(const std::string& locale) {
   base::PathService::Get(base::DIR_MODULE, &pak_dir);
 #endif
 
-  ui::ResourceBundle::InitSharedInstanceWithLocale(
+  std::string loaded_locale = ui::ResourceBundle::InitSharedInstanceWithLocale(
       locale, nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
-  bundle.ReloadLocaleResources(locale);
   bundle.AddDataPackFromPath(pak_dir.Append(FILE_PATH_LITERAL("resources.pak")),
                              ui::SCALE_FACTOR_NONE);
+  return loaded_locale;
 }
 
 ElectronMainDelegate::ElectronMainDelegate() = default;
@@ -287,36 +277,6 @@ bool ElectronMainDelegate::BasicStartupComplete(int* exit_code) {
   return false;
 }
 
-void ElectronMainDelegate::PostEarlyInitialization(bool is_running_tests) {
-  std::string custom_locale;
-  ui::ResourceBundle::InitSharedInstanceWithLocale(
-      custom_locale, nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
-  auto* cmd_line = base::CommandLine::ForCurrentProcess();
-  if (cmd_line->HasSwitch(::switches::kLang)) {
-    const std::string locale = cmd_line->GetSwitchValueASCII(::switches::kLang);
-    const base::FilePath locale_file_path =
-        ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale);
-    if (!locale_file_path.empty()) {
-      custom_locale = locale;
-#if defined(OS_LINUX)
-      /* When built with USE_GLIB, libcc's GetApplicationLocaleInternal() uses
-       * glib's g_get_language_names(), which keys off of getenv("LC_ALL") */
-      g_setenv("LC_ALL", custom_locale.c_str(), TRUE);
-#endif
-    }
-  }
-
-#if defined(OS_MACOSX)
-  if (custom_locale.empty())
-    l10n_util::OverrideLocaleWithCocoaLocale();
-#endif
-
-  LoadResourceBundle(custom_locale);
-
-  ElectronBrowserClient::SetApplicationLocale(
-      l10n_util::GetApplicationLocale(custom_locale));
-}
-
 void ElectronMainDelegate::PreSandboxStartup() {
   auto* command_line = base::CommandLine::ForCurrentProcess();
 

+ 1 - 2
shell/app/electron_main_delegate.h

@@ -17,7 +17,7 @@ class TracingSamplerProfiler;
 
 namespace electron {
 
-void LoadResourceBundle(const std::string& locale);
+std::string LoadResourceBundle(const std::string& locale);
 
 class ElectronMainDelegate : public content::ContentMainDelegate {
  public:
@@ -31,7 +31,6 @@ class ElectronMainDelegate : public content::ContentMainDelegate {
   bool BasicStartupComplete(int* exit_code) override;
   void PreSandboxStartup() override;
   void PreCreateMainMessageLoop() override;
-  void PostEarlyInitialization(bool is_running_tests) override;
   content::ContentBrowserClient* CreateContentBrowserClient() override;
   content::ContentGpuClient* CreateContentGpuClient() override;
   content::ContentRendererClient* CreateContentRendererClient() override;

+ 30 - 7
shell/browser/electron_browser_main_parts.cc

@@ -8,10 +8,6 @@
 
 #include <utility>
 
-#if defined(OS_LINUX)
-#include <glib.h>  // for g_setenv()
-#endif
-
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
@@ -51,6 +47,7 @@
 #include "shell/common/node_bindings.h"
 #include "shell/common/node_includes.h"
 #include "ui/base/idle/idle.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_switches.h"
 
 #if defined(USE_AURA)
@@ -79,7 +76,6 @@
 
 #if defined(OS_WIN)
 #include "ui/base/cursor/cursor_loader_win.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_win.h"
 #include "ui/display/win/dpi.h"
 #include "ui/gfx/system_fonts_win.h"
@@ -359,9 +355,36 @@ int ElectronBrowserMainParts::PreCreateThreads() {
   if (!views::LayoutProvider::Get())
     layout_provider_ = std::make_unique<views::LayoutProvider>();
 
+  auto* command_line = base::CommandLine::ForCurrentProcess();
+  std::string locale = command_line->GetSwitchValueASCII(::switches::kLang);
+
+#if defined(OS_MAC)
+  // The browser process only wants to support the language Cocoa will use,
+  // so force the app locale to be overridden with that value. This must
+  // happen before the ResourceBundle is loaded
+  if (locale.empty())
+    l10n_util::OverrideLocaleWithCocoaLocale();
+#elif defined(OS_LINUX)
+  // l10n_util::GetApplicationLocaleInternal uses g_get_language_names(),
+  // which keys off of getenv("LC_ALL").
+  // We must set this env first to make ui::ResourceBundle accept the custom
+  // locale.
+  g_setenv("LC_ALL", locale.c_str(), TRUE);
+#endif
+
+  // Load resources bundle according to locale.
+  std::string loaded_locale = LoadResourceBundle(locale);
+
+#if defined(OS_LINUX)
+  // Reset to the loaded locale if the custom locale is invalid.
+  if (loaded_locale != locale)
+    g_setenv("LC_ALL", loaded_locale.c_str(), TRUE);
+#endif
+
   // Initialize the app locale.
-  fake_browser_process_->SetApplicationLocale(
-      ElectronBrowserClient::Get()->GetApplicationLocale());
+  std::string app_locale = l10n_util::GetApplicationLocale(loaded_locale);
+  ElectronBrowserClient::SetApplicationLocale(app_locale);
+  fake_browser_process_->SetApplicationLocale(app_locale);
 
   // Force MediaCaptureDevicesDispatcher to be created on UI thread.
   MediaCaptureDevicesDispatcher::GetInstance();

+ 1 - 1
spec-main/chromium-spec.ts

@@ -302,7 +302,7 @@ describe('command line switches', () => {
     const testLocale = async (locale: string, result: string) => {
       const appPath = path.join(fixturesPath, 'api', 'locale-check');
       const electronPath = process.execPath;
-      appProcess = ChildProcess.spawn(electronPath, [appPath, `--lang=${locale}`]);
+      appProcess = ChildProcess.spawn(electronPath, [appPath, `--set-lang=${locale}`]);
 
       let output = '';
       appProcess.stdout.on('data', (data) => { output += data; });

+ 3 - 0
spec/fixtures/api/locale-check/main.js

@@ -1,5 +1,8 @@
 const { app } = require('electron');
 
+const locale = process.argv[2].substr(11);
+app.commandLine.appendSwitch('lang', locale);
+
 app.whenReady().then(() => {
   process.stdout.write(app.getLocale());
   process.stdout.end();