From 30802e0c13a65afac1bb045a0366025ea8e5afdb Mon Sep 17 00:00:00 2001 From: Adam Zysko <1789131+azyzio@users.noreply.github.com> Date: Tue, 24 Nov 2020 14:04:31 +0100 Subject: [PATCH] feat: Ability to set installation-wide default locale (#1433) * Dashboard locale can be set via env variable * Change account locale based on registration page * Set account locale if available Co-authored-by: Pranav Raj Sreepuram --- .env.example | 4 ++ app/builders/account_builder.rb | 2 +- app/controllers/application_controller.rb | 24 +----------- app/controllers/concerns/switch_locale.rb | 38 +++++++++++++++++++ app/controllers/dashboard_controller.rb | 1 + app/javascript/dashboard/App.vue | 7 +++- app/views/layouts/vueapp.html.erb | 3 +- .../project-setup/environment-variables.md | 6 +++ 8 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 app/controllers/concerns/switch_locale.rb diff --git a/.env.example b/.env.example index 84dd75946..008195ef7 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,10 @@ SECRET_KEY_BASE=replace_with_lengthy_secure_hex # Replace with the URL you are planning to use for your app FRONTEND_URL=http://0.0.0.0:3000 +# If the variable is set, all non-authenticated pages would fallback to the default locale. +# Whenever a new account is created, the default language will be DEFAULT_LOCALE instead of en +# DEFAULT_LOCALE=en + # If you plan to use CDN for your assets, set Asset CDN Host ASSET_CDN_HOST= diff --git a/app/builders/account_builder.rb b/app/builders/account_builder.rb index ae6db3b4e..85a391c62 100644 --- a/app/builders/account_builder.rb +++ b/app/builders/account_builder.rb @@ -40,7 +40,7 @@ class AccountBuilder end def create_account - @account = Account.create!(name: @account_name) + @account = Account.create!(name: @account_name, locale: I18n.locale) Current.account = @account end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 58246bb73..ada185681 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,7 +5,7 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :null_session before_action :set_current_user, unless: :devise_controller? - around_action :switch_locale + include SwitchLocale around_action :handle_with_exception, unless: :devise_controller? # after_action :verify_authorized @@ -60,28 +60,6 @@ class ApplicationController < ActionController::Base render json: exception.to_hash, status: exception.http_status end - def locale_from_params - I18n.available_locales.map(&:to_s).include?(params[:locale]) ? params[:locale] : nil - end - - def locale_from_account(account) - return unless account - - I18n.available_locales.map(&:to_s).include?(account.locale) ? account.locale : nil - end - - def switch_locale(&action) - # priority is for locale set in query string (mostly for widget/from js sdk) - locale ||= locale_from_params - # if local is not set in param, lets try account - locale ||= locale_from_account(@current_account) - # if nothing works we rely on default locale - locale ||= I18n.default_locale - # ensure locale won't bleed into other requests - # https://guides.rubyonrails.org/i18n.html#managing-the-locale-across-requests - I18n.with_locale(locale, &action) - end - def pundit_user { user: Current.user, diff --git a/app/controllers/concerns/switch_locale.rb b/app/controllers/concerns/switch_locale.rb new file mode 100644 index 000000000..739c5bb7f --- /dev/null +++ b/app/controllers/concerns/switch_locale.rb @@ -0,0 +1,38 @@ +module SwitchLocale + extend ActiveSupport::Concern + included do + around_action :switch_locale + end + + private + + def switch_locale(&action) + # priority is for locale set in query string (mostly for widget/from js sdk) + locale ||= locale_from_params + # if locale is not set in param, lets try account + locale ||= locale_from_account(@current_account) + # if locale is not set in account, let's use DEFAULT_LOCALE env variable + locale ||= locale_from_env_variable + # if nothing works we rely on default locale + locale ||= I18n.default_locale + # ensure locale won't bleed into other requests + # https://guides.rubyonrails.org/i18n.html#managing-the-locale-across-requests + I18n.with_locale(locale, &action) + end + + def locale_from_params + I18n.available_locales.map(&:to_s).include?(params[:locale]) ? params[:locale] : nil + end + + def locale_from_account(account) + return unless account + + I18n.available_locales.map(&:to_s).include?(account.locale) ? account.locale : nil + end + + def locale_from_env_variable + return unless ENV.fetch('DEFAULT_LOCALE', nil) + + I18n.available_locales.map(&:to_s).include?(ENV.fetch('DEFAULT_LOCALE')) ? ENV.fetch('DEFAULT_LOCALE') : nil + end +end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 27fa7fb86..5a1bddbf6 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,5 +1,6 @@ class DashboardController < ActionController::Base before_action :set_global_config + include SwitchLocale layout 'vueapp' diff --git a/app/javascript/dashboard/App.vue b/app/javascript/dashboard/App.vue index bef1323e2..e37d5864e 100644 --- a/app/javascript/dashboard/App.vue +++ b/app/javascript/dashboard/App.vue @@ -28,10 +28,15 @@ export default { mounted() { this.$store.dispatch('setUser'); + this.setLocale(window.chatwootConfig.selectedLocale); this.initializeAccount(); }, methods: { + setLocale(locale) { + Vue.config.lang = locale; + }, + async initializeAccount() { const { pathname } = window.location; const accountId = accountIdFromPathname(pathname); @@ -39,7 +44,7 @@ export default { if (accountId) { await this.$store.dispatch('accounts/get'); const { locale } = this.getAccount(accountId); - Vue.config.lang = locale; + this.setLocale(locale); } }, }, diff --git a/app/views/layouts/vueapp.html.erb b/app/views/layouts/vueapp.html.erb index c2dae5279..40d9b7a1b 100644 --- a/app/views/layouts/vueapp.html.erb +++ b/app/views/layouts/vueapp.html.erb @@ -35,7 +35,8 @@ <% if ENV['VAPID_PUBLIC_KEY'] %> vapidPublicKey: new Uint8Array(<%= Base64.urlsafe_decode64(ENV['VAPID_PUBLIC_KEY']).bytes %>), <% end %> - enabledLanguages: <%= available_locales_with_name.to_json.html_safe %> + enabledLanguages: <%= available_locales_with_name.to_json.html_safe %>, + selectedLocale: '<%= I18n.locale %>' } window.globalConfig = <%= raw @global_config.to_json %> diff --git a/docs/development/project-setup/environment-variables.md b/docs/development/project-setup/environment-variables.md index d9ae9542c..faa04f9e4 100644 --- a/docs/development/project-setup/environment-variables.md +++ b/docs/development/project-setup/environment-variables.md @@ -93,6 +93,12 @@ Provide the following value as frontend url FRONTEND_URL='http://localhost:3000' ``` +### Configure default language + +```bash +DEFAULT_LOCALE='en' +``` + ### Configure storage Chatwoot uses [active storage](https://edgeguides.rubyonrails.org/active_storage_overview.html) for storing attachments. The default storage option is the local storage on your server.