# Configuration Better i18n CLI automatically detects your project context from `i18n.config.ts`. This file is the source of truth for your translation workflow. ## Basic Configuration For simple projects, you only need to export the project slug and default locale. ```ts title="i18n.config.ts" export const project = "your-org/your-project"; export const defaultLocale = "en"; ``` ## Workspace Configuration For full control over scanning and linting behavior, use the `i18nWorkspaceConfig` export. ```ts title="i18n.config.ts" export const project = "your-org/your-project"; export const defaultLocale = "en"; export const i18nWorkspaceConfig = { project, defaultLocale, lint: { // Glob patterns for files to scan include: ["src/**/*.tsx", "app/**/*.tsx"], // Files to explicitly ignore (merges with defaults) exclude: [ "**/skeletons.tsx", // UI skeletons "**/*.stories.tsx", // Storybook "**/*.test.tsx", // Tests "**/components/ui/**", // UI library components (e.g., shadcn) ], // Rule configuration rules: { "jsx-text": "warning", // Show as warning "jsx-attribute": "warning", "ternary-locale": "error", // Block CI if detected }, }, }; ``` ## Lint Options | Option | Type | Description | | -------------- | ---------- | --------------------------------------------------------------------------- | | `lint.include` | `string[]` | Files to scan. Default: `["src", "app", "components", "pages"]` | | `lint.exclude` | `string[]` | Files to ignore. These are merged with system defaults like `node_modules`. | | `lint.rules` | `object` | Customize the severity of detection rules. | ## Rule Severities You can set each rule to one of three levels: * **`error`**: Reports as an error and causes `better-i18n scan --ci` to fail with exit code 1. * **`warning`**: Reports as a warning but does not fail the CI (unless `--ci` is combined with specific flags). * **`off`**: Disables the rule entirely. ## Default Exclusions The CLI automatically ignores these directories to ensure high performance and fewer false positives: * `node_modules/**` * `.next/**` (Next.js build artifacts) * `dist/**` / `build/**` (Production bundles) * `.git/**` * `public/**` (Static assets) # Introduction Better i18n CLI helps you manage the entire lifecycle of your translation keys, from detecting hardcoded strings to auditing remote sync status. ## Core Capabilities * **`scan`**: Find hardcoded strings that need translation. * **`sync`**: Compare your local `t()` calls with Better i18n cloud (Remote) and detect missing or unused keys. ## Why use the CLI? Managing i18n manually is error-prone. The CLI provides a "Senior Tooling" experience to ensure your translations are always consistent and fully covered. ```tsx // ❌ Detected by 'scan'

Welcome to our app

// ✅ Analyzed by 'sync'

{t('welcome')}

// Linked to 'home.welcome' namespace ``` ## Installation ```bash # With npx (no install needed) npx @better-i18n/cli scan # Or install globally npm install -g @better-i18n/cli ``` ## Workflow 1. **Scan**: Run `better-i18n scan` to find untranslated text. 2. **Translate**: Wrap text with `t()` calls using `@better-i18n/next`. 3. **Sync**: Run `better-i18n sync` to verify your local keys exist in Better i18n cloud. ## Features * ✅ **Lexical Scope Tracking** - Smart namespace detection for both `useTranslations` and `getTranslations`. * ✅ **Server Component Support** - Full support for Next.js App Router async server functions. * ✅ **Compact Tree Output** - Human-readable grouping of missing/unused keys. * ✅ **Senior Audit Log** - Deep transparency with `--verbose`. * ✅ **CI/CD Ready** - Enforce 100% key coverage in your pipeline. * ✅ **Smart Filtering** - Automatically ignores CSS, URLs, and constants. **Cmd+Click** on any file path in the terminal to jump directly to the code in VS Code! # scan Scan your codebase for hardcoded strings that need translation. Better i18n CLI uses a robust AST parser to differentiate between UI text and developer symbols. ## Usage ```bash better-i18n scan # Scan current directory better-i18n scan --dir ./src # Scan specific directory better-i18n scan --format json # JSON output for tooling better-i18n scan --ci # Exit code 1 if issues found better-i18n scan --staged # Only staged files better-i18n scan --verbose # Detailed output with scan stats ``` ## Options | Option | Description | | ----------------- | ---------------------------------------------------------- | | `--dir ` | Directory to scan | | `--format ` | `eslint` (default) or `json` | | `--ci` | Exit with code 1 if issues found. Useful for blocking PRs. | | `--staged` | Only scan git staged files. Perfect for pre-commit hooks. | | `--verbose` | Shows detailed output and a **Scan Audit** summary. | ## Example Output ```text ✓ Project: better-i18n/landing ✓ Found 246 files components/sign-up.tsx (3) 24:13 missing "Create an account" i18n/jsx-text 32:22 missing "Name" i18n/jsx-text 40:22 missing "Email" i18n/jsx-text ✖ 87 problems (87 missing translations) Scanned 246 files in 0.85s ``` ### Scan Details (with --verbose) When running with `--verbose`, the CLI provides a breakdown of its discovery process: ```text 🔍 Scan Details: - Root-scoped translators: 4 - Unbound translators: 0 - Dynamic namespaces skipped: 12 - Dynamic keys skipped: 5 ``` ## Detection Rules | Rule | Catches | Example | | ----------------- | -------------------- | --------------------------------- | | `jsx-text` | Hardcoded JSX text | `

Hello

` | | `jsx-attribute` | Hardcoded attributes | `Logo` | | `toast-message` | Toast notifications | `toast.error("Failed")` | | `ternary-locale` | Locale-based logic | `locale === 'en' ? 'Hi' : 'Hola'` | | `string-variable` | String variables | `const x = "Hello"` | ## Ignored Patterns The CLI is smart enough to ignore common developer symbols and technical strings: * **HTML entities**: `"`, `&`, `'` * **Tailwind/CSS classes**: `className="flex items-center bg-blue-500"` * **URLs & Paths**: `href="https://..."`, `src="/images/..."` * **Technical strings**: `SCREAMING_CASE`, variables, and numbers. ## CI/CD Integration ### GitHub Actions Enforce zero hardcoded strings in your main branch: ```yaml name: i18n Check on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npx @better-i18n/cli scan --ci ``` ### Pre-commit Hook Catch issues before they are even committed: ```bash # Using husky npx husky init echo "npx @better-i18n/cli scan --staged --ci" > .husky/pre-commit ``` # sync Compare your codebase's `t()` calls with translations stored in Better i18n (remote) and audit your project for consistency. ## When to use sync The `sync` command is a powerful auditing tool. Common scenarios include: * **Before opening a PR**: Ensure all new translation keys are present in Better i18n. * **After adding new pages**: Automatically identify and log missing keys. * **After refactors**: Detect "dead" keys that are no longer referenced in code. * **Before shipping a new locale**: Verify that the source keys are stable. * **Debugging**: Use `--verbose` to trace why certain keys are not being picked up. * **CI Gating**: Use `--format json` to fail builds if missing keys are detected. *** ## Workflow 1. **Run `sync`**: See the tree of missing or unused keys. 2. **Dashboard/AI**: Add the missing keys via the Better i18n dashboard or AI suggestions. 3. **Verify**: Run `sync --summary` to confirm `missingCount` is 0. 4. **Enforce**: Integrate into CI to prevent missing keys from reaching production. *** ## Usage ```bash better-i18n sync # Grouped tree output (default) better-i18n sync --summary # High-level metrics only better-i18n sync --verbose # Deep audit & verification better-i18n sync --format json # JSON output for automation better-i18n sync -d ./src # Scan specific directory ``` ## Options | Option | Description | | ------------------ | -------------------------------------------------------------------------------------------------------------- | | `--format ` | `eslint` (default) for humans, `json` for machines. | | `--verbose` | Detailed audit log: invariant checks (PASS/FAIL), scoping summary, dynamic key skips, and specific key probes. | | `--summary` | Show only top-level percentage coverage and counts without the detailed tree. | | `-d, --dir ` | Specify the directory to scan (default: current directory). | *** ## Output Example The default output provides a 2-level compact tree of mismatches. ```text 📊 Translation Keys Comparison Source locale: en Coverage: Local → Remote: 59% Remote Used: 63% ⊕ Missing in Remote (473 keys) Keys used in code but not uploaded to Better i18n pages (300) affordableEnglishLearning (meta.title, meta.description, meta.keywords, hero.badge, ...+12) bestApps (hero.badge, title_prefix, title_accent, subtitle) hero (5) hero (ariaLabel, imageAlt, ...) ⊖ Unused in Code (386 keys) Keys in Better i18n but not detected in code usage features (25) practiceSpeaking (title, subtitle, icon) Scanned 246 files in 0.85s ✓ Comparison complete ``` *** ## How namespace binding works The CLI uses **Lexical Scope Tracking** to resolve namespaces automatically for both client and server components. ### Client Components (React Hooks) ```tsx // All t() calls inside this scope become 'hero.key' const t = useTranslations('hero'); return

{t('title')}

; // Detected as: hero.title ``` ### Server Components (Async Functions) ```tsx // ✅ Direct string namespace const t = await getTranslations('welcome'); return

{t('title')}

; // Detected as: welcome.title // ✅ Object with namespace property const t = await getTranslations({ locale: params.locale, namespace: 'maintenance' }); return

{t('message')}

; // Detected as: maintenance.message // ⚠️ Root scoped (no namespace) const t = await getTranslations(); return

{t('global.title')}

; // Detected as: global.title (root scope) ``` ### Supported Patterns * **`useTranslations('namespace')`** - Client component with namespace * **`getTranslations('namespace')`** - Server component with namespace * **`getTranslations({ locale, namespace: 'namespace' })`** - Server with locale * **`useTranslations()` / `getTranslations()`** - Root scoped (no namespace prefix) * **Standard Methods**: All patterns support `t()`, `t.raw()`, `t.rich()`, and `t.has()`. ### Dynamic Namespaces If a namespace is a variable or template literal (e.g., ``useTranslations(`pages.${slug}`)``), it is reported as **unknown-scoped** in `--verbose` mode and skipped from metrics to prevent false positives. *** ## Flattening rules To ensure CLI metrics match the Better i18n UI: 1. **Primitives are leaves**: Strings, numbers, and booleans are counted as keys. 2. **Arrays are leaves**: `meta.keywords: ["i18n", "cli"]` is counted as **one key**, not two. This matches the UI's "Base Key" counting. 3. **Objects are containers**: Keys like `pages.home.hero` representing a grouping of sub-keys are ignored in the final key count. *** ## JSON Output Use `--format json` for CI scripts and automation. ```json { "project": { "workspace": "my-org", "slug": "my-app", "sourceLocale": "en" }, "localKeys": { "total": 1223 }, "comparison": { "missingInRemote": { "pages.bestApps": ["pages.bestApps.meta.title"] }, "unusedInCode": { "old": ["old.unused_key"] }, "missingCount": 473, "unusedCount": 386 }, "coverage": { "local": 59, "remote": 63 }, "files": 246, "duration": 850 } ``` *** ## CI Integration ### Fail build on missing keys ```bash # Using jq to check missingCount better-i18n sync --format json | jq -e '.comparison.missingCount == 0' > /dev/null || exit 1 ``` ### List missing keys in CI logs ```bash better-i18n sync --format json | jq '.comparison.missingInRemote' ``` # Setup Better i18n MCP (Model Context Protocol) allows AI assistants like Claude and Cursor to directly interact with your translation workspace. ### Get your API Key 1. Sign in to [dash.better-i18n.com](https://dash.better-i18n.com). 2. Go to **Settings > API Keys**. 3. Create a new key and copy it. ### Configure Project Context The MCP server needs to know which project to manage. It looks for a `project` identifier in your `i18n.config.ts`. ```ts title="i18n.config.ts" import { createI18n } from "@better-i18n/next"; export const i18n = createI18n({ project: "your-org/your-project", // MCP uses this ID defaultLocale: "en", }); ``` ### Configure your AI Assistant Pass your API key using the `BETTER_I18N_API_KEY` environment variable. Add this to your MCP settings in Cursor (`~/.cursor/mcp.json`): ```json title="~/.cursor/mcp.json" { "mcpServers": { "better-i18n": { "command": "npx", "args": ["@better-i18n/mcp"], "env": { "BETTER_I18N_API_KEY": "your-api-key" } } } } ``` Add this to your Claude Desktop config: ```json { "mcpServers": { "better-i18n": { "command": "npx", "args": ["@better-i18n/mcp"], "env": { "BETTER_I18N_API_KEY": "your-api-key" } } } } ``` ### Verify Connectivity Ask your AI assistant a translation-related question to verify the setup: > "Show me the translation status for my current project." If configured correctly, the AI will use the `getProject` tool to fetch your real-time stats. ## Environment Variables | Variable | Required | Description | | --------------------- | -------- | ---------------------------------------------- | | `BETTER_I18N_API_KEY` | Yes | Your organization API key | | `BETTER_I18N_API_URL` | No | Custom API URL (default: dash.better-i18n.com) | | `BETTER_I18N_DEBUG` | No | Enable detailed debug logging | # Introduction Better i18n MCP (Model Context Protocol) is the bridge between your AI assistant and your translation workspace. It allows tools like Cursor and Claude to directly manage your project's I18n lifecycle without you leaving your IDE. ## Core Features * 🤖 **AI-Native Workflow** - Empower your AI to fix missing translations and create keys. * ⚡ **Zero Scan Latency** - Uses your `i18n.config.ts` to immediately connect to the cloud. * 🔄 **Efficient Bulk Updates** - Single commands to update hundreds of values in seconds. * 🔍 **Context-Aware** - AI understands your namespaces and project structure. ## Quick Start The fastest way to get started is by configuring your favorite AI assistant: Add the server to Cursor's MCP pool: ```bash npx @better-i18n/mcp ``` See the [Setup Guide](/docs/mcp/setup) for detailed environment configuration. Configure Claude Desktop to include `@better-i18n/mcp`. See [Setup](/docs/mcp/setup). ## Why use MCP? Instead of manually copying keys and text to the dashboard, you can simply ask: > "Translate the new auth namespace to Turkish and German." The AI assistant will: 1. Verify the keys exist. 2. Generate accurate translations in context. 3. Apply them directly to your project using the [Available Tools](/docs/mcp/tools). # Available Tools The Better i18n MCP server provides a set of tools that allow AI assistants to manage translations, create keys, and perform bulk updates. All tools require `orgSlug` and `projectSlug` parameters. The AI assistant automatically reads these from your `i18n.config.ts`. ## Discovery Tools List all projects the user has access to across all organizations. **Use this first** to discover available projects before other operations. **Returns:** * Project slugs in `org/project` format * Source and target languages * Organization names **Example Prompts:** * "What projects do I have access to?" * "List my translation projects" Get detailed project information including structure and coverage stats. **Returns:** * Available namespaces * Available languages with translation coverage percentages * Total key count **Example Prompts:** * "Show my project stats" * "How many translation keys do I have?" * "What's the translation coverage for Turkish?" ## Reading Tools Fetch ALL translation keys with their translations in a single request. Designed for AI usage - no pagination, returns everything. **Parameters:** * `namespaces` (optional): Filter by specific namespaces * `search` (optional): Search keys by name **Example Prompts:** * "Show me all translations" * "Get all keys in the auth namespace" List translation keys with pagination and filtering options. **Parameters:** * `search`: Search by key name (partial match) * `namespaces`: Filter by namespaces * `missingLanguage`: Find keys that DON'T have a translation for this language * `page`, `limit`: Pagination **Example Prompts:** * "Which keys are not yet translated to Turkish?" * "List keys in the common namespace" * "Find keys missing German translations" ## Writing Tools Create one or more translation keys with optional translations. Handles both single key creation and bulk operations efficiently. **Parameters:** * `k`: Array of keys to create, each containing: * `n`: Unique key identifier (e.g., "submit\_button", "nav.home") * `ns`: Namespace for grouping (default: "default") * `v`: Source language text * `t`: Target language translations (optional object: `{ "de": "...", "fr": "..." }`) **Important:** Don't include the source language in translations (`t`) - it goes in `v`. **Example Prompts:** * "Create a new key called auth.login.title with source text 'Sign In'" * "Add a new translation key for the submit button" * "Create these new keys: nav.home, nav.about, nav.contact" * "Add all these hardcoded strings as translation keys" Update translations for one or more keys. Handles both single updates and bulk operations. Works for both source and target languages. **Parameters:** * `t`: Array of updates, each containing: * `k`: The key identifier to update * `n`: Key name (optional) * `ns`: Namespace of the key * `l`: Language code to update * `t`: New translation text * `s`: Boolean flag, true if updating source language (optional) **Note:** If `s` is true or `l` matches the source language, it updates the source text. **Example Prompts:** * "Update the Turkish translation for auth.login.title" * "Change the German text for nav.home" * "Translate all missing keys to Turkish" * "Update these 10 translations" * "Apply these translations to the project" Add a new target language to the project. **Parameters:** * `languageCode`: ISO 639-1 code (e.g., "fr", "ja", "de") **Example Prompts:** * "Add Japanese to my project" * "I want to support French" *** ## Best Practices 1. **Discover First**: Start with `listProjects` to find available projects. 2. **Analyze Structure**: Use `getProject` to understand namespaces and coverage. 3. **Find Gaps**: Use `listKeys` with `missingLanguage` to find untranslated keys. 4. **Use Array-based Tools**: `createKeys` and `updateKeys` handle both single and bulk operations efficiently. 5. **Human Verification**: Always review critical translations before shipping. # API Reference Complete API reference for the Next.js SDK. ## createI18n The main entry point for the SDK. It returns an object containing everything needed for Next.js i18n integration. ```ts import { createI18n } from "@better-i18n/next"; const i18n = createI18n(config); ``` ### Return Properties Configuration object intended for the `next-intl` request handler in `src/i18n/request.ts`. Next.js middleware function that handles locale detection and URL routing (e.g., adding `/tr` prefix). *** ## Core Methods Fetches the project manifest from the Better i18n CDN. This includes the list of supported languages and project metadata. ```ts const manifest = await i18n.getManifest(); // Force refresh (bypass internal cache) const manifest = await i18n.getManifest({ forceRefresh: true }); ``` Fetches the full translation dictionary for a specific locale. ```ts const messages = await i18n.getMessages("tr"); // Returns: { common: { welcome: "Hoş geldiniz" }, ... } ``` Returns an array of all available locale codes configured in your project. ```ts const locales = await i18n.getLocales(); // ["en", "tr", "de", "fr"] ``` *** ## Types Commonly used types for manual integrations and custom logic. ```ts import type { I18nConfig, LanguageOption, Locale, ManifestResponse, Messages, } from "@better-i18n/next"; ``` # Configuration The `createI18n` function is the entry point for the SDK. It accepts a configuration object that defines your project context and delivery preferences. ## Basic Configuration The absolute minimum required is your project indentifier and default locale. ```ts title="i18n.config.ts" import { createI18n } from "@better-i18n/next"; export const i18n = createI18n({ project: "your-org/your-project", defaultLocale: "en", }); ``` The `project` value uses `org/project` format. This same value is used by the [CLI](/docs/cli) and [MCP](/docs/mcp) to identify your project. You can also configure CLI-specific options (like linting rules and file exclusions) in this same file. See [CLI Configuration](/docs/cli/configuration) for details. ## Full Reference | Option | Type | Default | Description | | --------------------------- | ---------------------------------------- | ------------- | ------------------------------------------ | | `project` | `string` | required | Project identifier in `org/project` format | | `defaultLocale` | `string` | required | Default/fallback locale code | | `cdnBaseUrl` | `string` | auto | CDN base URL (auto-detected) | | `localePrefix` | `"as-needed"` \| `"always"` \| `"never"` | `"as-needed"` | URL locale prefix behavior | | `debug` | `boolean` | `false` | Enable debug logging | | `logLevel` | `LogLevel` | `"warn"` | Logging verbosity | | `manifestCacheTtlMs` | `number` | `60000` | Manifest cache TTL in ms | | `manifestRevalidateSeconds` | `number` | `60` | Next.js revalidate for manifest | | `messagesRevalidateSeconds` | `number` | `60` | Next.js revalidate for messages | *** ## Behavior Customization Control how locales appear in your URLs. ```ts // /page for default, /tr/page for others createI18n({ localePrefix: "as-needed" }); // always includes locale: /en/page, /tr/page createI18n({ localePrefix: "always" }); // never includes locale in URL createI18n({ localePrefix: "never" }); ``` Configure TTL for edge and runtime caching. ```ts createI18n({ // Cache manifest in memory for 5 minutes manifestCacheTtlMs: 5 * 60 * 1000, // Next.js ISR revalidation times manifestRevalidateSeconds: 300, messagesRevalidateSeconds: 300, }); ``` Enable detailed logging for troubleshooting. ```ts createI18n({ debug: true, logLevel: "debug", }); ``` # Getting Started Get started with Better i18n in your Next.js app. Our SDK integrates seamlessly with `next-intl` to provide a type-safe, CDN-powered translation experience. ### Create a Project 1. Go to [dash.better-i18n.com](https://dash.better-i18n.com) 2. Create an organization (e.g., `my-company`) 3. Create a project (e.g., `web-app`) Your project identifier will be in the format: `my-company/web-app`. ### Install the SDK Install the package via your preferred package manager: ```bash npm install @better-i18n/next ``` ```bash yarn add @better-i18n/next ``` ```bash pnpm add @better-i18n/next ``` ```bash bun add @better-i18n/next ``` ### Configure i18n Create an `i18n.config.ts` file in your project root. This file is shared between the SDK and the Better i18n CLI. ```ts title="i18n.config.ts" import { createI18n } from "@better-i18n/next"; export const i18n = createI18n({ project: "my-company/web-app", defaultLocale: "en", }); ``` ### Set Up next-intl Configure the `next-intl` request handler using the exported configuration. ```ts title="src/i18n/request.ts" import { i18n } from "../i18n.config"; export default i18n.requestConfig; ``` ### Add Middleware Register the i18n middleware in your `middleware.ts`. ```ts title="middleware.ts" import { i18n } from "./i18n.config"; export const middleware = i18n.middleware; export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"], }; ``` ### Use Translations Now you can use standard `next-intl` hooks. The CLI will automatically track these scopes for syncing. ```tsx title="app/page.tsx" import { useTranslations } from "next-intl"; export default function Home() { const t = useTranslations("common"); return

{t("welcome")}

; } ```
## Next Steps * Configure [caching and revalidation](/docs/next/configuration) * Set up [middleware options](/docs/next/middleware) * Explore the [API reference](/docs/next/api) * Audit your keys with the [CLI](/docs/cli/sync) # Middleware Configure locale routing with the middleware. ## Basic Setup ```ts title="middleware.ts" import { i18n } from "./src/i18n"; export const middleware = i18n.middleware; export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"], }; ``` ## Matcher Patterns The matcher determines which routes use i18n: ```ts export const config = { matcher: [ // Skip API routes and static files "/((?!api|_next|.*\\..*).*)", ], }; ``` ## How It Works 1. Middleware detects locale from URL, cookies, or headers 2. Sets `x-locale` header for server components 3. Redirects to localized URL if needed ## Locale Detection Order 1. URL path (`/tr/about` → `tr`) 2. Cookie (`NEXT_LOCALE`) 3. Accept-Language header 4. Default locale from config # Introduction `@better-i18n/next` is the official SDK for integrating Better i18n translations into your Next.js application. It handles manifest fetching, caching, and provides a seamless integration with `next-intl`. ## Features * ⚡ **Zero-Config Sync** - Connects to your project via `i18n.config.ts`. * 🌍 **Edge-Ready Caching** - Built-in support for manifest and message caching. * 🧪 **Type-Safe** - Full TypeScript support for your translation keys. * 🤝 **next-intl First** - Designed to work perfectly as a message provider for `next-intl`. ## Installation ```bash npm install @better-i18n/next ``` ```bash yarn add @better-i18n/next ``` ```bash pnpm add @better-i18n/next ``` ```bash bun add @better-i18n/next ``` ## Quick Start Create your configuration file to establish project context: ```ts title="i18n.config.ts" import { createI18n } from "@better-i18n/next"; export const i18n = createI18n({ project: "your-org/your-project", defaultLocale: "en", }); ``` ## SDK Methods The `createI18n` function returns a suite of tools to manage your i18n lifecycle: | Method | Description | | --------------------- | ------------------------------------------------------------------- | | `requestConfig` | Ready-to-use configuration for `next-intl` request handler. | | `middleware` | Next.js middleware for handling locale-based routing. | | `getManifest()` | Fetches the latest project manifest (languages, metadata). | | `getMessages(locale)` | Fetches the standard dictionary for a specific locale from the CDN. | | `getLocales()` | Returns an array of available locale codes for the project. | | `config` | The resolved configuration object. |