Skip to content

Commit bbd815b

Browse files
committed
Sort localizations by languages on add
1 parent 78a5303 commit bbd815b

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

src/commands/add.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ import { runAddCommand, StringsFormat } from '../utils/cli.js';
66
import logger from '../utils/logger.js';
77
import chalk from 'chalk';
88

9+
type LocalizationMap = NonNullable<XCStringUnit['localizations']>;
10+
11+
const sortLocalizations = (localizations: LocalizationMap): LocalizationMap => {
12+
const sorted = Object.entries(localizations)
13+
.sort(([langA], [langB]) => langA.localeCompare(langB, 'en', { sensitivity: 'case' }));
14+
return Object.fromEntries(sorted) as LocalizationMap;
15+
};
16+
917
export function createAddCommand(): CommandModule {
1018
return {
1119
command: 'add',
@@ -172,5 +180,9 @@ export async function add(
172180
}
173181

174182
data.strings[key] = unit;
183+
184+
if (unit.localizations) {
185+
unit.localizations = sortLocalizations(unit.localizations);
186+
}
175187
await writeXCStrings(path, data);
176188
}

tests/cli.add-state.single.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ describe('cli add: state (single)', () => {
4747
expect(content.strings['greeting-review'].localizations.ja.stringUnit.state).toBe('needs_review');
4848
});
4949

50+
it('sorts localizations alphabetically when adding default text with translations', async () => {
51+
const tempFile = await setupTempFile('no-strings.xcstrings');
52+
const tempConfigPath = resolve(tempFile + '.config.json');
53+
await writeFile(tempConfigPath, JSON.stringify({ missingLanguagePolicy: 'include' }), 'utf-8');
54+
55+
await runAddCommand({
56+
path: tempFile,
57+
key: 'greeting-order',
58+
comment: undefined,
59+
stringsArg: '{"ja":{"value":"こんにちは"},"de":{"value":"Hallo"}}',
60+
stringsFormat: 'json',
61+
defaultString: 'Hello',
62+
stdinReader: async () => Promise.resolve(''),
63+
configPath: tempConfigPath,
64+
});
65+
66+
const content = JSON.parse(await readFile(tempFile, 'utf-8'));
67+
const localizations = content.strings['greeting-order'].localizations;
68+
expect(Object.keys(localizations)).toEqual(['de', 'en', 'ja']);
69+
});
70+
5071
it('rejects invalid state values with a clear message', async () => {
5172
const tempFile = await setupTempFile('no-strings.xcstrings');
5273
const tempConfigPath = resolve(tempFile + '.config.json');

0 commit comments

Comments
 (0)