GBC Language Cabinet

About

GBC Language Cabinet is an easy to use way to display text in different languages. Simply specify which languages you are supporting, create or import tables of translated text, and use a basic function call to return the text in the correct language.

Several options exist to make your life even easier:

  • Text can be created with embedded keys. During the getText call, parameters can then be passed via a table. The returning text will be formatted to replace the keys with the parameters you passed. See below for examples.
  • You can import a comma-delimited file or a json file containing your text (including embedded keys!) instead of using multiple addText calls.

Set Up

GBC Language Cabinet is now part of the Solar2D Free Plugins Directory, so there is nothing you need to do except to add the following reference in your build.settings file.

plugins = {  
    ["plugin.GBCLanguageCabinet"] = {
        publisherId = "com.gamesbycandlelight",
    },
}

Be sure to require the plugin in each module you need to manage your data:

local GBCLanguageCabinet = require ("plugin.GBCLanguageCabinet")

Reference

GBCLanguageCabinet.addLanguage(language, languageKey)

language – full name of the language to add
languageKey – reference key to the language

Adds support for the specified language.

Example:

GBCLanguageCabinet.addLanguage("English", "en")

GBCLanguageCabinet.removeLanguage(languageKey)

languageKey – reference key to language

Removes support for the specified language.


GBCLanguageCabinet.clearLanguages()

Removes all language support. This basically resets the supported language table.


GBCLanguageCabinet.getLanguages()

Returns as table with the following information for all supported languages:

key – the reference key to the supported language
language – the full name of the supported language


GBCLanguageCabinet.getDeviceLanguage()

This is a helper function that will return the 2 character language code currently set on the device.


GBCLanguageCabinet.addText(key, entryTable)

key – the reference key to the text in various languages
entryTable – a table of table entries in the following format:

languageKey – reference key to the language, as defined in previous addLanguage call.
textString – the actual translated text string.

Example:

GBCLanguage.addText("hello", {
    {"en", "Hi, my name is John."},
    {"de", "Hallo , mein Name ist John"},
    {"klingon", "nuqneH, pongwIj 'oH yo'a'neS"},
    {"yoda", "John, my name is"},
})
GBCLanguageCabinet.addTextFromFile(fileName, fileType)

fileName – the name of a comma-delimited file used to create a series of text entries.
filetype – Either “csv” for a comman-delimited file, or “json” for a json file.

Instead of adding multiple entries individually with the addText function, you can import a comma-delimited or json file of text strings.

When this function is called, the file specified is read and imported. In order for this call to be successful, the following must be true:

  • The file must be in the same folder as your Lua code… no subdirectories.
  • If using a comma-delimited file:
    • It must contain a header record containing reference keys.
    • The keys listed in the header record must have been defined during an addLanguage function call.
    • All entries in the comma-delimited file should be enclosed in quotes.
    • CSV file should be encoded with utf-8-BOM encoding. For example, in NotePad++ select Encoding -> Convert to UTF-8-BOM.
  • If using a json file:
    • The keys listed in each table record must have been defined during an addLanguage function call.

The following is a valid comma-delimited file that can be used for import:

"Languages","en","de"
"hello","My name is John","Meine Name ist John"
"RedBall","That is a ##color## ##object##","Das ist eine ##color## ##object##"

The first line is the header line, and contains the keys for the rest of the file. Only the languages that have previously been enabled during an addLanguage call are imported.

The following is a valid json file that can be used for import:

{
    "hello":{
        "en":"My name is John",
        "de":"Mein Name ist John"
    },
    
    "RedBall":{
        "en":"That is a ##color## ##object##",
        "de":"Das ist eine ##color## ##object##"
    }
}

Example:

GBCLanguageCabinet.addLanguage("English", "en")
GBCLanguageCabinet.addTextFromFile("testfile.txt", "csv")

Note that in this example, the German (“de”) text from the comma-delimited and file will not be imported since that language was not enabled with a previous addLanguage call. Also notice that the language keys (“en” in this example) must match in the addLanguage and addTextFromFile calls.


GBCLanguageCabinet.removeText(key)

key – Reference key to specific table of language strings

Removes all text associated with key.


GBCLanguageCabinet.clearText()

Removes all text entries.


GBCLanguageCabinet.getText(textKey, languageKey, params)

textKey – Reference key to the text entry in the language cabinet.
languageKey – Reference key to the language of the text you want.
params – list of optional parameters, in table format, to insert into the string.

This function will return a single text entry in a specific language you specify.

If the text string contains parameter placeholders, the string is formatted with the parameter values passed to it in that order. For more details on passing parameters, see below.

Example:

GBCLanguageCabinet.addText("RedBall", {
    {"en", "That is a ##color## ##object##."},
    {"de", "Das ist eine ##color## ##object##."},
    {"es", "Esa es una ##object## ##color##."},
    {"zh", "這是一個 ##color## ##object##."},
    {"yoda", "##color##, that ##object## is."},
}) 

print (GBCLanguageCabinet.getText("RedBall", "en", {color = "red", object = "ball"})) 
print (GBCLanguageCabinet.getText("RedBall", "es", {color = "rojo", object = "bola"}))
print (GBCLanguageCabinet.getText("RedBall", "en"))

The output of the above code would be:

That is a red ball.
Esa es una bola rojo.
That is a ##color## ##object##.

This is extremely useful for dynamic creation of text… you do not have to split apart and rebuild text strings to include values you need. This also supports the grammatical differences between languages. Notice the Spanish statement grammatically lists the object first.

This function will substitute a passed parameter into an embedded key until all keys are substituted, or until all parameters have been used.  An extra embedded keys not substituted with a matching parameter are returned as well.

To create a placeholder, surround a keyword with two hash symbols. The keyword can be any keyword you wish, since this is just for your reference.

Sample Code

A sample Corona SDK project, including code and test json and csv files, are located here:  GBCLanguageCabinetExample.

Below is some examples on how to use GBC Language Cabinet

local GBCLanguageCabinet = require "plugin.GBCLanguageCabinet"

local widget = require "widget"
local Buttons = {}
local txtString

-- button event handler
-- displays the translated text when button is pressed
local function buttonHandler(event)
    local target = event.target.id
    
    if target == "zh" then
        txtString.text = GBCLanguageCabinet.getText("RedBall", "zh", {
            color = "紅",
            object = "球"
        })
    elseif target == "en" then
        txtString.text = GBCLanguageCabinet.getText("RedBall", "en", {
            color = "red",
            object = "ball",
        })
    elseif target == "es" then
        txtString.text = GBCLanguageCabinet.getText("RedBall", "es", {
            color = "rojo",
            object = "bola",
        }) 
    elseif target == "de" then
        txtString.text = GBCLanguageCabinet.getText("RedBall", "de", {
            color = "rot",
            object = "Ball",
        })         
    end
end

-- add some languages
GBCLanguageCabinet.addLanguage("English", "en")
GBCLanguageCabinet.addLanguage("Deutsch", "de")
GBCLanguageCabinet.addLanguage("Español", "es")
GBCLanguageCabinet.addLanguage("中國", "zh")


------------------------------------
-- add a table of text.
-- Notice choose one of the 3 options below to populate a table of text
------------------------------------  

-- Option 1 - create entry using addText()
-- Notice that "yoda" will not be imported since we did not add that
-- as a language in the previous step.
GBCLanguageCabinet.addText("RedBall", {
    {"en", "That is a ##color## ##object##"},
    {"de", "Das ist eine ##color## ##object##"},
    {"es", "Esa es una ##object## ##color##"},
    {"zh", "這是一個 ##color## ##object##"},
    {"yoda", "##color##, that ##object## is"},
})

-- Option 2 - create entry by importing a json file
-- Note that json file only has entries for some of the languages,
-- so some buttons will not display text
--GBCLanguageCabinet.addTextFromFile("testfile.json", "json")

-- Option 3 - create entry by importing a csv file
-- Note that csv file only has entries for some of the languages,
-- so some buttons will not display text
--GBCLanguageCabinet.addTextFromFile("testfile.txt", "csv")

-------------------------------

-- Create some buttons for the demo
-- Utilize the language table
local Languages = GBCLanguageCabinet.getLanguages()

for i = 1, #Languages do
    Buttons[i] = widget.newButton({
        id = Languages[i].key,
        label = Languages[i].language,
        labelColor = {default = {0,0,0,1}, over = {0.5, 0.5, 0.5, 1}},
        width = 80,
        height = 30,
        shape = "roundedRect",
        fillColor = {default = {1, 0.5, 0 , 1}, over = {204/255, 102/255, 0, 1}},
        left = 20,
        top = 50 * i,
        onRelease = buttonHandler,
    })
end

-- create text string to hold the displayed text on the screen
txtString = display.newText({
    text = "",
    x = display.contentCenterX,
    y = display.contentCenterY + (display.contentCenterY * 0.5),
    align = "center",
    width = 380,
    height = 0,
    fontSize = 24,
})