إعداد مشروعك متعدد اللغات

 التثبيتات الهامة:

npm install @ngx-translate/core@14 --save

npm install @ngx-translate/http-loader@7 --save



تعديل ملف الـ app.module.ts ليكون بهذا النحو على الأقل:

import { HttpClient, HttpClientModule } from '@angular/common/http';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { DatePipe } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';

export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@NgModule({
    declarations: [
    ],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
TranslateModule.forRoot({
defaultLanguage: (localStorage.getItem('currentLanguage') !== null) ? localStorage.getItem('currentLanguage')! : 'ar'!,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
  schemas: [
    CUSTOM_ELEMENTS_SCHEMA
  ],
  providers: [
    DatePipe
  ],
  bootstrap: [AppComponent]

})
export class AppModule { }

من أهم الأشياء الآن إنشاء ملفات اللغات وهي عبارة عن ملفات JSON وأدناه مثل بسيط عليها:

{
    "TEXT_LOGO": "عبدالله علي السالم",
    "MY_NAME": "عبدالله علي السالم",
    "ADDRESS": "الأحساء - قرية الفضول",
    "DESIRE": {
        "SOFTWARE_ENGINEER": "مهندس برمجيات",
        "UI_UX_DESIGNER": "أعمل أن أكون مصمم UI / UX",
        "FRONT_END_DEVELOPER": "أعمل على تطوير الواجهة الأمامية",
        "FULL_STACK_DEVELOPER": "مطور مكدس كامل",
        "SPA": "أطور تطبيقات الصفحة الواحدة (SPA)",
        "AGILE_METHODOLOGIES": "أعمل على المنهجيات الرشيقة",
        "SOFTWARE_DEVELOPMENT": "أعمل على تطوير البرمجيات"
    },
    "BUTTONS": {
        "HIRE_ME": "وظفني",
        "DOWNLOAD_MY_CV": "تنزيل السيرة",
        "MY_BLOG": "مدونتي",
        "ARABIC": "العربية",
        "ENGLISH": "English",
        "VIEW_ALL_PLAYLISTS": "الاطلاع على كافة قوائم التشغيل",
        "SUBMIT": "ارسال",
        "CREATE_A_SIMILAR_RESUME": "اطلب مني إنشاء سيرة ذاتية مشابهة لك",
        "AGREE": "أوافق على جميع الشروط",
        "CLOSE": "إغلاق"
    }
}



مثال على أسماء لفات اللغة:

الآن سنقوم بإنشاء مكوّن جديد باسم lang وهو لتغير اللغة:

محتوى الـ HTML
<button mat-button [matMenuTriggerFor]="menu">
    <i class="mdi mdi-flag"></i>
    {{translateService.currentLang !== 'ar'? ('BUTTONS.ARABIC' | translate) : ('BUTTONS.ENGLISH' | translate)}}
</button>
<mat-menu #menu="matMenu">
    <button mat-menu-item (click)="selectLanguage('ar')">{{'BUTTONS.ARABIC' | translate}}</button>
    <button mat-menu-item (click)="selectLanguage('en')">{{'BUTTONS.ENGLISH' | translate}}</button>
</mat-menu>

محتوى الـ css
i{
    font-size: x-large;
}

محتوى الـ ts
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'app-lang',
  templateUrl: './lang.component.html',
  styleUrls: ['./lang.component.scss']
})
export class LangComponent implements OnInit {

  constructor(public translateService: TranslateService) { }

  public selectLanguage(event: any) {
    // TODO
    this.translateService.use(event);  
  }

  ngOnInit(): void {
    this.translateService.currentLang = (localStorage.getItem('currentLanguage') != null)? localStorage.getItem('currentLanguage'):'ar';
  }

}


الآن بعد ذلك يمكننا ببساطة استخدام الأنبوب (Pipe) أدناه لاستدعاء خصائص وكائنات ملف اللغة:

<h1 class="text-center text-capitalize mb-2 mt-2">{{'MY_NAME' | translate}}</h1>


------------------------------------------------------------------------------------

تغيير اللغة لأدوات التحكم الخاصة بالـ pagination-controls الجدول:



بدايةً سنقوم بتعريف متغيرات خاصة بالجدول وهي كالتالي:

import { LiveAnnouncer } from '@angular/cdk/a11y';
import { HttpErrorResponse } from '@angular/common/http';
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort, Sort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Router } from '@angular/router';
import { UsersService } from 'src/app/services/users.service';

@Component({
selector: 'app-users-table',
templateUrl: './users-table.component.html',
styleUrls: ['./users-table.component.scss']
})
export class UsersTableComponent implements AfterViewInit {
// @ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
public page: number = 0;

// @ViewChild(MatTable) table!: MatTable<UsersTableItem>;
dataSource: any = [];
user:any;

/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['id', 'name', 'actions'];

constructor(private _liveAnnouncer: LiveAnnouncer,
public usersService: UsersService,
public _MatPaginatorIntl: MatPaginatorIntl,
router: Router) {
}

ngOnInit(): void {

//--------------------------
this.usersService.getAllUsers().subscribe((res: any) => {
this.dataSource = new MatTableDataSource(res);
this.dataSource.sort = this.sort;
console.log('response is ', res);
});
}

ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
//------------------------------
this._MatPaginatorIntl.itemsPerPageLabel = "العناصر لكل صفحة";
this._MatPaginatorIntl.firstPageLabel = "الصفحة الأولى";
this._MatPaginatorIntl.lastPageLabel = "الصفحة الأخيرة";
this._MatPaginatorIntl.nextPageLabel = "الصفحة التالية";
this._MatPaginatorIntl.previousPageLabel = "الصفحة التالية";
this._MatPaginatorIntl.getRangeLabel = this.getRangeDisplayText;
}

getRangeDisplayText = (page: number, pageSize: number, length: number) => {
const initialText = 'من'; // customize this line
if (length == 0 || pageSize == 0) {
return `${initialText} 0 ${'من'} ${length}`;
}
length = Math.max(length, 0);
const startIndex = page * pageSize;
const endIndex = startIndex < length
? Math.min(startIndex + pageSize, length)
: startIndex + pageSize;
return `${initialText} ${startIndex + 1} ${'إلى'} ${endIndex} ${'والمجموع'} ${length}`; // customize this line
};

delete(id: number) {
this.usersService.deletUser(id).subscribe(data => {
alert("لقد تم حذف العنصر بنجاح");
},
(error: HttpErrorResponse) => {
alert("هناك مشكلة أدّت إلى عدم حذف العنصر");
}
)
}




announceSortChange(sortState: Sort) {
// This example uses English messages. If your application supports
// multiple language, you would internationalize these strings.
// Furthermore, you can customize the message to add additional
// details about the values being sorted.
if (sortState.direction) {
this._liveAnnouncer.announce(`Sorted ${sortState.direction}ending`);
} else {
this._liveAnnouncer.announce('Sorting cleared');
}
}

}


ويمكننا أيضاً إنشاء خدمة تقوم بتكوين متغير في ذاكرة المتصفح لحفظ اللغة التي اختارها المستخدم مؤخراً وأدناه ستجد الطريقة:

import { Injectable } from '@angular/core';
import { User } from '../models/user';


@Injectable({
  providedIn: 'root'
})
export class LocalStorageService {
  user: User = new User();

  constructor() { }

  public setUserItem(user: any) {
    localStorage.setItem('user', JSON.stringify(user));
  }

  public getUserItem() {
    return JSON.parse(localStorage.getItem('user') || '{}');
  }

  public setLanguageCode(currentLang: any) {
    localStorage.setItem('currentLanguage', currentLang);
  }

  public getLanguageCode(): string {
    return localStorage.getItem('currentLanguage');
  }

}


كيف نقوم بترجمة Date Picker أو تقويم Angular Material إلى اللغة العربية والإنجليزية حسب الطلب؟


import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core';


  constructor(
    private localStorageService: LocalStorageService,
    private timeCalculator: _FileTimeCalculatorService,
    private uploadService: FirebaseUploadService,
    private snackBarService: SnackBarService,
    private _formBuilder: FormBuilder,
    public translateService: TranslateService,
    public googleTranslateService: _GoogleTranslateService,
    public dialog: MatDialog,
    private revenueClassificationsService: RevenueClassificationsService,
    public copyToClipboardService: CopyToClipboardService,
    private branchesService: BranchesService,
    private departmentsService: DepartmentsService,
    @Inject(MAT_DIALOG_DATA) public data: Revenue,
    private _adapter: DateAdapter<any>,
    @Inject(MAT_DATE_LOCALE) private _locale: string,
  ) {
    this.refresh();
    this.bringBranches();
    this.bringDepartments();
    this.lang = this.localStorageService.getLanguageCode();
    this._locale = this.lang;
    this._adapter.setLocale(this._locale);
    if (this.data) {

      this.editMode = false;
    } else {
      // حالة الإنشاء
      this.data = new Revenue();
      this.editMode = true;
    }
  }

//--------------------------------------------------------------------------
بكل بساطة سنضيف الأداة إلى ملف الـ HTML بالشكل الطبيعي من ثم سنقوم بإضافة الـ Provider التالي إلى صفحة الـ ts

ولا ننسى التثبيت الهام للغاية:
npm i @angular/material-moment-adapter

import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MAT_MOMENT_DATE_ADAPTER_OPTIONS, MAT_MOMENT_DATE_FORMATS, MomentDateAdapter } from '@angular/material-moment-adapter';


@Component({
  selector: 'app-generate-employee-cards',
  templateUrl: './generate-employee-cards.component.html',
  styleUrls: ['./generate-employee-cards.component.scss'],
  providers: [
    {
      provide: STEPPER_GLOBAL_OPTIONS,
      useValue: { showError: true },
    },
    { provide: MAT_DATE_LOCALE, useValue: (localStorage.getItem('currentLanguage') === "ar") ? 'ar-SA':'en-US' },//'ar-SA'
    {
      provide: DateAdapter,
      useClass: MomentDateAdapter,
      deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
    },
    { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },

  ]
})


//-------------------------------------------------------------------------------

استخدام أنبوب الترجمة في ملف ts في Angular



While you cannot directly use the translate pipe within a TypeScript file in Angular, there are different ways to achieve translation logic outside the template:

1. TranslateService:

  • Inject the TranslateService into your component or service.
  • Use the instant method to translate a key instantly:
TypeScript
import { TranslateService } from '@ngx-translate/core';

constructor(private translate: TranslateService) {}

myTranslatedText = this.translate.instant('KEY_IN_TRANSLATION_FILE');
  • Consider using get or stream methods if you need to subscribe to translation changes or handle asynchronous loading.

2. Interpolation within a string literal:

  • Use string interpolation with backticks (`) and access the translation key directly:
TypeScript
const translatedText = `${'WELCOME'} ${this.translate.currentLang}`;
  • Be cautious not to abuse this approach for complex formatting.

3. Custom helper function:

  • Create a function that receives a translation key and returns the translated value using TranslateService:
TypeScript
getTranslatedText(key: string): string {
  return this.translate.instant(key);
}

translatedText = this.getTranslatedText('KEY_IN_TRANSLATION_FILE');

Remember:

  • Choose the approach that best suits your needs and coding style.
  • TranslateService offers powerful control and flexibility.
  • String interpolation is convenient for simple cases.
  • Custom functions provide organization and reusability.

Additional Resources:

  • ngx-translate documentation: [[https ngx translate documentation ON GitHub Pages ngx-translate.github.io]]
  • TranslateService API: [[https ngx translate documentation ON GitHub Pages ngx-translate.github.io]]

I hope this comprehensive explanation helps you utilize translation logic effectively in your Angular application!













ستواجه مشاكلات كبيرة في حال عملك بـ Netlify






































تعليقات

المشاركات الشائعة من هذه المدونة

ngx-extended-pdf-viewer

how to getting access token for https://fcm.googleapis.com/v1/projects/al-ayahya-co/messages:send for angular and backend nestjs

طريقة تفعيل زر Inline Keyboard في Telegram Bot