Skip to content

Commit 6bb3212

Browse files
author
Andrea Barbasso
committed
[CST-16756] create dsNormalizeLanguageCode pipe
1 parent 8ca81ed commit 6bb3212

11 files changed

Lines changed: 92 additions & 13 deletions

src/app/item-page/field-components/metadata-values/metadata-values.component.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414

1515
<!-- Render value as markdown -->
1616
<ng-template #markdown let-value="value" let-lang="lang">
17-
<span class="dont-break-out" [dsMarkdown]="value" [attr.lang]="lang">
17+
<span class="dont-break-out" [dsMarkdown]="value" [attr.lang]="lang | dsNormalizeLanguageCode">
1818
</span>
1919
</ng-template>
2020

2121
<!-- Render value as a link (href and label) -->
2222
<ng-template #link let-value="value" let-lang="lang">
2323
<a class="dont-break-out ds-simple-metadata-link"
24-
[attr.lang]="lang"
24+
[attr.lang]="lang | dsNormalizeLanguageCode"
2525
[href]="value"
2626
[attr.target]="getLinkAttributes(value).target"
2727
[attr.rel]="getLinkAttributes(value).rel" role="link" tabindex="0">
@@ -32,7 +32,7 @@
3232
<!-- Render value as a link with icon -->
3333
<ng-template #linkImg let-img="img" let-value="value" let-lang="lang">
3434
<a [href]="value" class="link-anchor dont-break-out ds-simple-metadata-link"
35-
target="_blank" role="link" tabindex="0" [attr.lang]="lang">
35+
target="_blank" role="link" tabindex="0" [attr.lang]="lang | dsNormalizeLanguageCode">
3636
<img class="link-logo"
3737
[alt]="img.alt | translate"
3838
[style.height]="'var(' + img.heightVar + ', --ds-item-page-img-field-default-inline-height)'"
@@ -43,13 +43,13 @@
4343

4444
<!-- Render simple value in a span -->
4545
<ng-template #simple let-value="value" let-lang="lang">
46-
<span class="dont-break-out preserve-line-breaks" [attr.lang]="lang">{{value}}</span>
46+
<span class="dont-break-out preserve-line-breaks" [attr.lang]="lang | dsNormalizeLanguageCode">{{value}}</span>
4747
</ng-template>
4848

4949
<!-- Render value as a link to browse index -->
5050
<ng-template #browselink let-value="value" let-lang="lang">
5151
<a class="dont-break-out preserve-line-breaks ds-browse-link"
52-
[attr.lang]="lang"
52+
[attr.lang]="lang | dsNormalizeLanguageCode"
5353
[routerLink]="['/browse', browseDefinition.id]"
5454
[queryParams]="getQueryParams(value)" role="link" tabindex="0">{{ value }}</a>
5555
</ng-template>

src/app/item-page/field-components/metadata-values/metadata-values.component.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ describe('MetadataValuesComponent', () => {
9999
expect(result.rel).toBe('noopener noreferrer');
100100
});
101101

102-
it('should set the lang attribute for each rendered metadata value', () => {
102+
it('should set the lang attribute for each rendered metadata value and convert underscores', () => {
103103
const valueSpans = fixture.debugElement.queryAll(By.css('span.dont-break-out.preserve-line-breaks'));
104104
expect(valueSpans.length).toBe(mockMetadata.length);
105105
valueSpans.forEach(spanDebugEl => {
106-
expect(spanDebugEl.attributes.lang).toBe('en_US');
106+
expect(spanDebugEl.attributes.lang).toBe('en-US');
107107
});
108108
});
109109

src/app/item-page/field-components/metadata-values/metadata-values.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-br
2323
import { hasValue } from '../../../shared/empty.util';
2424
import { MetadataFieldWrapperComponent } from '../../../shared/metadata-field-wrapper/metadata-field-wrapper.component';
2525
import { MarkdownDirective } from '../../../shared/utils/markdown.directive';
26+
import { NormalizeLanguageCodePipe } from '../../../shared/utils/normalize-language-code.pipe';
2627
import { ImageField } from '../../simple/field-components/specific-field/image-field';
2728

2829
/**
@@ -39,6 +40,7 @@ import { ImageField } from '../../simple/field-components/specific-field/image-f
3940
MarkdownDirective,
4041
MetadataFieldWrapperComponent,
4142
NgTemplateOutlet,
43+
NormalizeLanguageCodePipe,
4244
RouterLink,
4345
TranslateModule,
4446
],

src/app/shared/metadata.directive.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from '@angular/core';
88

99
import { MetadataValue } from '../core/shared/metadata.models';
10+
import { normalizeLanguageCode } from './utils/normalize-language-code-utils';
1011

1112
/**
1213
* A directive that sets the innerHTML and lang attribute of the host element
@@ -61,7 +62,8 @@ export class MetadataDirective {
6162
const val = this._metadataValue.value ?? '';
6263
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', val);
6364
if (this._metadataValue.language) {
64-
this.renderer.setAttribute(this.el.nativeElement, 'lang', this._metadataValue.language);
65+
const normalizedLang = normalizeLanguageCode(this._metadataValue.language);
66+
this.renderer.setAttribute(this.el.nativeElement, 'lang', normalizedLang);
6567
} else {
6668
this.renderer.removeAttribute(this.el.nativeElement, 'lang');
6769
}

src/app/shared/object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<a
44
target="_blank" class="dont-break-out"
55
[routerLink]="['/browse/', mdRepresentation.browseDefinition.id]"
6-
[attr.lang]="mdRepresentation.getLanguage()"
6+
[attr.lang]="mdRepresentation.getLanguage() | dsNormalizeLanguageCode"
77
[queryParams]="getQueryParams()">
88
{{mdRepresentation.getValue()}}
99
</a>

src/app/shared/object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { Component } from '@angular/core';
33
import { RouterLink } from '@angular/router';
44

55
import { VALUE_LIST_BROWSE_DEFINITION } from '../../../../core/shared/value-list-browse-definition.resource-type';
6+
import { NormalizeLanguageCodePipe } from '../../../utils/normalize-language-code.pipe';
67
import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component';
78

89
@Component({
910
selector: 'ds-browse-link-metadata-list-element',
1011
templateUrl: './browse-link-metadata-list-element.component.html',
1112
standalone: true,
1213
imports: [
14+
NormalizeLanguageCodePipe,
1315
RouterLink,
1416
],
1517
})

src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
<div>
22
<!-- Because this template is used by default, we will additionally test for representation type and display accordingly -->
33
@if ((mdRepresentation.representationType==='plain_text') && !isLink()) {
4-
<span class="dont-break-out" [attr.lang]="mdRepresentation.getLanguage()">
4+
<span class="dont-break-out" [attr.lang]="mdRepresentation.getLanguage() | dsNormalizeLanguageCode">
55
{{mdRepresentation.getValue()}}
66
</span>
77
}
88
@if ((mdRepresentation.representationType==='plain_text') && isLink()) {
99
<a class="dont-break-out"
10-
[attr.lang]="mdRepresentation.getLanguage()"
10+
[attr.lang]="mdRepresentation.getLanguage() | dsNormalizeLanguageCode"
1111
target="_blank" [href]="mdRepresentation.getValue()" role="link" tabindex="0">
1212
{{mdRepresentation.getValue()}}
1313
</a>
1414
}
1515
@if ((mdRepresentation.representationType==='authority_controlled')) {
16-
<span class="dont-break-out" [attr.lang]="mdRepresentation.getLanguage()">{{mdRepresentation.getValue()}}</span>
16+
<span class="dont-break-out" [attr.lang]="mdRepresentation.getLanguage() | dsNormalizeLanguageCode">{{mdRepresentation.getValue()}}</span>
1717
}
1818
@if ((mdRepresentation.representationType==='browse_link')) {
1919
<a
2020
class="dont-break-out ds-browse-link"
2121
[routerLink]="['/browse/', mdRepresentation.browseDefinition.id]"
2222
[queryParams]="getQueryParams()"
2323
role="link"
24-
[attr.lang]="mdRepresentation.getLanguage()"
24+
[attr.lang]="mdRepresentation.getLanguage() | dsNormalizeLanguageCode"
2525
tabindex="0">
2626
{{mdRepresentation.getValue()}}
2727
</a>

src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { Component } from '@angular/core';
33
import { RouterLink } from '@angular/router';
44

55
import { VALUE_LIST_BROWSE_DEFINITION } from '../../../../core/shared/value-list-browse-definition.resource-type';
6+
import { NormalizeLanguageCodePipe } from '../../../utils/normalize-language-code.pipe';
67
import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component';
78

89
@Component({
910
selector: 'ds-plain-text-metadata-list-element',
1011
templateUrl: './plain-text-metadata-list-element.component.html',
1112
standalone: true,
1213
imports: [
14+
NormalizeLanguageCodePipe,
1315
RouterLink,
1416
],
1517
})
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Normalizes a language code by replacing underscores with hyphens.
3+
*
4+
* This function is useful for transforming POSIX-style language codes (e.g., 'en_US') into
5+
* standard BCP 47 language tags (e.g., 'en-US').
6+
*
7+
* @param value - The input string to be transformed. Can be null or undefined.
8+
* @returns The transformed string with underscores replaced by dashes, or the original value if null/undefined.
9+
*/
10+
export function normalizeLanguageCode(value: string | null | undefined): string | null | undefined {
11+
if (value === null || value === undefined) {
12+
return value;
13+
}
14+
return value.replace(/_/g, '-');
15+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { NormalizeLanguageCodePipe } from './normalize-language-code.pipe';
2+
3+
describe('NormalizeLanguageCodePipe', () => {
4+
const pipe = new NormalizeLanguageCodePipe();
5+
6+
it('transforms language codes replacing underscores with dashes', () => {
7+
expect(pipe.transform('en_US')).toBe('en-US');
8+
expect(pipe.transform('pt_BR')).toBe('pt-BR');
9+
expect(pipe.transform('zh_Hant_TW')).toBe('zh-Hant-TW');
10+
});
11+
12+
it('returns the same value when there are no underscores', () => {
13+
expect(pipe.transform('en')).toBe('en');
14+
expect(pipe.transform('fr')).toBe('fr');
15+
});
16+
17+
it('preserves null and undefined input', () => {
18+
expect(pipe.transform(null)).toBeNull();
19+
expect(pipe.transform(undefined)).toBeUndefined();
20+
});
21+
22+
it('handles empty string input', () => {
23+
expect(pipe.transform('')).toBe('');
24+
});
25+
});

0 commit comments

Comments
 (0)