From c30b269b412c3f996b2f0383a6f0efd3424c4ca2 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 2 Mar 2022 16:06:14 -0500 Subject: [PATCH] Fixes #1859 adds defaultDateLocale setting --- CHANGELOG.md | 5 +++++ README.md | 21 +++++++++++---------- package.json | 26 ++++++++++++++++++-------- src/config.ts | 1 + src/extension.ts | 10 ++++++++++ src/system/date.ts | 30 ++++++++++++++++++++++-------- src/views/branchesView.ts | 1 + src/views/commitsView.ts | 1 + src/views/contributorsView.ts | 1 + src/views/fileHistoryView.ts | 1 + src/views/lineHistoryView.ts | 1 + src/views/remotesView.ts | 1 + src/views/repositoriesView.ts | 1 + src/views/searchAndCompareView.ts | 1 + src/views/stashesView.ts | 1 + src/views/tagsView.ts | 1 + src/views/worktreesView.ts | 1 + 17 files changed, 78 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a7d78..3a700d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Added + +- Adds `gitlens.defaultDateFormat` setting to specify the locale, a [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag), to use for date formatting + ### Changes - Removes dependency on GitKraken Authentication extension ### Fixed +- Fixes [#1859](https://github.com/gitkraken/vscode-gitlens/issues/1859) - GitLens dates use system locale instead of vscode language setting - Fixes [#1854](https://github.com/gitkraken/vscode-gitlens/issues/1854) - All repos have the same name - Fixes [#1866](https://github.com/gitkraken/vscode-gitlens/issues/1866) - Copy SHA and Copy Message don't work from the views (commits, branches, etc) - Fixes [#1865](https://github.com/gitkraken/vscode-gitlens/issues/1865) - Value shortOffset out of range for Intl.DateTimeFormat options property timeZoneName diff --git a/README.md b/README.md index 889ec51..4beb2bb 100644 --- a/README.md +++ b/README.md @@ -708,7 +708,7 @@ GitLens is highly customizable and provides many configuration settings to allow | Name | Description | | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `gitlens.currentLine.dateFormat` | Specifies how to format absolute dates (e.g. using the `${date}` token) for the current line blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats | +| `gitlens.currentLine.dateFormat` | Specifies how to format absolute dates (e.g. using the `${date}` token) for the current line blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats | | `gitlens.currentLine.enabled` | Specifies whether to provide a blame annotation for the current line, by default. Use the _Toggle Line Blame Annotations_ command (`gitlens.toggleLineBlame`) to toggle the annotations on and off for the current window | | `gitlens.currentLine.format` | Specifies the format of the current line blame annotation. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `gitlens.currentLine.dateFormat` setting | | `gitlens.currentLine.pullRequests.enabled` | Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the current line blame annotation. Requires a connection to a supported remote service (e.g. GitHub) | @@ -733,7 +733,7 @@ GitLens is highly customizable and provides many configuration settings to allow | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `gitlens.statusBar.alignment` | Specifies the blame alignment in the status bar

`left` - aligns to the left
`right` - aligns to the right | | `gitlens.statusBar.command` | Specifies the command to be executed when the blame status bar item is clicked

`gitlens.toggleFileBlame` - toggles file blame annotations
`gitlens.toggleFileHeatmap` - toggles file heatmap
`gitlens.toggleFileChanges` - toggles file changes since before the commit
`gitlens.toggleFileChangesOnly` - toggles file changes from the commit
`gitlens.diffWithPrevious` - opens changes with the previous revision
`gitlens.revealCommitInView` - reveals the commit in the Side Bar
`gitlens.showCommitsInView` - searches for commits within the range
`gitlens.showQuickCommitDetails` - shows details of the commit
`gitlens.showQuickCommitFileDetails` - show file details of the commit
`gitlens.showQuickFileHistory` - shows the current file history
`gitlens.showQuickRepoHistory` - shows the current branch history
`gitlens.openCommitOnRemote` - opens the commit on the remote service (when available)
`gitlens.copyRemoteCommitUrl` - copies the remote commit url to the clipboard (when available)
`gitlens.openFileOnRemote` - opens the file revision on the remote service (when available)
`gitlens.copyRemoteFileUrl` - copies the remote file url to the clipboard (when available) | -| `gitlens.statusBar.dateFormat` | Specifies how to format absolute dates (e.g. using the `${date}` token) in the blame information in the status bar. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats | +| `gitlens.statusBar.dateFormat` | Specifies how to format absolute dates (e.g. using the `${date}` token) in the blame information in the status bar. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats | | `gitlens.statusBar.enabled` | Specifies whether to provide blame information in the status bar | | `gitlens.statusBar.format` | Specifies the format of the blame information in the status bar. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `gitlens.statusBar.dateFormat` setting | | `gitlens.statusBar.pullRequests.enabled` | Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the status bar. Requires a connection to a supported remote service (e.g. GitHub) | @@ -943,7 +943,7 @@ See also [View Settings](#view-settings- 'Jump to the View settings') | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `gitlens.blame.avatars` | Specifies whether to show avatar images in the gutter blame annotations | | `gitlens.blame.compact` | Specifies whether to compact (deduplicate) matching adjacent gutter blame annotations | -| `gitlens.blame.dateFormat` | Specifies how to format absolute dates (e.g. using the `${date}` token) in gutter blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats | +| `gitlens.blame.dateFormat` | Specifies how to format absolute dates (e.g. using the `${date}` token) in gutter blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats | | `gitlens.blame.format` | Specifies the format of the gutter blame annotations. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `gitlens.blame.dateFormat` setting | | `gitlens.blame.heatmap.enabled` | Specifies whether to provide a heatmap indicator in the gutter blame annotations | | `gitlens.blame.heatmap.location` | Specifies where the heatmap indicators will be shown in the gutter blame annotations

`left` - adds a heatmap indicator on the left edge of the gutter blame annotations
`right` - adds a heatmap indicator on the right edge of the gutter blame annotations | @@ -997,13 +997,14 @@ See also [View Settings](#view-settings- 'Jump to the View settings') ## Date & Time Settings [#](#date--time-settings- 'Date & Time Settings') -| Name | Description | -| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `gitlens.defaultDateFormat` | Specifies how absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats | -| `gitlens.defaultDateShortFormat` | Specifies how short absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats | -| `gitlens.defaultDateSource` | Specifies whether commit dates should use the authored or committed date | -| `gitlens.defaultDateStyle` | Specifies how dates will be displayed by default | -| `gitlens.defaultTimeFormat` | Specifies how times will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats | +| Name | Description | +| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `gitlens.defaultDateFormat` | Specifies how absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats | +| `gitlens.defaultDateLocale` | Specifies the locale, a [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag), to use for date formatting. For example: 'en-US' = US English, 'en-GB' = British English, 'de-DE' = German, 'ko-KR' = Korean, 'ar-EG' = Arabic, 'ja-JP = Japanese, etc. | +| `gitlens.defaultDateShortFormat` | Specifies how short absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats | +| `gitlens.defaultDateSource` | Specifies whether commit dates should use the authored or committed date | +| `gitlens.defaultDateStyle` | Specifies how dates will be displayed by default | +| `gitlens.defaultTimeFormat` | Specifies how times will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats | ## Menu & Toolbar Settings [#](#menu--toolbar-settings- 'Menu & Toolbar Settings') diff --git a/package.json b/package.json index 1b4b52a..529000a 100644 --- a/package.json +++ b/package.json @@ -256,7 +256,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) for the current line blame annotation. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) for the current line blame annotation. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", "scope": "window", "order": 50 } @@ -450,7 +450,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates in the Git CodeLens. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies how to format absolute dates in the Git CodeLens. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", "scope": "window", "order": 73 }, @@ -567,7 +567,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in the blame information in the status bar. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in the blame information in the status bar. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", "scope": "window", "order": 80 } @@ -1932,7 +1932,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in gutter blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in gutter blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", "scope": "window", "order": 80 } @@ -2433,27 +2433,37 @@ "null" ], "default": null, - "markdownDescription": "Specifies how absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies how absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", "scope": "window", "order": 20 }, - "gitlens.defaultDateShortFormat": { + "gitlens.defaultDateLocale": { "type": [ "string", "null" ], "default": null, - "markdownDescription": "Specifies how short absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies the locale, a [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag), to use for date formatting. For example: 'en-US' = US English, 'en-GB' = British English, 'de-DE' = German, 'ko-KR' = Korean, 'ar-EG' = Arabic, 'ja-JP = Japanese, etc.", "scope": "window", "order": 21 }, + "gitlens.defaultDateShortFormat": { + "type": [ + "string", + "null" + ], + "default": null, + "markdownDescription": "Specifies how short absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "scope": "window", + "order": 22 + }, "gitlens.defaultTimeFormat": { "type": [ "string", "null" ], "default": null, - "markdownDescription": "Specifies how times will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for valid formats", + "markdownDescription": "Specifies how times will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", "scope": "window", "order": 30 }, diff --git a/src/config.ts b/src/config.ts index 89d51ab..8aec948 100644 --- a/src/config.ts +++ b/src/config.ts @@ -35,6 +35,7 @@ export interface Config { }; debug: boolean; defaultDateFormat: DateTimeFormat | string | null; + defaultDateLocale: string | null; defaultDateShortFormat: DateTimeFormat | string | null; defaultDateSource: DateSource; defaultDateStyle: DateStyle; diff --git a/src/extension.ts b/src/extension.ts index 2cb2a32..2fb6212 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,6 +14,7 @@ import { Messages } from './messages'; import { registerPartnerActionRunners } from './partners'; import { StorageKeys, SyncedStorageKeys } from './storage'; import { executeCommand, registerCommands } from './system/command'; +import { setDefaultDateLocales } from './system/date'; import { once } from './system/event'; import { Stopwatch } from './system/stopwatch'; import { compare } from './system/version'; @@ -95,6 +96,15 @@ export async function activate(context: ExtensionContext): Promise { + if (!e.affectsConfiguration('gitlens.defaultDateLocale')) return; + setDefaultDateLocales(configuration.get('defaultDateLocale')); + }), + ); + // await migrateSettings(context, previousVersion); const container = Container.create(context, cfg); diff --git a/src/system/date.ts b/src/system/date.ts index d477980..ba3f992 100644 --- a/src/system/date.ts +++ b/src/system/date.ts @@ -1,11 +1,7 @@ // NOTE@eamodio If this changes we need to update the replacement function too (since its parameter number/order relies on the matching) const customDateTimeFormatParserRegex = /(?\[.*?\])|(?YYYY|YY)|(?M{1,4})|(?Do|DD?)|(?d{2,4})|(?HH?|hh?)|(?mm?)|(?ss?)|(?SSS)|(?A|a)|(?ZZ?)/g; -const dateTimeFormatCache = new Map(); const dateTimeFormatRegex = /(?full|long|medium|short)(?:\+(?full|long|medium|short))?/; -let defaultRelativeTimeFormat: InstanceType | undefined; -let defaultShortRelativeTimeFormat: InstanceType | undefined; -let locale: string | undefined; const relativeUnitThresholds: [Intl.RelativeTimeFormatUnit, number, string][] = [ ['year', 24 * 60 * 60 * 1000 * 365, 'yr'], ['month', (24 * 60 * 60 * 1000 * 365) / 12, 'mo'], @@ -20,6 +16,24 @@ type DateStyle = 'full' | 'long' | 'medium' | 'short'; type TimeStyle = 'full' | 'long' | 'medium' | 'short'; export type DateTimeFormat = DateStyle | `${DateStyle}+${TimeStyle}`; +let locale: string | undefined; +const dateTimeFormatCache = new Map(); +let defaultLocales: string[] | undefined; +let defaultRelativeTimeFormat: InstanceType | undefined; +let defaultShortRelativeTimeFormat: InstanceType | undefined; + +export function setDefaultDateLocales(locales: string | string[] | null | undefined) { + if (typeof locales === 'string') { + defaultLocales = [locales]; + } else { + defaultLocales = locales ?? undefined; + } + defaultRelativeTimeFormat = undefined; + defaultShortRelativeTimeFormat = undefined; + dateTimeFormatCache.clear(); + locale = undefined; +} + export function createFromDateDelta( date: Date, delta: { years?: number; months?: number; days?: number; hours?: number; minutes?: number; seconds?: number }, @@ -67,7 +81,7 @@ export function fromNow(date: Date, short?: boolean): string { } else if (defaultRelativeTimeFormat != null) { locale = defaultRelativeTimeFormat.resolvedOptions().locale; } else { - defaultShortRelativeTimeFormat = new Intl.RelativeTimeFormat(undefined, { + defaultShortRelativeTimeFormat = new Intl.RelativeTimeFormat(defaultLocales, { localeMatcher: 'best fit', numeric: 'always', style: 'narrow', @@ -82,7 +96,7 @@ export function fromNow(date: Date, short?: boolean): string { } if (defaultShortRelativeTimeFormat == null) { - defaultShortRelativeTimeFormat = new Intl.RelativeTimeFormat(undefined, { + defaultShortRelativeTimeFormat = new Intl.RelativeTimeFormat(defaultLocales, { localeMatcher: 'best fit', numeric: 'always', style: 'narrow', @@ -93,7 +107,7 @@ export function fromNow(date: Date, short?: boolean): string { } if (defaultRelativeTimeFormat == null) { - defaultRelativeTimeFormat = new Intl.RelativeTimeFormat(undefined, { + defaultRelativeTimeFormat = new Intl.RelativeTimeFormat(defaultLocales, { localeMatcher: 'best fit', numeric: 'auto', style: 'long', @@ -112,7 +126,7 @@ export function formatDate(date: Date, format: 'full' | 'long' | 'medium' | 'sho let formatter = dateTimeFormatCache.get(format); if (formatter == null) { const options = getDateTimeFormatOptionsFromFormatString(format); - formatter = new Intl.DateTimeFormat(undefined, options); + formatter = new Intl.DateTimeFormat(defaultLocales, options); dateTimeFormatCache.set(format, formatter); } diff --git a/src/views/branchesView.ts b/src/views/branchesView.ts index a63b69a..34b4b26 100644 --- a/src/views/branchesView.ts +++ b/src/views/branchesView.ts @@ -204,6 +204,7 @@ export class BranchesView extends ViewBase if ( !changed && !configuration.changed(e, 'defaultDateFormat') && + !configuration.changed(e, 'defaultDateLocale') && !configuration.changed(e, 'defaultDateShortFormat') && !configuration.changed(e, 'defaultDateSource') && !configuration.changed(e, 'defaultDateStyle') && diff --git a/src/views/commitsView.ts b/src/views/commitsView.ts index f74e188..4d623b9 100644 --- a/src/views/commitsView.ts +++ b/src/views/commitsView.ts @@ -271,6 +271,7 @@ export class CommitsView extends ViewBase { if ( !changed && !configuration.changed(e, 'defaultDateFormat') && + !configuration.changed(e, 'defaultDateLocale') && !configuration.changed(e, 'defaultDateShortFormat') && !configuration.changed(e, 'defaultDateSource') && !configuration.changed(e, 'defaultDateStyle') && diff --git a/src/views/contributorsView.ts b/src/views/contributorsView.ts index e039501..b68fab3 100644 --- a/src/views/contributorsView.ts +++ b/src/views/contributorsView.ts @@ -204,6 +204,7 @@ export class ContributorsView extends ViewBase { if ( !changed && !configuration.changed(e, 'defaultDateFormat') && + !configuration.changed(e, 'defaultDateLocale') && !configuration.changed(e, 'defaultDateShortFormat') && !configuration.changed(e, 'defaultDateSource') && !configuration.changed(e, 'defaultDateStyle') && diff --git a/src/views/repositoriesView.ts b/src/views/repositoriesView.ts index e89caf7..213282a 100644 --- a/src/views/repositoriesView.ts +++ b/src/views/repositoriesView.ts @@ -265,6 +265,7 @@ export class RepositoriesView extends ViewBase { if ( !changed && !configuration.changed(e, 'defaultDateFormat') && + !configuration.changed(e, 'defaultDateLocale') && !configuration.changed(e, 'defaultDateShortFormat') && !configuration.changed(e, 'defaultDateSource') && !configuration.changed(e, 'defaultDateStyle') && diff --git a/src/views/tagsView.ts b/src/views/tagsView.ts index 2e46c15..4651f87 100644 --- a/src/views/tagsView.ts +++ b/src/views/tagsView.ts @@ -166,6 +166,7 @@ export class TagsView extends ViewBase { if ( !changed && !configuration.changed(e, 'defaultDateFormat') && + !configuration.changed(e, 'defaultDateLocale') && !configuration.changed(e, 'defaultDateShortFormat') && !configuration.changed(e, 'defaultDateSource') && !configuration.changed(e, 'defaultDateStyle') && diff --git a/src/views/worktreesView.ts b/src/views/worktreesView.ts index bbe0582..22a69d5 100644 --- a/src/views/worktreesView.ts +++ b/src/views/worktreesView.ts @@ -247,6 +247,7 @@ export class WorktreesView extends ViewBase