Skip to content

Commit 5bfcde4

Browse files
authored
Merge pull request #2850 from ORCID/angel-leo-peer/PD-5670
PD-5670
2 parents 6502811 + 54d366c commit 5bfcde4

13 files changed

Lines changed: 1459 additions & 64 deletions

SUPPORTED_BROWSERS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
| Browser | Minimum version |
66
| ---------------- | --------------- |
77
| Android WebView | 145 or newer |
8-
| Apple Safari | 17 or newer |
9-
| Google Chrome | 119 or newer |
10-
| Microsoft Edge | 119 or newer |
11-
| Mozilla Firefox | 119 or newer |
12-
| Opera | 105 or newer |
8+
| Apple Safari | 17.2 or newer |
9+
| Google Chrome | 120 or newer |
10+
| Microsoft Edge | 120 or newer |
11+
| Mozilla Firefox | 120 or newer |
12+
| Opera | 106 or newer |
1313
| Opera Mobile | 80 or newer |
1414
| Samsung Internet | 25 or newer |

angular.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,13 @@
117117
{
118118
"glob": "**/*",
119119
"input": "src/assets/",
120-
"ignore": ["fonts/**/*", "**/*.scss"],
120+
"ignore": ["fonts/**/*", "**/*.scss", "**/*.spec.ts", "print-view/**"],
121121
"output": "/assets/"
122122
},
123123
{
124124
"glob": "**/*",
125125
"input": "src/assets/print-view/",
126+
"ignore": ["fetch-orcid.js", "**/*.spec.ts"],
126127
"output": "/print-view/"
127128
},
128129
{
@@ -425,7 +426,8 @@
425426
],
426427
"scripts": [
427428
"/scripts/environment.runtime.js",
428-
"/scripts/onetrust.runtime.js"
429+
"/scripts/onetrust.runtime.js",
430+
"src/assets/print-view/fetch-orcid.js"
429431
],
430432
"assets": ["src/favicon.ico", "src/assets", "src/manifest.json"],
431433
"sourceMap": true

scripts/normalize-xlf.prebuild.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,107 @@ function normalizeXlf12Sources(path: string) {
8585
}
8686
})
8787

88+
// Inject @@printView.* source-only trans-units so the test-language
89+
// generator (generateTestingLanguages) will also stamp X / LR / RL for
90+
// these strings, and so Transifex can discover them for real locales.
91+
// We use a stable @@-prefixed id so $localize can match by explicit id.
92+
const PRINT_VIEW_UNITS = [
93+
'printView.unnamedProfile',
94+
'printView.orcidIdAlt',
95+
'printView.biography',
96+
'printView.personalInformation',
97+
'printView.emails',
98+
'printView.websitesSocialLinks',
99+
'printView.otherIds',
100+
'printView.keywords',
101+
'printView.countries',
102+
'printView.activities',
103+
'printView.employments',
104+
'printView.educationAndQualifications',
105+
'printView.professionalActivities',
106+
'printView.fundings',
107+
'printView.researchResources',
108+
'printView.works',
109+
'printView.organization',
110+
'printView.organizationAddress',
111+
'printView.startDate',
112+
'printView.endDate',
113+
'printView.publicationDate',
114+
'printView.journal',
115+
'printView.roleTitle',
116+
'printView.department',
117+
'printView.type',
118+
'printView.url',
119+
'printView.untitled',
120+
'printView.identifier',
121+
'printView.enterOrcidId',
122+
'printView.orcidIdHelp',
123+
'printView.loadProfile',
124+
'printView.invalidOrcidId',
125+
'printView.loadingRecord',
126+
'printView.recordNotFound',
127+
'printView.redirectingToPrimary',
128+
'printView.fetchFailed',
129+
'printView.couldNotLoad',
130+
'printView.activityGroupHeading',
131+
'printView.peerReviewHeading',
132+
]
133+
const PRINT_VIEW_SOURCES: Record<string, string> = {
134+
'printView.unnamedProfile': 'Unnamed ORCID profile',
135+
'printView.orcidIdAlt': 'ORCID iD',
136+
'printView.biography': 'Biography',
137+
'printView.personalInformation': 'Personal information',
138+
'printView.emails': 'Emails',
139+
'printView.websitesSocialLinks': 'Websites & social links',
140+
'printView.otherIds': 'Other IDs',
141+
'printView.keywords': 'Keywords',
142+
'printView.countries': 'Countries',
143+
'printView.activities': 'Activities',
144+
'printView.employments': 'Employments',
145+
'printView.educationAndQualifications': 'Education and qualifications',
146+
'printView.professionalActivities': 'Professional activities',
147+
'printView.fundings': 'Fundings',
148+
'printView.researchResources': 'Research Resources',
149+
'printView.works': 'Works',
150+
'printView.organization': 'Organization',
151+
'printView.organizationAddress': 'Organization address',
152+
'printView.startDate': 'Start date',
153+
'printView.endDate': 'End date',
154+
'printView.publicationDate': 'Publication date',
155+
'printView.journal': 'Journal',
156+
'printView.roleTitle': 'Role title',
157+
'printView.department': 'Department',
158+
'printView.type': 'Type',
159+
'printView.url': 'URL',
160+
'printView.untitled': 'Untitled',
161+
'printView.identifier': 'Identifier',
162+
'printView.enterOrcidId': 'Enter an ORCID iD',
163+
'printView.orcidIdHelp':
164+
'Add an ORCID iD to the URL or use the form below.',
165+
'printView.loadProfile': 'Load profile',
166+
'printView.invalidOrcidId':
167+
'Enter a valid ORCID iD (format: 0000-0000-0000-0000).',
168+
'printView.loadingRecord': 'Loading ORCID record...',
169+
'printView.recordNotFound':
170+
'Record data was not found in ORCID response.',
171+
'printView.redirectingToPrimary':
172+
'Redirecting to primary ORCID record\u2026',
173+
'printView.fetchFailed': 'Failed to fetch ORCID record',
174+
'printView.couldNotLoad': 'Could not load',
175+
'printView.activityGroupHeading': 'Activity group heading',
176+
'printView.peerReviewHeading': 'Peer review heading',
177+
}
178+
const existingIds = new Set(transUnits.map((tu: any) => tu?.$?.id))
179+
const printViewBody = fileNode?.body?.[0]
180+
PRINT_VIEW_UNITS.forEach((id) => {
181+
if (!existingIds.has(id)) {
182+
printViewBody['trans-unit'].push({
183+
$: { id, datatype: 'html', resname: id },
184+
source: [PRINT_VIEW_SOURCES[id] ?? id],
185+
})
186+
}
187+
})
188+
88189
writeXlf(path, data)
89190
generateTestingLanguages(data)
90191
})

scripts/postbuild.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { renameSync, readFileSync } from 'fs'
1010
import { createShareAssetsFolder } from './moveToShareFolder.postbuild'
1111
import { addOneTrustNotAutoBlockForAppScripts } from './onetrust.postbuild'
1212
import { newRelic } from './new-relic.postbuild'
13+
import { localizeAndWritePrintViewScript } from './print-view-localize.postbuild'
1314

1415
const glob = require('glob')
1516
// Run updates on index.html files across languages
@@ -38,6 +39,11 @@ glob.sync('./dist/*/*.js').forEach((file) => {
3839
replacedHash[hash] = true
3940
})
4041

42+
// Translate and write the print-view script for every locale using
43+
// @angular/localize/tools so $localize calls are replaced with the
44+
// correct locale's strings at build time.
45+
localizeAndWritePrintViewScript()
46+
4147
// Replace all the `runtime*.js` references to match updated JS values with language code
4248
glob.sync('./dist/*/runtime*.js').forEach((file) => {
4349
const options = getOptionsObjet(file)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/**
2+
* Translates src/assets/print-view/fetch-orcid.js for every locale produced by
3+
* `ng build --localize` and writes the result to dist/<locale>/print-view/fetch-orcid.js.
4+
*
5+
* This is required because Angular's `scripts` bundle entries do not run through
6+
* the @angular/localize inlining pass. Instead, we use Babel +
7+
* makeEs2015TranslatePlugin to perform the same substitution here.
8+
*
9+
* Special cases:
10+
* - `en` (source locale): $localize calls are replaced with their English source text.
11+
* - Locales whose XLF filename differs from the folder name (pl→pl_PL, tr→tr_TR,
12+
* zh-CN→zh_CN, zh-TW→zh_TW) are handled via XLF_LOCALE_MAP.
13+
*/
14+
15+
import { existsSync, readFileSync, writeFileSync } from 'fs'
16+
import {
17+
makeEs2015TranslatePlugin,
18+
Xliff1TranslationParser,
19+
Diagnostics,
20+
} from '@angular/localize/tools'
21+
22+
// eslint-disable-next-line @typescript-eslint/no-var-requires
23+
const babel = require('@babel/core')
24+
// eslint-disable-next-line @typescript-eslint/no-var-requires
25+
const glob = require('glob')
26+
27+
/** Maps Angular locale folder name → XLF filename suffix when they differ. */
28+
const XLF_LOCALE_MAP: Record<string, string> = {
29+
pl: 'pl_PL',
30+
tr: 'tr_TR',
31+
'zh-CN': 'zh_CN',
32+
'zh-TW': 'zh_TW',
33+
src: 'source',
34+
}
35+
36+
/** Source file (pre-translation). */
37+
const PRINT_VIEW_SOURCE = './src/assets/print-view/fetch-orcid.js'
38+
39+
function xlfFileForLocale(locale: string): string {
40+
const suffix = XLF_LOCALE_MAP[locale] ?? locale
41+
return `./src/locale/messages.${suffix}.xlf`
42+
}
43+
44+
function getTranslations(locale: string): Record<string, any> | null {
45+
const xlf = xlfFileForLocale(locale)
46+
if (!existsSync(xlf)) {
47+
return null
48+
}
49+
const content = readFileSync(xlf, 'utf8')
50+
const parser = new Xliff1TranslationParser()
51+
const analyzed = (parser as any).analyze(xlf, content) as {
52+
canParse: boolean
53+
hint: any
54+
}
55+
if (!analyzed.canParse) {
56+
console.warn(
57+
`[print-view-localize] Could not parse XLF for locale "${locale}": ${xlf}`
58+
)
59+
return null
60+
}
61+
const { translations } = parser.parse(xlf, content, analyzed.hint)
62+
return translations
63+
}
64+
65+
export function localizeAndWritePrintViewScript(): void {
66+
const source = readFileSync(PRINT_VIEW_SOURCE, 'utf8')
67+
68+
// Process every dist locale folder (index.html is the canonical indicator
69+
// that the folder is a locale build output).
70+
const indexFiles: string[] = glob.sync('./dist/*/index.html')
71+
72+
for (const indexFile of indexFiles) {
73+
const localeFolderSegments = indexFile.split('/')
74+
// indexFile pattern: ./dist/<locale>/index.html
75+
const locale = localeFolderSegments[2]
76+
const localeFolder = localeFolderSegments.slice(0, 3).join('/')
77+
const destDir = `${localeFolder}/print-view`
78+
const destFile = `${destDir}/fetch-orcid.js`
79+
80+
let output: string
81+
82+
if (locale === 'share-assets') {
83+
// Not a locale folder — skip.
84+
continue
85+
}
86+
87+
const translations = getTranslations(locale)
88+
89+
if (!translations) {
90+
// No XLF for this locale (includes 'en' which is the source locale):
91+
// inline the source strings via Babel using an empty translation map and
92+
// missingTranslation:'ignore' so the source text is used as the fallback.
93+
const diagnostics = new Diagnostics()
94+
const result = babel.transformSync(source, {
95+
filename: PRINT_VIEW_SOURCE,
96+
plugins: [
97+
makeEs2015TranslatePlugin(
98+
diagnostics,
99+
{},
100+
{
101+
missingTranslation: 'ignore',
102+
}
103+
),
104+
],
105+
configFile: false,
106+
babelrc: false,
107+
})
108+
output = result?.code ?? source
109+
} else {
110+
const diagnostics = new Diagnostics()
111+
const result = babel.transformSync(source, {
112+
filename: PRINT_VIEW_SOURCE,
113+
plugins: [
114+
makeEs2015TranslatePlugin(diagnostics, translations, {
115+
missingTranslation: 'warning',
116+
}),
117+
],
118+
configFile: false,
119+
babelrc: false,
120+
})
121+
122+
if (diagnostics.hasErrors) {
123+
console.warn(
124+
`[print-view-localize] Errors for locale "${locale}":`,
125+
diagnostics.messages
126+
)
127+
}
128+
129+
output = result?.code ?? source
130+
}
131+
132+
writeFileSync(destFile, output, 'utf8')
133+
console.log(`[print-view-localize] ✓ ${destFile}`)
134+
135+
// Fix the lang attribute in the copied print-view/index.html.
136+
// The source file always has lang="en"; we rewrite it to the actual locale.
137+
const printViewIndexPath = `${destDir}/index.html`
138+
if (existsSync(printViewIndexPath)) {
139+
const htmlSource = readFileSync(printViewIndexPath, 'utf8')
140+
const htmlLocalized = htmlSource.replace(
141+
/<html([^>]*)lang="[^"]*"/,
142+
`<html$1lang="${locale}"`
143+
)
144+
if (htmlLocalized !== htmlSource) {
145+
writeFileSync(printViewIndexPath, htmlLocalized, 'utf8')
146+
console.log(
147+
`[print-view-localize] ✓ ${printViewIndexPath} (lang=${locale})`
148+
)
149+
}
150+
}
151+
}
152+
}

src/app/cdk/platform-info/supported-browsers.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
{
22
"chrome": {
3-
"major": 119,
3+
"major": 120,
44
"minor": 0
55
},
66
"firefox": {
7-
"major": 119,
7+
"major": 120,
88
"minor": 0
99
},
1010
"android": {
1111
"major": 145,
1212
"minor": 0
1313
},
1414
"edge": {
15-
"major": 119,
15+
"major": 120,
1616
"minor": 0
1717
},
1818
"safari": {
1919
"major": 17,
20-
"minor": 0
20+
"minor": 2
2121
},
2222
"op_mob": {
2323
"major": 80,
2424
"minor": 0
2525
},
2626
"opera": {
27-
"major": 105,
27+
"major": 106,
2828
"minor": 0
2929
},
3030
"samsung": {

0 commit comments

Comments
 (0)