Skip to content

Commit 9df6950

Browse files
authored
Merge pull request #5737 from HSLdevcom/add-translation-sorting
AB#542 - Add translation sorting script, add format script, and change lint script to only check
2 parents 1e6ed97 + 8521d07 commit 9df6950

3 files changed

Lines changed: 116 additions & 6 deletions

File tree

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,15 @@
3030
"test:update-all-desktop-snapshots": "CONFIG=hsl yarn test:update-snapshots && CONFIG=tampere yarn test:update-snapshots && CONFIG=matka yarn test:update-snapshots",
3131
"test:update-all-mobile-snapshots": "MOBILE=true CONFIG=hsl yarn test:update-snapshots && MOBILE=true CONFIG=tampere yarn test:update-snapshots && MOBILE=true CONFIG=matka yarn test:update-snapshots",
3232
"test:update-all-snapshots": "yarn test:update-all-desktop-snapshots && yarn test:update-all-mobile-snapshots",
33-
"es-lint": "eslint .",
34-
"lint": "yarn run es-lint && yarn run prettier-styles && yarn run stylelint",
35-
"prettier-styles": "prettier sass/**/*.scss app/**/*.scss digitransit-component/**/*.scss --fix --write",
33+
"lint": "yarn run eslint && yarn run prettier-styles && yarn run stylelint",
34+
"format": "yarn run sort-translations && yarn run eslint-fix && yarn run prettier-styles-fix && yarn run stylelint-fix",
35+
"sort-translations": "node scripts/sort-translations.mjs",
36+
"eslint": "eslint .",
37+
"eslint-fix": "eslint . --fix",
38+
"prettier-styles": "prettier sass/**/*.scss app/**/*.scss digitransit-component/**/*.scss --check",
39+
"prettier-styles-fix": "prettier sass/**/*.scss app/**/*.scss digitransit-component/**/*.scss --write",
3640
"stylelint": "stylelint sass/**/*.scss app/**/*.scss digitransit-component/**/*.scss",
41+
"stylelint-fix": "stylelint sass/**/*.scss app/**/*.scss digitransit-component/**/*.scss --fix",
3742
"build": "NODE_OPTIONS=--openssl-legacy-provider && NODE_ENV=production && yarn prebuild && node --max_old_space_size=4096 node_modules/.bin/webpack --progress --color",
3843
"build-workspaces": "yarn build-components && yarn build-search-utils && yarn build-store",
3944
"start": "NODE_ENV=production node $NODE_OPTS server/server",

scripts/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
# Using scripts
1+
# Scripts
2+
3+
## Using `sort-translations.js`
4+
5+
This script sorts translation files in the [`app/translations`](/app/translations) directory.
6+
See the `sort-translations` and `format` scripts in [`package.json`](/package.json).
7+
8+
## Using `ui.sh`
29

310
See the `themeMap` in `app/configurations/config.default.js` for configuration options.
411

5-
## Before using
12+
### Before using
613
```
714
source ui.sh
815
```
9-
## Usage examples
16+
### Usage examples
1017

1118
Using remote instance of OTP with subscription key:
1219
```

scripts/sort-translations.mjs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env node
2+
/* eslint-disable no-console */
3+
4+
import fs from 'fs';
5+
import path from 'path';
6+
7+
const TRANSLATIONS_DIR = path.resolve(
8+
import.meta.dirname,
9+
'../app/translations',
10+
);
11+
const PRINT_WIDTH = 80;
12+
13+
function needsQuoting(key) {
14+
return !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
15+
}
16+
17+
function formatKey(key) {
18+
return needsQuoting(key) ? `'${key}'` : key;
19+
}
20+
21+
function formatValue(value) {
22+
const escaped = value
23+
.replace(/\\/g, '\\\\')
24+
.replace(/\n/g, '\\n')
25+
.replace(/\r/g, '\\r')
26+
.replace(/\t/g, '\\t');
27+
// Use double quotes when value contains a single quote to avoid escaping
28+
if (escaped.includes("'")) {
29+
return `"${escaped.replace(/"/g, '\\"')}"`;
30+
}
31+
return `'${escaped}'`;
32+
}
33+
34+
function sortedTranslationsFileContent(lang, translations) {
35+
const lines = [];
36+
lines.push('/* eslint sort-keys: "error" */');
37+
lines.push('export default {');
38+
lines.push(` ${formatKey(lang)}: {`);
39+
40+
const keys = Object.keys(translations).sort();
41+
for (let j = 0; j < keys.length; j++) {
42+
const key = keys[j];
43+
const formattedKey = formatKey(key);
44+
const formattedValue = formatValue(translations[key]);
45+
const singleLine = ` ${formattedKey}: ${formattedValue},`;
46+
if (singleLine.length <= PRINT_WIDTH) {
47+
lines.push(singleLine);
48+
} else {
49+
lines.push(` ${formattedKey}:`);
50+
lines.push(` ${formattedValue},`);
51+
}
52+
}
53+
54+
lines.push(' },');
55+
lines.push('};');
56+
lines.push('');
57+
58+
return lines.join('\n');
59+
}
60+
61+
async function main() {
62+
try {
63+
console.log('---------- Running sort-translations.mjs script ----------');
64+
65+
const files = fs
66+
.readdirSync(TRANSLATIONS_DIR)
67+
.filter(f => f.endsWith('.js'))
68+
.sort();
69+
70+
for (let i = 0; i < files.length; i++) {
71+
const file = files[i];
72+
const filePath = path.join(TRANSLATIONS_DIR, file);
73+
console.log('Processing file', filePath);
74+
// eslint-disable-next-line no-await-in-loop
75+
const module = await import(filePath);
76+
const langData = module.default;
77+
const lang = Object.keys(langData)[0];
78+
const sorted = sortedTranslationsFileContent(lang, langData[lang]);
79+
80+
try {
81+
fs.writeFileSync(filePath, sorted, 'utf-8');
82+
console.log('Sorted translations written to', filePath);
83+
} catch (error) {
84+
const message = error instanceof Error ? error.message : String(error);
85+
console.error(
86+
`Failed to write sorted translations to ${filePath}: ${message}`,
87+
);
88+
process.exitCode = 1;
89+
}
90+
}
91+
} catch (error) {
92+
const message = error instanceof Error ? error.message : String(error);
93+
console.error(`Failed to process translations: ${message}`);
94+
process.exitCode = 1;
95+
}
96+
}
97+
98+
main();

0 commit comments

Comments
 (0)