diff options
-rw-r--r-- | ext/data/schemas/options-schema.json | 11 | ||||
-rw-r--r-- | ext/js/background/backend.js | 4 | ||||
-rw-r--r-- | ext/js/data/options-util.js | 15 | ||||
-rw-r--r-- | ext/js/language/translator.js | 22 | ||||
-rw-r--r-- | ext/settings.html | 12 | ||||
-rw-r--r-- | test/options-util.test.js | 3 | ||||
-rw-r--r-- | types/ext/settings.d.ts | 3 | ||||
-rw-r--r-- | types/ext/translation.d.ts | 5 |
8 files changed, 69 insertions, 6 deletions
diff --git a/ext/data/schemas/options-schema.json b/ext/data/schemas/options-schema.json index f5b24160..65c4102e 100644 --- a/ext/data/schemas/options-schema.json +++ b/ext/data/schemas/options-schema.json @@ -728,9 +728,18 @@ "convertHiraganaToKatakana", "convertKatakanaToHiragana", "collapseEmphaticSequences", - "textReplacements" + "textReplacements", + "searchResolution" ], "properties": { + "searchResolution": { + "type": "string", + "enum": [ + "letter", + "word" + ], + "default": "letter" + }, "convertHalfWidthCharacters": { "type": "string", "enum": ["false", "true", "variant"], diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index ae78a97b..68d4e0c8 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -2417,7 +2417,8 @@ export class Backend { convertHiraganaToKatakana, convertKatakanaToHiragana, collapseEmphaticSequences, - textReplacements: textReplacementsOptions + textReplacements: textReplacementsOptions, + searchResolution } } = options; const textReplacements = this._getTranslatorTextReplacements(textReplacementsOptions); @@ -2444,6 +2445,7 @@ export class Backend { convertHiraganaToKatakana, convertKatakanaToHiragana, collapseEmphaticSequences, + searchResolution, textReplacements, enabledDictionaryMap, excludeDictionaryDefinitions diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index c219bed3..eb9af9b6 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -555,7 +555,8 @@ export class OptionsUtil { {async: false, update: this._updateVersion18.bind(this)}, {async: false, update: this._updateVersion19.bind(this)}, {async: false, update: this._updateVersion20.bind(this)}, - {async: true, update: this._updateVersion21.bind(this)} + {async: true, update: this._updateVersion21.bind(this)}, + {async: false, update: this._updateVersion22.bind(this)} ]; /* eslint-enable no-multi-spaces */ if (typeof targetVersion === 'number' && targetVersion < result.length) { @@ -1174,6 +1175,18 @@ export class OptionsUtil { } /** + * @type {import('options-util').ModernUpdateFunctionAsync} + */ + _updateVersion22(options) { + // Added translation.searchResolution + for (const {options: profileOptions} of options.profiles) { + profileOptions.translation.searchResolution = 'letter'; + } + + return options; + } + + /** * @param {string} url * @returns {Promise<chrome.tabs.Tab>} */ diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js index 733955c2..36ed8b43 100644 --- a/ext/js/language/translator.js +++ b/ext/js/language/translator.js @@ -329,8 +329,12 @@ export class Translator { text2 = jp.collapseEmphaticSequences(text2, collapseEmphaticFull, sourceMap); } - for (let i = text2.length; i > 0; --i) { - const source = text2.substring(0, i); + for ( + let source = text2, i = text2.length; + i > 0; + i = this._getNextSubstringLength(options.searchResolution, i, source) + ) { + source = text2.substring(0, i); if (used.has(source)) { break; } used.add(source); const rawSource = sourceMap.source.substring(0, sourceMap.getSourceLength(i)); @@ -343,6 +347,20 @@ export class Translator { } /** + * @param {string} searchResolution + * @param {number} currentLength + * @param {string} source + * @returns {number} + */ + _getNextSubstringLength(searchResolution, currentLength, source) { + if (searchResolution === 'word') { + return source.search(/[^\p{Letter}][\p{Letter}\p{Number}]*$/u); + } else { + return currentLength - 1; + } + } + + /** * @param {string} text * @param {TextSourceMap} sourceMap * @param {import('translation').FindTermsTextReplacement[]} replacements diff --git a/ext/settings.html b/ext/settings.html index 323be708..1095e3b7 100644 --- a/ext/settings.html +++ b/ext/settings.html @@ -1505,6 +1505,18 @@ </div> </div> <div class="settings-group advanced-only"> + <div class="settings-item advanced-only"><div class="settings-item-inner settings-item-inner-wrappable"> + <div class="settings-item-left"> + <div class="settings-item-label">Dictionary search resolution</div> + <div class="settings-item-description" lang="en"><p>"A dog" → search for "A dog","A do", "A d", "A"</p> or <p>"A dog" → "A dog", "A"</p></div> + </div> + <div class="settings-item-right"> + <select data-setting="translation.searchResolution"> + <option value="letter">Letter</option> + <option value="word">Word</option> + </select> + </div> + </div></div> <div class="settings-item settings-item-button" data-modal-action="show,translation-text-replacement-patterns"><div class="settings-item-inner"> <div class="settings-item-left"> <div class="settings-item-label">Configure custom text replacement patterns…</div> diff --git a/test/options-util.test.js b/test/options-util.test.js index 7bb9767a..daffe886 100644 --- a/test/options-util.test.js +++ b/test/options-util.test.js @@ -413,6 +413,7 @@ function createProfileOptionsUpdatedTestData1() { convertHiraganaToKatakana: 'false', convertKatakanaToHiragana: 'variant', collapseEmphaticSequences: 'false', + searchResolution: 'letter', textReplacements: { searchOriginal: true, groups: [] @@ -601,7 +602,7 @@ function createOptionsUpdatedTestData1() { } ], profileCurrent: 0, - version: 21, + version: 22, global: { database: { prefixWildcardsSupported: false diff --git a/types/ext/settings.d.ts b/types/ext/settings.d.ts index 8ce82b28..25ea46d9 100644 --- a/types/ext/settings.d.ts +++ b/types/ext/settings.d.ts @@ -234,8 +234,11 @@ export type TranslationOptions = { convertKatakanaToHiragana: TranslationConvertType; collapseEmphaticSequences: TranslationCollapseEmphaticSequences; textReplacements: TranslationTextReplacementOptions; + searchResolution: SearchResolution; }; +export type SearchResolution = 'letter' | 'word'; + export type TranslationTextReplacementOptions = { searchOriginal: boolean; groups: TranslationTextReplacementGroup[][]; diff --git a/types/ext/translation.d.ts b/types/ext/translation.d.ts index 595a5a35..c8938e00 100644 --- a/types/ext/translation.d.ts +++ b/types/ext/translation.d.ts @@ -17,6 +17,7 @@ */ import type * as Dictionary from './dictionary'; +import type {SearchResolution} from 'settings'; // Kanji @@ -116,6 +117,10 @@ export type FindTermsOptions = { * A set of dictionary names which should have definitions removed. */ excludeDictionaryDefinitions: Set<string> | null; + /** + * Whether every substring should be searched for, or only whole words. + */ + searchResolution: SearchResolution; }; /** |