UNPKG

@nextcloud/l10n

Version:

Nextcloud localization and translation helpers for apps and libraries

1 lines 26.2 kB
{"version":3,"file":"translation-DoG5ZELJ.mjs","sources":["../../lib/locale.ts","../../lib/registry.ts","../../lib/translation.ts"],"sourcesContent":["/*!\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\n\n/**\n * Returns the user's locale\n */\nexport function getLocale(): string {\n\treturn globalThis._nc_l10n_locale\n}\n\n/**\n * Returns user's locale in canonical form\n * E.g. `en-US` instead of `en_US`\n */\nexport function getCanonicalLocale(): string {\n\treturn getLocale().replaceAll(/_/g, '-')\n}\n\n/**\n * Set the current user's language (locally).\n * This is to be used only for e.g. usage within web workers etc.\n *\n * @param locale - The new language code\n * @since 3.4.0\n */\nexport function setLocale(locale: string): void {\n\tglobalThis._nc_l10n_locale = locale\n\n\t// also for browsers set the DOM\n\tif (typeof document !== 'undefined') {\n\t\tdocument.documentElement.dataset.locale = locale\n\t}\n}\n\n/**\n * Returns the user's language\n */\nexport function getLanguage(): string {\n\treturn globalThis._nc_l10n_language\n}\n\n/**\n * Set the current user's language (locally).\n * This is to be used only for e.g. usage within web workers etc.\n *\n * @param lang - The new language code\n * @since 3.4.0\n */\nexport function setLanguage(lang: string): void {\n\tglobalThis._nc_l10n_language = lang\n\n\t// also for browsers set the DOM\n\tif (typeof document !== 'undefined') {\n\t\tdocument.documentElement.lang = lang\n\t}\n}\n\n/**\n * Check whether the current, or a given, language is read right-to-left\n *\n * @param language Language code to check, defaults to current language\n */\nexport function isRTL(language?: string): boolean {\n\tconst languageCode = language || getLanguage()\n\n\t// Source: https://meta.wikimedia.org/wiki/Template:List_of_language_names_ordered_by_code\n\tconst rtlLanguages = [\n\n\t\t'ae', // Avestan\n\t\t'ar', // 'العربية', Arabic\n\t\t'arc', // Aramaic\n\t\t'arz', // 'مصرى', Egyptian\n\t\t'bcc', // 'بلوچی مکرانی', Southern Balochi\n\t\t'bqi', // 'بختياري', Bakthiari\n\t\t'ckb', // 'Soranî / کوردی', Sorani\n\t\t'dv', // Dhivehi\n\t\t'fa', // 'فارسی', Persian\n\t\t'glk', // 'گیلکی', Gilaki\n\t\t'ha', // 'هَوُسَ', Hausa\n\t\t'he', // 'עברית', Hebrew\n\t\t'khw', // 'کھوار', Khowar\n\t\t'ks', // 'कॉशुर / کٲشُر', Kashmiri\n\t\t'ku', // 'Kurdî / كوردی', Kurdish\n\t\t'mzn', // 'مازِرونی', Mazanderani\n\t\t'nqo', // 'ߒߞߏ', N’Ko\n\t\t'pnb', // 'پنجابی', Western Punjabi\n\t\t'ps', // 'پښتو', Pashto,\n\t\t'sd', // 'سنڌي', Sindhi\n\t\t'ug', // 'Uyghurche / ئۇيغۇرچە', Uyghur\n\t\t'ur', // 'اردو', Urdu\n\t\t'ur-PK', // 'اردو', Urdu (nextcloud BCP47 variant)\n\t\t'uz-AF', // 'اوزبیکی', Uzbek Afghan\n\t\t'yi', // 'ייִדיש', Yiddish\n\n\t]\n\n\treturn rtlLanguages.includes(languageCode)\n}\n\n// Initialize global state if needed (e.g. when not in DOM context like on WebWorker)\n\nglobalThis._nc_l10n_locale ??= (typeof document !== 'undefined' && document.documentElement.dataset.locale)\n\t|| Intl.DateTimeFormat().resolvedOptions().locale.replaceAll(/-/g, '_')\n\nglobalThis._nc_l10n_language ??= (typeof document !== 'undefined' && document.documentElement.lang)\n\t|| (globalThis.navigator?.language ?? 'en')\n","/*!\n * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\n\n/**\n * Translation bundle\n *\n * @example For German translation\n * ```json\n\t{\n\t\t\"some\": \"einige\",\n\t\t\"_%n tree_::_%n trees_\": [\n\t\t\t\"%n Baum\",\n\t\t\t\"%n Bäume\"\n\t\t]\n\t}\n```\n */\nexport type Translations = Record<string, string | string[] | undefined>\n\n/**\n * Function for getting plural form index from translated number\n *\n * @param number Input number to translate\n * @return Index of translation plural form\n * @example For most languages, like English or German\n * ```js\n(number:number) => number === 1 ? 0 : 1\n```\n */\nexport type PluralFunction = (number: number) => number\n\nexport interface AppTranslations {\n\ttranslations: Translations\n\tpluralFunction: PluralFunction\n}\n\n/**\n * Check if translations and plural function are set for given app\n *\n * @param appId - The app id\n */\nexport function hasAppTranslations(appId: string): boolean {\n\treturn (\n\t\tappId in globalThis._oc_l10n_registry_translations\n\t\t&& appId in globalThis._oc_l10n_registry_plural_functions\n\t)\n}\n\n/**\n * Register new, or extend available, translations for an app\n *\n * @param appId - The app id\n * @param translations - The translations list\n * @param pluralFunction - The plural function\n */\nexport function registerAppTranslations(\n\tappId: string,\n\ttranslations: Translations,\n\tpluralFunction: PluralFunction,\n): void {\n\tif (appId === '__proto__' || appId === 'constructor' || appId === 'prototype') {\n\t\tthrow new Error('Invalid appId')\n\t}\n\n\tglobalThis._oc_l10n_registry_translations[appId] = {\n\t\t...(globalThis._oc_l10n_registry_translations[appId] || {}),\n\t\t...translations,\n\t}\n\n\tglobalThis._oc_l10n_registry_plural_functions[appId] = pluralFunction\n}\n\n/**\n * Unregister all translations and plural function for given app\n *\n * @param appId - The app id\n */\nexport function unregisterAppTranslations(appId: string): void {\n\tdelete globalThis._oc_l10n_registry_translations[appId]\n\tdelete globalThis._oc_l10n_registry_plural_functions[appId]\n}\n\n/**\n * Get translations bundle for given app and current locale\n *\n * @param appId - The app id\n */\nexport function getAppTranslations(appId: string): AppTranslations {\n\treturn {\n\t\ttranslations: globalThis._oc_l10n_registry_translations[appId] ?? {},\n\t\tpluralFunction: globalThis._oc_l10n_registry_plural_functions[appId] ?? ((number: number) => number),\n\t}\n}\n\n// Initialize global state if needed\nglobalThis._oc_l10n_registry_translations ??= {}\nglobalThis._oc_l10n_registry_plural_functions ??= {}\n","/*!\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\n\nimport type { AppTranslations, Translations } from './registry.ts'\n\nimport { generateFilePath } from '@nextcloud/router'\nimport DOMPurify from 'dompurify'\nimport escapeHTML from 'escape-html'\nimport { getLanguage } from './locale.ts'\nimport {\n\tgetAppTranslations,\n\thasAppTranslations,\n\tregisterAppTranslations,\n\tunregisterAppTranslations,\n} from './registry.ts'\n\ninterface TranslationOptions {\n\t/** enable/disable auto escape of placeholders (by default enabled) */\n\tescape?: boolean\n\t/** enable/disable sanitization (by default enabled) */\n\tsanitize?: boolean\n\n\t/**\n\t * This is only intended for internal usage.\n\t *\n\t */\n\tbundle?: AppTranslations\n}\n\ninterface TranslationVariableReplacementObject<T> {\n\t/** The value to use for the replacement */\n\tvalue: T\n\t/** Overwrite the `escape` option just for this replacement */\n\tescape: boolean\n}\n\n/**\n * Extracts variables from a translation key\n */\ntype ExtractedVariables<T extends string> =\n\tT extends `${string}{${infer Variable}}${infer Rest}`\n\t\t? Variable | ExtractedVariables<Rest>\n\t\t: never\n\ntype TranslationVariables<K extends string> = Record<ExtractedVariables<K>, string | number | TranslationVariableReplacementObject<string | number>>\n\nexport function translate<T extends string>(app: string, text: T, placeholders?: TranslationVariables<T>, options?: TranslationOptions): string\nexport function translate<T extends string>(app: string, text: T, number?: number, options?: TranslationOptions): string\n/**\n * @inheritdoc\n * @deprecated This overload is deprecated either use placeholders or a number but not both\n */\nexport function translate<T extends string>(app: string, text: T, placeholders?: TranslationVariables<T>, number?: number, options?: TranslationOptions): string\n\n/**\n * Translate a string\n *\n * @param app - The id of the app for which to translate the string\n * @param text - The string to translate\n * @param placeholdersOrNumber - Map of placeholder key to value or a number replacing `%n`\n * @param optionsOrNumber - The translation options or a number to replace `%n` with\n * @param options - Options object\n * @param options.escape - Enable/disable auto escape of placeholders (by default enabled)\n * @param options.sanitize - Enable/disable sanitization (by default enabled) [WARNING: This only work in DOM environment!]\n */\nexport function translate<T extends string>(\n\tapp: string,\n\ttext: T,\n\tplaceholdersOrNumber?: TranslationVariables<T> | number,\n\toptionsOrNumber?: number | TranslationOptions,\n\toptions?: TranslationOptions,\n): string {\n\tconst vars = typeof placeholdersOrNumber === 'object' ? placeholdersOrNumber : undefined\n\tconst number = typeof optionsOrNumber === 'number' ? optionsOrNumber : (typeof placeholdersOrNumber === 'number' ? placeholdersOrNumber : undefined)\n\n\tconst allOptions = {\n\t\t// defaults\n\t\tescape: true,\n\t\tsanitize: true,\n\t\t// overwrite with user config\n\t\t...(\n\t\t\ttypeof options === 'object'\n\t\t\t\t? options\n\t\t\t\t: (\n\t\t\t\t\t\ttypeof optionsOrNumber === 'object'\n\t\t\t\t\t\t\t? optionsOrNumber\n\t\t\t\t\t\t\t: {}\n\t\t\t\t\t)\n\t\t),\n\t}\n\n\tconst identity = <T>(value: T): T => value\n\tconst optSanitize = (allOptions.sanitize ? DOMPurify.sanitize : identity) || identity\n\tconst optEscape = allOptions.escape ? escapeHTML : identity\n\n\tconst isValidReplacement = (value: unknown) => typeof value === 'string' || typeof value === 'number'\n\n\t// TODO: cache this function to avoid inline recreation\n\t// of the same function over and over again in case\n\t// translate() is used in a loop\n\tconst _build = (text: string, vars?: TranslationVariables<T>, number?: number) => {\n\t\treturn text.replace(/%n/g, '' + number).replace(/{([^{}]*)}/g, (match, key: ExtractedVariables<T>) => {\n\t\t\tif (vars === undefined || !(key in vars)) {\n\t\t\t\treturn optEscape(match)\n\t\t\t}\n\n\t\t\tconst replacement = vars[key]\n\t\t\tif (isValidReplacement(replacement)) {\n\t\t\t\treturn optEscape(`${replacement}`)\n\t\t\t} else if (typeof replacement === 'object' && isValidReplacement(replacement.value)) {\n\t\t\t\t// Replacement is an object so indiviual escape handling\n\t\t\t\tconst escape = replacement.escape !== false ? escapeHTML : identity\n\t\t\t\treturn escape(`${replacement.value}`)\n\t\t\t} else {\n\t\t\t\t/* This should not happen,\n\t\t\t\t * but the variables are used defined so not allowed types could still be given,\n\t\t\t\t * in this case ignore the replacement and use the placeholder\n\t\t\t\t */\n\t\t\t\treturn optEscape(match)\n\t\t\t}\n\t\t})\n\t}\n\n\tconst bundle = options?.bundle ?? getAppTranslations(app)\n\tlet translation = bundle.translations[text] || text\n\ttranslation = Array.isArray(translation) ? translation[0] : translation\n\n\tif (typeof vars === 'object' || number !== undefined) {\n\t\treturn optSanitize(_build(\n\t\t\ttranslation,\n\t\t\tvars,\n\t\t\tnumber,\n\t\t))\n\t} else {\n\t\treturn optSanitize(translation)\n\t}\n}\n\n/**\n * Translate a string containing an object which possibly requires a plural form\n *\n * @param app - The id of the app for which to translate the string\n * @param textSingular - The string to translate for exactly one object\n * @param textPlural - The string to translate for n objects\n * @param number - Number to determine whether to use singular or plural\n * @param vars - Mapping of placeholder key to value\n * @param options - Options object\n */\nexport function translatePlural<T extends string, K extends string>(\n\tapp: string,\n\ttextSingular: T,\n\ttextPlural: K,\n\tnumber: number,\n\tvars?: TranslationVariables<T> & TranslationVariables<K>,\n\toptions?: TranslationOptions,\n): string {\n\tconst identifier = '_' + textSingular + '_::_' + textPlural + '_'\n\tconst bundle = options?.bundle ?? getAppTranslations(app)\n\tconst value = bundle.translations[identifier]\n\n\tif (typeof value !== 'undefined') {\n\t\tconst translation = value\n\t\tif (Array.isArray(translation)) {\n\t\t\tconst plural = bundle.pluralFunction(number)\n\t\t\treturn translate(app, translation[plural], vars, number, options)\n\t\t}\n\t}\n\n\t// vars type is casted to allow extra keys without runtime filtering (they are harmless), and without allowing wrong keys in translate\n\tif (number === 1) {\n\t\treturn translate(app, textSingular, vars as TranslationVariables<T>, number, options)\n\t} else {\n\t\treturn translate(app, textPlural, vars as TranslationVariables<K>, number, options)\n\t}\n}\n\n/**\n * Load an app's translation bundle if not loaded already.\n *\n * @param appName - Name of the app to load\n */\nexport async function loadTranslations(appName: string): Promise<AppTranslations>\n/**\n * Load an app's translation bundle if not loaded already.\n *\n * @param appName - Name of the app to load\n * @param callback - Callback to be called when the translations are loaded\n * @deprecated Use the returned promise instead\n */\nexport async function loadTranslations(appName: string, callback: (...args: []) => unknown): Promise<AppTranslations>\n/**\n * Load an app's translation bundle if not loaded already.\n *\n * @param appName - Name of the app to load\n * @param callback - Callback to be called when the translations are loaded (deprecated)\n */\nexport async function loadTranslations(appName: string, callback?: (bundle: AppTranslations) => void): Promise<AppTranslations> {\n\tif (hasAppTranslations(appName) || getLanguage() === 'en') {\n\t\tconst bundle = getAppTranslations(appName)\n\t\tcallback?.(bundle)\n\t\treturn bundle\n\t}\n\n\tlet response: Response\n\ttry {\n\t\tconst url = generateFilePath(appName, 'l10n', getLanguage() + '.json')\n\t\tresponse = await fetch(url)\n\t} catch (error) {\n\t\tthrow new Error('Network error', { cause: error })\n\t}\n\n\tif (response.ok) {\n\t\ttry {\n\t\t\tconst bundle = await response.json()\n\t\t\tif (typeof bundle.translations === 'object') {\n\t\t\t\tregister(appName, bundle.translations)\n\t\t\t\tcallback?.(bundle)\n\t\t\t\treturn bundle\n\t\t\t}\n\t\t} catch {\n\t\t\t// error is probably a SyntaxError due to invalid response text, this is handled by next line\n\t\t}\n\t\tthrow new Error('Invalid content of translation bundle')\n\t} else {\n\t\tthrow new Error(response.statusText)\n\t}\n}\n\n/**\n * Register an app's translation bundle.\n *\n * @param appName name of the app\n * @param bundle translation bundle\n */\nexport function register(appName: string, bundle: Translations) {\n\tregisterAppTranslations(appName, bundle, getPlural)\n}\n\n/**\n * Unregister all translations of an app\n *\n * @param appName name of the app\n * @since 2.1.0\n */\nexport function unregister(appName: string) {\n\treturn unregisterAppTranslations(appName)\n}\n\n/**\n * Get array index of translations for a plural form\n *\n * @param number - The number of elements\n * @param language - The language to use (or autodetect if not set)\n * @return 0 for the singular form(, 1 for the first plural form, ...)\n */\nexport function getPlural(number: number, language = getLanguage()) {\n\tif (language === 'pt-BR') {\n\t\t// temporary set a locale for brazilian\n\t\tlanguage = 'xbr'\n\t}\n\n\tif (language.length > 3) {\n\t\tlanguage = language.substring(0, language.lastIndexOf('-'))\n\t}\n\n\t/*\n\t * The plural rules are derived from code of the Zend Framework (2010-09-25),\n\t * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).\n\t * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)\n\t */\n\tswitch (language) {\n\t\tcase 'az':\n\t\tcase 'bo':\n\t\tcase 'dz':\n\t\tcase 'id':\n\t\tcase 'ja':\n\t\tcase 'jv':\n\t\tcase 'ka':\n\t\tcase 'km':\n\t\tcase 'kn':\n\t\tcase 'ko':\n\t\tcase 'ms':\n\t\tcase 'th':\n\t\tcase 'tr':\n\t\tcase 'vi':\n\t\tcase 'zh':\n\t\t\treturn 0\n\n\t\tcase 'af':\n\t\tcase 'bn':\n\t\tcase 'bg':\n\t\tcase 'ca':\n\t\tcase 'da':\n\t\tcase 'de':\n\t\tcase 'el':\n\t\tcase 'en':\n\t\tcase 'eo':\n\t\tcase 'es':\n\t\tcase 'et':\n\t\tcase 'eu':\n\t\tcase 'fa':\n\t\tcase 'fi':\n\t\tcase 'fo':\n\t\tcase 'fur':\n\t\tcase 'fy':\n\t\tcase 'gl':\n\t\tcase 'gu':\n\t\tcase 'ha':\n\t\tcase 'he':\n\t\tcase 'hu':\n\t\tcase 'is':\n\t\tcase 'it':\n\t\tcase 'ku':\n\t\tcase 'lb':\n\t\tcase 'ml':\n\t\tcase 'mn':\n\t\tcase 'mr':\n\t\tcase 'nah':\n\t\tcase 'nb':\n\t\tcase 'ne':\n\t\tcase 'nl':\n\t\tcase 'nn':\n\t\tcase 'no':\n\t\tcase 'oc':\n\t\tcase 'om':\n\t\tcase 'or':\n\t\tcase 'pa':\n\t\tcase 'pap':\n\t\tcase 'ps':\n\t\tcase 'pt':\n\t\tcase 'so':\n\t\tcase 'sq':\n\t\tcase 'sv':\n\t\tcase 'sw':\n\t\tcase 'ta':\n\t\tcase 'te':\n\t\tcase 'tk':\n\t\tcase 'ur':\n\t\tcase 'zu':\n\t\t\treturn number === 1 ? 0 : 1\n\n\t\tcase 'am':\n\t\tcase 'bh':\n\t\tcase 'fil':\n\t\tcase 'fr':\n\t\tcase 'gun':\n\t\tcase 'hi':\n\t\tcase 'hy':\n\t\tcase 'ln':\n\t\tcase 'mg':\n\t\tcase 'nso':\n\t\tcase 'xbr':\n\t\tcase 'ti':\n\t\tcase 'wa':\n\t\t\treturn number === 0 || number === 1 ? 0 : 1\n\n\t\tcase 'be':\n\t\tcase 'bs':\n\t\tcase 'hr':\n\t\tcase 'ru':\n\t\tcase 'sh':\n\t\tcase 'sr':\n\t\tcase 'uk':\n\t\t\treturn number % 10 === 1 && number % 100 !== 11\n\t\t\t\t? 0\n\t\t\t\t: number % 10 >= 2\n\t\t\t\t\t&& number % 10 <= 4\n\t\t\t\t\t&& (number % 100 < 10 || number % 100 >= 20)\n\t\t\t\t\t? 1\n\t\t\t\t\t: 2\n\n\t\tcase 'cs':\n\t\tcase 'sk':\n\t\t\treturn number === 1 ? 0 : number >= 2 && number <= 4 ? 1 : 2\n\n\t\tcase 'ga':\n\t\t\treturn number === 1 ? 0 : number === 2 ? 1 : 2\n\n\t\tcase 'lt':\n\t\t\treturn number % 10 === 1 && number % 100 !== 11\n\t\t\t\t? 0\n\t\t\t\t: number % 10 >= 2 && (number % 100 < 10 || number % 100 >= 20)\n\t\t\t\t\t? 1\n\t\t\t\t\t: 2\n\n\t\tcase 'sl':\n\t\t\treturn number % 100 === 1\n\t\t\t\t? 0\n\t\t\t\t: number % 100 === 2\n\t\t\t\t\t? 1\n\t\t\t\t\t: number % 100 === 3 || number % 100 === 4\n\t\t\t\t\t\t? 2\n\t\t\t\t\t\t: 3\n\n\t\tcase 'mk':\n\t\t\treturn number % 10 === 1 ? 0 : 1\n\n\t\tcase 'mt':\n\t\t\treturn number === 1\n\t\t\t\t? 0\n\t\t\t\t: number === 0 || (number % 100 > 1 && number % 100 < 11)\n\t\t\t\t\t? 1\n\t\t\t\t\t: number % 100 > 10 && number % 100 < 20\n\t\t\t\t\t\t? 2\n\t\t\t\t\t\t: 3\n\n\t\tcase 'lv':\n\t\t\treturn number === 0\n\t\t\t\t? 0\n\t\t\t\t: number % 10 === 1 && number % 100 !== 11\n\t\t\t\t\t? 1\n\t\t\t\t\t: 2\n\n\t\tcase 'pl':\n\t\t\treturn number === 1\n\t\t\t\t? 0\n\t\t\t\t: number % 10 >= 2\n\t\t\t\t\t&& number % 10 <= 4\n\t\t\t\t\t&& (number % 100 < 12 || number % 100 > 14)\n\t\t\t\t\t? 1\n\t\t\t\t\t: 2\n\n\t\tcase 'cy':\n\t\t\treturn number === 1\n\t\t\t\t? 0\n\t\t\t\t: number === 2\n\t\t\t\t\t? 1\n\t\t\t\t\t: number === 8 || number === 11\n\t\t\t\t\t\t? 2\n\t\t\t\t\t\t: 3\n\n\t\tcase 'ro':\n\t\t\treturn number === 1\n\t\t\t\t? 0\n\t\t\t\t: number === 0 || (number % 100 > 0 && number % 100 < 20)\n\t\t\t\t\t? 1\n\t\t\t\t\t: 2\n\n\t\tcase 'ar':\n\t\t\treturn number === 0\n\t\t\t\t? 0\n\t\t\t\t: number === 1\n\t\t\t\t\t? 1\n\t\t\t\t\t: number === 2\n\t\t\t\t\t\t? 2\n\t\t\t\t\t\t: number % 100 >= 3 && number % 100 <= 10\n\t\t\t\t\t\t\t? 3\n\t\t\t\t\t\t\t: number % 100 >= 11 && number % 100 <= 99\n\t\t\t\t\t\t\t\t? 4\n\t\t\t\t\t\t\t\t: 5\n\n\t\tdefault:\n\t\t\treturn 0\n\t}\n}\n\n// Export short-hand\n\nexport {\n\ttranslatePlural as n,\n\ttranslate as t,\n}\n"],"names":["text","vars","number"],"mappings":"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"}