Difference between revisions of "Stringtable.xml"

From Bohemia Interactive Community
Jump to navigation Jump to search
m
m (Some wiki formatting)
(41 intermediate revisions by 7 users not shown)
Line 1: Line 1:
==Stringtable.xml==
+
{{TOC|side}}
 +
{{Feature | Informative | [[Stringtable.xml]] was introduced with {{arma1}}. For {{ofp}}, see [[Stringtable.csv]].}}
 
String tables are used to make internationalization easier for the game. They are used in addons, missions, and scripts, and are located in the root of the mission or addon folders.
 
String tables are used to make internationalization easier for the game. They are used in addons, missions, and scripts, and are located in the root of the mission or addon folders.
  
Any strings that are used in the game can be kept separate from the code, and can therefore easily be edited and expanded into different languages. Instead of using strings directly in the code, you are using a variable. This variable will then contain the actual string, read from stringtable.xml, with the language that's being read depending on the game settings.
+
Any strings that are used in the game can be kept separate from the code, and can therefore easily be edited and expanded into different languages. Instead of using strings directly in the code, you are using a variable. This variable will then contain the actual string, read from stringtable.xml, with the language that is being read depending on the game settings.
  
=====Example Format:=====
+
 
<syntaxhighlight lang=cpp>
+
== Stringtable Editors ==
 +
 
 +
It is strongly recommended to use a tool to edit the XML file; a selection of Stringtable [[:Category:Community Tools|Community Tools]] can be found in the [[:Category:Community Tools#Localisation Tools|Community Tools - Localisation Tools]] page section.
 +
 
 +
 
 +
== Example ==
 +
 
 +
<syntaxhighlight lang="xml"></syntaxhighlight><!-- so the syntaxhighlight works in the spoiler tag -->
 +
<spoiler text="Show Stringtable.xml example">
 +
<syntaxhighlight lang="xml">
 
<?xml version="1.0" encoding="utf-8" ?>
 
<?xml version="1.0" encoding="utf-8" ?>
 
<Project name="Any Name">
 
<Project name="Any Name">
 
<Package name="Mission One">
 
<Package name="Mission One">
 
<Container name="Some Words">
 
<Container name="Some Words">
<Key ID="str_myTag_Yes">
+
<Key ID="STR_TAG_Yes">
 
<Original>yes</Original>
 
<Original>yes</Original>
 
<English>yes</English>
 
<English>yes</English>
Line 23: Line 33:
 
<Korean>네</Korean>
 
<Korean>네</Korean>
 
<Japanese>はい</Japanese>
 
<Japanese>はい</Japanese>
                                <Chinesesimp>是</Chinesesimp>
+
<Chinesesimp>是</Chinesesimp>
                                <Chinese>是(繁體)</Chinese>
+
<Chinese>是(繁體)</Chinese>
 
</Key>
 
</Key>
<Key ID="str_myTag_No">
+
<Key ID="STR_TAG_No">
 
<Original>no</Original>
 
<Original>no</Original>
 
</Key>
 
</Key>
 
</Container>
 
</Container>
 
<Container name="Another Container">
 
<Container name="Another Container">
<Key ID="str_myTag_another_key">
+
<Key ID="STR_TAG_formatted">
<Original></Original>
 
</Key>
 
<Key ID="str_myTag_formatted">
 
 
<Original>Hello, %1.</Original>
 
<Original>Hello, %1.</Original>
 
</Key>
 
</Key>
<Key ID="str_myTag_structured">
+
<Key ID="STR_TAG_structuredText">
<Original>Some text &amp;lt;t color='%1'&amp;gt;%2&amp;lt;/t&amp;gt;</Original>
+
<Original>Some text &lt;t color='%1'&gt;%2&lt;/t&gt;</Original>
 
</Key>
 
</Key>
 
</Container>
 
</Container>
Line 44: Line 51:
 
</Project>
 
</Project>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
</spoiler>
  
*Replace ''myTag'' in str_myTag_someKey with your OFPEC tag or other means of personal identification so other addon and mission string names won't collide, potentially breaking your mission - this is just good practice
+
{{Feature | Informative | {{hl|Package}} and {{hl|Container}} "groups" are only helpful for organisation and have no impact on the translations; use them for your own sanity.}}
*Package and container names appear to only be for organizational use; use them for your own sanity
+
{{Feature | important | [[Stringtable.xml]] must be saved with '''UTF-8 Encoding''' for international characters to display and save correctly.}}
{{Important|Stringtable.xml must be saved with UTF-8 Encoding for international characters to display and save correctly}}
 
  
=====Naming Key IDs=====
 
If you are planning to use your <tt>stringtable.xml</tt> with scripts only, there are no rules in regards to naming format of Key IDs. [[localize]] and [[isLocalized]] will work with any name, as long as it matches Key ID name in <tt>stringtable.xml</tt>. For example:
 
  
<syntaxhighlight lang=cpp>
+
== Supported languages ==
// stringtable.xml
 
<?xml version="1.0" encoding="utf-8" ?>
 
<Project name="Any Name">
 
<Package name="Mission One">
 
<Container name="Some Words">
 
<Key ID="myCrazyNameTag">
 
<Original>wuga wuga</Original>
 
</Key>
 
</Container>
 
</Package>
 
</Project>
 
</syntaxhighlight>
 
  
<code>// some script
+
{|
[[hint]] [[str]] [[isLocalized]] "myCrazyNameTag"; // true;
+
! {{arma2}} &amp; {{arma2oa}}
[[hint]] [[str]] [[localize]] "myCrazyNameTag"; // "wuga wuga";</code>
+
! {{arma3}}
 +
|-
 +
| style="vertical-align: top" |
  
However, if you are also going to use <tt>stringtable.xml</tt> with configs, you '''must''' use special prefix <tt>$STR</tt> (dollar sign $ followed by uppercase STR) to reference Key ID in config. The Key IDs in <tt>stringtable.xml</tt> will have to start with "str" or "STR" accordingly, case doesn't matter here. For example:
+
{| class="wikitable"
 +
! className
 +
! In-game name
 +
! Note
 +
|-
 +
| English
 +
| '''English'''
 +
|
 +
|-
 +
| Czech
 +
| '''Čeština'''
 +
|
 +
|-
 +
| French
 +
| '''Français'''
 +
|
 +
|-
 +
| Spanish
 +
| '''Español'''
 +
|
 +
|-
 +
| Italian
 +
| '''Italiano'''
 +
|
 +
|-
 +
| Polish
 +
| '''Polski'''
 +
|
 +
|-
 +
| Russian
 +
| '''Русский'''
 +
|
 +
|-
 +
| German
 +
| '''Deutsch'''
 +
|
 +
|-
 +
| Hungarian
 +
| '''Magyar'''
 +
| Partially supported
 +
|-
 +
| Portuguese
 +
| '''Portuguese'''
 +
| Not available in-game
 +
|}
  
<syntaxhighlight lang=cpp>
+
| style="vertical-align: top" |
// stringtable.xml
 
<?xml version="1.0" encoding="utf-8" ?>
 
<Project name="Any Name">
 
<Package name="Mission One">
 
<Container name="Some Words">
 
<Key ID="STRblahblah">
 
<Original>blah</Original>
 
</Key>
 
</Container>
 
</Package>
 
</Project>
 
</syntaxhighlight>
 
  
<syntaxhighlight lang=cpp>
+
{| class="wikitable"
// some config
+
! className
class Test
+
! In-game name
{
+
! Note
word = $STRblahblah;
+
|-
};
+
| English
</syntaxhighlight>
+
| '''English'''
<code>[[hint]] [[str]] [[getText]] ([[configFile]] >> "Test" >> "word"); // "blah"</code>
+
|
 +
|-
 +
| Czech
 +
| '''Čeština'''
 +
|
 +
|-
 +
| French
 +
| '''Français'''
 +
|
 +
|-
 +
| Spanish
 +
| '''Español'''
 +
|
 +
|-
 +
| Italian
 +
| '''Italiano'''
 +
|
 +
|-
 +
| Polish
 +
| '''Polski'''
 +
|
 +
|-
 +
| Portuguese
 +
| '''Português do Brasil'''
 +
|
 +
|-
 +
| Russian
 +
| '''Русский'''
 +
|
 +
|-
 +
| German
 +
| '''Deutsch'''
 +
|
 +
|-
 +
| Korean
 +
| '''한국어'''
 +
|
 +
|-
 +
| Japanese
 +
| '''日本語'''
 +
|
 +
|-
 +
| Chinese
 +
| '''繁體中文'''
 +
| Chinese Traditional
 +
|-
 +
| Chinesesimp
 +
| '''简体中文'''
 +
| Chinese Simplified
 +
|-
 +
| Turkish
 +
| '''Türkçe'''
 +
|
 +
|-
 +
| Swedish
 +
| {{n/a}}
 +
| rowspan="9" | Cannot be set in-game.<br>Edit '''arma3.cfg''' to use that language.
 +
|-
 +
| Slovak
 +
| {{n/a}}
 +
|-
 +
| SerboCroatian
 +
| {{n/a}}
 +
|-
 +
| Norwegian
 +
| {{n/a}}
 +
|-
 +
| Icelandic
 +
| {{n/a}}
 +
|-
 +
| Hungarian
 +
| '''Magyar'''
 +
|-
 +
| Greek
 +
| {{n/a}}
 +
|-
 +
| Finnish
 +
| {{n/a}}
 +
|-
 +
| Dutch
 +
| {{n/a}}
 +
|}
  
By convention, an underscore <tt>_</tt> is added to the prefix <tt>STR_</tt> (<tt>$STR_</tt>). It provides clarity and makes <tt>stringtable.xml</tt> universally compatible with both scripts and configs.
+
|}
  
==Usage==
+
== Key naming convention ==
====Scripts====
 
A string from stringtable.xml can be retrieved and used in a script by using the [[localize]] command:
 
  
<code>[[hint]] ( [[localize]] "str_myTag_Yes" );</code>
+
Same as [[Identifier#Recommendations|global variables]], it is recommended to use a '''{{Color|purple|TAG}}''' to prevent translation collision between mods (e.g {{hl|STR_{{Color|purple|TAG}}_helloThere}}).
  
<code>"Marker1" [[setMarkerTextLocal]] [[localize]] "str_myTag_SiezeTheTown";</code>
 
  
<code>[[hint]] [[format]] [ [[localize]] "str_myTag_formatted", "Dave" ]; // "Hello, Dave."
+
== String Formats ==
&nbsp;
 
// str_myTag_formatted: <Original>Hello, %1.</Original></code>
 
  
 +
Strings stored in the stringtable can be in the following formats:
 +
* Normal text, such as {{hl|Hello there}}
 +
* [[format]] text, such as {{hl|Hello %1}}
 +
* [[Structured Text]], such as {{hl|c= <t size='2'>Hello</t> there}}, '''but''':<br><!--
 +
-->{{Feature | important | The HTML tag characters {{hl|&lt;}} and {{hl|&gt;}} must respectively be encoded as {{hl|&amp;lt;}} and {{hl|&amp;gt;}}.}}<!--
 +
-->{{hl|c= <t size='2'>Hello</t> there}} would then become {{hl|c= &amp;lt;t size='2'&amp;gt;Hello&amp;lt;/t&amp;gt; there}}.
  
The stringtable can also hold [[Structured Text]] xml tags, if the tag characters < > are encoded as {{Inline_code| &amp;lt; < }} and {{Inline_code| &amp;gt; > }}  [http://www.w3schools.com/html/html_entities.asp see: HTML Entities]
 
  
<code>[[hint]] [[parseText]] [[format]] [ [[localize]] "str_myTag_structured", "#FF0000", "with Color!" ]; //show 'with Color!' in Red
+
== Usage ==
&nbsp;
 
// str_myTag_structured: <English>Some text &amp;lt;t color='%1'&amp;gt;%2&amp;lt;/t&amp;gt;</English>
 
// after format & parseText: Some text <t color='#FF0000'>with Color!</t></code>
 
  
 +
=== Script ===
  
====Description.ext====
+
A translation can be retrieved and used in a script by using the [[localize]] command:
Stringtable values can be used in the [[Description.ext]] config by typing the key as such, {{Inline_code| $STR_myTag_keyName }}, and without quotation marks; these will be replaced by the preprocessor:
+
<sqf>
 +
hint localize "STR_TAG_Yes"; // returns "Yes" in English, "Oui" in French, etc.
 +
hint format [localize "STR_TAG_formatted", name player];
 +
hint localize "str_TAG_structuredText"; // casing in scripting does not matter
 +
</sqf>
  
<code>onLoadName = $STR_myTag_missionName;
+
=== Config ===
onLoadMission = $STR_myTag_loadMissionText;
 
overviewText = $STR_myTag_overviewText;
 
overviewPicture = $STR_myTag_overviewImage;
 
</code>
 
  
 +
Whether it is in [[Description.ext]], [[Campaign Description.ext]], Dialogs etc., a translated [[Config]] entry '''must''' use the {{hl|$}} prefix (to an '''uppercase''' {{hl|STR}}) for the engine to look the translation key up:
  
====Dialogs====
+
<syntaxhighlight lang="cpp">
As with Description.ext, the preprocessor will replace the values in configs as long as the key name is formatted correctly (see above) :
+
onLoadName = "$STR_TAG_missionName";
 +
onLoadMission = $STR_TAG_loadMissionText; // works without quotes too - not recommended
 +
overviewText = "$str_TAG_overviewText"; // invalid, will return "$str_TAG_overviewImage" (with $ sign)
 +
</syntaxhighlight>
  
<code>class RscText_1012: RscText
+
The preprocessor will replace {{hl|$STR}} entries with their corresponding Stringtable value.
{
 
idc = 1012;
 
text = $STR_myTag_someLabelText;
 
tooltip = $STR_myTag_someTip;
 
...</code>
 
  
====CfgRadio====
+
=== Editor ===
Stringtables can also be used for sounds and radio sentences in [[Description.ext#cfgRadio|CfgRadio]], also residing in Description.ext:
 
  
<code>class CfgRadio
+
In markers and other [[Eden Editor]] fields (e.g Mission Name), translation keys should be prefixed with {{hl|@}}, without any quotes around - e.g {{hl|@STR_myMarkerName}}. Casing does not matter here either.
{
 
sounds[] = {};
 
class RadioMsg1
 
{
 
name = "";
 
sound[] = {$STR_myTag_sound_RadioMsg1, db-100, 1.0};
 
title = $STR_myTag_RadioMsg1;
 
};
 
};
 
// str_myTag_sound_RadioMsg1: <English>\sound\radiomsg1_en.ogg</English>
 
// <Czech>\sound\radiomsg1_cz.ogg</Czech>
 
// str_myTag_RadioMsg1: <English>I am ready for your orders.</English>
 
</code>
 
  
  
====Multiplayer====
+
== Multiplayer ==
{{Informative|'''Multiplayer Scripts''' should take care in considering implementation when clients and server are likely in varied localizations, and mindful of commands with global effects}}
 
  
A string name could be passed to all clients for localized display:
+
[[Multiplayer Scripting]] should consider that the translation implementation ''should'' ideally happen client-side; clients and server are likely to be configured in a different language, as a server-side call to [[Multiplayer Scripting#Locality|global effect]] text commands (such as [[setMarkerText]]) would set the text in the server's language to everyone.
<code>str_myTag_teamKillers: <English>&amp;lt;t color='#dd1111'&amp;gt;Team Killing is NOT Tolerated&amp;lt;/t&amp;gt;&amp;lt;/ br&amp;gt; and will result in a Permanent Ban!</English>
 
  
// Server
+
Example of client-side translation of a server message:
if ( [[isServer]] ) then {
+
<sqf>
["str_myTag_teamKillers","TAG_fnc_localHint"] [[call]] [[BIS_fnc_MP]];
+
// Server-side
 +
if (isServer) then
 +
{
 +
[nil, nil, rHINT, localize "STR_TAG_myMessage"] call RE; // Arma 2 - server language
 +
[nil, nil, rSPAWN, { hint localize "STR_TAG_myMessage" }] call RE; // Arma 2 - client language
 +
["STR_TAG_myMessage"] remoteExecCall ["TAG_fnc_localHint"]; // Arma 3
 
};
 
};
  
// Clients
+
// Client-side executed function
 
TAG_fnc_localHint = {
 
TAG_fnc_localHint = {
if ( ! [[isDedicated]] ) then {
+
if (hasInterface) then
[[hintSilent]] [[parseText]] ([[localize]] _this);
+
{
 +
// hintSilent parseText (localize _this); // Arma 2
 +
hintSilent parseText (_this call BIS_fnc_localize); // Arma 3
 
};
 
};
 
};
 
};
</code>
+
</sqf>
 +
 
  
<!-- Do not include CSS styling in genuine example
+
== Commands & Functions ==
Example 2:
 
<code style="white-space:pre-wrap;">{{Lorem|}}</code>
 
-->
 
  
==Languages==
+
* [[localize]]
;Arma 3
+
* {{GVI|arma3|0.50|size=0.75}} [[isLocalized]]
:English, Czech, French, Spanish, Italian, Polish, Portuguese, Russian, German, Korean**, Japanese**  ''(**region exclusive)'',繁體中文(Chinese Traditional),简体中文(Chinese Simplified)
+
* {{GVI|arma3|1.00|size=0.75}} [[BIS_fnc_localize]]
;Arma 2 OA
+
* {{GVI|arma3|2.02|size=0.75}} [[getTextRaw]]
:English, Czech, French, Spanish, Italian
 
  
==Comments==
 
  
[[Category:BIS_File_Formats]]
+
[[Category:BIS File Formats]]
[[Category:Arma 3: Editing]]
+
{{GameCategory|arma1|Editing}}
 +
{{GameCategory|arma2|Editing}}
 +
{{GameCategory|arma3|Editing}}

Revision as of 21:36, 18 April 2022

Stringtable.xml was introduced with Armed Assault. For Operation Flashpoint, see Stringtable.csv.

String tables are used to make internationalization easier for the game. They are used in addons, missions, and scripts, and are located in the root of the mission or addon folders.

Any strings that are used in the game can be kept separate from the code, and can therefore easily be edited and expanded into different languages. Instead of using strings directly in the code, you are using a variable. This variable will then contain the actual string, read from stringtable.xml, with the language that is being read depending on the game settings.


Stringtable Editors

It is strongly recommended to use a tool to edit the XML file; a selection of Stringtable Community Tools can be found in the Community Tools - Localisation Tools page section.


Example

Show Stringtable.xml example


Package and Container "groups" are only helpful for organisation and have no impact on the translations; use them for your own sanity.
Stringtable.xml must be saved with UTF-8 Encoding for international characters to display and save correctly.


Supported languages

Arma 2 & Arma 2: Operation Arrowhead Arma 3
className In-game name Note
English English
Czech Čeština
French Français
Spanish Español
Italian Italiano
Polish Polski
Russian Русский
German Deutsch
Hungarian Magyar Partially supported
Portuguese Portuguese Not available in-game
className In-game name Note
English English
Czech Čeština
French Français
Spanish Español
Italian Italiano
Polish Polski
Portuguese Português do Brasil
Russian Русский
German Deutsch
Korean 한국어
Japanese 日本語
Chinese 繁體中文 Chinese Traditional
Chinesesimp 简体中文 Chinese Simplified
Turkish Türkçe
Swedish N/A Cannot be set in-game.
Edit arma3.cfg to use that language.
Slovak N/A
SerboCroatian N/A
Norwegian N/A
Icelandic N/A
Hungarian Magyar
Greek N/A
Finnish N/A
Dutch N/A

Key naming convention

Same as global variables, it is recommended to use a TAG to prevent translation collision between mods (e.g STR_TAG_helloThere).


String Formats

Strings stored in the stringtable can be in the following formats:

  • Normal text, such as Hello there
  • format text, such as Hello %1
  • Structured Text, such as <t size='2'>Hello</t> there, but:
    The HTML tag characters < and > must respectively be encoded as &lt; and &gt;.
    <t size='2'>Hello</t> there would then become &lt;t size='2'&gt;Hello&lt;/t&gt; there.


Usage

Script

A translation can be retrieved and used in a script by using the localize command:

hint localize "STR_TAG_Yes"; // returns "Yes" in English, "Oui" in French, etc. hint format [localize "STR_TAG_formatted", name player]; hint localize "str_TAG_structuredText"; // casing in scripting does not matter

Config

Whether it is in Description.ext, Campaign Description.ext, Dialogs etc., a translated Config entry must use the $ prefix (to an uppercase STR) for the engine to look the translation key up:

onLoadName = "$STR_TAG_missionName";
onLoadMission = $STR_TAG_loadMissionText;	// works without quotes too - not recommended
overviewText = "$str_TAG_overviewText";		// invalid, will return "$str_TAG_overviewImage" (with $ sign)

The preprocessor will replace $STR entries with their corresponding Stringtable value.

Editor

In markers and other Eden Editor fields (e.g Mission Name), translation keys should be prefixed with @, without any quotes around - e.g @STR_myMarkerName. Casing does not matter here either.


Multiplayer

Multiplayer Scripting should consider that the translation implementation should ideally happen client-side; clients and server are likely to be configured in a different language, as a server-side call to global effect text commands (such as setMarkerText) would set the text in the server's language to everyone.

Example of client-side translation of a server message:

// Server-side if (isServer) then { [nil, nil, rHINT, localize "STR_TAG_myMessage"] call RE; // Arma 2 - server language [nil, nil, rSPAWN, { hint localize "STR_TAG_myMessage" }] call RE; // Arma 2 - client language ["STR_TAG_myMessage"] remoteExecCall ["TAG_fnc_localHint"]; // Arma 3 }; // Client-side executed function TAG_fnc_localHint = { if (hasInterface) then { // hintSilent parseText (localize _this); // Arma 2 hintSilent parseText (_this call BIS_fnc_localize); // Arma 3 }; };


Commands & Functions