Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion testsuite/tests/util/Locale.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, test, expect } from '@jest/globals';
import { mathjax } from '#js/mathjax.js';
import { Locale } from '#js/util/Locale.js';
import '#js/util/asyncLoad/esm.js';

Expand Down Expand Up @@ -70,7 +71,7 @@ describe('Locale', () => {
expect(Locale.message('undefined', 'Id1')).toBe(
"MathJax(Locale): No localized or default version for message with id 'Id1' from 'undefined'"
);
expect(() => Locale.error('component', 'error', 'x')).toThrow('Error in x');
expect(() => Locale.throw('component', 'error', 'x')).toThrow('Error in x');
Locale.current = 'de';
expect(Locale.message('undefined', 'Id1')).toBe(
"MathJax(Locale): Keine lokalisierte oder Standardversion für die Meldung mit der ID 'Id1' aus 'undefined'"
Expand Down Expand Up @@ -120,6 +121,72 @@ describe('Locale', () => {
});

/********************************************************************************/

test('Locale error, warn, log', async () => {
Locale.registerLocaleFiles('component', '../testsuite/lib/component');

const log: string[] = [];
const methods = [console.error, console.warn, console.log];
console.error = (msg: string) => log.push('error: ' + msg);
console.warn = (msg: string) => log.push('warn: ' + msg);
console.log = (msg: string) => log.push('log: ' + msg);

Locale.error('component', 'test2', 'error');
Locale.warn('component', 'test2', 'warn');
Locale.log('component', 'test2', 'log');

console.error = methods[0];
console.warn = methods[1];
console.log = methods[2];

expect(log).toEqual([
"error: Has error one",
"warn: Has warn one",
"log: Has log one",
]);
});

/********************************************************************************/

test('Locale sync', async () => {
const locale = Locale as any;
Locale.registerLocaleFiles('sync', '../testsuite/lib/component');

//
// Save environment
//
const [load, sync] = [mathjax.asyncLoad, mathjax.asyncIsSynchronous];
const error = console.error;

//
// Test synchronous loading failure
//
mathjax.asyncLoad = () => {throw Error('failed!')};
mathjax.asyncIsSynchronous = true;

const log: string[] = [];
console.error = (msg) => log.push(msg);

locale.getLocaleData('sync', 'en', 'en.json').catch(() => {});
expect(log).toEqual(["MathJax(sync): Can't load 'en.json': failed!"]);

//
// Test synchronous loading success
//
mathjax.asyncLoad = () => {return {'test': 'A test'}};

locale.getLocaleData('sync', 'en', 'en.json');
expect(Locale.message('sync', 'test')).toBe('A test');

//
// Restore environment
//
mathjax.asyncLoad = load;
mathjax.asyncIsSynchronous = sync;
console.error = error;
});

/********************************************************************************/
});

/**********************************************************************************/
Expand Down
74 changes: 66 additions & 8 deletions ts/util/Locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @author dpvc@mathjax.org (Davide Cervone)
*/

import { mathjax } from '../mathjax.js';
import { asyncLoad } from './AsyncLoad.js';

/**
Expand Down Expand Up @@ -123,7 +124,7 @@ export class Locale {
*
* @param {string} component The component whose message is requested
* @param {string} id The id of the message
* @param {string|namedData} data The first argument or the object of names arguments
* @param {string|namedData} data The first argument or the object of named arguments
* @param {string[]} args Any additional string arguments (if data is a string)
* @returns {string} The localized message with arguments substituted in
*/
Expand All @@ -148,12 +149,10 @@ export class Locale {
* Process a message string by substituting the given arguments. The arguments
* can be positional, or a data mapping of names to values.
*
* @param {string} message The message string to process.
* @param {string | namedData = {}} data The first argument or the object of
* names arguments
* @param {string[]} ...args Additional arguments (if data is a string)
* @param {...any} args
* @returns {string} The processed message string with arguments substituted
* @param {string} message The message string to process.
* @param {string|namedData} data The first argument or the object of named arguments
* @param {string[]} args Additional arguments (if data is a string)
* @returns {string} The processed message string with arguments substituted
*/
public static processMessage(
message: string,
Expand Down Expand Up @@ -217,7 +216,7 @@ export class Locale {
* @param {string|namedData} data The first argument or the object of names arguments
* @param {string[]} args Any additional string arguments (if data is a string)
*/
public static error(
public static throw(
component: string,
id: string,
data: string | namedData,
Expand All @@ -226,6 +225,57 @@ export class Locale {
throw Error(this.message(component, id, data, ...args));
}

/**
* Report an error with a given string substituting the given parameters
*
* @param {string} component The component whose message is requested
* @param {string} id The id of the message
* @param {string|namedData} data The first argument or the object of names arguments
* @param {string[]} args Any additional string arguments (if data is a string)
*/
public static error(
component: string,
id: string,
data: string | namedData,
...args: string[]
) {
console.error(this.message(component, id, data, ...args));
}

/**
* Report a warning with a given string substituting the given parameters
*
* @param {string} component The component whose message is requested
* @param {string} id The id of the message
* @param {string|namedData} data The first argument or the object of names arguments
* @param {string[]} args Any additional string arguments (if data is a string)
*/
public static warn(
component: string,
id: string,
data: string | namedData,
...args: string[]
) {
console.warn(this.message(component, id, data, ...args));
}

/**
* Report a message with a given string substituting the given parameters
*
* @param {string} component The component whose message is requested
* @param {string} id The id of the message
* @param {string|namedData} data The first argument or the object of names arguments
* @param {string[]} args Any additional string arguments (if data is a string)
*/
public static log(
component: string,
id: string,
data: string | namedData,
...args: string[]
) {
console.log(this.message(component, id, data, ...args));
}

/**
* Set the locale to the given one (or use the current one), and load
* any needed files (or newly registered files for the current locale).
Expand Down Expand Up @@ -264,6 +314,14 @@ export class Locale {
locale: string,
file: string
): Promise<void> {
if (mathjax.asyncIsSynchronous) {
try {
this.registerMessages(component, locale, mathjax.asyncLoad(file));
} catch (error) {
await this.localeError(component, locale, error);
}
return;
}
return asyncLoad(file)
.then((data: messageData) =>
this.registerMessages(component, locale, data)
Expand Down