Merhaba,


Angular'da çoklu dil desteği nasıl yapılır? Projelerimizde çoklu dili nasıl ekleyebiliriz? Bununla ilgili bir yöntem göstermek istiyorum.


Projemizi oluşturarak başlayalım;

ng new angularMultiLanguage --routing
cd angularMultiLanguage
ng serve


Hemen app.component.html dosyamızı açtık ve gereksiz kodları temizledikten sonra bir menü oluşturalım dil değiştirme işini de buradan yaparız;

<header>
  <ul class="left-menu">
    <li><a routerLink="/">Anasayfa</a></li>
    <li><a routerLink="campaigns">Kampanyalar</a></li>
    <li><a>Son eklenen ürünler</a></li>
    <li><a>Çok satan ürünler</a></li>
  </ul>
  <ul class="right-menu">
    <li><a><img src="https://lipis.github.io/flag-icon-css/flags/4x3/tr.svg"></a></li>
    <li><a><img src="https://lipis.github.io/flag-icon-css/flags/4x3/gb.svg"></a></li>
  </ul>
</header>
<router-outlet></router-outlet>


birazda şekil verelim, app.component.scss;

header {
  background-color: #f9f9f9;
  padding: 15px 0;
  display: flex;
  justify-content: space-between;
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
    li {
      display: inline-block;
      a {
        cursor: pointer;
        transition: .3s;
        img {
          width: 30px;
          margin: 0 5px;
        }
        &:hover {
          background-color: #f3f3f3;
        }
      }
    }
    &.left-menu {
      li {
        a {
          padding: 15px;
        }
      }
    }
  }
}


2 tane yeni component oluşturalım.

ng g c components/home
ng g c components/campaigns


app-routing.module.ts içerisinde routes değişkenini aşağıdaki gibi ayarlayalım;

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'campaigns', component: CampaignsComponent }
];



Şimdi çoklu dil kısmına giriş yapıyoruz.


assets klasörü içinde i18n adında bir klasör oluşturalım ve içerisine de i18n.json adında bir dosya oluşturalım. Siz isimleri istediğiniz gibi verebilirsiniz. i18.json dosyamızda çevirilerimizi tutacağız. Örneğin aşağıdaki gibi;

{
  "home": {
    "tr": "Anasayfa",
    "en": "Homepage"
  },
  "campaigns": {
    "tr": "Kampanyalar",
    "en": "Campaigns"
  }
}


Bir tane servis oluşturacağız adınada translate diyelim; (spec dosyası istemiyorsanız komutun sonuna --spec false yazınız.)

ng g s services/translate


Burada HttpClientModule'i kullanacağız bunun için app.module.ts dosyamıza gidip bu modülü import edelim. app.module.ts;

imports: [
  ...
  HttpClientModule
]


translate.service.ts;

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class TranslateService {

  data: any = {};

  constructor(
    private http: HttpClient
  ) { }

  use(lang: string): Promise<{}> {
    return new Promise<{}>((resolve, reject) => {
      const langPath = `assets/i18n/i18n.json`;

      this.http.get<{}>(langPath).subscribe(
        translation => {
          // console.log(translation);
          Object.keys(translation).forEach((key) => {
            translation[key] = translation[key][lang];
          });
          this.data = Object.assign({}, translation || {});
          resolve(this.data);
        },
        error => {
          console.log(error);
          this.data = {};
          resolve(this.data);
        }
      );
    });
  }

}


Hemen sonrasında app.module.ts'yi açıyoruz ve @NgModule()'nin üstüne şu fonksiyonu oluşturuyoruz;

import {TranslateService} from './services/translate.service';

export function setupTranslateFactory(
  service: TranslateService): Function {
  return () => service.use('tr');
}

burada service.use('tr') kısmında varsayılan olarak hangi dili kullanacaksanız onun i18n.json dosyasındaki key olarak karşılığını yazıyorsunuz.

Bunu yaptıktan sonra da yine app.module.ts dosyasında providers bölümünde aşağıdaki tanımlamayı yapıyoruz;

import {APP_INITIALIZER, NgModule} from '@angular/core';

providers: [
  ...
  {
    provide: APP_INITIALIZER,
    useFactory: setupTranslateFactory,
    deps: [ TranslateService ],
    multi: true
  }
]


Buraya kadar bir sürü şey yaptık ama "aga bu nedir?" diye soruyor gibisiniz. Açıklayalım;

  1. i18n.json: bu dosyayı çevirilerimizi orada tanımlamak için oluşturduk. Orada değişken tanımlıyormuşuzda onun değerini çekiyormuşuz gibi düşünebilirsiniz. Örneğin home adında bir değişken oluşturdum ve bunun içerisinde "tr" ve "en" olarak değerlerini yazdım.
  2. TranslateService: Burada tanımladığımız data değişkeni bizim o an aktif olan dile ait değişkenleri ve buna ait kelimeleri, çevirileri tuttuğumuz değişkenimiz olacak. Bunuda use methodu ile yapacağız. use methodu aynı zamanda dil değiştirme işini halletmemiz için gerekiyor. Onun içerisinde yapılan işlemler ise kısaca i18n.json dosyamıza http.get isteği ile bağlanmak ve içerisindeki keyleri forEach ile döndürüp gönderdiğimiz dil parametresine göre içerideki değişkenlerin değerlerini almak ve bunları oluşturduğumuz data değişkenine atamak.
  3. setpTranslateFactory: app.module.ts içerisinde oluşturduğumuz bu fonksiyon ile projemiz açıldığında varsayılan olarak hangi dil kullanılacaksa onu TranslateService'indeki use methodumuza gönderiyoruz. Tabi bu fonksiyonu çalıştırmak içinde providers kısmında belirtiyoruz.


Evet buraya kadar yaptığımız kısımları anladık diye varsayıyorum ve geçelim bu yaptıklarımızı şimdi nasıl kullanacağız?


translate adında bir pipe oluşturalım; (spec dosyası istemiyorsanız komutun sonuna --spec false yazınız.)

ng g pipe pipes/translate


translate.pipe.ts;

import { Pipe, PipeTransform } from '@angular/core';
import {TranslateService} from '../services/translate.service';

@Pipe({
  name: 'translate',
  pure: false
})
export class TranslatePipe implements PipeTransform {

  constructor(
    private translate: TranslateService
  ) {
  }

  transform(key: any): any {
    return this.translate.data[key];
  }

}


Bu pipe'ın amacı: çevirisi olacak bir kelime veya cümlenin i18n.json içerisinde değişken karşılığı olacakya hani. işte o değişkenin adını alacak gönderecek ve TranslateService'e orada da data değişkeninden içinden cümlemizi getirecek.


Yapalım ve daha iyi anlayalım.

i18n.json dosyasında şu iki çeviriyi bi ekleyelim;

{
  "home": {
    "tr": "Anasayfa",
    "en": "Homepage"
  },
  "campaigns": {
    "tr": "Kampanyalar",
    "en": "Campaigns"
  }
}



Şimdi gelelim app.component.html dosyasını açalım ve menüdeki Anasayfa yazısını silelim onun yerine şunu yazalım;

{{ 'home' | translate }}


Şimdi bakalım çıktımızda bir değişiklik var mı?

Yok.


Süper, bu işi başarıyla tamamladık diyebiliriz. TranslatePipe'ına 'home' string ifadesini gönderdik. Ordanda gittik TranslateService içerisindeki data değişkenine. Orada şunu aradı: data.home, yani Anasayfa değeri dönmüş oldu.


Bunu doğrulamak için i18n.json içindeki "Anasayfa" yı değiştirin ve kaydettiğinizde çalıştığını göreceksiniz.


Şimdi birde dil değiştirmeyi deneyelim bakalım nasıl yapacağız;


Tahmin edeceğiniz gibi dil değiştirme bölümümüz hangi component içerisindeyse onun .ts dosyasını açıp TranslateService i constructor içerisinde tanımlayıp use methodunu kullanmak. Hemen yapalım ve öyle görelim;


Dil değiştirme bölümümüz app.component.html içerisinde olduğu için app.component.ts dosyasını açalım ve constructor'ı ekleyip TranslateService'i çağıralım;

import { Component } from '@angular/core';
import {TranslateService} from './services/translate.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angularMultiLanguage';

  constructor(
    public translateService: TranslateService
  ) {
  }
}


app.component.html'i açalım dil değişikliğini yapabilmek için click eventini kullanalım. Yani şunları;

<li><a><img src="https://lipis.github.io/flag-icon-css/flags/4x3/tr.svg"></a></li>
<li><a><img src="https://lipis.github.io/flag-icon-css/flags/4x3/gb.svg"></a></li>

şunlarla değiştirelim;

<li><a (click)="translateService.use('tr')"><img src="https://lipis.github.io/flag-icon-css/flags/4x3/tr.svg"></a></li>
<li><a (click)="translateService.use('en')"><img src="https://lipis.github.io/flag-icon-css/flags/4x3/gb.svg"></a></li>


Evet bakalım çıktımız ne durumda;


Süper. O zaman diğer çevirileride ekleyelim ve bitirelim.


i18n.json dosyası son hali;

{
  "home": {
    "tr": "Anasayfa",
    "en": "Homepage"
  },
  "campaigns": {
    "tr": "Kampanyalar",
    "en": "Campaigns"
  },
  "recentlyAdded": {
    "tr": "Son eklenen ürünler",
    "en": "Recently added products"
  },
  "bestsellers": {
    "tr": "Çok satan ürünler",
    "en": "Best selling products"
  },
  "homeWorks": {
    "tr": "anasayfa çalışıyor!",
    "en": "home works!"
  },
  "campaignWorks": {
    "tr": "kampanyalar çalışıyor!",
    "en": "campaigns works!"
  }
}


app.component.html dosyası son hali;

<header>
  <ul class="left-menu">
    <li><a routerLink="/">{{ 'home' | translate }}</a></li>
    <li><a routerLink="campaigns">{{ 'campaigns' | translate }}</a></li>
    <li><a>{{ 'recentlyAdded' | translate }}</a></li>
    <li><a>{{ 'bestsellers' | translate }}</a></li>
  </ul>
  <ul class="right-menu">
    <li><a (click)="translateService.use('tr')"><img src="https://lipis.github.io/flag-icon-css/flags/4x3/tr.svg"></a></li>
    <li><a (click)="translateService.use('en')"><img src="https://lipis.github.io/flag-icon-css/flags/4x3/gb.svg"></a></li>
  </ul>
</header>
<router-outlet></router-outlet>


home.component.html dosyası son hali;

<p>
  {{ 'homeWorks' | translate }}
</p>


campaigns.component.html dosyası son hali;

<p>
  {{ 'campaignWorks' | translate }}
</p>



Son olarak kontrol edelim;

Bu kadar.


Umarım faydalı olmuştur. Projemizin bitmiş hali için: https://github.com/MehmetSert/angularMultiLanguage