summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/foundation/amp-localization
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/foundation/amp-localization')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/foundation/amp-localization/amp-localization.js371
1 files changed, 371 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/foundation/amp-localization/amp-localization.js b/node_modules/@jet-app/app-store/tmp/src/foundation/amp-localization/amp-localization.js
new file mode 100644
index 0000000..df04983
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/foundation/amp-localization/amp-localization.js
@@ -0,0 +1,371 @@
+/**
+ * A type encapsulating localization logic for strings
+ * returned by localization server.
+ *
+ * Replacement for 'its' namespace from @onyx/localization package.
+ */
+export class AmpLocalization {
+ constructor() {
+ // region Properties
+ /**
+ * Localization JSON dictionary loaded from localization file.
+ */
+ this.locData = {};
+ /**
+ * The 2-letter code for current device language.
+ */
+ this.language = "en";
+ // endregion
+ }
+ // endregion
+ // region API
+ /**
+ * Updates the localization data for the device.
+ * @param localizations A JSON dictionary representing the localized strings.
+ * @param language Language code for current device language.
+ */
+ updateLocalizationData(localizations, language) {
+ this.locData = localizations;
+ this.language = language;
+ }
+ /**
+ * Localizes a string replacing placehoders in key with values in the parameters dictionary
+ * @param key The loc key to look up
+ * @param params Parameters to replace in the loc string
+ * @return The localized string
+ */
+ localize(key, params) {
+ let value = this.locData[key];
+ if (value === undefined || typeof value !== "string") {
+ value = key;
+ }
+ if (params) {
+ value = this.replaceTokens(value, params);
+ }
+ value = this.replaceMarkupTokens(value, params);
+ return value;
+ }
+ /**
+ * Localize with appropriate plural form based on the count.
+ *
+ * Some languages have more plural forms than others.
+ * The full set of categories is "zero", "one", "two", "few", "many", and "other".
+ *
+ * The base loc key is used for "other" (the default).
+ * Otherwise the category is appended to the base loc key with a "." separator.
+ *
+ * http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
+ * http://cldr.unicode.org/index/cldr-spec/plural-rules#TOC-Determining-Plural-Categories
+ * http://unicode.org/repos/cldr/trunk/specs/ldml/tr35-numbers.html#Language_Plural_Rules
+ *
+ * English loc keys
+ * key = "@@count@@ dogs"; // default, aka "plural"
+ * key.zero = "no dogs"; // used when count is 0
+ * key.one = "@@count@@ dog"; // used when count is 1, aka "singular"
+ *
+ * @param key base loc key
+ * @param count number used to determine the plural form
+ * @param params (optional) substitution keys and values, "count" will be added if it's not already present
+ * @return localized string
+ */
+ localizeWithCount(objectGraph, key, count, params) {
+ let keyToUse = null;
+ let pluralFormKey;
+ let category;
+ if (count === 0) {
+ // Special case zero for all languages so we can have strings like
+ // "you have no messages" instead of "you have 0 messages".
+ pluralFormKey = `${key}.zero`;
+ if (this.isLocalized(objectGraph, pluralFormKey)) {
+ keyToUse = pluralFormKey;
+ }
+ }
+ if (keyToUse === null) {
+ keyToUse = key;
+ category = this.pluralCategory(objectGraph, count);
+ if (category !== "other") {
+ pluralFormKey = `${key}.${category}`;
+ if (this.isLocalized(objectGraph, pluralFormKey)) {
+ keyToUse = pluralFormKey;
+ }
+ }
+ }
+ if (!params) {
+ params = {};
+ }
+ // @@count@@ is the standard, but @@number@@ is frequently used too.
+ if (params.count === undefined) {
+ params.count = this.formatNumber(count.toString());
+ }
+ if (params.number === undefined) {
+ params.number = this.formatNumber(count.toString());
+ }
+ return this.localize(keyToUse !== null && keyToUse !== void 0 ? keyToUse : key, params);
+ }
+ // endregion
+ // region Private Methods
+ replaceTokens(text, values) {
+ Object.entries(values).forEach(([key, value]) => {
+ const subKey = "@@" + key + "@@";
+ text = this.replaceSubstring(text, subKey, value);
+ });
+ return text;
+ }
+ replaceMarkupTokens(text, values) {
+ if (text.indexOf("##") <= -1) {
+ return text;
+ }
+ // Resolve token properties.
+ let markupParams;
+ if (values) {
+ // Create a copy to avoid mutating defaults.
+ markupParams = { ...AmpLocalization.MARKUP_PARAMS };
+ Object.entries(values).forEach(([key, value]) => {
+ markupParams[key] = value;
+ });
+ }
+ else {
+ markupParams = AmpLocalization.MARKUP_PARAMS;
+ }
+ Object.entries(markupParams).forEach(([key, value]) => {
+ const token = "##" + key + "##";
+ text = text.replace(new RegExp(token, "gi"), value);
+ });
+ // Replace any remaining standard markup tags like <br> etc.
+ text = text.replace(/##([^##]+)##/gi, "<$1>");
+ return text;
+ }
+ /**
+ * Searches "str" for "substr" and replaces each occurrence with "replacement"
+ * @param str input string
+ * @param substr the string to search for in the input string
+ * @param replacement value to use for the replacement
+ *
+ * JavaScript String.replace has a misfeature where "$" in the replacement is always interpreted as a meta char,
+ * i.e. you have to use "$$" in the replacement to get a single "$" in the resulting string
+ * which lead to <rdar://problem/16848063> tv episode title containing "$&" not displaying correctly
+ * Using split and join is faster than substituting $$ for $ in the replacement.
+ */
+ replaceSubstring(str, substr, replacement) {
+ return str.split(substr).join(replacement);
+ }
+ formatNumber(value) {
+ let decimalSeparator = this.locData["_decimalSeparator"];
+ if (decimalSeparator === undefined || typeof decimalSeparator !== "string") {
+ decimalSeparator = ".";
+ }
+ let thousandsSeparator = this.locData["_thousandsSeparator"];
+ if (thousandsSeparator === undefined || typeof thousandsSeparator !== "string") {
+ thousandsSeparator = ".";
+ }
+ const parts = parseFloat(value).toString().split(".");
+ const chars = parts[0].split("");
+ for (let i = chars.length - 3; i > 0; i -= 3) {
+ chars.splice(i, 0, thousandsSeparator);
+ }
+ parts[0] = chars.join("");
+ return parts.join(decimalSeparator);
+ }
+ /**
+ * Check whether the given key is localized or not.
+ * @param key The key to check.
+ */
+ isLocalized(objectGraph, key) {
+ const value = this.locData[key];
+ if (value === undefined || typeof value !== "string") {
+ return false;
+ }
+ else if (key.indexOf(".") === -1) {
+ // Simple localization keys such as "OK".
+ return true;
+ }
+ else if (value === key || (value.indexOf("**") === 0 && value.lastIndexOf("**") === value.length - 2)) {
+ objectGraph.console.error("Unlocalized key in keys dictionary", key);
+ return false;
+ }
+ return true;
+ }
+ /**
+ * Returns localization plural category for given number.
+ * @param num The number to return plural category for.
+ * @returns Plural category for specified number or "other"
+ * if there's no plural category function available for current language.
+ *
+ * @see:
+ * - http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
+ * - http://cldr.unicode.org/index/cldr-spec/plural-rules#TOC-Determining-Plural-Categories
+ * - http://unicode.org/repos/cldr/trunk/specs/ldml/tr35-numbers.html#Language_Plural_Rules
+ */
+ pluralCategory(objectGraph, num) {
+ const categoryFn = AmpLocalization.pluralCategoryFnByLanguage[this.language];
+ if (categoryFn !== undefined) {
+ return categoryFn(num);
+ }
+ else {
+ objectGraph.console.warn("Missing plural category function for: " + this.language);
+ return "other";
+ }
+ }
+}
+/**
+ * Markup parameters used for replacing markup tokens in text.
+ */
+AmpLocalization.MARKUP_PARAMS = { nbsp: "&nbsp;", gt: "&gt;", lt: "&lt;", copy: "\u00a9" };
+// endregion
+// regions Plurals
+AmpLocalization.pluralCategoryDefault = function (num) {
+ return "other";
+};
+AmpLocalization.pluralCategoryOne = function (num) {
+ if (num === 1) {
+ return "one";
+ }
+ return "other";
+};
+AmpLocalization.pluralCategoryArabic = function (num) {
+ const n = num >> 0;
+ if (n !== num) {
+ // non integer
+ return "other";
+ }
+ if (n === 0) {
+ return "zero";
+ }
+ if (n === 1) {
+ return "one";
+ }
+ if (n === 2) {
+ return "two";
+ }
+ const m100 = n % 100;
+ if (m100 >= 11) {
+ // n mod 100 in 11..99
+ return "many";
+ }
+ if (m100 >= 3) {
+ // n mod 100 in 3..10
+ return "few";
+ }
+ return "other";
+};
+AmpLocalization.pluralCategoryFrench = function (num) {
+ // Do not check for integer, French includes fractional values!
+ if (num < 2 && num >= 0) {
+ return "one";
+ }
+ return "other";
+};
+AmpLocalization.pluralCategoryHebrew = function (num) {
+ const n = num >> 0;
+ if (n !== num) {
+ // non integer
+ return "other";
+ }
+ if (n === 1) {
+ return "one";
+ }
+ if (n === 2) {
+ return "two";
+ }
+ const m10 = n % 10;
+ if (m10 === 0 && n > 10) {
+ // n mod 10 is 0 and n != 0..10
+ return "many";
+ }
+ return "other";
+};
+AmpLocalization.pluralCategoryPolish = function (num) {
+ const n = num >> 0;
+ if (n !== num) {
+ // non integer
+ return "other";
+ }
+ if (n === 1) {
+ return "one";
+ }
+ const m10 = n % 10;
+ if (m10 <= 4 && m10 >= 2) {
+ const m100 = n % 100;
+ if (m100 > 14 || m100 < 12) {
+ // n mod 10 in 2..4 and n mod 100 not in 12..14
+ return "few";
+ }
+ }
+ return "many";
+};
+AmpLocalization.pluralCategoryRomanian = function (num) {
+ const n = num >> 0;
+ if (n !== num) {
+ // non integer
+ return "few";
+ }
+ if (n === 0) {
+ return "few";
+ }
+ if (n === 1) {
+ return "one";
+ }
+ const m100 = num % 100;
+ if (m100 <= 19 && m100 >= 1) {
+ // n mod 100 in 1..19
+ return "few";
+ }
+ return "other";
+};
+AmpLocalization.pluralCategoryRussian = function (num) {
+ const n = num >> 0;
+ if (n !== num) {
+ // non integer
+ return "other";
+ }
+ const m10 = n % 10;
+ if (m10 >= 5 || m10 === 0) {
+ // n mod 10 is 0 or n mod 10 in 5..9
+ return "many";
+ }
+ const m100 = n % 100;
+ if (m100 <= 14 && m100 >= 11) {
+ // n mod 100 in 11..14
+ return "many";
+ }
+ if (m10 === 1) {
+ // n mod 10 is 1 and n mod 100 is not 11
+ return "one";
+ }
+ // n mod 10 in 2..4 and n mod 100 not in 12..14
+ return "few";
+};
+/**
+ * Mapping language code to plural category function.
+ */
+AmpLocalization.pluralCategoryFnByLanguage = {
+ zh: AmpLocalization.pluralCategoryDefault,
+ id: AmpLocalization.pluralCategoryDefault,
+ ja: AmpLocalization.pluralCategoryDefault,
+ ko: AmpLocalization.pluralCategoryDefault,
+ ms: AmpLocalization.pluralCategoryDefault,
+ th: AmpLocalization.pluralCategoryDefault,
+ vi: AmpLocalization.pluralCategoryDefault,
+ en: AmpLocalization.pluralCategoryOne,
+ ca: AmpLocalization.pluralCategoryOne,
+ da: AmpLocalization.pluralCategoryOne,
+ nl: AmpLocalization.pluralCategoryOne,
+ de: AmpLocalization.pluralCategoryOne,
+ el: AmpLocalization.pluralCategoryOne,
+ fi: AmpLocalization.pluralCategoryOne,
+ hu: AmpLocalization.pluralCategoryOne,
+ it: AmpLocalization.pluralCategoryOne,
+ nb: AmpLocalization.pluralCategoryOne,
+ no: AmpLocalization.pluralCategoryOne,
+ pt: AmpLocalization.pluralCategoryOne,
+ es: AmpLocalization.pluralCategoryOne,
+ sv: AmpLocalization.pluralCategoryOne,
+ tr: AmpLocalization.pluralCategoryOne,
+ ar: AmpLocalization.pluralCategoryArabic,
+ fr: AmpLocalization.pluralCategoryFrench,
+ iw: AmpLocalization.pluralCategoryHebrew,
+ pl: AmpLocalization.pluralCategoryPolish,
+ ro: AmpLocalization.pluralCategoryRomanian,
+ ru: AmpLocalization.pluralCategoryRussian, // Russian
+};
+//# sourceMappingURL=amp-localization.js.map \ No newline at end of file