Localize routes (#2250)

* Localize about path

* Localize faq path

* Localize features path

* Localize markets path

* Localize pricing path

* Localize register path

* Localize resources path

* Extend sitemap
pull/2251/head
Thomas Kaul 1 year ago committed by GitHub
parent ff59fd4196
commit 02dc7c52b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -322,6 +322,10 @@
<loc>https://ghostfol.io/es/sobre/licencia</loc> <loc>https://ghostfol.io/es/sobre/licencia</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url>
<loc>https://ghostfol.io/es/sobre/oss-friends</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url>
<url> <url>
<loc>https://ghostfol.io/es/sobre/politica-de-privacidad</loc> <loc>https://ghostfol.io/es/sobre/politica-de-privacidad</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
@ -342,6 +346,10 @@
<loc>https://ghostfol.io/fr/a-propos/licence</loc> <loc>https://ghostfol.io/fr/a-propos/licence</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url>
<loc>https://ghostfol.io/fr/a-propos/oss-friends</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url>
<url> <url>
<loc>https://ghostfol.io/fr/a-propos/politique-de-confidentialite</loc> <loc>https://ghostfol.io/fr/a-propos/politique-de-confidentialite</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
@ -396,12 +404,16 @@
<loc>https://ghostfol.io/it/informazioni-su/changelog</loc> <loc>https://ghostfol.io/it/informazioni-su/changelog</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url>
<loc>https://ghostfol.io/it/informazioni-su/informativa-sulla-privacy</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url>
<url> <url>
<loc>https://ghostfol.io/it/informazioni-su/licenza</loc> <loc>https://ghostfol.io/it/informazioni-su/licenza</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url> <url>
<loc>https://ghostfol.io/it/informazioni-su/informativa-sulla-privacy</loc> <loc>https://ghostfol.io/it/informazioni-su/oss-friends</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url> <url>
@ -460,6 +472,10 @@
<loc>https://ghostfol.io/nl/over/licentie</loc> <loc>https://ghostfol.io/nl/over/licentie</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url>
<loc>https://ghostfol.io/nl/over/oss-friends</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url>
<url> <url>
<loc>https://ghostfol.io/nl/over/privacybeleid</loc> <loc>https://ghostfol.io/nl/over/privacybeleid</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
@ -520,6 +536,10 @@
<loc>https://ghostfol.io/pt/sobre/licenca</loc> <loc>https://ghostfol.io/pt/sobre/licenca</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url>
<loc>https://ghostfol.io/pt/sobre/oss-friends</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url>
<url> <url>
<loc>https://ghostfol.io/pt/sobre/politica-de-privacidade</loc> <loc>https://ghostfol.io/pt/sobre/politica-de-privacidade</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>

@ -1,22 +1,27 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes, TitleStrategy } from '@angular/router'; import { RouterModule, Routes, TitleStrategy } from '@angular/router';
import { routes as aboutRoutes } from '@ghostfolio/client/pages/about/routes';
import { routes as faqRoutes } from '@ghostfolio/client/pages/faq/routes';
import { routes as featuresRoutes } from '@ghostfolio/client/pages/features/routes';
import { routes as marketsRoutes } from '@ghostfolio/client/pages/markets/routes';
import { routes as pricingRoutes } from '@ghostfolio/client/pages/pricing/routes';
import { routes as registerRoutes } from '@ghostfolio/client/pages/register/routes';
import { routes as resourcesRoutes } from '@ghostfolio/client/pages/resources/routes';
import { PageTitleStrategy } from '@ghostfolio/client/services/page-title.strategy'; import { PageTitleStrategy } from '@ghostfolio/client/services/page-title.strategy';
import { ModulePreloadService } from './core/module-preload.service'; import { ModulePreloadService } from './core/module-preload.service';
export const paths = {
about: $localize`about`,
faq: $localize`faq`,
features: $localize`features`,
license: $localize`license`,
markets: $localize`markets`,
pricing: $localize`pricing`,
privacyPolicy: $localize`privacy-policy`,
register: $localize`register`,
resources: $localize`resources`
};
const routes: Routes = [ const routes: Routes = [
...aboutRoutes.map((path) => ({ {
path, path: paths.about,
loadChildren: () => loadChildren: () =>
import('./pages/about/about-page.module').then((m) => m.AboutPageModule) import('./pages/about/about-page.module').then((m) => m.AboutPageModule)
})), },
{ {
path: 'account', path: 'account',
loadChildren: () => loadChildren: () =>
@ -51,30 +56,30 @@ const routes: Routes = [
loadChildren: () => loadChildren: () =>
import('./pages/demo/demo-page.module').then((m) => m.DemoPageModule) import('./pages/demo/demo-page.module').then((m) => m.DemoPageModule)
}, },
...faqRoutes.map((path) => ({ {
path, path: paths.faq,
loadChildren: () => loadChildren: () =>
import('./pages/faq/faq-page.module').then((m) => m.FaqPageModule) import('./pages/faq/faq-page.module').then((m) => m.FaqPageModule)
})), },
...featuresRoutes.map((path) => ({ {
path, path: paths.features,
loadChildren: () => loadChildren: () =>
import('./pages/features/features-page.module').then( import('./pages/features/features-page.module').then(
(m) => m.FeaturesPageModule (m) => m.FeaturesPageModule
) )
})), },
{ {
path: 'home', path: 'home',
loadChildren: () => loadChildren: () =>
import('./pages/home/home-page.module').then((m) => m.HomePageModule) import('./pages/home/home-page.module').then((m) => m.HomePageModule)
}, },
...marketsRoutes.map((path) => ({ {
path, path: paths.markets,
loadChildren: () => loadChildren: () =>
import('./pages/markets/markets-page.module').then( import('./pages/markets/markets-page.module').then(
(m) => m.MarketsPageModule (m) => m.MarketsPageModule
) )
})), },
{ {
path: 'open', path: 'open',
loadChildren: () => loadChildren: () =>
@ -94,27 +99,27 @@ const routes: Routes = [
(m) => m.PortfolioPageModule (m) => m.PortfolioPageModule
) )
}, },
...pricingRoutes.map((path) => ({ {
path, path: paths.pricing,
loadChildren: () => loadChildren: () =>
import('./pages/pricing/pricing-page.module').then( import('./pages/pricing/pricing-page.module').then(
(m) => m.PricingPageModule (m) => m.PricingPageModule
) )
})), },
...registerRoutes.map((path) => ({ {
path, path: paths.register,
loadChildren: () => loadChildren: () =>
import('./pages/register/register-page.module').then( import('./pages/register/register-page.module').then(
(m) => m.RegisterPageModule (m) => m.RegisterPageModule
) )
})), },
...resourcesRoutes.map((path) => ({ {
path, path: paths.resources,
loadChildren: () => loadChildren: () =>
import('./pages/resources/resources-page.module').then( import('./pages/resources/resources-page.module').then(
(m) => m.ResourcesPageModule (m) => m.ResourcesPageModule
) )
})), },
{ {
path: 'start', path: 'start',
loadChildren: () => loadChildren: () =>

@ -19,7 +19,7 @@
<a <a
*ngIf="canCreateAccount" *ngIf="canCreateAccount"
class="text-center" class="text-center"
[routerLink]="['/register']" [routerLink]="routerLinkRegister"
> >
<div <div
class="cursor-pointer d-inline-block info-message px-3 py-2" class="cursor-pointer d-inline-block info-message px-3 py-2"
@ -43,22 +43,7 @@
<router-outlet></router-outlet> <router-outlet></router-outlet>
</main> </main>
<footer <footer *ngIf="showFooter" class="d-flex justify-content-center py-4 w-100">
*ngIf="
(currentRoute === 'blog' ||
currentRoute === 'faq' ||
currentRoute === 'features' ||
currentRoute === 'markets' ||
currentRoute === 'open' ||
currentRoute === 'p' ||
currentRoute === 'pricing' ||
currentRoute === 'resources' ||
currentRoute === 'register' ||
currentRoute === 'start') &&
deviceType !== 'mobile'
"
class="d-flex justify-content-center py-4 w-100"
>
<div class="container"> <div class="container">
<div class="mb-3 row"> <div class="mb-3 row">
<div class="col-sm"> <div class="col-sm">
@ -68,36 +53,38 @@
<div class="h6 mt-2" i18n>Personal Finance</div> <div class="h6 mt-2" i18n>Personal Finance</div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li *ngIf="hasPermissionToAccessFearAndGreedIndex"> <li *ngIf="hasPermissionToAccessFearAndGreedIndex">
<a i18n [routerLink]="['/markets']">Markets</a> <a i18n [routerLink]="routerLinkMarkets">Markets</a>
</li> </li>
<li><a i18n [routerLink]="['/resources']">Resources</a></li> <li><a i18n [routerLink]="routerLinkResources">Resources</a></li>
</ul> </ul>
</div> </div>
<div class="col-sm"> <div class="col-sm">
<div class="h6 mt-2">Ghostfolio</div> <div class="h6 mt-2">Ghostfolio</div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li><a i18n [routerLink]="['/about']">About</a></li> <li><a i18n [routerLink]="routerLinkAbout">About</a></li>
<li *ngIf="hasPermissionForBlog"> <li *ngIf="hasPermissionForBlog">
<a i18n [routerLink]="['/blog']">Blog</a> <a i18n [routerLink]="['/blog']">Blog</a>
</li> </li>
<li> <li>
<a i18n [routerLink]="['/about', 'changelog']">Changelog</a> <a i18n [routerLink]="routerLinkAboutChangelog">Changelog</a>
</li> </li>
<li><a i18n [routerLink]="['/features']">Features</a></li> <li><a i18n [routerLink]="routerLinkFeatures">Features</a></li>
<li *ngIf="hasPermissionForSubscription"> <li *ngIf="hasPermissionForSubscription">
<a i18n [routerLink]="['/faq']">Frequently Asked Questions (FAQ)</a> <a i18n [routerLink]="routerLinkFaq"
>Frequently Asked Questions (FAQ)</a
>
</li> </li>
<li> <li>
<a i18n [routerLink]="['/about', 'license']">License</a> <a i18n [routerLink]="routerLinkAboutLicense">License</a>
</li> </li>
<li *ngIf="hasPermissionForStatistics"> <li *ngIf="hasPermissionForStatistics">
<a [routerLink]="['/open']">Open Startup</a> <a [routerLink]="['/open']">Open Startup</a>
</li> </li>
<li *ngIf="hasPermissionForSubscription"> <li *ngIf="hasPermissionForSubscription">
<a i18n [routerLink]="['/pricing']">Pricing</a> <a i18n [routerLink]="routerLinkPricing">Pricing</a>
</li> </li>
<li *ngIf="hasPermissionForSubscription"> <li *ngIf="hasPermissionForSubscription">
<a i18n [routerLink]="['/about', 'privacy-policy']" <a i18n [routerLink]="routerLinkAboutPrivacyPolicy"
>Privacy Policy</a >Privacy Policy</a
> >
</li> </li>

@ -38,6 +38,20 @@ export class AppComponent implements OnDestroy, OnInit {
public hasPermissionToAccessFearAndGreedIndex: boolean; public hasPermissionToAccessFearAndGreedIndex: boolean;
public info: InfoItem; public info: InfoItem;
public pageTitle: string; public pageTitle: string;
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkAboutChangelog = ['/' + $localize`about`, 'changelog'];
public routerLinkAboutLicense = ['/' + $localize`about`, $localize`license`];
public routerLinkAboutPrivacyPolicy = [
'/' + $localize`about`,
$localize`privacy-policy`
];
public routerLinkFaq = ['/' + $localize`faq`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkMarkets = ['/' + $localize`markets`];
public routerLinkPricing = ['/' + $localize`pricing`];
public routerLinkRegister = ['/' + $localize`register`];
public routerLinkResources = ['/' + $localize`resources`];
public showFooter = false;
public user: User; public user: User;
public version = environment.version; public version = environment.version;
@ -89,6 +103,19 @@ export class AppComponent implements OnDestroy, OnInit {
const urlSegments = urlSegmentGroup.segments; const urlSegments = urlSegmentGroup.segments;
this.currentRoute = urlSegments[0].path; this.currentRoute = urlSegments[0].path;
this.showFooter =
(this.currentRoute === 'blog' ||
this.currentRoute === this.routerLinkFaq[0].slice(1) ||
this.currentRoute === this.routerLinkFeatures[0].slice(1) ||
this.currentRoute === this.routerLinkMarkets[0].slice(1) ||
this.currentRoute === 'open' ||
this.currentRoute === 'p' ||
this.currentRoute === this.routerLinkPricing[0].slice(1) ||
this.currentRoute === this.routerLinkRegister[0].slice(1) ||
this.currentRoute === this.routerLinkResources[0].slice(1) ||
this.currentRoute === 'start') &&
this.deviceType !== 'mobile';
if (this.deviceType === 'mobile') { if (this.deviceType === 'mobile') {
setTimeout(() => { setTimeout(() => {
const index = this.title.getTitle().indexOf(''); const index = this.title.getTitle().indexOf('');

@ -69,10 +69,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'resources', 'font-weight-bold': currentRoute === routeResources,
'text-decoration-underline': currentRoute === 'resources' 'text-decoration-underline': currentRoute === routeResources
}" }"
[routerLink]="['/resources']" [routerLink]="routerLinkResources"
>Resources</a >Resources</a
> >
</li> </li>
@ -87,10 +87,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'pricing', 'font-weight-bold': currentRoute === routePricing,
'text-decoration-underline': currentRoute === 'pricing' 'text-decoration-underline': currentRoute === routePricing
}" }"
[routerLink]="['/pricing']" [routerLink]="routerLinkPricing"
>Pricing</a >Pricing</a
> >
</li> </li>
@ -100,10 +100,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'about', 'font-weight-bold': currentRoute === routeAbout,
'text-decoration-underline': currentRoute === 'about' 'text-decoration-underline': currentRoute === routeAbout
}" }"
[routerLink]="['/about']" [routerLink]="routerLinkAbout"
>About</a >About</a
> >
</li> </li>
@ -210,9 +210,9 @@
i18n i18n
mat-menu-item mat-menu-item
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'resources' 'font-weight-bold': currentRoute === routeResources
}" }"
[routerLink]="['/resources']" [routerLink]="routerLinkResources"
>Resources</a >Resources</a
> >
<a <a
@ -223,16 +223,16 @@
class="d-flex d-sm-none" class="d-flex d-sm-none"
i18n i18n
mat-menu-item mat-menu-item
[ngClass]="{ 'font-weight-bold': currentRoute === 'pricing' }" [ngClass]="{ 'font-weight-bold': currentRoute === routePricing }"
[routerLink]="['/pricing']" [routerLink]="routerLinkPricing"
>Pricing</a >Pricing</a
> >
<a <a
class="d-flex d-sm-none" class="d-flex d-sm-none"
i18n i18n
mat-menu-item mat-menu-item
[ngClass]="{ 'font-weight-bold': currentRoute === 'about' }" [ngClass]="{ 'font-weight-bold': currentRoute === routeAbout }"
[routerLink]="['/about']" [routerLink]="routerLinkAbout"
>About Ghostfolio</a >About Ghostfolio</a
> >
<hr class="d-flex d-sm-none m-0" /> <hr class="d-flex d-sm-none m-0" />
@ -260,10 +260,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'features', 'font-weight-bold': currentRoute === routeFeatures,
'text-decoration-underline': currentRoute === 'features' 'text-decoration-underline': currentRoute === routeFeatuers
}" }"
[routerLink]="['/features']" [routerLink]="routerLinkFeatures"
>Features</a >Features</a
> >
</li> </li>
@ -273,10 +273,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'about', 'font-weight-bold': currentRoute === routeAbout,
'text-decoration-underline': currentRoute === 'about' 'text-decoration-underline': currentRoute === routeAbout
}" }"
[routerLink]="['/about']" [routerLink]="routerLinkAbout"
>About</a >About</a
> >
</li> </li>
@ -285,10 +285,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'pricing', 'font-weight-bold': currentRoute === routePricing,
'text-decoration-underline': currentRoute === 'pricing' 'text-decoration-underline': currentRoute === routePricing
}" }"
[routerLink]="['/pricing']" [routerLink]="routerLinkPricing"
>Pricing</a >Pricing</a
> >
</li> </li>
@ -301,10 +301,10 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'markets', 'font-weight-bold': currentRoute === routeMarkets,
'text-decoration-underline': currentRoute === 'markets' 'text-decoration-underline': currentRoute === routeMarkets
}" }"
[routerLink]="['/markets']" [routerLink]="routerLinkMarkets"
>Markets</a >Markets</a
> >
</li> </li>
@ -329,7 +329,7 @@
class="d-none d-sm-block" class="d-none d-sm-block"
color="primary" color="primary"
mat-flat-button mat-flat-button
[routerLink]="['/register']" [routerLink]="routerLinkRegister"
><ng-container i18n>Get started</ng-container> ><ng-container i18n>Get started</ng-container>
</a> </a>
</li> </li>

@ -42,6 +42,17 @@ export class HeaderComponent implements OnChanges {
public hasPermissionToCreateUser: boolean; public hasPermissionToCreateUser: boolean;
public impersonationId: string; public impersonationId: string;
public isMenuOpen: boolean; public isMenuOpen: boolean;
public routeAbout = $localize`about`;
public routeFeatures = $localize`features`;
public routeMarkets = $localize`markets`;
public routePricing = $localize`pricing`;
public routeResources = $localize`resources`;
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkMarkets = ['/' + $localize`markets`];
public routerLinkPricing = ['/' + $localize`pricing`];
public routerLinkRegister = ['/' + $localize`register`];
public routerLinkResources = ['/' + $localize`resources`];
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();

@ -121,7 +121,7 @@ export class HomeSummaryComponent implements OnDestroy, OnInit {
}); });
this.snackBarRef.onAction().subscribe(() => { this.snackBarRef.onAction().subscribe(() => {
this.router.navigate(['/pricing']); this.router.navigate(['/' + $localize`pricing`]);
}); });
} }

@ -11,6 +11,8 @@ import { SubscriptionInterstitialDialogParams } from './interfaces/interfaces';
templateUrl: 'subscription-interstitial-dialog.html' templateUrl: 'subscription-interstitial-dialog.html'
}) })
export class SubscriptionInterstitialDialog { export class SubscriptionInterstitialDialog {
public routerLinkPricing = ['/' + $localize`pricing`];
public constructor( public constructor(
@Inject(MAT_DIALOG_DATA) public data: SubscriptionInterstitialDialogParams, @Inject(MAT_DIALOG_DATA) public data: SubscriptionInterstitialDialogParams,
public dialogRef: MatDialogRef<SubscriptionInterstitialDialog> public dialogRef: MatDialogRef<SubscriptionInterstitialDialog>

@ -56,7 +56,7 @@
<a <a
color="primary" color="primary"
mat-flat-button mat-flat-button
[routerLink]="['/pricing']" [routerLink]="routerLinkPricing"
(click)="closeDialog()" (click)="closeDialog()"
> >
<span i18n>Upgrade Plan</span> <span i18n>Upgrade Plan</span>

@ -4,13 +4,7 @@ import {
Router, Router,
RouterStateSnapshot RouterStateSnapshot
} from '@angular/router'; } from '@angular/router';
import { routes as aboutRoutes } from '@ghostfolio/client/pages/about/routes'; import { paths } from '@ghostfolio/client/app-routing.module';
import { routes as faqRoutes } from '@ghostfolio/client/pages/faq/routes';
import { routes as featuresRoutes } from '@ghostfolio/client/pages/features/routes';
import { routes as marketsRoutes } from '@ghostfolio/client/pages/markets/routes';
import { routes as pricingRoutes } from '@ghostfolio/client/pages/pricing/routes';
import { routes as registerRoutes } from '@ghostfolio/client/pages/register/routes';
import { routes as resourcesRoutes } from '@ghostfolio/client/pages/resources/routes';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service'; import { SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
@ -20,17 +14,17 @@ import { catchError } from 'rxjs/operators';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class AuthGuard { export class AuthGuard {
private static PUBLIC_PAGE_ROUTES = [ private static PUBLIC_PAGE_ROUTES = [
...aboutRoutes.map((route) => `/${route}`), `/${paths.about}`,
'/blog', '/blog',
'/demo', '/demo',
...faqRoutes.map((route) => `/${route}`), `/${paths.faq}`,
...featuresRoutes.map((route) => `/${route}`), `/${paths.features}`,
...marketsRoutes.map((route) => `/${route}`), `/${paths.markets}`,
'/open', '/open',
'/p', '/p',
...pricingRoutes.map((route) => `/${route}`), `/${paths.pricing}`,
...registerRoutes.map((route) => `/${route}`), `/${paths.register}`,
...resourcesRoutes.map((route) => `/${route}`) `/${paths.resources}`
]; ];
constructor( constructor(
@ -56,7 +50,7 @@ export class AuthGuard {
this.router.navigate(['/demo']); this.router.navigate(['/demo']);
resolve(false); resolve(false);
} else if (utmSource === 'trusted-web-activity') { } else if (utmSource === 'trusted-web-activity') {
this.router.navigate(['/register']); this.router.navigate(['/' + $localize`register`]);
resolve(false); resolve(false);
} else if ( } else if (
AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) => AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) =>

@ -77,7 +77,7 @@ export class HttpResponseInterceptor implements HttpInterceptor {
}); });
this.snackBarRef.onAction().subscribe(() => { this.snackBarRef.onAction().subscribe(() => {
this.router.navigate(['/pricing']); this.router.navigate(['/' + $localize`pricing`]);
}); });
} }
} else if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) { } else if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) {

@ -3,6 +3,8 @@ import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { AboutPageComponent } from './about-page.component'; import { AboutPageComponent } from './about-page.component';
import { paths } from '@ghostfolio/client/app-routing.module';
import * as path from 'path';
const routes: Routes = [ const routes: Routes = [
{ {
@ -22,22 +24,13 @@ const routes: Routes = [
(m) => m.ChangelogPageModule (m) => m.ChangelogPageModule
) )
}, },
...[ {
'license', path: paths.license,
/////
'licenca',
'licence',
'licencia',
'licentie',
'lizenz',
'licenza'
].map((path) => ({
path,
loadChildren: () => loadChildren: () =>
import('./license/license-page.module').then( import('./license/license-page.module').then(
(m) => m.LicensePageModule (m) => m.LicensePageModule
) )
})), },
{ {
path: 'oss-friends', path: 'oss-friends',
loadChildren: () => loadChildren: () =>
@ -45,22 +38,13 @@ const routes: Routes = [
(m) => m.OpenSourceSoftwareFriendsPageModule (m) => m.OpenSourceSoftwareFriendsPageModule
) )
}, },
...[ {
'privacy-policy', path: paths.privacyPolicy,
/////
'datenschutzbestimmungen',
'informativa-sulla-privacy',
'politique-de-confidentialite',
'politica-de-privacidad',
'politica-de-privacidade',
'privacybeleid'
].map((path) => ({
path,
loadChildren: () => loadChildren: () =>
import('./privacy-policy/privacy-policy-page.module').then( import('./privacy-policy/privacy-policy-page.module').then(
(m) => m.PrivacyPolicyPageModule (m) => m.PrivacyPolicyPageModule
) )
})) }
], ],
component: AboutPageComponent, component: AboutPageComponent,
path: '', path: '',

@ -48,17 +48,17 @@ export class AboutPageComponent implements OnDestroy, OnInit {
{ {
iconName: 'reader-outline', iconName: 'reader-outline',
label: $localize`About`, label: $localize`About`,
path: ['/about'] path: ['/' + $localize`about`]
}, },
{ {
iconName: 'sparkles-outline', iconName: 'sparkles-outline',
label: $localize`Changelog`, label: $localize`Changelog`,
path: ['/about', 'changelog'] path: ['/' + $localize`about`, 'changelog']
}, },
{ {
iconName: 'ribbon-outline', iconName: 'ribbon-outline',
label: $localize`License`, label: $localize`License`,
path: ['/about', 'license'] path: ['/' + $localize`about`, $localize`license`]
} }
]; ];
@ -66,7 +66,7 @@ export class AboutPageComponent implements OnDestroy, OnInit {
this.tabs.push({ this.tabs.push({
iconName: 'shield-checkmark-outline', iconName: 'shield-checkmark-outline',
label: $localize`Privacy Policy`, label: $localize`Privacy Policy`,
path: ['/about', 'privacy-policy'], path: ['/' + $localize`about`, $localize`privacy-policy`],
showCondition: this.hasPermissionForSubscription showCondition: this.hasPermissionForSubscription
}); });
this.user = state.user; this.user = state.user;
@ -83,7 +83,7 @@ export class AboutPageComponent implements OnDestroy, OnInit {
this.tabs.push({ this.tabs.push({
iconName: 'happy-outline', iconName: 'happy-outline',
label: 'OSS Friends', label: 'OSS Friends',
path: ['/about', 'oss-friends'] path: ['/' + $localize`about`, 'oss-friends']
}); });
}); });
} }

@ -6,7 +6,7 @@
><ng-container i18n>Our</ng-container> OSS Friends</span ><ng-container i18n>Our</ng-container> OSS Friends</span
> >
<small class="text-muted" i18n <small class="text-muted" i18n
>Discover more Open Source Software projects</small >Discover other exciting Open Source Software projects</small
> >
</h1> </h1>
<div class="row"> <div class="row">

@ -18,6 +18,8 @@ export class AboutOverviewPageComponent implements OnDestroy, OnInit {
public hasPermissionForStatistics: boolean; public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean; public hasPermissionForSubscription: boolean;
public isLoggedIn: boolean; public isLoggedIn: boolean;
public routerLinkFaq = ['/' + $localize`faq`];
public routerLinkFeatures = ['/' + $localize`features`];
public user: User; public user: User;
public version = environment.version; public version = environment.version;

@ -46,7 +46,7 @@
<p> <p>
If you encounter a bug or would like to suggest an improvement or a If you encounter a bug or would like to suggest an improvement or a
new new
<a [routerLink]="['/features']">feature</a>, please join the <a [routerLink]="routerLinkFeatures">feature</a>, please join the
Ghostfolio Ghostfolio
<a <a
href="https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg" href="https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg"
@ -139,7 +139,7 @@
class="py-4 w-100" class="py-4 w-100"
color="primary" color="primary"
mat-flat-button mat-flat-button
[routerLink]="['/faq']" [routerLink]="routerLinkFaq"
>Frequently Asked Questions (FAQ)</a >Frequently Asked Questions (FAQ)</a
> >
</div> </div>

@ -1,9 +0,0 @@
export const routes = [
'about',
/////
'a-propos',
'informazioni-su',
'over',
'sobre',
'ueber-uns'
] as const;

@ -9,4 +9,7 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './hallo-ghostfolio-page.html' templateUrl: './hallo-ghostfolio-page.html'
}) })
export class HalloGhostfolioPageComponent {} export class HalloGhostfolioPageComponent {
public routerLinkPricing = ['/' + $localize`pricing`];
public routerLinkResources = ['/' + $localize`resources`];
}

@ -19,7 +19,7 @@
Aufgrund der steigenden Inflation und den Negativzinsen befasse ich Aufgrund der steigenden Inflation und den Negativzinsen befasse ich
mich seit einiger Zeit, wie ich mein Vermögen möglichst mich seit einiger Zeit, wie ich mein Vermögen möglichst
diversifiziert anlegen kann. Konkret verfolge ich eine diversifiziert anlegen kann. Konkret verfolge ich eine
<a [routerLink]="['/resources']">Buy and Hold Strategie</a> mit <a [routerLink]="routerLinkResources">Buy and Hold Strategie</a> mit
Investitionen in verschiedene Anlageklassen verteilt auf Investitionen in verschiedene Anlageklassen verteilt auf
unterschiedliche Plattformen. Deshalb suchte ich nach einer App, die unterschiedliche Plattformen. Deshalb suchte ich nach einer App, die
mein Portfolio ganzheitlich zusammenfasst. Bei meiner mein Portfolio ganzheitlich zusammenfasst. Bei meiner
@ -119,7 +119,7 @@
Anlagestrategie? Ich freue mich über alle, die Ghostfolio Anlagestrategie? Ich freue mich über alle, die Ghostfolio
ausprobieren. Bist du überzeugt vom Potential der Software? Jede ausprobieren. Bist du überzeugt vom Potential der Software? Jede
Unterstützung für Ghostfolio ist willkommen. Sei es mit einer Unterstützung für Ghostfolio ist willkommen. Sei es mit einer
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> <a [routerLink]="routerLinkPricing">Ghostfolio Premium</a>
Subscription zur Finanzierung des Hostings, einem positiven Rating Subscription zur Finanzierung des Hostings, einem positiven Rating
im im
<a <a

@ -9,4 +9,7 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './hello-ghostfolio-page.html' templateUrl: './hello-ghostfolio-page.html'
}) })
export class HelloGhostfolioPageComponent {} export class HelloGhostfolioPageComponent {
public routerLinkPricing = ['/' + $localize`pricing`];
public routerLinkResources = ['/' + $localize`resources`];
}

@ -19,7 +19,7 @@
Due to rising inflation and negative interest rates, I have been Due to rising inflation and negative interest rates, I have been
looking for some time at how I can invest my assets in the most looking for some time at how I can invest my assets in the most
diversified way possible. Specifically, I follow a diversified way possible. Specifically, I follow a
<a [routerLink]="['/resources']">buy and hold strategy</a> with <a [routerLink]="routerLinkResources">buy and hold strategy</a> with
investments in different asset classes spread across different investments in different asset classes spread across different
platforms. Therefore, I was looking for an app that would platforms. Therefore, I was looking for an app that would
holistically aggregate my portfolio. During my research on the holistically aggregate my portfolio. During my research on the
@ -115,7 +115,7 @@
strategy? I'm happy for everyone who tries Ghostfolio. Are you strategy? I'm happy for everyone who tries Ghostfolio. Are you
convinced of its potential? Any support for Ghostfolio is welcome. convinced of its potential? Any support for Ghostfolio is welcome.
Be it with a Be it with a
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> <a [routerLink]="routerLinkPricing">Ghostfolio Premium</a>
Subscription to finance the hosting, a positive rating in the Subscription to finance the hosting, a positive rating in the
<a <a
href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa" href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa"

@ -9,4 +9,6 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './first-months-in-open-source-page.html' templateUrl: './first-months-in-open-source-page.html'
}) })
export class FirstMonthsInOpenSourcePageComponent {} export class FirstMonthsInOpenSourcePageComponent {
public routerLinkPricing = ['/' + $localize`pricing`];
}

@ -86,7 +86,7 @@
</p> </p>
<p> <p>
My personal goal is to reach break-even with the Saas offering (<a My personal goal is to reach break-even with the Saas offering (<a
[routerLink]="['/pricing']" [routerLink]="routerLinkPricing"
>Ghostfolio Premium</a >Ghostfolio Premium</a
>) and regularly report about the progress and my learnings on this >) and regularly report about the progress and my learnings on this
exciting journey. exciting journey.

@ -9,4 +9,6 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './how-do-i-get-my-finances-in-order-page.html' templateUrl: './how-do-i-get-my-finances-in-order-page.html'
}) })
export class HowDoIGetMyFinancesInOrderPageComponent {} export class HowDoIGetMyFinancesInOrderPageComponent {
public routerLinkResources = ['/' + $localize`resources`];
}

@ -9,9 +9,9 @@
<section class="mb-4"> <section class="mb-4">
<p> <p>
Before you can think of Before you can think of
<a [routerLink]="['/resources']">long-term investing</a>, you have <a [routerLink]="routerLinkResources">long-term investing</a>, you
to get your finances in order. Take a look at Peter's journey to see have to get your finances in order. Take a look at Peter's journey
how you can achieve it, too. to see how you can achieve it, too.
</p> </p>
<p> <p>
Peter enjoys life, but sometimes he overspends a bit. He realizes it Peter enjoys life, but sometimes he overspends a bit. He realizes it

@ -9,4 +9,7 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './500-stars-on-github-page.html' templateUrl: './500-stars-on-github-page.html'
}) })
export class FiveHundredStarsOnGitHubPageComponent {} export class FiveHundredStarsOnGitHubPageComponent {
public routerLinkMarkets = ['/' + $localize`markets`];
public routerLinkPricing = ['/' + $localize`pricing`];
}

@ -71,10 +71,10 @@
<h2 class="h4">Break-even Point</h2> <h2 class="h4">Break-even Point</h2>
<p> <p>
Despite the complicated Despite the complicated
<a [routerLink]="['/markets']">economic situation</a> at this time, <a [routerLink]="routerLinkMarkets">economic situation</a> at this
the goal set at the beginning of the year to build a sustainable time, the goal set at the beginning of the year to build a
business and reach break-even with the SaaS offering (<a sustainable business and reach break-even with the SaaS offering (<a
[routerLink]="['/pricing']" [routerLink]="routerLinkPricing"
>Ghostfolio Premium</a >Ghostfolio Premium</a
>) has been achieved. We will continue to leverage the revenue to >) has been achieved. We will continue to leverage the revenue to
further improve the fully managed cloud offering for our paying further improve the fully managed cloud offering for our paying

@ -11,5 +11,6 @@ import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
templateUrl: './black-friday-2022-page.html' templateUrl: './black-friday-2022-page.html'
}) })
export class BlackFriday2022PageComponent { export class BlackFriday2022PageComponent {
public constructor() {} public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkPricing = ['/' + $localize`pricing`];
} }

@ -35,17 +35,18 @@
software presents the current assets (stocks, ETFs, software presents the current assets (stocks, ETFs,
cryptocurrencies, commodities etc.) in real time to make solid, cryptocurrencies, commodities etc.) in real time to make solid,
data-driven investment decisions. Check out the numerous data-driven investment decisions. Check out the numerous
<a [routerLink]="['/features']">features</a> to manage your wealth. <a [routerLink]="routerLinkFeatures">features</a> to manage your
wealth.
</p> </p>
</section> </section>
<section class="mb-4"> <section class="mb-4">
<p> <p>
Snap the limited Black Friday 2022 deal before its gone. For Snap the limited Black Friday 2022 deal before its gone. For
detailed information on plans and pricing, please visit our detailed information on plans and pricing, please visit our
<a [routerLink]="['/pricing']">pricing page</a>. <a [routerLink]="routerLinkPricing">pricing page</a>.
</p> </p>
<p class="text-center"> <p class="text-center">
<a color="primary" mat-flat-button [routerLink]="['/pricing']" <a color="primary" mat-flat-button [routerLink]="routerLinkPricing"
>Get the Deal</a >Get the Deal</a
> >
</p> </p>

@ -9,4 +9,7 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './1000-stars-on-github-page.html' templateUrl: './1000-stars-on-github-page.html'
}) })
export class ThousandStarsOnGitHubPageComponent {} export class ThousandStarsOnGitHubPageComponent {
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkPricing = ['/' + $localize`pricing`];
}

@ -92,7 +92,7 @@
<p> <p>
These self-hosting platforms allow users to run applications on These self-hosting platforms allow users to run applications on
their own hardware rather than rely on a their own hardware rather than rely on a
<a [routerLink]="['/pricing']">SaaS offering</a>. As a result, <a [routerLink]="routerLinkPricing">SaaS offering</a>. As a result,
Ghostfolio has become accessible to an even wider range of users who Ghostfolio has become accessible to an even wider range of users who
would like to take control of their wealth management. would like to take control of their wealth management.
</p> </p>
@ -108,9 +108,9 @@
As the project continues to evolve, we can expect to see even more As the project continues to evolve, we can expect to see even more
exciting developments and innovations around Ghostfolio which guides exciting developments and innovations around Ghostfolio which guides
users through the process of users through the process of
<a [routerLink]="['/features']">tracking their assets</a>, such as <a [routerLink]="routerLinkFeatures">tracking their assets</a>, such
stocks, ETFs, or cryptocurrencies. Especially in the areas of data as stocks, ETFs, or cryptocurrencies. Especially in the areas of
import and portfolio analysis. data import and portfolio analysis.
</p> </p>
<p> <p>
We are honored to be a part of this vibrant and growing community, We are honored to be a part of this vibrant and growing community,

@ -9,4 +9,7 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './unlock-your-financial-potential-with-ghostfolio-page.html' templateUrl: './unlock-your-financial-potential-with-ghostfolio-page.html'
}) })
export class UnlockYourFinancialPotentialWithGhostfolioPageComponent {} export class UnlockYourFinancialPotentialWithGhostfolioPageComponent {
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResources = ['/' + $localize`resources`];
}

@ -44,13 +44,13 @@
<h2 class="h4">Empowering Buy & Hold Strategies</h2> <h2 class="h4">Empowering Buy & Hold Strategies</h2>
<p> <p>
For those committed to a For those committed to a
<a [routerLink]="['/resources']">buy & hold strategy</a>, Ghostfolio <a [routerLink]="routerLinkResources">buy & hold strategy</a>,
provides an intuitive interface to monitor long-term investments. Ghostfolio provides an intuitive interface to monitor long-term
Users can track performance over time, gaining insights into investments. Users can track performance over time, gaining insights
portfolio growth and stability. With strong visualizations and into portfolio growth and stability. With strong visualizations and
reporting <a [routerLink]="['/features']">features</a>, Ghostfolio reporting <a [routerLink]="routerLinkFeatures">features</a>,
equips users to make well-informed decisions aligned with their Ghostfolio equips users to make well-informed decisions aligned with
long-term investment goals. their long-term investment goals.
</p> </p>
</section> </section>
<section class="mb-4"> <section class="mb-4">
@ -91,7 +91,7 @@
<h2 class="h4">Driving Financial Independence (FIRE)</h2> <h2 class="h4">Driving Financial Independence (FIRE)</h2>
<p> <p>
Achieving Achieving
<a [routerLink]="['/resources']">financial independence</a> <a [routerLink]="routerLinkResources">financial independence</a>
including early retirement (<a including early retirement (<a
href="../en/blog/2023/07/exploring-the-path-to-fire" href="../en/blog/2023/07/exploring-the-path-to-fire"
>FIRE</a >FIRE</a

@ -9,4 +9,6 @@ import { RouterModule } from '@angular/router';
standalone: true, standalone: true,
templateUrl: './exploring-the-path-to-fire-page.html' templateUrl: './exploring-the-path-to-fire-page.html'
}) })
export class ExploringThePathToFirePageComponent {} export class ExploringThePathToFirePageComponent {
public routerLinkFeatures = ['/' + $localize`features`];
}

@ -135,10 +135,10 @@
track your investments, and make informed decisions to accelerate track your investments, and make informed decisions to accelerate
your progress towards financial independence. Ghostfolio also your progress towards financial independence. Ghostfolio also
provides a dedicated provides a dedicated
<a [routerLink]="['/features']">FIRE calculator</a>, allowing you to <a [routerLink]="routerLinkFeatures">FIRE calculator</a>, allowing
simulate your customized plan to achieve FIRE. You get the tools to you to simulate your customized plan to achieve FIRE. You get the
optimize your financial journey and confidently strive for a future tools to optimize your financial journey and confidently strive for
that is both personally fulfilling and financially secure. a future that is both personally fulfilling and financially secure.
</p> </p>
</section> </section>
<section class="mb-4 py-3"> <section class="mb-4 py-3">

@ -10,6 +10,10 @@ import { Subject, takeUntil } from 'rxjs';
templateUrl: './faq-page.html' templateUrl: './faq-page.html'
}) })
export class FaqPageComponent implements OnDestroy { export class FaqPageComponent implements OnDestroy {
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkMarkets = ['/' + $localize`markets`];
public routerLinkPricing = ['/' + $localize`pricing`];
public routerLinkRegister = ['/' + $localize`register`];
public user: User; public user: User;
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();

@ -39,7 +39,7 @@
> >
<mat-card-content> <mat-card-content>
Please find a feature overview to manage your wealth Please find a feature overview to manage your wealth
<a [routerLink]="['/features']">here</a>. <a [routerLink]="routerLinkFeatures">here</a>.
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="mb-3">
@ -47,7 +47,7 @@
<mat-card-title>How do I start?</mat-card-title></mat-card-header <mat-card-title>How do I start?</mat-card-title></mat-card-header
> >
<mat-card-content> <mat-card-content>
You can sign up via the “<a [routerLink]="['/register']" You can sign up via the “<a [routerLink]="routerLinkRegister"
>Get Started</a >Get Started</a
>” button at the top of the page. You have multiple options to join >” button at the top of the page. You have multiple options to join
Ghostfolio: Create an account with a security token, using Ghostfolio: Create an account with a security token, using
@ -93,7 +93,7 @@
world. The world. The
<a href="https://github.com/ghostfolio/ghostfolio">source code</a> is <a href="https://github.com/ghostfolio/ghostfolio">source code</a> is
fully available as open source software (OSS). Thanks to our generous fully available as open source software (OSS). Thanks to our generous
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> users and <a [routerLink]="routerLinkPricing">Ghostfolio Premium</a> users and
<a href="https://www.buymeacoffee.com/ghostfolio">sponsors</a> we have <a href="https://www.buymeacoffee.com/ghostfolio">sponsors</a> we have
the ability to run a free, limited plan for novice the ability to run a free, limited plan for novice
investors.</mat-card-content investors.</mat-card-content
@ -105,8 +105,8 @@
> >
<mat-card-content <mat-card-content
>Yes, it is! Our >Yes, it is! Our
<a [routerLink]="['/pricing']">pricing page</a> details everything you <a [routerLink]="routerLinkPricing">pricing page</a> details
get for free.</mat-card-content everything you get for free.</mat-card-content
> >
</mat-card> </mat-card>
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="mb-3">
@ -127,7 +127,8 @@
></mat-card-header ></mat-card-header
> >
<mat-card-content <mat-card-content
>By offering <a [routerLink]="['/pricing']">Ghostfolio Premium</a>, a >By offering
<a [routerLink]="routerLinkPricing">Ghostfolio Premium</a>, a
subscription plan with a managed hosting service and enhanced subscription plan with a managed hosting service and enhanced
features, we fund our business while providing added value to our features, we fund our business while providing added value to our
users.</mat-card-content users.</mat-card-content
@ -140,12 +141,12 @@
></mat-card-header ></mat-card-header
> >
<mat-card-content <mat-card-content
><a [routerLink]="['/pricing']">Ghostfolio Premium</a> is a fully ><a [routerLink]="routerLinkPricing">Ghostfolio Premium</a> is a fully
managed Ghostfolio cloud offering for ambitious investors. The revenue managed Ghostfolio cloud offering for ambitious investors. The revenue
is used to cover the hosting infrastructure and to fund the ongoing is used to cover the hosting infrastructure and to fund the ongoing
development. It is the Open Source code base with some extras like the development. It is the Open Source code base with some extras like the
<a [routerLink]="['/markets']">markets overview</a> and a professional <a [routerLink]="routerLinkMarkets">markets overview</a> and a
data provider.</mat-card-content professional data provider.</mat-card-content
> >
</mat-card> </mat-card>
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="mb-3">
@ -156,9 +157,9 @@
> >
<mat-card-content <mat-card-content
>Yes, you can try >Yes, you can try
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> by signing up <a [routerLink]="routerLinkPricing">Ghostfolio Premium</a> by signing
for Ghostfolio and applying for a trial (see “My Ghostfolio”). It is up for Ghostfolio and applying for a trial (see “My Ghostfolio”). It
easy, free and there is no commitment. You can stop using it at any is easy, free and there is no commitment. You can stop using it at any
time.</mat-card-content time.</mat-card-content
> >
</mat-card> </mat-card>
@ -214,8 +215,9 @@
</mat-card-header> </mat-card-header>
<mat-card-content <mat-card-content
>Any support for Ghostfolio is welcome. Be it with a >Any support for Ghostfolio is welcome. Be it with a
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> subscription to <a [routerLink]="routerLinkPricing">Ghostfolio Premium</a>
finance the hosting infrastructure, a positive rating in the subscription to finance the hosting infrastructure, a positive rating
in the
<a <a
href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa" href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa"
>Google Play Store</a >Google Play Store</a

@ -1,10 +0,0 @@
export const routes = [
'faq',
/////
'domande-piu-frequenti',
'foire-aux-questions',
'haeufig-gestellte-fragen',
'perguntas-mais-frequentes',
'preguntas-mas-frecuentes',
'vaak-gestelde-vragen'
] as const;

@ -14,6 +14,7 @@ import { Subject, takeUntil } from 'rxjs';
export class FeaturesPageComponent implements OnDestroy { export class FeaturesPageComponent implements OnDestroy {
public hasPermissionForSubscription: boolean; public hasPermissionForSubscription: boolean;
public info: InfoItem; public info: InfoItem;
public routerLinkRegister = ['/' + $localize`register`];
public user: User; public user: User;
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();

@ -211,7 +211,7 @@
</h4> </h4>
<p class="m-0"> <p class="m-0">
Check the current market mood (<a Check the current market mood (<a
[routerLink]="['/resources']" [routerLink]="routerLinkResources"
>Fear & Greed Index</a >Fear & Greed Index</a
>) within the app. >) within the app.
</p> </p>
@ -294,7 +294,7 @@
</div> </div>
<div *ngIf="!user" class="row"> <div *ngIf="!user" class="row">
<div class="col mt-3 text-center"> <div class="col mt-3 text-center">
<a color="primary" i18n mat-flat-button [routerLink]="['/register']" <a color="primary" i18n mat-flat-button [routerLink]="routerLinkRegister"
>Get Started</a >Get Started</a
> >
</div> </div>

@ -1,8 +0,0 @@
export const routes = [
'features',
/////
'fonctionnalites',
'funcionalidades',
'funzionalita',
'kenmerken'
] as const;

@ -22,6 +22,8 @@ export class LandingPageComponent implements OnDestroy, OnInit {
public hasPermissionForStatistics: boolean; public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean; public hasPermissionForSubscription: boolean;
public hasPermissionToCreateUser: boolean; public hasPermissionToCreateUser: boolean;
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkRegister = ['/' + $localize`register`];
public statistics: Statistics; public statistics: Statistics;
public testimonials = [ public testimonials = [
{ {

@ -31,7 +31,12 @@
<div class="button-container mb-5 row"> <div class="button-container mb-5 row">
<div class="align-items-center col d-flex justify-content-center"> <div class="align-items-center col d-flex justify-content-center">
<ng-container *ngIf="hasPermissionToCreateUser"> <ng-container *ngIf="hasPermissionToCreateUser">
<a color="primary" i18n mat-flat-button [routerLink]="['/register']"> <a
color="primary"
i18n
mat-flat-button
[routerLink]="routerLinkRegister"
>
Get Started Get Started
</a> </a>
</ng-container> </ng-container>
@ -290,7 +295,7 @@
</li> </li>
</ul> </ul>
<div class="mt-4 text-center"> <div class="mt-4 text-center">
<a i18n mat-stroked-button [routerLink]="['/about']" <a i18n mat-stroked-button [routerLink]="routerLinkAbout"
>Learn more about Ghostfolio</a >Learn more about Ghostfolio</a
> >
</div> </div>
@ -397,7 +402,12 @@
> >
</p> </p>
<div class="align-items-center d-flex justify-content-center py-2"> <div class="align-items-center d-flex justify-content-center py-2">
<a color="primary" i18n mat-flat-button [routerLink]="['/register']"> <a
color="primary"
i18n
mat-flat-button
[routerLink]="routerLinkRegister"
>
Get Started Get Started
</a> </a>
<ng-container *ngIf="hasPermissionForDemo"> <ng-container *ngIf="hasPermissionForDemo">

@ -1,9 +0,0 @@
export const routes = [
'markets',
/////
'maerkte',
'marches',
'markten',
'mercados',
'mercati'
] as const;

@ -29,6 +29,8 @@ export class PricingPageComponent implements OnDestroy, OnInit {
public isLoggedIn: boolean; public isLoggedIn: boolean;
public price: number; public price: number;
public priceId: string; public priceId: string;
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkRegister = ['/' + $localize`register`];
public user: User; public user: User;
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();

@ -106,7 +106,7 @@
class="mr-1" class="mr-1"
name="checkmark-circle-outline" name="checkmark-circle-outline"
></ion-icon> ></ion-icon>
<a i18n [routerLink]="['/features']" <a i18n [routerLink]="routerLinkFeatures"
>and more Features...</a >and more Features...</a
> >
</li> </li>
@ -302,7 +302,7 @@
class="mr-1" class="mr-1"
name="checkmark-circle-outline" name="checkmark-circle-outline"
></ion-icon> ></ion-icon>
<a i18n [routerLink]="['/features']" <a i18n [routerLink]="routerLinkFeatures"
>and more Features...</a >and more Features...</a
> >
</li> </li>
@ -360,7 +360,7 @@
</div> </div>
<div *ngIf="!user" class="row"> <div *ngIf="!user" class="row">
<div class="col mt-3 text-center"> <div class="col mt-3 text-center">
<a color="primary" i18n mat-flat-button [routerLink]="['/register']"> <a color="primary" i18n mat-flat-button [routerLink]="routerLinkRegister">
Get Started Get Started
</a> </a>
<p class="m-0 text-muted"><small i18n>Its free.</small></p> <p class="m-0 text-muted"><small i18n>Its free.</small></p>

@ -1,10 +0,0 @@
export const routes = [
'pricing',
/////
'precios',
'precos',
'preise',
'prezzi',
'prijzen',
'prix'
] as const;

@ -1,10 +0,0 @@
export const routes = [
'register',
/////
'enregistrement',
'iscrizione',
'registo',
'registratie',
'registrierung',
'registro'
] as const;

@ -22,7 +22,7 @@ const routes: Routes = [
path: `open-source-alternative-to-${key}`, path: `open-source-alternative-to-${key}`,
loadComponent: () => loadComponent: () =>
import(`./products/${key}-page.component`).then(() => component), import(`./products/${key}-page.component`).then(() => component),
title: `Open Source Alternative to ${name}` title: $localize`Open Source Alternative to ${name}`
}; };
}) })
]; ];

@ -10,9 +10,11 @@ import { products } from './products';
templateUrl: './personal-finance-tools-page.html' templateUrl: './personal-finance-tools-page.html'
}) })
export class PersonalFinanceToolsPageComponent implements OnDestroy { export class PersonalFinanceToolsPageComponent implements OnDestroy {
public pathResources = '/' + $localize`resources`;
public products = products.filter(({ key }) => { public products = products.filter(({ key }) => {
return key !== 'ghostfolio'; return key !== 'ghostfolio';
}); });
public routerLinkAbout = ['/' + $localize`about`];
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();

@ -5,15 +5,15 @@
Discover Open Source Alternatives for Personal Finance Tools Discover Open Source Alternatives for Personal Finance Tools
</h1> </h1>
<div class="introduction mb-4"> <div class="introduction mb-4">
<p> <p i18n>
This overview page features a curated collection of personal finance This overview page features a curated collection of personal finance
tools compared to the open source alternative tools compared to the open source alternative
<a [routerLink]="['/about']">Ghostfolio</a>. If you value <a [routerLink]="routerLinkAbout">Ghostfolio</a>. If you value
transparency, data privacy, and community collaboration, Ghostfolio transparency, data privacy, and community collaboration, Ghostfolio
provides an excellent opportunity to take control of your financial provides an excellent opportunity to take control of your financial
management. management.
</p> </p>
<p> <p i18n>
Explore the links below to compare a variety of personal finance tools Explore the links below to compare a variety of personal finance tools
with Ghostfolio. with Ghostfolio.
</p> </p>
@ -29,10 +29,10 @@
<a <a
class="d-flex overflow-hidden w-100" class="d-flex overflow-hidden w-100"
title="Compare Ghostfolio to {{ product.name }}" title="Compare Ghostfolio to {{ product.name }}"
[routerLink]="['/resources', 'personal-finance-tools', 'open-source-alternative-to-' + product.key]" [routerLink]="[pathResources, 'personal-finance-tools', 'open-source-alternative-to-' + product.key]"
> >
<div class="flex-grow-1 overflow-hidden"> <div class="flex-grow-1 overflow-hidden">
<div class="h6 m-0 text-truncate"> <div class="h6 m-0 text-truncate" i18n>
Open Source Alternative to {{ product.name }} Open Source Alternative to {{ product.name }}
</div> </div>
</div> </div>

@ -4,19 +4,22 @@
<article> <article>
<div class="mb-4 text-center"> <div class="mb-4 text-center">
<h1 class="mb-1"> <h1 class="mb-1">
<strong>Ghostfolio</strong>: The Open Source Alternative to <strong>Ghostfolio</strong>:
<strong>{{ product2.name }}</strong> <ng-container i18n>The Open Source Alternative to</ng-container
>&nbsp;<strong>{{ product2.name }}</strong>
</h1> </h1>
</div> </div>
<section class="mb-4"> <section class="mb-4">
<p> <p>
Are you looking for an open source alternative to {{ product2.name Are you looking for an open source alternative to {{ product2.name
}}? <a [routerLink]="['/about']">Ghostfolio</a> is a powerful }}? <a [routerLink]="routerLinkAbout">Ghostfolio</a> is a powerful
portfolio management tool that provides individuals with a portfolio management tool that provides individuals with a
comprehensive platform to track, analyze, and optimize their comprehensive platform to track, analyze, and optimize their
investments. Whether you are an experienced investor or just investments. Whether you are an experienced investor or just
starting out, Ghostfolio offers an intuitive user interface and a starting out, Ghostfolio offers an intuitive user interface and a
<a [routerLink]="['/features']">wide range of functionalities</a> <a [routerLink]="routerLinkFeatures"
>wide range of functionalities</a
>
to help you make informed decisions and take control of your to help you make informed decisions and take control of your
financial future. financial future.
</p> </p>
@ -280,7 +283,7 @@
<nav aria-label="breadcrumb"> <nav aria-label="breadcrumb">
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="breadcrumb-item"> <li class="breadcrumb-item">
<a i18n [routerLink]="['/resources', 'personal-finance-tools']" <a i18n [routerLink]="routerLinkResourcesPersonalFinanceTools"
>Personal Finance Tools</a >Personal Finance Tools</a
> >
</li> </li>

@ -21,4 +21,11 @@ export class AltooPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'altoo'; return key === 'altoo';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class CopilotMoneyPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'copilot-money'; return key === 'copilot-money';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class DeltaPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'delta'; return key === 'delta';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class DivvyDiaryPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'divvydiary'; return key === 'divvydiary';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class ExirioPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'exirio'; return key === 'exirio';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class FolisharePageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'folishare'; return key === 'folishare';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class GetquinPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'getquin'; return key === 'getquin';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class GoSpatzPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'gospatz'; return key === 'gospatz';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class JustEtfPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'justetf'; return key === 'justetf';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class KuberaPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'kubera'; return key === 'kubera';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class MarketsShPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'markets.sh'; return key === 'markets.sh';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class MaybeFinancePageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'maybe-finance'; return key === 'maybe-finance';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class MonsePageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'monse'; return key === 'monse';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class ParqetPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'parqet'; return key === 'parqet';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class PlannixPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'plannix'; return key === 'plannix';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class PortfolioDividendTrackerPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'portfolio-dividend-tracker'; return key === 'portfolio-dividend-tracker';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class PortseidoPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'portseido'; return key === 'portseido';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class ProjectionLabPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'projectionlab'; return key === 'projectionlab';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class SeekingAlphaPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'seeking-alpha'; return key === 'seeking-alpha';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class SharesightPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'sharesight'; return key === 'sharesight';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class SimplePortfolioPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'simple-portfolio'; return key === 'simple-portfolio';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class SnowballAnalyticsPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'snowball-analytics'; return key === 'snowball-analytics';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class SumioPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'sumio'; return key === 'sumio';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class UtlunaPageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'utluna'; return key === 'utluna';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -21,4 +21,11 @@ export class YeekateePageComponent {
public product2 = products.find(({ key }) => { public product2 = products.find(({ key }) => {
return key === 'yeekatee'; return key === 'yeekatee';
}); });
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
} }

@ -13,6 +13,10 @@ import { Subject } from 'rxjs';
export class ResourcesPageComponent implements OnInit { export class ResourcesPageComponent implements OnInit {
public hasPermissionForSubscription: boolean; public hasPermissionForSubscription: boolean;
public info: InfoItem; public info: InfoItem;
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();

@ -179,7 +179,7 @@
monitor investments, and make informed financial decisions. monitor investments, and make informed financial decisions.
</div> </div>
<div> <div>
<a [routerLink]="['/resources', 'personal-finance-tools']" <a [routerLink]="routerLinkResourcesPersonalFinanceTools"
>Personal Finance Tools →</a >Personal Finance Tools →</a
> >
</div> </div>

@ -1,9 +0,0 @@
export const routes = [
'resources',
/////
'bronnen',
'recursos',
'ressourcen',
'ressources',
'risorse'
] as const;

@ -15,7 +15,7 @@
<div class="pr-1 w-50" i18n>Membership</div> <div class="pr-1 w-50" i18n>Membership</div>
<div class="pl-1 w-50"> <div class="pl-1 w-50">
<div class="align-items-center d-flex mb-1"> <div class="align-items-center d-flex mb-1">
<a [routerLink]="['/pricing']" <a [routerLink]="routerLinkPricing"
>{{ user?.subscription?.type }}</a >{{ user?.subscription?.type }}</a
> >
<gf-premium-indicator <gf-premium-indicator

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save