This is a documentation for Board Game Arena: play board games online !

Translations: Розніца паміж версіямі

З пляцоўкі Board Game Arena
Перайсці да навігацыі Перайсці да пошуку
Радок 128: Радок 128:
     // A game log string with no argument:
     // A game log string with no argument:
     self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
     self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );
</pre>
As a consequence there is no point passing variables to this function, i.e.
<pre>
    notif="foo"; self::notifyAllPlayers( 'log', clienttraslate(notif)); // BAD
    notif=clienttraslate("foo"); self::notifyAllPlayers( 'log', notif); // GOOD
</pre>
</pre>


Радок 148: Радок 154:
'''self::_( "my string to translate" ):'''
'''self::_( "my string to translate" ):'''


This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player).
This function returns a string translated in the language of CURRENT user (i.e. player who send the request to the server) (be careful, this is NOT the active player).


Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
Most of the time, you don't need to translate strings on server side, except on the following 3 situations:
Радок 154: Радок 160:


<pre>
<pre>
// This will display a translatable red message to the player that just do some wrong action:
// This will display a translatable red message to the player that just did some wrong action:
throw new BgaUserException( self::_('You must choose 3 cards') );
throw new BgaUserException( self::_('You must choose 3 cards') );


Радок 169: Радок 175:


<pre>
<pre>
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this:
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. Now we can do this:
throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] );
throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] );
</pre>
</pre>

Версія ад 02:59, 26 верасня 2020

Studio Framework Navigation

File structure of a BGA game

Game logic (Server side)
Game interface (Client side)
Other components
BGA Studio game components reference
  • Deck: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
  • Counter: a JS component to manage a counter that can increase/decrease (ex: player's score).
  • Scrollmap: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
  • Stock: a JS component to manage and display a set of game elements displayed at a position.
  • Zone: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).

Undocumented component (if somebody knows please help with docs)

  • Draggable: a JS component to manage drag'n'drop actions.
  • ExpandableSection: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
  • Wrapper: a JS component to wrap a <div> element around its child, even if these elements are absolute positioned.
BGA Studio user guide



Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.

How translation works?

When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.

Before the release of the game, BGA team will do the French translation of the game.

After the release of the game, the BGA players community will translate the game in every language.

What should be translated?

Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ...

This does NOT include error messages that are not supposed to happen (unexpected errors).

What rules should I follow for the original English strings?

For a coherent and homogeneous interface, here are some rules about ending a sentence with a final dot '.'

  • As a general rule:
    • If a sentence is displayed isolated in the interface => no final dot
    • If a sentence is followed or could be followed by another sentence in the same interface space => final dot.
  • In detail:
    • No final dot:
      • button labels
      • section titles
      • menu elements
      • links triggering an isolated action
      • anything that is not a full sentence
      • current action in the status bar
    • Final dot:
      • complete explanation sentence, that can be chained with another sentence
    • We can tolerate a dot or no dot (but it should be consistent inside the game) for:
      • isolated tooltip / isolated small sentence
      • game log (no dot is usually preferable)
      • error messages (except if more than one sentence in the error message => final dot mandatory in this case)

Otherwise, you should try to follow as closely as possible the general style and format (including capitalization) used in the English rulebook and game material of the game.

Focus on translating notifications

Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function.

However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.

WARNING: how to make sure your strings will be translated

For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers).

If your original string is not "physically" inside one of this marker, it won't be translated.

    // Examples: the following strings will be translated:
    var mystring_translated = _("my string");       // JS
    $mystring_translated = self::_("my string");    // PHP
    $mystring_translated = sprintf( self::_("my string with an %s argument"), $argument );   // PHP

    // Examples: the following strings WILL NOT be translated:
    $my_string = "my string";
    $not_translated = self::_( $my_string );   // The original string is not bordered by a translator marker => no translation
    $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing

How to not make translators crazy ;)

  • When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.
  • Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it).
  • Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:
self::_("First part of the string, ").$argument.' '.self::_("second part of the string")

Write instead:

sprintf( self::_("First part of the string, %s second part of the string"), $argument )

(or the equivalent "dojo.string.substitute" in Javascript)

  • When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. You can also leave a comment on what is the context of the string in the translation program (English to English) if you are the developer of the game.
  • The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate.
  • Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY".
  • Use present tense instead of past, i.e. "player gets wood" instead of "player got wood"
  • Avoid using gender specific pronouns, i.e. instead of "player returns card to *his* hand" use "player returns card to *their* hand" or just avoid using it, i.e. "player picks up the card"

On client side (Javascript)

On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate.

Examples:

// Get a string in player's language:
var translated = _("original english string");

// Get a string in player's language with parameter:
var translated = dojo.string.substitute( _("You can pick ${p} cards and discard ${d}"), {
    p: 2,
    d: 4
} );

WARNING: in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead.

On server side (PHP)

On PHP side, you can use 3 different functions to specify that a string must be translated.

clienttranslate( "my string to translate" ):

This function is transparent: it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side.

In general, you use clienttranslate:

  • On your states.inc.php, for field "description" and "descriptionmyturn".
      "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'),
  • On "material.inc.php", when defining texts for game material that must be displayed on client side.
$this->card_types = array(

     1 => array(
        'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side.
  • When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation.
     // A game log string with no argument:
     self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() );

As a consequence there is no point passing variables to this function, i.e.

    notif="foo"; self::notifyAllPlayers( 'log', clienttraslate(notif)); // BAD
    notif=clienttraslate("foo"); self::notifyAllPlayers( 'log', notif); // GOOD

Translating arguments is a little bit more complex. It is using the "i18n" special argument as below:

 // In the following example, we translate the game log itself, but also the "card_name" argument:

 self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array(
                'i18n' => array( 'card_name' ),     // <===== We specify here that "card_name" argument must be translated
                'player_id' => $player_id,
                'player_name' => self::getActivePlayerName(),
                'points' => $points,
                'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string.
            ) ); 

Pay attention when using 'i18n' argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using 'card_name' to move it on player board as described in the example). It's pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument name like 'card_name_translated' by example.

self::_( "my string to translate" ):

This function returns a string translated in the language of CURRENT user (i.e. player who send the request to the server) (be careful, this is NOT the active player).

Most of the time, you don't need to translate strings on server side, except on the following 3 situations:

  • When throwing an exception because the player did a forbidden move.
// This will display a translatable red message to the player that just did some wrong action:
throw new BgaUserException( self::_('You must choose 3 cards') );

// ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated.
  • In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file.
$this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II");
  • Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions.
// In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. Now we can do this:
throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] );
  • Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user.

totranslate( "my string to translate" ):

This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side.

You should not use this function, except on the following cases:

  • Statistics name in stats.inc.php
  • Option names and option values name in gameoptions.inc.php