X Tutup
Skip to content

Commit 59629a0

Browse files
committed
feat(i18n): added i18nPlural and i18nSelect pipes
Closes angular#7268
1 parent b5e6319 commit 59629a0

File tree

8 files changed

+236
-30
lines changed

8 files changed

+236
-30
lines changed

modules/angular2/src/common/pipes.ts

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,6 @@
33
* @description
44
* This module provides a set of common Pipes.
55
*/
6-
import {AsyncPipe} from './pipes/async_pipe';
7-
import {UpperCasePipe} from './pipes/uppercase_pipe';
8-
import {LowerCasePipe} from './pipes/lowercase_pipe';
9-
import {JsonPipe} from './pipes/json_pipe';
10-
import {SlicePipe} from './pipes/slice_pipe';
11-
import {DatePipe} from './pipes/date_pipe';
12-
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
13-
import {ReplacePipe} from './pipes/replace_pipe';
14-
import {CONST_EXPR} from 'angular2/src/facade/lang';
156

167
export {AsyncPipe} from './pipes/async_pipe';
178
export {DatePipe} from './pipes/date_pipe';
@@ -21,23 +12,6 @@ export {LowerCasePipe} from './pipes/lowercase_pipe';
2112
export {NumberPipe, DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
2213
export {UpperCasePipe} from './pipes/uppercase_pipe';
2314
export {ReplacePipe} from './pipes/replace_pipe';
24-
25-
/**
26-
* A collection of Angular core pipes that are likely to be used in each and every
27-
* application.
28-
*
29-
* This collection can be used to quickly enumerate all the built-in pipes in the `pipes`
30-
* property of the `@Component` or `@View` decorators.
31-
*/
32-
export const COMMON_PIPES = CONST_EXPR([
33-
AsyncPipe,
34-
UpperCasePipe,
35-
LowerCasePipe,
36-
JsonPipe,
37-
SlicePipe,
38-
DecimalPipe,
39-
PercentPipe,
40-
CurrencyPipe,
41-
DatePipe,
42-
ReplacePipe
43-
]);
15+
export {I18nPluralPipe} from './pipes/i18n_plural_pipe';
16+
export {I18nSelectPipe} from './pipes/i18n_select_pipe';
17+
export {COMMON_PIPES} from './pipes/common_pipes';

modules/angular2/src/common/pipes/common_pipes.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {SlicePipe} from './slice_pipe';
1111
import {DatePipe} from './date_pipe';
1212
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
1313
import {ReplacePipe} from './replace_pipe';
14+
import {I18nPluralPipe} from './i18n_plural_pipe';
15+
import {I18nSelectPipe} from './i18n_select_pipe';
1416
import {CONST_EXPR} from 'angular2/src/facade/lang';
1517

1618
/**
@@ -30,5 +32,7 @@ export const COMMON_PIPES = CONST_EXPR([
3032
PercentPipe,
3133
CurrencyPipe,
3234
DatePipe,
33-
ReplacePipe
35+
ReplacePipe,
36+
I18nPluralPipe,
37+
I18nSelectPipe
3438
]);
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
CONST,
3+
isStringMap,
4+
StringWrapper,
5+
isPresent,
6+
RegExpWrapper
7+
} from 'angular2/src/facade/lang';
8+
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
9+
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
10+
11+
var interpolationExp: RegExp = RegExpWrapper.create('#');
12+
13+
/**
14+
*
15+
* Maps a value to a string that pluralizes the value properly.
16+
*
17+
* ## Usage
18+
*
19+
* expression | i18nPlural:mapping
20+
*
21+
* where `expression` is a number and `mapping` is an object that indicates the proper text for
22+
* when the `expression` evaluates to 0, 1, or some other number. You can interpolate the actual
23+
* value into the text using the `#` sign.
24+
*
25+
* ## Example
26+
*
27+
* ```
28+
* <div>
29+
* {{ messages.length | i18nPlural: messageMapping }}
30+
* </div>
31+
*
32+
* class MyApp {
33+
* messages: any[];
34+
* messageMapping: any = {
35+
* '=0': 'No messages.',
36+
* '=1': 'One message.',
37+
* 'other': '# messages.'
38+
* }
39+
* ...
40+
* }
41+
* ```
42+
*
43+
*/
44+
@CONST()
45+
@Pipe({name: 'i18nPlural', pure: true})
46+
@Injectable()
47+
export class I18nPluralPipe implements PipeTransform {
48+
transform(value: number, args: any[] = null): string {
49+
var key: string;
50+
var valueStr: string;
51+
var pluralMap: {[count: string]: string} = args[0];
52+
53+
if (!isStringMap(pluralMap)) {
54+
throw new InvalidPipeArgumentException(I18nPluralPipe, pluralMap);
55+
}
56+
57+
key = value === 0 || value === 1 ? `=${value}` : 'other';
58+
valueStr = isPresent(value) ? value.toString() : '';
59+
60+
return StringWrapper.replaceAll(pluralMap[key], interpolationExp, valueStr);
61+
}
62+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {CONST, isStringMap} from 'angular2/src/facade/lang';
2+
import {StringMapWrapper} from 'angular2/src/facade/collection';
3+
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
4+
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
5+
6+
/**
7+
*
8+
* Generic selector that displays the string that matches the current value.
9+
*
10+
* ## Usage
11+
*
12+
* expression | i18nSelect:mapping
13+
*
14+
* where `mapping` is an object that indicates the text that should be displayed
15+
* for different values of the provided `expression`.
16+
*
17+
* ## Example
18+
*
19+
* ```
20+
* <div>
21+
* {{ gender | i18nSelect: inviteMap }}
22+
* </div>
23+
*
24+
* class MyApp {
25+
* gender: string = 'male';
26+
* inviteMap: any = {
27+
* 'male': 'Invite her.',
28+
* 'female': 'Invite him.',
29+
* 'other': 'Invite them.'
30+
* }
31+
* ...
32+
* }
33+
* ```
34+
*/
35+
@CONST()
36+
@Pipe({name: 'i18nSelect', pure: true})
37+
@Injectable()
38+
export class I18nSelectPipe implements PipeTransform {
39+
transform(value: string, args: any[] = null): string {
40+
var mapping: {[key: string]: string} = args[0];
41+
if (!isStringMap(mapping)) {
42+
throw new InvalidPipeArgumentException(I18nSelectPipe, mapping);
43+
}
44+
45+
return StringMapWrapper.contains(mapping, value) ? mapping[value] : mapping['other'];
46+
}
47+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
ddescribe,
3+
describe,
4+
it,
5+
iit,
6+
xit,
7+
expect,
8+
beforeEach,
9+
afterEach
10+
} from 'angular2/testing_internal';
11+
12+
import {I18nPluralPipe} from 'angular2/common';
13+
import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver';
14+
15+
export function main() {
16+
describe("I18nPluralPipe", () => {
17+
var pipe;
18+
var mapping = {'=0': 'No messages.', '=1': 'One message.', 'other': 'There are some messages.'};
19+
var interpolatedMapping =
20+
{'=0': 'No messages.', '=1': 'One message.', 'other': 'There are # messages, that is #.'};
21+
22+
beforeEach(() => { pipe = new I18nPluralPipe(); });
23+
24+
it('should be marked as pure',
25+
() => { expect(new PipeResolver().resolve(I18nPluralPipe).pure).toEqual(true); });
26+
27+
describe("transform", () => {
28+
it("should return 0 text if value is 0", () => {
29+
var val = pipe.transform(0, [mapping]);
30+
expect(val).toEqual('No messages.');
31+
});
32+
33+
it("should return 1 text if value is 1", () => {
34+
var val = pipe.transform(1, [mapping]);
35+
expect(val).toEqual('One message.');
36+
});
37+
38+
it("should return other text if value is anything other than 0 or 1", () => {
39+
var val = pipe.transform(6, [mapping]);
40+
expect(val).toEqual('There are some messages.');
41+
});
42+
43+
it("should interpolate the value into the text where indicated", () => {
44+
var val = pipe.transform(6, [interpolatedMapping]);
45+
expect(val).toEqual('There are 6 messages, that is 6.');
46+
});
47+
48+
it("should use 'other' if value is undefined", () => {
49+
var messageLength;
50+
var val = pipe.transform(messageLength, [interpolatedMapping]);
51+
expect(val).toEqual('There are messages, that is .');
52+
});
53+
54+
it("should not support bad arguments",
55+
() => { expect(() => pipe.transform(0, ['hey'])).toThrowError(); });
56+
});
57+
58+
});
59+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {
2+
ddescribe,
3+
describe,
4+
it,
5+
iit,
6+
xit,
7+
expect,
8+
beforeEach,
9+
afterEach
10+
} from 'angular2/testing_internal';
11+
12+
import {I18nSelectPipe} from 'angular2/common';
13+
import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver';
14+
15+
export function main() {
16+
describe("I18nSelectPipe", () => {
17+
var pipe;
18+
var mapping = {'male': 'Invite him.', 'female': 'Invite her.', 'other': 'Invite them.'};
19+
20+
beforeEach(() => { pipe = new I18nSelectPipe(); });
21+
22+
it('should be marked as pure',
23+
() => { expect(new PipeResolver().resolve(I18nSelectPipe).pure).toEqual(true); });
24+
25+
describe("transform", () => {
26+
it("should return male text if value is male", () => {
27+
var val = pipe.transform('male', [mapping]);
28+
expect(val).toEqual('Invite him.');
29+
});
30+
31+
it("should return female text if value is female", () => {
32+
var val = pipe.transform('female', [mapping]);
33+
expect(val).toEqual('Invite her.');
34+
});
35+
36+
it("should return other text if value is anything other than male or female", () => {
37+
var val = pipe.transform('Anything else', [mapping]);
38+
expect(val).toEqual('Invite them.');
39+
});
40+
41+
it("should use 'other' if value is undefined", () => {
42+
var gender;
43+
var val = pipe.transform(gender, [mapping]);
44+
expect(val).toEqual('Invite them.');
45+
});
46+
47+
it("should not support bad arguments",
48+
() => { expect(() => pipe.transform('male', ['hey'])).toThrowError(); });
49+
});
50+
51+
});
52+
}

modules/angular2/test/public_api_spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ var NG_COMMON = [
208208
'FormBuilder.array()',
209209
'FormBuilder.control()',
210210
'FormBuilder.group()',
211+
'I18nPluralPipe',
212+
'I18nPluralPipe.transform()',
213+
'I18nSelectPipe',
214+
'I18nSelectPipe.transform()',
211215
'JsonPipe',
212216
'JsonPipe.transform()',
213217
'LowerCasePipe',

tools/public_api_guard/public_api_spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,10 @@ const COMMON = [
641641
'FormBuilder.array(controlsConfig:any[], validator:Function, asyncValidator:Function):ControlArray',
642642
'FormBuilder.control(value:Object, validator:Function, asyncValidator:Function):Control',
643643
'FormBuilder.group(controlsConfig:{[key:string]:any}, extra:{[key:string]:any}):ControlGroup',
644+
'I18nPluralPipe',
645+
'I18nPluralPipe.transform(value:number, args:any[]):string',
646+
'I18nSelectPipe',
647+
'I18nSelectPipe.transform(value:string, args:any[]):string',
644648
'JsonPipe',
645649
'JsonPipe.transform(value:any, args:any[]):string',
646650
'LowerCasePipe',

0 commit comments

Comments
 (0)
X Tutup