euparliamentmonitor 0.9.27 → 0.9.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/aggregator/html/shell.js +6 -4
- package/scripts/aggregator/html/toc.js +4 -2
- package/scripts/aggregator/progressive-disclosure.d.ts +2 -1
- package/scripts/aggregator/progressive-disclosure.js +8 -4
- package/scripts/constants/languages.d.ts +2 -1
- package/scripts/constants/languages.js +1 -1
- package/scripts/constants/ui/index.d.ts +2 -0
- package/scripts/constants/ui/index.js +2 -0
- package/scripts/constants/ui/progressive-disclosure.d.ts +40 -0
- package/scripts/constants/ui/progressive-disclosure.js +150 -0
- package/scripts/discover-untranslated-briefs.js +296 -1
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { BASE_URL, BUILD_SHORT, MERMAID_VERSION } from '../../constants/config.js';
|
|
14
14
|
import { buildHeadFreshnessTags } from '../../constants/build-info-meta.js';
|
|
15
|
-
import { ALL_LANGUAGES, PAGE_TITLES, SKIP_LINK_TEXTS, ARTICLE_NAV_LABELS, BACK_TO_NEWS_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, FOOTER_SITEMAP_LABELS, FOOTER_POLITICAL_INTELLIGENCE_LABELS, getLocalizedString, getTextDirection, } from '../../constants/languages.js';
|
|
15
|
+
import { ALL_LANGUAGES, PAGE_TITLES, SKIP_LINK_TEXTS, ARTICLE_NAV_LABELS, BACK_TO_NEWS_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, FOOTER_SITEMAP_LABELS, FOOTER_POLITICAL_INTELLIGENCE_LABELS, PROGRESSIVE_DISCLOSURE_LABELS, getLocalizedString, getTextDirection, } from '../../constants/languages.js';
|
|
16
16
|
import { buildOgLocaleTags } from '../../constants/og-locales.js';
|
|
17
17
|
import { ORG_SAME_AS, buildTwitterAttributionTags } from '../../constants/social-handles.js';
|
|
18
18
|
import { escapeHTML } from '../../utils/file-utils.js';
|
|
@@ -186,7 +186,7 @@ export function wrapArticleHtml(options) {
|
|
|
186
186
|
const tocHtml = buildArticleToc(options.toc ?? [], safeLang);
|
|
187
187
|
const articleMainClass = tocHtml.length > 0 ? 'article-main--with-toc' : 'article-main--no-toc';
|
|
188
188
|
const articleSectionLabel = getLocalizedArticleTypePlain(options.articleType, safeLang);
|
|
189
|
-
const disclosureBody = buildProgressiveDisclosureBody(options.body);
|
|
189
|
+
const disclosureBody = buildProgressiveDisclosureBody(options.body, safeLang);
|
|
190
190
|
const transformedBodyHtml = options.readerFriendly === false
|
|
191
191
|
? disclosureBody.bodyHtml
|
|
192
192
|
: applyReaderFriendlyTransform(disclosureBody.bodyHtml);
|
|
@@ -199,7 +199,9 @@ export function wrapArticleHtml(options) {
|
|
|
199
199
|
disclosureBody.wordCounts.analysis +
|
|
200
200
|
disclosureBody.wordCounts.intelligence;
|
|
201
201
|
const readingTimes = options.readingTimes ?? buildLayerReadingTimes(disclosureBody.wordCounts);
|
|
202
|
-
const
|
|
202
|
+
const disclosureLabels = getLocalizedString(PROGRESSIVE_DISCLOSURE_LABELS, safeLang);
|
|
203
|
+
const min = disclosureLabels.minutesAbbr;
|
|
204
|
+
const readingTimeLine = `⏱️ ${disclosureLabels.quickRead}: ${readingTimes.quickRead}${min} · ${disclosureLabels.fullAnalysis}: ${readingTimes.fullAnalysis}${min} · ${disclosureLabels.completeIntelligence}: ${readingTimes.completeIntelligence}${min}`;
|
|
203
205
|
// Pre-compute the per-surface SEO-budget-clamped variants of title
|
|
204
206
|
// and description. Each surface gets its own clamp tuned to the
|
|
205
207
|
// documented platform envelope (Google/Bing SERP, Facebook/LinkedIn
|
|
@@ -392,7 +394,7 @@ ${tocHtml} <article class="article-body" lang="${safeLang}">
|
|
|
392
394
|
<p class="article-kicker">${escapeHTML(getLocalizedArticleType(options.articleType, safeLang))}</p>
|
|
393
395
|
<h1>${escapeHTML(options.title)}</h1>
|
|
394
396
|
<p class="article-dek">${escapeHTML(options.description)}</p>
|
|
395
|
-
<p class="article-reading-times" aria-label="
|
|
397
|
+
<p class="article-reading-times" aria-label="${escapeHTML(disclosureLabels.readingTimeAria)}">${escapeHTML(readingTimeLine)}</p>
|
|
396
398
|
<p class="article-meta"><time datetime="${options.date}">${options.date}</time> · EU Parliament Monitor</p>
|
|
397
399
|
</header>
|
|
398
400
|
${sourceMdLink}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* that mirrors the Reader Intelligence Guide so the two navigation
|
|
9
9
|
* surfaces share a single visual vocabulary.
|
|
10
10
|
*/
|
|
11
|
-
import { TOC_ARIA_LABELS, TRADECRAFT_HEADING_LABELS, ANALYSIS_INDEX_HEADING_LABELS, KEY_TAKEAWAYS_HEADING_LABELS, SUPPLEMENTARY_HEADING_LABELS, SECTION_TITLE_LABELS, getLocalizedString, } from '../../constants/languages.js';
|
|
11
|
+
import { TOC_ARIA_LABELS, TRADECRAFT_HEADING_LABELS, ANALYSIS_INDEX_HEADING_LABELS, KEY_TAKEAWAYS_HEADING_LABELS, SUPPLEMENTARY_HEADING_LABELS, SECTION_TITLE_LABELS, PROGRESSIVE_DISCLOSURE_LABELS, getLocalizedString, } from '../../constants/languages.js';
|
|
12
12
|
import { escapeHTML } from '../../utils/file-utils.js';
|
|
13
13
|
import { READER_GUIDE_SECTION_ID } from '../reader-guide-constants.js';
|
|
14
14
|
import { READER_GUIDE_TITLE_LABELS, getReaderGuideSectionIcon, } from '../reader-intelligence-guide.js';
|
|
@@ -91,13 +91,15 @@ export function buildArticleToc(entries, lang) {
|
|
|
91
91
|
if (entries.length === 0)
|
|
92
92
|
return '';
|
|
93
93
|
const label = escapeHTML(getLocalizedString(TOC_ARIA_LABELS, lang));
|
|
94
|
+
const layerBadgeWord = getLocalizedString(PROGRESSIVE_DISCLOSURE_LABELS, lang).layerBadge;
|
|
94
95
|
const items = entries
|
|
95
96
|
.map((e) => {
|
|
96
97
|
const displayTitle = getLocalizedTocTitle(e.id, e.title, lang);
|
|
97
98
|
const icon = getTocSectionIcon(e.id);
|
|
98
99
|
const layer = resolveDisclosureLayer(e.id);
|
|
99
100
|
const layerBadge = layer === 'quick' ? 'L1' : layer === 'analysis' ? 'L2' : 'L3';
|
|
100
|
-
|
|
101
|
+
const layerAria = escapeHTML(`${layerBadgeWord} ${layerBadge}`);
|
|
102
|
+
return ` <li data-layer="${layer}"><a href="#${escapeHTML(e.id)}"><span class="article-toc-icon" aria-hidden="true">${icon}</span> <span class="article-toc-text">${escapeHTML(displayTitle)}</span><span class="article-toc-layer article-toc-layer--${layer}" aria-label="${layerAria}">${layerBadge}</span></a></li>`;
|
|
101
103
|
})
|
|
102
104
|
.join('\n');
|
|
103
105
|
return [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LanguageCode } from '../types/index.js';
|
|
1
2
|
export type DisclosureLayer = 'quick' | 'analysis' | 'intelligence';
|
|
2
3
|
export interface LayerWordCounts {
|
|
3
4
|
readonly quick: number;
|
|
@@ -20,7 +21,7 @@ export declare function splitBodyIntoDisclosureLayers(bodyHtml: string): {
|
|
|
20
21
|
};
|
|
21
22
|
export declare function estimateReadingMinutes(wordCount: number): number;
|
|
22
23
|
export declare function buildLayerReadingTimes(words: LayerWordCounts): LayerReadingTimes;
|
|
23
|
-
export declare function buildProgressiveDisclosureBody(bodyHtml: string): {
|
|
24
|
+
export declare function buildProgressiveDisclosureBody(bodyHtml: string, lang?: LanguageCode): {
|
|
24
25
|
readonly bodyHtml: string;
|
|
25
26
|
readonly wordCounts: LayerWordCounts;
|
|
26
27
|
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { stripHtmlTags } from '../utils/html-sanitize.js';
|
|
4
|
+
import { escapeHTML } from '../utils/file-utils.js';
|
|
5
|
+
import { PROGRESSIVE_DISCLOSURE_LABELS } from '../constants/languages.js';
|
|
6
|
+
import { getLocalizedString } from '../constants/language-core.js';
|
|
4
7
|
export const QUICK_LAYER_SECTION_IDS = new Set([
|
|
5
8
|
'executive-brief',
|
|
6
9
|
'key-takeaways',
|
|
@@ -87,18 +90,19 @@ export function buildLayerReadingTimes(words) {
|
|
|
87
90
|
completeIntelligence: estimateReadingMinutes(complete),
|
|
88
91
|
};
|
|
89
92
|
}
|
|
90
|
-
export function buildProgressiveDisclosureBody(bodyHtml) {
|
|
93
|
+
export function buildProgressiveDisclosureBody(bodyHtml, lang = 'en') {
|
|
94
|
+
const labels = getLocalizedString(PROGRESSIVE_DISCLOSURE_LABELS, lang);
|
|
91
95
|
const layers = splitBodyIntoDisclosureLayers(bodyHtml);
|
|
92
96
|
const output = [
|
|
93
|
-
`<section class="article-layer article-layer--quick" data-disclosure-layer="quick" aria-label="
|
|
97
|
+
`<section class="article-layer article-layer--quick" data-disclosure-layer="quick" aria-label="${escapeHTML(labels.quickRead)}">`,
|
|
94
98
|
layers.quickHtml,
|
|
95
99
|
`</section>`,
|
|
96
100
|
];
|
|
97
101
|
if (layers.analysisHtml.trim().length > 0) {
|
|
98
|
-
output.push(`<details class="article-layer article-layer--analysis article-layer-details" data-disclosure-layer="analysis" id="article-layer-analysis">`, `<summary class="article-layer-summary"><span class="article-layer-summary__title"
|
|
102
|
+
output.push(`<details class="article-layer article-layer--analysis article-layer-details" data-disclosure-layer="analysis" id="article-layer-analysis">`, `<summary class="article-layer-summary"><span class="article-layer-summary__title">${escapeHTML(labels.expandAnalysis)} ↓</span></summary>`, `<section class="article-layer-content" aria-label="${escapeHTML(labels.fullAnalysis)}">`, layers.analysisHtml, `</section>`, `</details>`);
|
|
99
103
|
}
|
|
100
104
|
if (layers.intelligenceHtml.trim().length > 0) {
|
|
101
|
-
output.push(`<details class="article-layer article-layer--intelligence article-layer-details" data-disclosure-layer="intelligence" id="article-layer-intelligence">`, `<summary class="article-layer-summary"><span class="article-layer-summary__title"
|
|
105
|
+
output.push(`<details class="article-layer article-layer--intelligence article-layer-details" data-disclosure-layer="intelligence" id="article-layer-intelligence">`, `<summary class="article-layer-summary"><span class="article-layer-summary__title">${escapeHTML(labels.expandIntelligence)} ↓</span></summary>`, `<section class="article-layer-content" aria-label="${escapeHTML(labels.completeIntelligence)}">`, layers.intelligenceHtml, `</section>`, `</details>`);
|
|
102
106
|
}
|
|
103
107
|
return { bodyHtml: output.join('\n'), wordCounts: layers.wordCounts };
|
|
104
108
|
}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* - **language-articles** — Article-type title generators and body-text strings
|
|
9
9
|
*/
|
|
10
10
|
export { ALL_LANGUAGES, LANGUAGE_PRESETS, LANGUAGE_FLAGS, LANGUAGE_NAMES, getLocalizedString, isSupportedLanguage, getTextDirection, } from './language-core.js';
|
|
11
|
-
export { PAGE_TITLES, PAGE_DESCRIPTIONS, SECTION_HEADINGS, NO_ARTICLES_MESSAGES, SKIP_LINK_TEXTS, ARTICLE_TYPE_LABELS, READ_TIME_LABELS, BACK_TO_NEWS_LABELS, ARTICLE_NAV_LABELS, RELATED_ARTICLES_NAV_LABELS, BREADCRUMB_HOME_LABELS, BREADCRUMB_NEWS_LABELS, TIMELINE_HEADINGS, COMPARISON_BEFORE_LABELS, COMPARISON_AFTER_LABELS, KEY_FIGURES_HEADINGS, AI_SECTION_CONTENT, FILTER_LABELS, SOURCES_HEADING_LABELS, HEADER_SUBTITLE_LABELS, THEME_TOGGLE_LABELS, FOOTER_ABOUT_HEADING_LABELS, FOOTER_ABOUT_TEXT_LABELS, FOOTER_QUICK_LINKS_LABELS, FOOTER_BUILT_BY_LABELS, FOOTER_LANGUAGES_LABELS, FOOTER_HOME_LABELS, FOOTER_SITEMAP_LABELS, FOOTER_RSS_LABELS, FOOTER_GITHUB_REPO_LABELS, FOOTER_LICENSE_LABELS, FOOTER_EUROPARL_LABELS, FOOTER_LINKEDIN_LABELS, FOOTER_SECURITY_POLICY_LABELS, FOOTER_CONTACT_LABELS, FOOTER_DISCLAIMER_LABELS, FOOTER_REPORT_ISSUES_LABELS, FOOTER_ARTICLES_AVAILABLE_LABELS, FOOTER_POLITICAL_INTELLIGENCE_LABELS, TOC_ARIA_LABELS, TRADECRAFT_HEADING_LABELS, TRADECRAFT_INTRO_LABELS, TRADECRAFT_METHODOLOGIES_LABELS, TRADECRAFT_TEMPLATES_LABELS, ANALYSIS_INDEX_HEADING_LABELS, ANALYSIS_INDEX_INTRO_LABELS, ANALYSIS_INDEX_COL_SECTION_LABELS, ANALYSIS_INDEX_COL_ARTIFACT_LABELS, ANALYSIS_INDEX_COL_PATH_LABELS, KEY_TAKEAWAYS_HEADING_LABELS, SUPPLEMENTARY_HEADING_LABELS, SECTION_TITLE_LABELS, RELATED_ANALYSIS_LABELS, ANALYSIS_TRANSPARENCY_LABELS, ANALYSIS_SUMMARY_LABELS, METHODOLOGY_LABELS, TRANSPARENCY_DISCLOSURE_LABELS, CLASSIFICATION_ANALYSIS_LABELS, THREAT_ASSESSMENT_LABELS, RISK_SCORING_LABELS, DEEP_ANALYSIS_LABELS, VIEW_SOURCE_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, ARTICLE_TYPE_ICONS, OPEN_SOURCE_NOTE_LABELS, AI_ANALYSIS_GUIDE_LABELS, SWOT_FRAMEWORK_LABELS, RISK_METHODOLOGY_LABELS, THREAT_FRAMEWORK_LABELS, CLASSIFICATION_GUIDE_LABELS, STYLE_GUIDE_LABELS, SIGNIFICANCE_CLASSIFICATION_LABELS, ACTOR_MAPPING_LABELS, FORCES_ANALYSIS_LABELS, IMPACT_MATRIX_LABELS, POLITICAL_THREAT_LANDSCAPE_LABELS, ACTOR_THREAT_PROFILING_LABELS, CONSEQUENCE_TREES_LABELS, LEGISLATIVE_DISRUPTION_LABELS, RISK_MATRIX_LABELS, QUANTITATIVE_SWOT_LABELS, POLITICAL_CAPITAL_RISK_LABELS, LEGISLATIVE_VELOCITY_RISK_LABELS, AGENT_RISK_WORKFLOW_LABELS, STAKEHOLDER_IMPACT_LABELS, COALITION_DYNAMICS_LABELS, VOTING_PATTERNS_LABELS, CROSS_SESSION_INTELLIGENCE_LABELS, SYNTHESIS_SUMMARY_LABELS, DOCUMENT_ANALYSIS_LABELS, SIGNIFICANCE_SCORING_LABELS, INSTALL_APP_LABELS, UPDATE_AVAILABLE_LABELS, UPDATE_REFRESH_CTA_LABELS, UPDATE_DISMISS_LABELS, OFFLINE_TITLE_LABELS, OFFLINE_BODY_LABELS, OFFLINE_RETRY_LABELS, BUILD_INFO_COMMIT_LABELS, BUILD_INFO_DEPLOYED_LABELS, HEADER_CTA_SPONSOR_LABELS, HEADER_CTA_BECOME_SPONSOR_LABELS, HEADER_CTA_SECURITY_LABELS, FOOTER_NEWS_LABELS, FOOTER_DASHBOARD_LABELS, FOOTER_ANALYSIS_REPORTS_LABELS, FOOTER_API_DOCS_LABELS, FOOTER_COMPANY_TAGLINE_LABELS, LANGUAGE_SELECTION_ARIA_LABELS, FOOTER_TRUST_BADGES_ARIA_LABELS, } from './language-ui.js';
|
|
11
|
+
export { PAGE_TITLES, PAGE_DESCRIPTIONS, SECTION_HEADINGS, NO_ARTICLES_MESSAGES, SKIP_LINK_TEXTS, ARTICLE_TYPE_LABELS, READ_TIME_LABELS, PROGRESSIVE_DISCLOSURE_LABELS, BACK_TO_NEWS_LABELS, ARTICLE_NAV_LABELS, RELATED_ARTICLES_NAV_LABELS, BREADCRUMB_HOME_LABELS, BREADCRUMB_NEWS_LABELS, TIMELINE_HEADINGS, COMPARISON_BEFORE_LABELS, COMPARISON_AFTER_LABELS, KEY_FIGURES_HEADINGS, AI_SECTION_CONTENT, FILTER_LABELS, SOURCES_HEADING_LABELS, HEADER_SUBTITLE_LABELS, THEME_TOGGLE_LABELS, FOOTER_ABOUT_HEADING_LABELS, FOOTER_ABOUT_TEXT_LABELS, FOOTER_QUICK_LINKS_LABELS, FOOTER_BUILT_BY_LABELS, FOOTER_LANGUAGES_LABELS, FOOTER_HOME_LABELS, FOOTER_SITEMAP_LABELS, FOOTER_RSS_LABELS, FOOTER_GITHUB_REPO_LABELS, FOOTER_LICENSE_LABELS, FOOTER_EUROPARL_LABELS, FOOTER_LINKEDIN_LABELS, FOOTER_SECURITY_POLICY_LABELS, FOOTER_CONTACT_LABELS, FOOTER_DISCLAIMER_LABELS, FOOTER_REPORT_ISSUES_LABELS, FOOTER_ARTICLES_AVAILABLE_LABELS, FOOTER_POLITICAL_INTELLIGENCE_LABELS, TOC_ARIA_LABELS, TRADECRAFT_HEADING_LABELS, TRADECRAFT_INTRO_LABELS, TRADECRAFT_METHODOLOGIES_LABELS, TRADECRAFT_TEMPLATES_LABELS, ANALYSIS_INDEX_HEADING_LABELS, ANALYSIS_INDEX_INTRO_LABELS, ANALYSIS_INDEX_COL_SECTION_LABELS, ANALYSIS_INDEX_COL_ARTIFACT_LABELS, ANALYSIS_INDEX_COL_PATH_LABELS, KEY_TAKEAWAYS_HEADING_LABELS, SUPPLEMENTARY_HEADING_LABELS, SECTION_TITLE_LABELS, RELATED_ANALYSIS_LABELS, ANALYSIS_TRANSPARENCY_LABELS, ANALYSIS_SUMMARY_LABELS, METHODOLOGY_LABELS, TRANSPARENCY_DISCLOSURE_LABELS, CLASSIFICATION_ANALYSIS_LABELS, THREAT_ASSESSMENT_LABELS, RISK_SCORING_LABELS, DEEP_ANALYSIS_LABELS, VIEW_SOURCE_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, ARTICLE_TYPE_ICONS, OPEN_SOURCE_NOTE_LABELS, AI_ANALYSIS_GUIDE_LABELS, SWOT_FRAMEWORK_LABELS, RISK_METHODOLOGY_LABELS, THREAT_FRAMEWORK_LABELS, CLASSIFICATION_GUIDE_LABELS, STYLE_GUIDE_LABELS, SIGNIFICANCE_CLASSIFICATION_LABELS, ACTOR_MAPPING_LABELS, FORCES_ANALYSIS_LABELS, IMPACT_MATRIX_LABELS, POLITICAL_THREAT_LANDSCAPE_LABELS, ACTOR_THREAT_PROFILING_LABELS, CONSEQUENCE_TREES_LABELS, LEGISLATIVE_DISRUPTION_LABELS, RISK_MATRIX_LABELS, QUANTITATIVE_SWOT_LABELS, POLITICAL_CAPITAL_RISK_LABELS, LEGISLATIVE_VELOCITY_RISK_LABELS, AGENT_RISK_WORKFLOW_LABELS, STAKEHOLDER_IMPACT_LABELS, COALITION_DYNAMICS_LABELS, VOTING_PATTERNS_LABELS, CROSS_SESSION_INTELLIGENCE_LABELS, SYNTHESIS_SUMMARY_LABELS, DOCUMENT_ANALYSIS_LABELS, SIGNIFICANCE_SCORING_LABELS, INSTALL_APP_LABELS, UPDATE_AVAILABLE_LABELS, UPDATE_REFRESH_CTA_LABELS, UPDATE_DISMISS_LABELS, OFFLINE_TITLE_LABELS, OFFLINE_BODY_LABELS, OFFLINE_RETRY_LABELS, BUILD_INFO_COMMIT_LABELS, BUILD_INFO_DEPLOYED_LABELS, HEADER_CTA_SPONSOR_LABELS, HEADER_CTA_BECOME_SPONSOR_LABELS, HEADER_CTA_SECURITY_LABELS, FOOTER_NEWS_LABELS, FOOTER_DASHBOARD_LABELS, FOOTER_ANALYSIS_REPORTS_LABELS, FOOTER_API_DOCS_LABELS, FOOTER_COMPANY_TAGLINE_LABELS, LANGUAGE_SELECTION_ARIA_LABELS, FOOTER_TRUST_BADGES_ARIA_LABELS, } from './language-ui.js';
|
|
12
12
|
export type { AISection, RelationshipLabels, RelatedAnalysisStrings } from './language-ui.js';
|
|
13
|
+
export type { ProgressiveDisclosureStrings } from './language-ui.js';
|
|
13
14
|
export { WEEK_AHEAD_TITLES, MONTH_AHEAD_TITLES, WEEKLY_REVIEW_TITLES, MONTHLY_REVIEW_TITLES, MOTIONS_TITLES, BREAKING_NEWS_TITLES, COMMITTEE_REPORTS_TITLES, PROPOSITIONS_TITLES, PROPOSITIONS_STRINGS, EDITORIAL_STRINGS, MOTIONS_STRINGS, WEEK_AHEAD_STRINGS, WEEK_AHEAD_STAKEHOLDER_STRINGS, BREAKING_STRINGS, DEEP_ANALYSIS_STRINGS, COMMITTEE_ANALYSIS_CONTENT_STRINGS, SWOT_STRINGS, DASHBOARD_STRINGS, SWOT_BUILDER_STRINGS, DASHBOARD_BUILDER_STRINGS, LOCALIZED_KEYWORDS, MONTH_IN_REVIEW_STRINGS, ANALYSIS_QUALITY_LABELS, ANALYSIS_INSIGHTS_HEADING, } from './language-articles.js';
|
|
14
15
|
//# sourceMappingURL=languages.d.ts.map
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
* - **language-articles** — Article-type title generators and body-text strings
|
|
11
11
|
*/
|
|
12
12
|
export { ALL_LANGUAGES, LANGUAGE_PRESETS, LANGUAGE_FLAGS, LANGUAGE_NAMES, getLocalizedString, isSupportedLanguage, getTextDirection, } from './language-core.js';
|
|
13
|
-
export { PAGE_TITLES, PAGE_DESCRIPTIONS, SECTION_HEADINGS, NO_ARTICLES_MESSAGES, SKIP_LINK_TEXTS, ARTICLE_TYPE_LABELS, READ_TIME_LABELS, BACK_TO_NEWS_LABELS, ARTICLE_NAV_LABELS, RELATED_ARTICLES_NAV_LABELS, BREADCRUMB_HOME_LABELS, BREADCRUMB_NEWS_LABELS, TIMELINE_HEADINGS, COMPARISON_BEFORE_LABELS, COMPARISON_AFTER_LABELS, KEY_FIGURES_HEADINGS, AI_SECTION_CONTENT, FILTER_LABELS, SOURCES_HEADING_LABELS, HEADER_SUBTITLE_LABELS, THEME_TOGGLE_LABELS, FOOTER_ABOUT_HEADING_LABELS, FOOTER_ABOUT_TEXT_LABELS, FOOTER_QUICK_LINKS_LABELS, FOOTER_BUILT_BY_LABELS, FOOTER_LANGUAGES_LABELS, FOOTER_HOME_LABELS, FOOTER_SITEMAP_LABELS, FOOTER_RSS_LABELS, FOOTER_GITHUB_REPO_LABELS, FOOTER_LICENSE_LABELS, FOOTER_EUROPARL_LABELS, FOOTER_LINKEDIN_LABELS, FOOTER_SECURITY_POLICY_LABELS, FOOTER_CONTACT_LABELS, FOOTER_DISCLAIMER_LABELS, FOOTER_REPORT_ISSUES_LABELS, FOOTER_ARTICLES_AVAILABLE_LABELS, FOOTER_POLITICAL_INTELLIGENCE_LABELS, TOC_ARIA_LABELS, TRADECRAFT_HEADING_LABELS, TRADECRAFT_INTRO_LABELS, TRADECRAFT_METHODOLOGIES_LABELS, TRADECRAFT_TEMPLATES_LABELS, ANALYSIS_INDEX_HEADING_LABELS, ANALYSIS_INDEX_INTRO_LABELS, ANALYSIS_INDEX_COL_SECTION_LABELS, ANALYSIS_INDEX_COL_ARTIFACT_LABELS, ANALYSIS_INDEX_COL_PATH_LABELS, KEY_TAKEAWAYS_HEADING_LABELS, SUPPLEMENTARY_HEADING_LABELS, SECTION_TITLE_LABELS, RELATED_ANALYSIS_LABELS, ANALYSIS_TRANSPARENCY_LABELS, ANALYSIS_SUMMARY_LABELS, METHODOLOGY_LABELS, TRANSPARENCY_DISCLOSURE_LABELS, CLASSIFICATION_ANALYSIS_LABELS, THREAT_ASSESSMENT_LABELS, RISK_SCORING_LABELS, DEEP_ANALYSIS_LABELS, VIEW_SOURCE_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, ARTICLE_TYPE_ICONS, OPEN_SOURCE_NOTE_LABELS, AI_ANALYSIS_GUIDE_LABELS, SWOT_FRAMEWORK_LABELS, RISK_METHODOLOGY_LABELS, THREAT_FRAMEWORK_LABELS, CLASSIFICATION_GUIDE_LABELS, STYLE_GUIDE_LABELS, SIGNIFICANCE_CLASSIFICATION_LABELS, ACTOR_MAPPING_LABELS, FORCES_ANALYSIS_LABELS, IMPACT_MATRIX_LABELS, POLITICAL_THREAT_LANDSCAPE_LABELS, ACTOR_THREAT_PROFILING_LABELS, CONSEQUENCE_TREES_LABELS, LEGISLATIVE_DISRUPTION_LABELS, RISK_MATRIX_LABELS, QUANTITATIVE_SWOT_LABELS, POLITICAL_CAPITAL_RISK_LABELS, LEGISLATIVE_VELOCITY_RISK_LABELS, AGENT_RISK_WORKFLOW_LABELS, STAKEHOLDER_IMPACT_LABELS, COALITION_DYNAMICS_LABELS, VOTING_PATTERNS_LABELS, CROSS_SESSION_INTELLIGENCE_LABELS, SYNTHESIS_SUMMARY_LABELS, DOCUMENT_ANALYSIS_LABELS, SIGNIFICANCE_SCORING_LABELS, INSTALL_APP_LABELS, UPDATE_AVAILABLE_LABELS, UPDATE_REFRESH_CTA_LABELS, UPDATE_DISMISS_LABELS, OFFLINE_TITLE_LABELS, OFFLINE_BODY_LABELS, OFFLINE_RETRY_LABELS, BUILD_INFO_COMMIT_LABELS, BUILD_INFO_DEPLOYED_LABELS, HEADER_CTA_SPONSOR_LABELS, HEADER_CTA_BECOME_SPONSOR_LABELS, HEADER_CTA_SECURITY_LABELS, FOOTER_NEWS_LABELS, FOOTER_DASHBOARD_LABELS, FOOTER_ANALYSIS_REPORTS_LABELS, FOOTER_API_DOCS_LABELS, FOOTER_COMPANY_TAGLINE_LABELS, LANGUAGE_SELECTION_ARIA_LABELS, FOOTER_TRUST_BADGES_ARIA_LABELS, } from './language-ui.js';
|
|
13
|
+
export { PAGE_TITLES, PAGE_DESCRIPTIONS, SECTION_HEADINGS, NO_ARTICLES_MESSAGES, SKIP_LINK_TEXTS, ARTICLE_TYPE_LABELS, READ_TIME_LABELS, PROGRESSIVE_DISCLOSURE_LABELS, BACK_TO_NEWS_LABELS, ARTICLE_NAV_LABELS, RELATED_ARTICLES_NAV_LABELS, BREADCRUMB_HOME_LABELS, BREADCRUMB_NEWS_LABELS, TIMELINE_HEADINGS, COMPARISON_BEFORE_LABELS, COMPARISON_AFTER_LABELS, KEY_FIGURES_HEADINGS, AI_SECTION_CONTENT, FILTER_LABELS, SOURCES_HEADING_LABELS, HEADER_SUBTITLE_LABELS, THEME_TOGGLE_LABELS, FOOTER_ABOUT_HEADING_LABELS, FOOTER_ABOUT_TEXT_LABELS, FOOTER_QUICK_LINKS_LABELS, FOOTER_BUILT_BY_LABELS, FOOTER_LANGUAGES_LABELS, FOOTER_HOME_LABELS, FOOTER_SITEMAP_LABELS, FOOTER_RSS_LABELS, FOOTER_GITHUB_REPO_LABELS, FOOTER_LICENSE_LABELS, FOOTER_EUROPARL_LABELS, FOOTER_LINKEDIN_LABELS, FOOTER_SECURITY_POLICY_LABELS, FOOTER_CONTACT_LABELS, FOOTER_DISCLAIMER_LABELS, FOOTER_REPORT_ISSUES_LABELS, FOOTER_ARTICLES_AVAILABLE_LABELS, FOOTER_POLITICAL_INTELLIGENCE_LABELS, TOC_ARIA_LABELS, TRADECRAFT_HEADING_LABELS, TRADECRAFT_INTRO_LABELS, TRADECRAFT_METHODOLOGIES_LABELS, TRADECRAFT_TEMPLATES_LABELS, ANALYSIS_INDEX_HEADING_LABELS, ANALYSIS_INDEX_INTRO_LABELS, ANALYSIS_INDEX_COL_SECTION_LABELS, ANALYSIS_INDEX_COL_ARTIFACT_LABELS, ANALYSIS_INDEX_COL_PATH_LABELS, KEY_TAKEAWAYS_HEADING_LABELS, SUPPLEMENTARY_HEADING_LABELS, SECTION_TITLE_LABELS, RELATED_ANALYSIS_LABELS, ANALYSIS_TRANSPARENCY_LABELS, ANALYSIS_SUMMARY_LABELS, METHODOLOGY_LABELS, TRANSPARENCY_DISCLOSURE_LABELS, CLASSIFICATION_ANALYSIS_LABELS, THREAT_ASSESSMENT_LABELS, RISK_SCORING_LABELS, DEEP_ANALYSIS_LABELS, VIEW_SOURCE_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, ARTICLE_TYPE_ICONS, OPEN_SOURCE_NOTE_LABELS, AI_ANALYSIS_GUIDE_LABELS, SWOT_FRAMEWORK_LABELS, RISK_METHODOLOGY_LABELS, THREAT_FRAMEWORK_LABELS, CLASSIFICATION_GUIDE_LABELS, STYLE_GUIDE_LABELS, SIGNIFICANCE_CLASSIFICATION_LABELS, ACTOR_MAPPING_LABELS, FORCES_ANALYSIS_LABELS, IMPACT_MATRIX_LABELS, POLITICAL_THREAT_LANDSCAPE_LABELS, ACTOR_THREAT_PROFILING_LABELS, CONSEQUENCE_TREES_LABELS, LEGISLATIVE_DISRUPTION_LABELS, RISK_MATRIX_LABELS, QUANTITATIVE_SWOT_LABELS, POLITICAL_CAPITAL_RISK_LABELS, LEGISLATIVE_VELOCITY_RISK_LABELS, AGENT_RISK_WORKFLOW_LABELS, STAKEHOLDER_IMPACT_LABELS, COALITION_DYNAMICS_LABELS, VOTING_PATTERNS_LABELS, CROSS_SESSION_INTELLIGENCE_LABELS, SYNTHESIS_SUMMARY_LABELS, DOCUMENT_ANALYSIS_LABELS, SIGNIFICANCE_SCORING_LABELS, INSTALL_APP_LABELS, UPDATE_AVAILABLE_LABELS, UPDATE_REFRESH_CTA_LABELS, UPDATE_DISMISS_LABELS, OFFLINE_TITLE_LABELS, OFFLINE_BODY_LABELS, OFFLINE_RETRY_LABELS, BUILD_INFO_COMMIT_LABELS, BUILD_INFO_DEPLOYED_LABELS, HEADER_CTA_SPONSOR_LABELS, HEADER_CTA_BECOME_SPONSOR_LABELS, HEADER_CTA_SECURITY_LABELS, FOOTER_NEWS_LABELS, FOOTER_DASHBOARD_LABELS, FOOTER_ANALYSIS_REPORTS_LABELS, FOOTER_API_DOCS_LABELS, FOOTER_COMPANY_TAGLINE_LABELS, LANGUAGE_SELECTION_ARIA_LABELS, FOOTER_TRUST_BADGES_ARIA_LABELS, } from './language-ui.js';
|
|
14
14
|
export { WEEK_AHEAD_TITLES, MONTH_AHEAD_TITLES, WEEKLY_REVIEW_TITLES, MONTHLY_REVIEW_TITLES, MOTIONS_TITLES, BREAKING_NEWS_TITLES, COMMITTEE_REPORTS_TITLES, PROPOSITIONS_TITLES, PROPOSITIONS_STRINGS, EDITORIAL_STRINGS, MOTIONS_STRINGS, WEEK_AHEAD_STRINGS, WEEK_AHEAD_STAKEHOLDER_STRINGS, BREAKING_STRINGS, DEEP_ANALYSIS_STRINGS, COMMITTEE_ANALYSIS_CONTENT_STRINGS, SWOT_STRINGS, DASHBOARD_STRINGS, SWOT_BUILDER_STRINGS, DASHBOARD_BUILDER_STRINGS, LOCALIZED_KEYWORDS, MONTH_IN_REVIEW_STRINGS, ANALYSIS_QUALITY_LABELS, ANALYSIS_INSIGHTS_HEADING, } from './language-articles.js';
|
|
15
15
|
//# sourceMappingURL=languages.js.map
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* - `article-category-labels.ts` — `ARTICLE_TYPE_LABELS`, `ARTICLE_TYPE_ICONS`
|
|
12
12
|
* - `accessibility.ts` — `SKIP_LINK_TEXTS`, `TOC_ARIA_LABELS`, language-switcher / footer trust-badge ARIA labels
|
|
13
13
|
* - `reading-time.ts` — `READ_TIME_LABELS` (per-language pluralization)
|
|
14
|
+
* - `progressive-disclosure.ts` — `PROGRESSIVE_DISCLOSURE_LABELS` (reading layers, expand CTAs, reading-time line, TOC layer badge)
|
|
14
15
|
* - `ai-content.ts` — `AI_SECTION_CONTENT` + `AISection` interface
|
|
15
16
|
* - `related-analysis.ts` — `SECTION_TITLE_LABELS`, `RELATED_ANALYSIS_LABELS`
|
|
16
17
|
* - `tradecraft-cards.ts` — tradecraft / analysis-index card labels
|
|
@@ -24,6 +25,7 @@ export { FOOTER_ABOUT_HEADING_LABELS, FOOTER_ABOUT_TEXT_LABELS, FOOTER_QUICK_LIN
|
|
|
24
25
|
export { ARTICLE_TYPE_LABELS, ARTICLE_TYPE_ICONS, HE_DEEP_ANALYSIS, } from './article-category-labels.js';
|
|
25
26
|
export { SKIP_LINK_TEXTS, TOC_ARIA_LABELS, LANGUAGE_SELECTION_ARIA_LABELS, FOOTER_TRUST_BADGES_ARIA_LABELS, } from './accessibility.js';
|
|
26
27
|
export { READ_TIME_LABELS } from './reading-time.js';
|
|
28
|
+
export { PROGRESSIVE_DISCLOSURE_LABELS, type ProgressiveDisclosureStrings, } from './progressive-disclosure.js';
|
|
27
29
|
export { AI_SECTION_CONTENT, type AISection } from './ai-content.js';
|
|
28
30
|
export { SECTION_TITLE_LABELS, RELATED_ANALYSIS_LABELS, type RelationshipLabels, type RelatedAnalysisStrings, } from './related-analysis.js';
|
|
29
31
|
export { TRADECRAFT_HEADING_LABELS, TRADECRAFT_INTRO_LABELS, TRADECRAFT_METHODOLOGIES_LABELS, TRADECRAFT_TEMPLATES_LABELS, ANALYSIS_INDEX_HEADING_LABELS, ANALYSIS_INDEX_INTRO_LABELS, ANALYSIS_INDEX_COL_SECTION_LABELS, ANALYSIS_INDEX_COL_ARTIFACT_LABELS, ANALYSIS_INDEX_COL_PATH_LABELS, VIEW_SOURCE_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, OPEN_SOURCE_NOTE_LABELS, } from './tradecraft-cards.js';
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* - `article-category-labels.ts` — `ARTICLE_TYPE_LABELS`, `ARTICLE_TYPE_ICONS`
|
|
14
14
|
* - `accessibility.ts` — `SKIP_LINK_TEXTS`, `TOC_ARIA_LABELS`, language-switcher / footer trust-badge ARIA labels
|
|
15
15
|
* - `reading-time.ts` — `READ_TIME_LABELS` (per-language pluralization)
|
|
16
|
+
* - `progressive-disclosure.ts` — `PROGRESSIVE_DISCLOSURE_LABELS` (reading layers, expand CTAs, reading-time line, TOC layer badge)
|
|
16
17
|
* - `ai-content.ts` — `AI_SECTION_CONTENT` + `AISection` interface
|
|
17
18
|
* - `related-analysis.ts` — `SECTION_TITLE_LABELS`, `RELATED_ANALYSIS_LABELS`
|
|
18
19
|
* - `tradecraft-cards.ts` — tradecraft / analysis-index card labels
|
|
@@ -26,6 +27,7 @@ export { FOOTER_ABOUT_HEADING_LABELS, FOOTER_ABOUT_TEXT_LABELS, FOOTER_QUICK_LIN
|
|
|
26
27
|
export { ARTICLE_TYPE_LABELS, ARTICLE_TYPE_ICONS, HE_DEEP_ANALYSIS, } from './article-category-labels.js';
|
|
27
28
|
export { SKIP_LINK_TEXTS, TOC_ARIA_LABELS, LANGUAGE_SELECTION_ARIA_LABELS, FOOTER_TRUST_BADGES_ARIA_LABELS, } from './accessibility.js';
|
|
28
29
|
export { READ_TIME_LABELS } from './reading-time.js';
|
|
30
|
+
export { PROGRESSIVE_DISCLOSURE_LABELS, } from './progressive-disclosure.js';
|
|
29
31
|
export { AI_SECTION_CONTENT } from './ai-content.js';
|
|
30
32
|
export { SECTION_TITLE_LABELS, RELATED_ANALYSIS_LABELS, } from './related-analysis.js';
|
|
31
33
|
export { TRADECRAFT_HEADING_LABELS, TRADECRAFT_INTRO_LABELS, TRADECRAFT_METHODOLOGIES_LABELS, TRADECRAFT_TEMPLATES_LABELS, ANALYSIS_INDEX_HEADING_LABELS, ANALYSIS_INDEX_INTRO_LABELS, ANALYSIS_INDEX_COL_SECTION_LABELS, ANALYSIS_INDEX_COL_ARTIFACT_LABELS, ANALYSIS_INDEX_COL_PATH_LABELS, VIEW_SOURCE_LABELS, VIEW_SOURCE_MARKDOWN_LABELS, OPEN_SOURCE_NOTE_LABELS, } from './tradecraft-cards.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Constants/UI/ProgressiveDisclosure
|
|
3
|
+
* @description Localized chrome for the article progressive-disclosure
|
|
4
|
+
* surface — the three reading layers (quick / full analysis / complete
|
|
5
|
+
* intelligence), the visible `<summary>` expand CTAs, the reading-time
|
|
6
|
+
* estimate line, and the Table-of-Contents layer badge.
|
|
7
|
+
*
|
|
8
|
+
* A single `PROGRESSIVE_DISCLOSURE_LABELS` map is shared by every call
|
|
9
|
+
* site (the layer wrappers in `aggregator/progressive-disclosure.ts`, the
|
|
10
|
+
* reading-time line in `aggregator/html/shell.ts`, and the TOC badge in
|
|
11
|
+
* `aggregator/html/toc.ts`) so the layer vocabulary stays consistent and
|
|
12
|
+
* each phrase is translated exactly once.
|
|
13
|
+
*/
|
|
14
|
+
import type { LanguageMap } from '../../types/index.js';
|
|
15
|
+
/** Per-language UI strings for the article progressive-disclosure chrome. */
|
|
16
|
+
export interface ProgressiveDisclosureStrings {
|
|
17
|
+
/** Name of the always-visible quick-read layer (reading-time + aria). */
|
|
18
|
+
readonly quickRead: string;
|
|
19
|
+
/** Name of the cumulative full-analysis layer (reading-time + aria). */
|
|
20
|
+
readonly fullAnalysis: string;
|
|
21
|
+
/** Name of the cumulative complete-intelligence layer (reading-time + aria). */
|
|
22
|
+
readonly completeIntelligence: string;
|
|
23
|
+
/** Visible CTA on the analysis `<summary>` toggle (a `↓` glyph is appended in markup). */
|
|
24
|
+
readonly expandAnalysis: string;
|
|
25
|
+
/** Visible CTA on the intelligence `<summary>` toggle (a `↓` glyph is appended in markup). */
|
|
26
|
+
readonly expandIntelligence: string;
|
|
27
|
+
/** Abbreviation for minutes used in the reading-time line (includes leading space for non-CJK locales). */
|
|
28
|
+
readonly minutesAbbr: string;
|
|
29
|
+
/** Aria-label for the reading-time estimate paragraph. */
|
|
30
|
+
readonly readingTimeAria: string;
|
|
31
|
+
/** Aria-label prefix for the TOC layer badge (rendered as e.g. "Layer L1"). */
|
|
32
|
+
readonly layerBadge: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Localised progressive-disclosure strings across all 14 supported
|
|
36
|
+
* languages. Reused by the layer wrappers, the reading-time line, and the
|
|
37
|
+
* TOC layer badge so the layer vocabulary is translated only once.
|
|
38
|
+
*/
|
|
39
|
+
export declare const PROGRESSIVE_DISCLOSURE_LABELS: LanguageMap<ProgressiveDisclosureStrings>;
|
|
40
|
+
//# sourceMappingURL=progressive-disclosure.d.ts.map
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Localised progressive-disclosure strings across all 14 supported
|
|
5
|
+
* languages. Reused by the layer wrappers, the reading-time line, and the
|
|
6
|
+
* TOC layer badge so the layer vocabulary is translated only once.
|
|
7
|
+
*/
|
|
8
|
+
export const PROGRESSIVE_DISCLOSURE_LABELS = {
|
|
9
|
+
en: {
|
|
10
|
+
quickRead: 'Quick read',
|
|
11
|
+
fullAnalysis: 'Full analysis',
|
|
12
|
+
completeIntelligence: 'Complete intelligence',
|
|
13
|
+
expandAnalysis: 'Read full analysis',
|
|
14
|
+
expandIntelligence: 'Open complete intelligence',
|
|
15
|
+
minutesAbbr: ' min',
|
|
16
|
+
readingTimeAria: 'Estimated reading time',
|
|
17
|
+
layerBadge: 'Layer',
|
|
18
|
+
},
|
|
19
|
+
sv: {
|
|
20
|
+
quickRead: 'Snabbläsning',
|
|
21
|
+
fullAnalysis: 'Fullständig analys',
|
|
22
|
+
completeIntelligence: 'Komplett underrättelse',
|
|
23
|
+
expandAnalysis: 'Läs fullständig analys',
|
|
24
|
+
expandIntelligence: 'Öppna komplett underrättelse',
|
|
25
|
+
minutesAbbr: ' min',
|
|
26
|
+
readingTimeAria: 'Uppskattad lästid',
|
|
27
|
+
layerBadge: 'Nivå',
|
|
28
|
+
},
|
|
29
|
+
da: {
|
|
30
|
+
quickRead: 'Hurtig læsning',
|
|
31
|
+
fullAnalysis: 'Fuld analyse',
|
|
32
|
+
completeIntelligence: 'Komplet efterretning',
|
|
33
|
+
expandAnalysis: 'Læs fuld analyse',
|
|
34
|
+
expandIntelligence: 'Åbn komplet efterretning',
|
|
35
|
+
minutesAbbr: ' min',
|
|
36
|
+
readingTimeAria: 'Anslået læsetid',
|
|
37
|
+
layerBadge: 'Niveau',
|
|
38
|
+
},
|
|
39
|
+
no: {
|
|
40
|
+
quickRead: 'Hurtiglesing',
|
|
41
|
+
fullAnalysis: 'Full analyse',
|
|
42
|
+
completeIntelligence: 'Komplett etterretning',
|
|
43
|
+
expandAnalysis: 'Les full analyse',
|
|
44
|
+
expandIntelligence: 'Åpne komplett etterretning',
|
|
45
|
+
minutesAbbr: ' min',
|
|
46
|
+
readingTimeAria: 'Anslått lesetid',
|
|
47
|
+
layerBadge: 'Nivå',
|
|
48
|
+
},
|
|
49
|
+
fi: {
|
|
50
|
+
quickRead: 'Pikaluku',
|
|
51
|
+
fullAnalysis: 'Täysi analyysi',
|
|
52
|
+
completeIntelligence: 'Täydellinen tiedustelu',
|
|
53
|
+
expandAnalysis: 'Lue täysi analyysi',
|
|
54
|
+
expandIntelligence: 'Avaa täydellinen tiedustelu',
|
|
55
|
+
minutesAbbr: ' min',
|
|
56
|
+
readingTimeAria: 'Arvioitu lukuaika',
|
|
57
|
+
layerBadge: 'Taso',
|
|
58
|
+
},
|
|
59
|
+
de: {
|
|
60
|
+
quickRead: 'Schnelllektüre',
|
|
61
|
+
fullAnalysis: 'Vollständige Analyse',
|
|
62
|
+
completeIntelligence: 'Vollständige Aufklärung',
|
|
63
|
+
expandAnalysis: 'Vollständige Analyse lesen',
|
|
64
|
+
expandIntelligence: 'Vollständige Aufklärung öffnen',
|
|
65
|
+
minutesAbbr: ' Min.',
|
|
66
|
+
readingTimeAria: 'Geschätzte Lesezeit',
|
|
67
|
+
layerBadge: 'Ebene',
|
|
68
|
+
},
|
|
69
|
+
fr: {
|
|
70
|
+
quickRead: 'Lecture rapide',
|
|
71
|
+
fullAnalysis: 'Analyse complète',
|
|
72
|
+
completeIntelligence: 'Renseignement complet',
|
|
73
|
+
expandAnalysis: "Lire l'analyse complète",
|
|
74
|
+
expandIntelligence: 'Ouvrir le renseignement complet',
|
|
75
|
+
minutesAbbr: ' min',
|
|
76
|
+
readingTimeAria: 'Temps de lecture estimé',
|
|
77
|
+
layerBadge: 'Niveau',
|
|
78
|
+
},
|
|
79
|
+
es: {
|
|
80
|
+
quickRead: 'Lectura rápida',
|
|
81
|
+
fullAnalysis: 'Análisis completo',
|
|
82
|
+
completeIntelligence: 'Inteligencia completa',
|
|
83
|
+
expandAnalysis: 'Leer análisis completo',
|
|
84
|
+
expandIntelligence: 'Abrir inteligencia completa',
|
|
85
|
+
minutesAbbr: ' min',
|
|
86
|
+
readingTimeAria: 'Tiempo de lectura estimado',
|
|
87
|
+
layerBadge: 'Nivel',
|
|
88
|
+
},
|
|
89
|
+
nl: {
|
|
90
|
+
quickRead: 'Snel lezen',
|
|
91
|
+
fullAnalysis: 'Volledige analyse',
|
|
92
|
+
completeIntelligence: 'Volledige inlichtingen',
|
|
93
|
+
expandAnalysis: 'Lees volledige analyse',
|
|
94
|
+
expandIntelligence: 'Volledige inlichtingen openen',
|
|
95
|
+
minutesAbbr: ' min',
|
|
96
|
+
readingTimeAria: 'Geschatte leestijd',
|
|
97
|
+
layerBadge: 'Niveau',
|
|
98
|
+
},
|
|
99
|
+
ar: {
|
|
100
|
+
quickRead: 'قراءة سريعة',
|
|
101
|
+
fullAnalysis: 'تحليل كامل',
|
|
102
|
+
completeIntelligence: 'استخبارات كاملة',
|
|
103
|
+
expandAnalysis: 'اقرأ التحليل الكامل',
|
|
104
|
+
expandIntelligence: 'افتح الاستخبارات الكاملة',
|
|
105
|
+
minutesAbbr: ' دقيقة',
|
|
106
|
+
readingTimeAria: 'وقت القراءة المقدر',
|
|
107
|
+
layerBadge: 'المستوى',
|
|
108
|
+
},
|
|
109
|
+
he: {
|
|
110
|
+
quickRead: 'קריאה מהירה',
|
|
111
|
+
fullAnalysis: 'ניתוח מלא',
|
|
112
|
+
completeIntelligence: 'מודיעין מלא',
|
|
113
|
+
expandAnalysis: 'קראו את הניתוח המלא',
|
|
114
|
+
expandIntelligence: 'פתחו מודיעין מלא',
|
|
115
|
+
minutesAbbr: ' דק׳',
|
|
116
|
+
readingTimeAria: 'זמן קריאה משוער',
|
|
117
|
+
layerBadge: 'שכבה',
|
|
118
|
+
},
|
|
119
|
+
ja: {
|
|
120
|
+
quickRead: 'クイックリード',
|
|
121
|
+
fullAnalysis: '完全な分析',
|
|
122
|
+
completeIntelligence: '完全なインテリジェンス',
|
|
123
|
+
expandAnalysis: '完全な分析を読む',
|
|
124
|
+
expandIntelligence: '完全なインテリジェンスを開く',
|
|
125
|
+
minutesAbbr: '分',
|
|
126
|
+
readingTimeAria: '推定読了時間',
|
|
127
|
+
layerBadge: 'レイヤー',
|
|
128
|
+
},
|
|
129
|
+
ko: {
|
|
130
|
+
quickRead: '빠른 읽기',
|
|
131
|
+
fullAnalysis: '전체 분석',
|
|
132
|
+
completeIntelligence: '완전한 인텔리전스',
|
|
133
|
+
expandAnalysis: '전체 분석 읽기',
|
|
134
|
+
expandIntelligence: '완전한 인텔리전스 열기',
|
|
135
|
+
minutesAbbr: '분',
|
|
136
|
+
readingTimeAria: '예상 읽기 시간',
|
|
137
|
+
layerBadge: '레이어',
|
|
138
|
+
},
|
|
139
|
+
zh: {
|
|
140
|
+
quickRead: '快速阅读',
|
|
141
|
+
fullAnalysis: '完整分析',
|
|
142
|
+
completeIntelligence: '完整情报',
|
|
143
|
+
expandAnalysis: '阅读完整分析',
|
|
144
|
+
expandIntelligence: '打开完整情报',
|
|
145
|
+
minutesAbbr: '分钟',
|
|
146
|
+
readingTimeAria: '预计阅读时间',
|
|
147
|
+
layerBadge: '层级',
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=progressive-disclosure.js.map
|
|
@@ -95,6 +95,15 @@
|
|
|
95
95
|
* { "lang": "zh", "count": 92 }
|
|
96
96
|
* ]
|
|
97
97
|
* },
|
|
98
|
+
* "translationRegister": {
|
|
99
|
+
* "sv": {
|
|
100
|
+
* "name": "Swedish", "family": "Nordic",
|
|
101
|
+
* "register": "Formal, impersonal …",
|
|
102
|
+
* "fixedTokenNote": "IMF/WEO verbatim — never IVF …",
|
|
103
|
+
* "terms": { "European Parliament": "Europaparlamentet", … }
|
|
104
|
+
* },
|
|
105
|
+
* ...
|
|
106
|
+
* },
|
|
98
107
|
* "queue": [
|
|
99
108
|
* {
|
|
100
109
|
* "date": "2026-05-15",
|
|
@@ -426,6 +435,276 @@ const FIXED_TOKEN_CLASSES = Object.freeze([
|
|
|
426
435
|
{ key: 'procedure-id', pattern: /\b\d{4}\/\d{4}\([A-Z]{3}\)/g },
|
|
427
436
|
]);
|
|
428
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Machine-readable mirror of the per-language register the translator agent
|
|
440
|
+
* needs on every run — the style register (§ 4) and canonical EP terminology
|
|
441
|
+
* pairs (§ 5) of `analysis/methodologies/executive-brief-translation-guide.md`.
|
|
442
|
+
*
|
|
443
|
+
* Emitted ONCE into the discovery queue payload (as `translationRegister`,
|
|
444
|
+
* filtered to the languages the run actually touches) so the agent reads the
|
|
445
|
+
* rows it needs inline from `queue.json` instead of opening the full ~18 KB
|
|
446
|
+
* guide in-session on every turn. Bounding what enters the agent's context
|
|
447
|
+
* directly bounds the per-session effective-token accumulation that is the
|
|
448
|
+
* binding constraint on this workflow (see news-translate.md frontmatter and
|
|
449
|
+
* regression run #26641760920).
|
|
450
|
+
*
|
|
451
|
+
* Each entry:
|
|
452
|
+
* - `name` — endonym/English name of the language (operator-facing)
|
|
453
|
+
* - `family` — register family (Nordic | EU-core | RTL | CJK)
|
|
454
|
+
* - `register` — one-line style-register reminder (guide § 4)
|
|
455
|
+
* - `fixedTokenNote` — one-line FIXED-TOKEN preservation trap (guide § 4,
|
|
456
|
+
* validator gate #5); the highest-frequency failure mode
|
|
457
|
+
* - `terms` — canonical EN→target EP terminology pairs (guide § 5)
|
|
458
|
+
*
|
|
459
|
+
* This is a deliberate, reviewed duplication of the prose guide: when § 4 / § 5
|
|
460
|
+
* change, update this constant in the same PR. The drift-guard test
|
|
461
|
+
* `discover-untranslated-briefs.test.js` asserts the shape and a few anchor
|
|
462
|
+
* values so the two cannot silently diverge on the fields that matter.
|
|
463
|
+
*
|
|
464
|
+
* @type {Readonly<Record<string, { name: string, family: string, register: string, fixedTokenNote: string, terms: Record<string, string> }>>}
|
|
465
|
+
*/
|
|
466
|
+
export const TRANSLATION_REGISTER = Object.freeze({
|
|
467
|
+
sv: {
|
|
468
|
+
name: 'Swedish',
|
|
469
|
+
family: 'Nordic',
|
|
470
|
+
register: 'Formal, impersonal (man / Europaparlamentet); avoid du-tilltal.',
|
|
471
|
+
fixedTokenNote:
|
|
472
|
+
"IMF/WEO verbatim — never IVF or 'Internationella valutafonden'. World Bank/Fiscal Monitor verbatim.",
|
|
473
|
+
terms: {
|
|
474
|
+
'European Parliament': 'Europaparlamentet',
|
|
475
|
+
'Plenary session': 'plenarsammanträde',
|
|
476
|
+
Committee: 'utskott',
|
|
477
|
+
Rapporteur: 'föredragande',
|
|
478
|
+
'Legislative procedure': 'lagstiftningsförfarande',
|
|
479
|
+
Resolution: 'resolution',
|
|
480
|
+
'Adopted text': 'antagen text',
|
|
481
|
+
Vote: 'omröstning',
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
da: {
|
|
485
|
+
name: 'Danish',
|
|
486
|
+
family: 'Nordic',
|
|
487
|
+
register: 'Formal, indicative mood; official EP designations.',
|
|
488
|
+
fixedTokenNote:
|
|
489
|
+
"IMF/WEO verbatim — never IMV or 'Den Internationale Valutafond'. World Bank/Fiscal Monitor verbatim.",
|
|
490
|
+
terms: {
|
|
491
|
+
'European Parliament': 'Europa-Parlamentet',
|
|
492
|
+
'Plenary session': 'plenarmøde',
|
|
493
|
+
Committee: 'udvalg',
|
|
494
|
+
Rapporteur: 'ordfører',
|
|
495
|
+
'Legislative procedure': 'lovgivningsprocedure',
|
|
496
|
+
Resolution: 'beslutning',
|
|
497
|
+
'Adopted text': 'vedtaget tekst',
|
|
498
|
+
Vote: 'afstemning',
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
no: {
|
|
502
|
+
name: 'Norwegian',
|
|
503
|
+
family: 'Nordic',
|
|
504
|
+
register: 'Formal, indicative mood; official EP designations.',
|
|
505
|
+
fixedTokenNote:
|
|
506
|
+
"IMF/WEO verbatim — never IPF/IMV/'Det internasjonale valutafondet'/Pengefondet/'Verdens økonomiske utsikter'. World Bank/Fiscal Monitor verbatim.",
|
|
507
|
+
terms: {
|
|
508
|
+
'European Parliament': 'Europaparlamentet',
|
|
509
|
+
'Plenary session': 'plenumsmøte',
|
|
510
|
+
Committee: 'komité',
|
|
511
|
+
Rapporteur: 'ordfører',
|
|
512
|
+
'Legislative procedure': 'lovgivningsprosedyre',
|
|
513
|
+
Resolution: 'resolusjon',
|
|
514
|
+
'Adopted text': 'vedtatt tekst',
|
|
515
|
+
Vote: 'avstemning',
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
fi: {
|
|
519
|
+
name: 'Finnish',
|
|
520
|
+
family: 'Nordic',
|
|
521
|
+
register: 'Formal; partitive + case agreement non-negotiable.',
|
|
522
|
+
fixedTokenNote:
|
|
523
|
+
"IMF/WEO verbatim — never KVR or 'Kansainvälinen valuuttarahasto'. World Bank/Fiscal Monitor verbatim.",
|
|
524
|
+
terms: {
|
|
525
|
+
'European Parliament': 'Euroopan parlamentti',
|
|
526
|
+
'Plenary session': 'täysistunto',
|
|
527
|
+
Committee: 'valiokunta',
|
|
528
|
+
Rapporteur: 'esittelijä',
|
|
529
|
+
'Legislative procedure': 'lainsäädäntömenettely',
|
|
530
|
+
Resolution: 'päätöslauselma',
|
|
531
|
+
'Adopted text': 'hyväksytty teksti',
|
|
532
|
+
Vote: 'äänestys',
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
de: {
|
|
536
|
+
name: 'German',
|
|
537
|
+
family: 'EU-core',
|
|
538
|
+
register:
|
|
539
|
+
"Formal (Sie); capitalise nouns; 'Europäisches Parlament' not 'EU-Parlament' in titles.",
|
|
540
|
+
fixedTokenNote:
|
|
541
|
+
'IMF/WEO/World Bank/Fiscal Monitor verbatim — never IWF.',
|
|
542
|
+
terms: {
|
|
543
|
+
'European Parliament': 'Europäisches Parlament',
|
|
544
|
+
'Plenary session': 'Plenarsitzung',
|
|
545
|
+
Committee: 'Ausschuss',
|
|
546
|
+
Rapporteur: 'Berichterstatter',
|
|
547
|
+
'Legislative procedure': 'Gesetzgebungsverfahren',
|
|
548
|
+
Resolution: 'Entschließung',
|
|
549
|
+
'Adopted text': 'angenommener Text',
|
|
550
|
+
Vote: 'Abstimmung',
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
fr: {
|
|
554
|
+
name: 'French',
|
|
555
|
+
family: 'EU-core',
|
|
556
|
+
register:
|
|
557
|
+
'Formal (vous); Académie française register; avoid Anglicisms unless source uses one as a fixed token.',
|
|
558
|
+
fixedTokenNote:
|
|
559
|
+
'IMF/WEO/World Bank/Fiscal Monitor verbatim — never FMI.',
|
|
560
|
+
terms: {
|
|
561
|
+
'European Parliament': 'Parlement européen',
|
|
562
|
+
'Plenary session': 'séance plénière',
|
|
563
|
+
Committee: 'commission',
|
|
564
|
+
Rapporteur: 'rapporteur',
|
|
565
|
+
'Legislative procedure': 'procédure législative',
|
|
566
|
+
Resolution: 'résolution',
|
|
567
|
+
'Adopted text': 'texte adopté',
|
|
568
|
+
Vote: 'vote',
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
es: {
|
|
572
|
+
name: 'Spanish',
|
|
573
|
+
family: 'EU-core',
|
|
574
|
+
register: 'Peninsular es-ES; formal; avoid Latin-American vocabulary.',
|
|
575
|
+
fixedTokenNote:
|
|
576
|
+
'IMF/WEO/World Bank/Fiscal Monitor verbatim — never FMI.',
|
|
577
|
+
terms: {
|
|
578
|
+
'European Parliament': 'Parlamento Europeo',
|
|
579
|
+
'Plenary session': 'sesión plenaria',
|
|
580
|
+
Committee: 'comisión',
|
|
581
|
+
Rapporteur: 'ponente',
|
|
582
|
+
'Legislative procedure': 'procedimiento legislativo',
|
|
583
|
+
Resolution: 'resolución',
|
|
584
|
+
'Adopted text': 'texto aprobado',
|
|
585
|
+
Vote: 'votación',
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
nl: {
|
|
589
|
+
name: 'Dutch',
|
|
590
|
+
family: 'EU-core',
|
|
591
|
+
register: 'Formal (u-form); prefer impersonal constructions.',
|
|
592
|
+
fixedTokenNote:
|
|
593
|
+
"IMF/WEO/World Bank/Fiscal Monitor verbatim — never IMV/'Internationaal Monetair Fonds'/Wereldbank.",
|
|
594
|
+
terms: {
|
|
595
|
+
'European Parliament': 'Europees Parlement',
|
|
596
|
+
'Plenary session': 'plenaire vergadering',
|
|
597
|
+
Committee: 'commissie',
|
|
598
|
+
Rapporteur: 'rapporteur',
|
|
599
|
+
'Legislative procedure': 'wetgevingsprocedure',
|
|
600
|
+
Resolution: 'resolutie',
|
|
601
|
+
'Adopted text': 'aangenomen tekst',
|
|
602
|
+
Vote: 'stemming',
|
|
603
|
+
},
|
|
604
|
+
},
|
|
605
|
+
ar: {
|
|
606
|
+
name: 'Arabic',
|
|
607
|
+
family: 'RTL',
|
|
608
|
+
register:
|
|
609
|
+
'Modern Standard Arabic, formal political register; Western Arabic numerals 0–9; no RLM unless disambiguating a Latin token.',
|
|
610
|
+
fixedTokenNote:
|
|
611
|
+
'Keep IMF/WEO/World Bank/Fiscal Monitor and EP acronyms in Latin script; data-vintage/TA-id/procedure-id verbatim.',
|
|
612
|
+
terms: {
|
|
613
|
+
'European Parliament': 'البرلمان الأوروبي',
|
|
614
|
+
'Plenary session': 'الجلسة العامة',
|
|
615
|
+
Committee: 'اللجنة',
|
|
616
|
+
Rapporteur: 'المقرر',
|
|
617
|
+
'Legislative procedure': 'الإجراء التشريعي',
|
|
618
|
+
Resolution: 'قرار',
|
|
619
|
+
Vote: 'تصويت',
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
he: {
|
|
623
|
+
name: 'Hebrew',
|
|
624
|
+
family: 'RTL',
|
|
625
|
+
register: 'Formal modern Hebrew; no nikud unless the source carries it.',
|
|
626
|
+
fixedTokenNote:
|
|
627
|
+
'Keep IMF/WEO/World Bank/Fiscal Monitor and EP acronyms in Latin script; data-vintage/TA-id/procedure-id verbatim.',
|
|
628
|
+
terms: {
|
|
629
|
+
'European Parliament': 'הפרלמנט האירופי',
|
|
630
|
+
'Plenary session': 'מליאה',
|
|
631
|
+
Committee: 'ועדה',
|
|
632
|
+
Rapporteur: 'מדווח',
|
|
633
|
+
'Legislative procedure': 'הליך חקיקה',
|
|
634
|
+
Resolution: 'החלטה',
|
|
635
|
+
Vote: 'הצבעה',
|
|
636
|
+
},
|
|
637
|
+
},
|
|
638
|
+
ja: {
|
|
639
|
+
name: 'Japanese',
|
|
640
|
+
family: 'CJK',
|
|
641
|
+
register: 'です・ます polite register; full-width punctuation 。、「」.',
|
|
642
|
+
fixedTokenNote:
|
|
643
|
+
'Keep proper nouns (IMF, WEO, World Bank, EP body names) in Latin script; data-vintage/TA-id/procedure-id verbatim.',
|
|
644
|
+
terms: {
|
|
645
|
+
'European Parliament': '欧州議会',
|
|
646
|
+
'Plenary session': '本会議',
|
|
647
|
+
Committee: '委員会',
|
|
648
|
+
Rapporteur: '報告者',
|
|
649
|
+
'Legislative procedure': '立法手続き',
|
|
650
|
+
Resolution: '決議',
|
|
651
|
+
Vote: '採決',
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
ko: {
|
|
655
|
+
name: 'Korean',
|
|
656
|
+
family: 'CJK',
|
|
657
|
+
register: '합쇼체 formal polite; half-width , . ; spaces between eojeol.',
|
|
658
|
+
fixedTokenNote:
|
|
659
|
+
'Keep proper nouns (IMF, WEO, World Bank, EP body names) in Latin script; data-vintage/TA-id/procedure-id verbatim.',
|
|
660
|
+
terms: {
|
|
661
|
+
'European Parliament': '유럽의회',
|
|
662
|
+
'Plenary session': '본회의',
|
|
663
|
+
Committee: '위원회',
|
|
664
|
+
Rapporteur: '보고자',
|
|
665
|
+
'Legislative procedure': '입법절차',
|
|
666
|
+
Resolution: '결의',
|
|
667
|
+
Vote: '표결',
|
|
668
|
+
},
|
|
669
|
+
},
|
|
670
|
+
zh: {
|
|
671
|
+
name: 'Chinese',
|
|
672
|
+
family: 'CJK',
|
|
673
|
+
register: 'Simplified zh-CN only; full-width punctuation 。,「」/“”.',
|
|
674
|
+
fixedTokenNote:
|
|
675
|
+
'Keep proper nouns (IMF, WEO, World Bank, EP body names) in Latin script; data-vintage/TA-id/procedure-id verbatim.',
|
|
676
|
+
terms: {
|
|
677
|
+
'European Parliament': '欧洲议会',
|
|
678
|
+
'Plenary session': '全体会议',
|
|
679
|
+
Committee: '委员会',
|
|
680
|
+
Rapporteur: '报告员',
|
|
681
|
+
'Legislative procedure': '立法程序',
|
|
682
|
+
Resolution: '决议',
|
|
683
|
+
Vote: '表决',
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Build the per-language register block emitted into the discovery payload.
|
|
690
|
+
* Returns only the entries for `langs` (the languages the run actually
|
|
691
|
+
* touches), so the agent's in-context copy stays as small as possible.
|
|
692
|
+
* Unknown codes are skipped silently — the caller derives `langs` from the
|
|
693
|
+
* canonical TARGET_LANGS union, so this is defensive only.
|
|
694
|
+
*
|
|
695
|
+
* @param {Iterable<string>} langs
|
|
696
|
+
* @returns {Record<string, (typeof TRANSLATION_REGISTER)[string]>}
|
|
697
|
+
*/
|
|
698
|
+
export function buildTranslationRegister(langs) {
|
|
699
|
+
const out = {};
|
|
700
|
+
for (const lang of langs) {
|
|
701
|
+
if (Object.prototype.hasOwnProperty.call(TRANSLATION_REGISTER, lang)) {
|
|
702
|
+
out[lang] = TRANSLATION_REGISTER[lang];
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return out;
|
|
706
|
+
}
|
|
707
|
+
|
|
429
708
|
/**
|
|
430
709
|
* Count the number of lines in a markdown source file. Returns 0 if the
|
|
431
710
|
* file is missing. Used by `buildQueue` to populate `sourceLineCount` and
|
|
@@ -640,6 +919,20 @@ export function buildQueue(sources, options) {
|
|
|
640
919
|
}
|
|
641
920
|
const queuedTranslations = queue.reduce((sum, item) => sum + item.missingCount, 0);
|
|
642
921
|
|
|
922
|
+
// Per-language register the run actually needs: the union of every queued
|
|
923
|
+
// brief's missing languages, in canonical TARGET_LANGS order. Emitting this
|
|
924
|
+
// once (rather than per-entry) lets the translator agent read the style
|
|
925
|
+
// register + EP terminology pairs inline from queue.json and skip opening
|
|
926
|
+
// the ~18 KB translator guide in-session — bounding the per-session
|
|
927
|
+
// effective-token accumulation (see news-translate.md frontmatter budget).
|
|
928
|
+
const queuedLangs = new Set();
|
|
929
|
+
for (const item of queue) {
|
|
930
|
+
for (const lang of item.missingLangs) queuedLangs.add(lang);
|
|
931
|
+
}
|
|
932
|
+
const translationRegister = buildTranslationRegister(
|
|
933
|
+
TARGET_LANGS.filter((lang) => queuedLangs.has(lang)),
|
|
934
|
+
);
|
|
935
|
+
|
|
643
936
|
// Top 3 most-blocked target languages across the entire backlog. Operators
|
|
644
937
|
// skim this to spot e.g. "Japanese keeps falling behind" without parsing
|
|
645
938
|
// the full queue. Sort by count desc, then language code asc for stable
|
|
@@ -675,6 +968,7 @@ export function buildQueue(sources, options) {
|
|
|
675
968
|
largeSourceCount,
|
|
676
969
|
maxSourceLines: opts.maxSourceLines,
|
|
677
970
|
},
|
|
971
|
+
translationRegister,
|
|
678
972
|
queue,
|
|
679
973
|
};
|
|
680
974
|
}
|
|
@@ -689,7 +983,7 @@ export function main(argv) {
|
|
|
689
983
|
includeExtended: opts.includeExtended,
|
|
690
984
|
maxAgeDays: opts.maxAgeDays,
|
|
691
985
|
});
|
|
692
|
-
const { totals, queue } = buildQueue(sources, {
|
|
986
|
+
const { totals, translationRegister, queue } = buildQueue(sources, {
|
|
693
987
|
maxBriefs: opts.maxBriefs,
|
|
694
988
|
mode: opts.mode,
|
|
695
989
|
runNumber: opts.runNumber,
|
|
@@ -708,6 +1002,7 @@ export function main(argv) {
|
|
|
708
1002
|
targetBrief: opts.targetBrief,
|
|
709
1003
|
},
|
|
710
1004
|
totals,
|
|
1005
|
+
translationRegister,
|
|
711
1006
|
queue,
|
|
712
1007
|
};
|
|
713
1008
|
const out = `${JSON.stringify(payload, null, 2)}\n`;
|