Internationalization (i18n)

Guidelines for multilingual support in the WvdS FPC RAD Suite.

Basic Principle

No literal strings in Pascal code (except in asm blocks and technical constants).

Supported Languages

Code Language Status
EN English Base (Required)
DE German Complete
SL Slovenian Complete
HR Croatian Complete

Resourcestrings

Structure

sources/common/core/
├── WvdS.VSCode.Strings.pas      # English (Default)
├── WvdS.VSCode.Strings.DE.pas   # German
├── WvdS.VSCode.Strings.SL.pas   # Slovenian
└── WvdS.VSCode.Strings.HR.pas   # Croatian

Base Unit (English)

unit WvdS.VSCode.Strings;
 
{$mode objfpc}{$H+}
 
interface
 
resourcestring
  // === CORE ===
  rsCoreActivated = 'WvdS Core extension activated';
  rsCoreDeactivated = 'WvdS Core extension deactivated';
  rsCoreError = 'Error: %s';
 
  // === BUILD ===
  rsBuildStarting = 'Build starting...';
  rsBuildCompleted = 'Build completed successfully';
  rsBuildFailed = 'Build failed: %s';
  rsBuildCompilerNotFound = 'Compiler not found: %s';
 
  // === PROJECTS ===
  rsProjectCreating = 'Creating project...';
  rsProjectCreated = 'Project ''%s'' created successfully';
  rsProjectNameEmpty = 'Project name cannot be empty';
  rsProjectNameTooLong = 'Project name cannot exceed %d characters';
  rsProjectNameInvalidChar = 'Invalid character in project name: ''%s''';
 
  // === TOOLCHAIN ===
  rsToolNotFound = 'Tool not found: %s';
  rsToolDetected = '%s detected at %s';
  rsToolVersionMismatch = '%s version %s found, expected %s';
 
  // === VALIDATION ===
  rsValidationFailed = 'Validation failed: %s';
  rsFileNotFound = 'File not found: %s';
  rsAccessDenied = 'Access denied: %s';
  rsUnexpectedError = 'Unexpected error (%s): %s';
 
implementation
 
end.

German Translation

unit WvdS.VSCode.Strings.DE;
 
{$mode objfpc}{$H+}
 
interface
 
resourcestring
  // === CORE ===
  rsCoreActivated = 'WvdS Core Extension aktiviert';
  rsCoreDeactivated = 'WvdS Core Extension deaktiviert';
  rsCoreError = 'Fehler: %s';
 
  // === BUILD ===
  rsBuildStarting = 'Build wird gestartet...';
  rsBuildCompleted = 'Build erfolgreich abgeschlossen';
  rsBuildFailed = 'Build fehlgeschlagen: %s';
  rsBuildCompilerNotFound = 'Compiler nicht gefunden: %s';
 
  // === PROJECTS ===
  rsProjectCreating = 'Projekt wird erstellt...';
  rsProjectCreated = 'Projekt ''%s'' erfolgreich erstellt';
  rsProjectNameEmpty = 'Projektname darf nicht leer sein';
  rsProjectNameTooLong = 'Projektname darf maximal %d Zeichen haben';
  rsProjectNameInvalidChar = 'Ungültiges Zeichen im Projektnamen: ''%s''';
 
  // === TOOLCHAIN ===
  rsToolNotFound = 'Werkzeug nicht gefunden: %s';
  rsToolDetected = '%s erkannt unter %s';
  rsToolVersionMismatch = '%s Version %s gefunden, erwartet %s';
 
  // === VALIDATION ===
  rsValidationFailed = 'Validierung fehlgeschlagen: %s';
  rsFileNotFound = 'Datei nicht gefunden: %s';
  rsAccessDenied = 'Zugriff verweigert: %s';
  rsUnexpectedError = 'Unerwarteter Fehler (%s): %s';
 
implementation
 
end.

Usage in Code

Simple Strings

uses
  WvdS.VSCode.Strings;
 
// CORRECT
ShowInfoMessage(rsBuildStarting);
 
// FORBIDDEN
ShowInfoMessage('Build starting...');

Strings with Parameters

// CORRECT - Use Format
ShowInfoMessage(Format(rsProjectCreated, [ProjectName]));
ShowErrorMessage(Format(rsBuildFailed, [ErrorMessage]));
 
// FORBIDDEN
ShowInfoMessage('Project ''' + ProjectName + ''' created');

Pluralization

resourcestring
  rsFilesFound_One = '%d file found';
  rsFilesFound_Many = '%d files found';
 
function GetFilesFoundMessage(ACount: Integer): string;
begin
  if ACount = 1 then
    Result := Format(rsFilesFound_One, [ACount])
  else
    Result := Format(rsFilesFound_Many, [ACount]);
end;

Allowed Exceptions

Technical Constants

const
  // Technical IDs - do not translate
  COMMAND_ID = 'wvds.build.run';
  FILE_EXTENSION = '.pas';
  CONFIG_KEY = 'wvds.toolchain.fpcPath';

Format Strings

const
  // JSON/XML Templates - do not translate
  JSON_TEMPLATE = '{"name": "%s", "version": "%s"}';
  XML_TEMPLATE = '<%s>%s</%s>';

asm Blocks

// JavaScript code may contain strings
asm
  console.log('Debug message');
  vscode.window.showInformationMessage('Hello');
end;

Workflow: Adding a New String

Step 1: Define English String

// WvdS.VSCode.Strings.pas
resourcestring
  rsNewFeatureMessage = 'New feature activated';

Step 2: German Translation

// WvdS.VSCode.Strings.DE.pas
resourcestring
  rsNewFeatureMessage = 'Neue Funktion aktiviert';

Step 3: Slovenian Translation

// WvdS.VSCode.Strings.SL.pas
resourcestring
  rsNewFeatureMessage = 'Nova funkcija aktivirana';

Step 4: Croatian Translation

// WvdS.VSCode.Strings.HR.pas
resourcestring
  rsNewFeatureMessage = 'Nova funkcija aktivirana';

Step 5: Use in Code

ShowInfoMessage(rsNewFeatureMessage);

Runtime Language Selection

The language is read from VS Code settings:

function GetCurrentLanguage: string;
begin
  Result := GetVSCodeLanguage;  // e.g. 'de', 'en', 'sl', 'hr'
end;
 
procedure LoadLanguageStrings;
var
  Lang: string;
begin
  Lang := GetCurrentLanguage;
  case Lang of
    'de': LoadGermanStrings;
    'sl': LoadSlovenianStrings;
    'hr': LoadCroatianStrings;
  else
    // English as fallback
    LoadEnglishStrings;
  end;
end;

Validation

wvds-lint i18n Check

wvds-lint i18n --path sources/

Checks:

  • Hardcoded strings in code
  • Missing translations
  • Unused resourcestrings
  • Format string consistency (same number of %s, %d)

Checklist

[ ] English string defined
[ ] German translation added
[ ] Slovenian translation added
[ ] Croatian translation added
[ ] Format parameters match
[ ] Used in code (not hardcoded)
[ ] wvds-lint i18n successful

Best Practices

Clear, Context-Free Strings

// GOOD - Self-explanatory
rsFileNotFound = 'File not found: %s';
 
// BAD - Context missing
rsNotFound = 'Not found: %s';  // What was not found?

Prefer Full Sentences

// GOOD
rsProjectCreatedSuccessfully = 'Project ''%s'' was created successfully.';
 
// BAD - Fragments
rsProject = 'Project';
rsCreated = 'created';
rsSuccessfully = 'successfully';
// UI: rsProject + ' ' + Name + ' ' + rsCreated + ' ' + rsSuccessfully
// Problem: Word order varies between languages!

Consistent Terminology

Term English German
Build Build Build (not „Erstellung“)
Compile Compile Kompilieren
Path Path Pfad
Settings Settings Einstellungen

See Also

Zuletzt geändert: on 2026/01/30 at 01:27 AM