# node: Node.js Quickstart URL: https://generaltranslation.com/en-US/docs/node/tutorials/quickstart.mdx --- title: Node.js Quickstart description: Add multiple languages to your Node.js server in under 10 minutes --- By the end of this guide, your Node.js server will respond with translated content based on the request's language, using either inline or pre-registered strings. **Prerequisites:** - A Node.js server (Express, Fastify, or similar) - Node.js 18+ **Want automatic setup?** Run `npx gt@latest` to configure everything with the [Setup Wizard](/docs/cli/init). This guide covers manual setup. --- ## Step 1: Install the packages `gt-node` is the library that powers translations in your server. `gt` is the CLI tool that prepares translations for production. ```bash npm i gt-node npm i -D gt ``` ```bash yarn add gt-node yarn add --dev gt ``` ```bash bun add gt-node bun add --dev gt ``` ```bash pnpm add gt-node pnpm add --save-dev gt ``` --- ## Step 2: Create a translation config file Create a **`gt.config.json`** file in your project root. This tells the library which languages you support: ```json title="gt.config.json" { "defaultLocale": "en", "locales": ["es", "fr", "ja"] } ``` - **`defaultLocale`** — the language your server's strings are written in. - **`locales`** — the languages you want to translate into. Pick any from the [supported locales list](/docs/platform/supported-locales). --- ## Step 3: Initialize General Translation Call **`initializeGT`** once at the top of your server's entry file, before any translation functions are used: ```js title="server.js" import { initializeGT } from 'gt-node'; initializeGT({ defaultLocale: 'en', locales: ['en', 'es', 'fr', 'ja'], projectId: process.env.GT_PROJECT_ID, }); ``` This configures the library with your supported languages and project credentials. --- ## Step 4: Set locale context per request Each request needs to know which language to use. Use **`withGT`** to wrap your request handlers — it uses async local storage so translation functions automatically pick up the right locale: ```js title="server.js" import { withGT } from 'gt-node'; app.use((req, res, next) => { const locale = req.headers['accept-language']?.split(',')[0] || 'en'; withGT(locale, () => next()); }); ``` --- ## Step 5: Translate inline strings For translating strings directly inside request handlers, use **`getGT`**: ```js title="server.js" import { getGT } from 'gt-node'; app.get('/api/greeting', async (req, res) => { const gt = await getGT(); res.json({ message: gt('Hello, world!'), welcome: gt('Welcome, {name}!', { name: 'Alice' }), }); }); ``` `getGT` returns a translation function scoped to the current request's locale. --- ## Step 6: Pre-register constant strings (optional) For strings defined outside request handlers — like error messages, enum labels, or constants — use **`msg`** to register them at module scope, then **`getMessages`** to resolve translations at runtime: ```js title="messages.js" import { msg } from 'gt-node'; export const GREETING = msg('Hello, world!'); export const WELCOME = msg('Welcome, {name}!'); export const NOT_FOUND = msg('Resource not found.'); ``` ```js title="handler.js" import { getMessages } from 'gt-node'; import { GREETING, WELCOME, NOT_FOUND } from './messages.js'; app.get('/api/status', async (req, res) => { const m = await getMessages(); res.json({ greeting: m(GREETING), welcome: m(WELCOME, { name: 'Alice' }), }); }); app.use(async (req, res) => { const m = await getMessages(); res.status(404).json({ error: m(NOT_FOUND) }); }); ``` This pattern is useful when the same strings are used across multiple handlers. --- ## Step 7: Set up environment variables (optional) To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your server translates content in real time as you develop. Create a **`.env`** file: ```bash title=".env" GT_API_KEY="your-api-key" GT_PROJECT_ID="your-project-id" ``` Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: ```bash npx gt auth ``` Never expose `GT_API_KEY` publicly or commit it to source control. Yes. Without API keys, `gt-node` works as a standard i18n library. You won't get on-demand translation in development, but you can still: - Provide your own translation files manually - Use all translation functions (`getGT`, `msg`, `getMessages`, etc.) - Run `npx gt generate` to create translation file templates, then translate them yourself --- ## Step 8: See it working Start your server and test with different `Accept-Language` headers: ```bash # Default (English) curl http://localhost:3000/api/greeting # Spanish curl -H "Accept-Language: es" http://localhost:3000/api/greeting # French curl -H "Accept-Language: fr" http://localhost:3000/api/greeting ``` You should see translated responses for each language. In development, translations happen on-demand — you may see a brief delay the first time a new language is requested. In production, translations are pre-generated and load instantly. --- ## Step 9: Full example Here's a complete Express server with all the pieces together: ```js title="server.js" import express from 'express'; import { initializeGT, withGT, getGT, msg, getMessages } from 'gt-node'; // Initialize GT before anything else initializeGT({ defaultLocale: 'en', locales: ['en', 'es', 'fr', 'ja'], projectId: process.env.GT_PROJECT_ID, }); // Pre-register constant strings const NOT_FOUND = msg('Resource not found.'); const app = express(); // Set locale context for each request app.use((req, res, next) => { const locale = req.headers['accept-language']?.split(',')[0] || 'en'; withGT(locale, () => next()); }); // Inline translation app.get('/api/greeting', async (req, res) => { const gt = await getGT(); res.json({ message: gt('Hello, world!') }); }); // Pre-registered message translation app.use(async (req, res) => { const m = await getMessages(); res.status(404).json({ error: m(NOT_FOUND) }); }); app.listen(3000, () => console.log('Server running on port 3000')); ``` --- ## Step 10: Deploy to production In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: ```json title="package.json" { "scripts": { "build": "npx gt translate && " } } ``` Set your **production** environment variables in your hosting provider: ```bash GT_PROJECT_ID=your-project-id GT_API_KEY=gtx-api-your-production-key ``` Never publicly expose your `GT_API_KEY`. That's it — your server is now multilingual. 🎉 --- ## Troubleshooting This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` option to help: ```js gt('Apple', { $context: 'the technology company' }); ``` Both `getGT()` and `msg()` support the `$context` option. --- ## Next steps - [**`initializeGT`**](/docs/node/api/initialize-gt) — Full configuration options - [**`withGT`**](/docs/node/api/with-gt) — Locale context for requests - [**`getGT`**](/docs/node/api/get-gt) — Inline string translation - [**`msg` & `getMessages`**](/docs/node/api/get-messages) — Pre-registered message translation - [**CLI Tool**](/docs/cli/translate) — Translation workflow reference