swiftlys2/docs/api/ai/

Translations

SwiftlyS2's translation APIs localize plugin text by key and automatically resolve player-specific language.

Translation File Layout

Place .jsonc files named by language code under resources/translations/ (for example en.jsonc, fr.jsonc, pt-BR.jsonc, es-419.jsonc). At least one must exist for the plugin's translations to load.

Custom language codes work for direct lookups through Core.Localizer, but Core.Translation.GetPlayerLocalizer(player) only resolves the codes listed below.

Keep an en.jsonc baseline with all keys so unsupported or incomplete languages still have usable text.

Language Codes

LanguageCodeFile Name
Arabicarar.jsonc
Bulgarianbgbg.jsonc
Chinese (CN & TW)zh-CN / zh-TWzh-CN.jsonc / zh-TW.jsonc
Czechcscs.jsonc
Danishdada.jsonc
Dutchnlnl.jsonc
Englishenen.jsonc
Finnishfifi.jsonc
Frenchfrfr.jsonc
Germandede.jsonc
Greekelel.jsonc
Hungarianhuhu.jsonc
Indonesianidid.jsonc
Italianitit.jsonc
Japanesejaja.jsonc
Koreankoko.jsonc
Norwegiannono.jsonc
Polishplpl.jsonc
Portugueseptpt.jsonc
Portuguese (Brazilian)pt-BRpt-BR.jsonc
Romanianroro.jsonc
Russianruru.jsonc
Spanisheses.jsonc
Spanish (Latin America)es-419es-419.jsonc
Swedishsvsv.jsonc
Thaithth.jsonc
Turkishtrtr.jsonc
Ukrainianukuk.jsonc
Vietnamesevnvn.jsonc

Example Translation File

{
    // General
    "plugin.name": "My Plugin",
    "plugin.ready": "Plugin is ready.",
 
    // Command feedback
    "command.heal.success": "You have been healed.",
    "command.heal.other": "{0} healed {1}",
    "command.heal.no_permission": "You do not have permission.",
 
    // Errors
    "error.player_not_found": "Player '{0}' was not found."
}

Values are chat-color-processed automatically, so [red]/[green]/etc. bracket syntax works directly inside translation strings. See Chat & CenterHTML Styling for the full color list.

Server-Side Localization

APIISwiftlyCore.Localizer (APIILocalizer) is for messages that aren't player-specific. It supports ["key"] and ["key", arg0, arg1, ...] - keep placeholder order stable across languages:

string readyMessage = Core.Localizer["plugin.ready"];
string versionMessage = Core.Localizer["plugin.version", "1.2.0"];

Player-Specific Localization

Use APIITranslationService.GetPlayerLocalizer when output should match the player's language. APIIPlayer.PlayerLanguage (a APILanguage value) is available for diagnostics or conditional flows:

public async Task GreetAsync(IPlayer player)
{
    var localizer = Core.Translation.GetPlayerLocalizer(player);
    string message = localizer["welcome.message", player.Name];
 
    await player.SendChatAsync(message);
    Core.Logger.LogInformation("Greeted {SteamId} in {Language}", player.SteamID, player.PlayerLanguage);
}

Key Design Best Practices

  • Use stable dot-separated keys (for example command.heal.success).
  • Keep the same key set across all language files.
  • Add JSONC comments for translator context when placeholders are involved.
  • Avoid string concatenation in code for translatable sentences.