乐闻世界logo
搜索文章和话题

How to manage i18next translation resources and workflows?

2月18日 22:04

Translation Management Platform Integration

i18next-locize-backend

javascript
import Locize from 'i18next-locize-backend'; i18next .use(Locize) .init({ backend: { projectId: 'your-project-id', apiKey: 'your-api-key', referenceLng: 'en', version: 'latest' } });

Crowdin Integration

javascript
// load from Crowdin using i18next-http-backend i18next .use(HttpBackend) .init({ backend: { loadPath: 'https://cdn.crowdin.com/api/v2/projects/{{projectId}}/translations/{{lng}}/{{ns}}?apiKey={{apiKey}}', queryStringParams: { projectId: 'your-project-id', apiKey: 'your-api-key' } } });

Automatic Translation Extraction

Using i18next-scanner

bash
npm install --save-dev i18next-scanner
javascript
// gulpfile.js const gulp = require('gulp'); const scanner = require('i18next-scanner'); gulp.task('i18next', function() { return gulp.src(['src/**/*.{js,jsx,ts,tsx}']) .pipe(scanner({ lngs: ['en', 'zh', 'fr'], resource: { loadPath: 'locales/{{lng}}/{{ns}}.json', savePath: 'locales/{{lng}}/{{ns}}.json' }, keySeparator: '.', nsSeparator: ':', defaultValue: '__TRANSLATION__' })) .pipe(gulp.dest('locales')); });

Using Babel Plugin

javascript
// .babelrc { "plugins": [ ["i18next-extract", { "locales": ["en", "zh"], "outputPath": "locales/{{locale}}/{{ns}}.json", "keyAsDefaultValue": true }] ] }

Translation Workflow

Development Process

  1. Extract Translation Keys: Use scanning tools to extract translation keys from code
  2. Add Translations: Add or update translations in translation files
  3. Commit Code: Commit translation files to version control
  4. Send for Translation: Send content needing translation to translation team
  5. Merge Translations: Merge translated content back into codebase

Automated Workflow

javascript
// CI/CD integration example const { execSync } = require('child_process'); // extract translations execSync('npm run extract:translations'); // check for new translation keys const newKeys = checkNewTranslationKeys(); if (newKeys.length > 0) { console.log('New translation keys found:', newKeys); // send notification or create issue notifyTranslationTeam(newKeys); } // run tests execSync('npm test');

Translation Quality Assurance

Translation Validation

javascript
function validateTranslations(translations) { const errors = []; Object.keys(translations).forEach(lang => { const langTranslations = translations[lang]; Object.keys(langTranslations).forEach(key => { const translation = langTranslations[key]; // check for unclosed interpolation placeholders if (translation.includes('{{') && !translation.includes('}}')) { errors.push(`${lang}.${key}: Unclosed interpolation placeholder`); } // check for HTML tags if (/<[^>]*>/g.test(translation)) { errors.push(`${lang}.${key}: Contains HTML tags`); } // check length if (translation.length > 500) { errors.push(`${lang}.${key}: Translation too long`); } }); }); return errors; }

Translation Coverage Check

javascript
function checkTranslationCoverage(translations) { const referenceLang = 'en'; const referenceKeys = Object.keys(translations[referenceLang]); const coverage = {}; Object.keys(translations).forEach(lang => { if (lang === referenceLang) return; const langKeys = Object.keys(translations[lang]); const missingKeys = referenceKeys.filter(key => !langKeys.includes(key)); coverage[lang] = { total: referenceKeys.length, translated: langKeys.length, missing: missingKeys, percentage: (langKeys.length / referenceKeys.length) * 100 }; }); return coverage; }

Translation Update Strategy

Incremental Updates

javascript
async function updateTranslations(newTranslations) { const currentTranslations = await loadCurrentTranslations(); Object.keys(newTranslations).forEach(lang => { if (!currentTranslations[lang]) { currentTranslations[lang] = {}; } Object.assign(currentTranslations[lang], newTranslations[lang]); }); await saveTranslations(currentTranslations); }

Version Control

javascript
// track translation changes using Git const { execSync } = require('child_process'); function commitTranslations(message) { execSync('git add locales/'); execSync(`git commit -m "${message}"`); execSync('git tag translations-v' + Date.now()); }

Translation Platform Integration

Locize

javascript
import locize from 'locize'; import locizeBackend from 'i18next-locize-backend'; const locizeOptions = { projectId: 'your-project-id', apiKey: 'your-api-key', referenceLng: 'en', version: 'latest' }; i18next .use(locizeBackend) .use(locize.plugin()) .init({ backend: locizeOptions, locizeLastUsed: locizeOptions, saveMissing: true, debug: true });

PhraseApp

javascript
import PhraseBackend from 'i18next-phraseapp-backend'; i18next .use(PhraseBackend) .init({ backend: { projectId: 'your-project-id', apiKey: 'your-api-key', version: 'latest' } });

Best Practices

  1. Automated Extraction: Use tools to automatically extract translation keys
  2. Version Control: Include translation files in version control
  3. Continuous Integration: Validate translation quality in CI/CD
  4. Translation Management: Use professional translation management platforms
  5. Quality Assurance: Implement translation validation and coverage checks
  6. Team Collaboration: Establish clear translation workflows
  7. Documentation Maintenance: Keep translation documentation updated
标签:i18next