diff --git a/client/components/sidebar/sidebarCustomFields.js b/client/components/sidebar/sidebarCustomFields.js index b4fc82d38..748b02a53 100644 --- a/client/components/sidebar/sidebarCustomFields.js +++ b/client/components/sidebar/sidebarCustomFields.js @@ -139,6 +139,15 @@ Template.createCustomFieldPopup.helpers({ }); }, + // The template iterates `{{#each dropdownItems.get}}`. This component used to + // be a BlazeComponent, where `dropdownItems` resolved to the instance's + // ReactiveVar; after the migration to a plain Template that binding rendered + // nothing (so dropdown options never appeared and were lost on save). Expose + // the ReactiveVar as a helper again so `dropdownItems.get` works. + dropdownItems() { + return Template.instance().dropdownItems; + }, + getDropdownItems() { return getDropdownItems(Template.instance()); }, diff --git a/imports/i18n/tap.js b/imports/i18n/tap.js index 927138fe9..36be00cb0 100644 --- a/imports/i18n/tap.js +++ b/imports/i18n/tap.js @@ -105,18 +105,30 @@ export const TAPi18n = { // Return translation by key __(key, options, language) { this.current.dep.depend(); - const translation = this.i18n.t(key, { - ...options, - lng: language, - }); + + // The global sprintf post-processor (`postProcess: ["sprintf"]`) throws when + // a translation value contains a '%' sequence it cannot parse, e.g. the + // literal "%{value}" used in some help texts. That would crash the caller + // (the global Blaze '_' helper). Retry without sprintf so such strings + // render literally instead of throwing. + const translate = (lng, extra = {}) => { + const opts = { ...options, ...extra, lng }; + try { + return this.i18n.t(key, opts); + } catch (e) { + try { + return this.i18n.t(key, { ...opts, postProcess: false }); + } catch (e2) { + return key; + } + } + }; + + const translation = translate(language); // If the selected language misses the key, fallback explicitly to English. if (translation === key) { - const englishFallback = this.i18n.t(key, { - ...options, - lng: DEFAULT_LANGUAGE, - fallbackLng: false, - }); + const englishFallback = translate(DEFAULT_LANGUAGE, { fallbackLng: false }); if (englishFallback !== key) { return englishFallback;