discourse/app/controllers/extra_locales_controller.rb
Loïc Guitaut 301713ef96 DEV: Upgrade the MessageFormat library (JS)
This patch upgrades the MessageFormat library to version 3.3.0 from
0.1.5.

Our `I18n.messageFormat` method signature is unchanged, and now uses the
new API under the hood.

We don’t need dedicated locale files for handling pluralization rules
anymore as everything is now included by the library itself.

The compilation of the messages now happens through our
`messageformat-wrapper` gem. It then outputs an ES module that includes
all its needed dependencies.

Most of the changes happen in `JsLocaleHelper` and in the `ExtraLocales`
controller.

A new method called `.output_MF` has been introduced in
`JsLocaleHelper`. It handles all the fetching, compiling and
transpiling to generate the proper MF messages in JS. Overrides and
fallbacks are also handled directly in this method.

The other main change is that now the MF translations are served through
the `ExtraLocales` controller instead of being statically compiled in a
JS file, then having to patch the messages using overrides and
fallbacks. Now the MF translations are just another bundle that is
created on the fly and cached by the client.
2024-07-10 09:51:25 +02:00

91 lines
2.3 KiB
Ruby

# frozen_string_literal: true
class ExtraLocalesController < ApplicationController
layout false
skip_before_action :check_xhr,
:preload_json,
:redirect_to_login_if_required,
:redirect_to_profile_if_required,
:verify_authenticity_token
OVERRIDES_BUNDLE ||= "overrides"
MD5_HASH_LENGTH ||= 32
MF_BUNDLE = "mf"
BUNDLES = [OVERRIDES_BUNDLE, MF_BUNDLE]
class << self
def js_digests
@js_digests ||= {}
end
def bundle_js_hash(bundle)
bundle_key = "#{bundle}_#{I18n.locale}"
if bundle.in?(BUNDLES)
site = RailsMultisite::ConnectionManagement.current_db
js_digests[site] ||= {}
js_digests[site][bundle_key] ||= begin
js = bundle_js(bundle)
js.present? ? Digest::MD5.hexdigest(js) : nil
end
else
js_digests[bundle_key] ||= Digest::MD5.hexdigest(bundle_js(bundle))
end
end
def url(bundle)
"#{Discourse.base_path}/extra-locales/#{bundle}?v=#{bundle_js_hash(bundle)}"
end
def client_overrides_exist?
bundle_js_hash(OVERRIDES_BUNDLE).present?
end
def bundle_js(bundle)
locale_str = I18n.locale.to_s
bundle_str = "#{bundle}_js"
case bundle
when OVERRIDES_BUNDLE
JsLocaleHelper.output_client_overrides(locale_str)
when MF_BUNDLE
JsLocaleHelper.output_MF(locale_str)
else
JsLocaleHelper.output_extra_locales(bundle_str, locale_str)
end
end
def bundle_js_with_hash(bundle)
js = bundle_js(bundle)
[js, Digest::MD5.hexdigest(js)]
end
def clear_cache!
site = RailsMultisite::ConnectionManagement.current_db
js_digests.delete(site)
end
end
def show
bundle = params[:bundle]
raise Discourse::InvalidAccess.new if !valid_bundle?(bundle)
version = params[:v]
if version.present?
raise Discourse::InvalidParameters.new(:v) unless version.to_s.size == MD5_HASH_LENGTH
end
content, hash = ExtraLocalesController.bundle_js_with_hash(bundle)
immutable_for(1.year) if hash == version
render plain: content, content_type: "application/javascript"
end
private
def valid_bundle?(bundle)
bundle.in?(BUNDLES) || (bundle =~ /\A(admin|wizard)\z/ && current_user&.staff?)
end
end