mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-23 04:34:15 -04:00
(pronouns) enable translations for slash modifiers
This commit is contained in:
parent
d792270c80
commit
11d291a24f
@ -82,6 +82,10 @@ pronouns:
|
||||
comprehensive:
|
||||
simple: 'simple'
|
||||
comprehensive: 'comprehensive'
|
||||
slashes:
|
||||
plural: 'plural'
|
||||
pluralHonorific: 'plural-honorific'
|
||||
description: 'description'
|
||||
others: 'Other forms'
|
||||
othersRaw: 'other'
|
||||
or: 'or'
|
||||
|
@ -86,6 +86,9 @@ pronouns:
|
||||
comprehensive:
|
||||
simple: 'häufige'
|
||||
comprehensive: 'erweitert'
|
||||
slashes:
|
||||
plural: 'plural'
|
||||
description: 'beschreibung'
|
||||
others: 'Andere Formen'
|
||||
othersRaw: 'andere'
|
||||
or: 'oder'
|
||||
|
@ -79,6 +79,9 @@ pronouns:
|
||||
Even though for many people it's incredibly important that people use specific pronouns to talk about them,
|
||||
others don't mind being addressed in any way – as long as the context is clear as to who one talks about.
|
||||
options: 'check out the options [share]{/pronouns=here}.'
|
||||
slashes:
|
||||
plural: 'plural'
|
||||
description: 'description'
|
||||
others: 'Other forms'
|
||||
othersRaw: 'other'
|
||||
or: 'or'
|
||||
|
@ -60,7 +60,7 @@ export default {
|
||||
continue;
|
||||
}
|
||||
|
||||
const pronounEntity = buildPronoun(pronouns, link);
|
||||
const pronounEntity = buildPronoun(pronouns, link, this.$translator);
|
||||
|
||||
if (pronounEntity) {
|
||||
pronounOpinions.push({
|
||||
@ -76,7 +76,7 @@ export default {
|
||||
if (!this.config.profile?.flags?.defaultPronoun) {
|
||||
return null;
|
||||
}
|
||||
let mainPronoun = buildPronoun(pronouns, this.config.profile.flags.defaultPronoun);
|
||||
let mainPronoun = buildPronoun(pronouns, this.config.profile.flags.defaultPronoun, this.$translator);
|
||||
let mainOpinion = -1;
|
||||
for (const { pronoun, opinion } of this.pronounOpinions) {
|
||||
if (typeof pronoun === 'string') {
|
||||
|
@ -532,7 +532,7 @@ export default {
|
||||
if (!this.config.profile?.flags?.defaultPronoun) {
|
||||
return null;
|
||||
}
|
||||
let mainPronoun = buildPronoun(pronouns, this.config.profile.flags?.defaultPronoun);
|
||||
let mainPronoun = buildPronoun(pronouns, this.config.profile.flags?.defaultPronoun, this.$translator);
|
||||
let mainOpinion = -1;
|
||||
for (const { value: pronoun, opinion } of this.pronouns) {
|
||||
const opinionValue = opinions[opinion]?.value || 0;
|
||||
@ -627,7 +627,7 @@ export default {
|
||||
}
|
||||
},
|
||||
normaliseAndBuildPronoun(pronoun) {
|
||||
return buildPronoun(pronouns, this.normalisePronoun(pronoun));
|
||||
return buildPronoun(pronouns, this.normalisePronoun(pronoun), this.$translator);
|
||||
},
|
||||
validatePronoun(pronoun) {
|
||||
pronoun = this.normalisePronoun(pronoun);
|
||||
@ -637,7 +637,7 @@ export default {
|
||||
return this.validateAnyPronoun(pronoun) ||
|
||||
this.config.pronouns.null && this.config.pronouns.null.routes && this.config.pronouns.null.routes.includes(pronoun) ||
|
||||
this.config.pronouns.mirror && this.config.pronouns.mirror.route === pronoun ||
|
||||
buildPronoun(pronouns, pronoun)
|
||||
buildPronoun(pronouns, pronoun, this.$translator)
|
||||
? null
|
||||
: 'profile.pronounsNotFound';
|
||||
},
|
||||
|
@ -130,7 +130,7 @@ export default {
|
||||
const key = this.getPronounKeyFromUrl();
|
||||
|
||||
const selectedPronoun = this.config.pronouns.enabled && key
|
||||
? buildPronoun(pronouns, key)
|
||||
? buildPronoun(pronouns, key, this.$translator)
|
||||
: null;
|
||||
|
||||
return {
|
||||
|
@ -322,7 +322,7 @@ export default {
|
||||
return null;
|
||||
}
|
||||
|
||||
const slashes = this.selectedPronoun.toStringSlashes();
|
||||
const slashes = this.selectedPronoun.toStringSlashes(this.$translator);
|
||||
|
||||
let link;
|
||||
if (this.usedBaseEquals) {
|
||||
|
@ -1,15 +1,19 @@
|
||||
import { Router } from 'express';
|
||||
import SQL from 'sql-template-strings';
|
||||
import { createCanvas, loadImage } from 'canvas';
|
||||
import { loadSuml } from '../loader.js';
|
||||
import { loadSuml, loadSumlFromBase } from '../loader.js';
|
||||
import avatar from '../avatar.js';
|
||||
import { buildPronoun, parsePronouns } from '../../src/buildPronoun.js';
|
||||
import { loadTsv } from '../../src/tsv.js';
|
||||
import { handleErrorAsync } from '../../src/helpers.js';
|
||||
import { Translator } from '../../src/translator.js';
|
||||
import { CacheObject } from '../../src/cache.js';
|
||||
import { registerLocaleFont } from '../localeFont.js';
|
||||
|
||||
const translations = loadSuml('translations');
|
||||
const baseTranslations = loadSumlFromBase('locale/_base/translations');
|
||||
|
||||
const translator = new Translator(translations, baseTranslations, global.config);
|
||||
|
||||
const drawCircle = (context, image, x, y, size) => {
|
||||
context.save();
|
||||
@ -84,6 +88,7 @@ router.get('/banner/:pronounName*.png', handleErrorAsync(async (req, res) => {
|
||||
const pronoun = buildPronoun(
|
||||
parsePronouns(loadTsv(`${__dirname}/../../data/pronouns/pronouns.tsv`)),
|
||||
pronounName,
|
||||
translator,
|
||||
);
|
||||
|
||||
if (pronounName === 'zaimki' || !pronoun && pronounName !== global.config.pronouns.any && (!global.config.pronouns || pronounName !== global.config.pronouns.mirror)) {
|
||||
|
@ -1,13 +1,19 @@
|
||||
import { Router } from 'express';
|
||||
import { loadTsv } from '../loader.js';
|
||||
import { loadSuml, loadSumlFromBase, loadTsv } from '../loader.js';
|
||||
import { buildPronoun, parsePronouns } from '../../src/buildPronoun.js';
|
||||
import { buildList, handleErrorAsync } from '../../src/helpers.js';
|
||||
import { Example } from '../../src/classes.js';
|
||||
import { caches } from '../../src/cache.js';
|
||||
import { Translator } from '../../src/translator.js';
|
||||
import md5 from 'js-md5';
|
||||
import assert from 'assert';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
const translations = loadSuml('translations');
|
||||
const baseTranslations = loadSumlFromBase('locale/_base/translations');
|
||||
|
||||
const translator = new Translator(translations, baseTranslations, global.config);
|
||||
|
||||
const buildExample = (e) => new Example(
|
||||
Example.parse(e.singular),
|
||||
Example.parse(e.plural || e.singular),
|
||||
@ -52,6 +58,7 @@ router.get('/pronouns/:pronoun*', handleErrorAsync(async (req, res) => {
|
||||
const pronoun = buildPronoun(
|
||||
parsePronouns(loadTsv('pronouns/pronouns')),
|
||||
req.params.pronoun + req.params[0],
|
||||
translator,
|
||||
);
|
||||
if (pronoun) {
|
||||
pronoun.examples = addExamples(pronoun, requestExamples(req.query.examples));
|
||||
@ -64,6 +71,7 @@ router.get('/pronouns-name/:pronoun*', handleErrorAsync(async (req, res) => {
|
||||
const pronoun = buildPronoun(
|
||||
parsePronouns(loadTsv('pronouns/pronouns')),
|
||||
(req.params.pronoun + req.params[0]).toLowerCase(),
|
||||
translator,
|
||||
);
|
||||
if (!pronoun) {
|
||||
return res.status(404).json({ error: 'Not found' });
|
||||
|
@ -58,7 +58,23 @@ const buildPronounFromTemplate = (key, template) => {
|
||||
);
|
||||
};
|
||||
|
||||
const buildPronounFromSlashes = (config, path) => {
|
||||
const isModifier = (chunk, key, translator) => {
|
||||
// use both locale and base translations to ensure backwards compatibility if key gets translated
|
||||
return chunk === `:${translator.translate(key)}` || chunk === `:${translator.get(key, false, true)}`;
|
||||
};
|
||||
|
||||
const extractModifierValue = (chunk, key, translator) => {
|
||||
// use both locale and base translations to ensure backwards compatibility if key gets translated
|
||||
const prefixes = [`:${translator.translate(key)}=`, `:${translator.get(key, false, true)}=`];
|
||||
for (const prefix of prefixes) {
|
||||
if (chunk.startsWith(prefix)) {
|
||||
return chunk.substring(prefix.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const buildPronounFromSlashes = (config, path, translator) => {
|
||||
const chunks = path.split(/(?<!`)\//);
|
||||
let plural = false;
|
||||
let pluralHonorific = false;
|
||||
@ -66,14 +82,16 @@ const buildPronounFromSlashes = (config, path) => {
|
||||
const morphemeChunks = [];
|
||||
for (const chunk of chunks) {
|
||||
if (chunk.startsWith(':')) {
|
||||
if (config.pronouns.plurals && chunk === ':plural') {
|
||||
if (config.pronouns.plurals && isModifier(chunk, 'pronouns.slashes.plural', translator)) {
|
||||
plural = true;
|
||||
} else if (config.pronouns.plurals && config.pronouns.honorifics && chunk === ':plural-honorific') {
|
||||
} else if (config.pronouns.plurals && config.pronouns.honorifics &&
|
||||
isModifier(chunk, 'pronouns.slashes.pluralHonorific', translator)) {
|
||||
pluralHonorific = true;
|
||||
} else {
|
||||
const descriptionModifierPrefix = ':description=';
|
||||
if (chunk.startsWith(descriptionModifierPrefix)) {
|
||||
description = unescapeControlSymbols(chunk.substring(descriptionModifierPrefix.length));
|
||||
const descriptionModifierValue =
|
||||
extractModifierValue(chunk, 'pronouns.slashes.description', translator);
|
||||
if (descriptionModifierValue) {
|
||||
description = unescapeControlSymbols(descriptionModifierValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -112,7 +130,7 @@ const buildPronounFromSlashes = (config, path) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const buildPronoun = (pronouns, path) => {
|
||||
export const buildPronoun = (pronouns, path, translator) => {
|
||||
if (!path) {
|
||||
return null;
|
||||
}
|
||||
@ -180,7 +198,7 @@ export const buildPronoun = (pronouns, path) => {
|
||||
}
|
||||
|
||||
if (!pronoun && config.pronouns.slashes !== false) {
|
||||
return buildPronounFromSlashes(config, path);
|
||||
return buildPronounFromSlashes(config, path, translator);
|
||||
}
|
||||
|
||||
return pronoun;
|
||||
|
@ -467,7 +467,7 @@ export class Pronoun {
|
||||
return this.toArray().join(',');
|
||||
}
|
||||
|
||||
toStringSlashes() {
|
||||
toStringSlashes(translator) {
|
||||
if (!config.pronouns.slashes) {
|
||||
return null;
|
||||
}
|
||||
@ -490,13 +490,14 @@ export class Pronoun {
|
||||
});
|
||||
|
||||
if (this.plural[0]) {
|
||||
chunks.push(':plural');
|
||||
chunks.push(`:${translator.translate('pronouns.slashes.plural')}`);
|
||||
}
|
||||
if (this.pluralHonorific[0]) {
|
||||
chunks.push(':plural-honorific');
|
||||
chunks.push(`:${translator.translate('pronouns.slashes.pluralHonorific')}`);
|
||||
}
|
||||
if (this.description) {
|
||||
chunks.push(`:description=${escapeControlSymbols(this.description)}`);
|
||||
const escapedDescription = escapeControlSymbols(this.description);
|
||||
chunks.push(`:${translator.translate('pronouns.slashes.description')}=${escapedDescription}`);
|
||||
}
|
||||
|
||||
// encode a trailing space so that it does not get removed during a request
|
||||
|
@ -63,6 +63,22 @@ export function listMissingTranslations(translations, baseTranslations, config)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config.pronouns.slashes && keyMatches('pronouns.slashes.')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config.pronouns.plurals && keyMatches(
|
||||
'pronouns.plural',
|
||||
'pronouns.slashes.plural',
|
||||
'pronouns.slashes.pluralHonorific',
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config.pronouns.honorifics && keyMatches('pronouns.slashes.pluralHonorific')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config.pronouns.comprehensive && keyMatches('pronouns.comprehensive.')) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,16 @@
|
||||
import { beforeEach, describe, expect, jest, test } from '@jest/globals';
|
||||
import { Translator } from '../src/translator.js';
|
||||
|
||||
const translations = {
|
||||
pronouns: {
|
||||
slashes: {
|
||||
plural: 'plural',
|
||||
pluralHonorific: 'plural-honorific',
|
||||
description: 'description',
|
||||
},
|
||||
},
|
||||
};
|
||||
const translator = new Translator(translations, translations, []);
|
||||
|
||||
// workaround to be independent of the current selected locale
|
||||
jest.unstable_mockModule('../data/pronouns/morphemes.js', () => {
|
||||
@ -21,13 +33,13 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
test('finds pronouns by canonical name', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'they'));
|
||||
const actual = expect(buildPronoun(pronouns, 'they', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toBe(pronouns.they);
|
||||
});
|
||||
|
||||
test('finds pronouns by alias', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'they/them'));
|
||||
const actual = expect(buildPronoun(pronouns, 'they/them', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toBe(pronouns.they);
|
||||
});
|
||||
@ -46,7 +58,7 @@ describe('when configured that emojiself pronouns are available', () => {
|
||||
});
|
||||
|
||||
test('builds pronouns from emoji', () => {
|
||||
const actual = expect(buildPronoun(pronouns, '💙'));
|
||||
const actual = expect(buildPronoun(pronouns, '💙', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(new Pronoun(
|
||||
'💙',
|
||||
@ -82,7 +94,7 @@ describe('when configured that null pronouns are available', () => {
|
||||
});
|
||||
|
||||
test('builds pronouns from name', () => {
|
||||
const actual = expect(buildPronoun(pronouns, ':S'));
|
||||
const actual = expect(buildPronoun(pronouns, ':S', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(new Pronoun(
|
||||
'S',
|
||||
@ -103,7 +115,7 @@ describe('when configured that null pronouns are available', () => {
|
||||
));
|
||||
});
|
||||
test('builds nothing if name too long', () => {
|
||||
expect(buildPronoun(pronouns, ':Abcdefghijklmnopqrstuvwxyz')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, ':Abcdefghijklmnopqrstuvwxyz', translator)).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('with conditional placeholders', () => {
|
||||
@ -112,10 +124,10 @@ describe('when configured that null pronouns are available', () => {
|
||||
});
|
||||
|
||||
test.each(['S', 'Ringelnatz', 'Max', 'X'])('builds morpheme conditionally if name matches', (name) => {
|
||||
expect(buildPronoun(pronouns, `:${name}`).morphemes.possessive_pronoun).toBe(`${name}’`);
|
||||
expect(buildPronoun(pronouns, `:${name}`, translator).morphemes.possessive_pronoun).toBe(`${name}’`);
|
||||
});
|
||||
test.each(['Sofi', 'Xavier'])('builds morpheme by default if name does not match', (name) => {
|
||||
expect(buildPronoun(pronouns, `:${name}`).morphemes.possessive_pronoun).toBe(`${name}s`);
|
||||
expect(buildPronoun(pronouns, `:${name}`, translator).morphemes.possessive_pronoun).toBe(`${name}s`);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -127,27 +139,31 @@ describe('when configured that slashes contain all morphemes', () => {
|
||||
});
|
||||
|
||||
test('builds generated pronoun from all morphemes', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aer);
|
||||
});
|
||||
test('unescapes morphemes', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 's`/he/hir/hir/hirs/hirself'));
|
||||
const actual = expect(buildPronoun(pronouns, 's`/he/hir/hir/hirs/hirself', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.sSlashHe);
|
||||
});
|
||||
test('builds generated pronoun from all required morphemes and plural modifier', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerselves/:plural'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerselves/:plural', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerPlural);
|
||||
});
|
||||
test('builds generated pronoun from all required morphemes and plural honorific modifier', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerselves/:plural-honorific'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerselves/:plural-honorific', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerPluralHonorific);
|
||||
});
|
||||
test('builds generated pronoun from all required morphemes and description', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself/:description=Neopronoun “ae” `/ “æ”'));
|
||||
const actual = expect(buildPronoun(
|
||||
pronouns,
|
||||
'ae/aer/aer/aers/aerself/:description=Neopronoun “ae” `/ “æ”',
|
||||
translator,
|
||||
));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerWithDescription);
|
||||
});
|
||||
@ -155,35 +171,37 @@ describe('when configured that slashes contain all morphemes', () => {
|
||||
const actual = expect(buildPronoun(
|
||||
pronouns,
|
||||
'ae/aer/:description=Neopronoun “ae” `/ “æ”/:plural/aer/aers/aerselves',
|
||||
translator,
|
||||
));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerPluralWithDescription);
|
||||
});
|
||||
test('builds generated pronoun with some morphemes empty', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/ /aerself'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/ /aerself', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerWithEmptyPossessivePronoun);
|
||||
});
|
||||
test('builds generated pronoun with morpheme at end empty', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aers/', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerWithEmptyReflexive);
|
||||
});
|
||||
test('builds generated pronoun with some morphemes unset', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/~/aerself'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/~/aerself', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerWithUnsetPossessivePronoun);
|
||||
});
|
||||
test('builds nothing if morphemes are missing', () => {
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer/aerself')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer/aerself', translator)).toBeUndefined();
|
||||
});
|
||||
test('builds nothing if too many morphemes are given', () => {
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself/aer')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself/aer', translator)).toBeUndefined();
|
||||
});
|
||||
test('builds nothing if description too long', () => {
|
||||
expect(buildPronoun(
|
||||
pronouns,
|
||||
'ae/aer/aer/aers/aerself/:description=Neopronoun “ae” `/ “æ” which is my favorite so you should use it too',
|
||||
translator,
|
||||
)).toBeNull();
|
||||
});
|
||||
});
|
||||
@ -193,15 +211,15 @@ describe('when configured that slashes contain some morphemes', () => {
|
||||
});
|
||||
|
||||
test('builds generated pronoun from all required morphemes', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aerself'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae/aer/aer/aerself', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aerWithUnsetPossessivePronoun);
|
||||
});
|
||||
test('builds nothing if morphemes are missing', () => {
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer', translator)).toBeUndefined();
|
||||
});
|
||||
test('builds nothing if too many morphemes are given', () => {
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 'ae/aer/aer/aers/aerself', translator)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('when configured that slashes cannot contain morphemes', () => {
|
||||
@ -214,23 +232,23 @@ describe('when configured that slashes cannot contain morphemes', () => {
|
||||
test.each([3, 4, 5, 6])('builds nothing if %d morphemes are given', (count) => {
|
||||
const path = pathBase.split('/').slice(0, count)
|
||||
.join('/');
|
||||
expect(buildPronoun(pronouns, path.slice(0, count))).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, path.slice(0, count), translator)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('building generated pronouns from commas', () => {
|
||||
test('succeeds with all parts present', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae,aer,aer,aers,aerself,0,'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae,aer,aer,aers,aerself,0,', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aer);
|
||||
});
|
||||
test('succeeds with description missing present', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'ae,aer,aer,aers,aerself,0'));
|
||||
const actual = expect(buildPronoun(pronouns, 'ae,aer,aer,aers,aerself,0', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(generatedPronouns.aer);
|
||||
});
|
||||
test('succeeds with base pronoun and some custom morphemes', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'they,!2,aers,!2,'));
|
||||
const actual = expect(buildPronoun(pronouns, 'they,!2,aers,!2,', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(new Pronoun(
|
||||
'they/them',
|
||||
@ -251,19 +269,19 @@ describe('building generated pronouns from commas', () => {
|
||||
));
|
||||
});
|
||||
test('fails when too few parts are given', () => {
|
||||
expect(buildPronoun(pronouns, 'ae,aer,aer,aers,aerself')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 'ae, translator,aer,aer,aers,aerself', translator)).toBeUndefined();
|
||||
});
|
||||
test('fails when many few parts are given', () => {
|
||||
expect(buildPronoun(pronouns, 'ae,aer,aer,aers,aerself,aersing,0,')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 'ae, translator,aer,aer,aers,aerself,aersing,0,', translator)).toBeUndefined();
|
||||
});
|
||||
test('fails when base pronoun is unknown', () => {
|
||||
expect(buildPronoun(pronouns, 's/he,!2,aers,!2,')).toBeUndefined();
|
||||
expect(buildPronoun(pronouns, 's/he, translator,!2,aers,!2,', translator)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('builds interchangable pronouns from ampersand', () => {
|
||||
test('two interchangable pronouns', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'he&she'));
|
||||
const actual = expect(buildPronoun(pronouns, 'he&she', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(new Pronoun(
|
||||
'he&she',
|
||||
@ -284,7 +302,7 @@ describe('builds interchangable pronouns from ampersand', () => {
|
||||
));
|
||||
});
|
||||
test('three interchangable pronouns', () => {
|
||||
const actual = expect(buildPronoun(pronouns, 'he&she&they'));
|
||||
const actual = expect(buildPronoun(pronouns, 'he&she&they', translator));
|
||||
actual.toBeDefined();
|
||||
actual.toEqual(new Pronoun(
|
||||
'he&she&they',
|
||||
|
@ -8,6 +8,11 @@ const translations = {
|
||||
any: {
|
||||
short: 'any',
|
||||
},
|
||||
slashes: {
|
||||
plural: 'plural',
|
||||
pluralHonorific: 'plural-honorific',
|
||||
description: 'description',
|
||||
},
|
||||
},
|
||||
};
|
||||
const translator = new Translator(translations, translations, []);
|
||||
@ -39,7 +44,7 @@ describe('formatting a pronoun with slashes', () => {
|
||||
});
|
||||
|
||||
test('yields no result', () => {
|
||||
expect(generatedPronouns.aer.toStringSlashes()).toBeNull();
|
||||
expect(generatedPronouns.aer.toStringSlashes(translator)).toBeNull();
|
||||
});
|
||||
});
|
||||
describe('when configured that slashes contain all morphemes', () => {
|
||||
@ -48,39 +53,39 @@ describe('formatting a pronoun with slashes', () => {
|
||||
});
|
||||
|
||||
test('chunks contain all morphemes', () => {
|
||||
expect(generatedPronouns.aer.toStringSlashes())
|
||||
expect(generatedPronouns.aer.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/aers/aerself');
|
||||
});
|
||||
test('morphemes with control symbols gets escaped', () => {
|
||||
expect(generatedPronouns.sSlashHe.toStringSlashes())
|
||||
expect(generatedPronouns.sSlashHe.toStringSlashes(translator))
|
||||
.toEqual('s`/he/hir/hir/hirs/hirself');
|
||||
});
|
||||
test('empty morphemes receive space as placeholder', () => {
|
||||
expect(generatedPronouns.aerWithEmptyPossessivePronoun.toStringSlashes())
|
||||
expect(generatedPronouns.aerWithEmptyPossessivePronoun.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/ /aerself');
|
||||
});
|
||||
test('empty morphemes at end receive url-encoded space as placeholder', () => {
|
||||
expect(generatedPronouns.aerWithEmptyReflexive.toStringSlashes())
|
||||
expect(generatedPronouns.aerWithEmptyReflexive.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/aers/%20');
|
||||
});
|
||||
test('unset morphemes receive tilde as placeholder', () => {
|
||||
expect(generatedPronouns.aerWithUnsetPossessivePronoun.toStringSlashes())
|
||||
expect(generatedPronouns.aerWithUnsetPossessivePronoun.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/~/aerself');
|
||||
});
|
||||
test('adds plural modifier if necessary', () => {
|
||||
expect(generatedPronouns.aerPlural.toStringSlashes())
|
||||
expect(generatedPronouns.aerPlural.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/aers/aerselves/:plural');
|
||||
});
|
||||
test('adds plural honorific modifier if necessary', () => {
|
||||
expect(generatedPronouns.aerPluralHonorific.toStringSlashes())
|
||||
expect(generatedPronouns.aerPluralHonorific.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/aers/aerselves/:plural-honorific');
|
||||
});
|
||||
test('adds escaped description if necessary', () => {
|
||||
expect(generatedPronouns.aerWithDescription.toStringSlashes())
|
||||
expect(generatedPronouns.aerWithDescription.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/aers/aerself/:description=Neopronoun “ae” `/ “æ”');
|
||||
});
|
||||
test('adds multiple modifiers if necessary', () => {
|
||||
expect(generatedPronouns.aerPluralWithDescription.toStringSlashes())
|
||||
expect(generatedPronouns.aerPluralWithDescription.toStringSlashes(translator))
|
||||
.toEqual('ae/aer/aer/aers/aerselves/:plural/:description=Neopronoun “ae” `/ “æ”');
|
||||
});
|
||||
});
|
||||
@ -92,7 +97,7 @@ describe('formatting a pronoun with slashes', () => {
|
||||
});
|
||||
|
||||
test('chunks contain configured morphemes', () => {
|
||||
expect(generatedPronouns.aer.toStringSlashes()).toEqual('ae/aer/aer/aerself');
|
||||
expect(generatedPronouns.aer.toStringSlashes(translator)).toEqual('ae/aer/aer/aerself');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user