From 414256f4316b4815db302df3183b16dc48c1fb02 Mon Sep 17 00:00:00 2001 From: Kuuuube <61125188+Kuuuube@users.noreply.github.com> Date: Tue, 21 May 2024 13:17:17 -0400 Subject: Fix HTML lang tags not matching the selected language (#979) * Cleanup and add language tag to renderResult * Add language switching support to anki card templates scanned text * Update search page search-textbox lang on language switch * Set queryparser lang * Allow updating language for display-generator * Only use kanji-stroke-orders font for japanese --- ext/css/display.css | 2 +- ext/js/display/display-generator.js | 32 ++++++++++++++-------- ext/js/display/display.js | 1 + ext/js/display/query-parser.js | 2 ++ ext/js/display/search-display-controller.js | 1 + .../settings/anki-deck-generator-controller.js | 5 ++-- ext/js/pages/settings/anki-templates-controller.js | 20 +++++++++++++- ext/js/pages/settings/settings-main.js | 2 +- 8 files changed, 49 insertions(+), 16 deletions(-) diff --git a/ext/css/display.css b/ext/css/display.css index 9b4e0022..d5b4d82d 100644 --- a/ext/css/display.css +++ b/ext/css/display.css @@ -1502,7 +1502,7 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con position: relative; } .kanji-glyph { - font-family: kanji-stroke-orders, sans-serif; + font-family: sans-serif; font-size: 8.5em; line-height: 1; padding: 0.01em; diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index 8a388a38..2b0ceb58 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -38,6 +38,8 @@ export class DisplayGenerator { this._templates = new HtmlTemplateCollection(); /** @type {StructuredContentGenerator} */ this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, document); + /** @type {string} */ + this._language = 'ja'; } /** */ @@ -46,6 +48,13 @@ export class DisplayGenerator { this.updateHotkeys(); } + /** + * @param {string} language + */ + updateLanguage(language) { + this._language = language; + } + /** */ updateHotkeys() { const hotkeyHelpController = this._hotkeyHelpController; @@ -162,7 +171,8 @@ export class DisplayGenerator { const codepointsContainer = this._querySelector(node, '.kanji-codepoints'); const dictionaryIndicesContainer = this._querySelector(node, '.kanji-dictionary-indices'); - this._setTextContent(glyphContainer, dictionaryEntry.character, 'ja'); + this._setTextContent(glyphContainer, dictionaryEntry.character, this._language); + if (this._language === 'ja') { glyphContainer.style.fontFamily = 'kanji-stroke-orders, sans-serif'; } const groupedFrequencies = groupKanjiFrequencies(dictionaryEntry.frequencies); const dictionaryTag = this._createDictionaryTag(dictionaryEntry.dictionary); @@ -508,7 +518,7 @@ export class DisplayGenerator { _createTermDisambiguation(disambiguation) { const node = this._instantiate('definition-disambiguation'); node.dataset.term = disambiguation; - this._setTextContent(node, disambiguation, 'ja'); + this._setTextContent(node, disambiguation, this._language); return node; } @@ -519,7 +529,7 @@ export class DisplayGenerator { _createKanjiLink(character) { const node = document.createElement('a'); node.className = 'headword-kanji-link'; - this._setTextContent(node, character, 'ja'); + this._setTextContent(node, character, this._language); return node; } @@ -540,7 +550,7 @@ export class DisplayGenerator { */ _createKanjiReading(reading) { const node = this._instantiate('kanji-reading'); - this._setTextContent(node, reading, 'ja'); + this._setTextContent(node, reading, this._language); return node; } @@ -743,7 +753,7 @@ export class DisplayGenerator { n = this._querySelector(node, '.pronunciation-text-container'); - n.lang = 'ja'; + n.lang = this._language; n.appendChild(createPronunciationText(morae, position, nasalPositions, devoicePositions)); n = this._querySelector(node, '.pronunciation-graph-container'); @@ -762,14 +772,14 @@ export class DisplayGenerator { for (const term of exclusiveTerms) { const node = this._instantiate(templateName); node.dataset.type = 'term'; - this._setTextContent(node, term, 'ja'); + this._setTextContent(node, term, this._language); container.appendChild(node); } for (const exclusiveReading of exclusiveReadings) { const node = this._instantiate(templateName); node.dataset.type = 'reading'; - this._setTextContent(node, exclusiveReading, 'ja'); + this._setTextContent(node, exclusiveReading, this._language); container.appendChild(node); } @@ -826,8 +836,8 @@ export class DisplayGenerator { const frequencyValueList = this._querySelector(node, '.frequency-value-list'); this._setTextContent(tagLabel, dictionary); - this._setTextContent(disambiguationTerm, term, 'ja'); - this._setTextContent(disambiguationReading, (reading !== null ? reading : ''), 'ja'); + this._setTextContent(disambiguationTerm, term, this._language); + this._setTextContent(disambiguationReading, (reading !== null ? reading : ''), this._language); this._populateFrequencyValueList(frequencyValueList, values); node.dataset.term = term; @@ -892,7 +902,7 @@ export class DisplayGenerator { node2.title = frequencyString; } } - this._setTextContent(node2, text, 'ja'); + this._setTextContent(node2, text, this._language); node.appendChild(node2); fullFrequency += text; @@ -961,7 +971,7 @@ export class DisplayGenerator { * @param {(element: HTMLElement, text: string) => void} addText */ _appendFurigana(container, term, reading, addText) { - container.lang = 'ja'; + container.lang = this._language; const segments = distributeFurigana(term, reading); for (const {text, reading: furigana} of segments) { if (furigana) { diff --git a/ext/js/display/display.js b/ext/js/display/display.js index 6b73f19b..988aa0ae 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -418,6 +418,7 @@ export class Display extends EventDispatcher { this._setTheme(options); this._hotkeyHelpController.setOptions(options); this._displayGenerator.updateHotkeys(); + this._displayGenerator.updateLanguage(options.general.language); this._hotkeyHelpController.setupNode(document.documentElement); this._elementOverflowController.setOptions(options); diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js index f6c26ce7..ed10dab4 100644 --- a/ext/js/display/query-parser.js +++ b/ext/js/display/query-parser.js @@ -122,6 +122,8 @@ export class QueryParser extends EventDispatcher { if (selectedParserChanged && this._parseResults.length > 0) { this._renderParseResult(); } + + this._queryParser.lang = language; } /** diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index 90504beb..815c51c9 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -183,6 +183,7 @@ export class SearchDisplayController { this._clipboardMonitorEnabled = options.clipboard.enableSearchPageMonitor; this._updateClipboardMonitorEnabled(); this._updateWanakanaCheckbox(options); + this._queryInput.lang = options.general.language; await this._updateProfileSelect(); } diff --git a/ext/js/pages/settings/anki-deck-generator-controller.js b/ext/js/pages/settings/anki-deck-generator-controller.js index c8b17742..416e2025 100644 --- a/ext/js/pages/settings/anki-deck-generator-controller.js +++ b/ext/js/pages/settings/anki-deck-generator-controller.js @@ -530,11 +530,12 @@ export class AnkiDeckGeneratorController { /** */ async _updateExampleText() { - this._languageSummaries = await this._application.api.getLanguageSummaries(); + const languageSummaries = await this._application.api.getLanguageSummaries(); const options = await this._settingsController.getOptions(); - const activeLanguage = /** @type {import('language').LanguageSummary} */ (this._languageSummaries.find(({iso}) => iso === options.general.language)); + const activeLanguage = /** @type {import('language').LanguageSummary} */ (languageSummaries.find(({iso}) => iso === options.general.language)); this._renderTextInput.lang = options.general.language; this._renderTextInput.value = activeLanguage.exampleText; + this._renderResult.lang = options.general.language; } /** diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js index dd96f69c..d4f1dc10 100644 --- a/ext/js/pages/settings/anki-templates-controller.js +++ b/ext/js/pages/settings/anki-templates-controller.js @@ -25,11 +25,14 @@ import {TemplateRendererProxy} from '../../templates/template-renderer-proxy.js' export class AnkiTemplatesController { /** + * @param {import('../../application.js').Application} application * @param {import('./settings-controller.js').SettingsController} settingsController * @param {import('./modal-controller.js').ModalController} modalController * @param {import('./anki-controller.js').AnkiController} ankiController */ - constructor(settingsController, modalController, ankiController) { + constructor(application, settingsController, modalController, ankiController) { + /** @type {import('../../application.js').Application} */ + this._application = application; /** @type {import('./settings-controller.js').SettingsController} */ this._settingsController = settingsController; /** @type {import('./modal-controller.js').ModalController} */ @@ -52,6 +55,8 @@ export class AnkiTemplatesController { this._renderTextInput = querySelectorNotNull(document, '#anki-card-templates-test-text-input'); /** @type {HTMLElement} */ this._renderResult = querySelectorNotNull(document, '#anki-card-templates-render-result'); + /** @type {HTMLElement} */ + this._mainSettingsEntry = querySelectorNotNull(document, '[data-modal-action="show,anki-card-templates"]'); /** @type {?import('./modal.js').Modal} */ this._fieldTemplateResetModal = null; /** @type {AnkiNoteBuilder} */ @@ -89,6 +94,9 @@ export class AnkiTemplatesController { const options = await this._settingsController.getOptions(); const optionsContext = this._settingsController.getOptionsContext(); this._onOptionsChanged({options, optionsContext}); + + void this._updateExampleText(); + this._mainSettingsEntry.addEventListener('click', this._updateExampleText.bind(this), false); } // Private @@ -173,6 +181,16 @@ export class AnkiTemplatesController { void this._validate(infoNode, field, 'term-kanji', true, false); } + /** */ + async _updateExampleText() { + const languageSummaries = await this._application.api.getLanguageSummaries(); + const options = await this._settingsController.getOptions(); + const activeLanguage = /** @type {import('language').LanguageSummary} */ (languageSummaries.find(({iso}) => iso === options.general.language)); + this._renderTextInput.lang = options.general.language; + this._renderTextInput.value = activeLanguage.exampleText; + this._renderResult.lang = options.general.language; + } + /** * @param {import('popup-menu').MenuCloseEvent} event */ diff --git a/ext/js/pages/settings/settings-main.js b/ext/js/pages/settings/settings-main.js index 3d3e2352..3ff818ac 100644 --- a/ext/js/pages/settings/settings-main.js +++ b/ext/js/pages/settings/settings-main.js @@ -121,7 +121,7 @@ await Application.main(true, async (application) => { const ankiDeckGeneratorController = new AnkiDeckGeneratorController(application, settingsController, modalController, ankiController); preparePromises.push(ankiDeckGeneratorController.prepare()); - const ankiTemplatesController = new AnkiTemplatesController(settingsController, modalController, ankiController); + const ankiTemplatesController = new AnkiTemplatesController(application, settingsController, modalController, ankiController); preparePromises.push(ankiTemplatesController.prepare()); const popupPreviewController = new PopupPreviewController(settingsController); -- cgit v1.2.3