mirror of
https://github.com/bitwarden/desktop.git
synced 2024-11-28 12:35:40 +01:00
i18n service and helpers
This commit is contained in:
parent
0e33ad9b0b
commit
2ab23c2c9e
5
src/_locales/en/messages.json
Normal file
5
src/_locales/en/messages.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"hello": {
|
||||
"message": "hello"
|
||||
}
|
||||
}
|
5
src/_locales/es/messages.json
Normal file
5
src/_locales/es/messages.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"hello": {
|
||||
"message": "hola"
|
||||
}
|
||||
}
|
@ -18,7 +18,6 @@ export class LoginComponent implements OnInit {
|
||||
masterPassword: string = '';
|
||||
|
||||
constructor(private authService: AuthService, private router: Router) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -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,
|
||||
|
18
src/app/pipes/i18n.pipe.ts
Normal file
18
src/app/pipes/i18n.pipe.ts
Normal 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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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">
|
||||
|
62
src/services/i18n.service.ts
Normal file
62
src/services/i18n.service.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -57,6 +57,7 @@ const main = {
|
||||
new CopyWebpackPlugin([
|
||||
'./src/package.json',
|
||||
{ from: './src/images', to: 'images' },
|
||||
{ from: './src/_locales', to: '_locales' },
|
||||
]),
|
||||
],
|
||||
externals: [nodeExternals()]
|
||||
|
Loading…
Reference in New Issue
Block a user