extensions: Add static defineTranslationFunctions() method
The method can be used to define a set of gettext functions that call the corresponding method of an extension. Those functions are very similar to the gettext functions we are exporting, except that: - looking up the extension is delegated to the Extension/Preferences class - it is possible to avoid examining the stack when called with `import.meta.url` Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
This commit is contained in:
parent
cd99fbae50
commit
f59d523694
@ -1,4 +1,4 @@
|
|||||||
import {ExtensionBase, setExtensionManager} from './sharedInternals.js';
|
import {ExtensionBase, GettextWrapper, setExtensionManager} from './sharedInternals.js';
|
||||||
|
|
||||||
export {gettext, ngettext, pgettext} from './sharedInternals.js';
|
export {gettext, ngettext, pgettext} from './sharedInternals.js';
|
||||||
|
|
||||||
@ -6,6 +6,11 @@ const {extensionManager} = imports.ui.main;
|
|||||||
setExtensionManager(extensionManager);
|
setExtensionManager(extensionManager);
|
||||||
|
|
||||||
export class Extension extends ExtensionBase {
|
export class Extension extends ExtensionBase {
|
||||||
|
static defineTranslationFunctions(url) {
|
||||||
|
const wrapper = new GettextWrapper(this, url);
|
||||||
|
return wrapper.defineTranslationFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
enable() {
|
enable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import GObject from 'gi://GObject';
|
import GObject from 'gi://GObject';
|
||||||
|
|
||||||
import {ExtensionBase, setExtensionManager} from './sharedInternals.js';
|
import {ExtensionBase, GettextWrapper, setExtensionManager} from './sharedInternals.js';
|
||||||
import {extensionManager} from '../extensionsService.js';
|
import {extensionManager} from '../extensionsService.js';
|
||||||
|
|
||||||
setExtensionManager(extensionManager);
|
setExtensionManager(extensionManager);
|
||||||
@ -8,6 +8,11 @@ setExtensionManager(extensionManager);
|
|||||||
export {gettext, ngettext, pgettext} from './sharedInternals.js';
|
export {gettext, ngettext, pgettext} from './sharedInternals.js';
|
||||||
|
|
||||||
export class ExtensionPreferences extends ExtensionBase {
|
export class ExtensionPreferences extends ExtensionBase {
|
||||||
|
static defineTranslationFunctions(url) {
|
||||||
|
const wrapper = new GettextWrapper(this, url);
|
||||||
|
return wrapper.defineTranslationFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the preferences window with preferences.
|
* Fill the preferences window with preferences.
|
||||||
*
|
*
|
||||||
|
@ -184,6 +184,99 @@ export class ExtensionBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class GettextWrapper {
|
||||||
|
#url;
|
||||||
|
#extensionClass;
|
||||||
|
|
||||||
|
constructor(extensionClass, url) {
|
||||||
|
this.#url = url;
|
||||||
|
this.#extensionClass = extensionClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
#detectUrl() {
|
||||||
|
const basePath = '/gnome-shell/extensions/';
|
||||||
|
|
||||||
|
// Search for an occurrence of an extension stack frame
|
||||||
|
// Start at 1 because 0 is the stack frame of this function
|
||||||
|
const [, ...stack] = new Error().stack.split('\n');
|
||||||
|
const extensionLine = stack.find(
|
||||||
|
line => line.includes(basePath));
|
||||||
|
|
||||||
|
if (!extensionLine)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// The exact stack line differs depending on where the function
|
||||||
|
// was called (function or module scope), and whether it's called
|
||||||
|
// from a module or legacy import (file:// URI vs. plain path).
|
||||||
|
//
|
||||||
|
// We don't have to care about the exact composition, all we need
|
||||||
|
// is a string that can be traversed as path and contains the UUID
|
||||||
|
const path = extensionLine.slice(extensionLine.indexOf(basePath));
|
||||||
|
return `file://${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lookupExtension(funcName) {
|
||||||
|
if (!this.#url)
|
||||||
|
this.#url = this.#detectUrl();
|
||||||
|
|
||||||
|
const extension = this.#extensionClass.lookupByURL(this.#url);
|
||||||
|
if (!extension)
|
||||||
|
throw new Error(`${funcName} can only be called from extensions`);
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gettext(str) {
|
||||||
|
const extension = this.#lookupExtension('gettext');
|
||||||
|
return extension.gettext(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ngettext(str, strPlural, n) {
|
||||||
|
const extension = this.#lookupExtension('ngettext');
|
||||||
|
return extension.gettext(str, strPlural, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pgettext(context, str) {
|
||||||
|
const extension = this.#lookupExtension('pgettext');
|
||||||
|
return extension.pgettext(context, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineTranslationFunctions() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Translate `str` using the extension's gettext domain
|
||||||
|
*
|
||||||
|
* @param {string} str - the string to translate
|
||||||
|
*
|
||||||
|
* @returns {string} the translated string
|
||||||
|
*/
|
||||||
|
gettext: this.#gettext.bind(this),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate `str` and choose plural form using the extension's
|
||||||
|
* gettext domain
|
||||||
|
*
|
||||||
|
* @param {string} str - the string to translate
|
||||||
|
* @param {string} strPlural - the plural form of the string
|
||||||
|
* @param {number} n - the quantity for which translation is needed
|
||||||
|
*
|
||||||
|
* @returns {string} the translated string
|
||||||
|
*/
|
||||||
|
ngettext: this.#ngettext.bind(this),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate `str` in the context of `context` using the extension's
|
||||||
|
* gettext domain
|
||||||
|
*
|
||||||
|
* @param {string} context - context to disambiguate `str`
|
||||||
|
* @param {string} str - the string to translate
|
||||||
|
*
|
||||||
|
* @returns {string} the translated string
|
||||||
|
*/
|
||||||
|
pgettext: this.#pgettext.bind(this),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user