Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sort sensitivity opt-in and configurable #41

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading