Change language into game (SOLVED)

Started by , Tue 21/06/2016 21:44:48

Previous topic - Next topic

Neo_One

Hello.
In my game i have two languages, and i had did one button to change between one and other.
This work but if i exit of the game and into again always is the language by default.
I had used "WriteString" but doesn't work:
File *output = File.Open("acsetup.cfg", eFileWrite);
output.WriteString("translation=English");
Can't write in the file acsetup.

Help please.

Crimson Wizard

#1
Hello.

First of all, regarding possible technical problems
1. You should not write into acsetup.cfg just like that, because that may break INI format inside, and your changes will be ignored, or config stop working at all.
You would need to script some kind of INI reader and writer, which is not a simple task. There is a module written by Wyz (http://www.adventuregamestudio.co.uk/forums/index.php?topic=46631.0) but looking at the examples I cannot tell if it supports overwriting existing INI, or only writing a completely new one from scratch (if only the latter, this may screw up existing setup file as well).

2. Secondly, if you are using recent AGS 3.3.5, or 3.4.0, acsetup.cfg that you can change is located at "$SAVEGAMEDIR$/acsetup.cfg". And when you try to open it just like "acsetup.cfg" that will open new file "%APPDATADIR/acsetup.cfg", which will never be read by your game, unless you tell it to read it yourself (in script).

In the current time I may only suggest to create your own separate config file for this. Just write a file with any name in the "$APPDATADIR$" or "$SAVEGAMEDIR$", for example:
Code: ags

File *output = File.Open("$SAVEGAMEDIR$/user.cfg", eFileWrite);
output.WriteString("English");

And when starting the game:
Code: ags

File *input = File.Open("$SAVEGAMEDIR$/user.cfg", eFileRead);
if (input)
{
    String translation = input.ReadString();
    Game.ChangeTranslation(translation);
}




Neo_One

Thanks Crimson but it doesn't work. Create the file "user" but program not read it. :-\
I want do this becouse Linux compilation (3.04.X) doesn't run the Winsetup file and user can't change language and other options.

Crimson Wizard

Quote from: Neo_One on Wed 22/06/2016 11:52:38
Thanks Crimson but it doesn't work. Create the file "user" but program not read it. :-\
Where do you put the reading script? Are you sure it is run?
Try placing "Display" command just before file is opened to make sure.

Quote from: Neo_One on Wed 22/06/2016 11:52:38
I want do this becouse Linux compilation (3.04.X) doesn't run the Winsetup file and user can't change language and other options.
I am currently considering to make engine save last language to config on its own, so that you won't need to use custom file writing.

Neo_One

I put the reading script in function game_start()

File *outfile = File.Open("$SAVEGAMEDIR$/user.cfg", eFileRead);
if (outfile)
{
    String translation = outfile.ReadStringBack();
    Game.ChangeTranslation(translation);
}

and the write script in function button, everything in the GlobalScript.
Other thing i want to comment: input.ReadString() not exist, it write input.ReadStringBack() and sometimes back me error. Don't know if i'm doing something wrong.

Khris

I tested this and it works fine for me. However, restarting the game wouldn't show the changed value; I had to quit and run the game a 2nd time. Apparently the savegame slot used for restarting is created after game_start is called.

Neo_One

It works, but if i quit and run again the game the language back to "language default".

Neo_One

#7
At last it's working :-D

You have to put this script in the function initialize_control_panel(), of GlobalScript
File *outfile = File.Open("$SAVEGAMEDIR$/user.cfg", eFileRead);
if (outfile)
{
    String translation = outfile.ReadStringBack();
    Game.ChangeTranslation(translation);
}

And the last script in the event (button, combo box, etc...)
  File *outfile = File.Open("$SAVEGAMEDIR$/user.cfg",eFileWrite);
  if(bIdioma.Text=="Español")
  {
    Game.ChangeTranslation("English");
    bIdioma.Text="English";
    outfile.WriteString("English");
  }
  else if (bIdioma.Text=="English")
  {
    Game.ChangeTranslation("Spanish");
    bIdioma.Text="Español";
    outfile.WriteString("Spanish");
  }

I hope this can help more people.

Thanks to Crimson and Khris for your time ;-D

Crimson Wizard

I would like to mention, that I made AGS write latest chosen translation config when quitting the game. This feauture is now available in AGS 3.4.0 Beta 2.

Cookie_Wood

Hi everyone !

Re-opening this topic. I had the same problem than Neo_One and i managed to fix it thanks to this post. This is great, thank you :)
Nevertheless, I have another problem. I wanted somes sprites (button normal graphic, mouse ouver button and pushed graphic) and also many other sprites from GUIs to turn in English also (native language is French).

I noticed that, even if the language/translation really is English, my sprites are turning back in french when I restart the game. Is there a way to keep them consistent with the game choosen language when restaring the game also ?

This is what I tried :

In game start

Code: ags


File *input = File.Open("$SAVEGAMEDIR$/user.cfg", eFileRead);
   if (input)
   {
     String translation = input.ReadStringBack();
     Game.ChangeTranslation(translation);
   }
   
   if (Game.TranslationFilename == "French") 
   {
     File *output = File.Open("$SAVEGAMEDIR$/user.cfg", eFileWrite);
     output.WriteString("French");
   
     bNewgame.NormalGraphic=4;
     bNewgame.MouseOverGraphic=8;
     bNewgame.PushedGraphic=5;
     bLoad1.NormalGraphic=6;
     bLoad1.MouseOverGraphic=9;
     bLoad1.PushedGraphic=7;
     bQuit1.NormalGraphic=30;
     bQuit1.MouseOverGraphic=4505;
     bQuit1.PushedGraphic=31;
  }
   if (Game.TranslationFilename == "English")
   {
    File *output = File.Open("$SAVEGAMEDIR$/user.cfg", eFileWrite);
    output.WriteString("English");
  
    bNewgame.NormalGraphic=6995;
    bNewgame.MouseOverGraphic=6996;
    bNewgame.PushedGraphic=6997;
    bLoad1.NormalGraphic=6998;
    bLoad1.MouseOverGraphic=6999;
    bLoad1.PushedGraphic=7000;
    bQuit1.NormalGraphic=7001;
    bQuit1.MouseOverGraphic=7002;
    bQuit1.PushedGraphic=7003;
  }  
 


Into my switch language buttons

Code: ags


function bTurnEN_OnClick(GUIControl *control, MouseButton button)  ////VERS EN/////
 {
   File *output = File.Open("$SAVEGAMEDIR$/user.cfg", eFileWrite);
   output.WriteString("English");
   Game.ChangeTranslation("English");
 
  bNewgame.NormalGraphic=6995;
  bNewgame.MouseOverGraphic=6996;
  bNewgame.PushedGraphic=6997;
  bLoad1.NormalGraphic=6998;
  bLoad1.MouseOverGraphic=6999;
  bLoad1.PushedGraphic=7000;
  bQuit1.NormalGraphic=7001;
  bQuit1.MouseOverGraphic=7002;
  bQuit1.PushedGraphic=7003;
 
 
}

 function bTurnFR_OnClick(GUIControl *control, MouseButton button) ///VERS FR////
{
   File *output = File.Open("$SAVEGAMEDIR$/user.cfg", eFileWrite);
   output.WriteString("French");
   
  Game.ChangeTranslation("French");
  
 bNewgame.NormalGraphic=4;
 bNewgame.MouseOverGraphic=8;
 bNewgame.PushedGraphic=5;
 bLoad1.NormalGraphic=6;
 bLoad1.MouseOverGraphic=9;
 bLoad1.PushedGraphic=7;
 bQuit1.NormalGraphic=30;
 bQuit1.MouseOverGraphic=4505;
 bQuit1.PushedGraphic=31;
 
}


Thank you :D


Crimson Wizard

#10
Cookie_Wood, could you tell, why do you save translation option in a custom config; is there a problem relying on the default option?

Speaking about your script, I did not have time to think this through, but only wanted to note that you should close file right after finished working (reading/writing) with it, or you may get unexpected results, especially if you have multiple File.Open in same function.
(your code above seem to be safe by coincidence, but this may lead to bad habits, and eventually errors)

Khris

Disregarding what's causing the problem for a second, there's no need to write to the user.cfg file in game_start because assuming the code works as intended, you'll be writing back the exact same value you've just read from the file.

The only thing I can think of at the moment is that similar to other queued commands,  Game.ChangeTranslation(translation);  might not change the translation immediately but only after the function has finished. So at the time when game_start checks  Game.TranslationFilename  it's always the native "French".

Are you still using an older AGS version? Because like CW has mentioned back in 2016, for 3.4+ winsetup should store the chosen translation.

Cookie_Wood

Hi Crimson and Khris,

Thank you for your reply. I just tested it only by putting Game.ChangeTranslation("English"); and sprites graphics changes into the buttons "bTurnEN" and "bTurnFr" and you're right.... it works... The game indeed keep the last choosen language, even if I close the game or restart it. I don't know what I did wrong previously. Really sorry about that :/

Concerning closing the files, thank you for the advice :)

Khris

Ah, great  :)

Maybe a mod can put some note in the title or OP that this is no longer an issue since AGS 3.4?

Cookie_Wood

The strings translation is working great, but the sprites graphics changes still has a chaotic behaviour. Sometime sprites are in French when game is in English and vice versa but only when clicking on restarting game (when closing the game it works very well).

I just put this in game start, but maybe not enough ?

if (Game.TranslationFilename == "French")
   {
     bNewgame.NormalGraphic=4;
     bNewgame.MouseOverGraphic=8;
     bNewgame.PushedGraphic=5;
     etc...
  }
   if (Game.TranslationFilename == "English")
   {
    bNewgame.NormalGraphic=6995;
    bNewgame.MouseOverGraphic=6996;
    bNewgame.PushedGraphic=6997;
    etc
  } 

I'll try to find myself, but if you got an idea I'll take it :D

Khris

#15
My current understanding (take it with a grain of salt) is that when you run the game, this happens:
1. game_start runs
2. the game is saved to save slot #999
3. the first room is loaded

When you call RestartGame(); the engine simply loads save state #999, which means the crucial difference between running the game and restarting it is that game_start doesn't run again.
The current translation is a global setting, independent of save games, so if you switch to the other language, then restart, the wrong button sprites are "loaded" from savegame #999.

One way to potentially fix this is to use on_event:

Code: ags
function on_event(EventType event, int data) {
  if (event == eEventRestoreGame && data == 999) game_start();
}


This might fix it.

Crimson Wizard

Quote from: Khris on Wed 26/02/2020 19:38:21
My current understanding (take it with a grain of salt) is that when you run the game, this happens:
1. game_start runs
2. the game is saved to save slot #999
3. the first room is loaded

Yes, this is how it works, "restart game" is simply loading of save slot 999.

Cookie_Wood

It works GREAT. Thank you so much, that was the last big problem I had before official release of our game. You are, Khris and Crimson litteraly life savers !  :-*

Laura Hunt

Quote from: Khris on Wed 26/02/2020 19:38:21
(had to replace double ampersand with "AND" since forum software is still buggy)

(Just a quick reminder, the preview doesn't display ampersands, plus signs and other characters, but they will display normally once the post is published. i.e., && ++)

SMF spam blocked by CleanTalk