Page 1 of 2

How to Mark Dynamic Description for Translation

Posted: 30 August 2021, 16:39
by Grunt_the_Clever
Hi,

I have developed a game called Zener and I am trying to resolve a translation bug where the names of the pieces aren't translated in the description from states.inc.php.

I have this in states.inc.php:

Code: Select all

"description" => clienttranslate( '${actplayer} must move ${mandatory_move} piece' ),
"descriptionmyturn" => clienttranslate( '${you} must move ${mandatory_move} piece' ),
inside of zener.game.php, I have tried a few things that the forums seemed to suggest would work:

Code: Select all

in setupNewGame:
$tmp = clienttranslate( '${actplayer} must move the circle piece' );
$tmp = clienttranslate( '${actplayer} must move the square piece' );
$tmp = clienttranslate( '${actplayer} must move the waves piece' );
$tmp = clienttranslate( '${actplayer} must move the star piece' );
$tmp = clienttranslate( '${actplayer} must move the cross piece' );
$tmp = clienttranslate( '${actplayer} must move any piece' );
$tmp = clienttranslate( '${you} must move the circle piece' );
$tmp = clienttranslate( '${you} must move the square piece' );
$tmp = clienttranslate( '${you} must move the waves piece' );
$tmp = clienttranslate( '${you} must move the star piece' );
$tmp = clienttranslate( '${you} must move the cross piece' );
$tmp = clienttranslate( '${you} must move any piece' );

...

function argsMandatoryChoose()
    {
        $statement;
        $mandatory_move = self::getGameStateValue('mandatory_move');

        switch($mandatory_move)
        {
            case 1:
                $statement = clienttranslate( 'the circle' );
                break;
            case 2:
                $statement = clienttranslate( 'the cross' );
                break;
            case 3:
                $statement = clienttranslate( 'the waves' );
                break;
            case 4:
                $statement = clienttranslate( 'the square' );
                break;
            case 5:
                $statement = clienttranslate( 'the star' );
                break;
            case 0:
            default:
                $statement = clienttranslate( 'any' );
        }

        $possible_pieces = self::getPossiblePieces( $mandatory_move );

        // we check if the mandatory move can be made in stMandatoryChoose 

        return array(
            'mandatory_move' => $statement,
            'possible_pieces' => $possible_pieces
        );
    }
Neither of these have solved the issue, the strings still show as "<Translated text> the circle". From the forums, I have understood that translating substitutions does not work, hence trying adding the full strings (though keeping the actplayer/you substitutions), in the hopes those could then be translated, but I am still not seeing them translated. Can anyone help point me in the right direction? Thanks!

Re: How to Mark Dynamic Description for Translation

Posted: 30 August 2021, 17:47
by Tisaac
You are just missing the i18n field of the args.

Re: How to Mark Dynamic Description for Translation

Posted: 30 August 2021, 22:52
by Grunt_the_Clever
Would that look like this?

Code: Select all

return array(
            'mandatory_move' => $statement,
            'possible_pieces' => $possible_pieces,
            'i18n' => array( 'mandatory_move' )
        );

Re: How to Mark Dynamic Description for Translation

Posted: 30 August 2021, 23:21
by Tisaac
Grunt_the_Clever wrote: 30 August 2021, 22:52 Would that look like this?

Code: Select all

return array(
            'mandatory_move' => $statement,
            'possible_pieces' => $possible_pieces,
            'i18n' => array( 'mandatory_move' )
        );
Looking good to me.

Re: How to Mark Dynamic Description for Translation

Posted: 31 August 2021, 15:59
by Grunt_the_Clever
That worked for both my states.inc.php description and descriptionmyturn as well as player notifications. Thanks so much for the help!

Re: How to Mark Dynamic Description for Translation

Posted: 31 August 2021, 18:32
by Grunt_the_Clever
Actually, while this fixed the translation issue, after I pushed this change to production, translated games (i.e. not in English) were broken. All moves would say "Move recorded. Waiting for update..." on them, but not until the player refreshed were they able to do anything. In addition, they could not see the opponent's move happen until a refresh. As such, I have rolled back to the old build with untranslated strings.

The JS console has an error, saying: "Uncaught (in promise) DOMException: The fetching process for the media resource was aborted by the user agent at the user's request.

I'm not sure if that is related or not. Any thoughts on why the 'i18n' addition caused the notifications to not work correctly? As I'm assuming that's the piece that broke. In my notifications, I did this:

Code: Select all

self::notifyAllPlayers( "chooseMandatoryPiece", clienttranslate( '${player_name} chose the ${piece}' ), array( 
            'player_name' => self::getActivePlayerName(), 
            'piece' => $piece, 
            'i18n' => array( 'piece' ) // this line added
        ) );
However, English games worked just fine, no refreshes needed.

Re: How to Mark Dynamic Description for Translation

Posted: 31 August 2021, 18:54
by Tisaac
That's weird, have you tried changing your langage on studio to see if you can reproduce the issue ?

Re: How to Mark Dynamic Description for Translation

Posted: 31 August 2021, 20:12
by Grunt_the_Clever
Yeah, I can repro the issue by changing the language. Trying to see where it is getting hung up.

Re: How to Mark Dynamic Description for Translation

Posted: 01 September 2021, 15:50
by Grunt_the_Clever
Hmm, the bummer is though that I repro'd it by changing by language in BGA proper, then rolled back the build to not block anyone. But in studio, I cannot change my language to repro the issue.

Re: How to Mark Dynamic Description for Translation

Posted: 01 September 2021, 16:37
by Grunt_the_Clever
I'm starting to see some very weird things happen. I tried again, this time removing two clienttranslates that the Check Project had flagged as untranslatable (and that was just while I was testing stuff out). I tried this again in production, since I only see the problem in other languages, and this time, it hung for non-English again, but partway into the notification function. In my notification function, I rotate the board, so that I can place pieces, then I rotate it back. In my game, I saw the board rotate, but then not rotate back. There are no loops or any non-exitable pieces of the code in the notif function and this is the only place in the code that removes the rotate:

Code: Select all

        notif_makeMove: function( notif )
        {
            var x = 2;
            var y = 0;

            // remove rotate board for white player due to BGA incompatibility
            if ( !this.isSpectator && this.gamedatas.players[ this.player_id ][ 'color' ] == 'ffffff' )
            {   
                dojo.removeClass( 'znr_board', 'znr_rotate' );
            }

            if ( notif.args.new_y == 7 )
            {   
                this.slideToObjectPos( 'znr_piece_'+notif.args.piece+'_'+notif.args.color, 'znr_endHouse_bot', x, y ).play();
            }
            else if ( notif.args.new_y == -1 )
            { 
                this.slideToObjectPos( 'znr_piece_'+notif.args.piece+'_'+notif.args.color, 'znr_endHouse_top', x, y ).play(); 
            } 
            else 
            { 
                var z_index = 0; 
                if ( notif.args.bot_color != null ) 
                { 
                    z_index = $('znr_piece_'+notif.args.bot_piece+'_'+notif.args.bot_color).style.zIndex; 
                    if ( dojo.hasClass( 'znr_counter_'+notif.args.new_x+'_'+notif.args.new_y, 'znr_no_display' ) ) 
                    { 
                        dojo.removeClass( 'znr_counter_'+notif.args.new_x+'_'+notif.args.new_y, 'znr_no_display' ); 
                    } 
                } 
 
                this.counters[notif.args.new_x][notif.args.new_y].incValue( 1 ); 
                dojo.style( 'znr_piece_'+notif.args.piece+'_'+notif.args.color, 'z-index', Number( z_index ) + 1 ); 
                this.slideToObjectPos( 'znr_piece_'+notif.args.piece+'_'+notif.args.color, 'znr_house_'+notif.args.new_x+'_'+notif.args.new_y, x, y ).play(); 
            } 
 
            this.counters[notif.args.old_x][notif.args.old_y].incValue( -1 ); 
 
            if ( Number( this.counters[notif.args.old_x][notif.args.old_y].getValue() ) <= 1 && 
                 !dojo.hasClass( 'znr_counter_'+notif.args.old_x+'_'+notif.args.old_y, 'znr_no_display' ) ) 
            { 
                dojo.addClass( 'znr_counter_'+notif.args.old_x+'_'+notif.args.old_y, 'znr_no_display' ); 
            } 
 
            // rotate board for white player 
            if ( !this.isSpectator && this.gamedatas.players[ this.player_id ][ 'color' ] == 'ffffff' ) 
            { 
                dojo.addClass( 'znr_board', 'znr_rotate' ); 
            } 
        },
I have no idea what's going on, why the remove of the rotate would happen, but then the add of the rotate back would not happen. And why this only occurs with the i18n param on non-English games. I think I need some BGA side help here. Or maybe I'll just remove the substitutions from the messages and try to form them outside of the notif message.