diff --git a/app/assets/javascripts/locales/i18n.js b/app/assets/javascripts/locales/i18n.js index c88b0551604..fa7e9f95263 100644 --- a/app/assets/javascripts/locales/i18n.js +++ b/app/assets/javascripts/locales/i18n.js @@ -92,6 +92,24 @@ I18n.isValidNode = function(obj, node, undefined) { return obj[node] !== null && obj[node] !== undefined; }; +function checkExtras(origScope, sep, extras) { + if (!extras || extras.length === 0) { return; } + + for (var i=0; i 0) { + currentScope = scope.shift(); + messages = messages[currentScope]; + } + if (messages) { + return messages; + } + } +} + I18n.lookup = function(scope, options) { options = options || {}; var lookupInitialScope = scope, @@ -110,13 +128,20 @@ I18n.lookup = function(scope, options) { scope = options.scope.toString() + this.defaultSeparator + scope; } - scope = scope.split(this.defaultSeparator); + var origScope = "" + scope; + + scope = origScope.split(this.defaultSeparator); while (messages && scope.length > 0) { currentScope = scope.shift(); messages = messages[currentScope]; } + if (!messages) { + messages = checkExtras(origScope, this.defaultSeparator, this.extras); + } + + if (!messages) { if (I18n.fallbacks) { var fallbacks = this.getFallbacks(locale); @@ -192,7 +217,9 @@ I18n.interpolate = function(message, options) { }; I18n.translate = function(scope, options) { + options = this.prepareOptions(options); + var translation = this.lookup(scope, options); // Fallback to the default locale if (!translation && this.currentLocale() !== this.defaultLocale && !this.noFallbacks) { diff --git a/app/controllers/extra_locales_controller.rb b/app/controllers/extra_locales_controller.rb new file mode 100644 index 00000000000..d6819d8ae23 --- /dev/null +++ b/app/controllers/extra_locales_controller.rb @@ -0,0 +1,31 @@ +class ExtraLocalesController < ApplicationController + + layout :false + skip_before_filter :check_xhr, :preload_json + + def show + locale_str = I18n.locale.to_s + translations = JsLocaleHelper.translations_for(locale_str) + + bundle = params[:bundle] + raise Discourse::InvalidAccess.new unless bundle =~ /^[a-z]+$/ + for_key = translations[locale_str]["#{bundle}_js"] + + + if for_key.present? + js = <<-JS + (function() { + if (window.I18n) { + window.I18n.extras = window.I18n.extras || []; + window.I18n.extras.push(#{for_key.to_json}); + } + })(); + JS + else + js = "" + end + + + render text: js, content_type: "application/javascript" + end +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index af5e7df438d..bfbb54ab51d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -30,6 +30,7 @@ <%= script "application" %> <%- if staff? %> + <%= script "admin" %> <%- end %> diff --git a/config/routes.rb b/config/routes.rb index 77646512997..13163611161 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -163,6 +163,7 @@ Discourse::Application.routes.draw do get "customize/permalinks" => "permalinks#index", constraints: AdminConstraint.new get "customize/embedding" => "embedding#show", constraints: AdminConstraint.new put "customize/embedding" => "embedding#update", constraints: AdminConstraint.new + get "flags" => "flags#index" get "flags/:filter" => "flags#index" post "flags/agree/:id" => "flags#agree" @@ -251,6 +252,8 @@ Discourse::Application.routes.draw do get "email/unsubscribed" => "email#unsubscribed", as: "email_unsubscribed" post "email/unsubscribe/:key" => "email#perform_unsubscribe", as: "email_perform_unsubscribe" + get "extra-locales/:bundle" => "extra_locales#show" + resources :session, id: USERNAME_ROUTE_FORMAT, only: [:create, :destroy, :become] do get 'become' collection do diff --git a/lib/js_locale_helper.rb b/lib/js_locale_helper.rb index eb2f1a19d3f..02216d94eb8 100644 --- a/lib/js_locale_helper.rb +++ b/lib/js_locale_helper.rb @@ -20,15 +20,6 @@ module JsLocaleHelper # merge translations (plugin translations overwrite default translations) translations[locale_str]['js'].deep_merge!(plugin_translations[locale_str]['js']) if translations[locale_str] && plugin_translations[locale_str] && plugin_translations[locale_str]['js'] - # We used to split the admin versus the client side, but it's much simpler to just - # include both for now due to the small size of the admin section. - # - # For now, let's leave it split out in the translation file in case we want to split - # it again later, so we'll merge the JSON ourselves. - admin_contents = translations[locale_str].delete('admin_js') - translations[locale_str]['js'].deep_merge!(admin_contents) if admin_contents.present? - translations[locale_str]['js'].deep_merge!(plugin_translations[locale_str]['admin_js']) if translations[locale_str] && plugin_translations[locale_str] && plugin_translations[locale_str]['admin_js'] - translations end end @@ -72,9 +63,8 @@ module JsLocaleHelper end end - def self.output_locale(locale) - locale_sym = locale.to_sym - locale_str = locale.to_s + def self.translations_for(locale_str) + locale_sym = locale_str.to_sym current_locale = I18n.locale I18n.locale = locale_sym @@ -93,6 +83,19 @@ module JsLocaleHelper end end + I18n.locale = current_locale + + translations + end + + def self.output_locale(locale) + locale_str = locale.to_s + translations = translations_for(locale_str).dup + + translations[locale_str].keys.each do |k| + translations[locale_str].delete(k) unless k == "js" + end + message_formats = strip_out_message_formats!(translations[locale_str]['js']) result = generate_message_format(message_formats, locale_str) @@ -104,8 +107,6 @@ module JsLocaleHelper result << moment_locale(locale_str) result << moment_formats - I18n.locale = current_locale - result end diff --git a/spec/controllers/extra_locales_controller_spec.rb b/spec/controllers/extra_locales_controller_spec.rb new file mode 100644 index 00000000000..edc7212466a --- /dev/null +++ b/spec/controllers/extra_locales_controller_spec.rb @@ -0,0 +1,25 @@ +require 'rails_helper' + +describe ExtraLocalesController do + + context 'show' do + + it "needs a valid bundle" do + get :show, bundle: 'made-up-bundle' + expect(response).to_not be_success + expect(response.body).to be_blank + end + + it "won't work with a weird parameter" do + get :show, bundle: '-invalid..character!!' + expect(response).to_not be_success + end + + it "works with a valid bundle" do + get :show, bundle: 'admin' + expect(response).to be_success + expect(response.body).to be_present + end + end + +end