Skip to content
Merged

PD-5670 #2850

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions SUPPORTED_BROWSERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
| Browser | Minimum version |
| ---------------- | --------------- |
| Android WebView | 145 or newer |
| Apple Safari | 17 or newer |
| Google Chrome | 119 or newer |
| Microsoft Edge | 119 or newer |
| Mozilla Firefox | 119 or newer |
| Opera | 105 or newer |
| Apple Safari | 17.2 or newer |
| Google Chrome | 120 or newer |
| Microsoft Edge | 120 or newer |
| Mozilla Firefox | 120 or newer |
| Opera | 106 or newer |
| Opera Mobile | 80 or newer |
| Samsung Internet | 25 or newer |
6 changes: 4 additions & 2 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,13 @@
{
"glob": "**/*",
"input": "src/assets/",
"ignore": ["fonts/**/*", "**/*.scss"],
"ignore": ["fonts/**/*", "**/*.scss", "**/*.spec.ts", "print-view/**"],
"output": "/assets/"
},
{
"glob": "**/*",
"input": "src/assets/print-view/",
"ignore": ["fetch-orcid.js", "**/*.spec.ts"],
"output": "/print-view/"
},
{
Expand Down Expand Up @@ -425,7 +426,8 @@
],
"scripts": [
"/scripts/environment.runtime.js",
"/scripts/onetrust.runtime.js"
"/scripts/onetrust.runtime.js",
"src/assets/print-view/fetch-orcid.js"
],
"assets": ["src/favicon.ico", "src/assets", "src/manifest.json"],
"sourceMap": true
Expand Down
101 changes: 101 additions & 0 deletions scripts/normalize-xlf.prebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,107 @@ function normalizeXlf12Sources(path: string) {
}
})

// Inject @@printView.* source-only trans-units so the test-language
// generator (generateTestingLanguages) will also stamp X / LR / RL for
// these strings, and so Transifex can discover them for real locales.
// We use a stable @@-prefixed id so $localize can match by explicit id.
const PRINT_VIEW_UNITS = [
'printView.unnamedProfile',
'printView.orcidIdAlt',
'printView.biography',
'printView.personalInformation',
'printView.emails',
'printView.websitesSocialLinks',
'printView.otherIds',
'printView.keywords',
'printView.countries',
'printView.activities',
'printView.employments',
'printView.educationAndQualifications',
'printView.professionalActivities',
'printView.fundings',
'printView.researchResources',
'printView.works',
'printView.organization',
'printView.organizationAddress',
'printView.startDate',
'printView.endDate',
'printView.publicationDate',
'printView.journal',
'printView.roleTitle',
'printView.department',
'printView.type',
'printView.url',
'printView.untitled',
'printView.identifier',
'printView.enterOrcidId',
'printView.orcidIdHelp',
'printView.loadProfile',
'printView.invalidOrcidId',
'printView.loadingRecord',
'printView.recordNotFound',
'printView.redirectingToPrimary',
'printView.fetchFailed',
'printView.couldNotLoad',
'printView.activityGroupHeading',
'printView.peerReviewHeading',
]
const PRINT_VIEW_SOURCES: Record<string, string> = {
'printView.unnamedProfile': 'Unnamed ORCID profile',
'printView.orcidIdAlt': 'ORCID iD',
'printView.biography': 'Biography',
'printView.personalInformation': 'Personal information',
'printView.emails': 'Emails',
'printView.websitesSocialLinks': 'Websites & social links',
'printView.otherIds': 'Other IDs',
'printView.keywords': 'Keywords',
'printView.countries': 'Countries',
'printView.activities': 'Activities',
'printView.employments': 'Employments',
'printView.educationAndQualifications': 'Education and qualifications',
'printView.professionalActivities': 'Professional activities',
'printView.fundings': 'Fundings',
'printView.researchResources': 'Research Resources',
'printView.works': 'Works',
'printView.organization': 'Organization',
'printView.organizationAddress': 'Organization address',
'printView.startDate': 'Start date',
'printView.endDate': 'End date',
'printView.publicationDate': 'Publication date',
'printView.journal': 'Journal',
'printView.roleTitle': 'Role title',
'printView.department': 'Department',
'printView.type': 'Type',
'printView.url': 'URL',
'printView.untitled': 'Untitled',
'printView.identifier': 'Identifier',
'printView.enterOrcidId': 'Enter an ORCID iD',
'printView.orcidIdHelp':
'Add an ORCID iD to the URL or use the form below.',
'printView.loadProfile': 'Load profile',
'printView.invalidOrcidId':
'Enter a valid ORCID iD (format: 0000-0000-0000-0000).',
'printView.loadingRecord': 'Loading ORCID record...',
'printView.recordNotFound':
'Record data was not found in ORCID response.',
'printView.redirectingToPrimary':
'Redirecting to primary ORCID record\u2026',
'printView.fetchFailed': 'Failed to fetch ORCID record',
'printView.couldNotLoad': 'Could not load',
'printView.activityGroupHeading': 'Activity group heading',
'printView.peerReviewHeading': 'Peer review heading',
}
const existingIds = new Set(transUnits.map((tu: any) => tu?.$?.id))
const printViewBody = fileNode?.body?.[0]
PRINT_VIEW_UNITS.forEach((id) => {
if (!existingIds.has(id)) {
printViewBody['trans-unit'].push({
$: { id, datatype: 'html', resname: id },
source: [PRINT_VIEW_SOURCES[id] ?? id],
})
}
})

writeXlf(path, data)
generateTestingLanguages(data)
})
Expand Down
6 changes: 6 additions & 0 deletions scripts/postbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { renameSync, readFileSync } from 'fs'
import { createShareAssetsFolder } from './moveToShareFolder.postbuild'
import { addOneTrustNotAutoBlockForAppScripts } from './onetrust.postbuild'
import { newRelic } from './new-relic.postbuild'
import { localizeAndWritePrintViewScript } from './print-view-localize.postbuild'

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

// Translate and write the print-view script for every locale using
// @angular/localize/tools so $localize calls are replaced with the
// correct locale's strings at build time.
localizeAndWritePrintViewScript()

// Replace all the `runtime*.js` references to match updated JS values with language code
glob.sync('./dist/*/runtime*.js').forEach((file) => {
const options = getOptionsObjet(file)
Expand Down
152 changes: 152 additions & 0 deletions scripts/print-view-localize.postbuild.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* Translates src/assets/print-view/fetch-orcid.js for every locale produced by
* `ng build --localize` and writes the result to dist/<locale>/print-view/fetch-orcid.js.
*
* This is required because Angular's `scripts` bundle entries do not run through
* the @angular/localize inlining pass. Instead, we use Babel +
* makeEs2015TranslatePlugin to perform the same substitution here.
*
* Special cases:
* - `en` (source locale): $localize calls are replaced with their English source text.
* - Locales whose XLF filename differs from the folder name (pl→pl_PL, tr→tr_TR,
* zh-CN→zh_CN, zh-TW→zh_TW) are handled via XLF_LOCALE_MAP.
*/

import { existsSync, readFileSync, writeFileSync } from 'fs'
import {
makeEs2015TranslatePlugin,
Xliff1TranslationParser,
Diagnostics,
} from '@angular/localize/tools'

// eslint-disable-next-line @typescript-eslint/no-var-requires
const babel = require('@babel/core')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const glob = require('glob')

/** Maps Angular locale folder name → XLF filename suffix when they differ. */
const XLF_LOCALE_MAP: Record<string, string> = {
pl: 'pl_PL',
tr: 'tr_TR',
'zh-CN': 'zh_CN',
'zh-TW': 'zh_TW',
src: 'source',
}

/** Source file (pre-translation). */
const PRINT_VIEW_SOURCE = './src/assets/print-view/fetch-orcid.js'

function xlfFileForLocale(locale: string): string {
const suffix = XLF_LOCALE_MAP[locale] ?? locale
return `./src/locale/messages.${suffix}.xlf`
}

function getTranslations(locale: string): Record<string, any> | null {
const xlf = xlfFileForLocale(locale)
if (!existsSync(xlf)) {
return null
}
const content = readFileSync(xlf, 'utf8')
const parser = new Xliff1TranslationParser()
const analyzed = (parser as any).analyze(xlf, content) as {
canParse: boolean
hint: any
}
if (!analyzed.canParse) {
console.warn(
`[print-view-localize] Could not parse XLF for locale "${locale}": ${xlf}`
)
return null
}
const { translations } = parser.parse(xlf, content, analyzed.hint)
return translations
}

export function localizeAndWritePrintViewScript(): void {
const source = readFileSync(PRINT_VIEW_SOURCE, 'utf8')

// Process every dist locale folder (index.html is the canonical indicator
// that the folder is a locale build output).
const indexFiles: string[] = glob.sync('./dist/*/index.html')

for (const indexFile of indexFiles) {
const localeFolderSegments = indexFile.split('/')
// indexFile pattern: ./dist/<locale>/index.html
const locale = localeFolderSegments[2]
const localeFolder = localeFolderSegments.slice(0, 3).join('/')
const destDir = `${localeFolder}/print-view`
const destFile = `${destDir}/fetch-orcid.js`

let output: string

if (locale === 'share-assets') {
// Not a locale folder — skip.
continue
}

const translations = getTranslations(locale)

if (!translations) {
// No XLF for this locale (includes 'en' which is the source locale):
// inline the source strings via Babel using an empty translation map and
// missingTranslation:'ignore' so the source text is used as the fallback.
const diagnostics = new Diagnostics()
const result = babel.transformSync(source, {
filename: PRINT_VIEW_SOURCE,
plugins: [
makeEs2015TranslatePlugin(
diagnostics,
{},
{
missingTranslation: 'ignore',
}
),
],
configFile: false,
babelrc: false,
})
output = result?.code ?? source
} else {
const diagnostics = new Diagnostics()
const result = babel.transformSync(source, {
filename: PRINT_VIEW_SOURCE,
plugins: [
makeEs2015TranslatePlugin(diagnostics, translations, {
missingTranslation: 'warning',
}),
],
configFile: false,
babelrc: false,
})

if (diagnostics.hasErrors) {
console.warn(
`[print-view-localize] Errors for locale "${locale}":`,
diagnostics.messages
)
}

output = result?.code ?? source
}

writeFileSync(destFile, output, 'utf8')
console.log(`[print-view-localize] ✓ ${destFile}`)

// Fix the lang attribute in the copied print-view/index.html.
// The source file always has lang="en"; we rewrite it to the actual locale.
const printViewIndexPath = `${destDir}/index.html`
if (existsSync(printViewIndexPath)) {
const htmlSource = readFileSync(printViewIndexPath, 'utf8')
const htmlLocalized = htmlSource.replace(
/<html([^>]*)lang="[^"]*"/,
`<html$1lang="${locale}"`
)
if (htmlLocalized !== htmlSource) {
writeFileSync(printViewIndexPath, htmlLocalized, 'utf8')
console.log(
`[print-view-localize] ✓ ${printViewIndexPath} (lang=${locale})`
)
}
}
}
}
10 changes: 5 additions & 5 deletions src/app/cdk/platform-info/supported-browsers.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
{
"chrome": {
"major": 119,
"major": 120,
"minor": 0
},
"firefox": {
"major": 119,
"major": 120,
"minor": 0
},
"android": {
"major": 145,
"minor": 0
},
"edge": {
"major": 119,
"major": 120,
"minor": 0
},
"safari": {
"major": 17,
"minor": 0
"minor": 2
},
"op_mob": {
"major": 80,
"minor": 0
},
"opera": {
"major": 105,
"major": 106,
"minor": 0
},
"samsung": {
Expand Down
Loading
Loading