aboutsummaryrefslogtreecommitdiff
path: root/ext/js/language/translator.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/language/translator.js')
-rw-r--r--ext/js/language/translator.js131
1 files changed, 81 insertions, 50 deletions
diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js
index e9490346..f84328d9 100644
--- a/ext/js/language/translator.js
+++ b/ext/js/language/translator.js
@@ -70,16 +70,16 @@ export class Translator {
* @returns {Promise<{dictionaryEntries: import('dictionary').TermDictionaryEntry[], originalTextLength: number}>} An object containing dictionary entries and the length of the original source text.
*/
async findTerms(mode, text, options) {
- const {enabledDictionaryMap, excludeDictionaryDefinitions, sortFrequencyDictionary, sortFrequencyDictionaryOrder} = options;
+ const {enabledDictionaryMap, excludeDictionaryDefinitions, sortFrequencyDictionary, sortFrequencyDictionaryOrder, language} = options;
const tagAggregator = new TranslatorTagAggregator();
- let {dictionaryEntries, originalTextLength} = await this._findTermsInternal(text, enabledDictionaryMap, options, tagAggregator);
+ let {dictionaryEntries, originalTextLength} = await this._findTermsInternal(text, options, tagAggregator);
switch (mode) {
case 'group':
dictionaryEntries = this._groupDictionaryEntriesByHeadword(dictionaryEntries, tagAggregator);
break;
case 'merge':
- dictionaryEntries = await this._getRelatedDictionaryEntries(dictionaryEntries, options.mainDictionary, enabledDictionaryMap, tagAggregator);
+ dictionaryEntries = await this._getRelatedDictionaryEntries(dictionaryEntries, options, tagAggregator);
break;
}
@@ -115,7 +115,9 @@ export class Translator {
if (pronunciations.length > 1) { this._sortTermDictionaryEntrySimpleData(pronunciations); }
}
- return {dictionaryEntries, originalTextLength};
+ const withUserFacingInflections = this._addUserFacingInflections(language, dictionaryEntries);
+
+ return {dictionaryEntries: withUserFacingInflections, originalTextLength};
}
/**
@@ -206,23 +208,33 @@ export class Translator {
/**
* @param {string} text
- * @param {Map<string, import('translation').FindTermDictionary>} enabledDictionaryMap
* @param {import('translation').FindTermsOptions} options
* @param {TranslatorTagAggregator} tagAggregator
- * @returns {Promise<import('translator').FindTermsResult>}
+ * @returns {Promise<{dictionaryEntries: import('translation-internal').TermDictionaryEntry[], originalTextLength: number}>}
*/
- async _findTermsInternal(text, enabledDictionaryMap, options, tagAggregator) {
- if (options.removeNonJapaneseCharacters) {
+ async _findTermsInternal(text, options, tagAggregator) {
+ const {removeNonJapaneseCharacters, enabledDictionaryMap} = options;
+ if (removeNonJapaneseCharacters) {
text = this._getJapaneseOnlyText(text);
}
if (text.length === 0) {
return {dictionaryEntries: [], originalTextLength: 0};
}
- const deinflections = await this._getDeinflections(text, enabledDictionaryMap, options);
+ const deinflections = await this._getDeinflections(text, options);
+ return this._getDictionaryEntries(deinflections, enabledDictionaryMap, tagAggregator);
+ }
+
+ /**
+ * @param {import('translation-internal').DatabaseDeinflection[]} deinflections
+ * @param {import('translation').TermEnabledDictionaryMap} enabledDictionaryMap
+ * @param {TranslatorTagAggregator} tagAggregator
+ * @returns {{dictionaryEntries: import('translation-internal').TermDictionaryEntry[], originalTextLength: number}}
+ */
+ _getDictionaryEntries(deinflections, enabledDictionaryMap, tagAggregator) {
let originalTextLength = 0;
- /** @type {import('dictionary').TermDictionaryEntry[]} */
+ /** @type {import('translation-internal').TermDictionaryEntry[]} */
const dictionaryEntries = [];
const ids = new Set();
for (const {databaseEntries, originalText, transformedText, deinflectedText, inflectionRuleChainCandidates} of deinflections) {
@@ -247,19 +259,20 @@ export class Translator {
ids.add(id);
}
}
-
return {dictionaryEntries, originalTextLength};
}
/**
- * @param {import('dictionary').TermDictionaryEntry} existingEntry
- * @param {import('dictionary').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
+ * @param {import('translation-internal').TermDictionaryEntry} existingEntry
+ * @param {import('translation-internal').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
*/
_mergeInflectionRuleChains(existingEntry, inflectionRuleChainCandidates) {
const existingChains = existingEntry.inflectionRuleChainCandidates;
for (const {source, inflectionRules} of inflectionRuleChainCandidates) {
- const duplicate = existingChains.find((existingChain) => this._areArraysEqualIgnoreOrder(existingChain.inflectionRules, inflectionRules));
+ const duplicate = existingChains.find((existingChain) => {
+ return this._areArraysEqualIgnoreOrder(existingChain.inflectionRules, inflectionRules);
+ });
if (!duplicate) {
existingEntry.inflectionRuleChainCandidates.push({source, inflectionRules});
} else if (duplicate.source !== source) {
@@ -299,11 +312,10 @@ export class Translator {
/**
* @param {string} text
- * @param {Map<string, import('translation').FindTermDictionary>} enabledDictionaryMap
* @param {import('translation').FindTermsOptions} options
* @returns {Promise<import('translation-internal').DatabaseDeinflection[]>}
*/
- async _getDeinflections(text, enabledDictionaryMap, options) {
+ async _getDeinflections(text, options) {
let deinflections = (
options.deinflect ?
this._getAlgorithmDeinflections(text, options) :
@@ -311,7 +323,7 @@ export class Translator {
);
if (deinflections.length === 0) { return []; }
- const {matchType, language} = options;
+ const {matchType, language, enabledDictionaryMap} = options;
await this._addEntriesToDeinflections(language, deinflections, enabledDictionaryMap, matchType);
@@ -455,7 +467,7 @@ export class Translator {
const {trace, conditions} = deinflection;
const postprocessedTextVariants = this._getTextVariants(deinflection.text, textPostprocessors, [null], sourceCache);
for (const transformedText of postprocessedTextVariants) {
- /** @type {import('dictionary').InflectionRuleChainCandidate} */
+ /** @type {import('translation-internal').InflectionRuleChainCandidate} */
const inflectionRuleChainCandidate = {
source: 'algorithm',
inflectionRules: trace.map((frame) => frame.transform),
@@ -577,7 +589,7 @@ export class Translator {
* @param {string} transformedText
* @param {string} deinflectedText
* @param {number} conditions
- * @param {import('dictionary').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
+ * @param {import('translation-internal').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
* @returns {import('translation-internal').DatabaseDeinflection}
*/
_createDeinflection(originalText, transformedText, deinflectedText, conditions, inflectionRuleChainCandidates) {
@@ -587,20 +599,20 @@ export class Translator {
// Term dictionary entry grouping
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
- * @param {string} mainDictionary
- * @param {import('translation').TermEnabledDictionaryMap} enabledDictionaryMap
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation').FindTermsOptions} options
* @param {TranslatorTagAggregator} tagAggregator
- * @returns {Promise<import('dictionary').TermDictionaryEntry[]>}
+ * @returns {Promise<import('translation-internal').TermDictionaryEntry[]>}
*/
- async _getRelatedDictionaryEntries(dictionaryEntries, mainDictionary, enabledDictionaryMap, tagAggregator) {
+ async _getRelatedDictionaryEntries(dictionaryEntries, options, tagAggregator) {
+ const {mainDictionary, enabledDictionaryMap} = options;
/** @type {import('translator').SequenceQuery[]} */
const sequenceList = [];
- /** @type {import('translator').DictionaryEntryGroup[]} */
+ /** @type {import('translation-internal').DictionaryEntryGroup[]} */
const groupedDictionaryEntries = [];
- /** @type {Map<number, import('translator').DictionaryEntryGroup>} */
+ /** @type {Map<number, import('translation-internal').DictionaryEntryGroup>} */
const groupedDictionaryEntriesMap = new Map();
- /** @type {Map<number, import('dictionary').TermDictionaryEntry>} */
+ /** @type {Map<number, import('translation-internal').TermDictionaryEntry>} */
const ungroupedDictionaryEntriesMap = new Map();
for (const dictionaryEntry of dictionaryEntries) {
const {definitions: [{id, dictionary, sequences: [sequence]}]} = dictionaryEntry;
@@ -642,8 +654,8 @@ export class Translator {
}
/**
- * @param {import('translator').DictionaryEntryGroup[]} groupedDictionaryEntries
- * @param {Map<number, import('dictionary').TermDictionaryEntry>} ungroupedDictionaryEntriesMap
+ * @param {import('translation-internal').DictionaryEntryGroup[]} groupedDictionaryEntries
+ * @param {Map<number, import('translation-internal').TermDictionaryEntry>} ungroupedDictionaryEntriesMap
* @param {import('translator').SequenceQuery[]} sequenceList
* @param {import('translation').TermEnabledDictionaryMap} enabledDictionaryMap
* @param {TranslatorTagAggregator} tagAggregator
@@ -664,8 +676,8 @@ export class Translator {
}
/**
- * @param {import('translator').DictionaryEntryGroup[]} groupedDictionaryEntries
- * @param {Map<number, import('dictionary').TermDictionaryEntry>} ungroupedDictionaryEntriesMap
+ * @param {import('translation-internal').DictionaryEntryGroup[]} groupedDictionaryEntries
+ * @param {Map<number, import('translation-internal').TermDictionaryEntry>} ungroupedDictionaryEntriesMap
* @param {import('translation').TermEnabledDictionaryMap} enabledDictionaryMap
* @param {import('translation').TermEnabledDictionaryMap} secondarySearchDictionaryMap
* @param {TranslatorTagAggregator} tagAggregator
@@ -675,7 +687,7 @@ export class Translator {
/** @type {import('dictionary-database').TermExactRequest[]} */
const termList = [];
const targetList = [];
- /** @type {Map<string, {groups: import('translator').DictionaryEntryGroup[]}>} */
+ /** @type {Map<string, {groups: import('translation-internal').DictionaryEntryGroup[]}>} */
const targetMap = new Map();
for (const group of groupedDictionaryEntries) {
@@ -733,12 +745,12 @@ export class Translator {
}
/**
- * @param {Iterable<import('dictionary').TermDictionaryEntry>} dictionaryEntries
+ * @param {Iterable<import('translation-internal').TermDictionaryEntry>} dictionaryEntries
* @param {TranslatorTagAggregator} tagAggregator
- * @returns {import('dictionary').TermDictionaryEntry[]}
+ * @returns {import('translation-internal').TermDictionaryEntry[]}
*/
_groupDictionaryEntriesByHeadword(dictionaryEntries, tagAggregator) {
- /** @type {Map<string, import('dictionary').TermDictionaryEntry[]>} */
+ /** @type {Map<string, import('translation-internal').TermDictionaryEntry[]>} */
const groups = new Map();
for (const dictionaryEntry of dictionaryEntries) {
const {inflectionRuleChainCandidates, headwords: [{term, reading}]} = dictionaryEntry;
@@ -761,7 +773,7 @@ export class Translator {
// Removing data
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
* @param {Set<string>} excludeDictionaryDefinitions
*/
_removeExcludedDefinitions(dictionaryEntries, excludeDictionaryDefinitions) {
@@ -785,7 +797,7 @@ export class Translator {
}
/**
- * @param {import('dictionary').TermDictionaryEntry} dictionaryEntry
+ * @param {import('translation-internal').TermDictionaryEntry} dictionaryEntry
*/
_removeUnusedHeadwords(dictionaryEntry) {
const {definitions, pronunciations, frequencies, headwords} = dictionaryEntry;
@@ -1071,7 +1083,7 @@ export class Translator {
// Metadata
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
* @param {import('translation').TermEnabledDictionaryMap} enabledDictionaryMap
* @param {TranslatorTagAggregator} tagAggregator
*/
@@ -1543,7 +1555,7 @@ export class Translator {
/**
* @param {boolean} isPrimary
- * @param {import('dictionary').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
+ * @param {import('translation-internal').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
* @param {number} score
* @param {number} dictionaryIndex
* @param {number} dictionaryPriority
@@ -1551,7 +1563,7 @@ export class Translator {
* @param {number} maxOriginalTextLength
* @param {import('dictionary').TermHeadword[]} headwords
* @param {import('dictionary').TermDefinition[]} definitions
- * @returns {import('dictionary').TermDictionaryEntry}
+ * @returns {import('translation-internal').TermDictionaryEntry}
*/
_createTermDictionaryEntry(isPrimary, inflectionRuleChainCandidates, score, dictionaryIndex, dictionaryPriority, sourceTermExactMatchCount, maxOriginalTextLength, headwords, definitions) {
return {
@@ -1576,11 +1588,11 @@ export class Translator {
* @param {string} originalText
* @param {string} transformedText
* @param {string} deinflectedText
- * @param {import('dictionary').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
+ * @param {import('translation-internal').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
* @param {boolean} isPrimary
* @param {Map<string, import('translation').FindTermDictionary>} enabledDictionaryMap
* @param {TranslatorTagAggregator} tagAggregator
- * @returns {import('dictionary').TermDictionaryEntry}
+ * @returns {import('translation-internal').TermDictionaryEntry}
*/
_createTermDictionaryEntryFromDatabaseEntry(databaseEntry, originalText, transformedText, deinflectedText, inflectionRuleChainCandidates, isPrimary, enabledDictionaryMap, tagAggregator) {
const {
@@ -1628,10 +1640,10 @@ export class Translator {
}
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
* @param {boolean} checkDuplicateDefinitions
* @param {TranslatorTagAggregator} tagAggregator
- * @returns {import('dictionary').TermDictionaryEntry}
+ * @returns {import('translation-internal').TermDictionaryEntry}
*/
_createGroupedDictionaryEntry(dictionaryEntries, checkDuplicateDefinitions, tagAggregator) {
// Headwords are generated before sorting, so that the order of dictionaryEntries can be maintained
@@ -1864,13 +1876,13 @@ export class Translator {
}
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
*/
_sortTermDictionaryEntries(dictionaryEntries) {
const stringComparer = this._stringComparer;
/**
- * @param {import('dictionary').TermDictionaryEntry} v1
- * @param {import('dictionary').TermDictionaryEntry} v2
+ * @param {import('translation-internal').TermDictionaryEntry} v1
+ * @param {import('translation-internal').TermDictionaryEntry} v2
* @returns {number}
*/
const compareFunction = (v1, v2) => {
@@ -1968,7 +1980,7 @@ export class Translator {
}
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
*/
_sortTermDictionaryEntriesById(dictionaryEntries) {
if (dictionaryEntries.length <= 1) { return; }
@@ -2033,7 +2045,7 @@ export class Translator {
}
/**
- * @param {import('dictionary').TermDictionaryEntry[]} dictionaryEntries
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
* @param {string} dictionary
* @param {boolean} ascending
*/
@@ -2078,7 +2090,7 @@ export class Translator {
}
/**
- * @param {import('dictionary').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
+ * @param {import('translation-internal').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates
* @returns {number}
*/
_getShortestInflectionChainLength(inflectionRuleChainCandidates) {
@@ -2090,6 +2102,25 @@ export class Translator {
return length;
}
+
+ /**
+ * @param {string} language
+ * @param {import('translation-internal').TermDictionaryEntry[]} dictionaryEntries
+ * @returns {import('dictionary').TermDictionaryEntry[]}
+ */
+ _addUserFacingInflections(language, dictionaryEntries) {
+ const result = [];
+ for (const dictionaryEntry of dictionaryEntries) {
+ const {inflectionRuleChainCandidates} = dictionaryEntry;
+ const expandedChains = inflectionRuleChainCandidates.map(({source, inflectionRules}) => ({
+ source,
+ inflectionRules: this._multiLanguageTransformer.getUserFacingInflectionRules(language, inflectionRules),
+ }));
+ result.push({...dictionaryEntry, inflectionRuleChainCandidates: expandedChains});
+ }
+ return result;
+ }
+
// Miscellaneous
/**