Skip to content

Commit

Permalink
localization : adding localization in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
mBahrawy committed Aug 17, 2023
1 parent 496f3d3 commit 7985852
Show file tree
Hide file tree
Showing 17 changed files with 260 additions and 161 deletions.
5 changes: 0 additions & 5 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
<app-loader></app-loader>
<app-navbar></app-navbar>
<router-outlet></router-outlet>


<button mat-button *ngIf="translate.currentLang=== 'en'" (click)="switchLanguage('ar')" >{{"Arabic" | translate}}</button>
<button mat-button *ngIf="translate.currentLang=== 'ar'" (click)="switchLanguage('en')" >{{"English" | translate}}</button>
{{ 'HELLO' | translate }}
23 changes: 11 additions & 12 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LocalizationService } from './core/services/localization.service';

@Component({
selector: 'app-root',
Expand All @@ -8,25 +9,23 @@ import { TranslateService } from '@ngx-translate/core';
})
export class AppComponent {

setDefaultLanguage(language: string = 'en') {
this.translate.setDefaultLang(language);
this.translate.use(language);
localStorage.setItem('language', language);
}

constructor(public translate: TranslateService) {
constructor(
public translate: TranslateService,
localizService: LocalizationService
) {
const storedLanguage: string | null = localStorage.getItem('language');
if (
!storedLanguage ||
!(storedLanguage === 'en' || storedLanguage === 'ar')
) {
this.setDefaultLanguage();
localizService.setDefaultLanguage();
return;
}
this.setDefaultLanguage(storedLanguage);
}
switchLanguage(language: string) {
this.translate.use(language);
localStorage.setItem('language', language);
localizService.setDefaultLanguage(storedLanguage);

storedLanguage === 'ar'
? localizService.changeDirectionToRtl()
: localizService.changeDirectionToLtr();
}
}
37 changes: 13 additions & 24 deletions src/app/components/product-view/product-view.component.html
Original file line number Diff line number Diff line change
@@ -1,51 +1,40 @@
<div class="container my-5" *ngIf="product">
<div class="row">
<div class="col-md-12">

<div class="row justify-content-center">
<div class="col-lg-8">
<mat-card class="product-card">
<mat-card-header class="mb-3 d-flex justify-content-between">

<button (click)="handleBack()" mat-icon-button color="primary" aria-label="Back">
<mat-icon>keyboard_arrow_left</mat-icon>
<button (click)="handleBack()" mat-icon-button color="primary" [attr.aria-label]="'Back' | translate">
<mat-icon *ngIf="localize.getLang() === 'en'">keyboard_arrow_left</mat-icon>
<mat-icon *ngIf="localize.getLang() === 'ar'">keyboard_arrow_right</mat-icon>
</button>

<div class="d-flex flex-column flex-grow-1">
<mat-card-title>{{ product.title }}</mat-card-title>
<mat-card-subtitle>Category: {{ product.category }}</mat-card-subtitle>
<mat-card-subtitle>{{ 'Category' | translate }}: {{ product.category }}</mat-card-subtitle>
</div>


</mat-card-header>
<mat-divider class=""></mat-divider>
<mat-card-content>

<div class="row p-0">
<div class="col-md-6 py-4">
<img class="img-fluid" [src]="product.image" [alt]="product.title" />

</div>
<div class="col-md-6 py-4">

<div class="mb-5">
<h4><b>Product description</b></h4>
<h4><b>{{ 'Product description' | translate }}</b></h4>
<p>{{ product.description }}</p>
</div>

<p><b>Price:</b> ${{ product.price }}</p>
<p><b>Rating:</b> {{ product.rating.rate }} ({{ product.rating.count }} reviews)</p>
<p><b>{{ 'Price' | translate }}:</b> ${{ product.price }}</p>
<p><b>{{ 'Rating' | translate }}:</b> {{ product.rating.rate }} ({{ product.rating.count }} {{ 'reviews' | translate }})</p>
</div>
</div>

<mat-divider *ngIf="isShowingActions" class="mt-3"></mat-divider>
</mat-card-content>

<mat-card-actions *ngIf="isShowingActions" class="d-flex justify-content-end">

<button (click)="delete()" mat-button color="warn" aria-label="Delete">
<mat-icon>delete</mat-icon> Delete
<button (click)="delete()" mat-button color="warn" [attr.aria-label]="'Delete' | translate">
<mat-icon>delete</mat-icon> {{ 'Delete' | translate }}
</button>
<button [routerLink]="['edit']" mat-button color="primary" aria-label="Edit">
<mat-icon>edit</mat-icon> Edit
<button [routerLink]="['edit']" mat-button color="primary" [attr.aria-label]="'Edit' | translate">
<mat-icon>edit</mat-icon> {{ 'Edit' | translate }}
</button>
</mat-card-actions>
</mat-card>
Expand Down
4 changes: 3 additions & 1 deletion src/app/components/product-view/product-view.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Product } from 'src/app/core/interfaces/product';
import { AuthService } from 'src/app/core/services/auth.service';
import { ProductsService } from 'src/app/core/services/products.service';
import { Location } from '@angular/common';
import { LocalizationService } from 'src/app/core/services/localization.service';

@Component({
selector: 'app-product-view',
Expand All @@ -21,7 +22,8 @@ export class ProductViewComponent implements OnInit, OnDestroy {
private products: ProductsService,
private route: ActivatedRoute,
private auth: AuthService,
private location: Location
private location: Location,
public localize : LocalizationService
) {}

handleBack() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<h4>Filter products</h4>
<h4>{{ 'Filter products' | translate }}</h4>
<mat-divider></mat-divider>

<div class="d-flex flex-column">
<mat-checkbox [(ngModel)]="isAllCategoriesChecked" (change)="handleAllCheck()" >
All categories
<mat-checkbox [(ngModel)]="isAllCategoriesChecked" (change)="handleAllCheck()">
{{ 'All categories' | translate }}
</mat-checkbox>
<mat-checkbox *ngFor="let category of checkBoxcategories" (change)="handleCheck()" [(ngModel)]="category.checked">
{{ category.name }}
{{ category.name | translate }}
</mat-checkbox>

</div>
17 changes: 11 additions & 6 deletions src/app/components/ui/navbar/navbar.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<mat-toolbar color="primary" class="d-fle justify-content-between">
<span>Angular Store</span>
<span>{{ "Angular store" | translate}}</span>

<div>
<span class="spacer"></span>
<button mat-button *ngIf="translate.currentLang=== 'en'" (click)="switchLanguage('ar')" >{{"ENGLISH" | translate}}</button>
<button mat-button *ngIf="translate.currentLang=== 'ar'" (click)="switchLanguage('en')" >{{"ARABIC" | translate}}</button>
<button mat-button *ngIf="translate.currentLang === 'ar'" (click)="localizService.switchLanguage('en')">Switch to
EN</button>
<button mat-button *ngIf="translate.currentLang === 'en'" (click)="localizService.switchLanguage('ar')">التحويل
للعربي </button>

<ng-template *ngIf="!(auth.isAuth$ | async)" #loginTemplate>
<a mat-button routerLink="/auth">Login</a>
</ng-template>

<span class="mx-2" *ngIf="auth.isAuth$ | async"> |</span>

<ng-container *ngIf="auth.isAuth$ | async">
<a mat-button (click)="logout()">{{"Logout" | translate}}</a>
</ng-container>
</div>
</mat-toolbar>
12 changes: 4 additions & 8 deletions src/app/components/ui/navbar/navbar.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { AuthService } from 'src/app/core/services/auth.service';
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { AuthService } from 'src/app/core/services/auth.service';
import { LocalizationService } from 'src/app/core/services/localization.service';

@Component({
selector: 'app-navbar',
Expand All @@ -16,6 +17,7 @@ export class NavbarComponent {
public auth: AuthService,
private breakpointObserver: BreakpointObserver,
public translate: TranslateService,
public localizService: LocalizationService
) {}

ngOnInit(): void {
Expand All @@ -35,10 +37,4 @@ export class NavbarComponent {
logout(): void {
this.auth.logout();
}

switchLanguage(language: string) {
this.translate.use(language);
localStorage.setItem('language', language);
}

}
40 changes: 40 additions & 0 deletions src/app/core/services/localization.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Injectable, Renderer2, RendererFactory2 } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Injectable({
providedIn: 'root',
})
export class LocalizationService {
private renderer!: Renderer2;

constructor(
public translate: TranslateService,
rendererFactory: RendererFactory2
) {
this.renderer = rendererFactory.createRenderer(null, null);
}
setDefaultLanguage(language: string = 'en') {
this.translate.setDefaultLang(language);
this.translate.use(language);
localStorage.setItem('language', language);
}

changeDirectionToRtl() {
this.renderer.setAttribute(document.documentElement, 'dir', 'rtl');
}

changeDirectionToLtr() {
this.renderer.setAttribute(document.documentElement, 'dir', 'ltr');
}

switchLanguage(language: string) {
language === 'ar' ? this.changeDirectionToRtl() : this.changeDirectionToLtr();

this.translate.use(language);
localStorage.setItem('language', language);
}

getLang(): 'en' | 'ar' {
return this.translate.currentLang as 'en' | 'ar'
}
}
79 changes: 36 additions & 43 deletions src/app/modules/admin/product-form/product-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
<div class="col-md-12">
<mat-card class="product-card">
<mat-card-header class="mb-3 d-flex">
<button (click)="handleBack()" mat-icon-button color="primary" aria-label="Back">
<button (click)="handleBack()" mat-icon-button color="primary" [attr.aria-label]="'Back' | translate ">
<mat-icon>keyboard_arrow_left</mat-icon>
</button>
<div [ngSwitch]="formType" class="d-flex align-items-center">

<mat-card-title *ngSwitchCase="'create'">Add an new product</mat-card-title>
<mat-card-title *ngSwitchCase="'edit'">Edit product</mat-card-title>
<mat-card-title *ngSwitchDefault>Product form</mat-card-title>

<mat-card-title *ngSwitchCase="'create'">{{ 'Add a new product' | translate }}</mat-card-title>
<mat-card-title *ngSwitchCase="'edit'">{{ 'Edit product' | translate }}</mat-card-title>
<mat-card-title *ngSwitchDefault>{{ 'Product form' | translate }}</mat-card-title>
</div>
</mat-card-header>
<mat-card-content>
Expand All @@ -23,66 +21,61 @@
<div class="row">
<div class="col-md-12 mb-2">
<mat-form-field class="w-100" appearance="fill">
<mat-label>Title</mat-label>
<mat-label>{{ 'Title' | translate }}</mat-label>
<input matInput formControlName="title" required>
<mat-error>Please enter a product title</mat-error>
<mat-error>{{ 'Please enter a product title' | translate }}</mat-error>
</mat-form-field>

</div>
<div class="col-md-12 mb-2"> <mat-form-field class="w-100" appearance="fill">
<mat-label>Price</mat-label>
<mat-label>{{ 'Price' | translate }}</mat-label>
<input matInput type="number" formControlName="price" required>
<mat-error>Please enter a product price</mat-error>

<mat-error>{{ 'Please enter a product price' | translate }}</mat-error>
</mat-form-field></div>
<div class="col-md-12 mb-2"> <mat-form-field class="w-100" appearance="fill">
<mat-label>Description</mat-label>
<mat-label>{{ 'Description' | translate }}</mat-label>
<textarea matInput formControlName="description" required></textarea>

<mat-error *ngIf="productForm.get('description')?.hasError('required')">Please enter a product description</mat-error>
<mat-error *ngIf="productForm.get('description')?.hasError('minlength')">Product description is too short</mat-error>
<mat-error *ngIf="productForm.get('description')?.hasError('maxlength')">Product description is too long</mat-error>
<mat-error *ngIf="productForm.get('description')?.hasError('required')">{{ 'Please enter a product description' | translate }}</mat-error>
<mat-error *ngIf="productForm.get('description')?.hasError('minlength')">{{ 'Product description is too short' | translate }}</mat-error>
<mat-error *ngIf="productForm.get('description')?.hasError('maxlength')">{{ 'Product description is too long' | translate }}</mat-error>
</mat-form-field></div>
<div class="col-md-12 mb-2">

<mat-form-field *ngIf="categoriesList" class="w-100" appearance="fill">
<mat-label>Category</mat-label>
<mat-label>{{ 'Category' | translate }}</mat-label>
<mat-select formControlName="category" required>

<mat-option *ngFor="let category of categoriesList" [value]="category"><span
class="text-capitalize">{{category}}</span> </mat-option>
<mat-option *ngFor="let category of categoriesList" [value]="category"><span class="text-capitalize">{{category}}</span></mat-option>
</mat-select>
<mat-error>Please select a category</mat-error>
<mat-error>{{ 'Please select a category' | translate }}</mat-error>
</mat-form-field>
</div>

<div class="col-md-12 mb-2">
<mat-form-field class="w-100" appearance="fill">
<mat-label>Image URL</mat-label>
<input (input)="onImageUrlChange()" matInput formControlName="image" required>
<mat-error *ngIf="productForm.get('image')?.hasError('required')">Please add a product image url</mat-error>
<mat-error *ngIf="productForm.get('image')?.hasError('pattern')">Please add a valid product image url</mat-error>
</mat-form-field>
</div>
<div class="col-md-12 mb-2">
<mat-form-field class="w-100" appearance="fill">
<mat-label>{{ 'Image URL' | translate }}</mat-label>
<input (input)="onImageUrlChange()" matInput formControlName="image" required>
<mat-error *ngIf="productForm.get('image')?.hasError('required')">{{ 'Please add a product image URL' | translate }}</mat-error>
<mat-error *ngIf="productForm.get('image')?.hasError('pattern')">{{ 'Please add a valid product image URL' | translate }}</mat-error>
</mat-form-field>
</div>
</div>
</div>

<div class="col-md-6 mb-3">
<div *ngIf="productForm.value.image && validImageUrl" >
<img [src]="productForm.get('image')?.value" (error)="handleImageError()" [alt]="productForm.value.title" class="product-img img-fluid w-100 avatar-img">
</div>
<div *ngIf="productForm.value.image && !validImageUrl" >
<img src="assets/images/image-not-found.jpg" alt="No image to be shown" class="product-img img-fluid w-100 avatar-img">
</div>
<div *ngIf="!productForm.value.image" >
<img src="assets/images/no-image.png" alt="No image to be shown" class="product-img img-fluid w-100 avatar-img">
</div>
<div class="col-md-6 mb-3">
<div *ngIf="productForm.value.image && validImageUrl">
<img [src]="productForm.get('image')?.value" (error)="handleImageError()" [alt]="productForm.value.title" class="product-img img-fluid w-100 avatar-img">
</div>
<div *ngIf="productForm.value.image && !validImageUrl">
<img src="assets/images/image-not-found.jpg" alt="{{ 'No image to be shown' | translate }}" class="product-img img-fluid w-100 avatar-img">
</div>
<div *ngIf="!productForm.value.image">
<img src="assets/images/no-image.png" alt="{{ 'No image to be shown' | translate }}" class="product-img img-fluid w-100 avatar-img">
</div>
</div>
</div>

<div [ngSwitch]="formType" class="d-flex justify-content-end" >
<button *ngSwitchCase="'create'" mat-raised-button color="primary" type="submit">Create</button>
<button *ngSwitchCase="'edit'" mat-raised-button color="primary" type="submit">Save</button>
<div [ngSwitch]="formType" class="d-flex justify-content-end">
<button *ngSwitchCase="'create'" mat-raised-button color="primary" type="submit">{{ 'Create' | translate }}</button>
<button *ngSwitchCase="'edit'" mat-raised-button color="primary" type="submit">{{ 'Save' | translate }}</button>
</div>

</form>
Expand Down
Loading

0 comments on commit 7985852

Please sign in to comment.