SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Filterscripts > Includes

Thread Tools Display Modes
Old 07/10/2017, 01:34 PM   #1
Huge Clucker
IllidanS4's Avatar
Join Date: Feb 2013
Posts: 344
Reputation: 245
Default i_loc - Reference-based fast lightweight script localization system


This include provides a way to localize your script, i.e. present messages in different languages to different players, based on their language setting. This include can be used for gamemodes and filterscripts of any size, and doesn't require additional files. All translations will be stored in the AMX file.

I tried to come up with the easiest way to add localization to an already established script, and found a possible solution. In Pawn, all global variables have a unique address representing them, and if I get this address, I can use it to assign an identity to any variable, or any global string allocated in Pawn. Thanks to this, you don't have to specify any "ID" to represent each text in your script, and no string comparison is done when looking for translation.

Before you include this in your script, you have to define LOC_MAX_TEXTS and LOC_NUM_LOCALIZATIONS. LOC_MAX_TEXTS is the maximum number of localized texts in your script; if you set it too low, the include will produce an error if you try to register more translations. LOC_NUM_LOCALIZATIONS is the number of localizations you wish to use in your script (not counting the default one).

In addition, you can specify a number of optional constants. LOC_MAX_TEXT_LENGTH (default 144) must be set if you plan to use larger strings. As the player's selected language is stored in a PVar, you can set LOC_LANG_PVAR to change the PVar name, or LOC_LANG_FUNC to specify a different method of obtaining player's language. LOC_FILTER_FUNC can be defined for a case when a replacement is not available, and you want to process the message in some other way. You can also define LOC_PACKED to specify the default parameter for other functions.

All localizable strings must be defined globally, and only passed via their variables. Moving all your texts to one place will make your script more consistent and well-arranged, and if you reuse some strings, they will not require more memory than they need.

//Mandatory constants
#define LOC_MAX_TEXTS 4 //if you try to use more than 4 texts, an error is produced and the script is halted
#define LOC_NUM_LOCALIZATIONS 2 //use 2 additional languages

#include ""

//Do not use "stock". This will inform you if your text is not in use. With "const", you will not accidentally modify the text.
new const TEXT_WELCOME[] = "Welcome!";
new const TEXT_YES[] = "Yes.";
new const TEXT_NO[] = "No.";
new const TEXT_GOODBYE[] = "Goodbye!";

//Optionally use constants for language identifiers.
#define LANG_ENGLISH 0
#define LANG_GERMAN 1
#define LANG_FRENCH 2

//In this function, we register all translations for the texts. This should be called exactly once in your script.
stock RegisterTranslations()
    //These in-line defines help maintain the code. You can call "RegisterTranslation" directly, but this will make your code smaller and easier to understand.

    #define LOC[%0,%1] RegisterTranslation(LANG_GERMAN,TEXT_%0,%1)
    LOC[WELCOME, "Wilkommen!"];
    LOC[YES, "Ja."];
    LOC[NO, "Nein."];
    LOC[GOODBYE, "Auf Wiedersehen!"];
    #undef LOC
    #define LOC[%0,%1] RegisterTranslation(LANG_FRENCH,TEXT_%0,%1)
    LOC[WELCOME, "Salut!"];
    LOC[YES, "Oui."];
    LOC[NO, "Non."];
    LOC[GOODBYE, "Au revoir!"];
    #undef LOC

public OnFilterScriptInit()
    SetPlayerLanguage(0, LANG_ENGLISH); //player 0 will get English messages
    SetPlayerLanguage(1, LANG_GERMAN); //player 1 will get German messages
    SetPlayerLanguage(2, LANG_FRENCH); //player 2 will get French messages
    SendClientMessageToAllLoc(-1, TEXT_WELCOME);
"Welcome!" is displayed to player 0, player 1 sees "Wilkommen!", and player 2 sees "Salut!"

RegisterTranslation(language, const text[], const replacement[LOC_MAX_TEXT_LENGTH])
Registers a new replacement text for a specific language. language must be between 1 and LOC_NUM_LOCALIZATIONS, and you cannot use 0 (the default language). If you attempt to register over an already existing translation, it will be modified.

SetPlayerLanguage(playerid, language)
Sets a player's language. Only available when LOC_LANG_FUNC is not specified.

Returns a player's language. Always available.

GetLocText(playerid, const text[], rettext[], bool:packed=LOC_PACKED, maxlength=sizeof(rettext))
Gets the replacement of a text, for a specific player, if possible. On success, returns true and fills rettext. If packed is specified, the result string is packed (packed strings save ~75 % of memory).

LocText(playerid, const text[], bool:packed=LOC_PACKED)
Returns the localized text, for a specific player, or the one passed in text. The default buffer is used.

GetTextReplacement(language, const text[], rettext[], bool:packed=LOC_PACKED, maxlength=sizeof(rettext))
Gets the replacement of a text, for a specific language, if possible. On success, returns true and fills rettext.

TextReplacement(language, const text[], bool:packed=LOC_PACKED)
Returns the localized text, for a specific language, or the one passed.

SendClientMessageLoc(playerid, color, const message[])
Sends a localized message to a player.

SendClientMessageToAllLoc(color, const message[])
Sends a localized message to all players.

SendClientMessageFormatLoc(playerid, color, const format[], {Float,_}:...)
Sends a localized formatted message to a player. SendClientMessageFormat must be available to use this function.

GameTextForPlayerLoc(playerid, const string[], time, style)
Displays a localized text for a player.

If you define LOC_LANG_FUNC, it must have this signature, and return the player's language.

LOC_FILTER_FUNC(language, const text[], rettext[LOC_MAX_TEXT_LENGTH])
LOC_FILTER_FUNC must be defined with this signature. It should return true if the text was modified, or false to use the original text in caller functions.

If you do not specify any of the optional constants, they will be defined after you include the script.

At the top of this topic.
Yet Another Lua Plugin
Long Function Names running Cinematic Mode
IllidanS4 is offline   Reply With Quote
Old 07/10/2017, 01:55 PM   #2
StrikerZ's Avatar
Join Date: Mar 2016
Location: Vikendi
Posts: 1,103
Reputation: 154
Default Re: i_loc - Reference-based fast lightweight script localization system

Awesome one!
It could be handy for multi-language servers.
StrikerZ is offline   Reply With Quote

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Include] [INC] SII 2.0.6 - Fast cache based INI Reader/Writer [DRuG]Slick Includes 97 02/07/2017 05:23 PM
Weed System Help Fast In need it fast Toxik Scripting Help 1 02/05/2015 07:31 AM
Where would you like to see a roleplay script based upon? LivingLikeYouDo Everything and Nothing 19 22/12/2014 03:45 PM
[Tool/Web/Other] jS Web Based Model Viewer (SA-MP REFERENCE) Shoulen Tools and Files 4 01/05/2014 05:26 PM
Red County Based Script Lamare Scripting Help 6 16/06/2013 09:41 PM

All times are GMT. The time now is 03:06 PM.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.