Skip to content

Commit

Permalink
feat: Make sort sensitivity opt-in and configurable (#41)
Browse files Browse the repository at this point in the history
Co-authored-by: Bjarne CALLEWAERT <[email protected]>
  • Loading branch information
bjarne-callewaert and Bjarne CALLEWAERT authored Jun 10, 2024
1 parent bd8f4e6 commit bfcdacb
Show file tree
Hide file tree
Showing 4 changed files with 432 additions and 14 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ If you want to use spaces instead, you can do the following:
ngx-translate-extract --input ./src --output ./src/i18n/en.json --format-indentation ' '
```

### Sorting

Extracted keys are by default not sorted. You can enable sorting by using the `--sort` or `-s` flag.

If sorting is enabled, the keys will be sorted using the default variant sort sensitivity. Other sort sensitivity options are also available using the `--sort-sensitivity` or `-ss` flag:
- `base`: Strings that differ in base letters are unequal. For example `a !== b`, `a === á`, `a === A`
- `accent`: Strings that differ in base letters and accents are unequal. For example `a !== b`, `a !== á`, `a === A`
- `case`: Strings that differ in base letters or casing are unequal. For example `a !== b`, `a === á`, `a !== A`
- `variant`: Strings that differ in base letters, accents, or casing are unequal. For example `a !== b`, `a !== á`, `a !== A`

### Marker function

If you want to extract strings that are not passed directly to `NgxTranslate.TranslateService`'s
Expand All @@ -110,6 +120,7 @@ Output
--format, -f Format [string] [choices: "json", "namespaced-json", "pot"] [default: "json"]
--format-indentation, --fi Format indentation (JSON/Namedspaced JSON) [string] [default: "\t"]
--sort, -s Sort strings in alphabetical order [boolean]
--sort-sensitivity, -ss Sensitivity when sorting strings (only when sort is enabled) [string]
--clean, -c Remove obsolete strings after merge [boolean]
--replace, -r Replace the contents of output file if it exists (Merges by default) [boolean]
--strip-prefix, -sp Strip prefix from key [string]
Expand Down
11 changes: 9 additions & 2 deletions src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ const cli = await y
describe: 'Sort strings in alphabetical order',
type: 'boolean'
})
.option('sort-sensitivity', {
alias: 'ss',
describe: 'Sort sensitivitiy of strings (only to be used when sorting)',
type: 'string',
choices: ['base', 'accent', 'case', 'variant'],
default: undefined
})
.option('clean', {
alias: 'c',
describe: 'Remove obsolete strings after merge',
Expand Down Expand Up @@ -125,7 +132,7 @@ const cli = await y
describe: 'Strip a prefix from the extracted key',
type: 'string'
})
.group(['format', 'format-indentation', 'sort', 'clean', 'replace', 'strip-prefix'], 'Output')
.group(['format', 'format-indentation', 'sort', 'sort-sensitivity', 'clean', 'replace', 'strip-prefix'], 'Output')
.group(['key-as-default-value', 'key-as-initial-default-value', 'null-as-default-value', 'string-as-default-value'], 'Extracted key value (defaults to empty string)')
.conflicts('key-as-default-value', 'null-as-default-value')
.conflicts('key-as-initial-default-value', 'null-as-default-value')
Expand Down Expand Up @@ -177,7 +184,7 @@ if (cli.stripPrefix) {
}

if (cli.sort) {
postProcessors.push(new SortByKeyPostProcessor());
postProcessors.push(new SortByKeyPostProcessor(cli.sortSensitivity));
}
extractTask.setPostProcessors(postProcessors);

Expand Down
18 changes: 17 additions & 1 deletion src/post-processors/sort-by-key.post-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,24 @@ import { PostProcessorInterface } from './post-processor.interface.js';
export class SortByKeyPostProcessor implements PostProcessorInterface {
public name: string = 'SortByKey';

// More information on sort sensitivity: https://tc39.es/ecma402/#sec-collator-comparestrings
// Passing undefined will be treated as 'variant' by default: https://tc39.es/ecma402/#sec-intl.collator
public sortSensitivity: 'base' | 'accent' | 'case' | 'variant' | undefined = undefined;

constructor(sortSensitivity: string | undefined) {
if (isOfTypeSortSensitivity(sortSensitivity)) {
this.sortSensitivity = sortSensitivity;
} else {
throw new Error(`Unknown sortSensitivity: ${sortSensitivity}`);
}
}

public process(draft: TranslationCollection, extracted: TranslationCollection, existing: TranslationCollection): TranslationCollection {
const compareFn = new Intl.Collator('en', {sensitivity: 'base'}).compare;
const compareFn = this.sortSensitivity ? new Intl.Collator('en', { sensitivity: this.sortSensitivity }).compare : undefined;
return draft.sort(compareFn);
}
}

function isOfTypeSortSensitivity(keyInput: string | undefined): keyInput is 'base' | 'accent' | 'case' | 'variant' | undefined {
return ['base', 'accent', 'case', 'variant'].includes(keyInput) || keyInput === undefined;
}
Loading

0 comments on commit bfcdacb

Please sign in to comment.