/** * @param filesize - In bytes. * @return Object with quantized filesize and suitable unit of size. */ function filesizeToObj(filesize) { // We are unlikely to download files measured in units greater than GiB. let units = [ translateWithContext("filesize unit", "B"), translateWithContext("filesize unit", "KiB"), translateWithContext("filesize unit", "MiB"), translateWithContext("filesize unit", "GiB") ]; let i = 0; while (i < units.length - 1) { if (filesize < 1024) break; filesize /= 1024; ++i; } return { "filesize": filesize.toFixed(i == 0 ? 0 : 1), "unit": units[i] }; } function filesizeToString(filesize) { // Translation: For example: 123.4 KiB return sprintf(translate("%(filesize)s %(unit)s"), filesizeToObj(filesize)); } /** * Convert time in milliseconds to [HH:]mm:ss string representation. * * @param time Time period in milliseconds (integer) * @return String representing time period */ function timeToString(time) { return Engine.FormatMillisecondsIntoDateStringGMT(time, time < 1000 * 60 * 60 ? // Translation: Time-format string. See http://userguide.icu-project.org/formatparse/datetime for a guide to the meaning of the letters. translate("mm:ss") : translate("HH:mm:ss")); } /** * These functions rely on the JS cache where possible and * should be prefered over the Engine.Translate ones to optimize the performance. */ var g_Translations = {}; var g_PluralTranslations = {}; var g_TranslationsWithContext = {}; var g_PluralTranslationsWithContext = {}; function isTranslatableString(message) { return typeof message == "string" && !!message.trim(); } /** * Translates the specified English message into the current language. */ function translate(message) { if (!g_Translations[message]) g_Translations[message] = Engine.Translate(message); return g_Translations[message]; } /** * Translates the specified English message into the current language for the specified number. */ function translatePlural(singularMessage, pluralMessage, number) { if (!g_PluralTranslations[singularMessage]) g_PluralTranslations[singularMessage] = {}; if (!g_PluralTranslations[singularMessage][number]) g_PluralTranslations[singularMessage][number] = Engine.TranslatePlural(singularMessage, pluralMessage, number); return g_PluralTranslations[singularMessage][number]; } /** * Translates the specified English message into the current language for the specified context. */ function translateWithContext(context, message) { if (!g_TranslationsWithContext[context]) g_TranslationsWithContext[context] = {}; if (!g_TranslationsWithContext[context][message]) g_TranslationsWithContext[context][message] = Engine.TranslateWithContext(context, message); return g_TranslationsWithContext[context][message]; } /** * Translates the specified English message into the current language for the specified context and number. */ function translatePluralWithContext(context, singularMessage, pluralMessage, number) { if (!g_PluralTranslationsWithContext[context]) g_PluralTranslationsWithContext[context] = {}; if (!g_PluralTranslationsWithContext[context][singularMessage]) g_PluralTranslationsWithContext[context][singularMessage] = {}; if (!g_PluralTranslationsWithContext[context][singularMessage][number]) g_PluralTranslationsWithContext[context][singularMessage][number] = Engine.TranslatePluralWithContext(context, singularMessage, pluralMessage, number); return g_PluralTranslationsWithContext[context][singularMessage][number]; } /** * The input object should contain either of the following properties: * * • A ‘_string’ property that contains a message to translate. * * • A ‘list’ property that contains a list of messages to translate as a * comma-separated list of translated. * * Optionally, the input object may contain a ‘context’ property. In that case, * the value of this property is used as translation context, that is, passed to * the translateWithContext(context, message) function. */ function translateMessageObject(object) { let trans = translate; if (object.context) trans = msg => translateWithContext(object.context, msg); if (object._string) object = trans(object._string); else if (object.list) object = object.list.map(trans).join(translateWithContext("enumeration", ", ")); return object; } /** * Translates any string value in the specified JavaScript object * that is associated with a key included in the specified keys array. * * it accepts an object in the form of * * { * "translatedString1": "my first message", * "unTranslatedString1": "some English string", * "ignoredObject": { * "translatedString2": "my second message", * "unTranslatedString2": "some English string" * }, * "translatedObject1": { * "_string": "my third singular message", * "context": "message context", * }, * translatedObject2: { * "list": ["list", "of", "strings"], * "context": "message context", * }, * } * * Together with a keys list to translate the strings and objects * ["translatedString1", "translatedString2", "translatedObject1", * "translatedObject2"] * * The result will be (f.e. in Dutch) * { * "translatedString1": "mijn eerste bericht", * "unTranslatedString1": "some English string", * "ignoredObject": { * "translatedString2": "mijn tweede bericht", * "unTranslatedString2": "some English string" * }, * "translatedObject1": "mijn derde bericht", * "translatedObject2": "lijst, van, teksten", * } * * So you see that the keys array can also contain lower-level keys, * And that you can include objects in the keys array to translate * them with a context, or to join a list of translations. * * Also, the keys array may be an object where properties are keys to translate * and values are translation contexts to use for each key. */ function translateObjectKeys(object, keys) { if (keys instanceof Array) { for (let property in object) { if (keys.indexOf(property) > -1) { if (isTranslatableString(object[property])) object[property] = translate(object[property]); else if (object[property] instanceof Object) object[property] = translateMessageObject(object[property]); } else if (object[property] instanceof Object) translateObjectKeys(object[property], keys); } } // If ‘keys’ is not an array, it is an object where keys are properties to // translate and values are translation contexts to use for each key. // An empty value means no context. else { for (let property in object) { if (property in keys) { if (isTranslatableString(object[property])) if (keys[property]) object[property] = translateWithContext(keys[property], object[property]); else object[property] = translate(object[property]); else if (object[property] instanceof Object) object[property] = translateMessageObject(object[property]); } else if (object[property] instanceof Object) translateObjectKeys(object[property], keys); } } }