Chore/v2/translation fixes (#5011)

# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Reece Browne 2025-11-25 20:03:47 +00:00 committed by GitHub
parent d74856f675
commit 53d167eda5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 369 additions and 80 deletions

View File

@ -70,7 +70,7 @@
},
"devDependencies": {
"@eslint/js": "^9.36.0",
"@iconify-json/material-symbols": "^1.2.37",
"@iconify-json/material-symbols": "^1.2.48",
"@iconify/utils": "^3.0.2",
"@playwright/test": "^1.55.0",
"@tauri-apps/cli": "^2.5.0",
@ -455,7 +455,6 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
},
@ -499,7 +498,6 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@ -580,7 +578,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/core/-/core-1.4.1.tgz",
"integrity": "sha512-TGpxn2CvAKRnOJWJ3bsK+dKBiCp75ehxftRUmv7wAmPomhnG5XrDfoWJungvO+zbbqAwso6PocdeXINVt3hlAw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/engines": "1.4.1",
"@embedpdf/models": "1.4.1"
@ -680,7 +677,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-history/-/plugin-history-1.4.1.tgz",
"integrity": "sha512-5WLDiNMH6tACkLGGv/lJtNsDeozOhSbrh0mjD1btHun8u7Yscu/Vf8tdJRUOsd+nULivo2nQ2NFNKu0OTbVo8w==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -697,7 +693,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-interaction-manager/-/plugin-interaction-manager-1.4.1.tgz",
"integrity": "sha512-Ng02S9SFIAi9JZS5rI+NXSnZZ1Yk9YYRw4MlN2pig49qOyivZdz0oScZaYxQPewo8ccJkLeghjdeWswOBW/6cA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -715,7 +710,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-loader/-/plugin-loader-1.4.1.tgz",
"integrity": "sha512-m3ZOk8JygsLxoa4cZ+0BVB5pfRWuBCg2/gPqjhoFZNKTqAFw4J6HGUrhYKg94GRYe+w1cTJl/NbTBYuU5DOrsA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -752,7 +746,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-render/-/plugin-render-1.4.1.tgz",
"integrity": "sha512-gKCdNKw6WBHBEpTc2DLBWIWOxzsNnaNbpfeY6C4f2Bum0EO+XW3Hl2oIx1uaRHjIhhnXso1J3QweqelsPwDGwg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -787,7 +780,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-scroll/-/plugin-scroll-1.4.1.tgz",
"integrity": "sha512-Y9O+matB4j4fLim5s/jn7qIi+lMC9vmDJRpJhiWe8bvD9oYLP2xfD/DdhFgAjRKcNhPoxC+j8q8QN5BMeGAv2Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -824,7 +816,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-selection/-/plugin-selection-1.4.1.tgz",
"integrity": "sha512-lo5Ytk1PH0PrRKv6zKVupm4t02VGsqIrnSIeP6NO8Ujx0wfqEhj//sqIuO/EwfFVJD8lcQIP9UUo9y8baCrEog==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -900,7 +891,6 @@
"resolved": "https://registry.npmjs.org/@embedpdf/plugin-viewport/-/plugin-viewport-1.4.1.tgz",
"integrity": "sha512-+TgFHKPCLTBiDYe2DdsmTS37hwQgcZ3dYIc7bE0l5cp+GVwouu1h0MTmjL+90loizeWwCiu10E/zXR6hz+CUaQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@embedpdf/models": "1.4.1"
},
@ -1056,7 +1046,6 @@
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@ -1100,7 +1089,6 @@
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@ -1896,9 +1884,9 @@
}
},
"node_modules/@iconify-json/material-symbols": {
"version": "1.2.44",
"resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.2.44.tgz",
"integrity": "sha512-NAJjhswaK9FxBeIzFFsNygws7wHtmAkBWhF4YEwn1NZIMbA+LNITqhUiq6sP5mOdKQqnoritFTlQaZ47a5BgBg==",
"version": "1.2.48",
"resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.2.48.tgz",
"integrity": "sha512-qDjqYEeNCm31tae3YbsprEklWHIoVPvqlbTuqtisNjlhHRSiXy5x+AtUq9VwjlITRU+TtqsP6jW2h+pnEUURRQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@ -2131,7 +2119,6 @@
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.6.tgz",
"integrity": "sha512-paTl+0x+O/QtgMtqVJaG8maD8sfiOdgPmLOyG485FmeGZ1L3KMdEkhxZtmdGlDFsLXhmMGQ57ducT90bvhXX5A==",
"license": "MIT",
"peer": true,
"dependencies": {
"@floating-ui/react": "^0.27.16",
"clsx": "^2.1.1",
@ -2182,7 +2169,6 @@
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.6.tgz",
"integrity": "sha512-liHfaWXHAkLjJy+Bkr29UsCwAoDQ/a64WrM67lksx8F0qqyjR5RQH8zVlhuOjdpQnwtlUkE/YiTvbJiPcoI0bw==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"react": "^18.x || ^19.x"
}
@ -2250,7 +2236,6 @@
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.5.tgz",
"integrity": "sha512-8VVxFmp1GIm9PpmnQoCoYo0UWHoOrdA57tDL62vkpzEgvb/d71Wsbv4FRg7r1Gyx7PuSo0tflH34cdl/NvfHNQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.28.4",
"@mui/core-downloads-tracker": "^7.3.5",
@ -3183,7 +3168,6 @@
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.9.0.tgz",
"integrity": "sha512-ggs5k+/0FUJcIgNY08aZTqpBTtbExkJMYMLSMwyucrhtWexVOEY1KJmhBsxf+E/Q15f5rbwBpj+t0t2AW2oCsQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12.16"
}
@ -3302,6 +3286,7 @@
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.6.tgz",
"integrity": "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"acorn": "^8.9.0"
}
@ -4078,7 +4063,6 @@
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@ -4407,7 +4391,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@ -4418,7 +4401,6 @@
"integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==",
"dev": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@ -4488,7 +4470,6 @@
"integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.3",
"@typescript-eslint/types": "8.46.3",
@ -5202,6 +5183,7 @@
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.24.tgz",
"integrity": "sha512-BM8kBhtlkkbnyl4q+HiF5R5BL0ycDPfihowulm02q3WYp2vxgPcJuZO866qa/0u3idbMntKEtVNuAUp5bw4teg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/shared": "3.5.24"
}
@ -5211,6 +5193,7 @@
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.24.tgz",
"integrity": "sha512-RYP/byyKDgNIqfX/gNb2PB55dJmM97jc9wyF3jK7QUInYKypK2exmZMNwnjueWwGceEkP6NChd3D2ZVEp9undQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.5.24",
"@vue/shared": "3.5.24"
@ -5221,6 +5204,7 @@
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.24.tgz",
"integrity": "sha512-Z8ANhr/i0XIluonHVjbUkjvn+CyrxbXRIxR7wn7+X7xlcb7dJsfITZbkVOeJZdP8VZwfrWRsWdShH6pngMxRjw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.5.24",
"@vue/runtime-core": "3.5.24",
@ -5233,6 +5217,7 @@
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.24.tgz",
"integrity": "sha512-Yh2j2Y4G/0/4z/xJ1Bad4mxaAk++C2v4kaa8oSYTMJBJ00/ndPuxCnWeot0/7/qafQFLh5pr6xeV6SdMcE/G1w==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-ssr": "3.5.24",
"@vue/shared": "3.5.24"
@ -5259,7 +5244,6 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -5667,6 +5651,7 @@
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">= 0.4"
}
@ -5943,7 +5928,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751",
@ -7000,8 +6984,7 @@
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1521046.tgz",
"integrity": "sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==",
"dev": true,
"license": "BSD-3-Clause",
"peer": true
"license": "BSD-3-Clause"
},
"node_modules/dezalgo": {
"version": "1.0.4",
@ -7396,7 +7379,6 @@
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@ -7567,7 +7549,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@ -7734,7 +7715,8 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/espree": {
"version": "10.4.0",
@ -7799,6 +7781,7 @@
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.2.tgz",
"integrity": "sha512-DgvlIQeowRNyvLPWW4PT7Gu13WznY288Du086E751mwwbsgr29ytBiYeLzAGIo0qk3Ujob0SDk8TiSaM5WQzNg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
}
@ -8889,7 +8872,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.27.6"
},
@ -9375,6 +9357,7 @@
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "^1.0.6"
}
@ -9695,7 +9678,6 @@
"integrity": "sha512-Pcfm3eZ+eO4JdZCXthW9tCDT3nF4K+9dmeZ+5X39n+Kqz0DDIABRP5CAEOHRFZk8RGuC2efksTJxrjp8EXCunQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@acemir/cssom": "^0.9.19",
"@asamuzakjp/dom-selector": "^6.7.3",
@ -10282,7 +10264,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/locate-path": {
"version": "6.0.0",
@ -11470,7 +11453,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@ -11750,7 +11732,6 @@
"resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz",
"integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
@ -12133,7 +12114,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@ -12143,7 +12123,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@ -13643,6 +13622,7 @@
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">= 0.4"
}
@ -13851,7 +13831,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -14153,7 +14132,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -14235,7 +14213,6 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"peer": true,
"dependencies": {
"napi-postinstall": "^0.3.0"
},
@ -14440,7 +14417,6 @@
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@ -14592,7 +14568,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -14606,7 +14581,6 @@
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/expect": "3.2.4",
@ -15218,7 +15192,8 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/zod": {
"version": "3.25.76",

View File

@ -33,12 +33,12 @@
"@mantine/dates": "^8.3.1",
"@mantine/dropzone": "^8.3.1",
"@mantine/hooks": "^8.3.1",
"@stripe/react-stripe-js": "^4.0.2",
"@stripe/stripe-js": "^7.9.0",
"@supabase/supabase-js": "^2.47.13",
"@mui/icons-material": "^7.3.2",
"@mui/material": "^7.3.2",
"@reactour/tour": "^3.8.0",
"@stripe/react-stripe-js": "^4.0.2",
"@stripe/stripe-js": "^7.9.0",
"@supabase/supabase-js": "^2.47.13",
"@tailwindcss/postcss": "^4.1.13",
"@tanstack/react-virtual": "^3.13.12",
"@tauri-apps/api": "^2.5.0",
@ -57,8 +57,8 @@
"posthog-js": "^1.268.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-rnd": "^10.5.2",
"react-i18next": "^15.7.3",
"react-rnd": "^10.5.2",
"react-router-dom": "^7.9.1",
"signature_pad": "^5.0.4",
"tailwindcss": "^4.1.13",
@ -117,7 +117,7 @@
},
"devDependencies": {
"@eslint/js": "^9.36.0",
"@iconify-json/material-symbols": "^1.2.37",
"@iconify-json/material-symbols": "^1.2.48",
"@iconify/utils": "^3.0.2",
"@playwright/test": "^1.55.0",
"@tauri-apps/cli": "^2.5.0",

View File

@ -4059,7 +4059,8 @@
},
"languages": {
"label": "Available Languages",
"description": "Languages that users can select from (leave empty to enable all languages)"
"description": "Languages that users can select from (leave empty to enable all languages)",
"placeholder": "Select languages"
},
"customMetadata": {
"label": "Custom Metadata",
@ -4084,7 +4085,9 @@
"label": "Logo Style",
"description": "Set the default logo style for all users on this server. Users can override this setting in their personal preferences.",
"classic": "Classic",
"modern": "Modern"
"classicAlt": "Classic logo",
"modern": "Modern",
"modernAlt": "Modern logo"
},
"customPaths": {
"label": "Custom Paths",
@ -4992,7 +4995,16 @@
"config": {
"overview": {
"title": "Application Configuration",
"description": "Current application settings and configuration details."
"description": "Current application settings and configuration details.",
"loading": "Loading configuration...",
"error": "Error",
"warning": "Configuration Warning",
"sections": {
"basic": "Basic Configuration",
"security": "Security Configuration",
"system": "System Configuration",
"integration": "Integration Configuration"
}
},
"account": {
"overview": {
@ -5367,6 +5379,7 @@
"description": "Manage teams and organize workspace members",
"loading": "Loading teams...",
"loadingDetails": "Loading team details...",
"loadError": "Failed to load team details",
"createNewTeam": "Create New Team",
"teamName": "Team Name",
"totalMembers": "Total Members",
@ -5896,6 +5909,46 @@
}
},
"settings": {
"preferences": {
"title": "Preferences"
},
"workspace": {
"title": "Workspace",
"people": "People",
"teams": "Teams"
},
"configuration": {
"title": "Configuration",
"systemSettings": "System Settings",
"features": "Features",
"endpoints": "Endpoints",
"database": "Database",
"advanced": "Advanced"
},
"securityAuth": {
"title": "Security & Authentication",
"security": "Security",
"connections": "Connections"
},
"licensingAnalytics": {
"title": "Licensing & Analytics",
"plan": "Plan",
"audit": "Audit",
"usageAnalytics": "Usage Analytics"
},
"policiesPrivacy": {
"title": "Policies & Privacy",
"legal": "Legal",
"privacy": "Privacy"
},
"developer": {
"title": "Developer",
"apiKeys": "API Keys"
},
"tooltips": {
"enableLoginFirst": "Enable login mode first",
"requiresEnterprise": "Requires Enterprise license"
},
"connection": {
"title": "Connection Mode",
"mode": {
@ -5952,7 +6005,13 @@
"hideUnavailableConversionsDescription": "Remove disabled conversion options in the Convert tool instead of showing them greyed out."
},
"hotkeys": {
"title": "Keyboard Shortcuts",
"description": "Customize keyboard shortcuts for quick tool access. Click \"Change shortcut\" and press a new key combination. Press Esc to cancel.",
"errorConflict": "Shortcut already used by {{tool}}.",
"errorModifier": {
"mac": "Include ⌘ (Command), ⌥ (Option), or another modifier in your shortcut.",
"windows": "Include Ctrl, Alt, or another modifier in your shortcut."
},
"searchPlaceholder": "Search tools...",
"none": "Not assigned",
"customBadge": "Custom",

View File

@ -2,7 +2,7 @@ import React, { useMemo, useState, useEffect, useCallback } from 'react';
import { Modal, Text, ActionIcon, Tooltip, Group } from '@mantine/core';
import { useNavigate, useLocation } from 'react-router-dom';
import LocalIcon from '@app/components/shared/LocalIcon';
import { createConfigNavSections } from '@app/components/shared/config/configNavSections';
import { useConfigNavSections } from '@app/components/shared/config/configNavSections';
import { NavKey, VALID_NAV_KEYS } from '@app/components/shared/config/types';
import { useAppConfig } from '@app/contexts/AppConfigContext';
import '@app/components/shared/AppConfigModal.css';
@ -74,13 +74,10 @@ const AppConfigModalInner: React.FC<AppConfigModalProps> = ({ opened, onClose })
const loginEnabled = config?.enableLogin ?? false;
// Left navigation structure and icons
const configNavSections = useMemo(() =>
createConfigNavSections(
isAdmin,
runningEE,
loginEnabled
),
[isAdmin, runningEE, loginEnabled]
const configNavSections = useConfigNavSections(
isAdmin,
runningEE,
loginEnabled
);
const activeLabel = useMemo(() => {

View File

@ -1,4 +1,5 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { NavKey } from '@app/components/shared/config/types';
import HotkeysSection from '@app/components/shared/config/configSections/HotkeysSection';
import GeneralSection from '@app/components/shared/config/configSections/GeneralSection';
@ -27,11 +28,43 @@ export interface ConfigColors {
headerBorder: string;
}
export const useConfigNavSections = (
_isAdmin: boolean = false,
_runningEE: boolean = false,
_loginEnabled: boolean = false
): ConfigNavSection[] => {
const { t } = useTranslation();
const sections: ConfigNavSection[] = [
{
title: t('settings.preferences.title', 'Preferences'),
items: [
{
key: 'general',
label: t('settings.general.title', 'General'),
icon: 'settings-rounded',
component: <GeneralSection />
},
{
key: 'hotkeys',
label: t('settings.hotkeys.title', 'Keyboard Shortcuts'),
icon: 'keyboard-rounded',
component: <HotkeysSection />
},
],
},
];
return sections;
};
// Deprecated: Use useConfigNavSections hook instead
export const createConfigNavSections = (
_isAdmin: boolean = false,
_runningEE: boolean = false,
_loginEnabled: boolean = false
): ConfigNavSection[] => {
console.warn('createConfigNavSections is deprecated. Use useConfigNavSections hook instead for proper i18n support.');
const sections: ConfigNavSection[] = [
{
title: 'Preferences',

View File

@ -73,10 +73,7 @@ const HotkeysSection: React.FC = () => {
const binding = eventToBinding(event as KeyboardEvent);
if (!binding) {
const osKey = isMac ? 'mac' : 'windows';
const fallbackText = isMac
? 'Include ⌘ (Command), ⌥ (Option), or another modifier in your shortcut.'
: 'Include Ctrl, Alt, or another modifier in your shortcut.';
setError(t(`settings.hotkeys.errorModifier.${osKey}`, fallbackText));
setError(t(`settings.hotkeys.errorModifier.${osKey}`));
return;
}
@ -112,9 +109,9 @@ const HotkeysSection: React.FC = () => {
return (
<Stack gap="lg">
<div>
<Text fw={600} size="lg">Keyboard Shortcuts</Text>
<Text fw={600} size="lg">{t('settings.hotkeys.title', 'Keyboard Shortcuts')}</Text>
<Text size="sm" c="dimmed">
Customize keyboard shortcuts for quick tool access. Click "Change shortcut" and press a new key combination. Press Esc to cancel.
{t('settings.hotkeys.description', 'Customize keyboard shortcuts for quick tool access. Click "Change shortcut" and press a new key combination. Press Esc to cancel.')}
</Text>
</div>

View File

@ -1,9 +1,11 @@
import React from 'react';
import { Stack, Text, Code, Group, Badge, Alert, Loader } from '@mantine/core';
import { useTranslation } from 'react-i18next';
import { useAppConfig } from '@app/contexts/AppConfigContext';
import { OverviewHeader } from '@app/components/shared/config/OverviewHeader';
const Overview: React.FC = () => {
const { t } = useTranslation();
const { config, loading, error } = useAppConfig();
const renderConfigSection = (title: string, data: any) => {
@ -58,14 +60,14 @@ const Overview: React.FC = () => {
return (
<Stack align="center" py="md">
<Loader size="sm" />
<Text size="sm" c="dimmed">Loading configuration...</Text>
<Text size="sm" c="dimmed">{t('config.overview.loading', 'Loading configuration...')}</Text>
</Stack>
);
}
if (error) {
return (
<Alert color="red" title="Error">
<Alert color="red" title={t('config.overview.error', 'Error')}>
{error}
</Alert>
);
@ -77,13 +79,13 @@ const Overview: React.FC = () => {
{config && (
<>
{renderConfigSection('Basic Configuration', basicConfig)}
{renderConfigSection('Security Configuration', securityConfig)}
{renderConfigSection('System Configuration', systemConfig)}
{renderConfigSection('Integration Configuration', integrationConfig)}
{renderConfigSection(t('config.overview.sections.basic', 'Basic Configuration'), basicConfig)}
{renderConfigSection(t('config.overview.sections.security', 'Security Configuration'), securityConfig)}
{renderConfigSection(t('config.overview.sections.system', 'System Configuration'), systemConfig)}
{renderConfigSection(t('config.overview.sections.integration', 'Integration Configuration'), integrationConfig)}
{config.error && (
<Alert color="yellow" title="Configuration Warning">
<Alert color="yellow" title={t('config.overview.warning', 'Configuration Warning')}>
{config.error}
</Alert>
)}

View File

@ -1,8 +1,39 @@
import { createConfigNavSections as createProprietaryConfigNavSections } from '@proprietary/components/shared/config/configNavSections';
import { useTranslation } from 'react-i18next';
import { useConfigNavSections as useProprietaryConfigNavSections, createConfigNavSections as createProprietaryConfigNavSections } from '@proprietary/components/shared/config/configNavSections';
import { ConfigNavSection } from '@core/components/shared/config/configNavSections';
import { ConnectionSettings } from '@app/components/ConnectionSettings';
/**
* Hook version of desktop config nav sections with proper i18n support
*/
export const useConfigNavSections = (
isAdmin: boolean = false,
runningEE: boolean = false,
loginEnabled: boolean = false
): ConfigNavSection[] => {
const { t } = useTranslation();
// Get the proprietary sections (includes core Preferences + admin sections)
const sections = useProprietaryConfigNavSections(isAdmin, runningEE, loginEnabled);
// Add Connection section at the beginning (after Preferences)
sections.splice(1, 0, {
title: t('settings.connection.title', 'Connection Mode'),
items: [
{
key: 'connectionMode',
label: t('settings.connection.title', 'Connection Mode'),
icon: 'cloud-rounded',
component: <ConnectionSettings />,
},
],
});
return sections;
};
/**
* Deprecated: Use useConfigNavSections hook instead
* Desktop extension of createConfigNavSections that adds connection settings
*/
export const createConfigNavSections = (
@ -10,6 +41,8 @@ export const createConfigNavSections = (
runningEE: boolean = false,
loginEnabled: boolean = false
): ConfigNavSection[] => {
console.warn('createConfigNavSections is deprecated. Use useConfigNavSections hook instead for proper i18n support.');
// Get the proprietary sections (includes core Preferences + admin sections)
const sections = createProprietaryConfigNavSections(isAdmin, runningEE, loginEnabled);

View File

@ -1,5 +1,6 @@
import React from 'react';
import { createConfigNavSections as createCoreConfigNavSections, ConfigNavSection } from '@core/components/shared/config/configNavSections';
import { useTranslation } from 'react-i18next';
import { useConfigNavSections as useCoreConfigNavSections, createConfigNavSections as createCoreConfigNavSections, ConfigNavSection } from '@core/components/shared/config/configNavSections';
import PeopleSection from '@app/components/shared/config/configSections/PeopleSection';
import TeamsSection from '@app/components/shared/config/configSections/TeamsSection';
import AdminGeneralSection from '@app/components/shared/config/configSections/AdminGeneralSection';
@ -17,6 +18,196 @@ import AdminUsageSection from '@app/components/shared/config/configSections/Admi
import ApiKeys from '@app/components/shared/config/configSections/ApiKeys';
/**
* Hook version of proprietary config nav sections with proper i18n support
*/
export const useConfigNavSections = (
isAdmin: boolean = false,
runningEE: boolean = false,
loginEnabled: boolean = false
): ConfigNavSection[] => {
const { t } = useTranslation();
// Get the core sections (just Preferences)
const sections = useCoreConfigNavSections(isAdmin, runningEE, loginEnabled);
// Add Admin sections if user is admin OR if login is disabled (but mark as disabled)
if (isAdmin || !loginEnabled) {
const requiresLogin = !loginEnabled;
const enableLoginTooltip = t('settings.tooltips.enableLoginFirst', 'Enable login mode first');
const requiresEnterpriseTooltip = t('settings.tooltips.requiresEnterprise', 'Requires Enterprise license');
// Workspace
sections.push({
title: t('settings.workspace.title', 'Workspace'),
items: [
{
key: 'people',
label: t('settings.workspace.people', 'People'),
icon: 'group-rounded',
component: <PeopleSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'teams',
label: t('settings.workspace.teams', 'Teams'),
icon: 'groups-rounded',
component: <TeamsSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
],
});
// Configuration
sections.push({
title: t('settings.configuration.title', 'Configuration'),
items: [
{
key: 'adminGeneral',
label: t('settings.configuration.systemSettings', 'System Settings'),
icon: 'settings-rounded',
component: <AdminGeneralSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminFeatures',
label: t('settings.configuration.features', 'Features'),
icon: 'extension-rounded',
component: <AdminFeaturesSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminEndpoints',
label: t('settings.configuration.endpoints', 'Endpoints'),
icon: 'api-rounded',
component: <AdminEndpointsSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminDatabase',
label: t('settings.configuration.database', 'Database'),
icon: 'storage-rounded',
component: <AdminDatabaseSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminAdvanced',
label: t('settings.configuration.advanced', 'Advanced'),
icon: 'tune-rounded',
component: <AdminAdvancedSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
],
});
// Security & Authentication
sections.push({
title: t('settings.securityAuth.title', 'Security & Authentication'),
items: [
{
key: 'adminSecurity',
label: t('settings.securityAuth.security', 'Security'),
icon: 'shield-rounded',
component: <AdminSecuritySection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminConnections',
label: t('settings.securityAuth.connections', 'Connections'),
icon: 'link-rounded',
component: <AdminConnectionsSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
],
});
// Licensing & Analytics
sections.push({
title: t('settings.licensingAnalytics.title', 'Licensing & Analytics'),
items: [
{
key: 'adminPlan',
label: t('settings.licensingAnalytics.plan', 'Plan'),
icon: 'star-rounded',
component: <AdminPlanSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminAudit',
label: t('settings.licensingAnalytics.audit', 'Audit'),
icon: 'fact-check-rounded',
component: <AdminAuditSection />,
disabled: !runningEE || requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : requiresEnterpriseTooltip
},
{
key: 'adminUsage',
label: t('settings.licensingAnalytics.usageAnalytics', 'Usage Analytics'),
icon: 'analytics-rounded',
component: <AdminUsageSection />,
disabled: !runningEE || requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : requiresEnterpriseTooltip
},
],
});
// Policies & Privacy
sections.push({
title: t('settings.policiesPrivacy.title', 'Policies & Privacy'),
items: [
{
key: 'adminLegal',
label: t('settings.policiesPrivacy.legal', 'Legal'),
icon: 'gavel-rounded',
component: <AdminLegalSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
{
key: 'adminPrivacy',
label: t('settings.policiesPrivacy.privacy', 'Privacy'),
icon: 'visibility-rounded',
component: <AdminPrivacySection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
},
],
});
}
// Add Developer section if login is enabled
if (loginEnabled) {
const developerSection: ConfigNavSection = {
title: t('settings.developer.title', 'Developer'),
items: [
{
key: 'api-keys',
label: t('settings.developer.apiKeys', 'API Keys'),
icon: 'key-rounded',
component: <ApiKeys />
},
],
};
// Add Developer section after Preferences (or Workspace if it exists)
const insertIndex = isAdmin ? 2 : 1;
sections.splice(insertIndex, 0, developerSection);
}
return sections;
};
/**
* Deprecated: Use useConfigNavSections hook instead
* Proprietary extension of createConfigNavSections that adds all admin and workspace sections
*/
export const createConfigNavSections = (
@ -24,6 +215,8 @@ export const createConfigNavSections = (
runningEE: boolean = false,
loginEnabled: boolean = false
): ConfigNavSection[] => {
console.warn('createConfigNavSections is deprecated. Use useConfigNavSections hook instead for proper i18n support.');
// Get the core sections (just Preferences)
const sections = createCoreConfigNavSections(isAdmin, runningEE, loginEnabled);

View File

@ -336,7 +336,7 @@ export default function AdminGeneralSection() {
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', padding: '0.25rem 0' }}>
<img
src="/classic-logo/favicon.ico"
alt="Classic logo"
alt={t('admin.settings.general.logoStyle.classicAlt', 'Classic logo')}
style={{ width: '24px', height: '24px' }}
/>
<span>{t('admin.settings.general.logoStyle.classic', 'Classic')}</span>
@ -349,7 +349,7 @@ export default function AdminGeneralSection() {
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', padding: '0.25rem 0' }}>
<img
src="/modern-logo/StirlingPDFLogoNoTextLight.svg"
alt="Modern logo"
alt={t('admin.settings.general.logoStyle.modernAlt', 'Modern logo')}
style={{ width: '24px', height: '24px' }}
/>
<span>{t('admin.settings.general.logoStyle.modern', 'Modern')}</span>
@ -385,7 +385,7 @@ export default function AdminGeneralSection() {
]}
searchable
clearable
placeholder="Select languages"
placeholder={t('admin.settings.general.languages.placeholder', 'Select languages')}
comboboxProps={{ zIndex: 1400 }}
disabled={!loginEnabled}
/>

View File

@ -72,7 +72,7 @@ export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectio
});
} catch (error) {
console.error('Failed to fetch team details:', error);
alert({ alertType: 'error', title: 'Failed to load team details' });
alert({ alertType: 'error', title: t('workspace.teams.loadError', 'Failed to load team details') });
onBack();
} finally {
setLoading(false);