FEATURE: Add localized timezone names (#7004)

FEATURE: Add localized timezone names (#7004)

Uses github.com/discourse/moment-timezone-names-translations to translate timezone names. Plugins can also provide their own timezone name translations.

diff --git a/lib/js_locale_helper.rb b/lib/js_locale_helper.rb
index bff6391..21fba98 100644
--- a/lib/js_locale_helper.rb
+++ b/lib/js_locale_helper.rb
@@ -156,18 +156,26 @@ module JsLocaleHelper
     result << File.read("#{Rails.root}/vendor/assets/javascripts/moment.js")
     result << File.read("#{Rails.root}/vendor/assets/javascripts/moment-timezone-with-data.js")
     result << moment_locale(locale_str)
+    result << moment_locale(locale_str, timezone_names: true)
     result << moment_formats
 
     result
   end
 
-  def self.find_moment_locale(locale_chain)
-    path = "#{Rails.root}/vendor/assets/javascripts/moment-locale"
+  def self.find_moment_locale(locale_chain, timezone_names: false)
+    if timezone_names
+      path = "#{Rails.root}/vendor/assets/javascripts/moment-timezone-names-locale"
+      type = :moment_js_timezones
+    else
+      path = "#{Rails.root}/vendor/assets/javascripts/moment-locale"
+      type = :moment_js
+    end
 
-    find_locale(locale_chain, path, :moment_js, fallback_to_english: false) do |locale|
+    find_locale(locale_chain, path, type, fallback_to_english: false) do |locale|
       # moment.js uses a different naming scheme for locale files
       locale.tr('_', '-').downcase
     end
+
   end
 
   def self.find_message_format_locale(locale_chain, fallback_to_english:)
@@ -213,8 +221,8 @@ module JsLocaleHelper
     "moment.fn.#{name.camelize(:lower)} = function(){ return this.format('#{format}'); };\n"
   end
 
-  def self.moment_locale(locale)
-    _, filename = find_moment_locale([locale])
+  def self.moment_locale(locale, timezone_names: false)
+    _, filename = find_moment_locale([locale], timezone_names: timezone_names)
     filename && File.exist?(filename) ? File.read(filename) << "\n" : ""
   end
 
diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb
index 940cc90..83941d4 100644
--- a/lib/plugin/instance.rb
+++ b/lib/plugin/instance.rb
@@ -638,6 +638,10 @@ class Plugin::Instance
       opts[:moment_js] = find_locale_file(locale_chain, path)
       opts[:moment_js] = JsLocaleHelper.find_moment_locale(locale_chain) unless opts[:moment_js]
 
+      path = File.join(lib_locale_path, "moment_js_timezones")
+      opts[:moment_js_timezones] = find_locale_file(locale_chain, path)
+      opts[:moment_js_timezones] = JsLocaleHelper.find_moment_locale(locale_chain, timezone_names: true) unless opts[:moment_js_timezones]
+
       if valid_locale?(opts)
         DiscoursePluginRegistry.register_locale(locale, opts)
         Rails.configuration.assets.precompile << "locales/#{locale}.js"
diff --git a/lib/tasks/javascript.rake b/lib/tasks/javascript.rake
index 8bd8952..53015e3 100644
--- a/lib/tasks/javascript.rake
+++ b/lib/tasks/javascript.rake
@@ -74,6 +74,9 @@ task 'javascript:update' do
     }, {
       source: 'moment-timezone/builds/moment-timezone-with-data.js'
     }, {
+      source: 'moment-timezone-names-translations/locales/.',
+      destination: 'moment-timezone-names-locale'
+    }, {
       source: 'mousetrap/plugins/global-bind/mousetrap-global-bind.js'
     }, {
       source: 'resumablejs/resumable.js'
diff --git a/package.json b/package.json
index 7629ddd..628496d 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
     "markdown-it": "8.4.1",
     "moment": "2.22.1",
     "moment-timezone": "0.5.14",
+    "moment-timezone-names-translations": "https://github.com/discourse/moment-timezone-names-translations",
     "mousetrap": "https://github.com/discourse/mousetrap#firefox-alt-key",
     "pikaday": "1.7.0",
     "resumablejs": "1.1.0",
diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6 b/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6
index 3379de2..028a70c 100644
--- a/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6
+++ b/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6
@@ -65,6 +65,12 @@ export default Ember.Component.extend({
 
   @computed()
   allTimezones() {
+    if (
+      moment.locale() !== "en" &&
+      typeof moment.tz.localizedNames === "function"
+    ) {
+      return moment.tz.localizedNames();
+    }
     return moment.tz.names();
   },
 
diff --git a/spec/components/plugin/instance_spec.rb b/spec/components/plugin/instance_spec.rb
index ad31cfb..5fd47ff 100644
--- a/spec/components/plugin/instance_spec.rb
+++ b/spec/components/plugin/instance_spec.rb
@@ -358,6 +358,7 @@ describe Plugin::Instance do
       expect(DiscoursePluginRegistry.locales.count).to eq(0)
 
       plugin.activate!
+
       expect(DiscoursePluginRegistry.locales.count).to eq(2)
     end
 
@@ -377,12 +378,14 @@ describe Plugin::Instance do
       expect(locale[:fallbackLocale]).to be_nil
       expect(locale[:message_format]).to eq(["foo_BAR", "#{plugin_path}/lib/javascripts/locale/message_format/foo_BAR.js"])
       expect(locale[:moment_js]).to eq(["foo_BAR", "#{plugin_path}/lib/javascripts/locale/moment_js/foo_BAR.js"])
+      expect(locale[:moment_js_timezones]).to eq(["foo_BAR", "#{plugin_path}/lib/javascripts/locale/moment_js_timezones/foo_BAR.js"])
       expect(locale[:plural]).to eq(plural.with_indifferent_access)
 
       expect(Rails.configuration.assets.precompile).to include("locales/foo_BAR.js")
 
       expect(JsLocaleHelper.find_message_format_locale(["foo_BAR"], fallback_to_english: true)).to eq(locale[:message_format])
       expect(JsLocaleHelper.find_moment_locale(["foo_BAR"])).to eq (locale[:moment_js])
+      expect(JsLocaleHelper.find_moment_locale(["foo_BAR"], timezone_names: true)).to eq (locale[:moment_js_timezones])
     end
 
     it "correctly registers a new locale using a fallback locale" do
@@ -394,6 +397,7 @@ describe Plugin::Instance do
       expect(locale[:fallbackLocale]).to eq("es")
       expect(locale[:message_format]).to eq(["es", "#{Rails.root}/lib/javascripts/locale/es.js"])
       expect(locale[:moment_js]).to eq(["es", "#{Rails.root}/vendor/assets/javascripts/moment-locale/es.js"])
+      expect(locale[:moment_js_timezones]).to eq(["es", "#{Rails.root}/vendor/assets/javascripts/moment-timezone-names-locale/es.js"])
       expect(locale[:plural]).to be_nil
 
       expect(Rails.configuration.assets.precompile).to include("locales/es_MX.js")
diff --git a/spec/fixtures/plugins/custom_locales/lib/javascripts/locale/moment_js_timezones/foo_BAR.js b/spec/fixtures/plugins/custom_locales/lib/javascripts/locale/moment_js_timezones/foo_BAR.js
new file mode 100644
index 0000000..611f14d
--- /dev/null
+++ b/spec/fixtures/plugins/custom_locales/lib/javascripts/locale/moment_js_timezones/foo_BAR.js
@@ -0,0 +1 @@
+// this file should contain the locale configuration for moment.js timezone names
\ No newline at end of file
diff --git a/vendor/assets/javascripts/moment-timezone-names-locale/ar.js b/vendor/assets/javascripts/moment-timezone-names-locale/ar.js
new file mode 100644
index 0000000..5cd77eb
--- /dev/null
+++ b/vendor/assets/javascripts/moment-timezone-names-locale/ar.js
@@ -0,0 +1,16 @@
+// moment-timezone-localization for lang code: ar
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+moment.tz.localizedNames = function() {

[... diff too long, it was truncated ...]

GitHub sha: 9bf11a7c

2 Likes