fix(core): handle pluralize functions that expect a number (#36901)
Previously we were passing a string form of the value to pluralize to the `getLocalePluralCase()` function that is extracted from the locale data. But some locales have functions that rely upon this value being a number not a string. Now we convert the value to a number before passing it to the locale data function. Fixes #36888 PR Close #36901
This commit is contained in:
parent
1c26f40cd4
commit
2ff4b357d7
|
@ -8,26 +8,15 @@
|
|||
|
||||
import {getLocalePluralCase} from './locale_data_api';
|
||||
|
||||
const pluralMapping = ['zero', 'one', 'two', 'few', 'many'];
|
||||
|
||||
/**
|
||||
* Returns the plural case based on the locale
|
||||
*/
|
||||
export function getPluralCase(value: any, locale: string): string {
|
||||
const plural = getLocalePluralCase(locale)(value);
|
||||
|
||||
switch (plural) {
|
||||
case 0:
|
||||
return 'zero';
|
||||
case 1:
|
||||
return 'one';
|
||||
case 2:
|
||||
return 'two';
|
||||
case 3:
|
||||
return 'few';
|
||||
case 4:
|
||||
return 'many';
|
||||
default:
|
||||
return 'other';
|
||||
}
|
||||
export function getPluralCase(value: string, locale: string): string {
|
||||
const plural = getLocalePluralCase(locale)(parseInt(value, 10));
|
||||
const result = pluralMapping[plural];
|
||||
return (result !== undefined) ? result : 'other';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
import '@angular/localize/init';
|
||||
|
||||
import {CommonModule, registerLocaleData} from '@angular/common';
|
||||
import localeEs from '@angular/common/locales/es';
|
||||
import localeRo from '@angular/common/locales/ro';
|
||||
import {computeMsgId} from '@angular/compiler';
|
||||
import {Component, ContentChild, ContentChildren, Directive, ElementRef, HostBinding, Input, LOCALE_ID, NO_ERRORS_SCHEMA, Pipe, PipeTransform, QueryList, TemplateRef, Type, ViewChild, ViewContainerRef} from '@angular/core';
|
||||
|
@ -770,7 +771,20 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
|||
expect(fixture.nativeElement.innerHTML).toEqual(`<div>autre - 4<!--ICU 5--></div>`);
|
||||
});
|
||||
|
||||
it('should return the correct plural form for ICU expressions when using a specific locale', () => {
|
||||
it('should return the correct plural form for ICU expressions when using "ro" locale', () => {
|
||||
// The "ro" locale has a complex plural function that can handle muliple options
|
||||
// (and string inputs)
|
||||
//
|
||||
// function plural(n: number): number {
|
||||
// let i = Math.floor(Math.abs(n)), v = n.toString().replace(/^[^.]*\.?/, '').length;
|
||||
// if (i === 1 && v === 0) return 1;
|
||||
// if (!(v === 0) || n === 0 ||
|
||||
// !(n === 1) && n % 100 === Math.floor(n % 100) && n % 100 >= 1 && n % 100 <= 19)
|
||||
// return 3;
|
||||
// return 5;
|
||||
// }
|
||||
//
|
||||
// Compare this to the "es" locale in the next test
|
||||
loadTranslations({
|
||||
[computeMsgId(
|
||||
'{VAR_PLURAL, plural, =0 {no email} =one {one email} =few {a few emails} =other {lots of emails}}')]:
|
||||
|
@ -814,6 +828,57 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
|||
expect(fixture.nativeElement.innerHTML).toEqual('no email<!--ICU 2-->');
|
||||
});
|
||||
|
||||
it(`should return the correct plural form for ICU expressions when using "es" locale`, () => {
|
||||
// The "es" locale has a simple plural function that can only handle a few options
|
||||
// (and not string inputs)
|
||||
//
|
||||
// function plural(n: number): number {
|
||||
// if (n === 1) return 1;
|
||||
// return 5;
|
||||
// }
|
||||
//
|
||||
// Compare this to the "ro" locale in the previous test
|
||||
const icuMessage = '{VAR_PLURAL, plural, =0 {no email} =one ' +
|
||||
'{one email} =few {a few emails} =other {lots of emails}}';
|
||||
loadTranslations({[computeMsgId(icuMessage)]: icuMessage});
|
||||
registerLocaleData(localeEs);
|
||||
TestBed.configureTestingModule({providers: [{provide: LOCALE_ID, useValue: 'es'}]});
|
||||
// We could also use `TestBed.overrideProvider(LOCALE_ID, {useValue: 'es'});`
|
||||
const fixture = initWithTemplate(AppComp, `
|
||||
{count, plural,
|
||||
=0 {no email}
|
||||
=one {one email}
|
||||
=few {a few emails}
|
||||
=other {lots of emails}
|
||||
}`);
|
||||
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('no email<!--ICU 2-->');
|
||||
|
||||
// Change detection cycle, no model changes
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('no email<!--ICU 2-->');
|
||||
|
||||
fixture.componentInstance.count = 3;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('lots of emails<!--ICU 2-->');
|
||||
|
||||
fixture.componentInstance.count = 1;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('one email<!--ICU 2-->');
|
||||
|
||||
fixture.componentInstance.count = 10;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('lots of emails<!--ICU 2-->');
|
||||
|
||||
fixture.componentInstance.count = 20;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('lots of emails<!--ICU 2-->');
|
||||
|
||||
fixture.componentInstance.count = 0;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('no email<!--ICU 2-->');
|
||||
});
|
||||
|
||||
it('projection', () => {
|
||||
loadTranslations({
|
||||
[computeMsgId('{VAR_PLURAL, plural, =1 {one} other {at least {INTERPOLATION} .}}')]:
|
||||
|
|
Loading…
Reference in New Issue