Support EN and use it by default (#96)

This commit is contained in:
Rinat Arsaev 2022-12-20 18:39:09 +06:00 committed by GitHub
parent 7c38e35b8d
commit d360c9cdbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 50 additions and 106 deletions

View File

@ -1,3 +1,3 @@
files:
- source: /src/assets/i18n/**/ru.json
translation: /%original_path%/%two_letters_code%.json
- source: /src/assets/i18n/**/ru.json
translation: /%original_path%/%two_letters_code%.json

View File

@ -13,7 +13,7 @@ import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { TRANSLOCO_CONFIG, TRANSLOCO_LOADER, TranslocoConfig, TranslocoModule } from '@ngneat/transloco';
import { TRANSLOCO_CONFIG, TRANSLOCO_LOADER, TranslocoModule, translocoConfig } from '@ngneat/transloco';
import * as Sentry from '@sentry/angular';
import { AnapiModule } from '@dsh/api/anapi';
@ -32,7 +32,7 @@ import { ENV, environment } from '../environments';
import { OrganizationsModule } from './api/organizations';
import { AppComponent } from './app.component';
import { AuthModule, KeycloakAngularModule, KeycloakService } from './auth';
import { ConfigModule, ConfigService } from './config';
import { ConfigService } from './config';
import { HomeModule } from './home';
import { IconsModule, IconsService } from './icons';
import { initializer } from './initializer';
@ -40,8 +40,7 @@ import { LanguageService } from './language';
import { SectionsModule } from './sections';
import { SentryErrorHandler } from './sentry-error-handler.service';
import { SentryHttpInterceptor } from './sentry-http-interceptor';
import { SettingsModule } from './settings';
import { ThemeManager, ThemeManagerModule } from './theme-manager';
import { ThemeManager } from './theme-manager';
import { TranslocoHttpLoaderService } from './transloco-http-loader.service';
@NgModule({
@ -52,10 +51,7 @@ import { TranslocoHttpLoaderService } from './transloco-http-loader.service';
BrowserAnimationsModule,
SectionsModule,
AuthModule,
ThemeManagerModule,
ConfigModule,
HomeModule,
SettingsModule,
KeycloakAngularModule,
HttpClientModule,
TranslocoModule,
@ -98,13 +94,13 @@ import { TranslocoHttpLoaderService } from './transloco-http-loader.service';
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { appearance: 'outline' } },
{
provide: TRANSLOCO_CONFIG,
useValue: {
reRenderOnLangChange: false,
defaultLang: 'ru',
availableLangs: ['ru'],
useValue: translocoConfig({
availableLangs: ['en', 'ru'],
defaultLang: 'en',
fallbackLang: 'ru',
reRenderOnLangChange: true,
prodMode: environment.production,
} as TranslocoConfig,
}),
},
{ provide: TRANSLOCO_LOADER, useClass: TranslocoHttpLoaderService },
{ provide: ENV, useValue: environment },

View File

@ -1,8 +0,0 @@
import { NgModule } from '@angular/core';
import { ConfigService } from './config.service';
@NgModule({
providers: [ConfigService],
})
export class ConfigModule {}

View File

@ -4,7 +4,7 @@ import { BehaviorSubject } from 'rxjs';
import { BASE_CONFIG, Config } from './config';
@Injectable()
@Injectable({ providedIn: 'root' })
export class ConfigService extends BASE_CONFIG {
isInit$ = new BehaviorSubject(false);

View File

@ -1,2 +1 @@
export * from './config.module';
export * from './config.service';

View File

@ -3,11 +3,10 @@ import { NgModule } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { RouterModule } from '@angular/router';
import { ConfigModule } from '../../config';
import { BrandComponent } from './brand.component';
@NgModule({
imports: [RouterModule, MatIconModule, HttpClientModule, ConfigModule],
imports: [RouterModule, MatIconModule, HttpClientModule],
declarations: [BrandComponent],
exports: [BrandComponent],
})

View File

@ -4,7 +4,6 @@ import { FlexLayoutModule } from '@angular/flex-layout';
import { MatIconModule } from '@angular/material/icon';
import { RouterModule } from '@angular/router';
import { ConfigModule } from '../config';
import { HomeComponent } from './home.component';
import { LaptopGridModule } from './laptop-grid/laptop-grid.module';
import { MobileGridModule } from './mobile-grid/mobile-grid.module';
@ -19,7 +18,6 @@ import { ToolbarModule } from './toolbar';
MatIconModule,
MobileGridModule,
LaptopGridModule,
ConfigModule,
],
declarations: [HomeComponent],
exports: [HomeComponent],

View File

@ -1,11 +1,9 @@
import { NgModule } from '@angular/core';
import { LanguageModule } from '../language';
import { HumanizeDurationService } from './humanize-duration.service';
import { HumanizedDurationPipe } from './humanized-duration.pipe';
@NgModule({
imports: [LanguageModule],
declarations: [HumanizedDurationPipe],
providers: [HumanizeDurationService],
exports: [HumanizedDurationPipe],

View File

@ -4,7 +4,7 @@ import * as humanizeDuration from 'humanize-duration';
import moment from 'moment';
import { Observable, of } from 'rxjs';
import { Language, LanguageService } from '../language';
import { LanguageService } from '../language';
export type Value = number | string | moment.Moment | Date;
@ -25,7 +25,7 @@ export class HumanizeDurationService {
private get duration() {
return humanizeDuration.humanizer({
language: this.languageService.active || Language.En,
language: this.languageService.active || 'en',
round: true,
delimiter: ' ',
});

View File

@ -1,9 +1,9 @@
import localeEn from '@angular/common/locales/en';
import localeRu from '@angular/common/locales/ru';
import { Language } from './language';
import { Language } from './languages';
export const ANGULAR_LOCALE_DATA: { [language in Language]: any } = {
[Language.Ru]: localeRu,
[Language.En]: localeEn,
ru: localeRu,
en: localeEn,
};

View File

@ -1,3 +1,2 @@
export * from './language.module';
export * from './language.service';
export * from './language';
export * from './languages';

View File

@ -1,10 +0,0 @@
import { NgModule } from '@angular/core';
import { SettingsModule } from '../settings';
import { LanguageService } from './language.service';
@NgModule({
imports: [SettingsModule],
providers: [LanguageService],
})
export class LanguageModule {}

View File

@ -5,44 +5,40 @@ import * as moment from 'moment';
import { SettingsService } from '../settings';
import { ANGULAR_LOCALE_DATA } from './angular-locale-data';
import { Language } from './language';
import { LANGUAGES, Language } from './languages';
@Injectable()
@Injectable({ providedIn: 'root' })
export class LanguageService {
// eslint-disable-next-line @typescript-eslint/naming-convention
private static readonly KEY = 'language';
// eslint-disable-next-line @typescript-eslint/member-ordering
active: Language;
private static readonly key = 'language';
constructor(private settingsService: SettingsService, private transloco: TranslocoService) {}
async init() {
const language = this.settingsService.getLocalStorageItem(LanguageService.KEY);
const correctedLanguage = this.getCorrectLanguage(language);
await this.change(correctedLanguage);
// TODO: Use after language change support starts
// const storageLang = this.settingsService.getLocalStorageItem(LanguageService.key);
const storageLang = null;
let language: Language;
if (Array.from<string>(LANGUAGES).includes(storageLang)) {
language = storageLang as Language;
} else {
const browserLang: string =
navigator.language || (navigator as never as Record<PropertyKey, string>).userLanguage;
language = Array.from<string>(LANGUAGES).includes(browserLang)
? (browserLang as Language)
: this.active || 'en';
}
await this.set(language);
}
async change(language: Language) {
registerLocaleData(ANGULAR_LOCALE_DATA[language], language);
if (language !== Language.En) {
await import(`moment/locale/${language}`);
}
moment.locale(language);
this.settingsService.setLocalStorageItem(LanguageService.KEY, language);
this.transloco.setActiveLang(language);
// TODO: Make it public after language change support starts
private async set(language: Language) {
this.active = language;
}
private getCorrectLanguage(language: Language | string): Language {
if (!Object.values<string>(Language).includes(language)) {
return this.getRecommended();
}
return language as Language;
}
private getRecommended(): Language {
const language = navigator.language || (navigator as any).userLanguage;
return Object.values(Language).includes(language) ? language : this.active || Language.Ru;
registerLocaleData(ANGULAR_LOCALE_DATA[language], language);
if (language !== 'en') await import(`moment/locale/${language}`);
moment.locale(language);
this.settingsService.setLocalStorageItem(LanguageService.key, language);
this.transloco.setActiveLang(language);
}
}

View File

@ -1,4 +0,0 @@
export enum Language {
Ru = 'ru',
En = 'en',
}

View File

@ -0,0 +1,4 @@
import { ValuesType } from 'utility-types';
export const LANGUAGES = ['ru', 'en'] as const;
export type Language = ValuesType<typeof LANGUAGES>;

View File

@ -24,7 +24,6 @@ import { LayoutModule } from '@dsh/components/layout';
import { StateNavModule } from '@dsh/components/navigation';
import { ShowMorePanelModule } from '@dsh/components/show-more-panel';
import { LanguageModule } from '../../../../language';
import { CreateInvoiceModule } from './create-invoice';
import { InvoicesListModule } from './invoices-list';
import { InvoicesRoutingModule } from './invoices-routing.module';
@ -49,7 +48,6 @@ import { InvoicesComponent } from './invoices.component';
MatSnackBarModule,
StateNavModule,
TranslocoModule,
LanguageModule,
MatMenuModule,
EmptySearchResultModule,
MatDialogModule,

View File

@ -1,2 +1 @@
export * from './settings.module';
export * from './settings.service';

View File

@ -1,8 +0,0 @@
import { NgModule } from '@angular/core';
import { SettingsService } from './settings.service';
@NgModule({
providers: [SettingsService],
})
export class SettingsModule {}

View File

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
@Injectable()
@Injectable({ providedIn: 'root' })
export class SettingsService {
setLocalStorageItem(key: string, value: string) {
localStorage.setItem(this.getKeyName(key), value);

View File

@ -1,5 +1,4 @@
export * from './theme-manager.service';
export * from './theme-manager.module';
export * from './types/palette-color';
export * from './types/status-color';
export * from './types/theme-name';

View File

@ -1,11 +0,0 @@
import { NgModule } from '@angular/core';
import { ConfigModule } from '../config';
import { SettingsModule } from '../settings';
import { ThemeManager } from './theme-manager.service';
@NgModule({
imports: [SettingsModule, ConfigModule],
providers: [ThemeManager],
})
export class ThemeManagerModule {}

View File

@ -8,7 +8,7 @@ import { isTheme } from './utils/is-theme';
const THEME_POSTFIX = 'theme';
@Injectable()
@Injectable({ providedIn: 'root' })
export class ThemeManager {
current: ThemeName;

View File

@ -1,5 +1,5 @@
module.exports = {
langs: ['ru'],
langs: ['en', 'ru'],
keysManager: {
input: './',
fileFormat: 'json',