إعداد مشروعك متعدد اللغات
التثبيتات الهامة:
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
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
TranslateServiceinto your component or service. - Use the
instantmethod 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
getorstreammethods 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.
TranslateServiceoffers 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
إعداد:

تعليقات
إرسال تعليق