Skip to content

Localization ​

Group lang · 14 exports · from forks/gamexueren/scripthook.h (framework 1.0-beta7-wildm1, SH_API_VERSION 2)

Every piece of text a player can read goes through one lookup.

**Keys.** A key starting with '@' is a stable ID ("@camo.page.visibility"); anything else is a literal and is its own key. IDs survive a renamed row or menu title - which is what the old "[lang.<menu title>]" scheme could not - and a literal is how a plugin whose source you do not have is translated.

**Sources**, in order:

  1. plugins\<owner>\lang.ini, section [<language>] (the owner's)
  2. <gamedir>\lang.ini, section [<language>] (shared override)
  3. the compiled-in baseline this module declared with ShLangDeclare, for the active language
  4. the same baseline, for "en-US"
  5. an ID with no text anywhere is shown readable ("@a.b" -> "A B") and logged once; a literal falls through to itself

A lang.ini row overrides the baseline for that one key, so a file only needs the lines it changes. Nothing in the framework ever writes a lang.ini: the settings file is ours, the text is yours.

Language codes are standard BCP-47 tags ("zh-CN", "en-US") and are compared case-insensitively and exactly. [Settings] Language is the active language, [Settings] Languages the list the picker shows (default: the languages this build ships text for).

ExportSummary
ShLangDeclareDeclare this module's text for ONE language; call once per language (call again later to add a language - code that already declares two needs no change).
ShLangBuiltinOne of the languages this build ships text for, in declaration order.
ShLangExportFrameworkWrite the framework's own menu text out as lang.ini in the game folder, in the language in force.
ShLangExportPluginsThe same, for every installed plugin's own lang.ini, beside its .asi.
ShLangLabelThe label to show for a language code: its [LanguageNames] entry when a lang.ini carries one, else the code itself.
ShLangTextTranslate one key for one owner (NULL or "" = framework text).
ShLangHas1 when a source can answer for this key: a lang.ini row or a baseline row, in the active language or in en-US.
ShLangTranslate framework text: the same as ShLangText(NULL, text).
ShLangForRetained spellings for callers that still pass a scope.
ShLangForOwnedSee ShLangFor.
ShLangMatchThe framework's own language-code comparison, for callers that keep a code of their own: standard BCP-47 tags, case-insensitive.
ShLangGetThe active language, from [Settings] Language.
ShLangPickLineInternal, for the loader: one line saying where this session's menu language came from, on the run that picked it because the settings file had no [Settings] Language= row.
ShLangSetSwitch the active language now: what was read for the old language is dropped and the next lookup reads the files again, so the menu - which translates as it captures - is in the new language on the next frame.

ShLangDeclare ​

c
SH_API int ShLangDeclare(const char *owner, const char *lang,
                         const ShText *rows, int n);

Declare this module's text for ONE language; call once per language (call again later to add a language - code that already declares two needs no change). rows must stay alive for the life of the process: a static const array is what this is for. owner NULL or "" means the framework. The languages declared here are what ShLangBuiltin reports and what [Settings] Languages falls back to. Returns 1 when kept.

scripthook.h, line 3650

ShLangBuiltin ​

c
SH_API int ShLangBuiltin(int i, char *buf, int size);

One of the languages this build ships text for, in declaration order. Fills the tab-separated pair "code<TAB>label" and returns 1; 0 when i is out of range or buf is too small.

scripthook.h, line 3655

ShLangExportFramework ​

c
SH_API int ShLangExportFramework(void);

Write the framework's own menu text out as lang.ini in the game folder, in the language in force.

Filled in, never rewritten. A key already in that section keeps whatever value it has - that row is the player's translation, and pressing this a second time must not cost it. Only what is missing is appended, so a file that is complete is not touched at all: no write, no changed timestamp. Every other language section is left alone.

The write lands through lang.ini.tmp and a rename, so a failure part way leaves the file as it was. There is no .bak, because there is no state in which the original is half-written.

A key with no text in this language falls back to en-US, then to the key itself - for a plugin with no compiled-in table at all the key IS the English word, so that last step is what fills its rows.

Returns the number of files written; 0 when everything was already complete, or when there is nothing to write.

scripthook.h, line 3675

ShLangExportPlugins ​

c
SH_API int ShLangExportPlugins(void);

The same, for every installed plugin's own lang.ini, beside its .asi. Plugins that share a folder share one file, which is how the loader reads them anyway.

scripthook.h, line 3679

ShLangLabel ​

c
SH_API const char *ShLangLabel(const char *code);

The label to show for a language code: its [LanguageNames] entry when a lang.ini carries one, else the code itself. Never NULL.

scripthook.h, line 3682

ShLangText ​

c
SH_API const char *ShLangText(const char *owner, const char *key);

Translate one key for one owner (NULL or "" = framework text). Never NULL and never a failure: text that is missing everywhere comes back readable rather than empty.

scripthook.h, line 3687

ShLangHas ​

c
SH_API int ShLangHas(const char *owner, const char *key);

1 when a source can answer for this key: a lang.ini row or a baseline row, in the active language or in en-US. Ask this before showing text that must stay empty when there is none (a hint line, say): ShLangText always returns something, which is right for a label and wrong for a line that takes room.

scripthook.h, line 3694

ShLang ​

c
SH_API const char *ShLang(const char *text);

Translate framework text: the same as ShLangText(NULL, text).

scripthook.h, line 3697

ShLangFor ​

c
SH_API const char *ShLangFor(const char *scope, const char *text);

Retained spellings for callers that still pass a scope. The scope is ignored - a key says what text a row gets, not a menu path.

scripthook.h, line 3700

ShLangForOwned ​

c
SH_API const char *ShLangForOwned(const char *owner,
                                  const char *scope,
                                  const char *text);

Documented together with ShLangFor just above.

scripthook.h, line 3701

ShLangMatch ​

c
SH_API int ShLangMatch(const char *a, const char *b);

The framework's own language-code comparison, for callers that keep a code of their own: standard BCP-47 tags, case-insensitive.

scripthook.h, line 3706

ShLangGet ​

c
SH_API const char *ShLangGet(void);

The active language, from [Settings] Language.

scripthook.h, line 3708

ShLangPickLine ​

c
SH_API int ShLangPickLine(char *buf, int size);

Internal, for the loader: one line saying where this session's menu language came from, on the run that picked it because the settings file had no [Settings] Language= row. Returns 0 - and empties buf - on every other run.

scripthook.h, line 3713

ShLangSet ​

c
SH_API int ShLangSet(const char *code);

Switch the active language now: what was read for the old language is dropped and the next lookup reads the files again, so the menu - which translates as it captures - is in the new language on the next frame. Text that was already written into a line (a status line, a toast) is put away instead of left in the old language; a page that keeps its own line current fills it again on the next tick. This does not write scripthook.ini: the caller decides whether to persist the choice.

scripthook.h, line 3721

WildM is an independent community project. It is not affiliated with or endorsed by Ubisoft. Ghost Recon Wildlands is a trademark of Ubisoft Entertainment.