• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

robisim74/angular-l10n: An Angular library to translate texts, dates and numbers

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

robisim74/angular-l10n

开源软件地址(OpenSource Url):

https://github.com/robisim74/angular-l10n

开源编程语言(OpenSource Language):

TypeScript 93.1%

开源软件介绍(OpenSource Introduction):

Angular l10n

Node.js CI npm version npm npm

An Angular library to translate texts, dates and numbers

This library is for localization of Angular apps. It allows, in addition to translation, to format dates and numbers through Internationalization API

Documentation

Angular l10n Specification

Architecture

Architecture

Table of Contents

Installation

npm install angular-l10n --save 

Usage

You can find a complete sample app here and a live example on StackBlitz

Configuration

Create the configuration:

export const l10nConfig: L10nConfig = {
    format: 'language-region',
    providers: [
        { name: 'app', asset: i18nAsset }
    ],
    cache: true,
    keySeparator: '.',
    defaultLocale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' },
    schema: [
        { locale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles', units: { 'length': 'mile' } }, dir: 'ltr', text: 'United States' },
        { locale: { language: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome', units: { 'length': 'kilometer' } }, dir: 'ltr', text: 'Italia' }
    ],
};

const i18nAsset = {
    'en-US': {
        greeting: 'Hello world!',
        whoIAm: 'I am {{name}}',
        devs: {
            one: 'One software developer',
            other: '{{value}} software developers'
        }
    },
    'it-IT': {
        greeting: 'Ciao mondo!',
        whoIAm: 'Sono {{name}}',
        devs: {
            one: 'Uno sviluppatore software',
            other: "{{ value }} sviluppatori software"
        }
    }
};

Do you only need to localize and not translate? Give the providers an empty array, but provide the supported locales in the schema anyway

Import the modules and the configuration:

@NgModule({
    ...
    imports: [
        ...
        L10nTranslationModule.forRoot(l10nConfig),
        L10nIntlModule
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

Getting the translation

Pure Pipes

<!-- translate pipe -->
<p>{{ 'greeting' | translate:locale.language }}</p>
<!-- translate pipe with attributes -->
<p title="{{ 'greeting' | translate:locale.language }}">{{ 'greeting' | translate:locale.language }}</p>
<!-- Hello world! -->

<!-- translate pipe with params -->
<p>{{ 'whoIAm' | translate:locale.language:{ name: 'Angular l10n' } }}</p>
<!-- I am Angular l10n -->

<!-- l10nDate pipe -->
<p>{{ today | l10nDate:locale.language:{ dateStyle: 'full', timeStyle: 'short' } }}</p>
<!-- Wednesday, November 10, 2021, 2:17 PM -->

<!-- l10nTimeAgo pipe -->
<p>{{ -4 | l10nTimeAgo:locale.language:'second':{ numeric:'always', style:'long' } }}</p>
<!-- 4 seconds ago -->

<!-- l10nNumber pipe -->
<p>{{ 1000 | l10nNumber:locale.language:{ digits: '1.2-2', style: 'currency' } }}</p>
<!-- $1,000.00 -->

<!-- l10nNumber pipe with convert function -->
<p>{{ 1000 | l10nNumber:locale.language:{ digits: '1.2-2', style: 'currency' }:locale.currency:convertCurrency:{ rate: 1.16 } }}</p>
<!-- $1,160.00 -->

<!-- l10nNumber pipe with unit & convert function -->
<p>{{ 1 | l10nNumber:locale.language:{ digits: '1.0-2', style: 'unit', unit: locale.units['length'] }:undefined:convertLength }}</p>
<!-- 0.62 mi -->

<!-- l10nPlural pipe -->
<p>{{ 2 | l10nPlural:locale.language:'devs':{ type: 'cardinal' } }}</p>
<!-- 2 software developers -->

<!-- l10nDisplayNames pipe -->
<p>{{ 'en-US' | l10nDisplayNames:locale.language:{ type: 'language' } }}</p>
<!-- American English -->

Pure pipes need to know when the locale changes. So import L10nLocale injection token in every component that uses them:

export class PipeComponent {

    constructor(@Inject(L10N_LOCALE) public locale: L10nLocale) { }

}

or if you prefer the shortest inject function:

export class PipeComponent {

    locale = inject(L10N_LOCALE);

}
Convert function

An optional function to convert the value of numbers, with the same value, locale and destructured optional parameters in the signature:

export const convertCurrency = (value: number, locale: L10nLocale, rate: number) => {
    switch (locale.currency) {
        case "USD":
            return value * rate;
        default:
            return value;
    }
};
OnPush Change Detection Strategy

To support this strategy, there is an Async version of each pipe, which recognizes by itself when the locale changes:

<p>{{ 'greeting' | translateAsync }}</p>

Directives

<!-- l10nTranslate directive -->
<p l10nTranslate>greeting</p>
<!-- l10nTranslate directive with attributes -->
<p l10n-title title="greeting" l10nTranslate>greeting</p>
<!-- l10nTranslate directive with params -->
<p [params]="{ name: 'Angular l10n' }" l10nTranslate>whoIAm</p>

<!-- l10nDate directive -->
<p [options]="{ dateStyle: 'full', timeStyle: 'short' }" l10nDate>{{ today }}</p>

<!-- l10nTimeAgo directive -->
<p [options]="{ numeric:'always', style:'long' }" unit="second" l10nTimeAgo>-4</p>

<!-- l10nNumber directive -->
<p [options]="{ digits: '1.2-2', style: 'currency' }" l10nNumber>1000</p>
<!-- l10nNumber directive with convert function -->
<p [options]="{ digits: '1.2-2', style: 'currency' }" [convert]="convertCurrency" [convertParams]="{ rate: 1.16 }" l10nNumber>1000</p>
<!-- l10nNumber directive with unit & convert function -->
<p [options]="{ digits: '1.0-2', style: 'unit', unit: locale.units['length'] }" [convert]="convertLength" l10nNumber>1</p>

<!-- l10nPlural directive -->
<p [options]="{ type: 'cardinal' }" prefix="devs" l10nPlural>2</p>

<!-- l10nDisplayNames directive -->
<p [options]="{ type: 'language' }" l10nDisplayNames>en-US</p>

You can dynamically change parameters and expressions values as with pipes, but not in attributes.

APIs

L10nTranslationService provides an onChange event, which is fired whenever the locale changes.

export class ApiComponent implements OnInit {

    constructor(private translation: L10nTranslationService, private intl: L10nIntlService) { }

    ngOnInit() {
        this.translation.onChange().subscribe({
            next: (locale: L10nLocale) => {
                // Texts
                this.greeting = this.translation.translate('greeting');
                this.whoIAm = this.translation.translate('whoIAm', { name: 'Angular l10n' });
                // Dates
                this.formattedToday = this.intl.formatDate(this.today, { dateStyle: 'full', timeStyle: 'short' });
                this.formattedTimeAgo = this.intl.formatRelativeTime(-4, 'second', { numeric: 'always', style: 'long' });
                // Numbers
                this.formattedValue = this.intl.formatNumber(
                    1000,
                    { digits: '1.2-2', style: 'currency' },
                    undefined,
                    undefined,
                    convertCurrency,
                    { rate: 1.16 }
                );
                this.formattedLength = this.intl.formatNumber(
                    1,
                    { digits: '1.0-2', style: 'unit', unit: locale.units['length'] },
                    undefined,
                    undefined,
                    convertLength
                );
                this.formattedOnePlural = this.intl.plural(1, 'devs', { type: 'cardinal' });
                this.formattedOtherPlural = this.intl.plural(2, 'devs', { type: 'cardinal' });
            }
        });
    }

}

L10nIntlService provides methods for all Intl APIs, including Collator & ListFormat.

Changing the locale

You can change the locale at runtime at any time by calling the setLocale method of L10nTranslationService:

<button *ngFor="let item of schema" (click)="setLocale(item.locale)">{{ item.locale.language | l10nDisplayNames:locale.language:{ type: 'language' } }}</button>
export class AppComponent {

    schema = this.l10nConfig.schema;

    constructor(@Inject(L10N_CONFIG) private l10nConfig: L10nConfig, private translation: L10nTranslationService) { }

    setLocale(locale: L10nLocale): void {
        this.translation.setLocale(locale);
    }

}

It is not mandatory to use the schema provided during the configuration: it is possible to set the language or currency, or any other property of L10nLocale separately.

Customize the library

The following features can be customized. You just have to implement the indicated class-interface and pass the token during configuration.

E.g.

@Injectable() export class HttpTranslationLoader implements L10nTranslationLoader {

    private headers = new HttpHeaders({ 'Content-Type': 'application/json' });

    constructor(@Optional() private http: HttpClient) { }

    public get(language: string, provider: L10nProvider): Observable<{ [key: string]: any }> {
        const url = `${provider.asset}-${language}.json`;
        const options = {
            headers: this.headers,
            params: new HttpParams().set('v', provider.options.version)
        };
        return this.http.get(url, options);
    }

}

export const l10nConfig: L10nConfig = {
    ...
    providers: [
        { name: 'app', asset: './assets/i18n/app', options: { version: '1.0.0' } },
    ],
    ...
};

@NgModule({
    ...
    imports: [
        ...
        L10nTranslationModule.forRoot(
            l10nConfig,
            {
                translationLoader: HttpTranslationLoader
            }
        )
    ],
    ...
})
export class AppModule { }

Storage

By default, the library does not store the locale. To store it implement the L10nStorage class-interface using what you need, such as web storage or cookie, so that the next time the user has the locale he selected.

User Language

By default, the library attempts to set the locale using the user's browser language, before falling back on the default locale. You can change this behavior by implementing the L10nUserLanguage class-interface, for example to get the language via server.

Translation Loader

By default, you can only pass JavaScript objects as translation data provider. To implement a different loader, you can implement the L10nTranslationLoader class-interface, as in the example above.

Translation Fallback

You can enable translation fallback during configuration:

export const l10nConfig: L10nConfig = {
    ...
    fallback: true,
    ...
};

By default, the translation data will be merged in the following order:

  • 'language'
  • 'language[-script]'
  • 'language[-script][-region]'

To change it, implement the L10nTranslationFallback class-interface.

Translation Handler

By default, the library only parse the params. L10nTranslationHandler is the class-interface to implement to modify the behavior.

Missing Translation Handler

If a key is not found, the same key is returned. To return a different value, you can implement the L10nMissingTranslationHandler class-interface.

Loader

If you need to preload some data before initialization of the library, you can implement the L10nLoader class-interface:

@Injectable() export class AppLoader implements L10nLoader {
    constructor(private translation: L10nTranslationService) { }

    public async init(): Promise<void> {
        await ... // Some custom data loading action
        await this.translation.init();
    }
                      

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap