feat; add multi language support
This commit is contained in:
@@ -5,20 +5,20 @@
|
||||
<app-form-field
|
||||
[errorsDictionary]="companyAndNameErrorsDictionary"
|
||||
formControlName="name"
|
||||
[label]="(strings.name|upperfirst) + ':'"
|
||||
[placeholder]="strings.contactsName|upperfirst"
|
||||
[label]="(languageManager.strings.name|upperfirst) + ':'"
|
||||
[placeholder]="languageManager.strings.contactsName|upperfirst"
|
||||
/>
|
||||
<app-form-field
|
||||
[errorsDictionary]="companyAndNameErrorsDictionary"
|
||||
formControlName="company"
|
||||
[label]="(strings.company|upperfirst) + ':'"
|
||||
[placeholder]="strings.contactsCompany|upperfirst"
|
||||
[label]="(languageManager.strings.company|upperfirst) + ':'"
|
||||
[placeholder]="languageManager.strings.contactsCompany|upperfirst"
|
||||
/>
|
||||
<app-form-field
|
||||
[errorsDictionary]="phoneErrorsDictionary"
|
||||
formControlName="phone"
|
||||
[label]="(strings.phone|upperfirst) +':'"
|
||||
[placeholder]="strings.contactsPhone|upperfirst"
|
||||
[label]="(languageManager.strings.phone|upperfirst) +':'"
|
||||
[placeholder]="languageManager.strings.contactsPhone|upperfirst"
|
||||
type="tel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, inject, input, output } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { FormField } from '../form-field/form-field';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { SquaredBtn } from '../squared-btn/squared-btn';
|
||||
import { NameAndCompanyFieldsErrorsDictionary } from '../../errors-dictionaries/name-and-company-field';
|
||||
import { PhoneFieldErroresDictionary } from '../../errors-dictionaries/phone-field';
|
||||
@@ -9,6 +8,7 @@ import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||
import { ContactDTO } from '../../models/ContactDTO';
|
||||
import { ContactFormValue } from '../../types/ContactFormValue.type';
|
||||
import { FormGroupContact } from '../../utils/form-group-contact';
|
||||
import { LanguageManager } from '../../services/language-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact-form',
|
||||
@@ -20,7 +20,7 @@ export class ContactForm {
|
||||
contact = output<ContactDTO>();
|
||||
form = input(new FormGroupContact());
|
||||
submitText = input('');
|
||||
protected strings = inject(STRINGS_INJECTOR);
|
||||
protected languageManager = inject(LanguageManager);
|
||||
protected companyAndNameErrorsDictionary =
|
||||
new NameAndCompanyFieldsErrorsDictionary().getDictionary();
|
||||
protected phoneErrorsDictionary = new PhoneFieldErroresDictionary().getDictionary();
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<table class="contact-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{strings.name}}</th>
|
||||
<th>{{strings.company}}</th>
|
||||
<th>{{strings.phone}}</th>
|
||||
<th>{{strings.actions}}</th>
|
||||
<th>{{languageManager.strings.name}}</th>
|
||||
<th>{{languageManager.strings.company}}</th>
|
||||
<th>{{languageManager.strings.phone}}</th>
|
||||
<th>{{languageManager.strings.actions}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component, inject, input } from '@angular/core';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { ContactDTO } from '../../models/ContactDTO';
|
||||
import { ContactActionsBar } from '../contact-actions-bar/contact-actions-bar';
|
||||
import { ContactService } from '../../services/contact.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { LanguageManager } from '../../services/language-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact-list-table',
|
||||
@@ -13,7 +13,7 @@ import { Router } from '@angular/router';
|
||||
})
|
||||
export class ContactListTable {
|
||||
contactList = input<ContactDTO[]>([]);
|
||||
protected readonly strings = inject(STRINGS_INJECTOR);
|
||||
protected readonly languageManager = inject(LanguageManager);
|
||||
private readonly contactService = inject(ContactService);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<div class="contact-list">
|
||||
<div class="contact-list__container">
|
||||
<h2>{{strings.contacts|upperfirst}}</h2>
|
||||
<h2>{{languageManager.strings.contacts|upperfirst}}</h2>
|
||||
<app-contact-search-bar (contactSearch)="filter=$event"/>
|
||||
<app-counter
|
||||
[count]="(this.contacts$|async)?.length ?? 0"
|
||||
item="{{strings.contacts}}"
|
||||
item="{{languageManager.strings.contacts}}"
|
||||
/>
|
||||
<app-contact-list-table [contactList]="(this.contacts$|async)|contactsFilter:filter"/>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||
import { ContactSearchBar } from '../contact-search-bar/contact-search-bar';
|
||||
import { ContactListTable } from '../contact-list-table/contact-list-table';
|
||||
@@ -7,6 +6,7 @@ import { ContactService } from '../../services/contact.service';
|
||||
import { AsyncPipe } from '@angular/common';
|
||||
import { Counter } from '../counter/counter';
|
||||
import { ContactsFilterPipe } from '../../pipes/contacts-filter-pipe';
|
||||
import { LanguageManager } from '../../services/language-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact-list',
|
||||
@@ -23,7 +23,7 @@ import { ContactsFilterPipe } from '../../pipes/contacts-filter-pipe';
|
||||
})
|
||||
export class ContactList implements OnInit {
|
||||
private readonly contactService = inject(ContactService);
|
||||
protected readonly strings = inject(STRINGS_INJECTOR);
|
||||
protected readonly languageManager = inject(LanguageManager);
|
||||
protected contacts$ = this.contactService.contacts$;
|
||||
protected filter = '';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<input
|
||||
(input)="contactSearch.emit($event.target.value)"
|
||||
class="search-bar shadow"
|
||||
placeholder="{{strings.searchContactPlaceholder}}"
|
||||
placeholder="{{languageManager.strings.searchContactPlaceholder|upperfirst}}"
|
||||
type="text">
|
||||
@@ -1,13 +1,14 @@
|
||||
import { Component, inject, output } from '@angular/core';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { LanguageManager } from '../../services/language-manager';
|
||||
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact-search-bar',
|
||||
imports: [],
|
||||
imports: [UpperfirstPipe],
|
||||
templateUrl: './contact-search-bar.html',
|
||||
styleUrl: './contact-search-bar.scss',
|
||||
})
|
||||
export class ContactSearchBar {
|
||||
contactSearch = output<string>()
|
||||
protected readonly strings = inject(STRINGS_INJECTOR);
|
||||
contactSearch = output<string>();
|
||||
protected readonly languageManager = inject(LanguageManager);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@if(notification$(); as notification) {
|
||||
<div class="notification notification--{{notification.type}} notification--fade-in-out">
|
||||
<p>{{ notification.message }}</p>
|
||||
<p>{{ notification.message|upperfirst }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Notifier } from '../../services/notifier';
|
||||
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-notification',
|
||||
imports: [],
|
||||
imports: [UpperfirstPipe],
|
||||
templateUrl: './notification.html',
|
||||
styleUrl: './notification.scss',
|
||||
})
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { Dictionary } from '../interfaces/dictionary.interface';
|
||||
import { STRINGS_INJECTOR } from '../app.config';
|
||||
import { LanguageManager } from '../services/language-manager';
|
||||
|
||||
export class NameAndCompanyFieldsErrorsDictionary implements Dictionary {
|
||||
private readonly strings = inject(STRINGS_INJECTOR);
|
||||
private readonly languageManager = inject(LanguageManager);
|
||||
private readonly maxlen: string;
|
||||
private readonly required = this.strings.errorMessageRequired;
|
||||
private readonly required = this.languageManager.strings.errorMessageRequired;
|
||||
|
||||
constructor() {
|
||||
this.maxlen = this.strings.errorMessageMaxLength(120);
|
||||
this.maxlen = this.languageManager.strings.errorMessageMaxLength(120);
|
||||
}
|
||||
|
||||
getDictionary(): { [key: string]: string } {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { Dictionary } from '../interfaces/dictionary.interface';
|
||||
import { STRINGS_INJECTOR } from '../app.config';
|
||||
import { LanguageManager } from '../services/language-manager';
|
||||
|
||||
export class PhoneFieldErroresDictionary implements Dictionary {
|
||||
strings = inject(STRINGS_INJECTOR);
|
||||
pattern = this.strings.errorMessagePhonePattern;
|
||||
required = this.strings.errorMessageRequired;
|
||||
languageManager = inject(LanguageManager);
|
||||
pattern = this.languageManager.strings.errorMessagePhonePattern;
|
||||
required = this.languageManager.strings.errorMessageRequired;
|
||||
|
||||
getDictionary(): { [key: string]: string } {
|
||||
const { required, pattern } = this;
|
||||
|
||||
@@ -6,6 +6,8 @@ import { ContactDTO } from '../../models/ContactDTO';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { strings } from '../../strings';
|
||||
|
||||
describe('contactResolver', () => {
|
||||
let httpTestingController: HttpTestingController;
|
||||
@@ -31,6 +33,7 @@ describe('contactResolver', () => {
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
{ provide: Router, useValue: router },
|
||||
{ provide: STRINGS_INJECTOR, useValue: strings },
|
||||
],
|
||||
});
|
||||
httpTestingController = TestBed.inject(HttpTestingController);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<app-main-header
|
||||
[title]="strings.editContact"
|
||||
[title]="languageManager.strings.editContact"
|
||||
>
|
||||
<app-rounded-btn
|
||||
(keydown)="goBack()"
|
||||
(click)="goBack()"
|
||||
slot="action-button"
|
||||
text="Go back"
|
||||
text={{languageManager.strings.goBack|upperfirst}}
|
||||
/>
|
||||
</app-main-header>
|
||||
<app-card bgColor="var(--secondary)">
|
||||
@@ -14,9 +14,9 @@
|
||||
class="form"
|
||||
(contact)="edit(form.value)"
|
||||
[form]="form"
|
||||
[submitText]="strings.save"
|
||||
[submitText]="languageManager.strings.save"
|
||||
><app-form-header
|
||||
[title]="strings.editTheContact|upperfirst"
|
||||
[title]="languageManager.strings.editTheContact|upperfirst"
|
||||
slot="header"
|
||||
/>
|
||||
</app-contact-form>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { MainHeader } from '../../components/main-header/main-header';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { RoundedBtn } from '../../components/rounded-btn/rounded-btn';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Card } from '../../components/card/card';
|
||||
@@ -13,6 +12,7 @@ import { FormGroupContact } from '../../utils/form-group-contact';
|
||||
import { AsyncPipe } from '@angular/common';
|
||||
import { ContactService } from '../../services/contact.service';
|
||||
import { ContactFormValue } from '../../types/ContactFormValue.type';
|
||||
import { LanguageManager } from '../../services/language-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit',
|
||||
@@ -21,7 +21,7 @@ import { ContactFormValue } from '../../types/ContactFormValue.type';
|
||||
styleUrl: './edit.scss',
|
||||
})
|
||||
export class Edit {
|
||||
protected readonly strings = inject(STRINGS_INJECTOR);
|
||||
protected readonly languageManager = inject(LanguageManager);
|
||||
private readonly activatedRoute = inject(ActivatedRoute);
|
||||
private readonly contactService = inject(ContactService);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<app-main-header [title]="strings.contactList"/>
|
||||
<app-main-header [title]="languageManager.strings.contactAgenda"/>
|
||||
<app-card bgColor="var(--secondary)">
|
||||
<app-contact-form
|
||||
(contact)="save($event)"
|
||||
[form]="form"
|
||||
[submitText]="strings.add"
|
||||
[submitText]="languageManager.strings.add"
|
||||
class="form"
|
||||
><app-form-header
|
||||
[subtitle]="strings.allFieldRequired|upperfirst"
|
||||
[title]="strings.addContact|upperfirst"
|
||||
[subtitle]="languageManager.strings.allFieldRequired|upperfirst"
|
||||
[title]="languageManager.strings.addContact|upperfirst"
|
||||
slot="header"
|
||||
/>
|
||||
</app-contact-form>
|
||||
|
||||
@@ -5,10 +5,10 @@ import { ContactList } from '../../components/contact-list/contact-list';
|
||||
import { ContactService } from '../../services/contact.service';
|
||||
import { ContactDTO } from '../../models/ContactDTO';
|
||||
import { FormHeader } from '../../components/form-header/form-header';
|
||||
import { STRINGS_INJECTOR } from '../../app.config';
|
||||
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||
import { MainHeader } from '../../components/main-header/main-header';
|
||||
import { FormGroupContact } from '../../utils/form-group-contact';
|
||||
import { LanguageManager } from '../../services/language-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'app-main',
|
||||
@@ -18,7 +18,7 @@ import { FormGroupContact } from '../../utils/form-group-contact';
|
||||
})
|
||||
export class Main {
|
||||
protected readonly form = new FormGroupContact();
|
||||
protected readonly strings = inject(STRINGS_INJECTOR);
|
||||
protected readonly languageManager = inject(LanguageManager);
|
||||
private readonly contactService = inject(ContactService);
|
||||
|
||||
save(contactDTO: ContactDTO) {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { ContactDTO } from '../models/ContactDTO';
|
||||
import { STRINGS_INJECTOR } from '../app.config';
|
||||
import { strings } from '../strings';
|
||||
|
||||
describe('ContactService', () => {
|
||||
let service: ContactService;
|
||||
@@ -16,7 +18,11 @@ describe('ContactService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [],
|
||||
providers: [provideHttpClient(), provideHttpClientTesting()],
|
||||
providers: [
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
{ provide: STRINGS_INJECTOR, useValue: strings },
|
||||
],
|
||||
});
|
||||
service = TestBed.inject(ContactService);
|
||||
httpTestingController = TestBed.inject(HttpTestingController);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ContactDTO } from '../models/ContactDTO';
|
||||
import { Response } from '../models/Response';
|
||||
import { BehaviorSubject, map, switchMap, tap } from 'rxjs';
|
||||
import { ResponseStateNotification } from './ResponseStateNotificatio';
|
||||
import { strings } from '../strings';
|
||||
import { LanguageManager } from './language-manager';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -14,7 +14,7 @@ export class ContactService {
|
||||
private readonly httpClient = inject(HttpClient);
|
||||
private readonly responseStateNotification = inject(ResponseStateNotification);
|
||||
private readonly contacts = new BehaviorSubject<ContactDTO[]>([]);
|
||||
|
||||
private readonly languageManager = inject(LanguageManager);
|
||||
readonly contacts$ = this.contacts.asObservable();
|
||||
|
||||
delete(id: number) {
|
||||
@@ -22,8 +22,8 @@ export class ContactService {
|
||||
(r) =>
|
||||
this.responseStateNotification.handleResponse(
|
||||
r,
|
||||
strings.deleteContactSuccessNotification,
|
||||
strings.errorNotification
|
||||
this.languageManager.strings.deleteContactSuccessNotification,
|
||||
this.languageManager.strings.errorNotification
|
||||
),
|
||||
switchMap(() => this.getAll())
|
||||
);
|
||||
@@ -47,8 +47,8 @@ export class ContactService {
|
||||
(r) =>
|
||||
this.responseStateNotification.handleResponse(
|
||||
r,
|
||||
strings.createContactSuccessNotification,
|
||||
strings.errorNotification
|
||||
this.languageManager.strings.createContactSuccessNotification,
|
||||
this.languageManager.strings.errorNotification
|
||||
),
|
||||
|
||||
switchMap(() => this.getAll())
|
||||
@@ -61,8 +61,8 @@ export class ContactService {
|
||||
.pipe((r) =>
|
||||
this.responseStateNotification.handleResponse(
|
||||
r,
|
||||
strings.editContactSuccessNotification,
|
||||
strings.errorNotification
|
||||
this.languageManager.strings.editContactSuccessNotification,
|
||||
this.languageManager.strings.errorNotification
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
27
src/app/services/language-manager.spec.ts
Normal file
27
src/app/services/language-manager.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LanguageManager } from './language-manager';
|
||||
import { strings } from '../strings';
|
||||
import { STRINGS_INJECTOR } from '../app.config';
|
||||
import { Language } from '../types/Language.type';
|
||||
|
||||
describe('LanguageManager', () => {
|
||||
let service: LanguageManager;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{ provide: STRINGS_INJECTOR, useValue: strings }],
|
||||
});
|
||||
service = TestBed.inject(LanguageManager);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should switch language', () => {
|
||||
const SELECTED_LANGUAGE_MOCK: Language = 'es';
|
||||
service.setLanguage(SELECTED_LANGUAGE_MOCK);
|
||||
expect(service.strings).toEqual(strings[SELECTED_LANGUAGE_MOCK]);
|
||||
});
|
||||
});
|
||||
16
src/app/services/language-manager.ts
Normal file
16
src/app/services/language-manager.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { STRINGS_INJECTOR } from '../app.config';
|
||||
import { Language } from '../types/Language.type';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LanguageManager {
|
||||
private readonly stringsDictionary = inject(STRINGS_INJECTOR);
|
||||
|
||||
strings = this.stringsDictionary.en;
|
||||
|
||||
setLanguage(language: Language) {
|
||||
this.strings = this.stringsDictionary[language];
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,54 @@
|
||||
export const strings = Object.freeze({
|
||||
en: {
|
||||
actions: 'actions',
|
||||
add: 'add',
|
||||
addContact: 'add a contact',
|
||||
allFieldRequired: 'all fields are required',
|
||||
company: 'company',
|
||||
contactAgenda: 'contact agenda',
|
||||
contacts: 'contacts',
|
||||
contactsName: "Contact's name",
|
||||
contactsCompany: "Contact's company",
|
||||
contactsPhone: "Contact's phone",
|
||||
contactList: 'contact list',
|
||||
createContactSuccessNotification: 'Contact created successfully',
|
||||
deleteContactSuccessNotification: 'Contact deleted successfully',
|
||||
contactsName: "contact's name",
|
||||
contactsCompany: "contact's company",
|
||||
contactsPhone: "contact's phone",
|
||||
createContactSuccessNotification: 'contact created successfully',
|
||||
deleteContactSuccessNotification: 'contact deleted successfully',
|
||||
editContact: 'edit contact',
|
||||
editContactSuccessNotification: 'Contact edited successfully',
|
||||
editContactSuccessNotification: 'contact edited successfully',
|
||||
editTheContact: 'edit the contact',
|
||||
errorMessageMaxLength: (maxLen: number) => `Must be ${maxLen} characters or fewer.`,
|
||||
errorMessagePhonePattern: `Valid format: + (optional) plus 12 to 15 digits`,
|
||||
errorMessageRequired: 'This field is required.',
|
||||
errorNotification: 'Oops, there was an error',
|
||||
goBack: 'go back',
|
||||
name: 'name',
|
||||
phone: 'phone',
|
||||
save: 'save',
|
||||
searchContactPlaceholder: 'Search contact...',
|
||||
},
|
||||
es: {
|
||||
actions: 'acciones',
|
||||
add: 'añadir',
|
||||
addContact: 'añada un contacto',
|
||||
allFieldRequired: 'todos los campos son obligatorios',
|
||||
company: 'empresa',
|
||||
contactAgenda: 'agenda de contactos',
|
||||
contacts: 'contactos',
|
||||
contactsName: 'nombre contacto',
|
||||
contactsCompany: 'empresa contacto',
|
||||
contactsPhone: 'teléfono contacto',
|
||||
createContactSuccessNotification: 'contacto creado correctamente',
|
||||
deleteContactSuccessNotification: 'contacto eliminado',
|
||||
editContact: 'editar contacto',
|
||||
editContactSuccessNotification: 'contacto editado correctamente',
|
||||
editTheContact: 'edite el contacto. ',
|
||||
errorMessageMaxLength: (maxLen: number) => `Debe contener ${maxLen} caracteres or menos.`,
|
||||
errorMessagePhonePattern: `Formato: + (opcional) y 12 a 15 digitos`,
|
||||
errorMessageRequired: 'este campo es requerido.',
|
||||
errorNotification: 'hubo un error',
|
||||
goBack: 'volver',
|
||||
name: 'nombre',
|
||||
phone: 'teléfono',
|
||||
save: 'guardar',
|
||||
searchContactPlaceholder: 'buscar contactos...',
|
||||
},
|
||||
});
|
||||
|
||||
3
src/app/types/Language.type.ts
Normal file
3
src/app/types/Language.type.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { strings } from '../strings';
|
||||
|
||||
export type Language = keyof typeof strings;
|
||||
Reference in New Issue
Block a user