diff --git a/blog/en-US/ai-chatbot.mdx b/blog/en-US/ai-chatbot.mdx index 3e9ac2d87..f4919d642 100644 --- a/blog/en-US/ai-chatbot.mdx +++ b/blog/en-US/ai-chatbot.mdx @@ -91,7 +91,7 @@ export default withGTConfig(nextConfig, { I could've added more locales, but I just wanted to test the chatbot with a few different languages. Feel free to add as many locales as you want! -[Here's a list of all of the ones supported by gt-next](https://generaltranslation.com/docs/platform/supported-locales). +[Here's a list of all of the ones supported by gt-next](/docs/platform/dashboard/reference/supported-locales). ### How it works @@ -220,4 +220,4 @@ internationalized AI chatbot that was available in Spanish, French, and Chinese. If you're interested in the code, you can find it [here](https://github.com/General-Translation/ai-chatbot). -If you're interested in using General Translation, check out the [website](https://generaltranslation.com), [GitHub repo](https://github.com/General-Translation/gt-libraries), or [docs](https://generaltranslation.com/docs). +If you're interested in using General Translation, check out the [website](https://generaltranslation.com), [GitHub repo](https://github.com/General-Translation/gt-libraries), or [docs](/docs/overview/get-started). diff --git a/blog/en-US/best-localization-software.mdx b/blog/en-US/best-localization-software.mdx index a9424cb5f..3955d4179 100644 --- a/blog/en-US/best-localization-software.mdx +++ b/blog/en-US/best-localization-software.mdx @@ -24,9 +24,9 @@ The library knows nothing about your translations. The TMS knows nothing about y General Translation is not a library. It's not a TMS. It's the whole pipeline, used by developer-first teams at [Cursor](https://cursor.com), [Cognition](https://cognition.ai), [Windsurf](https://windsurf.com), [Mintlify](https://mintlify.com), and [ClickHouse](https://clickhouse.com). -- **Open-source developer libraries**: [`gt-next`](https://generaltranslation.com/docs/react/nextjs), [`gt-react`](https://generaltranslation.com/docs/react), and support for [React Native/Expo](https://generaltranslation.com/docs/react/react-native). Drop-in SDKs with full TypeScript support. +- **Open-source developer libraries**: [`gt-next`](/docs/react/nextjs), [`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](https://generaltranslation.com/docs/locadex) that scans your codebase, internationalizes your code, creates translations, and opens pull requests on every push. +- **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. @@ -58,7 +58,7 @@ At 10 languages and 500 keys, that's 5,000 entries to maintain. At 50 languages ## How General Translation closes the loop -**1. Install and write code.** Run the [setup wizard](https://generaltranslation.com/docs/next/quickstart) and wrap content in `` components. No key extraction. No JSON files. +**1. Install and write code.** Run the [setup wizard](/docs/react/nextjs-quickstart) and wrap content in `` components. No key extraction. No JSON files. ```tsx import { T } from 'gt-next'; @@ -75,15 +75,15 @@ export default function Home() { **2. Develop.** Translations appear on-demand. Switch languages and see results immediately. -**3. Ship.** One command generates all translations at build time. They're pre-generated, cached, and delivered via CDN. Sub-50ms globally. [See the deploy guide β†’](https://generaltranslation.com/docs/next/quickstart#deploy) +**3. Ship.** One command generates all translations at build time. They're pre-generated, cached, and delivered via CDN. Sub-50ms globally. [See the deploy guide β†’](/docs/react/nextjs-quickstart#11-deploy-to-production) -**4. Automate.** [Locadex](https://generaltranslation.com/docs/locadex) 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. +**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. ## Why most translation AI gets it wrong 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. -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](https://generaltranslation.com/docs/react/reference/components/t#props) directly in the component. +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. ## Pricing that scales with usage, not headcount diff --git a/blog/en-US/branch_vs_ternary.mdx b/blog/en-US/branch_vs_ternary.mdx index 25ef65dde..8331c6651 100644 --- a/blog/en-US/branch_vs_ternary.mdx +++ b/blog/en-US/branch_vs_ternary.mdx @@ -87,4 +87,4 @@ accordinglyβ€”something that is not easily possible while using ternary operator If you take anything away from this article, you should always be looking for ways to leverage context and flexibility in your code. Using the `` component is probably one of the easiest ways to do this. -Check out the [`` component](https://generaltranslation.com/docs/react/reference/components/branch) documentation for more details. +Check out the [`` component](/docs/react/reference/components/branch) documentation for more details. diff --git a/blog/en-US/gt-next.mdx b/blog/en-US/gt-next.mdx index 4f30479e2..67814883e 100644 --- a/blog/en-US/gt-next.mdx +++ b/blog/en-US/gt-next.mdx @@ -38,7 +38,7 @@ The goal with gt-next is to create an abundance mindset around translations. The - Give a ⭐ to [gt-next on GitHub](https://github.com/General-Translation/gt-next) - Get an API key πŸ” on our [platform](https://generaltranslation.com) -- Read the [docs](https://generaltranslation.com/docs) πŸ“„ +- Read the [docs](/docs/overview/get-started) πŸ“„ ### What you can do with gt-next diff --git a/blog/en-US/i18n-without-translation-files.mdx b/blog/en-US/i18n-without-translation-files.mdx index e1baad441..39591b46e 100644 --- a/blog/en-US/i18n-without-translation-files.mdx +++ b/blog/en-US/i18n-without-translation-files.mdx @@ -66,13 +66,13 @@ function CheckoutSummary({ itemCount, discount }) { } ``` -The `` component in [`gt-react`](https://generaltranslation.com/docs/react) marks a block of JSX for translation. The English stays in your component. When a user visits in Spanish, the content inside `` is replaced with its Spanish equivalent. Structure and formatting carry over. +The `` component in [`gt-react`](/docs/react/react-quickstart) marks a block of JSX for translation. The English stays in your component. When a user visits in Spanish, the content inside `` is replaced with its Spanish equivalent. Structure and formatting carry over. There's no `t('checkout.summary.title')`, no `en.json`, no per-locale JSON files to keep in sync. ## Translations as build output -They're generated at deploy time. The [GT CLI](https://generaltranslation.com/docs/cli/reference/commands/translate) scans your codebase for everything inside `` components and produces translations for every target language. The output goes into a gitignored directory, like compiled CSS or bundled JavaScript. +They're generated at deploy time. The [GT CLI](/docs/cli/reference/commands/translate) scans your codebase for everything inside `` components and produces translations for every target language. The output goes into a gitignored directory, like compiled CSS or bundled JavaScript. ```json title="gt.config.json" { @@ -118,6 +118,6 @@ But most developers are already thinking in one language when they build UI. The npx gt@latest init ``` -The setup wizard configures your project, installs dependencies, and sets up translation hot reloading for development. Full walkthrough in the [quickstart guide](https://generaltranslation.com/docs/react). +The setup wizard configures your project, installs dependencies, and sets up translation hot reloading for development. Full walkthrough in the [quickstart guide](/docs/react/react-quickstart). -`gt-react` is open source. For Next.js App Router, there's [`gt-next`](https://generaltranslation.com/docs/react/nextjs). For React Native, there's [`gt-react-native`](https://generaltranslation.com/docs/react/react-native). +`gt-react` is open source. For Next.js App Router, there's [`gt-next`](/docs/react/nextjs-quickstart). For React Native, there's [`gt-react-native`](/docs/react/react-native-quickstart). diff --git a/blog/en-US/multilingual-nextjs-seo.mdx b/blog/en-US/multilingual-nextjs-seo.mdx index 228b5f8be..6ba10dec7 100644 --- a/blog/en-US/multilingual-nextjs-seo.mdx +++ b/blog/en-US/multilingual-nextjs-seo.mdx @@ -22,7 +22,7 @@ A multilingual site without proper SEO setup has problems: - Incorrect language shown in search result snippets **The good news:** getting multilingual SEO right in Next.js isn't complicated. -There are six things you need to get right, and this guide covers all of them using [gt-next](https://generaltranslation.com/docs/react/nextjs). +There are six things you need to get right, and this guide covers all of them using [gt-next](/docs/react/nextjs). --- @@ -311,7 +311,7 @@ Here's a quick summary of everything covered: ## Next steps -- [gt-next quickstart](https://generaltranslation.com/docs/react/nextjs) to set up the full i18n stack +- [gt-next quickstart](/docs/react/nextjs-quickstart) to set up the full i18n stack - [Middleware guide](/docs/react/nextjs/app-router-middleware) for routing configuration -- [SSG guide](/docs/react/nextjs) for statically generating multilingual pages +- [SSG guide](/docs/react/nextjs/app-router-static-site-generation) for statically generating multilingual pages - [RTL support](/docs/react/guides/managing-locales) for right-to-left languages diff --git a/blog/en-US/nextjs-i18n-code-is-the-source-of-truth.mdx b/blog/en-US/nextjs-i18n-code-is-the-source-of-truth.mdx index d49026952..c8bd61ecb 100644 --- a/blog/en-US/nextjs-i18n-code-is-the-source-of-truth.mdx +++ b/blog/en-US/nextjs-i18n-code-is-the-source-of-truth.mdx @@ -32,21 +32,21 @@ function Hero() { } ``` -Wrap your JSX in [``](https://generaltranslation.com/docs/react/reference/components/t). The English text stays right where you wrote it. When a user visits in Spanish or Japanese, the content inside `` is translated β€” structure, formatting, and all. +Wrap your JSX in [``](/docs/react/reference/components/t). The English text stays right where you wrote it. When a user visits in Spanish or Japanese, the content inside `` is translated β€” structure, formatting, and all. No keys. No JSON files. No cross-referencing. The source of truth is your code. ## Setup -The syntax above comes from [gt-next](https://generaltranslation.com/docs/react/nextjs), an open-source i18n library for Next.js App Router. Getting started takes one command: +The syntax above comes from [gt-next](/docs/react/nextjs), an open-source i18n library for Next.js App Router. Getting started takes one command: ```bash copy npx gt@latest init ``` -The [setup wizard](https://generaltranslation.com/docs/cli/init) installs dependencies, wraps your Next.js config with [`withGTConfig`](https://generaltranslation.com/docs/next/api/config/with-gt-config), adds [`GTProvider`](https://generaltranslation.com/docs/react/reference/components/gt-provider) to your root layout, creates a [`gt.config.json`](https://generaltranslation.com/docs/cli/reference/config) with your locales, sets up dev API keys for translation hot reloading, and configures CDN translation storage β€” all interactively. +The [setup wizard](/docs/cli/reference/commands/init) installs dependencies, wraps your Next.js config with [`withGTConfig`](/docs/react/nextjs/config), adds [`GTProvider`](/docs/react/reference/components/gt-provider) to your root layout, creates a [`gt.config.json`](/docs/cli/reference/config) with your locales, sets up dev API keys for translation hot reloading, and configures CDN translation storage β€” all interactively. -Once that's done, wrap content in ``, run your dev server, and use the [``](https://generaltranslation.com/docs/react/reference/components/locale-selector) component to switch between languages: +Once that's done, wrap content in ``, run your dev server, and use the [``](/docs/react/reference/components/locale-selector) component to switch between languages: ```tsx import { LocaleSelector } from 'gt-next'; @@ -79,11 +79,11 @@ In production, translations are pre-generated. } ``` -The [`translate`](https://generaltranslation.com/docs/cli/reference/commands/translate) command scans your codebase for all `` usage, generates translations, and publishes them to a CDN. When your app builds, every locale is ready. +The [`translate`](/docs/cli/reference/commands/translate) command scans your codebase for all `` usage, generates translations, and publishes them to a CDN. When your app builds, every locale is ready. ## Next steps -- [Variable components](https://generaltranslation.com/docs/react/guides/format-variables) β€” handle dynamic content inside `` with [``](https://generaltranslation.com/docs/react/reference/components/var), [``](https://generaltranslation.com/docs/react/reference/components/num), and [``](https://generaltranslation.com/docs/react/reference/components/currency) -- [Branching components](https://generaltranslation.com/docs/react/guides/plurals-and-branches) β€” conditionally render content based on locale with [``](https://generaltranslation.com/docs/react/reference/components/plural) and [``](https://generaltranslation.com/docs/react/reference/components/branch) -- [`useGT`](https://generaltranslation.com/docs/react/reference/hooks/use-gt) and [`getGT`](https://generaltranslation.com/docs/react/reference/functions/get-gt) β€” translate plain strings for attributes, placeholders, and metadata -- [Standalone mode](https://generaltranslation.com/docs/react/guides/local-translations) β€” use gt-next without the General Translation platform +- [Variable components](/docs/react/guides/formatting-variables) β€” handle dynamic content inside `` with [``](/docs/react/reference/components/var), [``](/docs/react/reference/components/num), and [``](/docs/react/reference/components/currency) +- [Branching components](/docs/react/guides/handling-plurals-and-branches) β€” conditionally render content based on locale with [``](/docs/react/reference/components/plural) and [``](/docs/react/reference/components/branch) +- [`useGT`](/docs/react/reference/hooks/use-gt) and [`getGT`](/docs/react/nextjs/reference/functions/get-gt) β€” translate plain strings for attributes, placeholders, and metadata +- [Standalone mode](/docs/react/guides/storing-translations) β€” use gt-next without the General Translation platform diff --git a/blog/en-US/plurals.mdx b/blog/en-US/plurals.mdx index 9b2755213..1d4bd0fea 100644 --- a/blog/en-US/plurals.mdx +++ b/blog/en-US/plurals.mdx @@ -200,7 +200,7 @@ 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](https://generaltranslation.com/docs/react)! +If you don't already have an internationalization library, consider [gt-react](/docs/react/react-quickstart)! gt-react's `` component: @@ -239,8 +239,8 @@ function Example({ count }) { Ready to handle plurals properly in your React app? Check out our quickstart guides: -- [gt-react quickstart](https://generaltranslation.com/docs/react) for React apps -- [gt-next quickstart](https://generaltranslation.com/docs/react/nextjs) for Next.js apps +- [gt-react quickstart](/docs/react/react-quickstart) for React apps +- [gt-next quickstart](/docs/react/nextjs-quickstart) for Next.js apps - [`` 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. diff --git a/devlog/en-US/gt-react_v10_19_0.mdx b/devlog/en-US/gt-react_v10_19_0.mdx index 398a1267e..94e3f13db 100644 --- a/devlog/en-US/gt-react_v10_19_0.mdx +++ b/devlog/en-US/gt-react_v10_19_0.mdx @@ -43,7 +43,7 @@ export default defineConfig({ }); ``` -See the [gt-react setup docs](https://generaltranslation.com/docs/react/tutorials/quickstart) for other bundlers. +See the [React Quickstart](/docs/react/react-quickstart) for setup. ### 2. Enable dev hot reload in `gt.config.json` diff --git a/docs/en-US/cli/guides/generating-translations.mdx b/docs/en-US/cli/guides/generating-translations.mdx index da6102f0f..daa0f1e07 100644 --- a/docs/en-US/cli/guides/generating-translations.mdx +++ b/docs/en-US/cli/guides/generating-translations.mdx @@ -70,7 +70,7 @@ npx gt translate --dry-run ## Re-translate existing content [#retranslate] -By default, the CLI only translates content whose source has changed, and it preserves local edits. To change that behavior: +By default, the CLI only translates content whose source has changed, preserves local edits, and can reuse a matching translation from an earlier version of the same file β€” not only the most recent version. A segment is translated again when its source text changes. To change that behavior: - `--force` re-translates all content and overwrites existing translations. Local changes are lost and you are charged for the new translations. - `--force-download` re-downloads translations and overwrites local changes without re-translating. diff --git a/docs/en-US/cli/guides/using-auto-jsx.mdx b/docs/en-US/cli/guides/using-auto-jsx.mdx index 91f1d1b69..1499ea62a 100644 --- a/docs/en-US/cli/guides/using-auto-jsx.mdx +++ b/docs/en-US/cli/guides/using-auto-jsx.mdx @@ -15,7 +15,7 @@ Automatic JSX injection makes the compiler wrap translatable JSX text in [``] Automatic JSX injection is disabled by default. -*Note: Automatic JSX injection currently works only with the i18n-context system and single-page React apps.* +*Note: Automatic JSX injection works in React single-page apps and in Next.js Webpack builds. Next.js Turbopack and SWC builds do not support it.* ## Enable automatic JSX injection [#enable] @@ -33,12 +33,77 @@ Set `enableAutoJsxInjection` under `files.gt.parsingFlags` in `gt.config.json`. } ``` +## Configure the compiler [#compiler] + +Install `@generaltranslation/compiler` as a development dependency: + + + + + ```bash + npm install --save-dev @generaltranslation/compiler + ``` + + + + + ```bash + yarn add --dev @generaltranslation/compiler + ``` + + + + + ```bash + bun add --dev @generaltranslation/compiler + ``` + + + + + ```bash + pnpm add --save-dev @generaltranslation/compiler + ``` + + + + +Then connect the compiler to your framework: + + + + + Add the compiler plugin for your bundler. See [Developing SPA translations](/docs/react/guides/developing-spa-translations#setup) for Vite, webpack, Rollup, and esbuild setup. + + + + + Configure the Babel-based compiler in `next.config.ts`. Keep `enableAutoJsxInjection` in `gt.config.json` so CLI extraction and the build use the same setting. + + ```ts title="next.config.ts" + import { withGTConfig } from 'gt-next/config'; + + export default withGTConfig( + {}, + { + experimentalCompilerOptions: { + type: 'babel', + }, + } + ); + ``` + + This integration runs only with Webpack. If your Next.js version defaults to Turbopack, use `next dev --webpack` and `next build --webpack`. + + + + ## How it works [#how] Without injection, you wrap translatable text yourself. ```jsx -import { T } from 'gt-next'; +import { T } from 'gt-react'; // Use 'gt-next' in Next.js. function Welcome() { return ( diff --git a/docs/en-US/integrations/google-drive/guides/configuring-google-drive.mdx b/docs/en-US/integrations/google-drive/guides/configuring-google-drive.mdx new file mode 100644 index 000000000..aadfe4e6e --- /dev/null +++ b/docs/en-US/integrations/google-drive/guides/configuring-google-drive.mdx @@ -0,0 +1,57 @@ +--- + +title: Configuring Google Drive +description: "How to connect Google Drive to General Translation: this guide covers individual Google accounts and Organization shared-drive access." +related: + links: + - /docs/integrations/google-drive/guides/translating-content + - /docs/integrations/google-drive/guides/managing-translations + - /docs/integrations/google-drive/guides/using-translated-content + +--- + +Connect a Project to Google Drive with an individual Google account or an Organization-managed shared-drive connection. Both modes translate native Google Docs and Google Slides files from the Dashboard. + +## Before you start [#before-start] + +- Connecting a Project requires `project:write` permission and a plan that includes Project integrations. +- Adding files and running translations requires `translations:content:write` permission. +- Setting up Organization shared drives requires `org:manage` permission and a plan that includes shared-drive access. + +## Choose an access mode [#access-mode] + +Go to **Project > Integrations**, find **Google Drive**, and click **Connect**. + +When your Organization has a verified **Active** Google Shared Drives connection on a plan that includes Google shared drives, choose: + +- **Use the org shared drive connection** when the source files live in shared drives and access should not depend on an individual user. +- **Each user connects their own Google account** when users should select files from accounts they authorize themselves. + +The Dashboard skips this choice when the Organization does not have an active shared-drive connection and uses individual accounts. + +## Connect an individual account [#individual-account] + +After connecting the Project integration, open its management page and click **Connect account**. Complete Google authorization, then return to the Dashboard. + +The authorization grants the integration the Google Drive file scope. It lets General Translation work with files selected through the integration without granting unrestricted access to every file in the account. + +If authorization fails or does not return a refresh token, the management page displays a Google Drive authorization error. Connect the account again before adding or translating files. + +## Configure Organization shared drives [#shared-drives] + +An Organization admin sets up shared-drive access once: + +1. Go to **Organization > Settings > Integrations**. +2. Under **Google Shared Drives**, click **Set up shared drives**. +3. Copy the generated translation account email. +4. In Google Drive, add that account to each shared drive it should access with the **Content manager** role. +5. Return to the Dashboard and click **Verify access**. + +After the connection becomes **Active**, connect a Project's Google Drive integration and choose **Use the org shared drive connection**. The Project can then browse files from shared drives that include the translation account. + +## Disconnect access [#disconnect] + +- **Individual account:** click **Disconnect account** on the integration management page. Linked files remain associated with the integration but cannot be used until an account reconnects. +- **Organization shared drives:** click **Disconnect** under **Organization > Settings > Integrations**. Projects using that connection cannot browse, sync, or translate Drive files until shared-drive access is configured again. + +You cannot switch a Project from Organization access to individual-account access while it has linked files. Remove the linked files first. diff --git a/docs/en-US/integrations/google-drive/guides/managing-translations.mdx b/docs/en-US/integrations/google-drive/guides/managing-translations.mdx new file mode 100644 index 000000000..2ca2edd2b --- /dev/null +++ b/docs/en-US/integrations/google-drive/guides/managing-translations.mdx @@ -0,0 +1,46 @@ +--- + +title: Managing translations +description: "How to keep Google Drive translations current: this guide covers applying source changes, forcing retranslation, and managing linked files." +related: + links: + - /docs/integrations/google-drive/guides/translating-content + - /docs/integrations/google-drive/guides/using-translated-content + - /docs/integrations/google-drive/guides/configuring-google-drive + +--- + +After the first run, use **Apply changes** to update translated Drive copies while reusing translations that are still current. + +## Apply source changes [#apply-changes] + +When a source file changes: + +1. Open the Google Drive integration from **Project > Integrations**. +2. Select the changed file and its target locales. +3. Click **Apply changes**. + +General Translation reads the latest source, reuses existing translations where the source still matches, translates new or changed content, and updates each existing locale copy. + +## Force a full retranslation [#force] + +When a selected file already has translations, the Dashboard shows **Force retranslation**. Select it when you need to discard translation reuse and translate the file again from scratch. + +Click **Retranslate**, then confirm **Force retranslation**. The confirmation warns that this overwrites existing translations and incurs additional usage. + +Use this only when the existing translations should not be preserved. The setting clears after the forced run and whenever you change the selected files. + +## Remove linked files [#remove-files] + +Click the trash icon next to a linked file, then confirm **Remove**. + +Removing a file only unlinks it from the General Translation integration. It does not delete the source file or any translated copies from Google Drive. + +## Restore interrupted access [#restore-access] + +The translation action is disabled when Drive access is unavailable. + +- For an individual connection, reconnect a Google account from the integration management page. +- For an Organization connection, ask an Organization admin to restore the shared-drive connection under **Organization > Settings > Integrations**. + +After access is restored, the linked files are available again and you can rerun **Apply changes**. diff --git a/docs/en-US/integrations/google-drive/guides/meta.json b/docs/en-US/integrations/google-drive/guides/meta.json new file mode 100644 index 000000000..59e30738a --- /dev/null +++ b/docs/en-US/integrations/google-drive/guides/meta.json @@ -0,0 +1,10 @@ +{ + "title": "guides", + "description": "Connect Google Drive, translate files, manage updates, and use translated copies.", + "pages": [ + "./configuring-google-drive", + "./translating-content", + "./managing-translations", + "./using-translated-content" + ] +} diff --git a/docs/en-US/integrations/google-drive/guides/translating-content.mdx b/docs/en-US/integrations/google-drive/guides/translating-content.mdx new file mode 100644 index 000000000..1354fba52 --- /dev/null +++ b/docs/en-US/integrations/google-drive/guides/translating-content.mdx @@ -0,0 +1,73 @@ +--- + +title: Translating content +description: How to select Google Drive files and locales, start translations, and follow progress in the General Translation Dashboard. +related: + links: + - /docs/integrations/google-drive/guides/managing-translations + - /docs/integrations/google-drive/guides/using-translated-content + - /docs/integrations/google-drive/guides/configuring-google-drive + +--- + +Use the Google Drive integration management page to translate native Google Docs and Google Slides files. The Project's default locale is the source locale for every linked file. + +## Add files [#add-files] + +Open **Project > Integrations**, click **Manage** on the **Google Drive** card, then click **Add files**. + +### Individual Google account + +The Google Picker lets you select multiple native Google Docs and Google Slides files from **My Drive** and shared drives. If Google blocks the Picker from browsing Drive, follow the Dashboard prompt to allow the required browser access, then reopen it. + +### Organization shared drives + +The shared-drive browser lets you: + +1. Choose a shared drive. +2. Browse folders or search for files. +3. Select native Google Docs and Google Slides files. +4. Click **Add selected**. + +Folders are used for navigation and cannot be translated. Files in **My Drive** cannot be added through an Organization shared-drive connection. + +## Select files and locales [#select-content] + +All linked files are selected by default. Use the checkboxes to choose which files to translate. + +Under **Translate into**, select target locales. The menu: + +- Includes the Project's configured locales and lets you add other supported locales. +- Excludes the source locale. +- Initially selects every locale that any linked file has already been translated into, or all available locales when the integration has no translations. + +If you have not configured target locales on the Project, the locale menu opens automatically. + +## Start the run [#start-run] + +The primary action changes with the selected files and locales: + +| Button | When it appears | Result | +| --- | --- | --- | +| **Select locales** | No target locale is selected. | Opens the locale menu. | +| **Translate** | The selected files have no previous translations. | Starts the first translation run. | +| **Apply changes** | At least one selected file has previous translations. | Reuses existing translations and updates translated copies. | +| **Retranslate** | **Force retranslation** is selected. | Re-translates from scratch after confirmation. | + +Click the available action. General Translation starts one background job for each selected file and locale, then applies completed translations to Drive. + +The Dashboard confirms when translation starts. If only some jobs can be started, it reports the successful and failed counts so you can retry the failed selections. + +## Follow progress [#progress] + +Google Slides runs show progress for each target locale. The progress row moves through: + +- **Generating context** +- **Translating**, with a percentage when available +- **Applying translation** +- **Preparing to edit formatting** +- **Formatted X of Y slides**, with an estimated time when available +- **Cleaning up** +- **Complete!** + +When a Slides copy is ready, open it from the completed progress row. Google Docs translations also run in the background and update their translated copies, but they do not show the same slide-formatting progress. diff --git a/docs/en-US/integrations/google-drive/guides/using-translated-content.mdx b/docs/en-US/integrations/google-drive/guides/using-translated-content.mdx new file mode 100644 index 000000000..d00771585 --- /dev/null +++ b/docs/en-US/integrations/google-drive/guides/using-translated-content.mdx @@ -0,0 +1,48 @@ +--- + +title: Using translated content +description: How does General Translation create, name, and update translated Google Drive copies for each locale? +related: + links: + - /docs/integrations/google-drive/guides/translating-content + - /docs/integrations/google-drive/guides/managing-translations + - /docs/integrations/google-drive/guides/configuring-google-drive + +--- + +General Translation creates a separate Google Drive copy for each source file and target locale. You review, edit, share, and publish those copies with the normal Google Docs and Google Slides tools. + +## Copy names [#copy-names] + +Translated copies use the source name followed by the target locale in brackets: + +```txt +Source file name [locale] +``` + +For example: + +```txt +Launch deck [fr] +Launch deck [de] +``` + +The locale is the General Translation locale code selected in the Dashboard. + +General Translation creates each translated copy in the same Google Drive folder as the source file, using the source file's first parent folder. + +While a Google Slides copy is being formatted, its name temporarily uses `Source file name [locale, DRAFT]`. The name returns to `Source file name [locale]` when formatting finishes. + +## Updates to existing copies [#copy-updates] + +The first successful run for a file and locale creates the translated copy. Later **Apply changes** runs update that same copy instead of creating another one. + +This lets you keep a stable Drive file for each locale while the source evolves. General Translation reuses translations whose source still matches and applies translated changes to the existing copy. + +## Open and review copies [#review] + +For completed Google Slides runs, click the completed locale in the Dashboard progress view to open the translated presentation. You can also find Docs and Slides copies in Google Drive by their locale-suffixed names. + +Review each copy before sharing it. For Slides, General Translation applies the translated text and then runs the formatting stage shown in the Dashboard progress view. + +Edits made directly in a translated copy can be reused by later **Apply changes** runs. A forced retranslation intentionally replaces existing translations, so use it only when you want to start over. diff --git a/docs/en-US/integrations/google-drive/meta.json b/docs/en-US/integrations/google-drive/meta.json new file mode 100644 index 000000000..0bd79a40e --- /dev/null +++ b/docs/en-US/integrations/google-drive/meta.json @@ -0,0 +1,9 @@ +{ + "title": "Google Drive", + "description": "Translate native Google Docs and Google Slides files from the General Translation Dashboard.", + "pages": [ + "./quickstart", + "./guides", + "./reference" + ] +} diff --git a/docs/en-US/integrations/google-drive/quickstart.mdx b/docs/en-US/integrations/google-drive/quickstart.mdx new file mode 100644 index 000000000..ad8b99b92 --- /dev/null +++ b/docs/en-US/integrations/google-drive/quickstart.mdx @@ -0,0 +1,67 @@ +--- + +title: Quickstart +description: Connect Google Drive to General Translation and translate native Google Docs and Google Slides files from the Dashboard. +related: + links: + - /docs/integrations/google-drive/guides/translating-content + - /docs/integrations/google-drive/guides/managing-translations + - /docs/integrations/google-drive/guides/using-translated-content + - /docs/integrations/google-drive/guides/configuring-google-drive + +--- + +Use the Google Drive integration to translate native Google Docs and Google Slides files from the General Translation Dashboard. General Translation creates one translated Drive copy per target locale and updates that copy on later runs. + +## Before you start [#before-start] + +You need: + +- A General Translation [Project](/docs/platform/dashboard/get-started) on a plan that includes Project integrations. +- `project:write` permission to connect the integration. +- `translations:content:write` permission to add files and run translations. +- Native Google Docs or Google Slides files. Google Sheets and uploaded Microsoft Office files are not supported. + +## Quickstart [#quickstart] + +### 1. Connect Google Drive + +In the Dashboard, go to **Project > Integrations** (the **Integration Catalog** page), find **Google Drive**, and click **Connect**. + +If your Organization has a verified **Active** Google Shared Drives connection on a plan that includes Google shared drives, choose how the Project accesses Drive: + +- **Use the org shared drive connection** for files in shared drives. +- **Each user connects their own Google account** for files the individual user can access. + +If no Organization connection is available, the Project uses individual Google accounts. See [Configuring Google Drive](/docs/integrations/google-drive/guides/configuring-google-drive) for both connection modes. + +### 2. Authorize Drive access + +For an individual connection, click **Connect account** on the integration management page and complete Google authorization. + +For an Organization shared-drive connection, an Organization admin with `org:manage` permission must first set up and verify the translation account under **Organization > Settings > Integrations**. + +### 3. Add source files + +Click **Add files**. + +- Individual connections open the Google Picker, where you can select files from **My Drive** or shared drives. +- Organization connections open a shared-drive browser. Choose a shared drive, browse or search its folders, and select files. + +Only native Google Docs and Google Slides files can be selected. The Project's default locale is used as the source locale. + +### 4. Select locales and translate + +Linked files are selected by default. Under **Translate into**, choose one or more target locales, then click **Translate**. + +General Translation reads each selected file, starts translation in the background, and creates a translated copy for every file and locale. For Google Slides, the Dashboard also shows translation and formatting progress. + +### 5. Open the translated copies + +Translated copies use the name: + +```txt +Source file name [locale] +``` + +For example, translating `Launch deck` into `fr` creates `Launch deck [fr]`. For Google Slides, open the completed copy from the locale link in the progress row after it shows **Complete!**. For Google Docs, find the copy in Google Drive by its locale-suffixed name. diff --git a/docs/en-US/integrations/google-drive/reference/connection.mdx b/docs/en-US/integrations/google-drive/reference/connection.mdx new file mode 100644 index 000000000..68fa77195 --- /dev/null +++ b/docs/en-US/integrations/google-drive/reference/connection.mdx @@ -0,0 +1,65 @@ +--- + +title: Connection +description: Connect Google Drive to General Translation with individual or Organization-managed access. Reference for connection modes, permissions, and authorization. + +--- + +The Google Drive integration supports individual Google accounts and Organization-managed shared drives. The selected mode determines which files users can browse and which credentials General Translation uses. + +## Overview [#overview] + +| Topic | Description | +| --- | --- | +| [Access modes](#access-modes) | Choose individual-account or Organization shared-drive access. | +| [Individual authorization](#individual-authorization) | OAuth access for files selected by a user. | +| [Organization shared drives](#shared-drives) | Translation-account access managed by the Organization. | +| [Plan and permissions](#gating) | Requirements for connecting and running the integration. | +| [Disconnecting](#disconnecting) | What remains when credentials are removed. | + +## Access modes [#access-modes] + +| Mode | Credentials | Available files | +| --- | --- | --- | +| Individual account | Each user authorizes a Google account. | Native Docs and Slides available through that user's Picker. | +| Organization shared drives | The Organization provisions a translation account. | Native Docs and Slides in shared drives that include the translation account. | + +The Dashboard asks you to choose a mode only when the Organization has a verified **Active** Google Shared Drives connection and a plan that includes Google shared drives. Otherwise, the Project uses individual accounts. + +A Project cannot switch from Organization access to individual access while linked files remain. Remove those files before changing modes. + +## Individual authorization [#individual-authorization] + +Click **Connect account** on the Project integration management page to start OAuth authorization. + +The integration requests: + +- `openid` +- `https://www.googleapis.com/auth/drive.file` + +The Drive file scope allows General Translation to work with files selected through the integration. The connection is usable only after Google returns both that scope and a refresh token. + +## Organization shared drives [#shared-drives] + +Organization shared-drive access is configured under **Organization > Settings > Integrations**. + +Under **Google Shared Drives**, setup provisions a translation account. Add its email to every permitted shared drive with the **Content manager** role, then click **Verify access**. A Project can select Organization access only while this connection is **Active**. + +Files added in this mode must belong to a shared drive. Files in **My Drive** are rejected. + +## Plan and permissions [#gating] + +| Action | Permission | Plan feature | +| --- | --- | --- | +| Connect the Project integration | `project:write` | Project integrations | +| Add, translate, or remove files | `translations:content:write` | Project integrations | +| Configure Organization shared drives | `org:manage` | Google shared drives | + +Without the Project integration feature, the catalog shows an upgrade prompt instead of the connection controls. Without the required permission, the corresponding action is unavailable. + +## Disconnecting [#disconnecting] + +- **Disconnect account** removes an individual's stored Google credentials. Linked files remain associated with the Project but cannot be used until an account reconnects. +- **Disconnect** under the Organization integration removes the shared-drive translation credentials. Projects using that connection lose Drive access until it is configured again. + +Removing a linked file from the Project integration does not delete the source file or translated copies from Drive. diff --git a/docs/en-US/integrations/google-drive/reference/locales.mdx b/docs/en-US/integrations/google-drive/reference/locales.mdx new file mode 100644 index 000000000..bc420b4f5 --- /dev/null +++ b/docs/en-US/integrations/google-drive/reference/locales.mdx @@ -0,0 +1,33 @@ +--- + +title: Locales +description: Choose source and target locales for Google Drive translations in General Translation. Reference for Google Drive locale handling. + +--- + +The Google Drive integration uses the Project's default locale as the source and creates one translated Drive copy for each selected target locale. + +## Overview [#overview] + +| Setting | Description | Optional | Default | +| --- | --- | --- | --- | +| [Source locale](#source-locale) | Locale of every linked source file. | No | Project default locale | +| [Target locales](#target-locales) | Locales selected under **Translate into**. | No | Existing translated locales, or all available locales | + +## Source locale [#source-locale] + +**Type** `string` Β· **Required** Β· **Default** Project default locale + +The Project's default locale is assigned when a Drive file is linked. The Google Drive management page does not provide a per-file source-locale control. + +To use a different source locale, update the Project default before linking the file. + +## Target locales [#target-locales] + +**Type** `string[]` Β· **Required** + +The **Translate into** menu starts with the Project's configured locales and excludes each selected file's source locale. You can also add locales from the General Translation [supported locale list](/docs/platform/dashboard/reference/supported-locales). + +When any linked file already has translations, every locale used on the integration is selected initially, including locales for files that are not currently checked. When the integration has no translations, all available target locales are selected. + +At least one target locale is required. Without one, the primary action reads **Select locales** and opens the locale menu instead of starting translation. diff --git a/docs/en-US/integrations/google-drive/reference/meta.json b/docs/en-US/integrations/google-drive/reference/meta.json new file mode 100644 index 000000000..833c38784 --- /dev/null +++ b/docs/en-US/integrations/google-drive/reference/meta.json @@ -0,0 +1,9 @@ +{ + "title": "reference", + "description": "Browse reference pages for the General Translation Google Drive integration.", + "pages": [ + "./connection", + "./supported-content", + "./locales" + ] +} diff --git a/docs/en-US/integrations/google-drive/reference/supported-content.mdx b/docs/en-US/integrations/google-drive/reference/supported-content.mdx new file mode 100644 index 000000000..55c81cead --- /dev/null +++ b/docs/en-US/integrations/google-drive/reference/supported-content.mdx @@ -0,0 +1,58 @@ +--- + +title: Supported content +description: Translate native Google Docs and Google Slides content with General Translation. Reference for supported Drive file types and translatable regions. + +--- + +The Google Drive integration translates native Google Docs and Google Slides files. It extracts supported text regions, translates them, and applies the result to a locale-specific Drive copy. + +## Overview [#overview] + +| Topic | Description | +| --- | --- | +| [Supported files](#supported-files) | Native Google file types accepted by the integration. | +| [Google Docs content](#docs-content) | Document regions extracted for translation. | +| [Google Slides content](#slides-content) | Presentation regions extracted for translation. | +| [Skipped content](#skipped-content) | Content that is empty, structurally unsupported, or missing a text range. | + +## Supported files [#supported-files] + +| File type | Google MIME type | Supported | +| --- | --- | --- | +| Google Docs | `application/vnd.google-apps.document` | Yes | +| Google Slides | `application/vnd.google-apps.presentation` | Yes | +| Google Sheets | `application/vnd.google-apps.spreadsheet` | No | +| Uploaded Word or PowerPoint files | Microsoft Office MIME types | No | +| Folders and other Drive resources | Varies | No | + +The Picker and shared-drive browser only allow native Google Docs and Google Slides files. Backend validation rejects unsupported types even if a file ID is submitted directly. + +## Google Docs content [#docs-content] + +General Translation extracts text from: + +- Document paragraphs. +- Table cells. + +The translated content is merged into a Google Docs copy for the target locale. Non-text structures that cannot be represented safely are preserved or skipped instead of being sent for translation. + +## Google Slides content [#slides-content] + +General Translation extracts text from: + +- Text shapes. +- Table cells. +- Speaker notes. + +After translation is applied, Slides runs include a separate formatting stage. The Dashboard reports translation and formatting progress for each locale. + +## Skipped content [#skipped-content] + +Content is not translated when it is: + +- Empty. +- In an unsupported file type or structural element. +- In an unsupported document region. +- Missing the text range needed to apply a translation. +- Rich content that the integration cannot serialize safely. diff --git a/docs/en-US/integrations/index.mdx b/docs/en-US/integrations/index.mdx index f6e811643..a743d88a9 100644 --- a/docs/en-US/integrations/index.mdx +++ b/docs/en-US/integrations/index.mdx @@ -5,8 +5,9 @@ description: Use General Translation with third-party content platforms and plug --- -Connect General Translation to third-party content platforms so you can translate content where it already lives. Each integration is a plugin with its own Quickstart, Guides, and Reference. +Connect General Translation to third-party content platforms so you can translate content where it already lives. Each integration has its own Quickstart, Guides, and Reference. +- [Google Drive](/docs/integrations/google-drive/quickstart): Translate native Google Docs and Google Slides files from the General Translation Dashboard. - [Mintlify](/docs/integrations/mintlify/quickstart): Translate a Mintlify documentation site through GitHub with Locadex, the General Translation AI agent β€” no plugin to install. - [Sanity](/docs/integrations/sanity/quickstart): Translate Sanity documents from inside Sanity Studio with the `gt-sanity` plugin. - [Storyblok](/docs/integrations/storyblok/quickstart): Translate Storyblok stories from the General Translation Dashboard by connecting a space with credentials. diff --git a/docs/en-US/integrations/meta.json b/docs/en-US/integrations/meta.json index b3b093b60..7c27fa4e5 100644 --- a/docs/en-US/integrations/meta.json +++ b/docs/en-US/integrations/meta.json @@ -2,6 +2,6 @@ "title": "Integrations", "icon": "Plug", "root": true, - "description": "CMS, Docs Frameworks", - "pages": ["./index", "./mintlify", "./sanity", "./storyblok"] + "description": "Drive, CMS, docs frameworks", + "pages": ["./index", "./google-drive", "./mintlify", "./sanity", "./storyblok"] } diff --git a/docs/en-US/platform/locadex/guides/configuring-workflows.mdx b/docs/en-US/platform/locadex/guides/configuring-workflows.mdx index 443e4a54d..d14c6df87 100644 --- a/docs/en-US/platform/locadex/guides/configuring-workflows.mdx +++ b/docs/en-US/platform/locadex/guides/configuring-workflows.mdx @@ -26,6 +26,12 @@ In your Dashboard Project sidebar, open **Locadex > Configuration**. You can con - **Locales** for locale updates. - Set when Locadex should update files in your Project, if languages are added or removed. Use this workflow when changing source or target languages from the Agent page. +### Static checks during Codegen + +During **Codegen**, Locadex runs lint rules on edited files and feeds issues back to the agent. In files that already import General Translation, the `user-facing-object` rule warns when hardcoded text reaches the interface through an object or constant β€” for example, `{labels.save}` or a value destructured from a configuration object. + +Fix the warning by translating the string at its source with the appropriate API, such as `` for JSX content or `gt()` and `msg()` for strings stored in props and objects. + ## Configure your workflow [#configure-workflow] ### Edit trigger diff --git a/docs/en-US/react/(frameworks)/nextjs/config.mdx b/docs/en-US/react/(frameworks)/nextjs/config.mdx index 089654407..444375139 100644 --- a/docs/en-US/react/(frameworks)/nextjs/config.mdx +++ b/docs/en-US/react/(frameworks)/nextjs/config.mdx @@ -9,6 +9,8 @@ description: Configure General Translation in a Next.js app with the withGTConfi This page documents the plugin and its options. For the shared `gt.config.json` locale and file settings, see the [`gt-react` configuration reference](/docs/react/reference/config); for the CLI-side `files` schema, see the [CLI configuration reference](/docs/cli/reference/config). +*Note: `gt-next` supports Next.js 13.0.0 or later, excluding Next.js 15.2.1 and 15.2.2.* + ## Overview [#overview] Import `withGTConfig` from `gt-next/config` and wrap your Next.js config. Options can be passed as the second argument, but most projects keep locale settings in `gt.config.json` instead. @@ -226,17 +228,18 @@ Settings for the compiler plugin that analyzes your source at build time. Fields | `disableBuildChecks` | Disable build-time validation checks. | `boolean` | `false` | | `enableAutoJsxInjection` | Automatically wrap translatable JSX at build time. | `boolean` | `false` | -Set `enableAutoJsxInjection` here or under `files.gt.parsingFlags` in `gt.config.json`. Prefer `gt.config.json` to keep CLI extraction and compiler transforms in sync; see [Using automatic JSX injection](/docs/cli/guides/using-auto-jsx). In either case, configure `gt-next` to use the Babel-based webpack compiler: +Set `enableAutoJsxInjection` under `files.gt.parsingFlags` in `gt.config.json` to keep CLI extraction and compiler transforms in sync. Install `@generaltranslation/compiler`, then configure `gt-next` to use the Babel-based Webpack compiler: ```ts title="next.config.ts" export default withGTConfig(nextConfig, { experimentalCompilerOptions: { type: 'babel', - enableAutoJsxInjection: true, }, }); ``` +Automatic JSX injection does not run with Turbopack or the SWC compiler. If your Next.js version defaults to Turbopack, use `next dev --webpack` and `next build --webpack`. See [Using automatic JSX injection](/docs/cli/guides/using-auto-jsx) for the complete setup. + ### `headersAndCookies` [#headers-and-cookies] **Type** `object` Β· **Optional** diff --git a/docs/en-US/react/(frameworks)/nextjs/index.mdx b/docs/en-US/react/(frameworks)/nextjs/index.mdx index 27160e2b2..c626bf60b 100644 --- a/docs/en-US/react/(frameworks)/nextjs/index.mdx +++ b/docs/en-US/react/(frameworks)/nextjs/index.mdx @@ -9,6 +9,8 @@ description: Explore the Next.js-specific features of General Translation, inclu If you are just getting started, follow the [Next.js App Router Quickstart](/docs/react/nextjs-quickstart) or [Next.js Pages Router Quickstart](/docs/react/nextjs-pages-router-quickstart). The shared [Guides](/docs/react/guides/configuring) and [Reference](/docs/react/reference/config) cover everything that works the same across frameworks; the pages here cover the Next.js-only surface. +*Note: `gt-next` supports Next.js 13.0.0 or later, excluding Next.js 15.2.1 and 15.2.2.* + ## What is Next.js-specific [#overview] Most of `gt-next` is the shared React API. The Next.js-only pieces are: diff --git a/docs/en-US/react/(frameworks)/react-native/index.mdx b/docs/en-US/react/(frameworks)/react-native/index.mdx index 86dc5009b..da5ef7d0d 100644 --- a/docs/en-US/react/(frameworks)/react-native/index.mdx +++ b/docs/en-US/react/(frameworks)/react-native/index.mdx @@ -13,7 +13,7 @@ If you are just getting started, follow the [React Native Quickstart](/docs/reac ## What is React Native-specific [#overview] -- **Module-level setup.** You call [`initializeGT`](/docs/node/reference/functions/initialize-gt) once at your app's entry point, and [``](/docs/react/reference/components/gt-provider) loads translations internally rather than taking `locale` and `translations` props. See [Setup](/docs/react/react-native/setup). +- **Module-level setup.** You call [`initializeGT`](/docs/react/reference/config#initialize) once at your app's entry point, and [``](/docs/react/reference/components/gt-provider) loads translations internally rather than taking `locale` and `translations` props. See [Setup](/docs/react/react-native/setup). - **The polyfill plugin.** `gt-react-native/plugin` injects the `@formatjs` `Intl` polyfills that React Native's runtime does not include. See [Plugin](/docs/react/react-native/plugin). There is also no prebuilt [``](/docs/react/reference/components/locale-selector) component in React Native β€” build a language switcher with the [`useLocaleSelector`](/docs/react/reference/hooks/use-locale-selector) hook instead. diff --git a/docs/en-US/react/(frameworks)/react-native/setup.mdx b/docs/en-US/react/(frameworks)/react-native/setup.mdx index 2bf2b0e9d..40679b561 100644 --- a/docs/en-US/react/(frameworks)/react-native/setup.mdx +++ b/docs/en-US/react/(frameworks)/react-native/setup.mdx @@ -5,7 +5,7 @@ description: Initialize General Translation in a React Native app, add the provi --- -`gt-react-native` is set up at your app's entry point: you call [`initializeGT`](/docs/node/reference/functions/initialize-gt) once at the module level, then wrap your app in [``](/docs/react/reference/components/gt-provider). Unlike the web packages, the provider loads translations itself, so you do not pass it a `translations` prop and it resolves the `locale` from the device by default. +`gt-react-native` is set up at your app's entry point: you call [`initializeGT`](/docs/react/reference/config#initialize) once at the module level, then wrap your app in [``](/docs/react/reference/components/gt-provider). Unlike the web packages, the provider loads translations itself, so you do not pass it a `translations` prop and it resolves the `locale` from the device by default. This page covers the React Native-specific parts of setup. For the full step-by-step path including installation and the CLI, follow the [React Native Quickstart](/docs/react/react-native-quickstart). For the polyfill plugin that setup depends on, see [Plugin](/docs/react/react-native/plugin). diff --git a/docs/en-US/react/(frameworks)/tanstack-start/index.mdx b/docs/en-US/react/(frameworks)/tanstack-start/index.mdx index 89df52a6c..01004e970 100644 --- a/docs/en-US/react/(frameworks)/tanstack-start/index.mdx +++ b/docs/en-US/react/(frameworks)/tanstack-start/index.mdx @@ -13,7 +13,7 @@ If you are just getting started, follow the [TanStack Start Quickstart](/docs/re ## What is TanStack Start-specific [#overview] -- **Root-route setup.** You call [`initializeGT`](/docs/node/reference/functions/initialize-gt) at the module level, resolve the locale with `parseLocale`, load a translations snapshot in the route loader, and pass both to [``](/docs/react/reference/components/gt-provider). See [Setup](/docs/react/tanstack-start/setup). +- **Root-route setup.** You call [`initializeGT`](/docs/react/reference/config#initialize) at the module level, resolve the locale with `parseLocale`, load a translations snapshot in the route loader, and pass both to [``](/docs/react/reference/components/gt-provider). See [Setup](/docs/react/tanstack-start/setup). - **`parseLocale`.** A helper that reads the locale from the request cookie and `Accept-Language` header on the server, and from the cookie in the browser. It is the one export unique to `gt-tanstack-start`; everything else comes from `gt-react`. ## Pages [#pages] diff --git a/docs/en-US/react/(frameworks)/tanstack-start/setup.mdx b/docs/en-US/react/(frameworks)/tanstack-start/setup.mdx index 713b66013..e3774c85f 100644 --- a/docs/en-US/react/(frameworks)/tanstack-start/setup.mdx +++ b/docs/en-US/react/(frameworks)/tanstack-start/setup.mdx @@ -5,7 +5,7 @@ description: Initialize General Translation in a TanStack Start app, resolve the --- -`gt-tanstack-start` is set up entirely in the root route. You call [`initializeGT`](/docs/node/reference/functions/initialize-gt) at the module level, resolve the request locale with `parseLocale`, load a translations snapshot in the route loader, and pass both to [``](/docs/react/reference/components/gt-provider). Because TanStack Start renders on the server, the provider needs the locale and translations up front, so this pattern hydrates them from the loader. +`gt-tanstack-start` is set up entirely in the root route. You call [`initializeGT`](/docs/react/reference/config#initialize) at the module level, resolve the request locale with `parseLocale`, load a translations snapshot in the route loader, and pass both to [``](/docs/react/reference/components/gt-provider). Because TanStack Start renders on the server, the provider needs the locale and translations up front, so this pattern hydrates them from the loader. This page covers the TanStack Start-specific setup. For the full path including installation and the CLI, follow the [TanStack Start Quickstart](/docs/react/tanstack-start-quickstart). diff --git a/docs/en-US/react/nextjs-pages-router-quickstart.mdx b/docs/en-US/react/nextjs-pages-router-quickstart.mdx index b8881c9b1..4340e770f 100644 --- a/docs/en-US/react/nextjs-pages-router-quickstart.mdx +++ b/docs/en-US/react/nextjs-pages-router-quickstart.mdx @@ -18,7 +18,7 @@ In the Pages Router, `gt-next` works through `getServerSideProps`: on each reque The `gt-next/server` entry is App Router-only and does not work with the Pages Router. **Prerequisites:** -- A Next.js app using the **Pages Router** +- A Next.js app using the **Pages Router** (Next.js 13.0.0 or later, excluding 15.2.1 and 15.2.2) - Node.js 18+ diff --git a/docs/en-US/react/nextjs-quickstart.mdx b/docs/en-US/react/nextjs-quickstart.mdx index 623530656..4fe95cf90 100644 --- a/docs/en-US/react/nextjs-quickstart.mdx +++ b/docs/en-US/react/nextjs-quickstart.mdx @@ -14,7 +14,7 @@ related: By the end of this guide, your Next.js app will display content in multiple languages, with a language switcher your users can interact with. **Prerequisites:** -- A Next.js app using the **App Router** (Next.js 13+) +- A Next.js app using the **App Router** (Next.js 13.0.0 or later, excluding 15.2.1 and 15.2.2) - Node.js 18+ diff --git a/docs/en-US/react/react-native-quickstart.mdx b/docs/en-US/react/react-native-quickstart.mdx index 464d6b02f..791e93f74 100644 --- a/docs/en-US/react/react-native-quickstart.mdx +++ b/docs/en-US/react/react-native-quickstart.mdx @@ -147,7 +147,7 @@ The CLI generates these files when you run `npx gt translate`. ### 5. Initialize General Translation and add the provider -Call [`initializeGT`](/docs/node/reference/functions/initialize-gt) once at your app's entry point, before rendering, then wrap your app in `GTProvider`. Unlike the web packages, `GTProvider` loads translations internally, so you do not pass a `translations` prop and normally do not need to pass `locale` either β€” it is auto-detected. An optional `locale` prop is still accepted if you need to override detection. +Call [`initializeGT`](/docs/react/reference/config#initialize) once at your app's entry point, before rendering, then wrap your app in `GTProvider`. Unlike the web packages, `GTProvider` loads translations internally, so you do not pass a `translations` prop and normally do not need to pass `locale` either β€” it is auto-detected. An optional `locale` prop is still accepted if you need to override detection. diff --git a/docs/en-US/react/reference/components/t.mdx b/docs/en-US/react/reference/components/t.mdx index 4bf4f52c7..443688036 100644 --- a/docs/en-US/react/reference/components/t.mdx +++ b/docs/en-US/react/reference/components/t.mdx @@ -22,7 +22,7 @@ Wrap any static JSX in `` and it is translated into the active locale. Use va ``` -*Note: `` must be rendered inside a [``](/docs/react/reference/components/gt-provider) so it can access translations. For standalone strings, use [`useGT`](/docs/react/reference/hooks/use-gt) instead.* +*Note: Provider-based `gt-react`, TanStack Start, and React Native setups render `` under a [``](/docs/react/reference/components/gt-provider). React SPAs initialized with [`initializeGTSPA`](/docs/react/reference/config#initialize-spa) use a global translation cache and do not need a provider. In `gt-next`, `` works without a provider in synchronous server components, while client components still need the provider in the root layout. For standalone strings, use [`useGT`](/docs/react/reference/hooks/use-gt) instead.* ## How it works [#how-it-works] @@ -148,5 +148,5 @@ export default function Example() { ## Notes [#notes] - `` is for translating content. Use it for plain text or JSX structures, including variables and pluralization. -- It must be wrapped in a [``](/docs/react/reference/components/gt-provider) to access the translation context. +- Provider-based setups render `` under [``](/docs/react/reference/components/gt-provider). React SPAs and `gt-next` synchronous server components do not require one, but `gt-next` client components do. - For translating standalone strings such as placeholders and labels, use [`useGT`](/docs/react/reference/hooks/use-gt). diff --git a/docs/en-US/react/tanstack-start-quickstart.mdx b/docs/en-US/react/tanstack-start-quickstart.mdx index bcb1a5dfe..4ccccc114 100644 --- a/docs/en-US/react/tanstack-start-quickstart.mdx +++ b/docs/en-US/react/tanstack-start-quickstart.mdx @@ -86,7 +86,7 @@ export default async function loadTranslations(locale: string) { ### 4. Set up the root route -In `src/routes/__root.tsx`, call [`initializeGT`](/docs/node/reference/functions/initialize-gt) at the module level, resolve the locale with `parseLocale`, and load a translations snapshot in the route loader. Pass the `locale` and `translations` to `GTProvider`. +In `src/routes/__root.tsx`, call [`initializeGT`](/docs/react/reference/config#initialize) at the module level, resolve the locale with `parseLocale`, and load a translations snapshot in the route loader. Pass the `locale` and `translations` to `GTProvider`. ```tsx title="src/routes/__root.tsx" import { diff --git a/scripts/test-validate-links.ts b/scripts/test-validate-links.ts index 02d334a58..2a18d14c9 100644 --- a/scripts/test-validate-links.ts +++ b/scripts/test-validate-links.ts @@ -9,6 +9,7 @@ import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs'; import { join } from 'path'; +import { normalizeInternalLink } from './validate-links.ts'; // ─── Test Harness ─────────────────────────────────────────────────────────── @@ -323,15 +324,33 @@ description: A test 'Strips fr' ); - // Test 6: Integration test against fixtures - console.log('\nπŸ“‹ Test: Integration β€” fixture validation'); + // Test 6: Same-origin absolute link normalization + console.log('\nπŸ“‹ Test: Same-origin absolute links'); + assertEqual( + normalizeInternalLink( + 'https://generaltranslation.com/docs/next/introduction#install' + ), + '/docs/next/introduction#install', + 'Normalizes a same-origin docs URL' + ); + assertEqual( + normalizeInternalLink( + 'https://generaltranslation.com/docs/next/introduction?source=blog#install' + ), + '/docs/next/introduction#install', + 'Removes a query string and preserves the anchor' + ); + assertEqual( + normalizeInternalLink('https://example.com/docs/next/introduction'), + null, + 'Ignores external docs URLs' + ); + + // Test 7: Fixture setup + console.log('\nπŸ“‹ Test: Fixture setup'); setupTestFixtures(); try { - // We can't easily run the validator against a custom root without refactoring, - // so we test the key behaviors verified above and trust the integration via - // the real run against the content repo. - // Verify fixture files exist assert( existsSync(join(TEST_DIR, 'docs', 'en-US', 'next', 'introduction.mdx')), @@ -349,7 +368,7 @@ description: A test ); console.log( - '\n ℹ️ Full integration test runs via: npx tsx validate-links.ts' + '\n ℹ️ Full repository validation runs via: npx tsx validate-links.ts' ); } finally { cleanupTestFixtures(); diff --git a/scripts/validate-links.ts b/scripts/validate-links.ts index eeeb08cc8..d3fabf5b4 100644 --- a/scripts/validate-links.ts +++ b/scripts/validate-links.ts @@ -3,7 +3,7 @@ * * CI script that validates all internal links in MDX content files. * Parses MDX into an AST, extracts links and headings, then checks: - * 1. Internal links (starting with /) resolve to actual files + * 1. Root-relative and same-origin absolute links resolve to actual files * 2. Anchor fragments (#heading) exist in the target file * 3. Same-page anchors (#heading) exist in the current file * 4. Template placeholder links expand correctly for all target libraries @@ -15,7 +15,8 @@ */ import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join, relative, extname, dirname, basename } from 'path'; +import { join, relative, extname, dirname, basename, resolve } from 'path'; +import { fileURLToPath } from 'url'; import { fromMarkdown } from 'mdast-util-from-markdown'; import { mdxFromMarkdown } from 'mdast-util-mdx'; import { mdxjs } from 'micromark-extension-mdxjs'; @@ -62,6 +63,7 @@ const TEMPLATE_TARGETS: Record< }; const VERBOSE = process.argv.includes('--verbose'); +const CONTENT_ORIGIN = 'https://generaltranslation.com'; // ─── Types ────────────────────────────────────────────────────────────────── @@ -230,6 +232,33 @@ function buildFileIndex(): void { // ─── Link Extraction & Validation ─────────────────────────────────────────── +/** + * Normalize root-relative and same-origin links for internal validation. + * Query strings do not affect file or anchor resolution. + */ +export function normalizeInternalLink(href: string): string | null { + let normalized = href; + if ( + href === CONTENT_ORIGIN || + href.startsWith(`${CONTENT_ORIGIN}/`) + ) { + normalized = href.slice(CONTENT_ORIGIN.length); + } + + if (!normalized.startsWith('/') && !normalized.startsWith('#')) { + return null; + } + + const hashIndex = normalized.indexOf('#'); + const fragment = hashIndex >= 0 ? normalized.slice(hashIndex) : ''; + const pathAndQuery = + hashIndex >= 0 ? normalized.slice(0, hashIndex) : normalized; + const queryIndex = pathAndQuery.indexOf('?'); + const path = queryIndex >= 0 ? pathAndQuery.slice(0, queryIndex) : pathAndQuery; + + return `${path}${fragment}`; +} + /** * Extract all internal links from an MDX file. * Returns an array of { link, line, column } objects. @@ -259,8 +288,9 @@ function extractLinks( let match; while ((match = linkRegex.exec(lines[i])) !== null) { const href = match[1]; - if (href.startsWith('/') || href.startsWith('#')) { - links.push({ link: href, line: i + 1, column: match.index + 1 }); + const link = normalizeInternalLink(href); + if (link) { + links.push({ link, line: i + 1, column: match.index + 1 }); } } } @@ -270,9 +300,10 @@ function extractLinks( // Walk AST for markdown links: [text](url) visit(tree, 'link', (node: any) => { const href: string = node.url || ''; - if (href.startsWith('/') || href.startsWith('#')) { + const link = normalizeInternalLink(href); + if (link) { links.push({ - link: href, + link, line: node.position?.start?.line ?? 0, column: node.position?.start?.column ?? 0, }); @@ -287,13 +318,14 @@ function extractLinks( let match; while ((match = jsxHrefRegex.exec(lines[i])) !== null) { const href = match[1]; - if (href.startsWith('/') || href.startsWith('#')) { + const link = normalizeInternalLink(href); + if (link) { // Avoid duplicates with AST-extracted links on same line const alreadyFound = links.some( - (l) => l.line === i + 1 && l.link === href + (l) => l.line === i + 1 && l.link === link ); if (!alreadyFound) { - links.push({ link: href, line: i + 1, column: match.index + 1 }); + links.push({ link, line: i + 1, column: match.index + 1 }); } } } @@ -550,4 +582,9 @@ function main(): void { } } -main(); +if ( + process.argv[1] && + resolve(process.argv[1]) === fileURLToPath(import.meta.url) +) { + main(); +}