i18n service and helpers

This commit is contained in:
Kyle Spearrin 2018-01-24 14:59:03 -05:00
parent 0e33ad9b0b
commit 2ab23c2c9e
9 changed files with 124 additions and 14 deletions

View File

@ -0,0 +1,5 @@
{
"hello": {
"message": "hello"
}
}

View File

@ -0,0 +1,5 @@
{
"hello": {
"message": "hola"
}
}

View File

@ -18,7 +18,6 @@ export class LoginComponent implements OnInit {
masterPassword: string = '';
constructor(private authService: AuthService, private router: Router) {
}
ngOnInit() {

View File

@ -11,6 +11,7 @@ import { AppComponent } from './app.component';
import { CiphersComponent } from './vault/ciphers.component';
import { FallbackSrcDirective } from './directives/fallback-src.directive';
import { GroupingsComponent } from './vault/groupings.component';
import { I18nPipe } from './pipes/i18n.pipe';
import { IconComponent } from './vault/icon.component';
import { LoginComponent } from './accounts/login.component';
import { StopClickDirective } from './directives/stop-click.directive';
@ -30,6 +31,7 @@ import { ViewComponent } from './vault/view.component';
CiphersComponent,
FallbackSrcDirective,
GroupingsComponent,
I18nPipe,
IconComponent,
LoginComponent,
StopClickDirective,

View File

@ -0,0 +1,18 @@
import {
Pipe,
PipeTransform,
} from '@angular/core';
import { I18nService } from '../../services/i18n.service';
@Pipe({
name: 'i18n',
})
export class I18nPipe implements PipeTransform {
constructor(private i18nService: I18nService) {
}
transform(id: string): string {
return this.i18nService.t(id);
}
}

View File

@ -1,11 +1,15 @@
import { webFrame } from 'electron';
import { NgModule } from '@angular/core';
import {
APP_INITIALIZER,
NgModule
} from '@angular/core';
import { DesktopMessagingService } from '../../services/desktopMessaging.service';
import { DesktopPlatformUtilsService } from '../../services/desktopPlatformUtils.service';
import { DesktopStorageService } from '../../services/desktopStorage.service';
import { DesktopSecureStorageService } from '../../services/desktopSecureStorage.service';
import { I18nService } from '../../services/i18n.service';
import {
ApiService,
@ -52,6 +56,7 @@ import {
webFrame.registerURLSchemeAsPrivileged('file');
const i18nService = new I18nService(window, './_locales');
const utilsService = new UtilsService();
const platformUtilsService = new DesktopPlatformUtilsService();
const messagingService = new DesktopMessagingService();
@ -69,7 +74,7 @@ const settingsService = new SettingsService(userService, storageService);
const cipherService = new CipherService(cryptoService, userService, settingsService,
apiService, storageService);
const folderService = new FolderService(cryptoService, userService,
() => 'No Folder', apiService, storageService);
() => i18nService.t('noneFolder'), apiService, storageService);
const collectionService = new CollectionService(cryptoService, userService, storageService);
const lockService = new LockService(cipherService, folderService, collectionService,
cryptoService, platformUtilsService, storageService,
@ -89,6 +94,10 @@ environmentService.setUrlsFromStorage().then(() => {
return syncService.fullSync(true);
});
function initFactory(i18n: I18nService): Function {
return () => i18n.init();
}
@NgModule({
imports: [],
declarations: [],
@ -98,6 +107,13 @@ environmentService.setUrlsFromStorage().then(() => {
{ provide: FolderServiceAbstraction, useValue: folderService },
{ provide: CollectionServiceAbstraction, useValue: collectionService },
{ provide: EnvironmentServiceAbstraction, useValue: environmentService },
{ provide: I18nService, useValue: i18nService },
{
provide: APP_INITIALIZER,
useFactory: initFactory,
deps: [I18nService],
multi: true
}
],
})
export class ServicesModule {

View File

@ -9,17 +9,19 @@
<span class="row-label">Name</span>
{{cipher.name}}
</div>
<div class="box-content-row">
<span class="row-label">URI</span>
{{cipher.login.uri}}
</div>
<div class="box-content-row">
<span class="row-label">Username</span>
{{cipher.login.username}}
</div>
<div class="box-content-row">
<span class="row-label">Password</span>
{{cipher.login.password}}
<div *ngIf="cipher.login">
<div class="box-content-row">
<span class="row-label">URI</span>
{{cipher.login.uri}}
</div>
<div class="box-content-row">
<span class="row-label">Username</span>
{{cipher.login.username}}
</div>
<div class="box-content-row">
<span class="row-label">Password</span>
{{cipher.login.password}}
</div>
</div>
</div>
<div class="box-footer">

View File

@ -0,0 +1,62 @@
// First locale is the default (English)
const SupportedLocales = [
'en', 'es',
];
export class I18nService {
defaultMessages: any = {};
localeMessages: any = {};
systemLanguage: string;
language: string;
inited: boolean;
constructor(win: Window, private localesDirectory: string) {
this.systemLanguage = win.navigator.language;
}
async init(language?: string) {
if (this.inited) {
throw new Error('i18n already initialized.');
}
this.inited = true;
this.language = language != null ? language : this.systemLanguage;
if (SupportedLocales.indexOf(this.language) === -1) {
this.language = this.language.slice(0, 2);
if (SupportedLocales.indexOf(this.language) === -1) {
this.language = SupportedLocales[0];
}
}
await this.loadMessages(this.language, this.localeMessages);
if (this.language !== SupportedLocales[0]) {
await this.loadMessages(SupportedLocales[0], this.defaultMessages);
}
}
t(id: string): string {
return this.translation(id);
}
translation(id: string): string {
if (this.localeMessages.hasOwnProperty(id) && this.localeMessages[id]) {
return this.localeMessages[id];
} else if (this.defaultMessages.hasOwnProperty(id) && this.defaultMessages[id]) {
return this.defaultMessages[id];
}
return '';
}
private async loadMessages(locale: string, messagesObj: any): Promise<any> {
const formattedLocale = locale.replace('-', '_');
const file = await fetch(this.localesDirectory + '/' + formattedLocale + '/messages.json');
const locales = await file.json();
for (const prop in locales) {
if (locales.hasOwnProperty(prop)) {
messagesObj[prop] = locales[prop].message;
}
}
}
}

View File

@ -57,6 +57,7 @@ const main = {
new CopyWebpackPlugin([
'./src/package.json',
{ from: './src/images', to: 'images' },
{ from: './src/_locales', to: '_locales' },
]),
],
externals: [nodeExternals()]