mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 11:23:10 +02:00
Remove ambiguous translations and fix invalid translations (#4841)
# Description of Changes
`i18next` allows this pattern for translations, which we use quite a few
times in our current translation files:
```json
{
"a": {
"b": "hello"
},
"a.b": "world"
}
```
This makes it ambiguous when selecting `a.b` which string will be
retrieved. We have seen issues in other languages in the current release
like this:
<img width="325" height="249" alt="image"
src="https://github.com/user-attachments/assets/f24a29f0-550f-49b8-b355-c5e5eb436558"
/>
because we are expecting this:
<img width="1022" height="210" alt="image"
src="https://github.com/user-attachments/assets/b6d5cdd4-96cd-4b2b-8f1a-465da8bf70c8"
/>
but the Spanish file has:
<img width="312" height="136" alt="image"
src="https://github.com/user-attachments/assets/1e13392c-8484-47d1-b0c4-19d52b3ea5eb"
/>
and no `removeDigitalSignature` key on its own.
This PR resolves all of these ambiguities in the source by restructuring
all of the keys to uniquely target either an object or a string, not
both. It also adds a test which will fail on any keys with a `.` in
their name, therefore making it impossible to add anything ambiguous.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const LOCALES_DIR = path.join(__dirname, '../../../public/locales');
|
||||
|
||||
const getLocaleDirectories = () => {
|
||||
if (!fs.existsSync(LOCALES_DIR)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return fs.readdirSync(LOCALES_DIR, { withFileTypes: true })
|
||||
.filter(dirent => dirent.isDirectory())
|
||||
.map(dirent => dirent.name);
|
||||
};
|
||||
|
||||
const findDottedKeys = (node: unknown, segments: string[] = []): string[] => {
|
||||
if (!node || typeof node !== 'object') {
|
||||
return [];
|
||||
}
|
||||
|
||||
const issues: string[] = [];
|
||||
for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
|
||||
if (key.includes('.')) {
|
||||
issues.push([...segments, key].join('.'));
|
||||
}
|
||||
issues.push(...findDottedKeys(value, [...segments, key]));
|
||||
}
|
||||
return issues;
|
||||
};
|
||||
|
||||
const localeDirectories = getLocaleDirectories();
|
||||
|
||||
describe('Translation key structure', () => {
|
||||
test('should locate locales directory', () => {
|
||||
expect(fs.existsSync(LOCALES_DIR)).toBe(true);
|
||||
});
|
||||
|
||||
test('should have at least one locale directory', () => {
|
||||
expect(localeDirectories.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test.each(localeDirectories)('should not contain dotted keys in %s/translation.json', (localeDir) => {
|
||||
const translationFile = path.join(LOCALES_DIR, localeDir, 'translation.json');
|
||||
expect(fs.existsSync(translationFile)).toBe(true);
|
||||
|
||||
const data = JSON.parse(fs.readFileSync(translationFile, 'utf8'));
|
||||
const dottedKeys = findDottedKeys(data);
|
||||
expect(dottedKeys, `Dotted keys found in ${localeDir}: ${dottedKeys.join(', ')}`).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user