Skip to content

Localization

This suite module provides the translation core to the Angular apps, here you can switch between available languages, translate resources and display texts based on the current locale.

Note

The Suite localization feature uses the underlying Angular i18n scaffolding, therefore most of the features,characteristics and limitations of i18n library remains valid.

The current feature configuration is provided by the backend, which feeds all the required values for the localization feature to work properly. The most relevant configuration values are:

  • The current culture
  • The set of available cultures

The current culture will be used to get the proper resources for template and typescript translations. In the other hand, the set of available cultures let us know the currently supported cultures by the application.

Important

To provide a consistent user experience we encourage you to develop your application with localization in mind, this means that the application must interact with the user displaying texts using the proper language.

Loading localization resources

The Suite Framework loads the localization resources from a static json file at a specific location: assets/i18n/{culture-name}.json, relative to the application location. The file location starts at the folder /assets/i18n,
followed by the {culture-name}, which is determined by the current configuration mentioned before, and finally ends with the .json extension. For example, for en-US current culture, the resources will be loaded from assets/i18n/en-US.json.

Note

In future releases of the Suite Framework the resource localization file will be loaded directly from the backend, instead of using static file assets. Nevertheless you shouldn't even note this change, because it won't affect any public api in use.

Localizing your app

The Suite Framework will add the necessary imports, and configuration needs, to make the localization features available, these imports include the reference to localization init, as stand below:

TypeScript
import '@angular/localize/init';

Info

@angular/localize is a new package that supports i18n of messages in Ivy applications. This package requires a global $localize symbol to exist. The symbol is loaded by importing the @angular/localize/init module, which has the side-effect of attaching it to the global scope.

Template localization

To translate the texts present on templates we are going to use the attribute i18n (note that this attribute isn't an Angular directive).

The following is an example of how to localize a text in a template:

HTML
<h1 i18n="@@LBL_WELCOME">LBL_WELCOME</h1>

Note

In order to be able to detect which of the resource are translated and which of those are missing, we encourage you not to use a real text for the content of the element being localized, please use the same resource localization key instead. By mean of using the same key as the content you will be able to recognize at runtime those missing resources in your module's resource localization bundle.

You can use the browser console log to identify the missing resources as well, but these hints are likely to be omitted when the log entry count grow up as the application becomes bigger.

It is also possible to use i18n to mark element's attributes for translation as well, this is explained in the i18n documentation.

The following example shows how to provide translations for several attributes of a component template.

HTML
1
2
3
4
5
6
7
8
    <mat-form-field appearance="legacy">
        <mat-label i18n="@@LBL_COMPONENT_LABEL">LBL_COMPONENT_LABEL</mat-label>
        <input matInput
                i18n-placeholder="@@LBL_COMPONENT_PLACEHOLDER"
                placeholder="LBL_COMPONENT_PLACEHOLDER">
        <mat-icon matSuffix>sentiment_very_satisfied</mat-icon>
        <mat-hint i18n="@@LBL_COMPONENT_HINT">LBL_COMPONENT_HINT</mat-hint>
    </mat-form-field>

Please note the usage of different i18n-{attribute} usage to provide localized values for those properties.

Also a model binding can be used to provide the localized values, those values comes from the component model and can be obtained by mean of using $localize function directly in typescript, as you can see later in next section.

HTML
1
2
3
4
5
6
    <mat-form-field appearance="legacy">
        <mat-label>{{componentLabel}}</mat-label>
        <input matInput placeholder="{{componentPlaceHolder}}">
        <mat-icon matSuffix>sentiment_very_satisfied</mat-icon>
        <mat-hint>{{componentHint}}</mat-hint>
    </mat-form-field>

Typescript localization

To translate resources in typescript files you will need to use the $localize function. This function must be used as shown here below:

TypeScript
    const label = $localize`:meaning|description@@id:message`

The $localize argument is a composed by:

  • meaning and description are useful when translation files are extracted out of the source code and then sent to translators to perform their job, they providing context on where is this term is used and what is it used for. We will not be using template files, therefore these values tends to be not useful for our purposes.
  • id is the resource key, this resource must be expressed as @@ + key name, and identify the required localization resource.
  • message is a default message, used when no translation is available for the specified id.

Even though the $localize allows us to provide metadata, the same rule as we saw before runs here for the typescript localization: don't use real texts as default values because it would be difficult to find out which of them are missing afterwards.

Warning

When localizing typescript assets is very likely to providing only the key value. In such cases the correct $localize argument for invocation is:

TypeScript
    const label = $localize`:@@key:`

Don't forget the leading and trailing colons, otherwise the i18n scaffolding will be unable to provide the localized value because will not recognize the argument as a valid localization key.

Important

When choosing an id for the resource please follow the the .NET Naming Convention

Format data based on locale

Besides translations, the localization feature also manage how to display resources using the configured locale.

Dates, decimals, currencies and percentages values can be shown in different ways depending the selected locale, to do that you can use the pipes provided by angular, we provide a nutshell which configure the locale and register the required locale configuration without any additional configuration.

Pipes which support localization:

  1. DatePipe: Formats a date value.

  2. DecimalPipe: Transforms a number into a decimal number string.

  3. PercentPipe: Transforms a number to a percentage string.

  4. CurrencyPipe: Transforms a number to a currency string.

The suite will set the current culture as value of the "LOCALE_ID" token, this will configure all the pipes.

To use the locales formats, you have to import and register the locales that your SPA needs to support.

In the example bellow we are importing 'es' and then in the modules declarations the locale is registered:

TypeScript
import es from '@angular/common/locales/es';

@NgModule({
    imports: [
        // ...
        SuiteLocalizationDomainModule.forRoot([es])
        // ...
    ]
})
export class AppModule extends BaseSuiteAppModule {}

Once the locale was added, it will be used by default if the LOCALE_ID is 'es', this token is set internally by the localization module using the CurrentLocaleId property that comes from the SPA configuration.

Multi locale support

In case you need to show information in two different locales, you can set to each pipe the localeId.

Let see some examples:

DatePipe

  • With default locale:

    HTML
    <!-- DateObject | date:[ : Format [ : timezone [: LocaleId ]]]-->
    <p>{{ birthday | date}}</p>
    
  • With default locale, custom format and custom timezone:

    HTML
    <!-- DateObject | date:[ : Format [ : timezone [: LocaleId ]]]-->
    <p>{{ birthday | date: 'medium' : 'UTC' }}</p>
    
  • With custom locale, custom format and custom timezone:

    HTML
    <!-- DateObject | date:[ : Format [ : timezone [: LocaleId ]]]-->
    <p>{{ birthday | date: 'medium' : 'UTC -3' : 'es-AR'}}</p>
    
  • With custom locale, custom format and default timezone:

    HTML
    <!-- DateObject | date:[ : Format [ : timezone [: LocaleId ]]]-->
    <p>{{ birthday | date: 'medium' : undefined : 'en'}}</p>
    

DecimalPipe

  • With default locale:

    HTML
    <!-- {{ DecimalValue | number [ : digitsInfo [ : locale ] ] }}-->
    <p>{{ kilometers | number}}</p>
    
  • With default locale and custom digits:

    HTML
    <!-- {{ DecimalValue | number [ : digitsInfo [ : locale ] ] }}-->
    <p>{{ kilometers | number:'3:1-3'}}</p>
    
  • With custom locale, custom digits and custom localeId:

    HTML
    <!-- {{ DecimalValue | number [ : digitsInfo [ : locale ] ] }}-->
    <p>{{ kilometers | number:'4.5-5':'fr'}}</p>
    

PercentagePipe

  • With default locale:

    HTML
    <!-- {{ value_expression | percent [ : digitsInfo [ : locale ] ] }}-->
    <p>{{ completed | percent}}</p>
    
  • With default locale and custom digits:

    HTML
    1
    2
    3
    <!--The output should look like: '0,134.950%'-->
    <!-- {{ DecimalValue | percent [ : digitsInfo [ : locale ] ] }}-->
    <p>{{ kilometers | percent:'4.3-5'}}</p>
    
  • With custom locale, custom digits and custom localeId:

    HTML
    1
    2
    3
    <!--The output should look like: '0 134,950 %'-->
    <!-- {{ DecimalValue | percent [ : digitsInfo [ : locale ] ] }}-->
    <p>{{ kilometers | percent:'4.3-5':'fr'}}</p>
    

CurrencyPipe

  • With default locale:

    HTML
    1
    2
    3
    <!--The output should look like: '$0.26'-->
    <!-- {{ value_expression | currency [ : currencyCode [ : display [ : digitsInfo [ : locale ] ] ] ] }} -->
    <p>{{ cost | currency}}</p>
    
  • With custom locale, custom code and custom locale:

    HTML
    <!-- {{ value_expression | currency [ : currencyCode [ : display [ : digitsInfo [ : locale ] ] ] ] }} -->
    <p>{{ cost | currency:'USD':'symbol':undefined:'es'}}</p>
    
  • With custom locale, custom digits, custom display and custom localeId:

    HTML
    1
    2
    3
    <!--The output should look like: '0 001,35 $'-->
    <!-- {{ value_expression | currency [ : currencyCode [ : display [ : digitsInfo [ : locale ] ] ] ] }} -->
    <p>{{ cost | currency:'CAD':'symbol-narrow':'4.2-2':'fr'}}</p>