@@ -1445,3 +1445,195 @@ angularWidget('ng:view', function(element) {
1445
1445
compiler . directives ( true ) ;
1446
1446
}
1447
1447
} ) ;
1448
+
1449
+
1450
+ /**
1451
+ * @ngdoc widget
1452
+ * @name angular.widget.ng:pluralize
1453
+ *
1454
+ * @description
1455
+ * # Overview
1456
+ * ng:pluralize is a widget that displays messages according to en-US localization rules.
1457
+ * These rules are bundled with angular.js and the rules can be overridden
1458
+ * (see {@link guide/dev_guide.i18n Angular i18n} dev guide). You configure ng:pluralize by
1459
+ * specifying the mappings between
1460
+ * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
1461
+ * plural categories} and the strings to be displayed.
1462
+ *
1463
+ * # Plural categories and explicit number rules
1464
+ * There are two
1465
+ * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
1466
+ * plural categories} in Angular's default en-US locale: "one" and "other".
1467
+ *
1468
+ * While a pural category may match many numbers (for example, in en-US locale, "other" can match
1469
+ * any number that is not 1), an explicit number rule can only match one number. For example, the
1470
+ * explicit number rule for "3" matches the number 3. You will see the use of plural categories
1471
+ * and explicit number rules throughout later parts of this documentation.
1472
+ *
1473
+ * # Configuring ng:pluralize
1474
+ * You configure ng:pluralize by providing 2 attributes: `count` and `when`.
1475
+ * You can also provide an optional attribute, `offset`.
1476
+ *
1477
+ * The value of the `count` attribute can be either a string or an {@link guide/dev_guide.expressions
1478
+ * Angular expression}; these are evaluated on the current scope for its binded value.
1479
+ *
1480
+ * The `when` attribute specifies the mappings between plural categories and the actual
1481
+ * string to be displayed. The value of the attribute should be a JSON object so that Angular
1482
+ * can interpret it correctly.
1483
+ *
1484
+ * The following example shows how to configure ng:pluralize:
1485
+ *
1486
+ * <pre>
1487
+ * <ng:pluralize count="personCount"
1488
+ when="{'0': 'Nobody is viewing.',
1489
+ * 'one': '1 person is viewing.',
1490
+ * 'other': '{} people are viewing.'}">
1491
+ * </ng:pluralize>
1492
+ *</pre>
1493
+ *
1494
+ * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
1495
+ * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
1496
+ * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
1497
+ * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
1498
+ * show "a dozen people are viewing".
1499
+ *
1500
+ * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted
1501
+ * into pluralized strings. In the previous example, Angular will replace `{}` with
1502
+ * <span ng:non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
1503
+ * for <span ng:non-bindable>{{numberExpression}}</span>.
1504
+ *
1505
+ * # Configuring ng:pluralize with offset
1506
+ * The `offset` attribute allows further customization of pluralized text, which can result in
1507
+ * a better user experience. For example, instead of the message "4 people are viewing this document",
1508
+ * you might display "John, Kate and 2 others are viewing this document".
1509
+ * The offset attribute allows you to offset a number by any desired value.
1510
+ * Let's take a look at an example:
1511
+ *
1512
+ * <pre>
1513
+ * <ng:pluralize count="personCount" offset=2
1514
+ * when="{'0': 'Nobody is viewing.',
1515
+ * '1': '{{person1}} is viewing.',
1516
+ * '2': '{{person1}} and {{person2}} are viewing.',
1517
+ * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
1518
+ * 'other': '{{person1}}, {{person2}} and {} other people are viewing.' }">
1519
+ * </ng:pluralize>
1520
+ * </pre>
1521
+ *
1522
+ * Notice that we are still using two plural categories(one, other), but we added
1523
+ * three explicit number rules 0, 1 and 2.
1524
+ * When one person, perhaps John, views the document, "John is viewing" will be shown.
1525
+ * When three people view the document, no explicit number rule is found, so
1526
+ * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
1527
+ * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing"
1528
+ * is shown.
1529
+ *
1530
+ * Note that when you specify offsets, you must provide explicit number rules for
1531
+ * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
1532
+ * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
1533
+ * plural categories "one" and "other".
1534
+ *
1535
+ * @param {string|expression } count The variable to be bounded to.
1536
+ * @param {string } when The mapping between plural category to its correspoding strings.
1537
+ * @param {number= } offset Offset to deduct from the total number.
1538
+ *
1539
+ * @example
1540
+ <doc:example>
1541
+ <doc:source>
1542
+ Person 1:<input type="text" name="person1" value="Igor" /><br/>
1543
+ Person 2:<input type="text" name="person2" value="Misko" /><br/>
1544
+ Number of People:<input type="text" name="personCount" value="1" /><br/>
1545
+
1546
+ <!--- Example with simple pluralization rules for en locale --->
1547
+ Without Offset:
1548
+ <ng:pluralize count="personCount"
1549
+ when="{'0': 'Nobody is viewing.',
1550
+ 'one': '1 person is viewing.',
1551
+ 'other': '{} people are viewing.'}">
1552
+ </ng:pluralize><br>
1553
+
1554
+ <!--- Example with offset --->
1555
+ With Offset(2):
1556
+ <ng:pluralize count="personCount" offset=2
1557
+ when="{'0': 'Nobody is viewing.',
1558
+ '1': '{{person1}} is viewing.',
1559
+ '2': '{{person1}} and {{person2}} are viewing.',
1560
+ 'one': '{{person1}}, {{person2}} and one other person are viewing.',
1561
+ 'other': '{{person1}}, {{person2}} and {} other people are viewing.' }">
1562
+ </ng:pluralize>
1563
+ </doc:source>
1564
+ <doc:scenario>
1565
+ it('should show correct pluralized string', function(){
1566
+ expect(element('.doc-example-live .ng-pluralize:first').text()).
1567
+ toBe('1 person is viewing.');
1568
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1569
+ toBe('Igor is viewing.');
1570
+
1571
+ using('.doc-example-live').input('personCount').enter('0');
1572
+ expect(element('.doc-example-live .ng-pluralize:first').text()).
1573
+ toBe('Nobody is viewing.');
1574
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1575
+ toBe('Nobody is viewing.');
1576
+
1577
+ using('.doc-example-live').input('personCount').enter('2');
1578
+ expect(element('.doc-example-live .ng-pluralize:first').text()).
1579
+ toBe('2 people are viewing.');
1580
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1581
+ toBe('Igor and Misko are viewing.');
1582
+
1583
+ using('.doc-example-live').input('personCount').enter('3');
1584
+ expect(element('.doc-example-live .ng-pluralize:first').text()).
1585
+ toBe('3 people are viewing.');
1586
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1587
+ toBe('Igor, Misko and one other person are viewing.');
1588
+
1589
+ using('.doc-example-live').input('personCount').enter('4');
1590
+ expect(element('.doc-example-live .ng-pluralize:first').text()).
1591
+ toBe('4 people are viewing.');
1592
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1593
+ toBe('Igor, Misko and 2 other people are viewing.');
1594
+ });
1595
+
1596
+ it('should show data-binded names', function(){
1597
+ using('.doc-example-live').input('personCount').enter('4');
1598
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1599
+ toBe('Igor, Misko and 2 other people are viewing.');
1600
+
1601
+ using('.doc-example-live').input('person1').enter('Di');
1602
+ using('.doc-example-live').input('person2').enter('Vojta');
1603
+ expect(element('.doc-example-live .ng-pluralize:last').text()).
1604
+ toBe('Di, Vojta and 2 other people are viewing.');
1605
+ });
1606
+ </doc:scenario>
1607
+ </doc:example>
1608
+ */
1609
+ angularWidget ( 'ng:pluralize' , function ( element ) {
1610
+ var numberExp = element . attr ( 'count' ) ,
1611
+ whenExp = element . attr ( 'when' ) ,
1612
+ offset = element . attr ( 'offset' ) || 0 ;
1613
+
1614
+ return annotate ( '$locale' , function ( $locale , element ) {
1615
+ var scope = this ,
1616
+ whens = scope . $eval ( whenExp ) ,
1617
+ whensExpFns = { } ;
1618
+
1619
+ forEach ( whens , function ( expression , key ) {
1620
+ whensExpFns [ key ] = compileBindTemplate ( expression . replace ( / { } / g,
1621
+ '{{' + numberExp + '-' + offset + '}}' ) ) ;
1622
+ } ) ;
1623
+
1624
+ scope . $watch ( function ( ) {
1625
+ var value = parseFloat ( scope . $eval ( numberExp ) ) ;
1626
+
1627
+ if ( ! isNaN ( value ) ) {
1628
+ //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
1629
+ //check it against pluralization rules in $locale service
1630
+ if ( ! whens [ value ] ) value = $locale . pluralCat ( value - offset ) ;
1631
+ return whensExpFns [ value ] ( scope , element , true ) ;
1632
+ } else {
1633
+ return '' ;
1634
+ }
1635
+ } , function ( scope , newVal ) {
1636
+ element . text ( newVal ) ;
1637
+ } ) ;
1638
+ } ) ;
1639
+ } ) ;
0 commit comments