Skip to content

Commit

Permalink
feat: inline english texts if no translation is fetched (#479)
Browse files Browse the repository at this point in the history
  • Loading branch information
MapTo0 committed Jun 4, 2019
1 parent 2261f1c commit abfb221
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 48 deletions.
65 changes: 33 additions & 32 deletions packages/base/src/ResourceBundle.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,11 @@
import "./shims/jquery-shim.js";
import ResourceBundle from "@ui5/webcomponents-core/dist/sap/base/i18n/ResourceBundle.js";
import formatMessage from "@ui5/webcomponents-core/dist/sap/base/strings/formatMessage.js";
import { getLanguage } from "./LocaleProvider.js";
import { registerModuleContent } from "./ResourceLoaderOverrides.js";
import { fetchJsonOnce } from "./util/FetchHelper.js";

const bundleURLs = new Map();
const singletonPromises = new Map();

/**
* Creates a new promise for the specified key (or returns a new one and stores it for next calls).
* The same promise is always returned for multiple calls to this method for the same key.
* This promise can also be resolved so that all usages that await its resolution can continue.
* @param {key} key the unique key identifying the promise
* @private
*/
const _getSingletonPromise = key => {
const prevPromise = singletonPromises.get(key);
if (prevPromise) {
return prevPromise;
}

let resolveFn;
const newPromise = new Promise(resolve => {
resolveFn = resolve;
});
// private usage for making a deferred-like API to avoid storing resolve functions in a second map
newPromise._deferredResolve = resolveFn;

singletonPromises.set(key, newPromise);
return newPromise;
};

/**
* This method preforms the asyncronous task of fething the actual text resources. It will fetch
Expand All @@ -41,10 +17,14 @@ const _getSingletonPromise = key => {
* @public
*/
const fetchResourceBundle = async packageId => {
// depending on the module resolution order, the fetch might run before the bundle URLs are registered - sync them here
await _getSingletonPromise(packageId);
const bundlesForPackage = bundleURLs.get(packageId);

if (!bundlesForPackage) {
console.warn(`Message bundle assets are not configured. Falling back to english texts.`, /* eslint-disable-line */
` You need to import @ui5/webcomponents/dist/MessageBundleAssets.js with a build tool that supports JSON imports.`); /* eslint-disable-line */
return;
}

const language = getLanguage();

let localeId = ResourceBundle.__normalize(language);
Expand Down Expand Up @@ -72,13 +52,34 @@ const fetchResourceBundle = async packageId => {
*/
const registerMessageBundles = (packageId, bundlesMap) => {
bundleURLs.set(packageId, bundlesMap);
_getSingletonPromise(packageId)._deferredResolve();
};

const getResourceBundle = library => {
return ResourceBundle.create({
url: `${library}.properties`,
});
class ResourceBundleFallback {
getText(textObj, ...params) {
return formatMessage(textObj.defaultText, params);
}
}

class ResourceBundleWrapper {
constructor(resouceBundle) {
this._resourceBundle = resouceBundle;
}

getText(textObj, ...params) {
return this._resourceBundle.getText(textObj.key, ...params);
}
}

const getResourceBundle = packageId => {
const bundleLoaded = bundleURLs.has(packageId);

if (bundleLoaded) {
return new ResourceBundleWrapper(ResourceBundle.create({
url: `${packageId}.properties`,
}));
}

return new ResourceBundleFallback();
};

export { fetchResourceBundle, registerMessageBundles, getResourceBundle };
2 changes: 2 additions & 0 deletions packages/main/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import "@ui5/webcomponents-base/src/browsersupport/Edge.js";
import "@ui5/webcomponents-base/src/shims/jquery-shim.js";
import "./dist/ThemePropertiesProvider.js";

import "@ui5/webcomponents/dist/MessageBundleAssets.js";

import Gregorian from "@ui5/webcomponents-core/dist/sap/ui/core/date/Gregorian.js";
import Buddhist from "@ui5/webcomponents-core/dist/sap/ui/core/date/Buddhist.js";
import Islamic from "@ui5/webcomponents-core/dist/sap/ui/core/date/Islamic.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fetchResourceBundle, registerMessageBundles, getResourceBundle } from "@ui5/webcomponents-base/src/ResourceBundle.js";
import { registerMessageBundles } from "@ui5/webcomponents-base/src/ResourceBundle.js";

import ar from "./i18n/messagebundle_ar.json";
import bg from "./i18n/messagebundle_bg.json";
Expand Down Expand Up @@ -97,5 +97,3 @@ Suggested pattern: "i18n\\\/.*\\\.json"`);
/* eslint-enable */

registerMessageBundles("@ui5/webcomponents", bundleMap);

export { fetchResourceBundle, getResourceBundle };
10 changes: 6 additions & 4 deletions packages/main/src/Panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { getIconURI } from "@ui5/webcomponents-base/src/IconPool.js";
import slideDown from "@ui5/webcomponents-base/src/animations/slideDown.js";
import slideUp from "@ui5/webcomponents-base/src/animations/slideUp.js";
import { isSpace, isEnter } from "@ui5/webcomponents-base/src/events/PseudoEvents.js";
import { fetchResourceBundle, getResourceBundle } from "@ui5/webcomponents-base/src/ResourceBundle.js";
import Icon from "./Icon.js";
import PanelAccessibleRole from "./types/PanelAccessibleRole.js";
import PanelRenderer from "./build/compiled/PanelRenderer.lit.js";
import { fetchResourceBundle, getResourceBundle } from "./ResourceBundleProvider.js";

import { PANEL_ICON } from "./i18n/defaults.js";

// Styles
import panelCss from "./themes/Panel.css.js";
Expand Down Expand Up @@ -193,14 +195,13 @@ class Panel extends UI5Element {
constructor() {
super();

this.resourceBundle = getResourceBundle("@ui5/webcomponents");

this._header = {};

this._icon = {};
this._icon.id = `${this.id}-CollapsedImg`;
this._icon.src = getIconURI("navigation-right-arrow");
this._icon.title = this.resourceBundle.getText("PANEL_ICON");
this._icon.functional = true;
this.resourceBundle = getResourceBundle("@ui5/webcomponents");

this._toggle = event => { event.preventDefault(); this._toggleOpen(); };
this._noOp = () => {};
Expand All @@ -213,6 +214,7 @@ class Panel extends UI5Element {
}

const toggleWithInternalHeader = !this.header;
this._icon.title = this.resourceBundle.getText(PANEL_ICON);
this._header.press = toggleWithInternalHeader ? this._toggle : this._noOp;
this._icon.press = !toggleWithInternalHeader ? this._toggle : this._noOp;
}
Expand Down
12 changes: 7 additions & 5 deletions packages/main/src/TextArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import Bootstrap from "@ui5/webcomponents-base/src/Bootstrap.js";
import UI5Element from "@ui5/webcomponents-base/src/UI5Element.js";
import CSSSize from "@ui5/webcomponents-base/src/types/CSSSize.js";
import Integer from "@ui5/webcomponents-base/src/types/Integer.js";
import { fetchResourceBundle, getResourceBundle } from "@ui5/webcomponents-base/src/ResourceBundle.js";
import TextAreaRenderer from "./build/compiled/TextAreaRenderer.lit.js";
import { fetchResourceBundle, getResourceBundle } from "./ResourceBundleProvider.js";

import { TEXTAREA_CHARACTERS_LEFT, TEXTAREA_CHARACTERS_EXCEEDED } from "./i18n/defaults.js";

// Styles
import styles from "./themes/TextArea.css.js";
Expand Down Expand Up @@ -231,11 +233,11 @@ class TextArea extends UI5Element {
constructor() {
super();

this.resourceBundle = getResourceBundle("@ui5/webcomponents");

this._listeners = {
change: this._handleChange.bind(this),
};

this.resourceBundle = getResourceBundle("@ui5/webcomponents");
}

onBeforeRendering() {
Expand Down Expand Up @@ -319,9 +321,9 @@ class TextArea extends UI5Element {
leftCharactersCount = maxLength - this.value.length;

if (leftCharactersCount >= 0) {
exceededText = this.resourceBundle.getText("TEXTAREA_CHARACTERS_LEFT", [leftCharactersCount]);
exceededText = this.resourceBundle.getText(TEXTAREA_CHARACTERS_LEFT, [leftCharactersCount]);
} else {
exceededText = this.resourceBundle.getText("TEXTAREA_CHARACTERS_EXCEEDED", [Math.abs(leftCharactersCount)]);
exceededText = this.resourceBundle.getText(TEXTAREA_CHARACTERS_EXCEEDED, [Math.abs(leftCharactersCount)]);
}
}
} else {
Expand Down
10 changes: 7 additions & 3 deletions packages/main/src/Tokenizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import Bootstrap from "@ui5/webcomponents-base/src/Bootstrap.js";
import UI5Element from "@ui5/webcomponents-base/src/UI5Element.js";
import ResizeHandler from "@ui5/webcomponents-base/src/delegate/ResizeHandler.js";
import ItemNavigation from "@ui5/webcomponents-base/src/delegate/ItemNavigation.js";
import { fetchResourceBundle, getResourceBundle } from "@ui5/webcomponents-base/src/ResourceBundle.js";

import { fetchResourceBundle, getResourceBundle } from "./ResourceBundleProvider.js";
import TokenizerRenderer from "./build/compiled/TokenizerRenderer.lit.js";
import { MULTIINPUT_SHOW_MORE_TOKENS } from "./i18n/defaults.js";

// Styles
import styles from "./themes/Tokenizer.css.js";


// all themes should work via the convenience import (inlined now, switch to json when elements can be imported individyally)
import "./ThemePropertiesProvider.js";

Expand Down Expand Up @@ -93,8 +95,9 @@ class Tokenizer extends UI5Element {
return this._getTokens();
};

this._delegates.push(this._itemNav);
this.resourceBundle = getResourceBundle("@ui5/webcomponents");

this._delegates.push(this._itemNav);
}

onBeforeRendering() {
Expand All @@ -105,7 +108,7 @@ class Tokenizer extends UI5Element {
}

this._lastTokenCount = this.tokens.length;
this._nMoreText = this.resourceBundle.getText("MULTIINPUT_SHOW_MORE_TOKENS", [this._hiddenTokens.length]);
this._nMoreText = this.resourceBundle.getText(MULTIINPUT_SHOW_MORE_TOKENS, [this._hiddenTokens.length]);
}

onAfterRendering() {
Expand Down Expand Up @@ -211,6 +214,7 @@ class Tokenizer extends UI5Element {

static async define(...params) {
await fetchResourceBundle("@ui5/webcomponents");

super.define(...params);
}
}
Expand Down
26 changes: 26 additions & 0 deletions packages/main/src/i18n/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const MULTIINPUT_SHOW_MORE_TOKENS = {
key: "MULTIINPUT_SHOW_MORE_TOKENS",
defaultText: "{0} More",
};

const TEXTAREA_CHARACTERS_LEFT = {
key: "TEXTAREA_CHARACTERS_LEFT",
defaultText: "{0} characters remaining",
};

const TEXTAREA_CHARACTERS_EXCEEDED = {
key: "TEXTAREA_CHARACTERS_EXCEEDED",
defaultText: "{0} characters over limit",
};

const PANEL_ICON = {
key: "PANEL_ICON",
defaultText: "Expand/Collapse",
};

export {
MULTIINPUT_SHOW_MORE_TOKENS,
TEXTAREA_CHARACTERS_LEFT,
TEXTAREA_CHARACTERS_EXCEEDED,
PANEL_ICON,
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ TestHelper.ready(function () {
QUnit.test("The default 'headerText' is empty string", function (assert) {
var panel = this.getPanelRoot(),
sExpected = "";

assert.equal(panel.querySelector(".sapMPanelHdr").innerText.trim(), sExpected, "headerText is empty string");
});

Expand Down

0 comments on commit abfb221

Please sign in to comment.