Vins
Vins

Reputation: 125

JSON object interfaced return undefined

i want to create a pipe in Angular 9 that translate my table words in various language. I have created a JSON file that contains a key and the value for a translation service. I have also created some interfaces for this json file.

translate.json

{
"lang":[
    {
      "IT": [
        { "name": "Nome" },
        { "surname": "Cognome" },
        { "email": "E-mail" },
        { "cf": "Codice fiscale" },
        { "phone": "Cellulare" },
        { "age": "Età" },
        { "city": "Città" },
        { "job": "Lavoro" }
      ]
    },
    {
      "EN": [
        { "name": "first name" },
        { "surname": "last name" },
        { "email": "E-mail" },
        { "cf": "Fiscal code" },
        { "phone": "Phone" },
        { "age": "Age" },
        { "city": "City" },
        { "job": "Job" }
      ]
    }
  ]

}

translateInterface.ts

export interface Lang {
  lang: (Langs)[];
}
export interface Langs {
  IT: (ITEntityOrENEntity)[];
  EN: (ITEntityOrENEntity)[];
}
export interface ITEntityOrENEntity {
  name: string;
  surname: string;
  email: string;
  cf: string;
  phone: string;
  age: string;
  city: string;
  job: string;
}


translate.service.ts

translate(key: string, lang:string) {
    return this.http.get<Langs>('assets/json/translate.json').subscribe((res: Lang) => console.log(res))

    }

I have updated the json and the interface, now how i can return one object of the IT array?

Upvotes: 0

Views: 387

Answers (1)

Barremian
Barremian

Reputation: 31105

I see multiple issues.

  1. You don't need to define the properties IT and EN as arrays in the JSON file. It could very well be plain JS objects.
{
  "IT": {
    "name": "Nome",
    "surname": "Cognome",
    "email": "E-mail",
    "cf": "Codice fiscale",
    "phone": "Cellulare",
    "age": "Età",
    "city": "Città",
    "job": "Lavoro" 
  },
  "EN": {
    "name": "first name",
    "surname": "last name",
    "email": "E-mail",
    "cf": "Fiscal code",
    "phone": "Phone",
    "age": "Age",
    "city": "City",
    "job": "Job" 
  }
}
  1. There is no need for two different interfaces. You could assign one single interface.
export interface Details {
  name: string;
  surname: string;
  email: string;
  cf: string;
  phone: string;
  age: string;
  city: string;
  job: string;
}
  1. You are defining the type as array in Langs interface instead of the defined details interface. You could do something like
export interface Langs {
  IT: Details;
  EN: Details;
}
  1. At the moment you're wrongfully returning the subscription instead of the observable from the function. You could return the observable from the service and subscribe to it the component controller.

Service

translate(language: string): Observable<Details> {
  return this.http.get<Langs>('assets/json/translate.json').pipe(
    map(response => response[language])
  );
}

Component

ngOnInit() {
  this.translateService.translate('IT').subscribe(
    details => { this.details = details },
    error => { }
  );
}

Template

<span>{{ details?.name }}</span>
<span>{{ details?.surname }}</span>
<span>{{ details?.email }}</span>
...

Working example: Stackblitz

Upvotes: 1

Related Questions