0
votes

ı am developing an ionic angular android app, and using ngx translate, it just work perfect on web and by installing to my android phone via terminal. but when ı create an apk, and install it on my phone, or downloading the published apk from google play store, at first run of app, translate doesnt work on app, when ı close app and reopen, it works fine after it. some says its about angular lazy loading thing, some says its about configuration thing, some say its version thing, some say do not use ./assets/i18n, use assets/i18n without './'. I tried also but same issue. here is my code:

my app.module:

   import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import {HttpClient, HttpClientModule,HTTP_INTERCEPTORS} from '@angular/common/http'
import {HTTP} from '@ionic-native/http/ngx'
import { TokenInterceptorService } from './core/interceptors/TokenInterceptor.service';
import { NativeStorage } from '@ionic-native/native-storage/ngx';
import { IonicStorageModule } from '@ionic/storage';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {MatDialogModule} from '@angular/material/dialog';
import {MatButtonModule} from '@angular/material/button';
import {MatExpansionModule} from '@angular/material/expansion';
import {MatSelectModule} from '@angular/material/select';
import { MatCommonModule } from '@angular/material/core';
import {MatInputModule} from '@angular/material/input';
import { FormsModule } from '@angular/forms';
import {MatRadioModule} from '@angular/material/radio';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatTabsModule} from '@angular/material/tabs';
import {MatTableModule} from '@angular/material/table';
import { DatePipe } from '@angular/common';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HousekeepingrackComponent } from './core/components/alerts/housekeepingrack/housekeepingrack/housekeepingrack.component';
import { HousekeepingComponent } from './core/components/alerts/housekeeping/housekeeping.component';
import { SecurityComponent } from './core/components/alerts/security/security.component';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { IonicSelectableModule } from 'ionic-selectable';
import { EventService } from './core/services/event/Event.service';

export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}


@NgModule({
  declarations: [AppComponent,HousekeepingrackComponent,HousekeepingComponent,SecurityComponent],
  entryComponents: [],
  schemas:[CUSTOM_ELEMENTS_SCHEMA],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    HttpClientModule,
    IonicStorageModule.forRoot(),
    BrowserAnimationsModule,
    MatDialogModule,
    MatButtonModule,
    MatExpansionModule,
    MatSelectModule,
    MatCommonModule,
    MatInputModule,
    FormsModule,
    MatRadioModule,
    MatCheckboxModule,
    MatTabsModule,
    MatTableModule,
    IonicSelectableModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (HttpLoaderFactory),
        deps: [HttpClient]
      }
    })
  ],
  providers: [
    StatusBar,
    SplashScreen,
    EventService,
    DatePipe,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    HTTP,
    {
      provide:HTTP_INTERCEPTORS,
      useClass:TokenInterceptorService,
      multi:true
    },
    NativeStorage
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

here is my app-routing.module.ts:

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'dasda',
    redirectTo: 'folder/Inbox',
    pathMatch: 'full'
  },
  {
    path: 'folder/:id',
    loadChildren: () => import('./folder/folder.module').then( m => m.FolderPageModule)
  },
  {
    path: '',
    loadChildren: () => import('./pages/login/login.module').then( m => m.LoginPageModule)    
  },
  {
    path: '',
    loadChildren: () => import('./pages/traces/traces.module').then( m => m.TracesPageModule)
  },
  {
    path: 'housekeeping/housekeepingrack',
    loadChildren: () => import('./pages/housekeepingrack/housekeepingrack.module').then( m => m.HousekeepingrackPageModule)
  },
  {
    path: 'housekeeping/rooms',
    loadChildren: () => import('./pages/housekeeping/housekeeping.module').then( m => m.HousekeepingPageModule)
  },
  {
    path: 'operation/security',
    loadChildren: () => import('./pages/security/security.module').then( m => m.SecurityPageModule)
  },
  {
    path: 'profile/search',
    loadChildren: () => import('./pages/profile/profile.module').then( m => m.ProfilePageModule)
  },
  {
    path: 'profilemodal',
    loadChildren: () => import('./modalpages/profilemodal/profilemodal.module').then( m => m.ProfilemodalPageModule)
  },
  {
    path: 'main/dashboard',
    loadChildren: () => import('./pages/dashboard/dashboard.module').then( m => m.DashboardPageModule)
  },
  {
    path: 'guest-search',
    loadChildren: () => import('./modalpages/guest-search/guest-search.module').then( m => m.GuestSearchPageModule)
  },
  {
    path: 'activities',
    loadChildren: () => import('./pages/activities/activities.module').then( m => m.ActivitiesPageModule)
  },
  {
    path: 'reservation',
    loadChildren: () => import('./modalpages/reservation/reservation.module').then( m => m.ReservationPageModule)
  },
  {
    path: 'alakart-modal',
    loadChildren: () => import('./pages/alakart-modal/alakart-modal.module').then( m => m.AlakartModalPageModule)
  },
  {
    path: 'iframe',
    loadChildren: () => import('./modalpages/iframe/iframe.module').then( m => m.IframePageModule)
  },
  {
    path: 'options',
    loadChildren: () => import('./pages/options/options.module').then( m => m.OptionsPageModule)
  },
  {
    path: 'accounting',
    loadChildren: () => import('./pages/accounting/accounting.module').then( m => m.AccountingPageModule)
  }




  
 
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

in my app.component.ts:

     import { Component, OnInit } from '@angular/core';

import { Platform, ToastController } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { EventService } from './core/services/event/Event.service';
import { HttpService } from './core/services/http/http.service';
import { MenuService } from './core/services/menu/menu.service';
import { CompanyService } from './core/services/company/company.service';
import { StorageService } from './core/services/storage/storage.service';
import { Router } from '@angular/router';
import { TranslatingService } from './core/services/translate/translate.service';
import { TranslateService } from '@ngx-translate/core';
import { LoadingService } from './core/services/loading/loading.service';
import { SharedService } from './core/services/shared/shared.service';
import { ThemeService } from './core/services/theme.service';


@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})


export class AppComponent implements OnInit {


  public selectedIndex = 0;
  public userName: string = "";
  public lastCompanyName: string = "";
  public appPages = [];
  public companies = [];
  public userInfo: any;

  public labels = ['Family', 'Friends', 'Notes', 'Work', 'Travel', 'Reminders'];
  menuList: any[];
  deviceLanguage: any;
  isFromLogin: Boolean = false;
  loaderInstance: any;
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private loading: LoadingService,
    private eventService: EventService,
    private httpService: HttpService,
    private menuService: MenuService,
    private router: Router,
    private sharedService: SharedService,
    private translatingService: TranslatingService,
    private companyService: CompanyService,
    private storageService: StorageService,
    private angularTranslateService: TranslateService,
    private toastCtrl: ToastController,
    private themeService: ThemeService,
    private shared: SharedService) {
    this.initializeApp();
    this.storageService.getItem("themeColor").then(res => {
      if (res) {

      } else {
        this.storageService.setItem("themeColor", "#8f074d")
      }
      this.themeService.setTheme()
    })
    this.shared.loaderObservable.subscribe(res => {
      this.loaderInstance = res
    })
    this.eventService.isLoggedInObserved.subscribe(data => {
      if (data) {
        return this.FillCurrentAppPages(data.isLoggedIn).then(res => {
          return res
        }).catch(err => {
          console.log("FillCurrentAppPages error", err)
        });
      }
    });
    this.storageService.getItem("appPages").then(appPages => {
      this.appPages = appPages
    }).catch(err => { })
    this.storageService.getItem("GetAccountAndCompanyInfo").then(GetAccountAndCompanyInfo => {
      // alert("GetAccountAndCompanyInfo cache "+ JSON.stringify(GetAccountAndCompanyInfo))
      if (GetAccountAndCompanyInfo) {
        this.userInfo = GetAccountAndCompanyInfo.UserInfo;
        this.storageService.setItem('userInfo', this.userInfo);
        this.IsHotelApiWorking();
        this.userName = GetAccountAndCompanyInfo.UserInfo.UserName;
        this.companies = GetAccountAndCompanyInfo.CompaniesAccounts;
        this.storageService.setItem("companies", this.companies)
        this.lastCompanyName = this.GetLastCompanyName(this.companies, GetAccountAndCompanyInfo.UserInfo.LastCompanyId);
        GetAccountAndCompanyInfo.SidebarNavigations.forEach(nav => {
          nav.submenu.forEach(sub => {
            this.menuList.forEach(menu => {
              if (menu.target == sub.target) {
                this.appPages.push({ title: menu.name, url: menu.url, icon: menu.icon })
              }
            });
          });
        });
      }
    }).catch(err => { })

  }
  // ngOnDestroy() {
  //   console.log('destroy app comp');

  //   // this.onDestroy.next();
  // }
  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      //cihazın dilini bulur ve çevirici servise ilgili parametreleri gönderip json dil dosyalarını kullanır
      this.deviceLanguage = this.translatingService.languageSelectorFromStringToNumber(this.angularTranslateService.getBrowserLang())
      // alert("dil: "+JSON.stringify(this.deviceLanguage))
      this.storageService.setItem("LangID", this.deviceLanguage)
      this.translatingService.switchLanguage(this.deviceLanguage)
    });
  }

  GetAccountAndCompanyInfo(): Promise<any> {
    return this.httpService.Post('v1/SednaMobileB2B/GetAccountAndCompanyInfo', {}).then(GetAccountAndCompanyInforesponse => {
      // alert("GetAccountAndCompanyInfo api istek "+ JSON.stringify(GetAccountAndCompanyInforesponse))
      if (GetAccountAndCompanyInforesponse) {
        this.storageService.setItem("GetAccountAndCompanyInfo", GetAccountAndCompanyInforesponse)
        this.userInfo = GetAccountAndCompanyInforesponse.UserInfo;
        this.storageService.setItem('userInfo', this.userInfo);
        this.IsHotelApiWorking();
        this.userName = GetAccountAndCompanyInforesponse.UserInfo.UserName;
        this.companies = GetAccountAndCompanyInforesponse.CompaniesAccounts;
        this.storageService.setItem("companies", this.companies)
        this.lastCompanyName = this.GetLastCompanyName(this.companies, GetAccountAndCompanyInforesponse.UserInfo.LastCompanyId);
        const findPage = this.appPages.find(x => x.title == 'Dashboard');
        if (!findPage) {
          this.appPages.push({ title: 'Dashboard', url: '/main/dashboard', icon: 'home' })
        }
        GetAccountAndCompanyInforesponse.SidebarNavigations.forEach(nav => {
          nav.submenu.forEach(sub => {
            this.menuList.forEach(menu => {
              if (menu.target == sub.target) {
                if (menu.target == "bms.mobileb2b.dashboard") {

                } else {
                  this.appPages.push({ title: menu.name, url: menu.url, icon: menu.icon })
                  this.storageService.SetPagePermissions(menu.target);
                }

              }
            });
          });
        });

        this.appPages.push({ title: 'Ayarlar', url: '/options', icon: 'settings' });
        // this.appPages.push({ title: 'Accounting', url: '/accounting', icon: 'exit' })
        this.appPages.push({ title: 'Çıkış Yap', url: '', icon: 'exit', type: 'exit' })
        this.storageService.setItem("appPages", this.appPages)

        this.router.navigateByUrl('/main/dashboard');
        if (this.loaderInstance) {
          console.log("loader instance: ", this.loaderInstance)
          this.loaderInstance.loadingController.ctrl.dismiss()
        }
        this.eventService.publish({ name: 'refreshdashboard' });

        return GetAccountAndCompanyInforesponse

      }

    }).catch(err => {
      return err
      if (this.loaderInstance) {
        console.log("loader instance: ", this.loaderInstance)
        this.loaderInstance.loadingController.ctrl.dismiss()
      }
      alert("getAccountAndCompanyInfos error " + JSON.stringify(err))
    })

  }



  FillCurrentAppPages(isLoggedIn: boolean): Promise<any> {
    if (isLoggedIn) {
      this.appPages = [];
      this.menuList = this.menuService.GetMobileMenuList();
      return this.GetAccountAndCompanyInfo().then(res => {
        return res
      }).catch(err=>{
        alert("fill current hata: "+JSON.stringify(err))
        return err
        
      })
    }
  }

  GetLastCompanyName(companies: any, lastCompanyId: any): string {
    var companyName: string = "Not Found";
    companies.forEach(company => {
      company.Companies.forEach(subCompany => {
        if (subCompany.Id == lastCompanyId) {
          companyName = subCompany.CompanyName;
          return;
        }
      })
    });
    this.storageService.setItem("lastCompanyName", companyName)
    this.sharedService.updateLastCompanyName(true);
    return companyName;
  }

  changeCompany(subCompany): void {
    this.loading.show().then(res => {
      this.companyService.ChangeActiveCompany(subCompany.Id).then(response => {
        this.storageService.getItem('token').then(token => {
          this.httpService.Sedna360RefreshToken(token.refresh_token).then(refreshResponse => {
            this.storageService.setItem('token', refreshResponse);
            this.FillCurrentAppPages(true).then(res => {

              this.loading.hide()
            });
          }).catch(err => {
            alert("change company refresh token err: " + JSON.stringify(err))
          });
        })
      });
    })
  }

  async IsHotelApiWorking() {
    this.storageService.getItem('userInfo').then(async userResponse => {
      // alert("isotelapiworking "+ JSON.stringify(userResponse))
      if (userResponse.IsHotelApiWorking == false) {
        const toast = await this.toastCtrl.create({
          message: 'Hotel bağlantı Hatası',
          duration: 2000,
          cssClass: 'failToast',
          position: 'top'
        });
        toast.present();
      }
    });
  }

  selectedIndexFunc(i) {
    this.selectedIndex = i;
    var selectedMenu = this.appPages[i];
    console.log(selectedMenu)
    if (selectedMenu.type) {
      if (selectedMenu.type == 'exit') {
        this.storageService.removeAll()
      }

    }
  }
  ngOnInit() {
    console.log("Buraya ne zaman geliyor.")
    const path = window.location.pathname.split('folder/')[1];
    if (path !== undefined) {
      this.selectedIndex = this.appPages.findIndex(page => page.title.toLowerCase() === path.toLowerCase());
      console.log("selected index app comp ", this.selectedIndex)
    }
  }
}

and my package.json:

{
  "name": "sednamobileb2b",
  "version": "0.0.1",
  "author": "Ionic Framework",
  "homepage": "https://ionicframework.com/",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~10.0.0",
    "@angular/cdk": "^10.2.7",
    "@angular/common": "~10.0.0",
    "@angular/core": "~10.0.0",
    "@angular/forms": "~10.0.0",
    "@angular/material": "^10.2.7",
    "@angular/platform-browser": "~10.0.0",
    "@angular/platform-browser-dynamic": "~10.0.0",
    "@angular/router": "~10.0.0",
    "@capacitor/core": "2.4.2",
    "@ionic-native/core": "^5.0.0",
    "@ionic-native/http": "^5.31.1",
    "@ionic-native/native-storage": "^5.31.1",
    "@ionic-native/splash-screen": "^5.0.0",
    "@ionic-native/status-bar": "^5.0.0",
    "@ionic/angular": "^5.0.0",
    "@ionic/storage": "^2.3.1",
    "@ngx-translate/core": "^13.0.0",
    "@ngx-translate/http-loader": "^6.0.0",
    "@swimlane/ngx-datatable": "^18.0.0",
    "cordova-sqlite-storage": "^5.1.0",
    "ionic-selectable": "^4.7.1",
    "ngx-spinner": "^10.0.1",
    "rxjs": "~6.5.5",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1000.0",
    "@angular/cli": "~10.0.5",
    "@angular/compiler": "~10.0.0",
    "@angular/compiler-cli": "~10.0.0",
    "@angular/language-service": "~10.0.0",
    "@capacitor/cli": "2.4.2",
    "@ionic/angular-toolkit": "^2.3.0",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "cordova-android": "^9.0.0",
    "cordova-plugin-advanced-http": "^3.1.0",
    "cordova-plugin-device": "^2.0.2",
    "cordova-plugin-file": "^6.0.2",
    "cordova-plugin-ionic-keyboard": "^2.2.0",
    "cordova-plugin-ionic-webview": "^4.2.1",
    "cordova-plugin-nativestorage": "^2.3.2",
    "cordova-plugin-splashscreen": "^5.0.2",
    "cordova-plugin-statusbar": "^2.4.2",
    "cordova-plugin-whitelist": "^1.3.3",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.0.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~3.3.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~3.9.5"
  },
  "description": "An Ionic project",
  "config": {
    "ionic_sass": "./config/sass.config.js",
    "ionic_copy": "./config/copy.config.js"
  },
  "cordova": {
    "plugins": {
      "cordova-plugin-nativestorage": {},
      "cordova-plugin-whitelist": {},
      "cordova-plugin-statusbar": {},
      "cordova-plugin-device": {},
      "cordova-plugin-splashscreen": {},
      "cordova-plugin-ionic-webview": {
        "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
      },
      "cordova-plugin-ionic-keyboard": {},
      "cordova-plugin-advanced-http": {}
    },
    "platforms": [
      "android"
    ]
  }
}

and my translateservice is just working fine, I mean the lang data is coming correctly. I realized the root must be changed at least once but still it looks like its not working, but after changing root once, ı close and reopen app, its works perfectly anytime. can someone tell me how to fix this?

1

1 Answers

1
votes

Please share your app.component.ts code complete or constructor where you added language, in my case, I set English as a default language inside constructor and then called initializeApp() function where I first get my privious language and set after that, hide the splash screen. So the problem is you have to set language before showing preview, but in your and my case function which get the language id is take some time, so you just have to show delay and call and set language before splash screen hide, and also set a default language for user good experience.

enter image description here