Skip to main content

Using Angular’s Internationalization Features

Introduction

Today, the users access to the Web apps through a wide variety of devices, such as laptops, tablets, smartPhones, desktop computers, etc..., which have different screen sizes and resolutions. On the other hand, one of the principles of accessibility is to get as many users as possible enriching and satisfying the experience in accessing applications overcoming both physical barriers (hearing, visual disabilities, cognitive, etc ...) as well as material or technological. Today, there are users who connect from different devices, as we have already indicated, and also with different technological features such as the bandwidth of internet network.

In addition, there are web applications that have high visual content, and therefore, a lot of images. These images are normally stored on a CDN (Content-Delivery-Network) from which the images are downloaded to the device.

In some specific areas of the world, or circumstances, downloading all these images can mean a bandwidth that is excessive for the users. Similarly, any optimization, even to users who have high performance devices is a benefit since the app will be available sooner.

In this post, we are going to show step by step how to build an Angular application with responsive images for different sizes although it could be for any technology.


Problem to solve

The problem I have solved is the one I have experienced for the open source project Angular-Communities. This project consists of a Google Map in which the shields of the different Angular communities around the world are displayed. Also, on a side-nav we find all the shields of the different communities, so we can navigate and select them for advanced information on those Angular communities. Allow me to tell you, just as an aside, do not hesitate and add your community to this map so that we can all have the information of your community.

In this specific problem, we had,at the date of this post, about 70 communities, each with its personalized shield. Each of these shields is an scalar image in PNG format that can be between 13KiB — 186KiB. The 70 images have a size of 2.6MiB. In this situation, we need to download all the images at the beginning, not being able to perform a technique lazy to download the images. This simplifies the code and the development complexity drastically. However, it seems worrying that all devices, no matter their sizes, have to download 2.6MiB every time that access the website, causing an unnecessary loss of performance.

For this post, I have built a small demo in which all the images from Angular-Communitiesare downloaded in a single component with the final result of the post.

The following table shows the size of the images according to the format and the image size. It can be seen that the format getting the smallest file size, even with the same image size, is .webp.


-------------
raw  | xs.png | xs.webp | sm.png | sm.webp | md.png | md.webp | lg.png | lg.webp | xl.png | xl.webp |
2.6M | 776K   | 504K    | 900K   | 560K    | 1.1M   | 628K    | 1.1M   | 656K    | 1.1M   | 680K    | 
-----

Create images of different sizes and formats

Imagine we had to edit each of the images with a software graphic editing, such as Gimp or Photoshop, manually. This would provoke a great amount of time invested just changing the size, quality and format of the images. We might think that doing this task only once for our task it could be a tedious but valid task (still I think that we should not do it manually, being able to do it automatically). However, this task gets more complicated if the images we want to carry out the process to gradually increases by interaction with the users or even if we have to make different adjustments to the sizes and qualities that we want to generate for each of the images.

Therefore, the ideal would be to have a tool/script that allows us to automate this task so that it is only a matter of executing a simple script and all our battery of images is generated automatically.

In our context, we are going to use a tool built using node.js since installing it and using it in our Angular application does not require the installation of new applications or package managers for different programming languages.

The chosen tool is responsive-image-builder (RIB), which is defined as a building pipelineof images in.Webp format ultra fast for the Web. The time it will take to generate the images will depend on your processor or the processor of your integration system and the number of images to be transformed.

RIB Features

  • ⚡ Fast — Uses the lightning-quick libvips image processing.
  • 🔥 Multithreaded — Scales to all available CPU cores.
  • 📦 Zero configuration — Change nothing, change everything. You choose.
  • 🌍 Universal — a flexible image build process that doesn’t enforce any principles.
  • ✂️ Cross-platform — Tested on Windows, macOS and Linux.
  • 😊 Friendly experience — telling you what’s going on, from start to finish.

All these features make this open-source tool ideal for our purpose. First of all, we install the package as a development dependency.

rib -i <input> -o <output> <options>

The use of this tool is quite simple since we only have to specify the parameters of the following command:

"pre:deploy": "rib -i src/assets/images_raw -o src/assets/images --no-clean --force"

Therefore, if we want to include in our deploy pipeline that all the images in a certain directory are transformed and generated in a new directory, we can build the following npm-script that runs just before the deploy task.

Although one of the characteristics of this tool/package is that it does not need configuration, in our specific case we want to build a responsive application in which each screen size has a set of images adjusted to its parameters. In other words, when a user accesses the Web page from a mobile device, they must download images that are the appropriate size for that device, images that are lighter than the ones for large screens, and when accessed from a device with a large screen, laptop or smartTV high resolution images can be enjoyed.

Therefore, we must configure the different sizes of images that we want to automatically generate. This configuration is done by creating a file called .ribrc.json in which an array is specified with the different configurations or image generation formats that you want to generate from each of the original images. Thus, each of the configurations allows you to specify a suffix using the name *property, the width of the image using the *width property, and that you want to force the creation of the image (it is overwritten if a previous one already exists) with the force property.

Therefore, in our configuration file, we are specifying that we will generate five images from each of the original images that will have the configurations as prefixes: xs, sm, md, lg and xl.


{
  "exportPresets": [
    {
      "name": "xs",
      "width": 240,
      "force": true
    },
    {
      "name": "sm",
      "width": 320,
      "force": true,
      "default": true
    },
    {
      "name": "md",
      "width": 480,
      "force": true
    },
    {
      "name": "lg",
      "width": 640,
      "force": true
    },
    {
      "name": "xl",
      "width": 1024,
      "force": true
    }
  ]
}

Also, rib generates all images in the original format, .png or .jpg and in the .webpformat. So if the browser supports the .webp format, it uses this one instead of the previous ones. The following section shows how you can delegate responsibility for using one image or another to the HTML (using the picture element).


Picture Element

HTML5 introduced the <picture> element which allows more flexibility to specify images compared to the <img> element. The most common use of the <picture>element is to delegate responsibility for images in adaptive layouts to the browser via HTML. In other words, instead of scaling large images using the CSS width property, the most appropriate image can be selected depending on the device that is accessing the web application.

The <picture> element consists of two tags: one or more <source> elements and an <img> element. The browser checks the first <source> element that satisfies the media query with the device that is accessing the web application, and the image specified in the srcset attribute will be displayed. The <img> element is used as the fallback option in case the media query of any <source> element is not satisfied.



responsiveImagesConfiguration = [
    {
      min: 0,
      max: 599,
      suffix: '_xs',
      format: 'webp',
    },
    {
      min: 0,
      max: 599,
      suffix: '_xs',
      format: 'png',
    },
    {
      min: 600,
      max: 959,
      suffix: '_sm',
      format: 'webp',
    },
    {
      min: 600,
      max: 959,
      suffix: '_sm',
      format: 'png',
    },
    {
      min: 960,
      max: 1279,
      suffix: '_md',
      format: 'webp',
    },
    {
      min: 960,
      max: 1279,
      suffix: '_md',
      format: 'png',
    },
    {
      min: 1280,
      max: 1919,
      suffix: '_lg',
      format: 'webp',
    },
    {
      min: 1280,
      max: 1919,
      suffix: '_lg',
      format: 'png',
    },
    {
      min: 1920,
      max: 5000,
      suffix: '_xl',
      format: 'webp',
    },

    {
      min: 1920,
      max: 5000,
      suffix: '_xl',
      format: 'png',
    },
  ];

In our Angular component, we define an array of configuration of the images to show in the template. In this array we define several properties:
<picture *ngFor="let community of communities | keyvalue">
  <source
    *ngFor="let media of responsiveImagesConfiguration"
    [media]="
      '(max-width: ' + media.max + 'px) and (min-width: ' + media.min + 'px)'
    "
    [srcset]="
      './assets/images/' +
      community.value.id +
      media.suffix +
      '.' +
      media.format
    "
    [type]="'image/' + media.format"
  />

  <img
    alt="{{ community.name }} logo"
    [src]="'./assets/images/' + community.value.id + '_md.png'"
  />
</picture>

  • min/max: width viewport of the device that accesses the Web application.
  • suffix: The image suffix.
  • format: Format of the image, having the formats .webp and .png.

In our template, we only need to go through the array defined above to generate the <source> and <img> elements to delegate responsibility to the template.


Result

The result obtained after performing these simple steps is that we have a directory with the images in deploy with different sizes and formats to be used depending on the device that accesses the Web application. The following images show the result of our application, which downloads some images or others depending on the device that accesses the application. The images show the images that would be downloaded by a mobile device and a large screen device (large monitors or television). In this way, we are providing greater accessibility to our Web











































Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...