Lexicon is a translation and locale-selection library for Vendetta Online plugins.
It allows plugins to:
register one or more translation files;
retrieve translated strings using numeric or string keys;
provide a fallback string when no translation is available;
follow the user’s preferred and secondary locale choices;
inspect Lexicon-supported languages;
embed Lexicon’s language-selection interface;
import older Babel-format translation files.
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.
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
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.
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")
Lexicon translation files use the [lexicon] section.
[lexicon]
code=en
lang=English
flag=flag.png
fallback=
1=First translated string
2=Second translated string
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.
The human-readable name of the language.
lang=Français
This name is displayed in Lexicon’s language-selection interface.
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.
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 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.
Registers one translation file.
local fast_id, error_message = lexicon.register(
"myplugin",
"1.0.0",
plugin_path .. "lang/en.ini"
)
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.
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
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.
Retrieves a translated string using the numeric lookup ID returned by register() .
local value = lexicon.fetch(
page_id,
3,
"Plugin settings"
)
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.
A translated string or default_value .
Lexicon searches for a usable locale in this general order:
the user’s primary locale;
the primary locale’s declared fallback;
the user’s safe or secondary locale;
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.
local lstr = function(id, default)
return lexicon.fetch(page_id, id, default)
end
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"
)
entry_id
Registered translation-page ID.
entry_version
Registered translation-page version.
read_key
Translation key.
default_value
Fallback string.
A translated string or default_value .
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.
Lexicon distinguishes between two user locale choices.
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.
The safe fallback language.
The secondary locale is intended to be compatible with the game’s available locale/font support.
Returns the current primary locale code.
local code = lexicon.get_primary_locale()
Example result:
"fr"
Returns the current secondary locale code.
local code = lexicon.get_secondary_locale()
Returns the locale Lexicon considers safe for the game’s currently available language support.
local code = lexicon.get_safe_locale()
Lexicon prefers:
the primary locale when it is game-supported;
otherwise the secondary locale when it is game-supported;
otherwise the game’s current locale.
Sets the preferred locale.
local success, error_message =
lexicon.set_primary_locale("fr")
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.
Sets the secondary fallback locale.
local success, error_message =
lexicon.set_secondary_locale("en")
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
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.
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")
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
Returns metadata for a supported locale.
local language = lexicon.get_language("fr")
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,
}
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.
Lexicon exposes reusable IUP language-selection controls through:
lexicon.interface
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.
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.
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,
})
Opens Lexicon’s default language-selection dialog.
lexicon.open()
This is equivalent to:
lexicon.interface.locale_selector_dialog()
These functions expose Lexicon’s own configuration table.
Most plugins should use the locale-selection functions instead of modifying configuration values directly.
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
Returns a configuration value.
local enabled =
lexicon.get_config("do_translit")
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.
Writes the current Lexicon configuration to config.ini .
lexicon.save_config()
Reloads Lexicon configuration values from config.ini .
lexicon.load_config()
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.
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.
Normalizes a locale code.
local code =
lexicon.transliterator.normalize_lang_code(
"PT_BR"
)
-- "pt-br"
Normalization includes:
conversion to lowercase;
replacement of underscores with hyphens;
selected aliases such as jp → ja and ua → uk .
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.
Registers a transliteration table for a glyph family.
lexicon.transliterator.register_transliterator_service(
"custom_family",
{
["original"] = "replacement",
}
)
This is an advanced extension API.
Adds one replacement pairing to an existing transliterator.
lexicon.transliterator.add_transliteration_char_pairing(
"é",
"e",
"latin_extended"
)
This is an advanced extension API.
lexicon.register() automatically detects legacy Babel translation files.
A Babel file is recognized when:
no [lexicon] code value is present; and
a valid [babel] 0 language-name entry exists.
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.
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:
Lexicon has not loaded;
registration failed;
the preferred language is unavailable;
the requested key is missing.
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()
lexicon.set_primary_locale()
lexicon.set_secondary_locale()
lexicon.interface.locale_selector()
lexicon.interface.locale_selector_compact()
lexicon.interface.locale_selector_dialog()
lexicon.open()
lexicon.get_config_list()
lexicon.get_config()
lexicon.set_config()
lexicon.save_config()
lexicon.load_config()
lexicon.transliterator.*
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.