Yet another multiple languages system.
This language system is designed for open.mp - Most of it could be made compatible with SA-MP, except using in-memory SQLite database (unless if there's a plugin I don't know about), but highly discouraged since that would be very slow.
- Uses in-memory SQLite database
- Use embedded colour names in language files (eg.
{YELLOW}[NOTICE] {WHITE}Hello world!
) - Languages can be added/removed/modified without restarting the server
- Uses multiple files - No huge single file please
- Works best with YSI, but works without it (biggest drawback: no variable arguments if not using YSI)
Language directory
A directory inside scriptfiles/languages
, named as languageCode_languageName
, that holds all language files of that language.
Language code
A two-letter code of a language. See ISO 639, Set 1
Language name
The full name of a language
Language file
A single file inside a language directory, or language sub-directory
Table
Refers to a single language file from runtime perspective.
Function descriptions refer to table
because data is fetched from an SQLite database (which uses tables), and not directly from the files.
Identifier
Entry in a table/language file that identifies a single string.
- Including the language system
- Compile options
- Embedded colour names
- Adding language data
- Fetching language data
- Make sure you're using open.mp, the provided 3.10.11 compiler and that you have the dependencies listed in
dependencies.txt
- Make sure
omp_language.inc
is in your includes directory - Optionally, add
omp_language_colours.inc
to your includes directory (see Embedded colour names) - Make sure
scriptfiles/languages
is added to your server files - Include omp_language:
#include <omp_language>
That's all! <!> Make sure at least one language exist: This language system doesn't support having no languages added and may cause issues. Pointless anyway to include this language system if you're not using any language
Before including omp_language you can set several compile options:
SQLITE_INVALID_HANDLE
Since open.mp doesn't have a definition for this, it's added by this include.
Default value if not defined: (DB:-1)
LANGUAGE_MAX_CONTENT_LENGTH
Defines the maximum allowed length of language strings.
This sets array sizes of retrieved language strings and the size of the VARCHAR column in the language tables.
Default value if not defined: (1024)
LANGUAGES_MAX
Defines the maximum amount of languages that can be added.
Default value if not defined: (4)
LANGUAGE_DEFAULT
Defines the default server language.
<!> Ultimately the default language is stored to a variable. If this given language does not exist, the default language is changed to the first available language! (language at index 0)
Default value if not defined: "en"
LANGUAGE_SQLITE_PERSISTENT_DATA
Define this to create an on-disk database file.
<!> Only use this to investigate the language database (since there is no sqlite shell)
<!> SIGNIFICANTLY slower than using in-memory database. Do NOT use this in production!
LANGUAGE_SQLITE_PERSISTENT_FILE
If LANGUAGE_SQLITE_PERSISTENT_DATA
is defined, this definition is the name of the created language database.
Default value if not defined: "languages.db"
DIALOG_SELECT_LANGUAGE
If YSI is not used (or at least if y_dialog and y_inline are not used), the default ShowPlayerDialog()
and OnDialogResponse()
are used (instead of Dialog_ShowCallBack()
and an inline on dialog response callback).
Since those require a dialog ID, this sets that dialog ID. Only effective if y_dialog or y_inline is not included.
Default value if not defined: (1)
LANGUAGE_NO_BUILD_MESSAGE
By default, when the language database is built some messages are printed:
[Info] ===== Building language database =====
[Info] Found 2 language(s):
[Info] 0: (en) English
[Info] 1: (nl) Nederlands
[Info] > Adding language files to language database
[Info] >> Adding data for language "English"...
[Info] >> Adding data for language "Nederlands"...
[Info] ===== Language database built =====
If you don't want that, simply define LANGUAGE_NO_BUILD_MESSAGE
LANGUAGE_NO_YSI
Define this to prevent inclusion of any YSI include.
LANGUAGE_NO_YSI_HOOKS
Define this to prevent inclusion of y_hooks.
LANGUAGE_NO_YSI_VA
Define this to prevent inclusion of y_va.
LANGUAGE_NO_YSI_FOREACH
Define this to prevent inclusion of y_foreach.
LANGUAGE_NO_YSI_DIALOG
Define this to prevent inclusion of y_dialog and y_inline.
If not defined, omp_language will attempt to include both y_dialog and y_inline.
The language files are added in run-time and therefor macros (eg COL_RED
) can't be used.
Since it would be very inconvenient to use hexadecimal numbers all the time, this language system allows using colour names.
There is a default set of language colours, included in file includes/omp_language_colours.inc
. This creates a constant array called gLanguageColours
.
You can simply use these colours, or define the array yourself before including omp_language.
<!> You can use this language system without using this array, though that will throw a compile warning.
If gLanguageColours exists, all colour names are translated to colour numbers when creating the database.
First of all, to add a language, create a directory named languageCode_languageName
(eg en_English
) inside scriptfiles/languages
.
Language name is preferably in its own language (so nl_Nederlands
and de_Deutsch
, not nl_Dutch
and de_German
).
Inside a language directory, you can create text files (.txt) or directories.
When calling a language, you can get content from those files using fileName
or directoryName-fileName
.
Take this directory tree:
scriptfiles/
├─ languages/
│ ├─ en_English/
│ │ ├─ command/
│ │ │ ├─ admin.txt
│ │ │ ├─ player.txt
│ │ ├─ global.txt
To retrieve a string from global.txt
you would use "global"
. To retrieve one from admin.txt
inside the command
directory, you would use "command-admin"
.
<!> Only one sub-directory is supported, creating another directory inside a sub-directory (in this case, command
) will not work: Those files will not be added.
To add strings to a language file, simply create an identifier, and then the string attached to that identifier. Use a space (or preferably one or more tabs) to seperate those two.
<!> Empty lines and lines starting with #
are ignored. As are invalid lines (single words)
For example:
## This line is ignored and thus functions as a comment.
# This is the prefered way of adding entries: Identifier fully capitalized, using words and underscores only, identating all strings on the same column (? did I call that right ?)
MY_IDENTIFIER This is my identifier!
HELLO_WORLD Hello {GREEN}world!
# However, this is also valid:
_foo BAR
$myIdentifier0 This is my ugly identifier!
# Even this is valid:
Hello world!
Lorem ipsum dolor sit amet
# This is invalid:
TEST
NOTE: Make sure that all language directories have the same sub directories and files, and the same identifiers!
NOTE 2: Since version 1.03, any file extension (or none) is valid. But .txt
is still preferred and recommended.
I'll keep this short, since all available functions are described below.
To fetch data from the database, use Language_Get()
or Player_Language_Get()
To set/get language of a player, use Player_SelectLanguage()
or Player_SetLanguage()
and Player_GetLanguage()
To get amount of available languages and their language codes and names, use Language_Count()
and Language_GetIDFromData()
. For example, to print all available languages to the server log:
for (new i = 0, j = Language_Count(); i < j; i++)
{
new languageCode[3], languageName[32];
Language_GetDataFromID(i, languageCode, languageName);
PrintF("> %s(%s)", languageName, languageCode);
}
For some more examples, see the example directory in this repository.
Yes.
- Even though support for not using YSI is added, it wasn't tested thoroughly and may not be stable
- Using YSI makes life much easier thanks to variable arguments, which is a standard in open.mp anyway
- Language_Count()
- Language_GetDataFromID()
- Language_GetIDFromData()
- Language_Exists()
- LanguageDB_Build()
- Language_Get()
- Player_GetLanguage()
- Player_SetLanguage()
- Player_SelectLanguage()
- Player_Language_Get()
- SendClientLanguageMessage()
- SendClientLanguageMessageToAll()
- GameLanguageTextForPlayer()
- GameLanguageTextForAll()
- OnPlayerSelectLanguage()
Language_Count()
Returns the amount of available languages
Parameters
None
Returns
(int) Amount of available languages
Notes
None
Related functions/callbacks
bool:Language_GetDataFromID(const languageId, string:languageCode[], string:languageName[], const lenLanguageCode = sizeof(languageCode), const lenLanguageName = sizeof(languageName))
Retrieves language code and language name from given language ID
Parameters
const languageId
: Language ID to get data from
string:languageCode[]
: (reference) Array to store language code in
string:languageName[]
: (reference) Array to store language name in
const lenLanguageCode
: (optional) Size of array languageCode[]
const lenLanguageName
: (optional) Size of array languageName[]
Returns
(bool) true: Language exists, data retrieved. false: Given language does not exist
Notes
None
Related functions/callbacks
Language_GetIDFromData(const string:search[])
Gets the language ID by looking up language code or language name.
Parameters
const string:search[]
: Language to get the ID of, using language code or language name.
Returns
(int) Language ID, or LANGUAGE_INVALID_ID if given language does not exist
Notes
<!> search[]
must be the full language code or name
Case insensitive
Related functions/callbacks
bool:Language_Exists(const string:search[])
Checks if given language exists
Parameters
const string:search[]
: Language to check, using language code or language name.
Returns
(bool) true: Language exists. false: Language does not exist
Notes
<!> search[]
must be the full language code or name
Case insensitive
Related functions/callbacks
bool:LanguageDB_Build()
Builds or rebuilds the language database.
Automatically used on script initialization. Can be used to rebuild the language database during runtime (in an admin command), useful if languages were modified.
Parameters
None
Returns
(bool) true: Language database created. false: Directory "scriptfiles/languages" does not exist
Notes
<!> Returns true if no languages were added (which happens if directory "scriptfiles/languages" is empty or doesn't have valid language directory names)
Related functions/callbacks
None
string:Language_Get(const string:languageCode[], const string:table[], const string:identifier[], OPEN_MP_TAGS:...)
Retrieves a language string. Optionally formats retrieved string (only when using YSI)
Parameters
const string:languageCode[]
: Language to get content from, using the language code
const string:table[]
: Table to get the content from
const string:identifier[]
: String to retrieve from given language code and table
OPEN_MP_TAGS:...
: (optional) Used for formatting the string if format specifiers were used. Only works when using YSI
Returns
(string) Retrieved (and formatted) string
Notes
<!> If given language, table or identifier doesn't exist, it returns [languageCode]table:identifier
(eg. [en]global:SOME_IDENTIFIER
)
Related functions/callbacks
string:Player_GetLanguage(const playerid)
Returns the language of a player
Parameters
const playerid
: Player to get language from
Returns
(string) Language code the player is using
Notes
If no language was selected for the player, or if the player doesn't exist, it returns the server default language
Related functions/callbacks
bool:Player_SetLanguage(const playerid, const string:language[])
Sets the language for a player
Parameters
const playerid
: Player to set the language for
const string:language[]
: Language to set, using language code
Returns
(bool) true: Language was set for the player. false: Language unchanged: Player isn't connected or given language doesn't exist
Notes
None
Related functions/callbacks
void:Player_SelectLanguage(const playerid)
Shows a dialog to the player displaying all available languages, allowing them to change their language to one of them.
Parameters
const playerid
: Player to show the dialog to
Returns
Nothing
Notes
If only one language is available, no dialog is displayed and their language is set to that language.
After changing their language, OnPlayerSelectLanguage()
is called.
Related functions/callbacks
string:Player_Language_Get(const playerid, const string:table[], const string:identifier[], OPEN_MP_TAGS:...)
Retrieves a language string for a player. Optionally formats retrieved string (only when using YSI)
Parameters
const playerid
: Player to fetch the string for (or rather, fetch a string, using the selected language of given player)
const string:table[]
: Table to get the content from
const string:identifier[]
: String to retrieve from given language code and table
OPEN_MP_TAGS:...
: (optional) Used for formatting the string if format specifiers were used. Only works when using YSI
Returns
(string) Retrieved (and formatted) string
Notes
<!> If the player's language doesn't exist or if given table or identifier doesn't exist, it returns [languageCode]table:identifier
(eg. [en]global:SOME_IDENTIFIER
)
Related functions/callbacks
bool:SendClientLanguageMessage(const playerid, const colour, const string:table[], const string:identifier[], OPEN_MP_TAGS:...)
Sends a client message to the player using the language system
Parameters
const playerid
: Player to send the message to
const colour
: Colour of the message
const string:table[]
: Language table to get content from
const string:identifier[]
: String to retrieve from the language table
OPEN_MP_TAGS:...
: (optional) Used for formatting the string if format specifiers were used. Only works when using YSI
Returns
(bool) Output of SendClientMessage(), thus true: Message was sent or false: Player isn't connected
Notes
None
Related functions/callbacks
bool:SendClientLanguageMessageToAll(const colour, const string:table[], const string:identifier[], OPEN_MP_TAGS:...)
Sends a client message to all players, displaying the message in the selected language of each individual player
Parameters
const colour
: Colour of the message
const string:table[]
: Language table to get content from
const string:identifier[]
: String to retrieve from the language table
OPEN_MP_TAGS:...
: (optional) Used for formatting the string if format specifiers were used. Only works when using YSI
Returns
(bool) Output of SendClientMessage(), thus always returns true
Notes
<!> If you're not using YSI, and the to-be-sent text has format specifiers, you can't use this function. Instead you'll have to loop through each player and use SendClientLanguageMessage()
for each player.
Related functions/callbacks
bool:GameLanguageTextForPlayer(const playerid, const string:table[], const string:identifier[], const time, const style, OPEN_MP_TAGS:...)
Sends a game text to a player using the language system
Parameters
const playerid
: Player to show the gametext for
const string:table[]
: Language table to get content from
const string:identifier[]
: String to retrieve from the language table
const time
: The duration of the text being shown in milliseconds
const style
: The style of text to be displayed
OPEN_MP_TAGS:...
: (optional) Used for formatting the string if format specifiers were used. Only works when using YSI
Returns
(bool) Output of GameTextForPlayer(), true: Function executed or false: Player not connected or gametext string is null
Notes
None
Related functions/callbacks
void:GameLanguageTextForAll(const string:table[], const string:identifier[], const time, const style, OPEN_MP_TAGS:...)
Sends a game text to all players using the language system, displaying the gametext in the selected language of each individual player
Parameters
const string:table[]
: Language table to get content from
const string:identifier[]
: String to retrieve from the language table
const time
: The duration of the text being shown in milliseconds
const style
: The style of text to be displayed
OPEN_MP_TAGS:...
: (optional) Used for formatting the string if format specifiers were used. Only works when using YSI
Returns
Nothing
Notes
<!> If you're not using YSI, and the to-be-sent text has format specifiers, you can't use this function. Instead you'll have to loop through each player and use GameLanguageTextForPlayer()
for each player.
Related functions/callbacks
OnPlayerSelectLanguage(playerid)
Callback that is called after a player changed their language from the dialog
Parameters
playerid
: Player that changed their language
Notes
<!> Only called when using Player_SelectLanguage()
, not when Player_SetLanguage()
was used.
Related functions/callbacks