Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Staging build disables fetch from backend #3180

Closed
pennal opened this issue Mar 17, 2023 · 9 comments
Closed

Staging build disables fetch from backend #3180

pennal opened this issue Mar 17, 2023 · 9 comments

Comments

@pennal
Copy link

pennal commented Mar 17, 2023

Hi,

we currently have a Nuxt app that uses Tolgee for translations. We also have three different stages: dev, staging and prod. To configure Tolgee, we use the following code:

import {
  DevTools,
  FormatSimple,
  T,
  Tolgee,
  TolgeeProvider,
  VueTolgee,
} from "@tolgee/vue";

const language = useLanguage();

export default defineNuxtPlugin((nuxtApp) => {
  const { tolgee: config, isProduction } = useRuntimeConfig();

  // Tolgee config that depends on the current NUXT_DEPLOYMENT_ENV
  const tolgeeConfig = isProduction
    ? {
        // Production
        staticData: importAvailableLanguages(),
      }
    : {
        // Development
        apiUrl: config.apiUrl,
        apiKey: config.apiKey,
      };
  const tolgee = Tolgee()
    .use(DevTools())
    .use(FormatSimple())
    .init({
      language: language.value || "en",
      ...tolgeeConfig,
    });

  nuxtApp.vueApp.use(VueTolgee, { tolgee });

  nuxtApp.vueApp.component("T", T).component("TolgeeProvider", TolgeeProvider);

  return {
    provide: {
      // useTranslate: str => useTranslate(str),
      t: (str) => tolgee.t(str),
    },
  };
});

Our package.json is as follows:

"scripts": {
    "build-production": "nuxi build  --dotenv .env.production",
    "build-staging": "nuxi build --dotenv .env.staging",
    "build-dev": "nuxi build --dotenv .env",
    "dev": "nuxi dev --dotenv .env.development",
    // ...
}

Our goal is to have two different behaviours:

  • On Prod, we download the translations using the REST Api, and bundle them directly in the build. This works fine.
  • On dev and staging, we want to be able to fetch the translations from the Backend live, and allow the translators to enter the translations without having to use the main UI. This works fine in two cases:
    • Running with the dev build: in this case, everything works. The translations are fetched, and we are able to see/edit/create them without any issues
    • Using the extension (Chrome). If we use the extension, the keys are substituted correctly and we can interact with the backend.

For staging, we want that whoever accesses the page can see the translations but not edit them. Therefore we have a read only key, that at least can display the translations. For some reason, the plugin does not fetch the translations from the backend, and therefore shows the keys we have assigned to them.

My suspicion is that once we run the build-staging script, nuxi sets the NODE_ENV to production and Tolgee then automatically switches off some setting. Is this the case? I found something that may be related in #3153, but I am not sure.

@stepan662
Copy link
Collaborator

Hey, yes once you do production build, the DevTools are ommited based on NODE_ENV.

What you can do in this case is to use InContextTools exported in @tolgee/web/tools, which is essentialy the same thing as DevTools only independent on NODE_ENV.

https://tolgee.io/js-sdk/api/web_package/tools#incontexttools

However this will increase your bundle size significantly, so i would do this through dynamic import only if isProduction is true.

Something like this:

  const tolgee = Tolgee()
    .use(FormatSimple())
    .init({
      language: language.value || "en",
      ...tolgeeConfig,
    });
    
...

if (isProduction) {
  import('@tolgee/web/tools').then((module) => {
    tolgee.addPlugin(module.InContextTools())
  })
}

@stepan662
Copy link
Collaborator

However, be aware that your staging shouldn't be publicly visible as your key will be included in the page.

@pennal
Copy link
Author

pennal commented Mar 17, 2023

Thank you, that solved the issue!

I understand that keys will be leaked, but this is a staging env that is behind auth. So I am not really worried about leaking data.

Maybe it would be good to add this info in the Docs? I know I would have appreciated seeing this a few days ago

@stepan662
Copy link
Collaborator

Cool, thanks for feedback. I'll make an issue for that 👍

@4F2E4A2E
Copy link

Could someone provide a nuxt example? This is how far I've come:

"devDependencies": {
    "@nuxt/devtools": "1.0.8",
    "nuxt": "3.11.1",
    "typescript": "^5.4.2",
    "vue": "3.4.21",
    "vue-router": "4.3.0",
    "vue-tsc": "^2.0.6"
  },
  "dependencies": {
    "@tolgee/vue": "^5.22.0",
    "@formkit/nuxt": "1.6.0",
    "@nuxtjs/i18n": "8.2.0",
    "@nuxt/ui": "2.14.2"
  }
// nuxt.config.ts

export default defineNuxtConfig({
    ssr: false,
    srcDir: "src",
    css: ["~/assets/css/main.css"],
    devtools: {enabled: true},
    modules: ["@nuxt/ui"],
    colorMode: {
        preference: "light",
    },
    typescript: {
        typeCheck: false,
        strict: true,
    },
    plugins: [
        '~/plugins/tolgee.ts'
    ],
});
// plugins/tolgee.ts
import {FormatSimple} from "@tolgee/core";
import {DevTools, Tolgee} from "@tolgee/web";
import {T, TolgeeProvider, VueTolgee} from "@tolgee/vue/lib";

export default defineNuxtPlugin((nuxtApp) => {
    const {tolgee: config, isProduction} = useRuntimeConfig();

    const tolgee = Tolgee()
        .use(DevTools())
        .use(FormatSimple())
        .init(({
            language: 'en',
            apiUrl: process.env.VUE_APP_TOLGEE_API_URL,
            apiKey: process.env.VUE_APP_TOLGEE_API_KEY,
        }));

    nuxtApp.vueApp.use(VueTolgee, {tolgee});
    nuxtApp.vueApp.component("T", T).component("TolgeeProvider", TolgeeProvider);

    return {
        provide: {
            // useTranslate: str => useTranslate(str),
            t: (str: string) => tolgee.t(str),
        },
    };
});
[8:16:47 PM]  ERROR  Nuxt Build Error: [vite]: Rollup failed to resolve import "src/plugins/tolgee.ts" from "virtual:nuxt:.nuxt/plugins/client.mjs".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
build.rollupOptions.external

  This is most likely unintended because it can break your application at runtime.
  If you do want to externalize this module explicitly add it to
  build.rollupOptions.external
  at viteWarn (node_modules/vite/dist/node/chunks/dep-jvB8WLp9.js:67190:27)
  at onRollupWarning (node_modules/vite/dist/node/chunks/dep-jvB8WLp9.js:67218:9)
  at onwarn (node_modules/vite/dist/node/chunks/dep-jvB8WLp9.js:66922:13)
  at node_modules/rollup/dist/es/shared/node-entry.js:18303:13
  at Object.logger [as onLog] (node_modules/rollup/dist/es/shared/node-entry.js:19950:9)
  at ModuleLoader.handleInvalidResolvedId (node_modules/rollup/dist/es/shared/node-entry.js:18893:26)
  at node_modules/rollup/dist/es/shared/node-entry.js:18851:26

error: script "build" exited with code 1

@4F2E4A2E
Copy link

I have also come across this nuxt-tolgee package, but I have not tried it yet: https://git.deditoolbox.fr/mlcsthor/nuxt-tolgee

@stepan662
Copy link
Collaborator

Hi, I'm not able to provide nuxt example, but I think this is not correct import {T, TolgeeProvider, VueTolgee} from "@tolgee/vue/lib";. It should be @tolgee/vue

@pennal
Copy link
Author

pennal commented Mar 20, 2024

This is what we are using in a nuxt app. It is stripped to the bare minimum, so you might have to adapt it to your situation:

// package.json
// ...
"dependencies": {
    // ...
    "@tolgee/vue": "^5.2.1"
   // ...
}
// ...
// plugins/vue-tolgee.js
import { FormatSimple, T, Tolgee, TolgeeProvider, VueTolgee } from '@tolgee/vue';


export default defineNuxtPlugin((nuxtApp) => {
  const tolgee = Tolgee()
    .use(FormatSimple())
    .init({
      language: 'en', // You need to supply your own way of switching the language
      apiUrl:'<YOUR_API_URL>',
      apiKey: '<YOUR_API_KEY>',
    });

  nuxtApp.vueApp.use(VueTolgee, { tolgee });

  nuxtApp.vueApp.component('T', T).component('TolgeeProvider', TolgeeProvider);

  return {
    provide: {
      // useTranslate: str => useTranslate(str),
      t: str => tolgee.t(str),
    },
  };
});

Since plugins are autoregistered (docs) in theory there is no need to import it manually.

Then to translate your text:

<p>{{ $t('your.translation.key') }}</p>

@4F2E4A2E
Copy link

4F2E4A2E commented Mar 21, 2024

Hi, I'm not able to provide nuxt example, but I think this is not correct import {T, TolgeeProvider, VueTolgee} from "@tolgee/vue/lib";. It should be @tolgee/vue

You're right, after git cloning and reinstalling everything the import error is gone. Thank you!

Now I have the plugin as typescript loaded, but nothing happens. It does not even try to fetch the translations.

// plugins/vue-tolgee.ts


import {FormatSimple, T, Tolgee, TolgeeProvider, useTranslate, VueTolgee} from "@tolgee/vue";

export default defineNuxtPlugin(nuxtApp => {
    const tolgee = Tolgee()
        .use(FormatSimple())
        .init({
            language: 'en',
            apiUrl: process.env.TOLGEE_API_URL,
            apiKey: process.env.TOLGEE_API_KEY,
        });

    nuxtApp.vueApp.use(VueTolgee, {tolgee});
    nuxtApp.vueApp.component('T', T).component('TolgeeProvider', TolgeeProvider);

    console.log('Tolgee initialized', tolgee.t('login-title'));

    return {
        provide: {
            useTranslate: (str: string) => useTranslate(str),
            t: (str: string) => tolgee.t(str),
        },
    };
})
<script lang="ts" setup>
const { $t, $useTranslate } = useNuxtApp()
console.log($useTranslate("login-title"))
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants