Difference between revisions of "Stringtable.xml"

From Bohemia Interactive Community
Jump to navigation Jump to search
m (side toc)
(Page refresh)
Line 1: Line 1:
 
{{SideTOC}}
 
{{SideTOC}}
 +
{{Informative | [[Stringtable.xml]] was introduced with {{arma}}. 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.
  
== Stringtable.xml ==
+
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.
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.
 
  
 
== Stringtable Editors ==
 
== Stringtable Editors ==
It's much more comfortable to use a tool to edit the .xml within a GUI. Here's a selection of tools capable of working with stringtable.xml files:
 
  
*[https://github.com/ajvorobiev/StringForge/releases StringForge]
+
It 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.
*[https://github.com/bux/tabler/releases Tabler]
 
*[https://forums.bohemia.net/forums/topic/202181-sqdev-sqf-developing-in-eclipse/ SQDev]
 
*[https://github.com/dedmen/de_stringtabler/releases de_stringtabler]
 
  
  
 +
== Example ==
  
===== Example Format =====
+
<syntaxhighlight lang="xml"></syntaxhighlight><!-- so the syntaxhighlight works in the spoiler tag -->
<syntaxhighlight lang="cpp">
+
<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 38: Line 36:
 
                 <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>
 
</Container>
 
</Package>
 
</Project>
 
</syntaxhighlight>
 
 
 
'''Good practice:'''
 
* 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
 
* Package and container names appear to only be for organizational use; use them for your own sanity
 
{{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">
 
// 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>
 
</Key>
 
</Container>
 
</Container>
Line 80: Line 51:
 
</Project>
 
</Project>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
</spoiler>
  
<code>{{codecomment|// some script}}
+
{{Informative | Package and container names are only for organisational use; use them for your own sanity.}}
[[hint]] [[str]] [[isLocalized]] "myCrazyNameTag"; {{codecomment|// true}}
+
{{Important | [[Stringtable.xml]] must be saved with '''UTF-8 Encoding''' for international characters to display and save correctly.}}
[[hint]] [[str]] [[localize]] "myCrazyNameTag"; {{codecomment|// "wuga wuga"}}</code>
 
 
 
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.
 
{{Informative|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.}}
 
For example:
 
 
 
<syntaxhighlight lang="cpp">
 
// stringtable.xml
 
<?xml version="1.0" encoding="utf-8" ?>
 
<Project name="Any Name">
 
<Package name="Mission One">
 
<Container name="Some Words">
 
<Key ID="STR_myKey">
 
<Original>Hey there</Original>
 
</Key>
 
</Container>
 
</Package>
 
</Project>
 
</syntaxhighlight>
 
 
 
<syntaxhighlight lang="cpp">
 
// config entry
 
class Test
 
{
 
word = $STR_myKey;
 
};
 
</syntaxhighlight>
 
<code>[[hint]] [[str]] [[getText]] ([[configFile]] >> "Test" >> "word"); {{codecomment|// "Hey there"}}</code>
 
  
  
 
== Supported languages ==
 
== Supported languages ==
  
=== {{arma3}} ===
+
{| class="wikitable"
 +
! {{arma2}} &amp; {{arma2oa}} !! {{arma3}}
 +
|-
 +
| style="vertical-align: top" |
 +
* English
 +
* Czech
 +
* French
 +
* Spanish
 +
* Italian
 +
* Polish
 +
* Russian
 +
* German
 +
|
 +
<div style="column-count: 3">
 
* English
 
* English
 
* Czech
 
* Czech
Line 139: Line 96:
 
* Finnish
 
* Finnish
 
* Dutch
 
* Dutch
 +
</div>
 +
|}
  
=== {{arma2oa}} ===
 
* English
 
* Czech
 
* French
 
* Spanish
 
* Italian
 
* Polish
 
* Russian
 
* German
 
  
 +
== Key naming convention ==
  
== Usage ==
+
{{Informative | Same as [[Identifier#Recommendations|global variables]], it is recommended to use a '''{{Color|purple|TAG}}''' to prevent translation collision with mods.}}
  
==== Scripts ====
+
If the key is to be used by [[Config]] ([[Description.ext]] and dialogs included), it '''must''' start with <tt>STR</tt> (or <tt>str</tt>, casing does not matter). '''By convention''' however, <tt>STR_</tt> is the norm for all the entries.
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>
 
  
<code>"Marker1" [[setMarkerTextLocal]] [[localize]] "str_myTag_SeizeTheTown";</code>
+
== String Formats ==
  
[[hint]] [[format]] [ [[localize]] "str_myTag_formatted", "Dave" ]; {{codecomment|// "Hello, Dave."}}
+
Strings stored in the stringtable can be in the following formats:
{{codecomment|// str_myTag_formatted: <Original>Hello, %1.</Original>}}
+
* Normal text, such as <tt>Hello there</tt>
 +
* [[format]] text, such as <tt>Hello %1</tt>
 +
* [[Structured Text]], such as <tt><t size='2'>Hello</t> there</tt>, '''but''':<br><!--
 +
-->{{Important | The HTML tag characters <tt>&lt;</tt> and <tt>&gt;</tt> must respectively be encoded as <tt>&amp;lt;</tt> and <tt>&amp;gt;</tt>.}}<!--
 +
--><tt><t size='2'>Hello</t> there</tt> would then become <tt>&amp;lt;t size='2'&amp;gt;Hello&amp;lt;/t&amp;gt; there</tt>.
  
  
The stringtable can also hold [[Structured Text]] xml tags, if the tag characters &lt; &gt; are encoded as {{Inline_code| &amp;lt; &lt; }} and {{Inline_code| &amp;gt; &gt; }}  [http://www.w3schools.com/html/html_entities.asp see: HTML Entities]
+
== Usage ==
  
<code>[[hint]] [[parseText]] [[format]] [ [[localize]] "str_myTag_structured", "#FF0000", "with Color!" ]; //show 'with Color!' in Red
+
=== Script ===
&nbsp;
 
{{codecomment|// str_myTag_structured: <English>Some text &amp;lt;t color{{=}}'%1'&amp;gt;%2&amp;lt;/t&amp;gt;</English>}}
 
{{codecomment|// after format & parseText: Some text <t color{{=}}'#FF0000'>with Color!</t>}}</code>
 
  
 +
A translation can be retrieved and used in a script by using the [[localize]] command:
  
==== Description.ext ====
+
[[hint]] [[localize]] "str_TAG_Yes"; {{cc|returns "Yes" in English, "Oui" in French, etc.}}
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:
+
[[hint]] [[format]] [<nowiki/>[[localize]] "str_TAG_formatted", [[name]] [[player]]];
 +
[[hint]] [[localize]] "str_TAG_structuredText";
  
<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., the [[Config]] syntax to refer to a Stringtable translation is as follow (here, a [[Description.ext]] example):
  
==== 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;
 +
overviewText = $STR_TAG_overviewText;
 +
overviewPicture = $STR_TAG_overviewImage;
 +
</syntaxhighlight>
  
<code>class RscText_1012: RscText
+
The preprocessor will replace <tt>$STR</tt> entries with the Stringtable values.
{
 
idc = 1012;
 
text = $STR_myTag_someLabelText;
 
tooltip = $STR_myTag_someTip;
 
 
};</code>
 
  
  
==== CfgRadio ====
+
== Multiplayer ==
Stringtable entries can also be used for sounds and radio sentences in [[Description.ext#cfgRadio|CfgRadio]], also residing in Description.ext:
 
  
<code>class CfgRadio
+
[[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 [[:Category:Commands with global effects|global effect]] text commands (such as [[setMarkerText]]) would set the text in the server's language to everyone.
{
 
sounds[] = {};
 
class RadioMsg1
 
{
 
name = "";
 
sound[] = { $STR_myTag_sound_RadioMsg1, db-100, 1.0 };
 
title = $STR_myTag_RadioMsg1;
 
};
 
};
 
{{codecomment|// 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>
 
  
 +
Example of client-side translation of a server message:
  
==== Multiplayer ====
+
{{cc|Server-side}}
'''Multiplayer scripts''' should consider their translation implementation when clients and server are likely in varied localizations, and be mindful of text commands with [[:Category:Commands_with_global_effects|global]] effect (such as [[setMarkerText]] for example).
+
[[if]] ([[isServer]]) [[then]]
 +
{
 +
[<nowiki/>[[nil]], [[nil]], rHINT, [[localize]] "str_TAG_myMessage"] [[call]] [[RE]]; {{cc|{{arma2}}}}
 +
["str_TAG_myMessage"] [[remoteExecCall]] ["TAG_fnc_localHint"]; {{cc|{{arma3}}}}
 +
};
 +
 +
{{cc|Client-side executed function}}
 +
TAG_fnc_localHint = {
 +
[[if]] ([[hasInterface]]) [[then]]
 +
{
 +
[[hintSilent]] [[parseText]] ([[localize]] [[_this]]); {{cc|{{arma2}}}}
 +
[[hintSilent]] [[parseText]] ([[_this]] [[call]] [[BIS_fnc_localize]]); {{cc|{{arma3}}}}
 +
};
 +
};
  
Example of client-side translation:
 
<code>{{codecomment|// Server-side}}
 
[[if]] ([[isServer]]) [[then]] {
 
[nil, nil, rHINT, [[localize]] "str_myTag_myMessage"] [[call]] [[RE]]; {{codecomment|// {{arma2}}}}
 
["str_myTag_myMessage"] [[remoteExecCall]] ["TAG_fnc_localHint"]; {{codecomment|// {{arma3}}}}
 
};</code>
 
 
<code>{{codecomment|// Client-side}}
 
TAG_fnc_localHint = {
 
[[if]] ([[hasInterface]]) [[then]] {
 
[[hintSilent]] [[parseText]] ([[localize]] [[_this]]); {{codecomment|// {{arma2}}}}
 
[[hintSilent]] [[parseText]] ([[_this]] [[call]] [[BIS_fnc_localize]]); {{codecomment|// {{arma3}}}}
 
};
 
};</code>
 
  
 +
== See also ==
  
See also '''[[BIS_fnc_localize]]''' (since {{arma3}}).
+
* localize
 +
* isLocalized
 +
* [[BIS_fnc_localize]] (since {{arma3}})
  
  
[[Category:BIS_File_Formats]]
+
[[Category:BIS File Formats]]
 
[[Category:Arma 3: Editing]]
 
[[Category:Arma 3: Editing]]

Revision as of 22:10, 24 April 2020

SideTOC Informative 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 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


Informative Important


Supported languages

Arma 2 & Arma 2: Operation Arrowhead Arma 3
  • English
  • Czech
  • French
  • Spanish
  • Italian
  • Polish
  • Russian
  • German
  • English
  • Czech
  • French
  • Spanish
  • Italian
  • Polish
  • Portuguese
  • Russian
  • German
  • Korean (region exclusive)
  • Japanese (region exclusive)
  • Chinese 繁體中文 (Chinese Traditional)
  • Chinesesimp 简体中文 (Chinese Simplified)
  • Turkish
  • Swedish
  • Slovak
  • SerboCroatian
  • Norwegian
  • Icelandic
  • Hungarian
  • Greek
  • Finnish
  • Dutch


Key naming convention

Informative

If the key is to be used by Config (Description.ext and dialogs included), it must start with STR (or str, casing does not matter). By convention however, STR_ is the norm for all the entries.


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:
    Important<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";

Config

Whether it is in Description.ext, Campaign Description.ext, Dialogs etc., the Config syntax to refer to a Stringtable translation is as follow (here, a Description.ext example):

onLoadName = $STR_TAG_missionName;
onLoadMission = $STR_TAG_loadMissionText;
overviewText = $STR_TAG_overviewText;
overviewPicture = $STR_TAG_overviewImage;

The preprocessor will replace $STR entries with the Stringtable values.


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
	["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
	};
};


See also