Lexicon API

Lexicon is a translation and locale-selection library for Vendetta Online plugins.

It allows plugins to:

Requirements

Lexicon is distributed as a Neoloader-managed library.

A plugin should request Lexicon through Neoloader before using its public class:

local lexicon

local lexicon_ready = function()
lexicon = lib.get_class("lexicon", "0")
end

lib.require({
{
name = "lexicon",
version = "0",
},
}, lexicon_ready)

Using version "0" requests the latest available active version through Neoloader.

Quick Start

1. Create translation files

Each language uses a separate INI file.

Example English file:

[lexicon]
code=en
lang=English
flag=flag.png
fallback=

1=Open
2=Close
3=Plugin settings

Example French file:

[lexicon]
code=fr
lang=Français
flag=flag.png
fallback=en

1=Ouvrir
2=Fermer
3=Paramètres du plugin

2. Register each file

local page_id

page_id = lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/en.ini"
)

lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/fr.ini"
)

Each translation file for the same plugin ID and version is added to the same translation page.

register() returns a numeric lookup ID. The same ID is returned for every successfully registered language belonging to that plugin/version page.

3. Fetch strings

local title = lexicon.fetch(
page_id,
1,
"Open"
)

If the selected translation does not contain key 1 , or no compatible translation page is available, "Open" is returned.

A plugin will commonly wrap this:

local lstr = function(id, default)
return lexicon.fetch(page_id, id, default)
end

Usage:

button.title = lstr(1, "Open")

Translation File Format

Lexicon translation files use the [lexicon] section.

[lexicon]
code=en
lang=English
flag=flag.png
fallback=

1=First translated string
2=Second translated string

Metadata fields

code

The locale code represented by this file.

code=fr

Examples include:

en
es
fr
pt
de
it
pl
tr
id
ru
uk
ja
ko
zh
ar

Locale codes should be lowercase. Hyphenated variants may be used where supported.

lang

The human-readable name of the language.

lang=Français

This name is displayed in Lexicon’s language-selection interface.

flag

Optional image filename for the language flag.

flag=flag.png

The path is resolved relative to the translation INI file.

When omitted, Lexicon uses its generic fallback image.

fallback

Optional fallback locale for this language.

fallback=en

When the preferred locale is registered but unavailable for a particular plugin, Lexicon may try its configured fallback before using the user’s secondary locale.

Translation keys

Translation strings are stored in the same section:

1=Open
2=Close

Although numeric keys are conventional and support precaching, fetch() converts the requested key to a string, so named keys may also be used when translations are loaded on demand:

button_open=Open
button_close=Close

For maximum compatibility with precaching and legacy conventions, sequential numeric keys are recommended.

Core Registration and Retrieval API

lexicon.register(entry_id, entry_version, ini_path)

Registers one translation file.

local fast_id, error_message = lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/en.ini"
)

Parameters

entry_id

The owning plugin or translation-page identifier.

"myplugin"

entry_version

The version associated with the translation page.

"1.0.0"

ini_path

The complete path to a Lexicon or legacy Babel translation file.

Returns

On success:

fast_id

fast_id is a numeric lookup ID suitable for lexicon.fetch() .

On failure:

false, error_message

Possible failures include:

invalid INI data
translation already present

Behavior

Calling register() repeatedly with the same entry ID and version adds additional locales to the same translation page:

local page_id = lexicon.register(
"myplugin",
"1.0.0",
path .. "lang/en.ini"
)

lexicon.register(
"myplugin",
"1.0.0",
path .. "lang/es.ini"
)

lexicon.register(
"myplugin",
"1.0.0",
path .. "lang/fr.ini"
)

All successful calls above refer to the same page.

lexicon.fetch(id_lookup, read_key, default_value)

Retrieves a translated string using the numeric lookup ID returned by register() .

local value = lexicon.fetch(
page_id,
3,
"Plugin settings"
)

Parameters

id_lookup

The numeric page ID returned by lexicon.register() .

read_key

The key within the translation file.

Numeric keys are converted to strings automatically.

default_value

The fallback value returned when no translation is found.

Returns

A translated string or default_value .

Locale resolution

Lexicon searches for a usable locale in this general order:

  1. the user’s primary locale;

  2. the primary locale’s declared fallback;

  3. the user’s safe or secondary locale;

  4. the caller-provided default string.

The selected string may be transliterated when its required glyph family is not available in the game’s currently loaded font atlas.

Recommended wrapper

local lstr = function(id, default)
return lexicon.fetch(page_id, id, default)
end

lexicon.retrieve(entry_id, entry_version, read_key, default_value)

Retrieves a translated value by plugin ID and version rather than by numeric page ID.

local value = lexicon.retrieve(
"myplugin",
"1.0.0",
3,
"Plugin settings"
)

Parameters

entry_id

Registered translation-page ID.

entry_version

Registered translation-page version.

read_key

Translation key.

default_value

Fallback string.

Returns

A translated string or default_value .

Notes

retrieve() is convenient when the page’s numeric lookup ID is not retained.

fetch() requires fewer registry lookups and is the preferred method for frequently accessed strings.

Locale Selection API

Lexicon distinguishes between two user locale choices.

Primary locale

The preferred translation language.

The primary locale may be any language known to Lexicon, including languages that the game cannot currently render directly.

When necessary, Lexicon may transliterate unsupported characters for display.

Secondary locale

The safe fallback language.

The secondary locale is intended to be compatible with the game’s available locale/font support.

lexicon.get_primary_locale()

Returns the current primary locale code.

local code = lexicon.get_primary_locale()

Example result:

"fr"

lexicon.get_secondary_locale()

Returns the current secondary locale code.

local code = lexicon.get_secondary_locale()

lexicon.get_safe_locale()

Returns the locale Lexicon considers safe for the game’s currently available language support.

local code = lexicon.get_safe_locale()

Lexicon prefers:

  1. the primary locale when it is game-supported;

  2. otherwise the secondary locale when it is game-supported;

  3. otherwise the game’s current locale.

lexicon.set_primary_locale(lang_code)

Sets the preferred locale.

local success, error_message =
lexicon.set_primary_locale("fr")

Returns

On success:

true

On failure:

false, "locale doesn't exist"

If Lexicon is configured to manage the game locale and the selected language is game-supported, the game locale is updated as well.

lexicon.set_secondary_locale(lang_code)

Sets the secondary fallback locale.

local success, error_message =
lexicon.set_secondary_locale("en")

Returns

On success:

true

On failure:

false, "locale doesn't exist"

The current implementation verifies that the language exists in Lexicon. Callers should normally select a language whose language metadata reports:

game_supported = true

Supported-Language API

lexicon.get_support_list()

Returns an alphabetically sorted array of locale codes known to Lexicon.

local languages = lexicon.get_support_list()

for _, code in ipairs(languages) do
print(code)
end

Example:

{
"da",
"de",
"en",
"eo",
"es",
"fr",
"it",
"nl",
"pl",
"pt",
"tr",
}

The exact contents depend on languages registered during the current session.

lexicon.is_supported(lang_code)

Checks whether a locale is registered with Lexicon and whether it is supported by the game.

local lexicon_supported, game_supported =
lexicon.is_supported("fr")

Returns

lexicon_supported

true when Lexicon has a registered language-support entry.

game_supported

true when the locale appears in Lexicon’s game-supported locale list.

Example:

local lexicon_supported, game_supported =
lexicon.is_supported("eo")

-- lexicon_supported may be true
-- game_supported may be false

lexicon.get_language(lang_code)

Returns metadata for a supported locale.

local language = lexicon.get_language("fr")

Returns

false when the language is unknown.

Otherwise, a table:

{
status = 2,
code = "fr",
lang = "Français",
flag = "path/to/flag.png",
game_supported = true,
provider = "path/to/fr.ini",
fallback = "en",
legacy = false,
official = true,
}

Fields

status

Language registration status.

0 = legacy or incomplete metadata
1 = fully registered external entry
2 = officially supplied by Lexicon

code

Locale code.

lang

Display name.

flag

Resolved flag-image path.

game_supported

Whether the game recognizes the locale as supported.

provider

INI file that supplied the language metadata.

fallback

Declared fallback locale, or an empty string.

legacy

True when the language was imported from a legacy Babel file.

official

True when the language is supplied directly by Lexicon.

Interface API

Lexicon exposes reusable IUP language-selection controls through:

lexicon.interface

lexicon.interface.locale_selector(options)

Creates and returns the full language-selection interface.

local selector =
lexicon.interface.locale_selector({
show_config = true,
})

The returned value is an IUP object and may be embedded in another interface.

lexicon.interface.locale_selector_compact(options)

Creates a compact version of the language selector.

local selector =
lexicon.interface.locale_selector_compact({
show_config = false,
})

This is a convenience wrapper equivalent to enabling compact mode in the standard selector.

lexicon.interface.locale_selector_dialog(options)

Creates, maps, and displays Lexicon’s language selector as a fullscreen modal-style dialog.

lexicon.interface.locale_selector_dialog()

Compact example:

lexicon.interface.locale_selector_dialog({
compact = true,
})

lexicon.open()

Opens Lexicon’s default language-selection dialog.

lexicon.open()

This is equivalent to:

lexicon.interface.locale_selector_dialog()

Configuration API

These functions expose Lexicon’s own configuration table.

Most plugins should use the locale-selection functions instead of modifying configuration values directly.

lexicon.get_config_list()

Returns an array of available configuration keys.

local keys = lexicon.get_config_list()

Current keys include:

precache
manage_game_locale
do_translit
baseline_locale
extended_locale

lexicon.get_config(cfg)

Returns a configuration value.

local enabled =
lexicon.get_config("do_translit")

lexicon.set_config(cfg, value)

Changes a recognized configuration value in memory.

lexicon.set_config(
"precache",
"YES"
)

Unknown configuration names are ignored.

This function does not automatically save the value.

lexicon.save_config()

Writes the current Lexicon configuration to config.ini .

lexicon.save_config()

lexicon.load_config()

Reloads Lexicon configuration values from config.ini .

lexicon.load_config()

Transliteration API

Lexicon exposes transliteration support through:

lexicon.transliterator

Most plugins do not need to call this API directly. Strings returned by fetch() are transliterated automatically when configured.

lexicon.transliterator.transliterate_for_display(str, lang_code)

Transliterates a string when its expected glyph family differs from the font atlas currently loaded by the game.

local safe_text =
lexicon.transliterator.transliterate_for_display(
"Français",
"fr"
)

When transliteration is disabled or unnecessary, the original string is returned.

Non-string values are returned unchanged.

lexicon.transliterator.normalize_lang_code(code)

Normalizes a locale code.

local code =
lexicon.transliterator.normalize_lang_code(
"PT_BR"
)

-- "pt-br"

Normalization includes:

lexicon.transliterator.register_glyph_family(lang_code, family)

Associates a locale code with a glyph family.

lexicon.transliterator.register_glyph_family(
"nl",
"latin_extended"
)

An existing mapping is not overwritten.

This is an advanced extension API.

lexicon.transliterator.register_translit e rator_service (family, table)

Registers a transliteration table for a glyph family.

lexicon.transliterator.register_transliterator_service(
"custom_family",
{
["original"] = "replacement",
}
)

This is an advanced extension API.

lexicon.transliterator.add_transliteration_char_pairing(original, replacement, transliterator_name)

Adds one replacement pairing to an existing transliterator.

lexicon.transliterator.add_transliteration_char_pairing(
"é",
"e",
"latin_extended"
)

This is an advanced extension API.

Babel Compatibility

lexicon.register() automatically detects legacy Babel translation files.

A Babel file is recognized when:

Example legacy file:

[babel]
0=English
1=Open
2=Close

Legacy files are imported into Lexicon’s registry and fully cached.

This compatibility layer allows older translation packs to continue functioning while plugins transition to the Lexicon format.

New translation files should use the [lexicon] format.

Recommended Plugin Pattern

local lexicon
local lexicon_page

local lstr = function(id, default)
if not lexicon or not lexicon_page then
return default
end

return lexicon.fetch(
lexicon_page,
id,
default
)
end

local lex
icon_ready = function()
lexicon = lib.get_class(
"lexicon",
"0"
)

lexicon_page = lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/en.ini"
)

lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/es.ini"
)

lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/fr.ini"
)
end

lib.require({
{
name = "lexicon",
version = "0",
},
}, lexicon_ready)

Then:

local button = iup.stationbutton {
title = lstr(1, "Open"),
}

Because the default string is supplied at each call, the plugin remains usable even when:

API Summary

Normal plugin-author API

lexicon.register()
lexicon.fetch()
lexicon.retrieve()

lexicon.get_primary_locale()
lexicon.get_secondary_locale()
lexicon.get_safe_locale()

lexicon.get_support_list()
lexicon.is_supported()
lexicon.get_language()

User-selection API

lexicon.set_primary_locale()
lexicon.set_secondary_locale()

lexicon.interface.locale_selector()
lexicon.interface.locale_selector_compact()
lexicon.interface.locale_selector_dialog()

lexicon.open()

Advanced API

lexicon.get_config_list()
lexicon.get_config()
lexicon.set_config()
lexicon.save_config()
lexicon.load_config()

lexicon.transliterator.*

Debug or implementation fields

The public class may currently expose fields such as:

lexicon.debug
lexicon.CCD1
lexicon.smart_config
lexicon.manifest
lexicon.commands

These should not be treated as stable translation-library API unless explicitly documented as such.