### Install i18next-cli Source: https://github.com/i18next/i18next-cli/blob/main/README.md Install i18next-cli as a development dependency in your project. ```bash npm install --save-dev i18next-cli ``` -------------------------------- ### Install locize-cli Source: https://github.com/i18next/i18next-cli/blob/main/README.md Install the locize-cli globally to use the locize integration commands. This is a prerequisite for syncing translations with the Locize platform. ```bash # Install globally (recommended) npm install -g locize-cli ``` -------------------------------- ### Initialize i18next-cli Configuration Source: https://github.com/i18next/i18next-cli/blob/main/README.md Create an i18next.config.ts file to configure the CLI. This example sets up locales and extraction paths. ```typescript import { defineConfig } from 'i18next-cli'; export default defineConfig({ locales: ['en', 'de'], extract: { input: ['src/**/*.{js,jsx,ts,tsx}'], output: 'public/locales/{{language}}/{{namespace}}.json', }, }); ``` -------------------------------- ### Lint Plugin API Example Source: https://github.com/i18next/i18next-cli/blob/main/README.md Provides a TypeScript example of creating a custom lint plugin for Vue files, demonstrating the use of `lintExtensions`, `lintSetup`, `lintOnLoad`, and `lintOnResult` hooks. ```APIDOC ### Lint Plugin API ```typescript import type { Plugin, LinterPlugin, LintPluginContext, LintIssue, } from 'i18next-cli'; // You can type your plugin as Plugin (full surface), LinterPlugin (lint-focused), // or InstrumenterPlugin (instrument-focused) export const vueLintPlugin = (): LinterPlugin => ({ name: 'vue-lint-plugin', lintExtensions: ['.vue'], lintSetup: async (context: LintPluginContext) => { context.logger.info('vue lint plugin initialized'); }, lintOnLoad: async (code, filePath) => { if (!filePath.endsWith('.vue')) return undefined; // preprocess SFC/template to lintable JS/TS/JSX text return code; }, lintOnResult: async (_filePath, issues: LintIssue[]) => { // Example: keep only interpolation issues return issues.filter(issue => issue.type === 'interpolation'); } }); ``` ``` -------------------------------- ### Extend Recommended Lint Tags and Attributes Source: https://github.com/i18next/i18next-cli/blob/main/README.md Import and spread recommended lists to extend built-in linting configurations. Ensure 'i18next-cli' is installed. ```typescript import { defineConfig, recommendedAcceptedTags, recommendedAcceptedAttributes } from 'i18next-cli'; export default defineConfig({ locales: ['en', 'de'], extract: { input: ['src/**/*.{js,jsx,ts,tsx}'], output: 'public/locales/{{language}}/{{namespace}}.json', }, lint: { acceptedTags: ['my-web-component', ...recommendedAcceptedTags], acceptedAttributes: ['data-label', ...recommendedAcceptedAttributes] } }); ``` -------------------------------- ### Example Location Metadata Output Source: https://github.com/i18next/i18next-cli/blob/main/README.md This is an example of the JSON output generated by the locationMetadataPlugin, showing translation keys and their usage locations. ```json { "translation": { "app.title": [ "src/App.tsx:12:15", "src/components/Header.tsx:8:22" ], "user.greeting": [ "src/pages/Profile.tsx:45:10" ] }, "common": { "button.save": [ "src/components/SaveButton.tsx:18:7", "src/forms/UserForm.tsx:92:5" ] } } ``` -------------------------------- ### Example YAML Translation File Content Source: https://github.com/i18next/i18next-cli/blob/main/README.md This is an example of a YAML translation file generated by i18next-cli, showing a structured key-value representation of translations. ```yaml app: title: My Application description: Welcome to our app button: save: Save cancel: Cancel ``` -------------------------------- ### Generated Merged Namespace File Example Source: https://github.com/i18next/i18next-cli/blob/main/README.md When `mergeNamespaces` is enabled, this is an example of the generated output file for a specific language, with namespaces as top-level keys. ```typescript export default { "translation": { "key1": "Value 1" }, "common": { "keyA": "Value A" } } as const; ``` -------------------------------- ### i18next-cli Configuration with Vue Lint Plugin Source: https://github.com/i18next/i18next-cli/blob/main/README.md Example configuration for i18next-cli using defineConfig. It sets up locales, input/output paths for extraction, and includes a custom Vue lint plugin. ```typescript import { defineConfig } from 'i18next-cli'; import { vueLintPlugin } from './plugins/vue-lint-plugin.mjs'; export default defineConfig({ locales: ['en', 'de'], extract: { input: ['src/**/*.{ts,tsx,js,jsx,vue}'], output: 'locales/{{language}}/{{namespace}}.json' }, plugins: [ vueLintPlugin() ] }); ``` -------------------------------- ### Basic i18next config with defineConfig Source: https://github.com/i18next/i18next-cli/blob/main/README.md Example of a basic i18next configuration file using TypeScript and the `defineConfig` helper for type safety and IntelliSense. This configuration specifies locales and extraction input/output paths. ```typescript // i18next.config.ts import { defineConfig } from 'i18next-cli'; export default defineConfig({ locales: ['en', 'de', 'fr'], extract: { input: ['src/**/*.{ts,tsx,js,jsx}'], output: 'locales/{{language}}/{{namespace}}.json', }, }); ``` -------------------------------- ### Gulp Integration with i18next-cli Source: https://github.com/i18next/i18next-cli/blob/main/README.md Example of integrating i18next-cli's runExtractor function into a Gulp build task. ```typescript import gulp from 'gulp'; import { runExtractor } from 'i18next-cli'; gulp.task('i18next-extract', async () => { const config = { locales: ['en', 'de', 'fr'], extract: { input: ['src/**/*.{ts,tsx,js,jsx}'], output: 'public/locales/{{language}}/{{namespace}}.json', }, }; await runExtractor(config); }); ``` -------------------------------- ### Basic Custom Plugin for i18next-cli Source: https://github.com/i18next/i18next-cli/blob/main/README.md A basic custom plugin example for i18next-cli that handles custom file formats. It uses glob to find .vue files and extracts translation keys from specific patterns within them. ```typescript import { glob } from 'glob'; import { readFile, writeFile } from 'node:fs/promises'; export const myCustomPlugin = () => ({ name: 'my-custom-plugin', // Handle custom file formats async onEnd(keys) { // Extract keys from .vue files const vueFiles = await glob('src/**/*.vue'); for (const file of vueFiles) { const content = await readFile(file, 'utf-8'); const keyMatches = content.matchAll(/\{\{\s*\$t\(['"]([^'"]+)['"]\)/g); for (const match of keyMatches) { keys.set(`translation:${match[1]}`, { key: match[1], defaultValue: match[1], ns: 'translation' }); } } } }); ``` -------------------------------- ### Locize Cloud Integration Source: https://context7.com/i18next/i18next-cli/llms.txt Commands for integrating with the Locize cloud translation management platform. Requires 'locize-cli' to be installed globally. Supports downloading translations, syncing, and migrating Locize configurations. ```bash npx i18next-cli locize-download ``` ```bash npx i18next-cli locize-sync ``` ```bash npx i18next-cli locize-sync --update-values --dry-run ``` ```bash npx i18next-cli locize-migrate ``` -------------------------------- ### Selector API in Strict Mode Source: https://github.com/i18next/i18next-cli/blob/main/README.md Shows how to use the Selector API in strict mode, where every path must explicitly start with a namespace segment. ```ts // useTranslation('common'); t($ => $.common.button.save); // → common.json: button.save // useTranslation(['auth', 'validation']); t($ => $.auth.login['Welcome Back!']); // → auth.json: login.Welcome Back! t($ => $.validation.email['Required']); // → validation.json: email.Required ``` -------------------------------- ### Example TypeScript Translation File Content Source: https://github.com/i18next/i18next-cli/blob/main/README.md This is an example of a TypeScript translation file generated by i18next-cli, exporting a default object with translation key-value pairs. ```typescript export default { "myKey": "My value" } as const; ``` -------------------------------- ### Create a Custom Vue Plugin for i18next-cli Source: https://context7.com/i18next/i18next-cli/llms.txt A custom plugin to handle Vue files, transforming them before parsing and adding custom logic for translation extraction. This example demonstrates `onLoad`, `onVisitNode`, `onEnd`, `afterSync`, `lintOnLoad`, `lintOnResult`, and `instrumentOnResult` hooks. ```typescript import { defineConfig } from 'i18next-cli'; import type { Plugin, ExtractedKey, ExtractedKeysMap, LintIssue, CandidateString } from 'i18next-cli'; import { readFile } from 'node:fs/promises'; import { glob } from 'glob'; const vuePlugin = (): Plugin => ({ name: 'vue-plugin', // Extension hints used as optimization skip hints lintExtensions: ['.vue'], instrumentExtensions: ['.vue'], // One-time initialization setup: async () => { console.log('Vue plugin initialized'); }, // Transform .vue files to JS/TSX before SWC parses them onLoad: async (code, filePath) => { if (!filePath.endsWith('.vue')) return undefined; // pass through const scriptMatch = code.match(/]*>([\s\S]*?)<\/script>/); return scriptMatch ? scriptMatch[1] : code; }, // Inject custom scope info for a proprietary hook (e.g. usePageT) onVisitNode: (node, context) => { if ( node.type === 'VariableDeclarator' && (node as any).init?.type === 'CallExpression' && (node as any).init?.callee?.value === 'usePageT' ) { context.setVarInScope('t', { defaultNs: 'pages', keyPrefix: 'dashboard' }); } }, // Observe every submitted key (read-only snapshot) onKeySubmitted: (key: Readonly) => { if (key.ns === 'banned') console.warn(`Banned namespace used: ${key.key}`); }, // Post-process the complete key map (add non-JS keys from .vue templates) onEnd: async (keys: ExtractedKeysMap) => { const vueFiles = await glob('src/**/*.vue'); for (const file of vueFiles) { const content = await readFile(file, 'utf-8'); for (const [, key] of content.matchAll(/\$t\('([^']+)'\)/g)) { keys.set(`translation:${key}`, { key, ns: 'translation', defaultValue: key }); } } }, // Run after translation files are written afterSync: async (results, config) => { const updatedCount = results.filter(r => r.updated).length; console.log(`${updatedCount} translation files updated.`); }, // Lint: preprocess .vue files lintOnLoad: async (code, filePath) => { if (!filePath.endsWith('.vue')) return undefined; const match = code.match(/