How to dynamically switch lua files?

Hello everyone,

I’ve six files

  1. main.lua

  2. english.lua

  3. russian.lua

  4. welcome.lua

  5. ice.lua //DATABASE FILE

  6. options.lua

main.lua

local myGroup = display.newGroup() _G.language = “english” function whatLanguage()      local settingData = IceBox:new( “settings” )    settingData:load()          _G.language = settingData:retrieve(“language”) or “english”    require (_G.language) end function mymain() director:changeScene(“welcome”, “none”);    return myGroup end mymain()

english.lua

function welcomeUser()    return “Welcome Guest” end

russian.lua

function welcomeUser()    return “Добро пожаловать, Гость” end

welcome.lua

module(…, package.seeall) function greetUser() whatLanguage() --Function Defined In main.lua       welcomeUser() --Function Defined In english.lua and russian.lua end

It works fine when I start the game but when I change language from english to russian in options.lua file and call welcome.lua file, It still shows me text in english language.

What I want is to remove english.lua and include russian.lua.

I cannot merge my files as there is hell lot of data.

Is it possible to switch the files?

Any help would be highly appreciated…

Thanks,

I don’t know what Icebox is, but have you tried printing out what is returned by this:

settingData:retrieve("language")

at line 7 in main.lua? I suspect it returns nil which means you’re always returning “english”.

The main problem is that you’re trying to switch language by calling a module which has been loaded as code and then later actually removing that module. While I believe this is possible in a Lua program, when your code executes on a device it will not be running as Lua but Objective-C or Java etc, because it will have been compiled for that platform.

So, what you want to do is reference the appropriate module as an object, not actually remove it from memory as if it were a linked library.

The way to do this is change your functions from global (which you should never do!) to local and return the local object from the module:

english.lua:

local lib = {} function lib.welcomeUser() return "welcome" end return lib

russian.lua:

local lib = {} function lib.welcomeUser() return "Добро пожаловать, Гость" end return lib

You would simply call the function on the required module at the right time:

local module = require( whatLanguage ) module:welcomeUser()

Now, I have to admit that this is not my preferred way of doing something like this because you should have language files which you simply load data from, rather than loading language specific code. But your method is totally valid and really just another way of doing it.

IMHO, this is the wrong way of handling translations.  You should never have a function return a string like that.  When you scale out there will be tonnes of programming involved.

If your app is simple use a plugin to manage your strings - https://marketplace.coronalabs.com/plugin/gbc-language-cabinet

In the game I’m building I decided to go for something like this:

--text.lua local M = {} M["en"] = {} M["fr"] = {} M["de"] = {} M["es"] = {} -- Start a new game M["en"]["newgame"] = "New Game" M["fr"]["newgame"] = "Nouvelle partie" M["de"]["newgame"] = "Neues Spiel" M["es"]["newgame"] = "Nuevo juego"

– Resume an existing game

M[“en”][“resume”] = “Resume”

M[“fr”][“resume”] = “Reprendre”

M[“de”][“resume”] = “Fortsetzen”

M[“es”][“resume”] = “Continuar”

return M

Then when I need a phrase in another scene I’ll

local text = require("text")

at the top of the scene, determine my language and then when I want to display text:

local playGameText = display.newText( text[myLanguage]["newgame"], 100, 100, display.systemFont, 20)

If myLanguage is “fr” it will get the French string. I don’t know that I would call what I’m doing a best practice but it works for me and seems pretty straight forward. 

You will find Corona will allow you to do things in many different ways.

Rob 

I do something slightly different.  Here is my version.

local M = {} local translations = { ["house builder"] = { ["de"] = "Bauherr", ["id"] = "pembangun rumah", ["it"] = "architetto", ["ja"] = "家屋建築家", ["ru"] = "Строитель домов", ["fr"] = "constructeur de maison", ["nl"] = "huizenbouwer", ["es"] = "Constructor de casa", ["pt"] = "construtor de casas", ["ko"] = "주택 건축가", }, -- more strings }

I then have a function which performs a lookup ONLY if the current language is not “en”.  So for English speaking players there is no table lookup involved so it will perform faster than Rob’s way of arranging his table.

It makes a difference when your translation table is over 17k lines long - as mine is.  For only a few strings the difference would be negligible.

I don’t know what Icebox is, but have you tried printing out what is returned by this:

settingData:retrieve("language")

at line 7 in main.lua? I suspect it returns nil which means you’re always returning “english”.

The main problem is that you’re trying to switch language by calling a module which has been loaded as code and then later actually removing that module. While I believe this is possible in a Lua program, when your code executes on a device it will not be running as Lua but Objective-C or Java etc, because it will have been compiled for that platform.

So, what you want to do is reference the appropriate module as an object, not actually remove it from memory as if it were a linked library.

The way to do this is change your functions from global (which you should never do!) to local and return the local object from the module:

english.lua:

local lib = {} function lib.welcomeUser() return "welcome" end return lib

russian.lua:

local lib = {} function lib.welcomeUser() return "Добро пожаловать, Гость" end return lib

You would simply call the function on the required module at the right time:

local module = require( whatLanguage ) module:welcomeUser()

Now, I have to admit that this is not my preferred way of doing something like this because you should have language files which you simply load data from, rather than loading language specific code. But your method is totally valid and really just another way of doing it.

IMHO, this is the wrong way of handling translations.  You should never have a function return a string like that.  When you scale out there will be tonnes of programming involved.

If your app is simple use a plugin to manage your strings - https://marketplace.coronalabs.com/plugin/gbc-language-cabinet

In the game I’m building I decided to go for something like this:

--text.lua local M = {} M["en"] = {} M["fr"] = {} M["de"] = {} M["es"] = {} -- Start a new game M["en"]["newgame"] = "New Game" M["fr"]["newgame"] = "Nouvelle partie" M["de"]["newgame"] = "Neues Spiel" M["es"]["newgame"] = "Nuevo juego"

– Resume an existing game

M[“en”][“resume”] = “Resume”

M[“fr”][“resume”] = “Reprendre”

M[“de”][“resume”] = “Fortsetzen”

M[“es”][“resume”] = “Continuar”

return M

Then when I need a phrase in another scene I’ll

local text = require("text")

at the top of the scene, determine my language and then when I want to display text:

local playGameText = display.newText( text[myLanguage]["newgame"], 100, 100, display.systemFont, 20)

If myLanguage is “fr” it will get the French string. I don’t know that I would call what I’m doing a best practice but it works for me and seems pretty straight forward. 

You will find Corona will allow you to do things in many different ways.

Rob 

I do something slightly different.  Here is my version.

local M = {} local translations = { ["house builder"] = { ["de"] = "Bauherr", ["id"] = "pembangun rumah", ["it"] = "architetto", ["ja"] = "家屋建築家", ["ru"] = "Строитель домов", ["fr"] = "constructeur de maison", ["nl"] = "huizenbouwer", ["es"] = "Constructor de casa", ["pt"] = "construtor de casas", ["ko"] = "주택 건축가", }, -- more strings }

I then have a function which performs a lookup ONLY if the current language is not “en”.  So for English speaking players there is no table lookup involved so it will perform faster than Rob’s way of arranging his table.

It makes a difference when your translation table is over 17k lines long - as mine is.  For only a few strings the difference would be negligible.