Tuesday, September 16, 2025

Sunday, September 29, 2019

Multilingual application using asp dot net core mvc with portable objects (PO)

What is PO files?
PO stands for portable objects, these are the files that containing translated text string each for language. It has some advantages over .resx (resource files).
1. It Support pluralization
2. PO files are not compiled like .resx
Example:
en.po
#: 1. Hello World
msgid "Hello_World"
msgstr "Hello World!"

hi.po
#: 1. Hello World
msgid "Hello_World"
msgstr "संसार को नमस्ते"

Configure PO files for ASP.Net Core MVC:

To configure PO files we have to include package reference:
<PackageReference Include="OrchardCore.Localization.Core" Version="1.0.0-rc1-10004" />

Now the time is to configure the services and middleware
Add these required configuration method in startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
        .AddDataAnnotationsLocalization();

// Put your .po files in Resources folder

services.AddPortableObjectLocalization(options => options.ResourcesPath = "Resources");

services.Configure<RequestLocalizationOptions>(options =>
        {
           var supportedCultures = new List<CultureInfo>
                 {
                   new CultureInfo("en-US"),
                    new CultureInfo("hi-IN")
                 };

                options.DefaultRequestCulture = new RequestCulture("en-US");
                 options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;
        });

}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   app.UseRequestLocalization();
}

Now add the following code on view:
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer

<p>@Localizer["Hello world!"]&lt;/p>
Test the application by Navigate the URL:
/Home/About?culture=en-US
/Home/About?culture=hi-IN

Model Localization:

public class RoleDto
  {
     [Display(Name = "Name")]
     [Required(ErrorMessage = "this_field_is_required")]
     public string Name { getset; }
  }

en.po

#: 1. Name
msgid "Name"
msgstr "Name"

#: 2. This field is required
msgid "this_field_is_required"
msgstr "This field is required."

hi.po

#: 1. Nam
msgid "Name"
msgstr "नाम"

#: 2. This field is required
msgid "this_field_is_required"
msgstr "यह फ़ील्ड आवश्यक है।"

Wednesday, December 19, 2018

Read Image from Excel

How to read images present in the column of Excel. I used EPPlus to do that.
Here how it goes.
C# Code:
using OfficeOpenXml; using OfficeOpenXml.Drawing;
namespace ExcelRead {     public void Index()     {         using (ExcelPackage pck = new ExcelPackage())         {             FileStream fileStream = new FileStream(
@"C:\Docs\Pictures.xlsx", FileMode.Open, FileAccess.ReadWrite);
            pck.Load(fileStream);             GetImage(pck);         };     }              public static void GetImage(ExcelPackage excelFile)     {         var sheet = excelFile.Workbook.Worksheets.First();         foreach (ExcelDrawing i in sheet.Drawings)         {             string picname = i.Name;             ExcelPicture pic = sheet.Drawings[i.Name] as ExcelPicture;             Image img = pic.Image;             img.Save(@"C:\Docs\" + i.Name + ".png", ImageFormat.Png);         }     } }

Monday, September 10, 2018

interval in Observables

Observable.interval(1000).takeWhile(() => true).subscribe(a => {
console.log('called');
}
);

Thursday, September 6, 2018

Angular 6 CLI command

ng generate class [name] generates a class
ng generate component [name] generates a component
ng generate directive [name] generates a directive
ng generate enum [name] generates an enumeration
ng generate guard [name] generates a guard
ng generate interface [name] <type> generates an interface
ng generate module [name] generates an NgModule
ng generate pipe [name] generates a pipe
ng generate service [name] generates a service

ng build
ng test
ng doc

Monday, July 9, 2018

Pipes in Angular

Pipe: Pipes are easy way to encapsulate and share common display data. With the help of we can enrich the views and format display data.

Type of Pipes:
     1. Pure Pipe
     2. Impure Pipe

We can make pure and impure pipe's by setting pure: true or false. By default it is true.

@Pipe({
          name: 'formatcurrency',
          pure: true
})

Pure Pipe:
     When true, it means that the transform() method is invoke only when its input argument change.
 
Impure Pipe: 
     When false, it means that the method invoke every change-detection cycle. even if the argument are not change. Impure pipe called in every keystroke or move move, so be careful to implement it.

Chaining Pipes: 
      We can chain pipes together to get desired output. Like:
      {{ currencyname | formatcurrency | uppercase }}

Here output is: INR

Sunday, July 8, 2018

Order by pipe in Angular



import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'orderBy'
})
export class OrderPipe implements PipeTransform {
  transform(value: any, ...args: any[]): any {
    const sortOrder = args[0].sortOrder;
    const columnName = args[0].columnName;
    if (columnName) {
      const desc = !(sortOrder === 'asc');
      return value.sort(
        (a: any, b: any) =>
          !desc
            ? this.OrderByComparator(a[columnName], b[columnName])
            : -this.OrderByComparator(a[columnName], b[columnName])
      );
    } else {
      return value;
    }
  }
  public OrderByComparator(a: any, b: any): number {
    if (typeof a === 'string') {
      return this.typeofString(a, b);
    } else if (typeof a === 'number') {
      return this.typeofNumber(a, b);
    } else {
      return this.typeofDate(a, b);
    }
  }
  private typeofNumber(a: number, b: number): number {
    if (!a || !b) {
      return -1;
    }
    if (a < b) {
      return -1;
    }
    if (a > b) {
      return 1;
    }
    return 0; // equal each other
  }


  private typeofDate(a: Date, b: Date): number {
    if (!a || !b) {
      return -1;
    }
    if (a < b) {
      return -1;
    }
    if (a > b) {
      return 1;
    }
    return 0; // equal each other
  }
  private typeofString(a: string, b: string): number {
    if (!a || !b) {
      return -1;
    }
    if (a.toLowerCase() < b.toLowerCase()) {
      return -1;
    }
    if (a.toLowerCase() > b.toLowerCase()) {
      return 1;
    }

return 0; // equal each other
  }
}

------------- Component -----------------------------------

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public sort;
  private _columnName: string;
  public data: Array<Employee> = [
    {
      name: 'Ashutosh',
      dob: new Date('08/11/1987'),
      id: 10001,
      accountnumber: 'a123logq',
      salary: 209.92
    },
    {
      name: 'Shivangi',
      dob: new Date('08/11/1986'),
      id: 10003,
      accountnumber: 'a123logq',
      salary: 209.01
    },
    {
      name: 'Abhishek',
      dob: new Date('08/11/1985'),
      id: 10002,
      accountnumber: 'm123logq',
      salary: 209.21
    },
    {
      name: 'Halrgen',
      dob: new Date('08/11/1992'),
      id: 10004,
      accountnumber: 'a123logx',
      salary: 100.91
    },
    {
      name: 'Kevin',
      dob: new Date('08/11/1982'),
      id: 10005,
      accountnumber: 'a123dmgq',
      salary: 208.92
    },
    {
      name: 'Ram',
      dob: new Date('08/11/1988'),
      id: 10006,
      accountnumber: 'c123chnq',
      salary: 206.92
    },
    {
      name: 'Laxman',
      dob: new Date('08/11/1981'),
      id: 10007,

      accountnumber: 'b123iuwq',
      salary: 209.32
    },
    {
      name: 'Ullas',
      dob: new Date('08/11/1985'),
      id: 10091,
      accountnumber: 'b123iuwq',
      salary: 309.32
    }
  ];
  constructor() {
    this.sort = { sortOrder: 'asc', columnName: 'name' };
  }
  public onAscending() {
    this.sort = { sortOrder: 'asc', columnName: this._columnName };
  }
  public onDescending() {
    this.sort = { sortOrder: 'desc', columnName: this._columnName };
  }

  public onSelectSortColumn(columnName: any) {
    this._columnName = columnName;
  }
}
interface Employee {
  name: string;
  dob: Date;
  id: number;
  accountnumber: string;
  salary: number;
}

--------------------- Component Template ------------------------

<div class="container">
  <div class="row" style="margin-top:20px">
    <div class="col-md-12"></div>
    <button class="btn btn-primary" (click)="onAscending()">Ascending</button>
    <button class="btn btn-primary" (click)="onDescending()">Descending</button>
    <select class="form-control" style="width: 200px" (change)="onSelectSortColumn($event.target.value)">
      <option value="name">Name</option>
      <option value="id">Employee Id</option>
      <option value="dob">DOB</option>
      <option value="accountnumber">Account Number</option>
      <option value="salary">Salary</option>
    </select>
  </div>
  <br>
  <div class="row">
    <div class="table-responsive">
      <table class="table" >
        <tr>
          <th>Id</th>
          <th>Name</th>
          <th>DOB</th>
          <th>Account Number</th>
          <th>Salary</th>
        </tr>
        <tr *ngFor="let user of data | orderBy : sort">
          <td>{{user.id}}</td>
          <td>{{user.name}}</td>
          <td>{{user.dob | date}}</td>
          <td>{{user.accountnumber}}</td>
          <td>{{user.salary}}</td>
        </tr>
      </table>
    </div>
  </div>