Skip to content

Commit 89cafb2

Browse files
author
Eric Amodio
committed
Localizes timeline strings
1 parent 5e80bf4 commit 89cafb2

5 files changed

Lines changed: 134 additions & 110 deletions

File tree

extensions/git/src/commands.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -430,25 +430,25 @@ export class CommandCenter {
430430
case Status.INDEX_MODIFIED:
431431
case Status.INDEX_RENAMED:
432432
case Status.INDEX_ADDED:
433-
return `${basename} (Index)`;
433+
return localize('git.title.index', '{0} (Index)', basename);
434434

435435
case Status.MODIFIED:
436436
case Status.BOTH_ADDED:
437437
case Status.BOTH_MODIFIED:
438-
return `${basename} (Working Tree)`;
438+
return localize('git.title.workingTree', '{0} (Working Tree)', basename);
439439

440440
case Status.DELETED_BY_US:
441-
return `${basename} (Theirs)`;
441+
return localize('git.title.theirs', '{0} (Theirs)', basename);
442442

443443
case Status.DELETED_BY_THEM:
444-
return `${basename} (Ours)`;
444+
return localize('git.title.ours', '{0} (Ours)', basename);
445445

446446
case Status.UNTRACKED:
447+
return localize('git.title.untracked', '{0} (Untracked)', basename);
447448

448-
return `${basename} (Untracked)`;
449+
default:
450+
return '';
449451
}
450-
451-
return '';
452452
}
453453

454454
@command('git.clone')
@@ -2348,12 +2348,12 @@ export class CommandCenter {
23482348

23492349
let title;
23502350
if ((item.previousRef === 'HEAD' || item.previousRef === '~') && item.ref === '') {
2351-
title = `${basename} (Working Tree)`;
2351+
title = localize('git.title.workingTree', '{0} (Working Tree)', basename);
23522352
}
23532353
else if (item.previousRef === 'HEAD' && item.ref === '~') {
2354-
title = `${basename} (Index)`;
2354+
title = localize('git.title.index', '{0} (Index)', basename);
23552355
} else {
2356-
title = `${basename} (${item.shortPreviousRef}) \u27f7 ${basename} (${item.shortRef})`;
2356+
title = localize('git.title.diffRefs', '{0} ({1}) \u27f7 {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
23572357
}
23582358

23592359
return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title);

extensions/git/src/repository.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,29 @@ export const enum ResourceGroupType {
4040

4141
export class Resource implements SourceControlResourceState {
4242

43+
static getStatusText(type: Status) {
44+
switch (type) {
45+
case Status.INDEX_MODIFIED: return localize('index modified', "Index Modified");
46+
case Status.MODIFIED: return localize('modified', "Modified");
47+
case Status.INDEX_ADDED: return localize('index added', "Index Added");
48+
case Status.INDEX_DELETED: return localize('index deleted', "Index Deleted");
49+
case Status.DELETED: return localize('deleted', "Deleted");
50+
case Status.INDEX_RENAMED: return localize('index renamed', "Index Renamed");
51+
case Status.INDEX_COPIED: return localize('index copied', "Index Copied");
52+
case Status.UNTRACKED: return localize('untracked', "Untracked");
53+
case Status.IGNORED: return localize('ignored', "Ignored");
54+
case Status.INTENT_TO_ADD: return localize('intent to add', "Intent to Add");
55+
case Status.BOTH_DELETED: return localize('both deleted', "Both Deleted");
56+
case Status.ADDED_BY_US: return localize('added by us', "Added By Us");
57+
case Status.DELETED_BY_THEM: return localize('deleted by them', "Deleted By Them");
58+
case Status.ADDED_BY_THEM: return localize('added by them', "Added By Them");
59+
case Status.DELETED_BY_US: return localize('deleted by us', "Deleted By Us");
60+
case Status.BOTH_ADDED: return localize('both added', "Both Added");
61+
case Status.BOTH_MODIFIED: return localize('both modified', "Both Modified");
62+
default: return '';
63+
}
64+
}
65+
4366
@memoize
4467
get resourceUri(): Uri {
4568
if (this.renameResourceUri && (this._type === Status.MODIFIED || this._type === Status.DELETED || this._type === Status.INDEX_RENAMED || this._type === Status.INDEX_COPIED)) {
@@ -110,26 +133,7 @@ export class Resource implements SourceControlResourceState {
110133
}
111134

112135
private get tooltip(): string {
113-
switch (this.type) {
114-
case Status.INDEX_MODIFIED: return localize('index modified', "Index Modified");
115-
case Status.MODIFIED: return localize('modified', "Modified");
116-
case Status.INDEX_ADDED: return localize('index added', "Index Added");
117-
case Status.INDEX_DELETED: return localize('index deleted', "Index Deleted");
118-
case Status.DELETED: return localize('deleted', "Deleted");
119-
case Status.INDEX_RENAMED: return localize('index renamed', "Index Renamed");
120-
case Status.INDEX_COPIED: return localize('index copied', "Index Copied");
121-
case Status.UNTRACKED: return localize('untracked', "Untracked");
122-
case Status.IGNORED: return localize('ignored', "Ignored");
123-
case Status.INTENT_TO_ADD: return localize('intent to add', "Intent to Add");
124-
case Status.BOTH_DELETED: return localize('both deleted', "Both Deleted");
125-
case Status.ADDED_BY_US: return localize('added by us', "Added By Us");
126-
case Status.DELETED_BY_THEM: return localize('deleted by them', "Deleted By Them");
127-
case Status.ADDED_BY_THEM: return localize('added by them', "Added By Them");
128-
case Status.DELETED_BY_US: return localize('deleted by us', "Deleted By Us");
129-
case Status.BOTH_ADDED: return localize('both added', "Both Added");
130-
case Status.BOTH_MODIFIED: return localize('both modified', "Both Modified");
131-
default: return '';
132-
}
136+
return Resource.getStatusText(this.type);
133137
}
134138

135139
private get strikeThrough(): boolean {

extensions/git/src/timelineProvider.ts

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as nls from 'vscode-nls';
67
import * as dayjs from 'dayjs';
78
import * as advancedFormat from 'dayjs/plugin/advancedFormat';
89
import { CancellationToken, Disposable, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode';
910
import { Model } from './model';
10-
import { Repository } from './repository';
11+
import { Repository, Resource } from './repository';
1112
import { debounce } from './decorators';
12-
import { Status } from './api/git';
1313

1414
dayjs.extend(advancedFormat);
1515

16-
// TODO[ECA]: Localize all the strings
16+
const localize = nls.loadMessageBundle();
17+
1718
// TODO[ECA]: Localize or use a setting for date format
1819

1920
export class GitTimelineItem extends TimelineItem {
@@ -68,7 +69,7 @@ export class GitTimelineProvider implements TimelineProvider {
6869
}
6970

7071
readonly id = 'git-history';
71-
readonly label = 'Git History';
72+
readonly label = localize('git.timeline.source', 'Git History');
7273

7374
private _disposable: Disposable;
7475

@@ -171,38 +172,18 @@ export class GitTimelineProvider implements TimelineProvider {
171172
});
172173

173174
if (options.cursor === undefined || options.before) {
175+
const you = localize('git.timeline.you', 'You');
176+
174177
const index = repo.indexGroup.resourceStates.find(r => r.resourceUri.fsPath === uri.fsPath);
175178
if (index) {
176179
const date = this._repoStatusDate ?? new Date();
177180
dateFormatter = dayjs(date);
178181

179-
let status;
180-
switch (index.type) {
181-
case Status.INDEX_MODIFIED:
182-
status = 'Modified';
183-
break;
184-
case Status.INDEX_ADDED:
185-
status = 'Added';
186-
break;
187-
case Status.INDEX_DELETED:
188-
status = 'Deleted';
189-
break;
190-
case Status.INDEX_RENAMED:
191-
status = 'Renamed';
192-
break;
193-
case Status.INDEX_COPIED:
194-
status = 'Copied';
195-
break;
196-
default:
197-
status = '';
198-
break;
199-
}
200-
201-
const item = new GitTimelineItem('~', 'HEAD', 'Staged Changes', date.getTime(), 'index', 'git:file:index');
182+
const item = new GitTimelineItem('~', 'HEAD', localize('git.timeline.stagedChanges', 'Staged Changes'), date.getTime(), 'index', 'git:file:index');
202183
// TODO[ECA]: Replace with a better icon -- reflecting its status maybe?
203184
item.iconPath = new (ThemeIcon as any)('git-commit');
204-
item.description = 'You';
205-
item.detail = `You \u2014 Index\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n${status}`;
185+
item.description = you;
186+
item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format('MMMM Do, YYYY h:mma'), Resource.getStatusText(index.type));
206187
item.command = {
207188
title: 'Open Comparison',
208189
command: 'git.timeline.openDiff',
@@ -217,33 +198,11 @@ export class GitTimelineProvider implements TimelineProvider {
217198
const date = new Date();
218199
dateFormatter = dayjs(date);
219200

220-
let status;
221-
switch (working.type) {
222-
case Status.INDEX_MODIFIED:
223-
status = 'Modified';
224-
break;
225-
case Status.INDEX_ADDED:
226-
status = 'Added';
227-
break;
228-
case Status.INDEX_DELETED:
229-
status = 'Deleted';
230-
break;
231-
case Status.INDEX_RENAMED:
232-
status = 'Renamed';
233-
break;
234-
case Status.INDEX_COPIED:
235-
status = 'Copied';
236-
break;
237-
default:
238-
status = '';
239-
break;
240-
}
241-
242-
const item = new GitTimelineItem('', index ? '~' : 'HEAD', 'Uncommited Changes', date.getTime(), 'working', 'git:file:working');
201+
const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommited Changes'), date.getTime(), 'working', 'git:file:working');
243202
// TODO[ECA]: Replace with a better icon -- reflecting its status maybe?
244203
item.iconPath = new (ThemeIcon as any)('git-commit');
245-
item.description = 'You';
246-
item.detail = `You \u2014 Working Tree\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n${status}`;
204+
item.description = you;
205+
item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format('MMMM Do, YYYY h:mma'), Resource.getStatusText(working.type));
247206
item.command = {
248207
title: 'Open Comparison',
249208
command: 'git.timeline.openDiff',

src/vs/base/common/date.ts

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { pad } from './strings';
7+
import { localize } from 'vs/nls';
78

89
const minute = 60;
910
const hour = minute * 60;
@@ -12,44 +13,106 @@ const week = day * 7;
1213
const month = day * 30;
1314
const year = day * 365;
1415

15-
// TODO[ECA]: Localize strings
1616
export function fromNow(date: number | Date, appendAgoLabel?: boolean): string {
1717
if (typeof date !== 'number') {
1818
date = date.getTime();
1919
}
2020

2121
const seconds = Math.round((new Date().getTime() - date) / 1000);
2222
if (seconds < 30) {
23-
return 'now';
23+
return localize('date.fromNow.now', 'now');
2424
}
2525

2626
let value: number;
27-
let unit: string;
2827
if (seconds < minute) {
2928
value = seconds;
30-
unit = 'sec';
31-
} else if (seconds < hour) {
29+
30+
if (appendAgoLabel) {
31+
return value === 1
32+
? localize('date.fromNow.seconds.singular.ago', '{0} sec ago', value)
33+
: localize('date.fromNow.seconds.plural.ago', '{0} secs ago', value);
34+
} else {
35+
return value === 1
36+
? localize('date.fromNow.seconds.singular', '{0} sec', value)
37+
: localize('date.fromNow.seconds.plural', '{0} secs', value);
38+
}
39+
}
40+
41+
if (seconds < hour) {
3242
value = Math.floor(seconds / minute);
33-
unit = 'min';
34-
} else if (seconds < day) {
43+
if (appendAgoLabel) {
44+
return value === 1
45+
? localize('date.fromNow.minutes.singular.ago', '{0} min ago', value)
46+
: localize('date.fromNow.minutes.plural.ago', '{0} mins ago', value);
47+
} else {
48+
return value === 1
49+
? localize('date.fromNow.minutes.singular', '{0} min', value)
50+
: localize('date.fromNow.minutes.plural', '{0} mins', value);
51+
}
52+
}
53+
54+
if (seconds < day) {
3555
value = Math.floor(seconds / hour);
36-
unit = 'hr';
37-
} else if (seconds < week) {
56+
if (appendAgoLabel) {
57+
return value === 1
58+
? localize('date.fromNow.hours.singular.ago', '{0} hr ago', value)
59+
: localize('date.fromNow.hours.plural.ago', '{0} hrs ago', value);
60+
} else {
61+
return value === 1
62+
? localize('date.fromNow.hours.singular', '{0} hr', value)
63+
: localize('date.fromNow.hours.plural', '{0} hrs', value);
64+
}
65+
}
66+
67+
if (seconds < week) {
3868
value = Math.floor(seconds / day);
39-
unit = 'day';
40-
} else if (seconds < month) {
69+
if (appendAgoLabel) {
70+
return value === 1
71+
? localize('date.fromNow.days.singular.ago', '{0} day ago', value)
72+
: localize('date.fromNow.days.plural.ago', '{0} days ago', value);
73+
} else {
74+
return value === 1
75+
? localize('date.fromNow.days.singular', '{0} day', value)
76+
: localize('date.fromNow.days.plural', '{0} days', value);
77+
}
78+
}
79+
80+
if (seconds < month) {
4181
value = Math.floor(seconds / week);
42-
unit = 'wk';
43-
} else if (seconds < year) {
44-
value = Math.floor(seconds / month);
45-
unit = 'mo';
46-
} else {
47-
value = Math.floor(seconds / year);
48-
unit = 'yr';
82+
if (appendAgoLabel) {
83+
return value === 1
84+
? localize('date.fromNow.weeks.singular.ago', '{0} wk ago', value)
85+
: localize('date.fromNow.weeks.plural.ago', '{0} wks ago', value);
86+
} else {
87+
return value === 1
88+
? localize('date.fromNow.weeks.singular', '{0} wk', value)
89+
: localize('date.fromNow.weeks.plural', '{0} wks', value);
90+
}
4991
}
5092

51-
return `${value} ${unit}${value === 1 ? '' : 's'}${appendAgoLabel ? ' ago' : ''}`;
93+
if (seconds < year) {
94+
value = Math.floor(seconds / month);
95+
if (appendAgoLabel) {
96+
return value === 1
97+
? localize('date.fromNow.months.singular.ago', '{0} mo ago', value)
98+
: localize('date.fromNow.months.plural.ago', '{0} mos ago', value);
99+
} else {
100+
return value === 1
101+
? localize('date.fromNow.months.singular', '{0} mo', value)
102+
: localize('date.fromNow.months.plural', '{0} mos', value);
103+
}
104+
}
52105

106+
value = Math.floor(seconds / year);
107+
if (appendAgoLabel) {
108+
return value === 1
109+
? localize('date.fromNow.years.singular.ago', '{0} yr ago', value)
110+
: localize('date.fromNow.years.plural.ago', '{0} yrs ago', value);
111+
} else {
112+
return value === 1
113+
? localize('date.fromNow.years.singular', '{0} yr', value)
114+
: localize('date.fromNow.years.plural', '{0} yrs', value);
115+
}
53116
}
54117

55118
export function toLocalISOString(date: Date): string {

0 commit comments

Comments
 (0)