diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java b/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
index 77bca8a..3ebac74 100644
--- a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
+++ b/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
@@ -239,6 +239,20 @@ class I18NData
 	}
 
 
+	/**
+	 * Access the store for some language
+	 * 
+	 * @param language
+	 *            the language to access
+	 * 
+	 * @return the language store, or <code>null</code> if the language is not defined.
+	 */
+	LanguageStore getStore( String language )
+	{
+		return this.languages.get( language );
+	}
+
+
 	/**
 	 * Sets or creates the translation for a given language/string identifier pair.
 	 * 
@@ -257,7 +271,8 @@ class I18NData
 	 * @throws IllegalArgumentException
 	 *             if the string does not exist
 	 */
-	String setTranslation( final int administrator , final String language , final String string , final String translation )
+	String setTranslation( final int administrator , final String language , final String string ,
+			final String translation )
 	{
 		// Get existing translation
 		LanguageStore store = this.languages.get( language );
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java b/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
index 7ce8046..4e97fbf 100644
--- a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
+++ b/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
@@ -1,7 +1,10 @@
 package com.deepclone.lw.beans.i18n;
 
 
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,10 +16,13 @@ import com.deepclone.lw.interfaces.i18n.UnknownStringException;
 
 
 /**
+ * Translation component
+ * 
+ * <p>
  * The translator bean's implementation uses the contents of the {@link I18NData} instance, which it
  * only accesses in read-only mode.
  * 
- * @author tseeker
+ * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
  */
 public class TranslatorBean
 		implements Translator
@@ -83,6 +89,23 @@ public class TranslatorBean
 	}
 
 
+	/* Documentation in Translator interface */
+	@Override
+	public String getLanguageName( String language )
+			throws UnknownLanguageException
+	{
+		this.data.readLock( ).lock( );
+		try {
+			if ( !this.data.isLanguageComplete( language ) ) {
+				throw new UnknownLanguageException( language );
+			}
+			return this.data.getLanguageName( language );
+		} finally {
+			this.data.readLock( ).unlock( );
+		}
+	}
+
+
 	/* Documentation in Translator interface */
 	@Override
 	public String translate( String language , String string )
@@ -103,17 +126,30 @@ public class TranslatorBean
 	}
 
 
-	/* Documentation in Translator interface */
+	/**
+	 * Access the store for the specified language then extract translations
+	 */
 	@Override
-	public String getLanguageName( String language )
-			throws UnknownLanguageException
+	public Map< String , String > translate( String language , Collection< String > strings )
+			throws UnknownStringException , UnknownLanguageException
 	{
 		this.data.readLock( ).lock( );
 		try {
 			if ( !this.data.isLanguageComplete( language ) ) {
 				throw new UnknownLanguageException( language );
 			}
-			return this.data.getLanguageName( language );
+			
+			LanguageStore store = this.data.getStore( language );
+			HashMap< String , String > result = new HashMap< String , String >( );
+			for ( String identifier : strings ) {
+				String value = store.getTranslation( identifier );
+				if ( value == null ) {
+					throw new UnknownStringException( identifier );
+				}
+				result.put( identifier , value );
+			}
+
+			return result;
 		} finally {
 			this.data.readLock( ).unlock( );
 		}
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
index 43524db..e515d04 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
+++ b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
@@ -79,19 +79,8 @@ public class EmpireDAOBean
 	public GeneralInformation getInformation( int empireId )
 	{
 		String sql = "SELECT * FROM emp.general_information WHERE id = ?";
-		RowMapper< GeneralInformation > mapper = new RowMapper< GeneralInformation >( ) {
-			@Override
-			public GeneralInformation mapRow( ResultSet rs , int rowNum )
-					throws SQLException
-			{
-				String st = rs.getString( "status" );
-				Character status = ( st == null ) ? null : st.charAt( 0 );
-				return new GeneralInformation( status , rs.getString( "name" ) , rs.getString( "alliance" ) , rs
-						.getLong( "cash" ) , rs.getLong( "game_time" ) , rs.getInt( "account_id" ) );
-			}
-		};
 		try {
-			return this.dTemplate.queryForObject( sql , mapper , empireId );
+			return this.dTemplate.queryForObject( sql , new GeneralInformationRowMapper( ) , empireId );
 		} catch ( EmptyResultDataAccessException e ) {
 			return null;
 		}
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
index 7a4c6fe..a940ef7 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
+++ b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
@@ -117,7 +117,7 @@ public class EmpireManagementBean
 
 		return new GamePageData( generalInformation.getName( ) , generalInformation.getStatus( ) ,
 				generalInformation.getTag( ) , generalInformation.getCash( ) , generalInformation.getNextTick( ) ,
-				planets , rlTime );
+				planets , rlTime, generalInformation.getLanguage( ) );
 	}
 
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/GeneralInformationRowMapper.java b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/GeneralInformationRowMapper.java
new file mode 100644
index 0000000..fd8be8a
--- /dev/null
+++ b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/GeneralInformationRowMapper.java
@@ -0,0 +1,36 @@
+package com.deepclone.lw.beans.empire;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.springframework.jdbc.core.RowMapper;
+
+import com.deepclone.lw.sqld.game.GeneralInformation;
+
+
+
+class GeneralInformationRowMapper
+		implements RowMapper< GeneralInformation >
+{
+
+	@Override
+	public GeneralInformation mapRow( ResultSet rs , int rowNum )
+			throws SQLException
+	{
+		GeneralInformation info = new GeneralInformation( );
+		
+		info.setName( rs.getString( "name" ) );
+		info.setTag( rs.getString( "alliance" ) );
+		info.setCash( rs.getLong( "cash" ) );
+		info.setLanguage( rs.getString( "language" ) );
+		info.setNextTick( rs.getLong( "game_time" ) );
+		info.setAccountId( rs.getInt( "account_id" ) );
+
+		String statusString = rs.getString( "status" );
+		info.setStatus( rs.wasNull( ) ? null : statusString.charAt( 0 ) );
+
+		return info;
+	}
+
+}
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql b/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
index 563c356..16443aa 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
+++ b/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
@@ -506,6 +506,7 @@ CREATE VIEW emp.enemies
 -- General information view
 --
 
+DROP VIEW IF EXISTS emp.general_information CASCADE;
 CREATE VIEW emp.general_information
 	AS SELECT e.name_id AS id , en.name AS name ,
 			  ( CASE
@@ -516,13 +517,17 @@ CREATE VIEW emp.general_information
 			  END ) AS status ,
 			  e.cash AS cash , a.tag AS alliance ,
 			  st.next_tick AS game_time ,
-			  av.id AS account_id
+			  av.id AS account_id ,
+			  av.language AS language
 		FROM emp.empires e
-			INNER JOIN naming.empire_names en ON en.id = e.name_id
-			INNER JOIN users.accounts_view av ON av.id = en.owner_id
+			INNER JOIN naming.empire_names en
+				ON en.id = e.name_id
+			INNER JOIN users.accounts_view av
+				ON av.id = en.owner_id
 			LEFT OUTER JOIN emp.alliance_members am
 				ON am.empire_id = e.name_id AND NOT am.is_pending
-			LEFT OUTER JOIN emp.alliances a ON a.id = am.alliance_id
+			LEFT OUTER JOIN emp.alliances a
+				ON a.id = am.alliance_id
 			CROSS JOIN sys.status st;
 
 GRANT SELECT ON emp.general_information TO :dbuser;
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java b/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
index 82b7270..afd37d3 100644
--- a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
+++ b/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
@@ -3,11 +3,12 @@ package com.deepclone.lw.sqld.game;
 
 public class GeneralInformation
 {
+	private String name;
+
+	private String language;
 
 	private Character status;
 
-	private String name;
-
 	private String tag;
 
 	private long cash;
@@ -17,50 +18,87 @@ public class GeneralInformation
 	private int accountId;
 
 
-	public GeneralInformation( Character status , String name , String tag , long cash , long nextTick , int accountId )
+	public String getName( )
+	{
+		return this.name;
+	}
+
+
+	public void setName( String name )
 	{
-		this.status = status;
 		this.name = name;
-		this.tag = tag;
-		this.cash = cash;
-		this.nextTick = nextTick;
-		this.accountId = accountId;
+	}
+
+
+	public String getLanguage( )
+	{
+		return this.language;
+	}
+
+
+	public void setLanguage( String language )
+	{
+		this.language = language;
 	}
 
 
 	public Character getStatus( )
 	{
-		return status;
+		return this.status;
 	}
 
 
-	public String getName( )
+	public void setStatus( Character status )
 	{
-		return name;
+		this.status = status;
 	}
 
 
 	public String getTag( )
 	{
-		return tag;
+		return this.tag;
+	}
+
+
+	public void setTag( String tag )
+	{
+		this.tag = tag;
 	}
 
 
 	public long getCash( )
 	{
-		return cash;
+		return this.cash;
+	}
+
+
+	public void setCash( long cash )
+	{
+		this.cash = cash;
 	}
 
 
 	public long getNextTick( )
 	{
-		return nextTick;
+		return this.nextTick;
+	}
+
+
+	public void setNextTick( long nextTick )
+	{
+		this.nextTick = nextTick;
 	}
 
 
 	public int getAccountId( )
 	{
-		return accountId;
+		return this.accountId;
+	}
+
+
+	public void setAccountId( int accountId )
+	{
+		this.accountId = accountId;
 	}
 
 }
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
index 9c5eb39..92ada50 100644
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
+++ b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
@@ -1,6 +1,8 @@
 package com.deepclone.lw.interfaces.i18n;
 
 
+import java.util.Collection;
+import java.util.Map;
 import java.util.Set;
 
 
@@ -8,12 +10,12 @@ import java.util.Set;
 /**
  * Translator service interface
  * 
+ * <p>
  * This interface defines the methods available on the Translator service. One such service should
  * be present on all nodes. All Translator service instances are managed by the I18NManager service,
  * which is shared between nodes and notifies Translator instances of database updates.
  * 
- * @author tseeker
- * 
+ * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
  */
 public interface Translator
 {
@@ -62,4 +64,28 @@ public interface Translator
 	 */
 	public String translate( String language , String string )
 			throws UnknownStringException , UnknownLanguageException;
+
+
+	/**
+	 * Translate multiple strings based on their identifiers
+	 * 
+	 * <p>
+	 * This method must be implemented to allow "en masse" string translations. It will fetch the
+	 * translations in a given language for an arbitrary quantity of string identifiers, returning
+	 * the results as a map of identifiers to translations.
+	 * 
+	 * @param language
+	 *            the identifier of the language to translate to
+	 * @param strings
+	 *            a collection of string identifiers
+	 * 
+	 * @return a map associating string identifiers to translations
+	 * 
+	 * @throws UnknownStringException
+	 *             if one of the string identifiers does not match a string
+	 * @throws UnknownLanguageException
+	 *             if the language does not exist or is not supported
+	 */
+	public Map< String , String > translate( String language , Collection< String > strings )
+			throws UnknownStringException , UnknownLanguageException;
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java
index 82e1767..59cef53 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java
@@ -8,23 +8,91 @@ import java.util.List;
 
 
 
+/**
+ * General information included in a game response
+ * 
+ * <p>
+ * This class stores common information which is included in most in-game responses. This
+ * information includes some essential preferences, the general state of the empire, and some
+ * information about the server's state.
+ * 
+ * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ */
 public class GamePageData
 		implements Serializable
 {
-
+	/**
+	 * The serialisation version identifier
+	 * 
+	 * <ul>
+	 * <li>Introduced in B6M1 with ID 1
+	 * <li>Modified in B6M2, ID set to 2
+	 * </ul>
+	 */
 	private static final long serialVersionUID = 1L;
+
+	/** The name of the current empire */
 	private final String empire;
+
+	/**
+	 * State of the account
+	 * 
+	 * <p>
+	 * This field indicates the "special" state of the account: <code>q</code> is for accounts that
+	 * are quitting, <code>v</code> for accounts in vacation mode and <code>s</code> for accounts
+	 * that are about to enter vacation mode. <code>null</code> indicates "none of the above".
+	 */
 	private final Character special;
+
+	/** Alliance tag, or <code>null</code> if not a full member of any alliance */
 	private final String alliance;
+
+	/**
+	 * Current cash of the empire
+	 * 
+	 * <p>
+	 * FIXME: will be replaced with actual resources
+	 */
 	private final long cash;
+
+	/** Timestamp from the server's system */
 	private final Date serverTime;
+
+	/** Current game time (from last update identifier) */
 	private final GameTime gameTime;
+
+	/** Planets owned by the empire */
 	private final List< NameIdPair > planets;
+
+	/** Whether the player wants to see "real" times or in-game times */
 	private final boolean useRLTime;
 
+	/** Code of selected language */
+	private final String language;
 
+
+	/**
+	 * Initialise the general game information record
+	 * 
+	 * @param empire
+	 *            the empire's name
+	 * @param special
+	 *            the special account state character (see {@link #special})
+	 * @param alliance
+	 *            current alliance tag
+	 * @param cash
+	 *            current cash
+	 * @param gameTime
+	 *            last update identifier
+	 * @param planets
+	 *            list of planets owned by the empire
+	 * @param useRLTime
+	 *            whether the player wants to see "real" times or in-game times
+	 * @param language
+	 *            selected language code
+	 */
 	public GamePageData( String empire , Character special , String alliance , long cash , long gameTime ,
-			List< NameIdPair > planets , boolean useRLTime )
+			List< NameIdPair > planets , boolean useRLTime , String language )
 	{
 		this.empire = empire;
 		this.special = special;
@@ -34,54 +102,107 @@ public class GamePageData
 		this.gameTime = new GameTime( gameTime );
 		this.planets = Collections.unmodifiableList( planets );
 		this.useRLTime = useRLTime;
+		this.language = language;
 	}
 
 
+	/**
+	 * Gets the name of the current empire.
+	 * 
+	 * @return the name of the current empire
+	 */
 	public String getEmpire( )
 	{
-		return empire;
+		return this.empire;
 	}
 
 
+	/**
+	 * Gets the state of the account
+	 * 
+	 * @return the state of the account
+	 */
 	public Character getSpecial( )
 	{
-		return special;
+		return this.special;
 	}
 
 
+	/**
+	 * Gets the alliance tag
+	 * 
+	 * @return the alliance tag, or <code>null</code> if not a full member of any alliance
+	 */
 	public String getAlliance( )
 	{
-		return alliance;
+		return this.alliance;
 	}
 
 
+	/**
+	 * Gets the current cash of the empire
+	 * 
+	 * @return the current cash of the empire
+	 */
 	public long getCash( )
 	{
-		return cash;
+		return this.cash;
 	}
 
 
+	/**
+	 * Gets the timestamp from the server's system.
+	 * 
+	 * @return the timestamp from the server's system
+	 */
 	public Date getServerTime( )
 	{
-		return serverTime;
+		return this.serverTime;
 	}
 
 
+	/**
+	 * Gets the current game time
+	 * 
+	 * @return the current game time
+	 */
 	public GameTime getGameTime( )
 	{
-		return gameTime;
+		return this.gameTime;
 	}
 
 
+	/**
+	 * Gets the planets owned by the empire.
+	 * 
+	 * @return the list of planets owned by the empire
+	 */
 	public List< NameIdPair > getPlanets( )
 	{
-		return planets;
+		return this.planets;
 	}
 
 
+	/**
+	 * Checks if the player wants to see "real" times or in-game times.
+	 * 
+	 * @return <code>true</code> if the player wants to see "real" times, <code>false</code> for
+	 *         in-game times
+	 */
 	public boolean isUseRLTime( )
 	{
-		return useRLTime;
+		return this.useRLTime;
+	}
+
+
+	/**
+	 * Gets the code of selected language.
+	 * 
+	 * @return the code of selected language
+	 */
+	public String getLanguage( )
+	{
+		return this.language;
 	}
 
 }