From b4250577d8262511b749d616ad76bc7db74dbb9f Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 2 Dec 2020 12:02:21 +0900 Subject: [PATCH] Apply fine-grained language tagging to popup --- _locales/en/messages.json | 4 +++ _locales/ja/messages.json | 4 +++ _locales/zh_hans/messages.json | 4 +++ css/popup.css | 7 ++++- src/content.ts | 1 - src/popup.ts | 49 ++++++++++++++++++++++++++++++++-- tests/browser-polyfill.ts | 2 ++ 7 files changed, 67 insertions(+), 4 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c66bbc9f18..d2360026f4 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1012,6 +1012,10 @@ "message": "Chinese", "description": "Label used to describe senses whose source language is 'zh' (Chinese)" }, + "lang_tag": { + "message": "en", + "description": "The BCP-47 compatible language code used to tag content from this localization" + }, "menu_enable_extension": { "message": "Enable Rikaichamp", "description": "Context menu item to enable the extension." diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index c987b034d0..aa49e520f7 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -1015,6 +1015,10 @@ "message": "中国語", "description": "Label used to describe senses whose source language is 'zh' (Chinese)" }, + "lang_tag": { + "message": "ja", + "description": "The BCP-47 compatible language code used to tag content from this localization" + }, "menu_enable_extension": { "message": "Rikaichampを有効にする", "description": "Context menu item to enable the extension." diff --git a/_locales/zh_hans/messages.json b/_locales/zh_hans/messages.json index 7fd8a0d108..9c34c712e8 100644 --- a/_locales/zh_hans/messages.json +++ b/_locales/zh_hans/messages.json @@ -1012,6 +1012,10 @@ "message": "汉语", "description": "Label used to describe senses whose source language is 'zh' (Chinese)" }, + "lang_tag": { + "message": "zh-Hans", + "description": "The BCP-47 compatible language code used to tag content from this localization" + }, "menu_enable_extension": { "message": "启用 Rikaichamp", "description": "Context menu item to enable the extension." diff --git a/css/popup.css b/css/popup.css index 371335e31e..f145c62b65 100644 --- a/css/popup.css +++ b/css/popup.css @@ -69,7 +69,12 @@ #rikaichamp-window .entry, #rikaichamp-window .entry * { - line-height: 1.2; + line-height: 1.3; +} + +#rikaichamp-window *:lang(en) { + /* Meiryo renders more crisply than Arial on Windows */ + font-family: Meiryo, sans-serif; } #rikaichamp-window .w-kanji { diff --git a/src/content.ts b/src/content.ts index 258f10dd52..df8db4ef2d 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1628,7 +1628,6 @@ export class RikaiContent { // Add the popup div const popup = doc.createElement('div'); popup.setAttribute('id', 'rikaichamp-window'); - popup.setAttribute('lang', 'ja'); popup.classList.add(`-${this._config.popupStyle}`); doc.documentElement.append(popup); diff --git a/src/popup.ts b/src/popup.ts index d72df3c571..ee0d3f2031 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -87,6 +87,7 @@ function renderWordEntries( const titleDiv = document.createElement('div'); container.append(titleDiv); titleDiv.classList.add('title'); + titleDiv.lang = 'ja'; titleDiv.append(title); } @@ -173,6 +174,7 @@ function renderWordEntries( if (entry.romaji?.length) { const romajiSpan = document.createElement('span'); romajiSpan.classList.add('w-romaji'); + romajiSpan.lang = 'ja'; romajiSpan.append(entry.romaji.join(', ')); headingDiv.append(romajiSpan); } @@ -180,6 +182,7 @@ function renderWordEntries( if (entry.reason) { const reasonSpan = document.createElement('span'); headingDiv.append(reasonSpan); + reasonSpan.lang = getLangTag(); reasonSpan.classList.add('w-conj'); reasonSpan.append(`(${entry.reason})`); } @@ -211,6 +214,7 @@ function renderWordEntries( function renderEraInfo(meta: SelectionMeta, eraInfo: EraInfo): HTMLElement { const metaDiv = document.createElement('div'); metaDiv.classList.add('meta'); + metaDiv.lang = 'ja'; const eraSpan = document.createElement('span'); eraSpan.classList.add('era'); @@ -362,6 +366,7 @@ function appendHeadwordInfo( for (const i of info) { const span = document.createElement('span'); span.classList.add('w-head-info'); + span.lang = getLangTag(); span.append('('); // Some KanjiInfo/RadicalInfo values differ only by case but @@ -437,6 +442,8 @@ function renderStar(style: 'full' | 'hollow'): SVGElement { function renderDefinitions(entry: WordResult, options: PopupOptions) { const definitionsSpan = document.createElement('span'); definitionsSpan.classList.add('w-def'); + // Currently all definitions are English + definitionsSpan.lang = 'en'; if (entry.s.length === 1) { definitionsSpan.append(renderSense(entry.s[0], options)); @@ -463,6 +470,7 @@ function renderSense( for (const field of sense.field) { const fieldSpan = document.createElement('span'); fieldSpan.classList.add('w-field', 'tag'); + fieldSpan.lang = getLangTag(); fieldSpan.textContent = browser.i18n.getMessage(`field_label_${field}`) || field; fragment.append(fieldSpan); @@ -473,6 +481,7 @@ function renderSense( for (const misc of sense.misc) { const miscSpan = document.createElement('span'); miscSpan.classList.add('w-misc', 'tag'); + miscSpan.lang = getLangTag(); miscSpan.textContent = browser.i18n.getMessage(`misc_label_${misc}`) || misc; fragment.append(miscSpan); @@ -483,6 +492,7 @@ function renderSense( for (const dial of sense.dial) { const dialSpan = document.createElement('span'); dialSpan.classList.add('w-dial', 'tag'); + dialSpan.lang = getLangTag(); dialSpan.textContent = browser.i18n.getMessage(`dial_label_${dial}`) || dial; fragment.append(dialSpan); @@ -494,6 +504,8 @@ function renderSense( if (sense.inf) { const infSpan = document.createElement('span'); infSpan.classList.add('w-inf'); + // Mark inf as Japanese because it often contains Japanese text + infSpan.lang = 'ja'; infSpan.textContent = ` (${sense.inf})`; fragment.append(infSpan); } @@ -507,6 +519,7 @@ function renderSense( posSpan.classList.add('w-pos', 'tag'); switch (options.posDisplay) { case 'expl': + posSpan.lang = getLangTag(); posSpan.append( sense.pos .map((pos) => browser.i18n.getMessage(`pos_label_${pos}`) || pos) @@ -542,6 +555,7 @@ function appendGlosses(glosses: Array, parent: ParentNode) { if (typeStr) { const typeSpan = document.createElement('span'); typeSpan.classList.add('w-type'); + typeSpan.lang = getLangTag(); typeSpan.textContent = `(${typeStr}) `; parent.append(typeSpan); } @@ -567,6 +581,7 @@ function renderLangSources(sources: Array): DocumentFragment { const wrapperSpan = document.createElement('span'); wrapperSpan.classList.add('w-lsrc'); + wrapperSpan.lang = getLangTag(); wrapperSpan.append('('); if (prefix && lsrc.src) { @@ -603,6 +618,7 @@ function renderNamesEntries( const titleDiv = document.createElement('div'); container.append(titleDiv); titleDiv.classList.add('title'); + titleDiv.lang = getLangTag(); titleDiv.append(browser.i18n.getMessage('content_names_dictionary')); const namesTable = document.createElement('div'); @@ -652,6 +668,7 @@ function renderName(entry: NameResult): HTMLElement { const entryTitleDiv = document.createElement('div'); entryTitleDiv.classList.add('w-title'); + entryTitleDiv.lang = 'ja'; entryDiv.append(entryTitleDiv); if (entry.k) { @@ -690,6 +707,8 @@ function renderName(entry: NameResult): HTMLElement { function renderNameTranslation(tr: NameTranslation): HTMLSpanElement { const definitionSpan = document.createElement('span'); + // ENAMDICT only has English glosses + definitionSpan.lang = 'en'; definitionSpan.append(tr.det.join(', ')); for (const tag of tr.type || []) { @@ -701,6 +720,7 @@ function renderNameTranslation(tr: NameTranslation): HTMLSpanElement { const tagSpan = document.createElement('span'); tagSpan.classList.add('tag'); tagSpan.classList.add(`tag-${tag}`); + tagSpan.lang = getLangTag(); tagSpan.append(tagText); definitionSpan.append(tagSpan); } @@ -745,6 +765,7 @@ function renderKanjiEntry( // -- The kanji itself const kanjiDiv = document.createElement('div'); kanjiDiv.classList.add('kanji'); + kanjiDiv.lang = 'ja'; kanjiDiv.append(entry.c); topPart.append(kanjiDiv); @@ -760,9 +781,10 @@ function renderKanjiEntry( topRightPart.append(renderMeta(entry.misc.meta)); } - // -- -- English + // -- -- Meanings const meaningsDiv = document.createElement('div'); meaningsDiv.classList.add('meanings'); + meaningsDiv.lang = entry.m_lang; meaningsDiv.append(entry.m.join(', ')); topRightPart.append(meaningsDiv); @@ -825,16 +847,18 @@ function renderKanjiComponents(entry: KanjiResult): HTMLElement { row.append(readingCell); readingCell.classList.add('reading'); readingCell.append(rad.na.join('、')); - radicalCell.lang = 'ja'; + readingCell.lang = 'ja'; const meaningCell = document.createElement('td'); row.append(meaningCell); meaningCell.classList.add('meaning'); + meaningCell.lang = rad.m_lang; meaningCell.append(rad.m.join(', ')); if (rad.base) { const baseRow = document.createElement('tr'); baseRow.classList.add('-baseradical'); + baseRow.lang = getLangTag(); componentsTable.append(baseRow); const baseChar = (rad.base.b || rad.base.k)!; @@ -872,16 +896,19 @@ function renderKanjiComponents(entry: KanjiResult): HTMLElement { const radicalCell = document.createElement('td'); row.append(radicalCell); radicalCell.classList.add('char'); + radicalCell.lang = 'ja'; radicalCell.append(component.c); const readingCell = document.createElement('td'); row.append(readingCell); readingCell.classList.add('reading'); + readingCell.lang = 'ja'; readingCell.append(component.na.length ? component.na[0] : '-'); const meaningCell = document.createElement('td'); row.append(meaningCell); meaningCell.classList.add('meaning'); + meaningCell.lang = component.m_lang; meaningCell.append(component.m.length ? component.m[0] : '-'); } @@ -892,6 +919,7 @@ function renderReadings(entry: KanjiResult): HTMLElement { // Readings const readingsDiv = document.createElement('div'); readingsDiv.classList.add('readings'); + readingsDiv.lang = 'ja'; if (entry.r.on && entry.r.on.length) { readingsDiv.append(entry.r.on.join('、')); @@ -928,6 +956,7 @@ function renderReadings(entry: KanjiResult): HTMLElement { if (entry.r.na && entry.r.na.length) { const nanoriLabelSpan = document.createElement('span'); nanoriLabelSpan.classList.add('nanorilabel'); + nanoriLabelSpan.lang = getLangTag(); nanoriLabelSpan.append( browser.i18n.getMessage('content_kanji_nanori_label') ); @@ -948,6 +977,7 @@ function renderMeta(meta: Array): HTMLElement { for (const tag of meta) { const span = document.createElement('span'); span.classList.add('tag'); + span.lang = 'en'; span.textContent = tag; metaDiv.append(span); } @@ -959,6 +989,7 @@ function renderMiscRow(entry: KanjiResult): HTMLElement { // Misc information row const miscInfoDiv = document.createElement('div'); miscInfoDiv.classList.add('misc'); + miscInfoDiv.lang = getLangTag(); // Strokes const strokesDiv = document.createElement('div'); @@ -1110,6 +1141,7 @@ function renderReferences( ): HTMLElement { const referenceTable = document.createElement('div'); referenceTable.classList.add('references'); + referenceTable.lang = getLangTag(); const referenceNames = getSelectedReferenceLabels(options.kanjiReferences); let numReferences = 0; @@ -1136,6 +1168,9 @@ function renderReferences( const value = getReferenceValue(entry, ref.ref) || '-'; const valueSpan = document.createElement('span'); valueSpan.classList.add('value'); + if (ref.ref === 'radical' || ref.ref === 'nelson_r') { + valueSpan.lang = 'ja'; + } valueSpan.append(value); referenceCell.append(valueSpan); numReferences++; @@ -1185,6 +1220,7 @@ function renderCopyDetails( const copyDiv = document.createElement('div'); copyDiv.classList.add('copy'); + copyDiv.lang = browser.i18n.getMessage('lang_tag'); const keysDiv = document.createElement('div'); keysDiv.classList.add('keys'); @@ -1248,4 +1284,13 @@ function renderCopyStatus(message: string): HTMLElement { return status; } +// Cache language tag since we fetch it a lot +let langTag: string | null = null; +function getLangTag() { + if (langTag === null) { + langTag = browser.i18n.getMessage('lang_tag'); + } + return langTag; +} + export default renderPopup; diff --git a/tests/browser-polyfill.ts b/tests/browser-polyfill.ts index 41c4286488..1f6c1d626d 100644 --- a/tests/browser-polyfill.ts +++ b/tests/browser-polyfill.ts @@ -106,6 +106,8 @@ export const browser = { return 'Radical (Nelson)'; case 'ref_label_unicode': return 'Unicode'; + case 'lang_tag': + return 'en'; case 'misc_label_abbr': return 'abbr.'; case 'misc_label_arch':