Skip to content

Latest commit

 

History

History
246 lines (193 loc) · 7.37 KB

File metadata and controls

246 lines (193 loc) · 7.37 KB

Dates-LE Internationalization (I18N) Guide

Goals and philosophy

  • Inclusive by default: all user‑facing text is localizable.
  • Privacy‑first and offline: no network calls; translations ship with the extension.
  • Predictable keys: two namespaces — manifest.* for package.json UI and runtime.* for in‑code strings.
  • Safe fallbacks: English is bundled and used when a key or locale is missing.
  • Translator‑friendly: consistent placeholders, small focused sentences, and a source language.json catalogue.

Non‑goals:

  • Remote translation fetching or telemetry.
  • Complex runtime pluralization logic. We use positional {0} placeholders with vscode-nls.

File layout

src/i18n/
  package.nls.json          # Base English strings for package.json
  runtime.json              # Runtime strings for in-code messages
  package.nls.de.json       # German translations
  package.nls.es.json       # Spanish translations
  package.nls.fr.json       # French translations
  package.nls.id.json       # Indonesian translations
  package.nls.it.json       # Italian translations
  package.nls.ja.json       # Japanese translations
  package.nls.ko.json       # Korean translations
  package.nls.ru.json       # Russian translations
  package.nls.uk.json       # Ukrainian translations
  package.nls.vi.json       # Vietnamese translations
  package.nls.zh-cn.json    # Chinese (Simplified) translations

Key namespaces

manifest.* keys (package.json UI)

Used for VS Code extension manifest strings:

{
  "manifest.ext.name": "Dates-LE",
  "manifest.ext.description": "Zero Hassle Date Extraction from Documentation, Configs, and Code",
  "manifest.command.category": "Dates-LE",
  "manifest.command.extract.title": "Extract Dates",
  "manifest.command.analyze.title": "Analyze Dates",
  "manifest.command.convert.title": "Convert Dates",
  "manifest.command.filter.title": "Filter Dates",
  "manifest.command.validate.title": "Validate Dates",
  "manifest.command.settings.title": "Open Settings",
  "manifest.command.help.title": "Help & Troubleshooting"
}

runtime.* keys (in-code messages)

Used for dynamic messages, notifications, and user feedback:

{
  "runtime.extraction.progress": "Extracting dates...",
  "runtime.extraction.complete": "Extracted {0} dates",
  "runtime.validation.progress": "Validating dates...",
  "runtime.validation.complete": "Validated {0} dates",
  "runtime.analysis.progress": "Analyzing dates...",
  "runtime.analysis.complete": "Analysis complete",
  "runtime.error.no-active-editor": "No active editor found",
  "runtime.error.file-too-large": "File size ({0} bytes) exceeds safety threshold ({1} bytes)",
  "runtime.error.extraction-failed": "Extraction failed: {0}",
  "runtime.error.validation-failed": "Validation failed: {0}",
  "runtime.error.analysis-failed": "Analysis failed: {0}",
  "runtime.success.dates-extracted": "Successfully extracted {0} dates",
  "runtime.success.dates-validated": "Successfully validated {0} dates",
  "runtime.success.analysis-complete": "Analysis completed successfully",
  "runtime.warning.large-file": "Large file detected. This may take a while...",
  "runtime.warning.no-dates-found": "No dates found in the current document",
  "runtime.warning.invalid-dates": "Found {0} invalid dates",
  "runtime.info.clipboard-copied": "Dates copied to clipboard",
  "runtime.info.settings-saved": "Settings saved successfully",
  "runtime.info.help-opened": "Help documentation opened"
}

Implementation

Package.json configuration

{
  "l10n": "./package.nls.json",
  "scripts": {
    "vscode:prepublish": "npm run build && npm run copy:i18n",
    "copy:i18n": "cp src/i18n/package.nls.*.json . 2>/dev/null || true"
  }
}

Runtime localization

import * as nls from 'vscode-nls'

const localize = nls.config({ messageFormat: nls.MessageFormat.file })()

// Usage examples
const message = localize('runtime.extraction.progress', 'Extracting dates...')
const countMessage = localize('runtime.extraction.complete', 'Extracted {0} dates', dateCount)
const errorMessage = localize(
  'runtime.error.extraction-failed',
  'Extraction failed: {0}',
  error.message,
)

Manifest localization

{
  "displayName": "%manifest.ext.name%",
  "description": "%manifest.ext.description%",
  "commands": [
    {
      "command": "dates-le.extractDates",
      "title": "%manifest.command.extract.title%"
    }
  ]
}

Translation guidelines

Key naming conventions

  • Use descriptive, hierarchical names
  • Separate manifest and runtime concerns
  • Use consistent prefixes (manifest.*, runtime.*)
  • Include context in key names

Message formatting

  • Use positional placeholders: {0}, {1}, {2}
  • Keep messages concise and actionable
  • Provide context for technical terms
  • Use consistent terminology

Quality standards

  • All user-facing text must be localizable
  • Provide fallback English text
  • Test with different locales
  • Validate placeholder consistency

Adding new languages

  1. Create package.nls.{locale}.json in src/i18n/
  2. Copy structure from package.nls.json
  3. Translate all values, keeping keys unchanged
  4. Test the extension with the new locale
  5. Update this documentation

Supported locales

Locale File Status
English package.nls.json ✅ Complete
German package.nls.de.json ✅ Complete
Spanish package.nls.es.json ✅ Complete
French package.nls.fr.json ✅ Complete
Indonesian package.nls.id.json ✅ Complete
Italian package.nls.it.json ✅ Complete
Japanese package.nls.ja.json ✅ Complete
Korean package.nls.ko.json ✅ Complete
Portuguese (Brazil) package.nls.pt-br.json ✅ Complete
Russian package.nls.ru.json ✅ Complete
Ukrainian package.nls.uk.json ✅ Complete
Vietnamese package.nls.vi.json ✅ Complete
Chinese (Simplified) package.nls.zh-cn.json ✅ Complete

Testing localization

Manual testing

  1. Change VS Code language setting
  2. Reload VS Code window
  3. Verify all UI elements are translated
  4. Test command palette entries
  5. Check status bar messages
  6. Validate error messages

Automated testing

// Test localization keys exist
describe('Localization', () => {
  it('should have all required manifest keys', () => {
    const manifestKeys = [
      'manifest.ext.name',
      'manifest.ext.description',
      'manifest.command.extract.title',
      // ... other keys
    ]

    manifestKeys.forEach((key) => {
      expect(localize(key, 'fallback')).not.toBe('fallback')
    })
  })
})

Best practices

Development

  • Always use localization for user-facing text
  • Provide meaningful fallback text
  • Test with different locales during development
  • Keep messages context-appropriate

Translation

  • Maintain consistency across languages
  • Preserve technical accuracy
  • Consider cultural context
  • Test with native speakers

Maintenance

  • Update translations when adding features
  • Validate placeholder consistency
  • Monitor for missing translations
  • Keep documentation current