diff --git a/app/helpers/pageflow/public_i18n_helper.rb b/app/helpers/pageflow/public_i18n_helper.rb index ebe1d023d6..29f81790f7 100644 --- a/app/helpers/pageflow/public_i18n_helper.rb +++ b/app/helpers/pageflow/public_i18n_helper.rb @@ -11,14 +11,14 @@ def public_i18n_translations(entry) value.presence || fallback end - { - pageflow: { - public: I18n.t('pageflow.public', locale: I18n.default_locale) - .dup - .deep_merge(I18n.t('pageflow.public', locale: entry.locale), - &merge_ignoring_nil) - } - } + locales = [I18n.default_locale, *I18n.fallbacks[entry.locale].reverse].uniq + + translations = locales.reduce({}) do |result, locale| + result.deep_merge(I18n.t('pageflow.public', locale:, default: {}), + &merge_ignoring_nil) + end + + {pageflow: {public: translations}} end end end diff --git a/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb b/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb index cee9e91965..6b4369702f 100644 --- a/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +++ b/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb @@ -32,10 +32,14 @@ def scrolled_i18n_translations(entry, end def scrolled_i18n_public_translations(entry) - translations = - I18n.t('pageflow_scrolled.public', locale: I18n.default_locale, default: {}) - .deep_merge(I18n.t('pageflow_scrolled.public', locale: entry.locale, default: {}), - &MERGE_IGNORING_NIL) + locales = [I18n.default_locale, *I18n.fallbacks[entry.locale].reverse].uniq + + translations = locales.reduce({}) do |result, locale| + result.deep_merge( + I18n.t('pageflow_scrolled.public', locale:, default: {}), + &MERGE_IGNORING_NIL + ) + end { entry.locale => { diff --git a/entry_types/scrolled/spec/helpers/pageflow_scrolled/i18n_helper_spec.rb b/entry_types/scrolled/spec/helpers/pageflow_scrolled/i18n_helper_spec.rb index 09eb13e77e..60ddba556e 100644 --- a/entry_types/scrolled/spec/helpers/pageflow_scrolled/i18n_helper_spec.rb +++ b/entry_types/scrolled/spec/helpers/pageflow_scrolled/i18n_helper_spec.rb @@ -84,6 +84,25 @@ module PageflowScrolled }) end + it 'merges parent locale translations for regional entry locales' do + translation(I18n.default_locale, 'pageflow_scrolled.public.from_default', 'default_text') + translation(:nl, 'pageflow_scrolled.public.from_parent', 'nl_text') + translation(:'nl-BE', 'pageflow_scrolled.public.from_regional', 'be_text') + entry = create(:published_entry, revision_attributes: {locale: 'nl-BE'}) + + result = helper.scrolled_i18n_translations(entry) + + expect(result).to include_json('nl-BE': { + pageflow_scrolled: { + public: { + from_default: 'default_text', + from_parent: 'nl_text', + from_regional: 'be_text' + } + } + }) + end + it 'supports including inline_editing translations in current locale' do translation(I18n.locale, 'pageflow_scrolled.inline_editing.some', 'text') entry = create(:published_entry, revision_attributes: {locale: 'fr'}) diff --git a/package/src/editor/base.js b/package/src/editor/base.js index 563193a5ae..a3d4c5284b 100644 --- a/package/src/editor/base.js +++ b/package/src/editor/base.js @@ -4,6 +4,8 @@ import {browser} from 'pageflow/frontend'; import {EditorApi} from './api'; import {app} from './app'; import I18n from 'i18n-js'; +import {patchSprocketsI18nForParentLocaleFallback} + from './utils/patchSprocketsI18nForParentLocaleFallback'; export const editor = new EditorApi(); @@ -15,6 +17,9 @@ export const startEditor = function(options) { I18n.defaultLocale = window.I18n.defaultLocale; I18n.locale = window.I18n.locale; I18n.translations = window.I18n.translations; + I18n.fallbacks = window.I18n.fallbacks; + + patchSprocketsI18nForParentLocaleFallback(window.I18n); $(function() { editor.ensureBrowserSupport(() => { diff --git a/package/src/editor/utils/patchSprocketsI18nForParentLocaleFallback.js b/package/src/editor/utils/patchSprocketsI18nForParentLocaleFallback.js new file mode 100644 index 0000000000..fc323626f0 --- /dev/null +++ b/package/src/editor/utils/patchSprocketsI18nForParentLocaleFallback.js @@ -0,0 +1,40 @@ +// The i18n-js JS lib shipped by the i18n-js Ruby gem (Sprockets) is an +// old version whose fallback only tries defaultLocale; it never walks +// parent locales. Patch lookup so e.g. `de-CH` falls back via `de` to +// defaultLocale. The Webpack-bundled I18n (npm i18n-js) does this +// natively when I18n.fallbacks is true. +export function patchSprocketsI18nForParentLocaleFallback(I18n) { + const originalLookup = I18n.lookup; + + I18n.lookup = function(scope, options) { + options = options || {}; + + if (!I18n.fallbacks || options.fallback) { + return originalLookup.call(I18n, scope, options); + } + + const candidates = parentLocaleChain( + options.locale || I18n.currentLocale(), I18n.defaultLocale + ); + + for (const candidate of candidates) { + const result = originalLookup.call(I18n, scope, I18n.prepareOptions( + {locale: candidate, fallback: true}, options + )); + if (result !== undefined) return result; + } + + return I18n.isValidNode(options, 'defaultValue') ? options.defaultValue : undefined; + }; +} + +function parentLocaleChain(locale, defaultLocale) { + const chain = []; + const parts = String(locale).split('-'); + while (parts.length > 0) { + chain.push(parts.join('-')); + parts.pop(); + } + if (!chain.includes(defaultLocale)) chain.push(defaultLocale); + return chain; +} diff --git a/spec/helpers/pageflow/public_i18n_helper_spec.rb b/spec/helpers/pageflow/public_i18n_helper_spec.rb index 018dd8427d..8200139003 100644 --- a/spec/helpers/pageflow/public_i18n_helper_spec.rb +++ b/spec/helpers/pageflow/public_i18n_helper_spec.rb @@ -67,6 +67,22 @@ module Pageflow expect(result[:pageflow][:public][:some][:key]).to eq('default_text') end + + it 'merges parent locale translations for regional entry locales' do + translation(I18n.default_locale, 'pageflow.public.from_default', 'default_text') + translation(:nl, 'pageflow.public.from_parent', 'nl_text') + translation(:'nl-BE', 'pageflow.public.from_regional', 'be_text') + + entry = PublishedEntry.new(create(:entry, + :published, + published_revision_attributes: {locale: 'nl-BE'})) + + result = helper.public_i18n_translations(entry) + + expect(result[:pageflow][:public][:from_default]).to eq('default_text') + expect(result[:pageflow][:public][:from_parent]).to eq('nl_text') + expect(result[:pageflow][:public][:from_regional]).to eq('be_text') + end end end end