From 3002228995e2343e08c2993e390d69f4070a0eae Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Fri, 16 Oct 2026 17:11:57 -0700 Subject: [PATCH 01/19] docs(kb): revise the five original knowledge base articles Applies the #630 revisions to the articles already on main: - kb/best-localization-software.mdx - kb/how-to-handle-plurals-in-react.mdx - kb/i18n-without-translation-files.mdx - kb/multilingual-nextjs-seo.mdx - kb/translate-conditional-jsx.mdx Co-Authored-By: Claude Opus 5.5 --- kb/best-localization-software.mdx | 101 ++++----- kb/how-to-handle-plurals-in-react.mdx | 246 ++------------------- kb/i18n-without-translation-files.mdx | 145 +++--------- kb/multilingual-nextjs-seo.mdx | 303 +------------------------- kb/translate-conditional-jsx.mdx | 101 ++------- 5 files changed, 129 insertions(+), 767 deletions(-) diff --git a/kb/best-localization-software.mdx b/kb/best-localization-software.mdx index d4939ba30..1a8aeb377 100644 --- a/kb/best-localization-software.mdx +++ b/kb/best-localization-software.mdx @@ -1,92 +1,71 @@ --- title: What is the best localization software for developers? -summary: Look for one system that covers the whole pipeline, from the i18n library in your code to translation and delivery, instead of stitching together a separate library, translation management system, and translation vendor. +summary: The best localization software for developers translates content where it is written in the code, with context from your product, and keeps every language current. General Translation does this with open-source libraries, Context Groups, and Locadex, an AI agent which opens pull requests. date: 2026-05-04 +updated: 2026-10-14 category: workflow-tools authors: [jackie] redirectFrom: [best-localization-software] related: [i18n-without-translation-files, multilingual-nextjs-seo] --- -If you search "best localization software" right now, you'll find a dozen articles written by localization vendors, each ranking themselves first. They compare feature matrices, list pros and cons, and conclude (surprise!) that you should pick them. +The best localization software for developers starts from the code: it translates content where the component is written, with context from your product, keeps every language current as the code changes, and lets people review the result. General Translation is the best fit because it's the full stack in one system: open-source internationalization (i18n) libraries, an AI-native translation platform, and Locadex, an AI agent which internationalizes your code and translates your content through pull requests. Because General Translation connects your code and translations, each translation can carry context from the code and stay consistent across releases. -We're not going to do that. Instead, we'll explain why the entire category is solving the wrong problem, and what solving the right one looks like. +## How the approaches compare -## The localization stack is broken into three +Localizing an app takes internationalization, which prepares the code to render each locale with its own dates, numbers, and plural forms, and translation, which writes the text in each language. It also takes tooling that keeps the two in step as the code changes. An i18n library renders translations but doesn't write them, and a translation engine writes them without seeing the code. -Shipping a multilingual app in 2026 requires stitching together three completely separate systems: +| Approach | What it does well | What it leaves to you | +| --- | --- | --- | +| An i18n library alone (`i18next`, `react-intl`, `next-intl`) | Mature runtimes for rendering translations and formatting values | Extracting strings into key files, refactoring components, and producing and maintaining every translation | +| Google Translate | Fast, general-purpose translation of text | It translates each string on its own, without the surrounding UI or your tone; plurals, delivery, and review are up to you | +| A raw AI API (OpenAI API, Claude API) | Fluent translation that follows instructions | Assembling context for every string, keeping terms consistent across releases, plurals and locale formatting, review, and delivery | +| A translation management system, which handles strings outside the codebase | One place for translators to edit and review strings | Exporting strings to files and importing the results, context that an exported list doesn't carry, and keeping the export current as the code changes | +| General Translation (libraries, Context Groups, and Locadex) | [``](/docs/react/reference/components/t) translates JSX in place, Context Groups (shared instructions for terms and tone) apply to new translations, and the `gt` CLI or Locadex translates each change | Wrapping content in [``](/docs/react/reference/components/t) (or letting Locadex do it), and a Starter or Enterprise plan for Locadex and team invites | -1. **An i18n library** — handles string extraction, interpolation, pluralization, and locale routing inside your codebase. It renders translations. It doesn't produce them. -2. **A translation management system (TMS)** — stores translation files, manages workflows, and coordinates handoffs. It sits between your code and your translators but doesn't do the translating. -3. **A language service provider (LSP)** — the human translators, agencies, or machine translation engines that actually produce the translated content. They don't know anything about your code or your TMS. +Use an i18n library alone when translators already maintain the language files and releases can wait for them. Use Google Translate or a raw AI API for one-off text. Use a translation management system when a separate localization team owns content outside the code. Use General Translation when copy changes with most releases and each change should ship in every language with the release that adds it. -The library knows nothing about your translations. The TMS knows nothing about your code. The translation provider knows nothing about either. Wiring them together takes weeks of engineering time upfront, and then bleeds hours every sprint on syncing files, resolving merge conflicts, debugging webhooks, and babysitting a pipeline that was never designed to be one. +## Translation in your code, with no keys to write -## What "end-to-end" actually means +General Translation's [``](/docs/react/reference/components/t) component wraps JSX and translates it in place, as one unit with its nested elements, so you don't assign keys or write a file for each language by hand. For standalone strings, such as placeholders and `aria-label` values, use the function that [`useGT`](/docs/react/reference/hooks/use-gt) returns. Run [`npx gt init`](/docs/cli/reference/commands/init) to detect your framework and create `gt.config.json`. -General Translation is not a library. It's not a TMS. It's the whole pipeline, used by developer-first teams at Cursor, Ramp, Profound, Cognition, Sierra, and ClickHouse. - -- **Open-source developer libraries**: [`gt-next`](/docs/react/nextjs-quickstart), [`gt-react`](/docs/react/react-quickstart), and support for [React Native/Expo](/docs/react/react-native-quickstart). Drop-in SDKs with full TypeScript support. -- **An AI-first translation platform** that understands your codebase, your product, and your terminology. Not generic machine translation bolted on top. -- **Locadex, the AI agent**: an [automated internationalization engineer](/docs/platform/locadex/quickstart) that scans your codebase, internationalizes your code, creates translations, and opens pull requests on every push. - -Building both the library and the translation engine together makes localization ten times easier. No JSON export/import, no file management, no agencies to coordinate. Translations flow directly from your source code to production. - -## What's wrong with traditional TMS platforms - -Legacy translation management systems were built for a pre-AI world. They assume a specific workflow: content gets extracted from your codebase, uploaded to a dashboard, assigned to translators, reviewed, approved, exported, and re-integrated. It works some of the time, but it's slow, expensive, and fragile. - -**They manage files, not code.** A TMS ingests your translation files (JSON, XLIFF, PO, etc.) and gives you tools to manage them. But the real source of truth is your codebase: your components, your variables, your UI hierarchy. Managing the files without understanding the code means context is always lost in transit. - -Most platforms have added AI/MT features in the last few years, usually by routing strings through third-party machine translation engines and letting you pick which one to use. The AI sees isolated strings. It doesn't see your component tree, your variable names, or the surrounding UI. That's why MT output still needs heavy editing. - -**They scale by adding people, not by removing work.** The TMS business model is built around coordinating human translators: roles, permissions, review chains, approval workflows. That's necessary for regulated enterprise content. It's pure overhead for a dev team shipping a SaaS app in 20 languages. - -And pricing? Several of the most popular platforms require a sales conversation to even see numbers. Others charge per-seat fees that balloon as your team grows. Unpredictable costs make it hard to budget for new languages. - -## What's wrong with standalone i18n libraries - -Popular i18n libraries for React and Next.js handle rendering well: interpolation, pluralization, locale routing, Server Component support. - -**But they don't translate anything.** - -They render whatever you give them. You still need to: -- Extract every translatable string into JSON files -- Maintain a separate file for every locale -- Either translate those files manually, hire translators, or plug in a TMS -- Keep every file in sync as your codebase changes - -At 10 languages and 500 keys, that's 5,000 entries to maintain. At 50 languages it's 25,000. The library doesn't help you with any of that. It just renders whatever you give it — half the problem, at best. - -## How General Translation closes the loop - -**1. Install and write code.** Run the [setup wizard](/docs/cli/quickstart) and wrap content in [``](/docs/react/reference/components/t) components. No key extraction. No JSON files. - -```tsx +```tsx title="app/page.tsx" import { T } from 'gt-next'; export default function Home() { return ( - -

Welcome to our app

-

This content is translated automatically.

-
+
+ +

Welcome to my app

+

This content will be translated automatically.

+
+
); } ``` -**2. Develop.** Translations appear on-demand. Switch languages and see results immediately. +The libraries are free, open source, and MIT-licensed, and they work without the platform: `gt-next` for Next.js, `gt-react` for React, `gt-vue` for Vue, and `gt-node` for Node.js. In React apps, [``](/docs/react/reference/components/num), [``](/docs/react/reference/components/currency), and [``](/docs/react/reference/components/datetime) format values for each locale, and [``](/docs/react/reference/components/plural) picks each language's plural form. If you already use `next-intl` or `react-i18next`, the `gt` CLI translates your existing files in their own string syntax. + +## Context for every translation + +A model translates a string well only when it knows what the string means in your product. General Translation applies the [Context Groups](/docs/platform/dashboard/guides/defining-context-for-translations) you assign to a project to each new translation in it. A group holds a Glossary for terms that need consistent treatment, such as a product name that stays untranslated, and Custom Prompts for audience, formality, and style. You can assign one group to your app, website, and docs. + +For a single ambiguous string, pass the `context` prop to [``](/docs/react/reference/components/t), for example to say whether "cells" means spreadsheet cells or phones. Turn on the `includeSourceCodeContext` parsing flag in `gt.config.json` to add the surrounding lines of source code as context for each translation. + +## Delivery from your build or the CDN + +In production, General Translation translates [``](/docs/react/reference/components/t) content during the build, before users load the app, and a missing translation falls back to the source text. Your configuration sets where `gt-next` and `gt-react` load translations from. With a local `output` path in `gt.config.json` and a [`loadTranslations`](/docs/react/reference/functions/load-translations) function, translations [ship in your bundle](/docs/react/guides/storing-translations), and updating them takes a redeploy. With a `projectId` and no [`loadTranslations`](/docs/react/reference/functions/load-translations) function, they load from General Translation's CDN at run time, after you enable the CDN in your project settings and publish them with [`npx gt translate --publish`](/docs/cli/reference/commands/translate). -**3. Ship.** One command generates all translations at build time. They're pre-generated, cached, and delivered via CDN. [See the deploy guide →](/docs/react/nextjs-quickstart#11-deploy-to-production) +## Translations that keep up with releases -**4. Automate.** [Locadex](/docs/platform/locadex/quickstart) monitors your repo. When you push code, it scans for changes, internationalizes new content, generates translations, and opens a PR. No human in the loop unless you want one. If you do, the translation editor gives you side-by-side diffs with the ability to edit before or after content goes live. +Run [`npx gt translate`](/docs/cli/reference/commands/translate) in CI before your build command, and production ships with current translations. The CLI translates only content whose source has changed, and it can reuse a matching translation from an earlier version of the same file. At scale, General Translation is fast: Ramp translated 40,000 keys (millions of words) in a few minutes. -## Why most translation AI gets it wrong +To automate the code changes as well, connect GitHub. [Locadex](/docs/platform/locadex/quickstart), General Translation's AI agent, wraps your source code in i18n calls such as [``](/docs/react/reference/components/t), translates new content, and opens or updates a pull request. You choose when each Locadex automation runs: manually, when a pull request changes, or when a commit is pushed. **Auto-merge** is off by default; turn it on and Locadex merges its pull requests when checks pass, if branch protection allows it. Locadex supports Next.js, React apps (Vite, Gatsby, React Router, and others), and the docs frameworks Mintlify, Fern, and Docusaurus, and it requires a Starter or Enterprise plan. -Most localization AI translates strings one at a time, in isolation. "Apple" could be the fruit or the company. "Cell" could be biological or a spreadsheet. Without context, the AI guesses. +## Review by people who read the language -General Translation's AI sees your full codebase context: component hierarchy, variable names, surrounding UI, your product glossary. The output is idiomatic without manual cleanup. For edge cases, you can [add explicit context](/docs/react/reference/components/t#props) directly in the component. +AI translation has gotten very good, but a production app still needs someone who reads the language to check it. In General Translation's Dashboard, open **Project > Translations**, select the locales to compare side by side, and click a cell to edit it. Team invites require a Starter or Enterprise plan, and Starter includes unlimited users with no seat charges. If someone edits a downloaded translation file by hand, [`npx gt save-local`](/docs/cli/reference/commands/save-local) sends the edit back to the platform. -## Pricing that scales with usage, not headcount +## Customers and pricing -GT uses usage-based pricing. You pay for what you translate. No per-seat fees that balloon as your team grows. No sales call required. [See full pricing →](https://generaltranslation.com/pricing) +General Translation covers each requirement, from [``](/docs/react/reference/components/t) in your code to review in the Dashboard, and is trusted by the world's best developer teams, including at Cursor, Ramp, Profound, Cognition, Sierra, and ClickHouse. Each free Organization gets 5M platform credits over a rolling 30-day window, and the Starter plan has a $0 platform fee with unlimited users, projects, and languages. Start with the [CLI Quickstart](/docs/cli/quickstart). diff --git a/kb/how-to-handle-plurals-in-react.mdx b/kb/how-to-handle-plurals-in-react.mdx index 5c66c6cf3..2e7a78aa9 100644 --- a/kb/how-to-handle-plurals-in-react.mdx +++ b/kb/how-to-handle-plurals-in-react.mdx @@ -1,240 +1,38 @@ --- title: How do I handle plurals in React? -summary: Don't hard-code plural logic with checks like n === 1. A small helper is enough for English-only apps, but multilingual apps need locale-aware plural rules, which an i18n component such as from gt-react or gt-next handles for every language. +summary: Handle plurals in React by choosing each sentence with the plural rules of the user's language, since English has 2 forms and Arabic has 6. General Translation's component takes the count and your source forms, and npx gt translate adds the forms each target language needs. date: 2025-02-17 +updated: 2026-10-14 category: locale-formatting authors: [archie] redirectFrom: [plurals] related: [translate-conditional-jsx, i18n-without-translation-files] --- -## Why pluralization matters in React +Handling plurals in React means showing the sentence that agrees with a count, chosen by the plural rules of the user's language. JavaScript's built-in [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) maps a number to a Unicode CLDR (Common Locale Data & Rules) plural category, such as `one`, `few`, or `other`, but the forms differ by language: English has 2, Arabic has 6, and Japanese has 1. A `count === 1` check models only English, so an Arabic page gets one sentence for 2, 3, and 11, where Arabic uses three forms. Each target language needs its own sentence for every form it uses. -We often encounter apps that display awkward messages like: +| Approach | What it does well | What it leaves to you | +| --- | --- | --- | +| A `count === 1` check | No dependency, and correct for English | Languages with more forms, such as Arabic's `zero`, `two`, `few`, and `many` | +| An internationalization (i18n) library alone (`i18next`, `react-intl`) | Picks the form for each locale with CLDR plural rules | Writing every form of every message in a key file per language, including the forms English lacks | +| Google Translate | Fast, general-purpose translation of text | Writing a sentence for each form a language needs, and the code that picks one at render | +| A raw AI API (OpenAI API, Claude API) | Fluent translation that follows instructions, including a request for every form | Prompting for each language's forms, checking them against its CLDR categories, the code that picks one, review, and delivery | +| General Translation ([``](/docs/react/reference/components/plural) in `gt-react` and `gt-next`) | [`npx gt translate`](/docs/cli/reference/commands/translate) translates your source forms and adds the forms each target language needs; [``](/docs/react/reference/components/plural) picks one with CLDR rules | Writing your source language's forms, putting the count in [``](/docs/react/reference/components/plural) and [``](/docs/react/reference/components/num) inside [``](/docs/react/reference/components/t), a one-time setup, and rerunning [`npx gt translate`](/docs/cli/reference/commands/translate) when content changes | -```text -You have 1 new message(s) -``` - -This is a telltale sign of a developer who hasn't thought carefully about user experience. - -React apps often need to handle pluralization — for notification counts, list lengths, or search results. -**And it's not that hard to get pluralization right, especially if you only need your app in English.** -But there are plenty of bad practices new developers fall into, especially when building multilingual interfaces. - -This guide covers how to handle English plurals cleanly, format numbers for different locales, and build a fully multilingual plural system in React and Next.js. - -### The problem with hard-coded plurals - -Many projects — including surprisingly large and important ones — hard-code plural logic. - -```jsx -export default function Example({ n }) { - return ( -

- Displaying {n} item{n === 1 ? '' : 's'} -

- ) -} -``` - -But pluralization is often more complex than just adding an "s" to the end of a word. -Some nouns have irregular plural forms, like "child" and "children". -Sometimes, other parts of the sentence also need to change to reflect the noun, like -"is" and "are" depending on the count. +Use a `count === 1` check, or `Intl.PluralRules` with your own sentences, when the app ships only in English, since English has just `one` and `other`. Use an i18n library alone when your team already keeps key files and translators write every form by hand. Use General Translation when the app ships in several languages and changes often, so a new plural message gets its forms in every language with the release that adds it. -The table below illustrates some common scenarios: +General Translation handles plurals with the [``](/docs/react/reference/components/plural) component in `gt-react` and `gt-next` (also in the experimental `gt-tanstack-start` and `gt-react-native`). Pass the count as `n` and one prop per form your source language uses, such as `one` and `other`, then place [``](/docs/react/reference/components/plural) inside [``](/docs/react/reference/components/t) with the count in [``](/docs/react/reference/components/num). [``](/docs/react/reference/components/t) translates its contents as one unit, so [`npx gt translate`](/docs/cli/reference/commands/translate) translates the forms together. It also adds the forms each target language needs, such as Arabic's `zero`, `two`, `few`, and `many`. -| Scenario | Examples | Notes | -| -------------- | ----------------------------------------------------------- | ------------------------------------------------------------------- | -| Viewer count | "1 person is watching"
"2 people are watching" | Irregular noun ("person" → "people") and verb changes needed. | -| Item deletion | "Delete this message?"
"Delete these 2 messages?" | Demonstrative changes ("this" vs. "these") plus noun pluralization. | -| Search results | "No results"
"1 result found"
"2 results found" | Different phrasing for zero, one, and multiple results. | +```tsx +import { T, Plural, Num } from 'gt-react'; -Using conditional expressions quickly becomes unwieldy. - -And it becomes a nightmare when you need to ship your app in other languages. -What works for English often breaks completely in languages like Polish or Arabic, which have entirely different rules for handling quantities. -**Companies we work with often put off internationalization -because of the pain of refactoring hardcoded UI like this.** - ---- - -## How to handle plurals in English - -In English, using the right plurals in your app is usually straightforward. - -For simple noun pluralization, write a utility function: - -```jsx -export function pluralize( - count: number, - singular: string, - plural: string = singular + 's' -) { - return `${count === 1 ? singular : plural}`; -} + + You have {count} message.} + other={<>You have {count} messages.} + /> +; ``` -Now there is a single function for handling all your plural logic, -and it works for irregular plurals too: - -```js -pluralize(2, 'user') // "users" -pluralize(2, 'person', 'people') // "people" -pluralize(2, 'child', 'children') // "children" -``` - -But what if you need more complicated logic, like: - -```text -"No one is watching" -"1 person is watching" -"2 people are watching" -``` - -At this stage, you should think seriously about a low-maintenance internationalization ("i18n") library. - -Although developers often think that i18n libraries are only for multilingual interfaces, -they can be very useful for plural and variable formatting even in single-language applications. -Under the hood, most i18n libraries use JavaScript's built-in `Intl.PluralRules` API to determine the correct plural form for any language. - -There are plenty of React i18n libraries, including ours, [`gt-react`](/docs/react/overview) (or [`gt-next`](/docs/react/nextjs-quickstart) if you're using Next.js). -Displaying an English plural using gt-react is simple: - -```jsx -import { Plural } from 'gt-react' - -function Example({ count }) { - return ( - - {count} people are watching - - ) -} -``` - -UI is conditionally rendered based on the value of `n`. - -Most libraries use JavaScript's [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) API to decide which plural form to display. -This means that in English, you would use the name `"one"` to refer to a singular and `"other"` to refer to a plural. -Our [``](/docs/react/reference/components/plural) component checks the exact plural category first, then the generic `plural` and `other` props. It falls back to its children only when none of those props are available. - -Using a library here is best practice even for English-only applications, and makes future internationalization much easier. - ---- - -## Pluralization in multilingual React apps (i18n) - -If your app only serves English-speaking users, the approach above may be all you need — but most production apps eventually need to support multiple languages. That's where things get interesting. - -- In Arabic, nouns have different forms depending on whether there are zero, one, two, or many of them -- In locales such as `de-DE`, `es-ES`, and `it-IT`, large numbers use periods instead of commas, so 1,000,000 becomes 1.000.000 -- In Hindi, digits are grouped in pairs, so 1,000,000 would become 10,00,000 - -**For an internationalized app, you should use a dedicated i18n library** which will have its own documentation on how to handle plurals and number formatting. - -### Formatting numbers for different locales - -You can use the `Intl` object to [format numbers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) for any locale. -The easiest way to do this is with the built-in `toLocaleString()` method. - -By default, this will use the runtime's current locale: - -```javascript -const n = 1000000 -n.toLocaleString() // displays 1,000,000 when the runtime locale is "en-US" (American English) -n.toLocaleString('de') // 1.000.000 because the locale has been specified as "de" (German) -``` - -gt-react also offers a [``](/docs/react/reference/components/num) component which relies on `Intl.NumberFormat` under the hood. - -```jsx -import { Num } from 'gt-react' - -// displays 1,000,000 when the language is "en-US" -// displays 1.000.000 when the language is "de" -// displays 10,00,000 when the language is "hi" -export default function Example() { - return 1000000 -} -``` - -### Understanding plural forms across languages - -The six plural forms supported by JavaScript's `Intl.PluralRules` API are: `zero`, `one`, `two`, `few`, `many`, `other`. -Although English uses only `one` ("singular") and `other` ("plural"), -languages like Arabic and Polish have more than just these two forms. - -For example, an English-speaking user might expect: - -```text -"No one is watching" -"1 person is watching" -"2 people are watching" -``` - -Whereas an Arabic-speaking user might expect different expressions for singular, -dual (when the count is exactly two things), and small and large plural forms: - -```text -"لا أحد يشاهد" -"1 شخص يشاهد" -"2 شخصان يشاهدان" -"3 أشخاص يشاهدون" -"11 شخصاً يشاهدون" -``` - -This is where an internationalization library becomes essential. -Every language has its own logic for when and how to display plurals, -so it's better to rely on a dedicated library to get it right. - -A good i18n library will do two things: - -1. Decide which plural form (`one`, `many`, `other`, etc.) to use based on the locale -2. Locate the translation in the right language which corresponds to that form - -**If you already have an internationalization library, -check their docs for information on plural formatting.** -Almost all libraries have dedicated documentation on rendering plurals. - -### Full example: plurals in a multilingual React app - -If you don't already have an internationalization library, consider [`gt-react`](/docs/react/react-quickstart)! - -gt-react's [``](/docs/react/reference/components/plural) component: - -- Is a simple, declarative way to render plurals correctly in React -- Works natively with the [``](/docs/react/reference/components/num) formatting component -- Works natively with the [``](/docs/react/reference/components/t) translation component, which integrates with our [translation service](https://generaltranslation.com) to generate plural forms automatically - -Putting all the building blocks together, here's a complete multilingual component: - -```jsx -import { T, Plural, Num } from 'gt-react' - -// Works out of the box in 100+ languages -function Example({ count }) { - return ( - - - {count} person is watching - - } - > - {count} people are watching - - - ) -} -``` - ---- - -Set up pluralization with the [`gt-react` Quickstart](/docs/react/react-quickstart) for React apps or the [`gt-next` Quickstart](/docs/react/nextjs-quickstart) for Next.js apps. See the [`` API reference](/docs/react/reference/components/plural) for the full component API. - -Pluralization is one of the most common i18n challenges in React — getting it right from the start saves significant refactoring later. +At render, [``](/docs/react/reference/components/plural) picks a form with the active locale's [CLDR plural rules](https://cldr.unicode.org/index/cldr-spec/plural-rules), and [``](/docs/react/reference/components/num) formats the count for that locale without sending it to the General Translation API. [Handling plurals and branches](/docs/react/guides/handling-plurals-and-branches) has the full steps, and the [React overview](/docs/react/overview#frameworks) links each framework's Quickstart. diff --git a/kb/i18n-without-translation-files.mdx b/kb/i18n-without-translation-files.mdx index 94efc6202..9ead80da7 100644 --- a/kb/i18n-without-translation-files.mdx +++ b/kb/i18n-without-translation-files.mdx @@ -1,150 +1,75 @@ --- title: Can I do i18n without translation files? -summary: Yes. With gt-react or gt-next, content stays inline in your components inside a component, and translations are generated at build time as output, so there are no keys or per-locale JSON files to write and keep in sync. +summary: "Yes: keep source copy in code and generate translations instead of maintaining dictionaries by hand. General Translation combines inline JSX, code context, automated translation, and built-in review. Generated locale data still exists, but the CLI or Locadex can keep it current as your app changes." date: 2026-05-07 +updated: 2026-10-16 category: internationalization authors: [jackie, ernest] redirectFrom: [i18n-without-translation-files, nextjs-i18n-code-is-the-source-of-truth] -related: [translate-conditional-jsx, how-to-handle-plurals-in-react, best-localization-software] +related: [add-i18n-to-nextjs, ai-agent-i18n-setup, how-to-handle-plurals-in-react, translations-in-ci] --- -Everyone who's internationalized a JavaScript app knows the workflow. You install an i18n library, create an `en.json` file, pull every user-facing string out of your components, assign each one a key, and reference the key where the string used to be. Then you duplicate that JSON file for every language you support. `es.json`, `fr.json`, `ja.json`. +You can remove the work of inventing translation keys and updating source dictionaries while still generating files that contain translated text. The useful distinction is who maintains those files: a developer copying changes between catalogs, or a translation workflow connected to the source code. -At first, it's fine. Thirty strings, three languages, 90 entries. +General Translation's `gt-react` and `gt-next` keep source copy in JSX. Its CLI collects marked content, generates translations with context, and prepares the locale data for your build or the CDN. The same platform provides translation review and ongoing automation. -Then your app grows. Six months later you have 400 strings and 12 languages. 4,800 entries across a dozen files. A developer adds a new feature, writes five new strings, forgets to update three of the translation files. Nobody notices until a user in Tokyo sees English fallbacks in a Japanese interface. Someone suggests buying a translation management system. +## Choose which maintenance work to remove -