tolgee / tolgee-js

Tolgee JavaScript libraries monorepo
https://tolgee.io
MIT License
219 stars 24 forks source link

feat: add flag for custom include DevTools #3153

Closed jmtt89 closed 1 year ago

jmtt89 commented 1 year ago

The new version does not load translations from the Tolgee Server using an API key and API URL when running in production. i have a Testing, Staging, and Production environment, all of which run with NODE_ENV set to "production". Testing runs with source maps and Staging runs exactly like Production.

For Staging, it would be useful to have the translations dynamically connected to the Tolgee server instead of using static data to avoid having to update every translation. However, the current configuration makes this difficult to achieve. If InContextTools are included, they will also be included in the production bundle, and if only DevTools are included, they will not be included in the Testing and Staging Environments.

I suggest include a configuration flag in DevTools to explicitly include it, instead of relying solely on process.env.NODE_ENV.

In Tolgee V4 i got this using require with @tolgee/ui package but on v5 i don't know if it's posible

  imports: [
    NgxTolgeeModule.forRoot({
      apiUrl: environment.tolgeeApiUrl,
      apiKey: environment.tolgeeApiKey,
      ui: environment.tolgeeApiKey ? require('@tolgee/ui') : undefined,
      staticData: !environment.tolgeeApiKey
        ? {
            en: () => import('../../assets/i18n/en.json'),
            ...
          }
        : undefined
    })
  ]

i already tried to require just InContextTools from @tolgee/web/tools but is included on production build too

{
      provide: TOLGEE_INSTANCE,
      useFactory: () => {
        return Tolgee()
          .use(environment.tolgeeApiKey && require('@tolgee/web/tools').InContextTools())
          .use(FormatIcu())
          .init({
            language: 'en',

            // for development
            apiUrl: environment.tolgeeApiUrl,
            apiKey: environment.tolgeeApiKey,

            // for production
            staticData: !environment.tolgeeApiKey
              ? {
                  en: () => import('../../assets/i18n/en.json'),
                  ...
                }
              : undefined
          })
      }
    }
stepan662 commented 1 year ago

Hey, the flag is a bit problematic. It depends on the build setup, but you can't generally use whatever you want instead of process.env.NODE_ENV because it must be replaced at the build time.

Easiest solution for you I think would be to build your staging build with production: false in angular environment. Then you can use DevTools and it won't be included on production.

stepan662 commented 1 year ago

BTW: I've tested your solution with environment.tolgeeApiKey and I think it doesn't work even with 4x version as the UI packages is still included even when it's not used.

jmtt89 commented 1 year ago

that solution was tool me by @JanCizmar here https://github.com/tolgee/tolgee-js/issues/3104

I checked it using this npm script

"analyzer:prod": "ng build --configuration production --source-map && source-map-explorer dist/messangi-ui/*.js --html dist/result.html

and work fine for me

But if not is posible on V5 i will find some workaround, maybe using fileReplacements on angular.json with one file per environment or something like that.

production: false can work for testing environment but for staging environment i need run with production:true

jmtt89 commented 1 year ago

ok, my solution was:

1- Create a Wrapper Module for Tolgee using apiURL, apiKey and InContextTool

Base TranslateModule (tolgee wrapper)

import { NgModule } from '@angular/core'
import { NgxTolgeeModule, Tolgee, TOLGEE_INSTANCE } from '@tolgee/ngx'
import { InContextTools } from '@tolgee/web/tools'
import { FormatIcu } from '@tolgee/format-icu'

import { environment } from '../../environments/environment'

@NgModule({
  ...
  imports: [NgxTolgeeModule],
  providers: [
    {
      provide: TOLGEE_INSTANCE,
      useFactory: () => {
        return Tolgee().use(InContextTools()).use(FormatIcu()).init({
          language: 'en',

          // for development
          apiUrl: environment.tolgeeApiUrl,
          apiKey: environment.tolgeeApiKey
        })
      }
    }
  ]
})
export class TranslateModule {}

2- Create a Second Module for tolgee using staticData

StaticData (another tolgee wrapper)

/* eslint-disable @typescript-eslint/no-var-requires */
import { NgModule } from '@angular/core'
import { NgxTolgeeModule, Tolgee, TOLGEE_INSTANCE } from '@tolgee/ngx'
import { FormatIcu } from '@tolgee/format-icu'

@NgModule({
  ...
  imports: [NgxTolgeeModule],
  providers: [
    {
      provide: TOLGEE_INSTANCE,
      useFactory: () => {
        return Tolgee()
          .use(FormatIcu())
          .init({
            language: 'en',

            // for production
            staticData: {
              en: () => import('../../assets/i18n/en.json'),
              es: () => import('../../assets/i18n/es.json'),
              pt: () => import('../../assets/i18n/pt.json')
            }
          })
      }
    }
  ]
})
export class TranslateModule {}

3- load base module on app.module.ts

import { TranslateModule } from './translate-wrapper/translate.module'
...
@NgModule({
  ...
  imports: [
    TranslateModule,
    ...
  ]
   ...
})
export class AppModule {}

4- on angular.json file, use fileReplacements for replace base module (dynamic) for the staticData version when is necesary

  {
    "replace": "src/app/translate-wrapper/translate.module.ts",
    "with": "src/app/translate-wrapper/translate.module.staticData.ts"
  }
JanCizmar commented 1 year ago

Thanks @jmtt89 !