[glom] translations change in progress



commit e2429937ec4049d86e0badc80dc3245d4fca9577
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Jan 13 18:54:26 2012 +0100

    translations change in progress
    
    More in progress
    
    More in progress 2

 glom/application.cc                                |   74 ++++++++++++++-
 glom/application.h                                 |   22 +++++
 glom/box_reports.cc                                |    9 +-
 glom/frame_glom.cc                                 |    6 +-
 glom/libglom/data_structure/has_title_singular.cc  |   23 +++--
 glom/libglom/data_structure/has_title_singular.h   |   10 ++-
 .../data_structure/layout/fieldformatting.cc       |    8 +-
 .../data_structure/layout/fieldformatting.h        |    4 +-
 .../data_structure/layout/layoutitem_field.cc      |   81 ++++++++++++++--
 .../data_structure/layout/layoutitem_field.h       |   24 ++++-
 .../data_structure/layout/layoutitem_portal.cc     |    8 +-
 .../data_structure/layout/layoutitem_portal.h      |    6 +-
 .../data_structure/layout/layoutitem_text.cc       |   13 ++-
 .../data_structure/layout/layoutitem_text.h        |    9 ++-
 .../layout/report_parts/layoutitem_fieldsummary.cc |    8 +-
 .../layout/report_parts/layoutitem_fieldsummary.h  |    6 +-
 .../data_structure/layout/usesrelationship.cc      |   12 +-
 .../data_structure/layout/usesrelationship.h       |    4 +-
 glom/libglom/data_structure/translatable_item.cc   |  100 ++++----------------
 glom/libglom/data_structure/translatable_item.h    |   65 ++++++-------
 glom/libglom/db_utils.cc                           |   10 +-
 glom/libglom/document/document.cc                  |   78 +++++++++-------
 glom/libglom/document/document.h                   |    8 +-
 glom/libglom/example_document_load.cc              |    6 +-
 glom/libglom/report_builder.cc                     |   19 ++--
 glom/libglom/report_builder.h                      |    5 +-
 glom/libglom/translations_po.cc                    |    2 +-
 glom/mode_data/box_data_calendar_related.cc        |    4 +-
 glom/mode_data/box_data_list_related.cc            |    3 +-
 glom/mode_data/box_data_manyrecords.cc             |    3 +-
 glom/mode_data/box_data_portal.cc                  |    8 +-
 glom/mode_data/box_data_portal.h                   |    4 +-
 glom/mode_data/datawidget/cellcreation.cc          |    5 +-
 .../datawidget/combochoiceswithtreemodel.cc        |    3 +-
 glom/mode_data/datawidget/datawidget.cc            |    2 +-
 glom/mode_data/datawidget/dialog_choose_id.cc      |    3 +-
 glom/mode_data/datawidget/dialog_new_record.cc     |    3 +-
 glom/mode_data/db_adddel/db_adddel.cc              |    2 +-
 glom/mode_data/flowtablewithfields.cc              |   33 ++++---
 glom/mode_data/test_flowtablewithfields.cc         |    4 +-
 glom/mode_design/box_db_table_relationships.cc     |    9 +-
 glom/mode_design/dialog_design.cc                  |    3 +-
 glom/mode_design/fields/box_db_table_definition.cc |    7 +-
 glom/mode_design/fields/dialog_fieldcalculation.cc |    1 +
 glom/mode_design/fields/dialog_fielddefinition.cc  |    7 +-
 glom/mode_design/layout/combobox_fields.cc         |    3 +-
 glom/mode_design/layout/combobox_relationship.cc   |    9 +-
 glom/mode_design/layout/dialog_choose_field.cc     |   11 +-
 .../layout/dialog_choose_relationship.cc           |    2 +-
 glom/mode_design/layout/dialog_layout_details.cc   |   15 ++--
 .../layout_item_dialogs/dialog_buttonscript.cc     |    5 +-
 .../layout_item_dialogs/dialog_field_layout.cc     |    7 +-
 .../layout_item_dialogs/dialog_imageobject.cc      |    5 +-
 .../layout/layout_item_dialogs/dialog_notebook.cc  |    5 +-
 .../layout_item_dialogs/dialog_textobject.cc       |    9 +-
 .../mode_design/print_layouts/box_print_layouts.cc |    9 +-
 .../print_layouts/window_print_layout_edit.cc      |   12 +-
 .../relationships_overview/canvas_group_dbtable.cc |    5 +-
 .../dialog_relationships_overview.cc               |    4 +-
 .../report_layout/dialog_layout_report.cc          |    7 +-
 .../translation/dialog_change_language.cc          |    3 +-
 .../translation/dialog_copy_translation.cc         |    3 +-
 .../translation/dialog_identify_original.cc        |    5 +-
 .../mode_design/translation/window_translations.cc |    7 +-
 glom/mode_design/users/dialog_groups_list.cc       |    5 +-
 glom/navigation/box_tables.cc                      |   18 ++--
 glom/print_layout/canvas_layout_item.cc            |    3 +-
 glom/print_layout/print_layout_utils.cc            |   12 ++-
 glom/utility_widgets/dialog_flowtable.cc           |    3 +-
 glom/utility_widgets/dialog_flowtable.h            |    5 +-
 glom/utility_widgets/notebooklabelglom.cc          |    7 +-
 glom/utils_ui.cc                                   |    3 +-
 tests/test_document_change.cc                      |    4 +-
 tests/test_document_load.cc                        |   12 +-
 tests/test_document_load_translations.cc           |   63 ++++++-------
 tests/test_selfhosting_new_then_report.cc          |    4 +-
 tests/translations_po/test_document_import_po.cc   |    4 +-
 77 files changed, 582 insertions(+), 411 deletions(-)
---
diff --git a/glom/application.cc b/glom/application.cc
index 3a9c04d..9b6379f 100644
--- a/glom/application.cc
+++ b/glom/application.cc
@@ -68,6 +68,9 @@ namespace Glom
 // Global application variable
 Application* global_application = 0;
 
+Glib::ustring Application::m_current_locale;
+Glib::ustring Application::m_original_locale;
+
 const char* Application::glade_id("window_main");
 const bool Application::glade_developer(false);
 
@@ -906,9 +909,14 @@ void Application::init_create_document()
   if(!m_pDocument)
   {
     Document* document_glom = new Document();
+
+    //By default, we assume that the original is in the current locale.
+    document_glom->set_translation_original_locale(Application::get_current_locale());
+
     m_pDocument = document_glom;
     //document_glom->set_parent_window(this); //So that it can show a BusyCursor when loading and saving.
 
+
     //Tell document about view:
     m_pDocument->set_view(m_pFrame);
 
@@ -987,6 +995,9 @@ bool Application::on_document_load()
   if(!pDocument)
     return false;
 
+  //Set this so that Application::get_current_locale() works as expected:
+  Application::set_original_locale(pDocument->get_translation_original_locale());
+
   if(!pDocument->get_is_new() && !check_document_hosting_mode_is_supported(pDocument))
     return false;
 
@@ -1998,7 +2009,7 @@ void Application::fill_menu_tables()
 
       ui_description += "<menuitem action='" + action_name + "' />";
 
-      Glib::RefPtr<Gtk::Action> refAction = Gtk::Action::create(action_name, Utils::string_escape_underscores(table_info->get_title_or_name()));
+      Glib::RefPtr<Gtk::Action> refAction = Gtk::Action::create(action_name, Utils::string_escape_underscores(table_info->get_title_or_name(Application::get_current_locale())));
       m_refNavTablesActionGroup->add(refAction,
         sigc::bind( sigc::mem_fun(*m_pFrame, &Frame_Glom::on_box_tables_selected), table_info->get_name()) );
 
@@ -2067,7 +2078,7 @@ void Application::fill_menu_reports(const Glib::ustring& table_name)
 
         ui_description += "<menuitem action='" + action_name + "' />";
 
-        Glib::RefPtr<Gtk::Action> refAction = Gtk::Action::create( action_name, Utils::string_escape_underscores(report->get_title_or_name()));
+        Glib::RefPtr<Gtk::Action> refAction = Gtk::Action::create( action_name, Utils::string_escape_underscores(report->get_title_or_name(Application::get_current_locale())));
         m_refNavReportsActionGroup->add(refAction,
           sigc::bind( sigc::mem_fun(*m_pFrame, &Frame_Glom::on_menu_report_selected), report->get_name()) );
 
@@ -2148,7 +2159,7 @@ void Application::fill_menu_print_layouts(const Glib::ustring& table_name)
 
         ui_description += "<menuitem action='" + action_name + "' />";
 
-        Glib::RefPtr<Gtk::Action> refAction = Gtk::Action::create( action_name, Utils::string_escape_underscores(print_layout->get_title_or_name()));
+        Glib::RefPtr<Gtk::Action> refAction = Gtk::Action::create( action_name, Utils::string_escape_underscores(print_layout->get_title_or_name(Application::get_current_locale())));
         m_refNavPrintLayoutsActionGroup->add(refAction,
           sigc::bind( sigc::mem_fun(*m_pFrame, &Frame_Glom::on_menu_print_layout_selected), print_layout->get_name()) );
 
@@ -2513,7 +2524,7 @@ void Application::on_menu_developer_changelanguage()
 
   if(response == Gtk::RESPONSE_OK)
   {
-    TranslatableItem::set_current_locale(dialog->get_locale());
+    Application::set_current_locale(dialog->get_locale());
 
     //Get the translations from the document (in Operator mode, we only load the necessary translations.)
     //This also updates the UI, so we show all the translated titles:
@@ -2733,7 +2744,7 @@ void Application::update_window_title()
 
   //Show the table title:
   const Glib::ustring table_name = m_pFrame->get_shown_table_name();
-  Glib::ustring table_label = document->get_table_title(table_name);
+  Glib::ustring table_label = document->get_table_title(table_name, Application::get_current_locale());
   if(!table_label.empty())
   {
     #ifndef GLOM_ENABLE_CLIENT_ONLY
@@ -2840,4 +2851,57 @@ void Application::clear_progress_message()
   m_pFrame->set_sensitive();
 }
 
+void Application::set_current_locale(const Glib::ustring& locale)
+{
+  if(locale.empty())
+    return;
+
+  m_current_locale = locale;
+}
+
+void Application::set_original_locale(const Glib::ustring& locale)
+{
+  if(locale.empty())
+    return;
+
+  m_original_locale = locale;
+}
+
+Glib::ustring Application::get_original_locale()
+{
+  if(m_original_locale.empty())
+    m_original_locale = "en_US"; //"en_US.UTF-8";
+
+  return m_original_locale; 
+}
+
+bool Application::get_current_locale_not_original() //TODO: Make this const?
+{
+  if(m_original_locale.empty())
+    get_original_locale();
+
+  if(m_current_locale.empty())
+    get_current_locale();
+
+  return m_original_locale != m_current_locale;
+}
+
+Glib::ustring Application::get_current_locale()
+{
+  //Return a previously-set current locale, if any:
+  if(!m_current_locale.empty())
+    return m_current_locale;
+
+  //Get the user's current locale:
+  const char* cLocale = setlocale(LC_ALL, 0); //Passing NULL means query, instead of set.
+  if(cLocale)
+  {
+    //std::cout << "debug1: " << G_STRFUNC << ": locale=" << cLocale << std::endl;
+    return Utils::locale_simplify(cLocale);
+    //std::cout << "debug2: " << G_STRFUNC << ": m_current_locale=" << m_current_locale << std::endl;
+  }
+  else
+    return "C";
+}
+
 } //namespace Glom
diff --git a/glom/application.h b/glom/application.h
index 073792f..7fae93d 100644
--- a/glom/application.h
+++ b/glom/application.h
@@ -128,6 +128,26 @@ public:
   void pulse_progress_message();
   void clear_progress_message();
 
+  /** Set the locale used for original text of titles. This 
+   * must usually be stored in the document. 
+   * Ideally, it would be English.
+   */
+  static void set_original_locale(const Glib::ustring& locale);
+
+  static Glib::ustring get_original_locale();
+
+  static bool get_current_locale_not_original();
+
+  /** Set the locale used for titles, to test translations.
+   * Usually the current locale is just the locale at startup.
+   */
+  static void set_current_locale(const Glib::ustring& locale);
+
+  /** Get the locale used by this program when it was started,
+   * or the locale set by set_current_locale().
+   */
+  static Glib::ustring get_current_locale();
+
   static Application* get_application();
 
 protected:
@@ -272,6 +292,8 @@ private:
   Glib::ustring m_temp_username, m_temp_password;
 
   bool m_show_sql_debug;
+
+  static Glib::ustring m_current_locale, m_original_locale;
 };
 
 } //namespace Glom
diff --git a/glom/box_reports.cc b/glom/box_reports.cc
index 7a85e7c..3a820f0 100644
--- a/glom/box_reports.cc
+++ b/glom/box_reports.cc
@@ -19,6 +19,7 @@
  */
 
 #include <glom/box_reports.h>
+#include <glom/application.h>
 #include <libglom/utils.h> //For bold_message()).
 #include <gtkmm/alignment.h>
 #include <gtkmm/dialog.h>
@@ -64,7 +65,7 @@ void Box_Reports::fill_row(const Gtk::TreeModel::iterator& iter, const sharedptr
     const Glib::ustring report_name = report->get_name();
     m_AddDel.set_value_key(iter, report_name);
     m_AddDel.set_value(iter, m_colReportName, report_name);
-    m_AddDel.set_value(iter, m_colTitle, report->get_title());
+    m_AddDel.set_value(iter, m_colTitle, report->get_title(Application::get_current_locale()));
   }
 }
 
@@ -140,7 +141,7 @@ void Box_Reports::on_adddel_Add(const Gtk::TreeModel::iterator& row)
       m_AddDel.set_value(row, m_colTitle, title);
     }
 
-    report->set_title(title);
+    report->set_title(title, Application::get_current_locale());
 
     get_document()->set_report(m_table_name, report);
   }
@@ -188,7 +189,7 @@ void Box_Reports::save_to_document()
         sharedptr<Report> report(new Report());
         report->set_name(report_name);
 
-        report->set_title( m_AddDel.get_value(iter, m_colTitle) ); //TODO: Translations: Store the original in the TreeView.
+        report->set_title( m_AddDel.get_value(iter, m_colTitle) , Application::get_current_locale()); //TODO: Translations: Store the original in the TreeView.
 
         get_document()->set_report(m_table_name, report);
         modified = true;
@@ -213,7 +214,7 @@ void Box_Reports::on_adddel_changed(const Gtk::TreeModel::iterator& row, guint c
     {
       if(column == m_colTitle)
       {
-        report->set_title( m_AddDel.get_value(row, m_colTitle) );
+        report->set_title( m_AddDel.get_value(row, m_colTitle) , Application::get_current_locale());
         //TODO: Unnecessary:
         document->set_report(m_table_name, report);
       }
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index 25df6f8..c36ce2b 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -1167,7 +1167,7 @@ void Frame_Glom::on_dialog_add_related_table_response(int response)
       sharedptr<Relationship> relationship = sharedptr<Relationship>::create();
 
       relationship->set_name(relationship_name);
-      relationship->set_title(Utils::title_from_string(relationship_name));
+      relationship->set_title(Utils::title_from_string(relationship_name), Application::get_current_locale());
       relationship->set_from_table(m_table_name);
       relationship->set_from_field(from_key_name);
       relationship->set_to_table(table_name);
@@ -1365,7 +1365,7 @@ void Frame_Glom::show_table_title()
     return;
 
   //Show the table title:
-  Glib::ustring table_label = document->get_table_title(m_table_name);
+  Glib::ustring table_label = document->get_table_title(m_table_name, Application::get_current_locale());
   if(!table_label.empty())
   {
     if(document->get_userlevel() == AppState::USERLEVEL_DEVELOPER)
@@ -2294,7 +2294,7 @@ void Frame_Glom::on_menu_report_selected(const Glib::ustring& report_name)
 
   FoundSet found_set = m_Notebook_Data.get_found_set();
 
-  ReportBuilder report_builder;
+  ReportBuilder report_builder(Application::get_current_locale());
   report_builder.set_document(document);
   const std::string filepath = 
     report_builder.report_build_and_save(found_set, report); //TODO: Use found set's where_clause.
diff --git a/glom/libglom/data_structure/has_title_singular.cc b/glom/libglom/data_structure/has_title_singular.cc
index e09fd13..63ffaf0 100644
--- a/glom/libglom/data_structure/has_title_singular.cc
+++ b/glom/libglom/data_structure/has_title_singular.cc
@@ -59,18 +59,27 @@ bool HasTitleSingular::operator!=(const HasTitleSingular& src) const
 }
 
 
-Glib::ustring HasTitleSingular::get_title_singular() const
+Glib::ustring HasTitleSingular::get_title_singular(const Glib::ustring& locale) const
 {
   Glib::ustring result;
   if(m_title_singular)
-    result = m_title_singular->get_title();
+    result = m_title_singular->get_title(locale);
 
   return result;
 }
 
-Glib::ustring HasTitleSingular::get_title_singular_with_fallback() const
+Glib::ustring HasTitleSingular::get_title_singular_original() const
 {
-  const Glib::ustring result = get_title_singular();
+  Glib::ustring result;
+  if(m_title_singular)
+    result = m_title_singular->get_title_original();
+
+  return result;
+}
+
+Glib::ustring HasTitleSingular::get_title_singular_with_fallback(const Glib::ustring& locale) const
+{
+  const Glib::ustring result = get_title_singular(locale);
   if(!result.empty())
     return result;
   
@@ -78,18 +87,18 @@ Glib::ustring HasTitleSingular::get_title_singular_with_fallback() const
   //then try getting the regular title instead.
   const TranslatableItem* translatable = dynamic_cast<const TranslatableItem*>(this);
   if(translatable)
-    return translatable->get_title_or_name();
+    return translatable->get_title_or_name(locale);
 
   return result;
 }
 
 
-void HasTitleSingular::set_title_singular(const Glib::ustring& title)
+void HasTitleSingular::set_title_singular(const Glib::ustring& title, const Glib::ustring& locale)
 {
   if(!m_title_singular)
     m_title_singular = sharedptr<TranslatableItem>::create();
 
-  m_title_singular->set_title(title);
+  m_title_singular->set_title(title, locale);
 }
 
 } //namespace Glom
diff --git a/glom/libglom/data_structure/has_title_singular.h b/glom/libglom/data_structure/has_title_singular.h
index b16a2b1..b5f9571 100644
--- a/glom/libglom/data_structure/has_title_singular.h
+++ b/glom/libglom/data_structure/has_title_singular.h
@@ -45,17 +45,21 @@ public:
   /** Get the (translation of the) singular form of the title, in the current locale, 
    * if specified.
    */
-  Glib::ustring get_title_singular() const;
+  Glib::ustring get_title_singular(const Glib::ustring& locale) const;
+
+  /** Get the title's original (non-translated, usually English) text.
+   */
+  Glib::ustring get_title_singular_original() const;
 
   /** Get the (translation of the) singular form of the title, in the current locale, 
    * if specified, falling back to the non-singular title, and 
    * then falling back to the table name.
    */
-  Glib::ustring get_title_singular_with_fallback() const;
+  Glib::ustring get_title_singular_with_fallback(const Glib::ustring& locale) const;
 
   /** Set the singular title's translation for the current locale.
    */
-  void set_title_singular(const Glib::ustring& title);
+  void set_title_singular(const Glib::ustring& title, const Glib::ustring& locale);
 
   /** For instance, "Customer" if the table is titled "Customers".
    * This is useful in some UI strings.
diff --git a/glom/libglom/data_structure/layout/fieldformatting.cc b/glom/libglom/data_structure/layout/fieldformatting.cc
index 2d34957..7696e8b 100644
--- a/glom/libglom/data_structure/layout/fieldformatting.cc
+++ b/glom/libglom/data_structure/layout/fieldformatting.cc
@@ -207,7 +207,7 @@ void FieldFormatting::set_choices_custom(const type_list_values& choices)
   m_choices_custom_list = choices;
 }
 
-Glib::ustring FieldFormatting::get_custom_choice_original_for_translated_text(const Glib::ustring& text) const
+Glib::ustring FieldFormatting::get_custom_choice_original_for_translated_text(const Glib::ustring& text, const Glib::ustring& locale) const
 {
   for(FieldFormatting::type_list_values::const_iterator iter = m_choices_custom_list.begin(); iter != m_choices_custom_list.end(); ++iter)
   {
@@ -215,14 +215,14 @@ Glib::ustring FieldFormatting::get_custom_choice_original_for_translated_text(co
     if(!value)
       continue;
 
-    if(value->get_title() == text)
+    if(value->get_title(locale) == text)
       return value->get_title_original();
   }
 
   return Glib::ustring();
 }
 
-Glib::ustring FieldFormatting::get_custom_choice_translated(const Glib::ustring& original_text) const
+Glib::ustring FieldFormatting::get_custom_choice_translated(const Glib::ustring& original_text, const Glib::ustring& locale) const
 {
   for(FieldFormatting::type_list_values::const_iterator iter = m_choices_custom_list.begin(); iter != m_choices_custom_list.end(); ++iter)
   {
@@ -231,7 +231,7 @@ Glib::ustring FieldFormatting::get_custom_choice_translated(const Glib::ustring&
       continue;
 
     if(value->get_title_original() == original_text)
-      return value->get_title();
+      return value->get_title(locale);
   }
 
   return Glib::ustring();
diff --git a/glom/libglom/data_structure/layout/fieldformatting.h b/glom/libglom/data_structure/layout/fieldformatting.h
index 2fc23c4..3d97023 100644
--- a/glom/libglom/data_structure/layout/fieldformatting.h
+++ b/glom/libglom/data_structure/layout/fieldformatting.h
@@ -62,12 +62,12 @@ public:
   /** Get the original text that corresponds to the translated choice for the 
    * current locale.
    */
-  Glib::ustring get_custom_choice_original_for_translated_text(const Glib::ustring& text) const;
+  Glib::ustring get_custom_choice_original_for_translated_text(const Glib::ustring& text, const Glib::ustring& locale = Glib::ustring()) const;
 
   /** Get the translated choice text, for the 
    * current locale, that corresponds to the original text .
    */
-  Glib::ustring get_custom_choice_translated(const Glib::ustring& original_text) const;
+  Glib::ustring get_custom_choice_translated(const Glib::ustring& original_text, const Glib::ustring& locale = Glib::ustring()) const;
 
   typedef std::pair< sharedptr<const LayoutItem_Field>, bool /* is_ascending */> type_pair_sort_field;
   typedef std::list<type_pair_sort_field> type_list_sort_fields;
diff --git a/glom/libglom/data_structure/layout/layoutitem_field.cc b/glom/libglom/data_structure/layout/layoutitem_field.cc
index d80a2c1..da2adb4 100644
--- a/glom/libglom/data_structure/layout/layoutitem_field.cc
+++ b/glom/libglom/data_structure/layout/layoutitem_field.cc
@@ -115,53 +115,114 @@ Glib::ustring LayoutItem_Field::get_name() const
   return LayoutItem_WithFormatting::get_name();
 }
 
-Glib::ustring LayoutItem_Field::get_title_no_custom() const
+Glib::ustring LayoutItem_Field::get_title_no_custom(const Glib::ustring& locale) const
 {
   //Use the field's default title:
   if(m_field_cache_valid && m_field)
   {
-    return m_field->get_title_or_name();
+    return m_field->get_title_or_name(locale);
+  }
+  else
+    return get_name(); //We ignore TranslatableItem::get_title() for LayoutItem_Field.
+}
+
+Glib::ustring LayoutItem_Field::get_title_no_custom_translation(const Glib::ustring& locale, bool fallback) const
+{
+  //Use the field's default title:
+  if(m_field_cache_valid && m_field)
+  {
+    return m_field->get_title_translation(locale, fallback);
+  }
+  else
+    return Glib::ustring();
+}
+
+Glib::ustring LayoutItem_Field::get_title_no_custom_original() const
+{
+  //Use the field's default title:
+  if(m_field_cache_valid && m_field)
+  {
+    return m_field->get_title_original();
   }
   else
     return get_name(); //We ignore TranslatableItem::get_title() for LayoutItem_Field.
 }
 
 
-Glib::ustring LayoutItem_Field::get_title_or_name_no_custom() const
+Glib::ustring LayoutItem_Field::get_title_or_name_no_custom(const Glib::ustring& locale) const
 {
   //Use the field's default title:
   if(m_field_cache_valid && m_field)
   {
-    return m_field->get_title();
+    return m_field->get_title(locale);
   }
 
   return Glib::ustring();
 }
 
-Glib::ustring LayoutItem_Field::get_title() const
+Glib::ustring LayoutItem_Field::get_title(const Glib::ustring& locale) const
+{
+  //Use the custom title (overriding the field's default title), if there is one:
+  //This may even be empty if the developer specifies that.
+  if(m_title_custom && m_title_custom->get_use_custom_title())
+  {
+    return m_title_custom->get_title(locale);
+  }
+
+  //Use the field's default title:
+  return get_title_no_custom(locale);
+}
+
+Glib::ustring LayoutItem_Field::get_title_translation(const Glib::ustring& locale, bool fallback) const
+{
+  //Use the custom title (overriding the field's default title), if there is one:
+  //This may even be empty if the developer specifies that.
+  if(m_title_custom && m_title_custom->get_use_custom_title())
+  {
+    return m_title_custom->get_title_translation(locale, fallback);
+  }
+
+  return m_field->get_title_translation(locale, fallback);
+}
+
+Glib::ustring LayoutItem_Field::get_title_original() const
+{
+  //Use the custom title (overriding the field's default title), if there is one:
+  //This may even be empty if the developer specifies that.
+  if(m_title_custom && m_title_custom->get_use_custom_title())
+  {
+    return m_title_custom->get_title_original();
+  }
+
+  //Use the field's default title:
+  return get_title_no_custom_original();
+}
+
+
+Glib::ustring LayoutItem_Field::get_title_or_name(const Glib::ustring& locale) const
 {
   //Use the custom title (overriding the field's default title), if there is one:
   //This may even be empty if the developer specifies that.
   if(m_title_custom && m_title_custom->get_use_custom_title())
   {
-    return m_title_custom->get_title();
+    return m_title_custom->get_title(locale);
   }
 
   //Use the field's default title:
-  return get_title_no_custom();
+  return get_title_no_custom(locale);
 }
 
-Glib::ustring LayoutItem_Field::get_title_or_name() const
+Glib::ustring LayoutItem_Field::get_title_or_name_original() const
 {
   //Use the custom title (overriding the field's default title), if there is one:
   //This may even be empty if the developer specifies that.
   if(m_title_custom && m_title_custom->get_use_custom_title())
   {
-    return m_title_custom->get_title();
+    return m_title_custom->get_title_original();
   }
 
   //Use the field's default title:
-  return get_title_no_custom();
+  return get_title_no_custom_original();
 }
 
 bool LayoutItem_Field::get_editable_and_allowed() const
diff --git a/glom/libglom/data_structure/layout/layoutitem_field.h b/glom/libglom/data_structure/layout/layoutitem_field.h
index fb2e1ae..49a64af 100644
--- a/glom/libglom/data_structure/layout/layoutitem_field.h
+++ b/glom/libglom/data_structure/layout/layoutitem_field.h
@@ -86,13 +86,24 @@ public:
   /** Get the user-visible title for the field, in the user's current locale.
    * This returns the name if no title is set.
    */
-  virtual Glib::ustring get_title() const;
+  virtual Glib::ustring get_title(const Glib::ustring& locale) const;
+
+  /** Get the user-visible title for the field, in the user's current locale.
+   * This returns the name if no title is set.
+   */
+  virtual Glib::ustring get_title_original() const;
+
+  virtual Glib::ustring get_title_translation(const Glib::ustring& locale, bool fallback = true) const;
 
   /** Get the user-visible title for the field, in the user's current locale.
    */
-  virtual Glib::ustring get_title_or_name() const;
+  virtual Glib::ustring get_title_or_name(const Glib::ustring& locale) const;
 
-  Glib::ustring get_title_or_name_no_custom() const;
+  /** Get the user-visible title for the field, in the original locale.
+   */
+  virtual Glib::ustring get_title_or_name_original() const;
+
+  Glib::ustring get_title_or_name_no_custom(const Glib::ustring& locale) const;
 
   sharedptr<const CustomTitle> get_title_custom() const;
   sharedptr<CustomTitle> get_title_custom();
@@ -163,7 +174,12 @@ public:
 
 private:
 
-  Glib::ustring get_title_no_custom() const;
+  Glib::ustring get_title_no_custom(const Glib::ustring& locale) const;
+
+  Glib::ustring get_title_no_custom_original() const;
+
+  Glib::ustring get_title_no_custom_translation(const Glib::ustring& locale, bool fallback = true) const;
+
 
   //This is just a cache, filled in by looking at the database structure:
   sharedptr<const Field> m_field;
diff --git a/glom/libglom/data_structure/layout/layoutitem_portal.cc b/glom/libglom/data_structure/layout/layoutitem_portal.cc
index 339bdf6..c231303 100644
--- a/glom/libglom/data_structure/layout/layoutitem_portal.cc
+++ b/glom/libglom/data_structure/layout/layoutitem_portal.cc
@@ -414,9 +414,9 @@ sharedptr<const LayoutItem_Field> LayoutItem_Portal::get_field_identifies_non_hi
   return result;
 }
 
-Glib::ustring LayoutItem_Portal::get_title_or_name() const
+Glib::ustring LayoutItem_Portal::get_title_or_name(const Glib::ustring& locale) const
 {
-  Glib::ustring title = get_title_used(Glib::ustring() /* parent table - not relevant */);
+  Glib::ustring title = get_title_used(Glib::ustring() /* parent table - not relevant */, locale);
   if(title.empty())
     title = get_relationship_name_used();
   
@@ -426,9 +426,9 @@ Glib::ustring LayoutItem_Portal::get_title_or_name() const
   return title;
 }
 
-Glib::ustring LayoutItem_Portal::get_title() const
+Glib::ustring LayoutItem_Portal::get_title(const Glib::ustring& locale) const
 {
-  Glib::ustring title = get_title_used(Glib::ustring() /* parent table - not relevant */);
+  Glib::ustring title = get_title_used(Glib::ustring() /* parent table - not relevant */, locale);
   if(title.empty()) //TODO: This prevents "" as a real title.
    title = _("Undefined Table");
 
diff --git a/glom/libglom/data_structure/layout/layoutitem_portal.h b/glom/libglom/data_structure/layout/layoutitem_portal.h
index 46964db..793ec5e 100644
--- a/glom/libglom/data_structure/layout/layoutitem_portal.h
+++ b/glom/libglom/data_structure/layout/layoutitem_portal.h
@@ -47,8 +47,10 @@ public:
 
   virtual LayoutItem* clone() const;
 
-  virtual Glib::ustring get_title() const;
-  virtual Glib::ustring get_title_or_name() const;
+  virtual Glib::ustring get_title(const Glib::ustring& locale) const;
+  //TODO: get_title_original() and get_title_translation()?
+  virtual Glib::ustring get_title_or_name(const Glib::ustring& locale) const;
+  //TODO: get_title_or_name_original()?
   virtual Glib::ustring get_part_type_name() const;
 
   virtual void change_field_item_name(const Glib::ustring& table_name, const Glib::ustring& field_name, const Glib::ustring& field_name_new);
diff --git a/glom/libglom/data_structure/layout/layoutitem_text.cc b/glom/libglom/data_structure/layout/layoutitem_text.cc
index c49f1a3..77e33dc 100644
--- a/glom/libglom/data_structure/layout/layoutitem_text.cc
+++ b/glom/libglom/data_structure/layout/layoutitem_text.cc
@@ -78,14 +78,19 @@ Glib::ustring LayoutItem_Text::get_report_part_id() const
   return "field"; //We reuse this for this node.
 }
 
-Glib::ustring LayoutItem_Text::get_text() const
+Glib::ustring LayoutItem_Text::get_text(const Glib::ustring& locale) const
 {
-  return m_text->get_title();
+  return m_text->get_title(locale);
 }
 
-void LayoutItem_Text::set_text(const Glib::ustring& text)
+void LayoutItem_Text::set_text(const Glib::ustring& text, const Glib::ustring& locale)
 {
-  m_text->set_title(text);
+  m_text->set_title(text, locale);
+}
+
+void LayoutItem_Text::set_text_original(const Glib::ustring& text)
+{
+  m_text->set_title_original(text);
 }
 
 } //namespace Glom
diff --git a/glom/libglom/data_structure/layout/layoutitem_text.h b/glom/libglom/data_structure/layout/layoutitem_text.h
index 4aad1bc..3244f74 100644
--- a/glom/libglom/data_structure/layout/layoutitem_text.h
+++ b/glom/libglom/data_structure/layout/layoutitem_text.h
@@ -46,11 +46,16 @@ public:
 
   /** Get the text that will be shown on each record.
    */
-  Glib::ustring get_text() const;
+  Glib::ustring get_text(const Glib::ustring& locale) const;
 
   /** Set the text that will be shown on each record.
    */
-  void set_text(const Glib::ustring& text);
+  void set_text(const Glib::ustring& text, const Glib::ustring& locale);
+
+  /** Set the text's original (non-translated, usually English) text.
+   * This is the same as calling set_text() with an empty locale parameter.
+   */
+  void set_text_original(const Glib::ustring& text);
 
   sharedptr<TranslatableItem> m_text; //Reuse the title concept of this class to give us translatable text.
 };
diff --git a/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.cc b/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.cc
index f656658..1318d61 100644
--- a/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.cc
+++ b/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.cc
@@ -59,16 +59,16 @@ LayoutItem_FieldSummary& LayoutItem_FieldSummary::operator=(const LayoutItem_Fie
   return *this;
 }
 
-Glib::ustring LayoutItem_FieldSummary::get_title_or_name() const
+Glib::ustring LayoutItem_FieldSummary::get_title_or_name(const Glib::ustring& locale) const
 {
-  const Glib::ustring field_title = get_full_field_details()->get_title_or_name();
+  const Glib::ustring field_title = get_full_field_details()->get_title_or_name(locale);
 
   return get_summary_type_name(m_summary_type) + ": " + field_title; //TODO: Allow a more human-readable title for summary headings.
 }
 
-Glib::ustring LayoutItem_FieldSummary::get_title() const
+Glib::ustring LayoutItem_FieldSummary::get_title(const Glib::ustring& locale) const
 {
-  const Glib::ustring field_title = get_full_field_details()->get_title();
+  const Glib::ustring field_title = get_full_field_details()->get_title(locale);
 
   return get_summary_type_name(m_summary_type) + ": " + field_title; //TODO: Allow a more human-readable title for summary headings.
 }
diff --git a/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h b/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h
index 9bdc16c..2d02943 100644
--- a/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h
+++ b/glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h
@@ -61,8 +61,10 @@ public:
 
   void set_field(const sharedptr<LayoutItem_Field>& field);
 
-  virtual Glib::ustring get_title() const;
-  virtual Glib::ustring get_title_or_name() const;
+  virtual Glib::ustring get_title(const Glib::ustring& locale) const;
+  //TODO: get_title_original() and get_title_translation():
+  virtual Glib::ustring get_title_or_name(const Glib::ustring& locale) const;
+  //TODO: get_title_or_name_original()?
 
   virtual Glib::ustring get_layout_display_name() const;
 
diff --git a/glom/libglom/data_structure/layout/usesrelationship.cc b/glom/libglom/data_structure/layout/usesrelationship.cc
index e7d3b71..91f7b28 100644
--- a/glom/libglom/data_structure/layout/usesrelationship.cc
+++ b/glom/libglom/data_structure/layout/usesrelationship.cc
@@ -135,17 +135,17 @@ Glib::ustring UsesRelationship::get_table_used(const Glib::ustring& parent_table
     return parent_table;
 }
 
-Glib::ustring UsesRelationship::get_title_used(const Glib::ustring& parent_table_title) const
+Glib::ustring UsesRelationship::get_title_used(const Glib::ustring& parent_table_title, const Glib::ustring& locale) const
 {
   if(m_related_relationship)
-    return m_related_relationship->get_title_or_name();
+    return m_related_relationship->get_title_or_name(locale);
   else if(m_relationship)
-    return m_relationship->get_title_or_name();
+    return m_relationship->get_title_or_name(locale);
   else
     return parent_table_title;
 }
 
-Glib::ustring UsesRelationship::get_title_singular_used(const Glib::ustring& parent_table_title) const
+Glib::ustring UsesRelationship::get_title_singular_used(const Glib::ustring& parent_table_title, const Glib::ustring& locale) const
 {
   sharedptr<const Relationship> used = m_related_relationship;
   if(!used)
@@ -154,11 +154,11 @@ Glib::ustring UsesRelationship::get_title_singular_used(const Glib::ustring& par
   if(!used)
     return Glib::ustring();
 
-  const Glib::ustring result = used->get_title_singular();
+  const Glib::ustring result = used->get_title_singular(locale);
   if(!result.empty())
     return result;
   else
-    return get_title_used(parent_table_title);
+    return get_title_used(parent_table_title, locale);
 }
 
 Glib::ustring UsesRelationship::get_to_field_used() const
diff --git a/glom/libglom/data_structure/layout/usesrelationship.h b/glom/libglom/data_structure/layout/usesrelationship.h
index 598dbe7..004b228 100644
--- a/glom/libglom/data_structure/layout/usesrelationship.h
+++ b/glom/libglom/data_structure/layout/usesrelationship.h
@@ -79,13 +79,13 @@ public:
    * falling back to the relationship's name.
    * @param parent_table_title The title of table to which the item (or its relatinoships) belong.
    */
-  Glib::ustring get_title_used(const Glib::ustring& parent_table_title) const;
+  Glib::ustring get_title_used(const Glib::ustring& parent_table_title, const Glib::ustring& locale) const;
   
   /** Get the singular title of the relationship that is actually used,
    * falling back to the regular (plural) title, and then to the relationship's name.
    * @param parent_table_title The title of table to which the item (or its relatinoships) belong.
    */
-  Glib::ustring get_title_singular_used(const Glib::ustring& parent_table_title) const;
+  Glib::ustring get_title_singular_used(const Glib::ustring& parent_table_title, const Glib::ustring& locale) const;
 
   Glib::ustring get_to_field_used() const;
 
diff --git a/glom/libglom/data_structure/translatable_item.cc b/glom/libglom/data_structure/translatable_item.cc
index 10e3fa2..e5f51ef 100644
--- a/glom/libglom/data_structure/translatable_item.cc
+++ b/glom/libglom/data_structure/translatable_item.cc
@@ -26,9 +26,6 @@
 namespace Glom
 {
 
-Glib::ustring TranslatableItem::m_current_locale;
-Glib::ustring TranslatableItem::m_original_locale;
-
 TranslatableItem::TranslatableItem()
 : m_translatable_item_type(TRANSLATABLE_TYPE_INVALID)
 {
@@ -89,11 +86,6 @@ Glib::ustring TranslatableItem::get_title_translation(const Glib::ustring& local
   type_map_locale_to_translations::const_iterator iterFind = m_map_translations.find(locale);
   if(iterFind != m_map_translations.end())
     return iterFind->second;
- 
-  //The original is not in m_map_translations,
-  //but we want to handle that locale too:
-  if(locale == m_original_locale)
-    return get_title_original();
 
   if(!fallback)
     return Glib::ustring();
@@ -143,12 +135,11 @@ bool TranslatableItem::get_has_translations() const
 }
 
 
-Glib::ustring TranslatableItem::get_title() const
+Glib::ustring TranslatableItem::get_title(const Glib::ustring& locale) const
 {
-  if(get_current_locale_not_original()) //Avoid this code if we don't need translations.
+  if(!locale.empty())
   {
-    const Glib::ustring current_locale_id = get_current_locale();
-    const Glib::ustring translated_title = get_title_translation(current_locale_id);
+    const Glib::ustring translated_title = get_title_translation(locale, true /* fallback */);
     if(!translated_title.empty())
       return translated_title;
   }
@@ -162,23 +153,15 @@ Glib::ustring TranslatableItem::get_title_original() const
   return m_title;
 }
 
-void TranslatableItem::set_title(const Glib::ustring& title)
+void TranslatableItem::set_title(const Glib::ustring& title, const Glib::ustring& locale)
 {
-  if(get_current_locale_not_original()) //Avoid this code if we don't need translations.
-  {
-    //std::cout << "TranslatableItem::set_title() setting translation: " << title;
-    const Glib::ustring the_locale = get_current_locale();
-    if(the_locale.empty())
-      set_title_original(title);
-    else
-    {
-      set_title_translation(the_locale, title);
-    }
-  }
-  else
+  if(locale.empty())
   {
     set_title_original(title);
+    return;
   }
+
+  set_title_translation(locale, title);
 }
 
 void TranslatableItem::set_title_original(const Glib::ustring& title)
@@ -198,60 +181,6 @@ void TranslatableItem::clear_title_in_all_locales()
   }
 }
 
-Glib::ustring TranslatableItem::get_current_locale()
-{
-  if(m_current_locale.empty())
-  {
-    const char* cLocale = setlocale(LC_ALL, 0); //Passing NULL means query, instead of set.
-    if(cLocale)
-    {
-      //std::cout << "debug1: " << G_STRFUNC << ": locale=" << cLocale << std::endl;
-      m_current_locale = Utils::locale_simplify(cLocale);
-      //std::cout << "debug2: " << G_STRFUNC << ": m_current_locale=" << m_current_locale << std::endl;
-    }
-    else
-      m_current_locale = 'C';
-  }
-
-  return m_current_locale;
-}
-
-void TranslatableItem::set_current_locale(const Glib::ustring& locale)
-{
-  if(locale.empty())
-    return;
-
-  m_current_locale = locale;
-}
-
-void TranslatableItem::set_original_locale(const Glib::ustring& locale)
-{
-  if(locale.empty())
-    return;
-
-  m_original_locale = locale;
-}
-
-
-Glib::ustring TranslatableItem::get_original_locale()
-{
-  if(m_original_locale.empty())
-    m_original_locale = "en_US"; //"en_US.UTF-8";
-
-  return m_original_locale; 
-}
-
-bool TranslatableItem::get_current_locale_not_original() //TODO: Make this const?
-{
-  if(m_original_locale.empty())
-    get_original_locale();
-
-  if(m_current_locale.empty())
-    get_current_locale();
-
-  return m_original_locale != m_current_locale;
-}
-
 TranslatableItem::enumTranslatableItemType TranslatableItem::get_translatable_item_type() const
 {
   return m_translatable_item_type;
@@ -338,9 +267,18 @@ bool TranslatableItem::get_name_not_empty() const
   return !(get_name().empty());
 }
 
-Glib::ustring TranslatableItem::get_title_or_name() const
+Glib::ustring TranslatableItem::get_title_or_name(const Glib::ustring& locale) const
+{
+  const Glib::ustring title = get_title(locale);
+  if(title.empty())
+    return get_name();
+  else
+    return title;
+}
+
+Glib::ustring TranslatableItem::get_title_or_name_original() const
 {
-  const Glib::ustring title = get_title();
+  const Glib::ustring title = get_title_original();
   if(title.empty())
     return get_name();
   else
diff --git a/glom/libglom/data_structure/translatable_item.h b/glom/libglom/data_structure/translatable_item.h
index a9b606f..97c84ff 100644
--- a/glom/libglom/data_structure/translatable_item.h
+++ b/glom/libglom/data_structure/translatable_item.h
@@ -51,34 +51,45 @@ public:
 
   bool get_name_not_empty() const; //For performance.
 
-  virtual Glib::ustring get_title_or_name() const;
-
-  /** Get the title's translation for the current locale.
+  virtual Glib::ustring get_title_or_name(const Glib::ustring& locale) const;
+
+  virtual Glib::ustring get_title_or_name_original() const;
+
+  /** Get the title's translation for the specified locale, falling back to the
+   * original text if there is no translation.
+   *
+   * See also get_title_translation() and get_title_original(), which (optionally)
+   * do not use fallbacks.
+   *
+   * @param locale The locale whose title text should be returned. If this is empty then the original text will be returned.
+   * @result The text of the title.
    */
-  virtual Glib::ustring get_title() const;
+  virtual Glib::ustring get_title(const Glib::ustring& locale) const;
 
   /** Get the title's original (non-translated, usually English) text.
    */
   virtual Glib::ustring get_title_original() const;
 
+  /** Get the title's translation for the specified @a locale, optionally
+   * falling back to a locale of the same language, and then falling back to 
+   * the original.
+   * Calling this with the current locale is the same as calling get_title_original().
+   */
+  virtual Glib::ustring get_title_translation(const Glib::ustring& locale, bool fallback = true) const;
+  
 
-  /** Set the title's translation for the current locale.
+  /** Set the title's translation for the specified locale.
+   * @param title The text of the title.
+   * @param locale The locale whose title text should be set. If this is empty then the original text will be set.
    */
-  void set_title(const Glib::ustring& title);
+  void set_title(const Glib::ustring& title, const Glib::ustring& locale);
 
   /** Set the title's original (non-translated, usually English) text.
+   * This is the same as calling set_title() with an empty locale parameter.
    */
   void set_title_original(const Glib::ustring& title);
 
-  void set_title_translation(const Glib::ustring& locale, const Glib::ustring& translation);
 
-  /** Get the title's translation for the specified @a locale, optionally
-   * falling back to a locale of the same language, and then falling back to 
-   * the original.
-   * Calling this with the current locale is the same as calling get_title_original().
-   */
-  Glib::ustring get_title_translation(const Glib::ustring& locale, bool fallback = true) const;
-  
   /// Clear the original title and any translations of the title.
   void clear_title_in_all_locales();
 
@@ -113,24 +124,6 @@ public:
    */
   static Glib::ustring get_translatable_type_name_nontranslated(enumTranslatableItemType item_type);
 
-
-  /** Set the locale used for titles, to test translations.
-   * Usually the current locale is just the locale at startup.
-   */
-  static void set_current_locale(const Glib::ustring& locale);
-
-  /** Get the locale used by this program when it was started.
-   */
-  static Glib::ustring get_current_locale();
-
-  /** Set the locale used for original text of titles. This 
-   * must usually be stored in the document. 
-   * Ideally, it would be English.
-   */
-  static void set_original_locale(const Glib::ustring& locale);
-
-  static bool get_current_locale_not_original();
-
 private:
 
   /** Get the locale used as the source language.
@@ -138,6 +131,8 @@ private:
    */
   static Glib::ustring get_original_locale();
 
+  void set_title_translation(const Glib::ustring& locale, const Glib::ustring& translation);
+
 
 protected:
   enumTranslatableItemType m_translatable_item_type;
@@ -146,8 +141,6 @@ private:
   Glib::ustring m_name; //Non-translated identifier;
   Glib::ustring m_title; //The original, untranslated (usually-English) title.
   type_map_locale_to_translations m_map_translations;
-
-  static Glib::ustring m_current_locale, m_original_locale;
 };
 
 template <class T_object>
@@ -160,10 +153,10 @@ Glib::ustring glom_get_sharedptr_name(const sharedptr<T_object>& item)
 }
 
 template <class T_object>
-Glib::ustring glom_get_sharedptr_title_or_name(const sharedptr<T_object>& item)
+Glib::ustring glom_get_sharedptr_title_or_name(const sharedptr<T_object>& item, const Glib::ustring& locale)
 {
   if(item)
-    return item->get_title_or_name();
+    return item->get_title_or_name(locale);
   else
     return Glib::ustring();
 }
diff --git a/glom/libglom/db_utils.cc b/glom/libglom/db_utils.cc
index 358d983..ebb1281 100644
--- a/glom/libglom/db_utils.cc
+++ b/glom/libglom/db_utils.cc
@@ -499,7 +499,7 @@ bool add_standard_tables(Document* document)
     {
       sharedptr<TableInfo> table_info(new TableInfo());
       table_info->set_name(GLOM_STANDARD_TABLE_AUTOINCREMENTS_TABLE_NAME);
-      table_info->set_title("System: Auto Increments"); //TODO: Provide standard translations.
+      table_info->set_title_original(_("System: Auto Increments"));
       table_info->m_hidden = true;
 
       Document::type_vec_fields fields;
@@ -1149,7 +1149,7 @@ bool create_table_with_default_fields(Document* document, const Glib::ustring& t
   //Primary key:
   sharedptr<Field> field_primary_key(new Field());
   field_primary_key->set_name(table_name + "_id");
-  field_primary_key->set_title(table_name + " ID");
+  field_primary_key->set_title_original( Glib::ustring::compose("%1 ID", table_name) );
   field_primary_key->set_primary_key();
   field_primary_key->set_auto_increment();
 
@@ -1166,21 +1166,21 @@ bool create_table_with_default_fields(Document* document, const Glib::ustring& t
   //Description:
   sharedptr<Field> field_description(new Field());
   field_description->set_name("description");
-  field_description->set_title(_("Description")); //Use a translation, because the original locale will be marked as non-English if the current locale is non-English.
+  field_description->set_title_original(_("Description")); //Use a translation, because the original locale will be marked as non-English if the current locale is non-English.
   field_description->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_description);
 
   //Comments:
   sharedptr<Field> field_comments(new Field());
   field_comments->set_name("comments");
-  field_comments->set_title(_("Comments"));
+  field_comments->set_title_original(_("Comments"));
   field_comments->set_glom_type(Field::TYPE_TEXT);
   field_comments->m_default_formatting.set_text_format_multiline();
   fields.push_back(field_comments);
 
   sharedptr<TableInfo> table_info(new TableInfo());
   table_info->set_name(table_name);
-  table_info->set_title( Utils::title_from_string( table_name ) ); //Start with a title that might be appropriate.
+  table_info->set_title_original( Utils::title_from_string( table_name ) ); //Start with a title that might be appropriate.
 
   created = create_table(table_info, fields);
 
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index 612f2e4..458bd6c 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -307,8 +307,6 @@ Document::Document()
   if(get_connection_server().empty())
     set_connection_server("localhost");
 
-  set_translation_original_locale(TranslatableItem::get_current_locale()); //By default, we assume that the original is in the current locale. We must do this here so that TranslatableItem::set/get_title() knows.
-
   m_app_state.signal_userlevel_changed().connect( sigc::mem_fun(*this, &Document::on_app_state_userlevel_changed) );
 
   set_modified(false);
@@ -504,7 +502,7 @@ sharedptr<Relationship> Document::create_relationship_system_preferences(const G
 {
   sharedptr<Relationship> relationship = sharedptr<Relationship>::create();
   relationship->set_name(GLOM_RELATIONSHIP_NAME_SYSTEM_PROPERTIES);
-  relationship->set_title(_("System Preferences"));
+  relationship->set_title_original(_("System Preferences"));
   relationship->set_from_table(table_name);
   relationship->set_to_table(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
   relationship->set_allow_edit(false);
@@ -522,7 +520,7 @@ sharedptr<TableInfo> Document::create_table_system_preferences(type_vec_fields&
 {
   sharedptr<TableInfo> prefs_table_info = sharedptr<TableInfo>::create();
   prefs_table_info->set_name(GLOM_STANDARD_TABLE_PREFS_TABLE_NAME);
-  prefs_table_info->set_title(_("System Preferences"));
+  prefs_table_info->set_title_original(_("System Preferences"));
   prefs_table_info->m_hidden = true;
 
 
@@ -535,55 +533,55 @@ sharedptr<TableInfo> Document::create_table_system_preferences(type_vec_fields&
 
   sharedptr<Field> field_name(new Field());
   field_name->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_NAME);
-  field_name->set_title(_("System Name"));
+  field_name->set_title_original(_("System Name"));
   field_name->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_name);
 
   sharedptr<Field> field_org_name(new Field());
   field_org_name->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_NAME);
-  field_org_name->set_title(_("Organisation Name"));
+  field_org_name->set_title_original(_("Organisation Name"));
   field_org_name->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_name);
 
   sharedptr<Field> field_org_logo(new Field());
   field_org_logo->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_LOGO);
-  field_org_logo->set_title(_("Organisation Logo"));
+  field_org_logo->set_title_original(_("Organisation Logo"));
   field_org_logo->set_glom_type(Field::TYPE_IMAGE);
   fields.push_back(field_org_logo);
 
   sharedptr<Field> field_org_address_street(new Field());
   field_org_address_street->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET);
-  field_org_address_street->set_title(_("Street"));
+  field_org_address_street->set_title_original(_("Street"));
   field_org_address_street->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_address_street);
 
   sharedptr<Field> field_org_address_street2(new Field());
   field_org_address_street2->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_STREET2);
-  field_org_address_street2->set_title(_("Street (line 2)"));
+  field_org_address_street2->set_title_original(_("Street (line 2)"));
   field_org_address_street2->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_address_street2);
 
   sharedptr<Field> field_org_address_town(new Field());
   field_org_address_town->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_TOWN);
-  field_org_address_town->set_title(_("City"));
+  field_org_address_town->set_title_original(_("City"));
   field_org_address_town->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_address_town);
 
   sharedptr<Field> field_org_address_county(new Field());
   field_org_address_county->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTY);
-  field_org_address_county->set_title(_("State"));
+  field_org_address_county->set_title_original(_("State"));
   field_org_address_county->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_address_county);
 
   sharedptr<Field> field_org_address_country(new Field());
   field_org_address_country->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_COUNTRY);
-  field_org_address_country->set_title(_("Country"));
+  field_org_address_country->set_title_original(_("Country"));
   field_org_address_country->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_address_country);
 
   sharedptr<Field> field_org_address_postcode(new Field());
   field_org_address_postcode->set_name(GLOM_STANDARD_TABLE_PREFS_FIELD_ORG_ADDRESS_POSTCODE);
-  field_org_address_postcode->set_title(_("Zip Code"));
+  field_org_address_postcode->set_title_original(_("Zip Code"));
   field_org_address_postcode->set_glom_type(Field::TYPE_TEXT);
   fields.push_back(field_org_address_postcode);
 
@@ -860,7 +858,7 @@ Document::type_vec_fields Document::get_table_fields(const Glib::ustring& table_
       if(table_name == GLOM_STANDARD_TABLE_PREFS_TABLE_NAME)
       {
         type_vec_fields fields;
-        sharedptr<TableInfo> temp = create_table_system_preferences(fields);
+        create_table_system_preferences(fields);
         result = fields;
       }
       else
@@ -1543,13 +1541,13 @@ Document::type_list_layout_groups Document::get_data_layout_groups_default(const
   {
     overview = sharedptr<LayoutGroup>::create();;
     overview->set_name("overview");
-    overview->set_title_original("Overview"); //Don't translate this, but TODO: add standard translations.
+    overview->set_title_original(_("Overview"));
     overview->set_columns_count(2);
     result.push_back(overview);
 
     details = sharedptr<LayoutGroup>::create();
     details->set_name("details");
-    details->set_title_original("Details"); //Don't translate this, but TODO: add standard translations.
+    details->set_title_original(_("Details"));
     details->set_columns_count(2);
     result.push_back(details);
   }
@@ -1735,33 +1733,51 @@ Document::DocumentTableInfo& Document::get_table_info_with_add(const Glib::ustri
   }
 }
 
-Glib::ustring Document::get_table_title(const Glib::ustring& table_name) const
+Glib::ustring Document::get_table_title(const Glib::ustring& table_name, const Glib::ustring& locale) const
+{
+  type_tables::const_iterator iterFind = m_tables.find(table_name);
+  if(iterFind != m_tables.end())
+    return iterFind->second.m_info->get_title(locale);
+  else
+    return Glib::ustring();
+}
+
+Glib::ustring Document::get_table_title_original(const Glib::ustring& table_name) const
+{
+  type_tables::const_iterator iterFind = m_tables.find(table_name);
+  if(iterFind != m_tables.end())
+    return iterFind->second.m_info->get_title_original();
+  else
+    return Glib::ustring();
+}
+
+Glib::ustring Document::get_table_title_singular(const Glib::ustring& table_name, const Glib::ustring& locale) const
 {
   type_tables::const_iterator iterFind = m_tables.find(table_name);
   if(iterFind != m_tables.end())
-    return iterFind->second.m_info->get_title();
+    return iterFind->second.m_info->get_title_singular_with_fallback(locale);
   else
     return Glib::ustring();
 }
 
-Glib::ustring Document::get_table_title_singular(const Glib::ustring& table_name) const
+Glib::ustring Document::get_table_title_singular_original(const Glib::ustring& table_name) const
 {
   type_tables::const_iterator iterFind = m_tables.find(table_name);
   if(iterFind != m_tables.end())
-    return iterFind->second.m_info->get_title_singular_with_fallback();
+    return iterFind->second.m_info->get_title_singular_original();
   else
     return Glib::ustring();
 }
 
-void Document::set_table_title(const Glib::ustring& table_name, const Glib::ustring& value)
+void Document::set_table_title(const Glib::ustring& table_name, const Glib::ustring& value, const Glib::ustring& locale)
 {
   //std::cout << "debug: " << G_STRFUNC << ": table_name=" << table_name << ", value=" << value << std::endl;
   if(!table_name.empty())
   {
     DocumentTableInfo& info = get_table_info_with_add(table_name);
-    if(info.m_info->get_title() != value)
+    if(info.m_info->get_title(locale) != value)
     {
-      info.m_info->set_title(value);
+      info.m_info->set_title(value, locale);
       set_modified();
     }
   }
@@ -2255,7 +2271,7 @@ void Document::load_after_layout_group(const xmlpp::Element* node, const Glib::u
 
   //Get the group details:
   group->set_name( get_node_attribute_value(node, GLOM_ATTRIBUTE_NAME) );
-  group->set_title( get_node_attribute_value(node, GLOM_ATTRIBUTE_TITLE) );
+  group->set_title_original( get_node_attribute_value(node, GLOM_ATTRIBUTE_TITLE) );
   group->set_columns_count(
     get_node_attribute_value_as_decimal(node, GLOM_ATTRIBUTE_COLUMNS_COUNT, 1)); //default to 1, because 0 is meaningless.
   group->set_border_width( get_node_attribute_value_as_decimal_double(node, GLOM_ATTRIBUTE_BORDER_WIDTH) );
@@ -2548,7 +2564,7 @@ void Document::load_after_translations(const xmlpp::Element* element, Translatab
   const ChoiceValue* choicevalue = dynamic_cast<ChoiceValue*>(&item);
   if(!choicevalue) //This item does not use the title, but uses the title translations to translate its value, if it is of type text.
   {
-    item.set_title_original( get_node_attribute_value(element, GLOM_ATTRIBUTE_TITLE) );
+    item.set_title_original( get_node_attribute_value(element, GLOM_ATTRIBUTE_TITLE));
   }
 
   const xmlpp::Element* nodeTranslations = get_node_child_named(element, GLOM_NODE_TRANSLATIONS_SET);
@@ -2562,7 +2578,7 @@ void Document::load_after_translations(const xmlpp::Element* element, Translatab
       {
         const Glib::ustring locale = get_node_attribute_value(element, GLOM_ATTRIBUTE_TRANSLATION_LOCALE);
         const Glib::ustring translation = get_node_attribute_value(element, GLOM_ATTRIBUTE_TRANSLATION_VALUE);
-        item.set_title_translation(locale, translation);
+        item.set_title(translation, locale);
 
         //Remember any new translation locales in our cached list:
         if(std::find(m_translation_available_locales.begin(), 
@@ -2656,7 +2672,6 @@ bool Document::load_after(int& failure_code)
       m_startup_script = get_child_text_node(nodeRoot, GLOM_NODE_STARTUP_SCRIPT);
 
       m_translation_original_locale = get_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_TRANSLATION_ORIGINAL_LOCALE);
-      TranslatableItem::set_original_locale(m_translation_original_locale);
       m_translation_available_locales.push_back(m_translation_original_locale); //Just a cache.
 
       const xmlpp::Element* nodeConnection = get_node_child_named(nodeRoot, GLOM_NODE_CONNECTION);
@@ -3708,11 +3723,6 @@ bool Document::save_before()
 
     set_child_text_node(nodeRoot, GLOM_NODE_STARTUP_SCRIPT, m_startup_script);
 
-    //Assume that the first language used is the original locale.
-    //It can be identified as a translation later.
-    if(m_translation_original_locale.empty())
-      m_translation_original_locale = TranslatableItem::get_current_locale();
-
     set_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_TRANSLATION_ORIGINAL_LOCALE, m_translation_original_locale);
 
     xmlpp::Element* nodeConnection = get_node_child_named_with_add(nodeRoot, GLOM_NODE_CONNECTION);
@@ -4390,8 +4400,10 @@ void Document::set_is_backup_file(bool value)
 
 void Document::set_translation_original_locale(const Glib::ustring& locale)
 {
+  if(m_translation_original_locale == locale)
+    return;
+
   m_translation_original_locale = locale;
-  TranslatableItem::set_original_locale(m_translation_original_locale);
   set_modified();
 }
 
diff --git a/glom/libglom/document/document.h b/glom/libglom/document/document.h
index 2155738..6a32e14 100644
--- a/glom/libglom/document/document.h
+++ b/glom/libglom/document/document.h
@@ -296,10 +296,12 @@ public:
   bool get_table_is_known(const Glib::ustring& table_name) const;
   bool get_table_is_hidden(const Glib::ustring& table_name) const;
 
-  Glib::ustring get_table_title(const Glib::ustring& table_name) const;
-  void set_table_title(const Glib::ustring& table_name, const Glib::ustring& value);
+  Glib::ustring get_table_title(const Glib::ustring& table_name, const Glib::ustring& locale) const;
+  Glib::ustring get_table_title_original(const Glib::ustring& table_name) const;
+  void set_table_title(const Glib::ustring& table_name, const Glib::ustring& value, const Glib::ustring& locale);
 
-  Glib::ustring get_table_title_singular(const Glib::ustring& table_name) const;
+  Glib::ustring get_table_title_singular(const Glib::ustring& table_name, const Glib::ustring& locale) const;
+  Glib::ustring get_table_title_singular_original(const Glib::ustring& table_name) const;
 
   typedef std::vector< Gnome::Gda::Value > type_row_data;
   typedef std::vector< type_row_data > type_example_rows;
diff --git a/glom/libglom/example_document_load.cc b/glom/libglom/example_document_load.cc
index 7b2fee7..c676227 100644
--- a/glom/libglom/example_document_load.cc
+++ b/glom/libglom/example_document_load.cc
@@ -40,7 +40,7 @@ void print_layout_group(const Glom::sharedptr<Glom::LayoutGroup>& layout_group,
     if(!layout_item)
       continue;
 
-    std::cout << indent << "Layout Item: title=" << layout_item->get_title_or_name()
+    std::cout << indent << "Layout Item: title=" << layout_item->get_title_or_name_original()
       << ", item type=" << layout_item->get_part_type_name();
 
     const Glib::ustring display_name = layout_item->get_layout_display_name();
@@ -66,7 +66,7 @@ void print_layout(const Glom::Document::type_list_layout_groups& layout_groups)
     if(!layout_group)
       continue;
 
-    std::cout << "    Layout Group: title=" << layout_group->get_title_or_name() << std::endl;
+    std::cout << "    Layout Group: title=" << layout_group->get_title_or_name_original() << std::endl;
     print_layout_group(layout_group, "      ");
   }
 }
@@ -125,7 +125,7 @@ int main()
        const Glom::Field::glom_field_type field_type = field->get_glom_type();
 
        std::cout << "  Field: name=" << field->get_name()
-         << ", title=" << field->get_title_or_name()
+         << ", title=" << field->get_title_or_name_original()
          << ", type=" << Glom::Field::get_type_name_ui(field_type) << std::endl;
 
     }
diff --git a/glom/libglom/report_builder.cc b/glom/libglom/report_builder.cc
index 27de092..fdda4db 100644
--- a/glom/libglom/report_builder.cc
+++ b/glom/libglom/report_builder.cc
@@ -30,8 +30,9 @@
 namespace Glom
 {
 
-ReportBuilder::ReportBuilder()
-: m_document(0)
+ReportBuilder::ReportBuilder(const Glib::ustring& locale)
+: m_document(0),
+  m_locale(locale)
 {
 }
 
@@ -201,7 +202,7 @@ void ReportBuilder::report_build_groupby(const FoundSet& found_set_parent, xmlpp
         xmlpp::Element* nodeGroupBy = parent_node.add_child(group_by->get_report_part_id());
         Document::set_node_attribute_value_as_decimal_double(nodeGroupBy, "border_width", group_by->get_border_width());
 
-        nodeGroupBy->set_attribute("group_field", field_group_by->get_title_or_name());
+        nodeGroupBy->set_attribute("group_field", field_group_by->get_title_or_name(m_locale));
         nodeGroupBy->set_attribute("group_value",
           Conversions::get_text_for_gda_value(field_group_by->get_glom_type(), group_value, field_group_by->get_formatting_used().m_numeric_format) );
 
@@ -287,7 +288,7 @@ void ReportBuilder::report_build_records(const FoundSet& found_set, xmlpp::Eleme
         nodeFieldHeading->set_attribute("field_type", "numeric"); //TODO: More sophisticated formatting.
 
       nodeFieldHeading->set_attribute("name", layout_item->get_name()); //Not really necessary, but maybe useful.
-      nodeFieldHeading->set_attribute("title", layout_item->get_title_or_name());
+      nodeFieldHeading->set_attribute("title", layout_item->get_title_or_name(m_locale));
     }
 
     //Get list of fields to get from the database.
@@ -405,7 +406,7 @@ void ReportBuilder::report_build_records_field(const FoundSet& found_set, xmlpp:
     value = datamodel->get_value_at(colField, row); //TODO: Catch exceptions.
   }
 
-  nodeField->set_attribute("title", field->get_title_or_name()); //Not always used, but useful.
+  nodeField->set_attribute("title", field->get_title_or_name(m_locale)); //Not always used, but useful.
 
   //Handle the value:
   if(field_type == Field::TYPE_IMAGE)
@@ -432,7 +433,7 @@ void ReportBuilder::report_build_records_text(const FoundSet& /* found_set */, x
 {
   //Text object:
   xmlpp::Element* nodeField = nodeParent.add_child(textobject->get_report_part_id()); //We reuse this node type for text objects.
-  nodeField->set_attribute("value", textobject->get_text());
+  nodeField->set_attribute("value", textobject->get_text(m_locale));
 
   if(vertical)
     nodeField->set_attribute("vertical", "true");
@@ -545,7 +546,7 @@ Glib::ustring ReportBuilder::report_build(const FoundSet& found_set, const share
     nodeRoot = pDocument->create_root_node("report_print");
   }
 
-  Glib::ustring table_title = get_document()->get_table_title(found_set.m_table_name);
+  Glib::ustring table_title = get_document()->get_table_title(found_set.m_table_name, m_locale);
   if(table_title.empty())
     table_title = found_set.m_table_name;
 
@@ -558,7 +559,7 @@ Glib::ustring ReportBuilder::report_build(const FoundSet& found_set, const share
   xmlpp::Element* nodeParent = nodeRoot;
 
 
-  nodeRoot->set_attribute("title", report->get_title_or_name());
+  nodeRoot->set_attribute("title", report->get_title_or_name(m_locale));
 
   type_vecLayoutItems itemsToGet_TopLevel;
 
@@ -631,7 +632,7 @@ sharedptr<Report> ReportBuilder::create_standard_list_report(const Document* doc
   sharedptr<Report> result(new Report());
   result->set_name("list");
   //Translators: This is a noun. It is the title of a report.
-  result->set_title(_("List"));
+  result->set_title_original(_("List"));
 
   const Document::type_list_layout_groups layout_groups = 
     document->get_data_layout_groups("list", table_name); //TODO: layout_platform.
diff --git a/glom/libglom/report_builder.h b/glom/libglom/report_builder.h
index 641c7f6..a6cb336 100644
--- a/glom/libglom/report_builder.h
+++ b/glom/libglom/report_builder.h
@@ -35,11 +35,12 @@ namespace Glom
 class ReportBuilder
 {
 public:
-  ReportBuilder();
+  explicit ReportBuilder(const Glib::ustring& locale);
   virtual ~ReportBuilder();
 
   static sharedptr<Report> create_standard_list_report(const Document* document, const Glib::ustring& table_name);
 
+  //TODO: Remove set_document() and get_document()?
   void set_document(Document* document);
 
   //void set_report(const Glib::ustring& table_name, const sharedptr<const Report>& report);
@@ -76,6 +77,8 @@ private:
   Document* get_document();
 
   Document* m_document;
+
+  Glib::ustring m_locale;
 };
 
 } //namespace Glom
diff --git a/glom/libglom/translations_po.cc b/glom/libglom/translations_po.cc
index e1e6cca..f6d2ca8 100644
--- a/glom/libglom/translations_po.cc
+++ b/glom/libglom/translations_po.cc
@@ -271,7 +271,7 @@ bool import_translations_from_po_file(Document* document, const Glib::ustring& p
         if( (item->get_title_original() == msgid) && 
           (get_po_context_for_item(item, hint) == msgcontext) ) // This is not efficient, but it should be reliable.
         {
-          item->set_title_translation(translation_locale, msgstr);
+          item->set_title(msgstr, translation_locale);
           // Keep examining items, in case there are duplicates. break;
         }
       }
diff --git a/glom/mode_data/box_data_calendar_related.cc b/glom/mode_data/box_data_calendar_related.cc
index c752472..197e554 100644
--- a/glom/mode_data/box_data_calendar_related.cc
+++ b/glom/mode_data/box_data_calendar_related.cc
@@ -92,7 +92,7 @@ bool Box_Data_Calendar_Related::init_db_details(const Glib::ustring& parent_tabl
   {
     Glib::ustring title;
     if(m_portal)
-      title = m_portal->get_title();
+      title = m_portal->get_title(Application::get_current_locale());
 
     m_Label.set_markup(Utils::bold_message(title));
     m_Label.show();
@@ -460,7 +460,7 @@ Glib::ustring Box_Data_Calendar_Related::on_calendar_details(guint year, guint m
       //Text for a text item:
       sharedptr<const LayoutItem_Text> layout_item_text = sharedptr<const LayoutItem_Text>::cast_dynamic(layout_item);
       if(layout_item_text)
-        text = layout_item_text->get_text();
+        text = layout_item_text->get_text(Application::get_current_locale());
       else
       {
         //Text for a field:
diff --git a/glom/mode_data/box_data_list_related.cc b/glom/mode_data/box_data_list_related.cc
index 1af2d61..7106867 100644
--- a/glom/mode_data/box_data_list_related.cc
+++ b/glom/mode_data/box_data_list_related.cc
@@ -20,6 +20,7 @@
 
 #include <glom/mode_data/box_data_list_related.h>
 #include <glom/mode_design/layout/dialog_layout_list_related.h>
+#include <glom/application.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
 #include <glom/glade_utils.h>
@@ -87,7 +88,7 @@ bool Box_Data_List_Related::init_db_details(const Glib::ustring& parent_table, b
   {
     Glib::ustring title;
     if(m_portal)
-      title = m_portal->get_title();
+      title = m_portal->get_title(Application::get_current_locale());
 
     m_Label.set_markup(Utils::bold_message(title));
     m_Label.show();
diff --git a/glom/mode_data/box_data_manyrecords.cc b/glom/mode_data/box_data_manyrecords.cc
index 6a83dad..467b7c3 100644
--- a/glom/mode_data/box_data_manyrecords.cc
+++ b/glom/mode_data/box_data_manyrecords.cc
@@ -21,6 +21,7 @@
 #include "box_data_manyrecords.h"
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/glade_utils.h>
+#include <glom/application.h>
 #include <libglom/report_builder.h>
 #include <glom/mode_design/layout/dialog_layout_list.h>
 #include <glom/utils_ui.h>
@@ -82,7 +83,7 @@ void Box_Data_ManyRecords::print_layout()
     Document* document = get_document();
     sharedptr<Report> report_temp = ReportBuilder::create_standard_list_report(document, m_table_name);
 
-    ReportBuilder report_builder;
+    ReportBuilder report_builder(Application::get_current_locale());
     report_builder.set_document(document);
     const std::string filepath = 
       report_builder.report_build_and_save(m_found_set, report_temp);
diff --git a/glom/mode_data/box_data_portal.cc b/glom/mode_data/box_data_portal.cc
index 6660d63..603cb6e 100644
--- a/glom/mode_data/box_data_portal.cc
+++ b/glom/mode_data/box_data_portal.cc
@@ -106,10 +106,10 @@ bool Box_Data_Portal::init_db_details(const sharedptr<const LayoutItem_Portal>&
   return init_db_details(parent_table, show_title);
 }
 
-Glib::ustring Box_Data_Portal::get_title() const
+Glib::ustring Box_Data_Portal::get_title(const Glib::ustring& locale) const
 {
   if(m_portal)
-    return m_portal->get_title_or_name();
+    return m_portal->get_title_or_name(locale);
   else
   {
     //Note to translators: This text is shown instead of a table title, when the table has not yet been chosen.
@@ -117,11 +117,11 @@ Glib::ustring Box_Data_Portal::get_title() const
   }
 }
 
-Glib::ustring Box_Data_Portal::get_title_singular() const
+Glib::ustring Box_Data_Portal::get_title_singular(const Glib::ustring& locale) const
 {
   Glib::ustring relationship_title;
   if(m_portal && m_portal->get_has_relationship_name())
-    relationship_title = m_portal->get_title_singular_used(Glib::ustring() /* parent title - not relevant */);
+    relationship_title = m_portal->get_title_singular_used(Glib::ustring() /* parent title - not relevant */, locale);
   else
   {
     //Note to translators: This text is shown instead of a table title, when the table has not yet been chosen.
diff --git a/glom/mode_data/box_data_portal.h b/glom/mode_data/box_data_portal.h
index f718294..1c59a05 100644
--- a/glom/mode_data/box_data_portal.h
+++ b/glom/mode_data/box_data_portal.h
@@ -114,11 +114,11 @@ protected:
 
   /** Get the title of the relationship used by the portal.
    */
-  Glib::ustring get_title() const;
+  Glib::ustring get_title(const Glib::ustring& locale) const;
   
   /** Get the singular title of the relationship used by the portal.
    */
-  Glib::ustring get_title_singular() const;  
+  Glib::ustring get_title_singular(const Glib::ustring& locale) const;  
   
   Gtk::Frame m_Frame;
   Gtk::Alignment m_Alignment;
diff --git a/glom/mode_data/datawidget/cellcreation.cc b/glom/mode_data/datawidget/cellcreation.cc
index ec3c2dd..b38af98 100644
--- a/glom/mode_data/datawidget/cellcreation.cc
+++ b/glom/mode_data/datawidget/cellcreation.cc
@@ -23,6 +23,7 @@
 #include <glom/mode_data/datawidget/cellrenderer_buttonimage.h>
 #include <glom/mode_data/datawidget/cellrenderer_buttontext.h>
 #include <glom/utils_ui.h>
+#include <glom/application.h>
 #include <gtkmm/cellrenderertext.h>
 #include <gtkmm/stock.h>
 #include <libglom/data_structure/layout/layoutitem_field.h>
@@ -140,7 +141,7 @@ Gtk::CellRenderer* create_cell(const sharedptr<const LayoutItem>& layout_item, c
       if(item_text)
       {
         Gtk::CellRendererText* pCellText = Gtk::manage( new Gtk::CellRendererText() );
-        pCellText->set_property("text", item_text->get_text());
+        pCellText->set_property("text", item_text->get_text(Application::get_current_locale()));
 
         cell = pCellText;
       }
@@ -150,7 +151,7 @@ Gtk::CellRenderer* create_cell(const sharedptr<const LayoutItem>& layout_item, c
         if(item_button)
         {
           GlomCellRenderer_ButtonText* pCellButton = Gtk::manage( new GlomCellRenderer_ButtonText() );
-          pCellButton->set_property("text", item_button->get_title_or_name());
+          pCellButton->set_property("text", item_button->get_title_or_name(Application::get_current_locale()));
           //pCellButton->set_fixed_width(50); //Otherwise it doesn't show up. TODO: Discover the width of the contents.
 
           cell = pCellButton;
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
index b75faab..1571ac9 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
@@ -22,6 +22,7 @@
 #include <glom/mode_data/datawidget/treemodel_db_withextratext.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/utils_ui.h>
+#include <glom/application.h>
 #include <gtkmm/liststore.h>
 #include <glibmm/i18n.h>
 //#include <sstream> //For stringstream
@@ -238,7 +239,7 @@ void ComboChoicesWithTreeModel::set_choices_fixed(const FieldFormatting::type_li
     {
       //Show the translated text of the value:
       //This will never be stored in the database:
-      text = choicevalue->get_title();
+      text = choicevalue->get_title(Application::get_current_locale());
     }
     else
     {
diff --git a/glom/mode_data/datawidget/datawidget.cc b/glom/mode_data/datawidget/datawidget.cc
index 7c74e01..cdc1627 100644
--- a/glom/mode_data/datawidget/datawidget.cc
+++ b/glom/mode_data/datawidget/datawidget.cc
@@ -71,7 +71,7 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
   
   //The GNOME HIG says that labels should have ":" at the end:
   //http://library.gnome.org/devel/hig-book/stable/design-text-labels.html.en
-  const Glib::ustring title = Glib::ustring::compose(_("%1:"), field->get_title_or_name());
+  const Glib::ustring title = Glib::ustring::compose(_("%1:"), field->get_title_or_name(Application::get_current_locale()));
 
   m_child = 0;
   LayoutWidgetField* pFieldWidget = 0;  
diff --git a/glom/mode_data/datawidget/dialog_choose_id.cc b/glom/mode_data/datawidget/dialog_choose_id.cc
index 0a3679f..7b2a65c 100644
--- a/glom/mode_data/datawidget/dialog_choose_id.cc
+++ b/glom/mode_data/datawidget/dialog_choose_id.cc
@@ -20,6 +20,7 @@
 
 #include "dialog_choose_id.h"
 #include <glom/utils_ui.h> //For bold_message()).
+#include <glom/application.h>
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
@@ -176,7 +177,7 @@ bool Dialog_ChooseID::init_db_details(const Glib::ustring& table_name, const Gli
   m_table_name = table_name;
   m_layout_platform = layout_platform;
 
-  m_label_table_name->set_text( get_document()->get_table_title(m_table_name) );
+  m_label_table_name->set_text( get_document()->get_table_title(m_table_name, Application::get_current_locale()) );
 
   //Start by asking for find criteria:
   m_stage = STAGE_FIND;
diff --git a/glom/mode_data/datawidget/dialog_new_record.cc b/glom/mode_data/datawidget/dialog_new_record.cc
index 88ebf35..da29579 100644
--- a/glom/mode_data/datawidget/dialog_new_record.cc
+++ b/glom/mode_data/datawidget/dialog_new_record.cc
@@ -20,6 +20,7 @@
 
 #include "dialog_new_record.h"
 #include <glom/utils_ui.h> //For bold_message()).
+#include <glom/application.h>
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
@@ -74,7 +75,7 @@ bool Dialog_NewRecord::init_db_details(const Glib::ustring& table_name, const Gl
   m_table_name = table_name;
   m_layout_platform = layout_platform;
 
-  m_label_table_name->set_text( get_document()->get_table_title(m_table_name) );
+  m_label_table_name->set_text( get_document()->get_table_title(m_table_name, Application::get_current_locale()) );
 
   FoundSet found_set;
   found_set.m_table_name = m_table_name;
diff --git a/glom/mode_data/db_adddel/db_adddel.cc b/glom/mode_data/db_adddel/db_adddel.cc
index cd2e8f26..6a788bf 100644
--- a/glom/mode_data/db_adddel/db_adddel.cc
+++ b/glom/mode_data/db_adddel/db_adddel.cc
@@ -728,7 +728,7 @@ void DbAddDel::construct_specified_columns()
     {
       no_columns_used = false;
 
-      const Glib::ustring column_name = layout_item->get_title_or_name();
+      const Glib::ustring column_name = layout_item->get_title_or_name(Application::get_current_locale());
       const Glib::ustring column_id = layout_item->get_name();
 
       // Whenever we are dealing with real database fields,
diff --git a/glom/mode_data/flowtablewithfields.cc b/glom/mode_data/flowtablewithfields.cc
index 1bf28c9..0d25eae 100644
--- a/glom/mode_data/flowtablewithfields.cc
+++ b/glom/mode_data/flowtablewithfields.cc
@@ -161,10 +161,11 @@ void FlowTableWithFields::add_layout_group(const sharedptr<LayoutGroup>& group,
   {
     Gtk::Frame* frame = Gtk::manage( new Gtk::Frame ); //TODO_leak: This is possibly leaked, according to valgrind.
 
-    if(!group->get_title().empty())
+    const Glib::ustring group_title = group->get_title(Application::get_current_locale());
+    if(!group_title.empty())
     {
       Gtk::Label* label = Gtk::manage( new Gtk::Label ); //TODO: This is maybe leaked, according to valgrind, though it should be managed by GtkFrame.
-      label->set_markup( Utils::bold_message(group->get_title()) );
+      label->set_markup( Utils::bold_message(group_title) );
       label->show();
       frame->set_label_widget(*label);
     }
@@ -174,13 +175,13 @@ void FlowTableWithFields::add_layout_group(const sharedptr<LayoutGroup>& group,
 
     Gtk::Alignment* alignment = Gtk::manage( new Gtk::Alignment ); //TODO_leak: This is possibly leaked, according to valgrind.
 
-    if(!group->get_title().empty()) //Don't indent if it has no title, to allow use of groups just for positioning.
+    if(!group_title.empty()) //Don't indent if it has no title, to allow use of groups just for positioning.
     {
       //Add some indenting just to avoid the out-denting caused by this GtkFrame bug:
       //https://bugzilla.gnome.org/show_bug.cgi?id=644199
       const int BASE_INDENT = 3;
       
-      //std::cout << "title= " << group->get_title() << ", with_indent=" << with_indent << std::endl;
+      //std::cout << "title= " << group_title << ", with_indent=" << with_indent << std::endl;
       if(with_indent) 
       {
         alignment->set_padding(Glom::Utils::DEFAULT_SPACING_SMALL, 0, Glom::Utils::DEFAULT_SPACING_SMALL + BASE_INDENT, 0);
@@ -368,7 +369,7 @@ void FlowTableWithFields::add_layout_notebook(const sharedptr<LayoutItem_Noteboo
       tab_label->show();
 #endif
 
-      tab_label->set_label(group->get_title_or_name());
+      tab_label->set_label(group->get_title_or_name(Application::get_current_locale()));
 
       sharedptr<LayoutItem_Portal> portal = sharedptr<LayoutItem_Portal>::cast_dynamic(group);
       if(portal)
@@ -563,7 +564,7 @@ void FlowTableWithFields::add_button(const sharedptr<LayoutItem_Button>& layouti
 {
   //Add the widget
   ButtonGlom* button = Gtk::manage(new ButtonGlom());
-  button->set_label(layoutitem_button->get_title_or_name());
+  button->set_label(layoutitem_button->get_title_or_name(Application::get_current_locale()));
   button->set_layout_item(layoutitem_button, table_name);
   button->signal_clicked().connect(
     sigc::bind(
@@ -611,7 +612,7 @@ void FlowTableWithFields::add_textobject(const sharedptr<LayoutItem_Text>& layou
   alignment_label->set(x_align, Gtk::ALIGN_CENTER);
   alignment_label->show();
 
-  const Glib::ustring text = layoutitem_text->get_text();
+  const Glib::ustring text = layoutitem_text->get_text(Application::get_current_locale());
   DataWidgetChildren::Label* label = Gtk::manage(new DataWidgetChildren::Label(text));
   label->set_layout_item(layoutitem_text, table_name);
   label->show();
@@ -621,7 +622,7 @@ void FlowTableWithFields::add_textobject(const sharedptr<LayoutItem_Text>& layou
 
   add_layoutwidgetbase(label);
 
-  const Glib::ustring title = layoutitem_text->get_title();
+  const Glib::ustring title = layoutitem_text->get_title(Application::get_current_locale());
   if(title.empty())
   {
     add(*alignment_label, true /* expand */);
@@ -655,7 +656,7 @@ void FlowTableWithFields::add_imageobject(const sharedptr<LayoutItem_Image>& lay
   add_layoutwidgetbase(image);
   //add_view(button); //So it can get the document.
 
-  const Glib::ustring title = layoutitem_image->get_title();
+  const Glib::ustring title = layoutitem_image->get_title(Application::get_current_locale());
   if(title.empty())
   {
     add(*image, true /* expand */);
@@ -1184,7 +1185,7 @@ void FlowTableWithFields::on_datawidget_layout_item_added(LayoutWidgetBase::enum
   else if(item_type == LayoutWidgetBase::TYPE_GROUP)
   {
     sharedptr<LayoutGroup> layout_item = sharedptr<LayoutGroup>::create();
-    layout_item->set_title(_("New Group"));
+    layout_item->set_title_original(_("New Group"));
     layout_item_new = layout_item;
   }
   else if(item_type == LayoutWidgetBase::TYPE_NOTEBOOK)
@@ -1199,7 +1200,7 @@ void FlowTableWithFields::on_datawidget_layout_item_added(LayoutWidgetBase::enum
     group_tab->set_name(_("tab1"));
 
     //Note to translators: This is the default label text for a notebook tab.
-    group_tab->set_title(_("Tab One"));
+    group_tab->set_title_original(_("Tab One"));
 
     layout_item->add_item(group_tab);
 
@@ -1213,14 +1214,14 @@ void FlowTableWithFields::on_datawidget_layout_item_added(LayoutWidgetBase::enum
   {
     sharedptr<LayoutItem_Button> layout_item = sharedptr<LayoutItem_Button>::create();
     layout_item->set_name(_("button"));
-    layout_item->set_title(_("New Button"));
+    layout_item->set_title_original(_("New Button"));
     layout_item_new = layout_item;
   }
   else if(item_type == LayoutWidgetBase::TYPE_TEXT)
   {
     sharedptr<LayoutItem_Text> layout_item = sharedptr<LayoutItem_Text>::create();
     layout_item->set_name(_("text"));
-    layout_item->set_text(_("New Text"));
+    layout_item->set_text_original(_("New Text"));
     layout_item_new = layout_item;
   }
 
@@ -1374,7 +1375,7 @@ void FlowTableWithFields::on_menu_properties_activate()
   {
     sharedptr<LayoutGroup> group = get_layout_group();
     group->set_columns_count( dialog->get_columns_count() );
-    group->set_title(dialog->get_title());
+    group->set_title(dialog->get_title(), Application::get_current_locale());
     signal_layout_changed().emit();
   }
 
@@ -1385,11 +1386,11 @@ void FlowTableWithFields::on_menu_properties_activate()
 void FlowTableWithFields::on_menu_delete_activate()
 {
   Glib::ustring message;
-  if(!get_layout_item()->get_title().empty())
+  if(!get_layout_item()->get_title(Application::get_current_locale()).empty())
   {
     //TODO: Use a real English sentence here?
     message = Glib::ustring::compose(_("Delete whole group \"%1\"?"),
-                                      get_layout_item()->get_title());
+                                      get_layout_item()->get_title(Application::get_current_locale()));
   }
   else
   {
diff --git a/glom/mode_data/test_flowtablewithfields.cc b/glom/mode_data/test_flowtablewithfields.cc
index dc972ae..e2ab4af 100644
--- a/glom/mode_data/test_flowtablewithfields.cc
+++ b/glom/mode_data/test_flowtablewithfields.cc
@@ -50,7 +50,7 @@ static void fill_flowtable(Glom::FlowTableWithFields& flowtable)
     Glom::sharedptr<Glom::LayoutItem_Text> item =
       Glom::sharedptr<Glom::LayoutItem_Text>::create();
     item->set_text("test static text 2");
-    item->set_title("title for text 2");
+    item->set_title("title for text 2", Application::get_current_locale());
     flowtable.add_layout_item(item);
   }
 
@@ -58,7 +58,7 @@ static void fill_flowtable(Glom::FlowTableWithFields& flowtable)
     Glom::sharedptr<Glom::LayoutItem_Image> item =
       Glom::sharedptr<Glom::LayoutItem_Image>::create();
     //item->set_image(somevalue);
-    item->set_title("title for image");
+    item->set_title("title for image", Application::get_current_locale());
     flowtable.add_layout_item(item);
   }
   
diff --git a/glom/mode_design/box_db_table_relationships.cc b/glom/mode_design/box_db_table_relationships.cc
index ab4ca41..f1228fd 100644
--- a/glom/mode_design/box_db_table_relationships.cc
+++ b/glom/mode_design/box_db_table_relationships.cc
@@ -20,6 +20,7 @@
 
 //#include <gtkmm/builder.h>
 #include "box_db_table_relationships.h"
+#include <glom/application.h>
 #include <libglom/db_utils.h>
 #include <algorithm>
 #include <glibmm/i18n.h>
@@ -111,8 +112,8 @@ bool Box_DB_Table_Relationships::fill_from_database()
         m_AddDel.set_value(iterTree, m_colName, relationship->get_name());
 
         //Title:
-        m_AddDel.set_value(iterTree, m_colTitle, relationship->get_title());
-        m_AddDel.set_value(iterTree, m_colTitleSingular, relationship->get_title_singular());
+        m_AddDel.set_value(iterTree, m_colTitle, relationship->get_title(Application::get_current_locale()));
+        m_AddDel.set_value(iterTree, m_colTitleSingular, relationship->get_title_singular(Application::get_current_locale()));
 
         //From Field:
         m_AddDel.set_value(iterTree, m_colFromField, relationship->get_from_field());
@@ -158,8 +159,8 @@ void Box_DB_Table_Relationships::save_to_document()
           relationship = sharedptr<Relationship>::create();
 
         relationship->set_name(name);
-        relationship->set_title(m_AddDel.get_value(iter, m_colTitle));
-        relationship->set_title_singular(m_AddDel.get_value(iter, m_colTitleSingular));
+        relationship->set_title(m_AddDel.get_value(iter, m_colTitle), Application::get_current_locale());
+        relationship->set_title_singular(m_AddDel.get_value(iter, m_colTitleSingular), Application::get_current_locale());
         relationship->set_from_table(m_table_name);
         relationship->set_from_field(m_AddDel.get_value(iter, m_colFromField));
         relationship->set_to_table(m_AddDel.get_value(iter, m_colToTable));
diff --git a/glom/mode_design/dialog_design.cc b/glom/mode_design/dialog_design.cc
index afd9e95..48b7d08 100644
--- a/glom/mode_design/dialog_design.cc
+++ b/glom/mode_design/dialog_design.cc
@@ -20,6 +20,7 @@
 
 #include "dialog_design.h"
 #include "../box_db_table.h"
+#include <glom/application.h>
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
@@ -55,7 +56,7 @@ bool Dialog_Design::init_db_details(const Glib::ustring& table_name)
      Document* document = dynamic_cast<Document*>(get_document());
      if(document)
      {
-       Glib::ustring table_title = document->get_table_title(table_name);
+       Glib::ustring table_title = document->get_table_title(table_name, Application::get_current_locale());
        if(table_title.empty())
          table_label = table_name;
        else
diff --git a/glom/mode_design/fields/box_db_table_definition.cc b/glom/mode_design/fields/box_db_table_definition.cc
index c223115..20d2098 100644
--- a/glom/mode_design/fields/box_db_table_definition.cc
+++ b/glom/mode_design/fields/box_db_table_definition.cc
@@ -22,6 +22,7 @@
 #include <glom/frame_glom.h>
 #include <glom/glade_utils.h>
 #include <glom/utils_ui.h> //For bold_message()).
+#include <glom/application.h>
 #include <libglom/libglom_config.h>
 #include <libglom/db_utils.h>
 #include <gtkmm/stock.h>
@@ -99,7 +100,7 @@ void Box_DB_Table_Definition::fill_field_row(const Gtk::TreeModel::iterator& ite
 
   m_AddDel.set_value(iter, m_colName, field->get_name());
 
-  const Glib::ustring title = field->get_title();
+  const Glib::ustring title = field->get_title(Application::get_current_locale());
   m_AddDel.set_value(iter, m_colTitle, title);
 
   //Type:
@@ -170,7 +171,7 @@ void Box_DB_Table_Definition::on_adddel_add(const Gtk::TreeModel::iterator& row)
   {
     sharedptr<Field> field(new Field());
     field->set_name(name);
-    field->set_title( Utils::title_from_string(name) ); //Start with a title that might be useful.
+    field->set_title( Utils::title_from_string(name) , Application::get_current_locale()); //Start with a title that might be useful.
     field->set_glom_type(Field::TYPE_NUMERIC);
 
     Glib::RefPtr<Gnome::Gda::Column> field_info = field->get_field_info();
@@ -444,7 +445,7 @@ sharedptr<Field> Box_DB_Table_Definition::get_field_definition(const Gtk::TreeMo
 
     //Title:
     const Glib::ustring title = m_AddDel.get_value(row, m_colTitle);
-    fieldResult->set_title(title);
+    fieldResult->set_title(title, Application::get_current_locale());
 
     //Type:
     const Glib::ustring& strType = m_AddDel.get_value(row, m_colType);
diff --git a/glom/mode_design/fields/dialog_fieldcalculation.cc b/glom/mode_design/fields/dialog_fieldcalculation.cc
index 8a4a848..a882b34 100644
--- a/glom/mode_design/fields/dialog_fieldcalculation.cc
+++ b/glom/mode_design/fields/dialog_fieldcalculation.cc
@@ -24,6 +24,7 @@
 #include <glom/frame_glom.h>
 #include <glom/python_embed/glom_python.h>
 #include <glom/utils_ui.h>
+#include <glom/application.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <gtksourceviewmm/languagemanager.h>
 
diff --git a/glom/mode_design/fields/dialog_fielddefinition.cc b/glom/mode_design/fields/dialog_fielddefinition.cc
index 868bdd7..fb82582 100644
--- a/glom/mode_design/fields/dialog_fielddefinition.cc
+++ b/glom/mode_design/fields/dialog_fielddefinition.cc
@@ -22,6 +22,7 @@
 #include "dialog_fieldcalculation.h"
 #include <glom/glade_utils.h>
 #include <glom/utils_ui.h>
+#include <glom/application.h>
 #include "../../box_db_table.h"
 #include <libglom/db_utils.h>
 //#include <libgnome/gnome-i18n.h>
@@ -155,7 +156,7 @@ void Dialog_FieldDefinition::set_field(const sharedptr<const Field>& field, cons
   sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
   sharedptr<Field> field_default_value = glom_sharedptr_clone(m_Field);
   field_default_value->set_name("glom_temp_default_value");
-  field_default_value->set_title(_("Default Value"));
+  field_default_value->set_title_original(_("Default Value"));
   layout_item->set_full_field_details(field_default_value);
   m_pDataWidget_DefaultValueSimple = Gtk::manage( new DataWidget(layout_item, "", get_document()) );
   if(!m_pDataWidget_DefaultValueSimple->get_data_child_widget())
@@ -210,7 +211,7 @@ void Dialog_FieldDefinition::set_field(const sharedptr<const Field>& field, cons
   m_pTextView_Calculation->get_buffer()->set_text(calculation);
   //std::cout << "  debug: dialog_fielddefinition.c:: after get_buffer()" << std::endl;
 
-  m_pEntry_Title->set_text(field->get_title());
+  m_pEntry_Title->set_text(field->get_title(Application::get_current_locale()));
 
   //Formatting:
   m_box_formatting->set_formatting_for_field(field->m_default_formatting, m_table_name, field);
@@ -270,7 +271,7 @@ sharedptr<Field> Dialog_FieldDefinition::get_field() const
   field->set_unique_key(m_pCheck_Unique->get_active());
   field->set_primary_key(m_pCheck_PrimaryKey->get_active());
 
-  field->set_title(m_pEntry_Title->get_text());
+  field->set_title(m_pEntry_Title->get_text(), Application::get_current_locale());
 
   //Formatting:
   m_box_formatting->get_formatting(field->m_default_formatting);
diff --git a/glom/mode_design/layout/combobox_fields.cc b/glom/mode_design/layout/combobox_fields.cc
index 956a57d..2ae9c60 100644
--- a/glom/mode_design/layout/combobox_fields.cc
+++ b/glom/mode_design/layout/combobox_fields.cc
@@ -19,6 +19,7 @@
  */
 
 #include <glom/mode_design/layout/combobox_fields.h>
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 #include <iostream>
@@ -201,7 +202,7 @@ void ComboBox_Fields::on_cell_data_title(const Gtk::TreeModel::const_iterator& i
   sharedptr<Field> field = row[m_model_columns.m_field];
   if(field)
   {
-    m_renderer_title->set_property("text", field->get_title_or_name());
+    m_renderer_title->set_property("text", field->get_title_or_name(Application::get_current_locale()));
   }
   else
   {
diff --git a/glom/mode_design/layout/combobox_relationship.cc b/glom/mode_design/layout/combobox_relationship.cc
index 1604836..3648aa3 100644
--- a/glom/mode_design/layout/combobox_relationship.cc
+++ b/glom/mode_design/layout/combobox_relationship.cc
@@ -19,6 +19,7 @@
  */
 
 #include <glom/mode_design/layout/combobox_relationship.h>
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -161,7 +162,7 @@ void ComboBox_Relationship::set_relationships(Document* document, const Glib::us
   m_model->clear();
 
   if(show_parent_table_name)
-    set_display_parent_table(parent_table_name, document->get_table_title(parent_table_name));
+    set_display_parent_table(parent_table_name, document->get_table_title(parent_table_name, Application::get_current_locale()));
 
   //Fill the model:
   for(type_vec_relationships::const_iterator iter = relationships.begin(); iter != relationships.end(); ++iter)
@@ -231,10 +232,10 @@ void ComboBox_Relationship::on_cell_data_title(const Gtk::TreeModel::const_itera
       //related relationship:
       sharedptr<Relationship> parent_relationship = (*iterParent)[m_model_columns.m_relationship];
       if(relationship)
-        m_renderer_title->set_property("text", parent_relationship->get_title_or_name() + "::" + relationship->get_title_or_name());
+        m_renderer_title->set_property("text", parent_relationship->get_title_or_name(Application::get_current_locale()) + "::" + relationship->get_title_or_name(Application::get_current_locale()));
     }
     else
-      m_renderer_title->set_property("text", relationship->get_title_or_name());
+      m_renderer_title->set_property("text", relationship->get_title_or_name(Application::get_current_locale()));
   }
   else if(get_has_parent_table())
   {
@@ -264,7 +265,7 @@ void ComboBox_Relationship::on_cell_data_fromfield(const Gtk::TreeModel::const_i
     {
       sharedptr<Relationship> parent_relationship = (*iterParent)[m_model_columns.m_relationship];
       if(parent_relationship)
-        m_renderer_fromfield->set_property("text", Glib::ustring::compose(_(" Via: %1::%2"), parent_relationship->get_title(), relationship->get_from_field()));
+        m_renderer_fromfield->set_property("text", Glib::ustring::compose(_(" Via: %1::%2"), parent_relationship->get_title(Application::get_current_locale()), relationship->get_from_field()));
     }
     else
     {
diff --git a/glom/mode_design/layout/dialog_choose_field.cc b/glom/mode_design/layout/dialog_choose_field.cc
index 1db4df8..5ff0adc 100644
--- a/glom/mode_design/layout/dialog_choose_field.cc
+++ b/glom/mode_design/layout/dialog_choose_field.cc
@@ -19,6 +19,7 @@
  */
 
 #include "dialog_choose_field.h"
+#include <glom/application.h>
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
@@ -86,7 +87,7 @@ void Dialog_ChooseField::set_document(Document* document, const Glib::ustring& t
     m_combo_relationship->set_selected_relationship( field->get_relationship(), field->get_related_relationship());
   }
   else
-    m_combo_relationship->set_selected_parent_table(table_name, document->get_table_title(table_name)); 
+    m_combo_relationship->set_selected_parent_table(table_name, document->get_table_title(table_name, Application::get_current_locale())); 
 
   //If one start field was specified, then multiple selection would not make 
   //much sense. The caller probably wants single selection.
@@ -148,10 +149,10 @@ void Dialog_ChooseField::set_document(Document* document, const Glib::ustring& t
     //Fill the list of relationships:
 
     //Add a special option for the current table:
-    m_combo_relationship->set_display_parent_table(table_name, document->get_table_title(table_name));
+    m_combo_relationship->set_display_parent_table(table_name, document->get_table_title(table_name, Application::get_current_locale()));
 
     //Add the relationships for this table:
-    const Glib::ustring table_title = document->get_table_title(table_name);
+    const Glib::ustring table_title = document->get_table_title(table_name, Application::get_current_locale());
     m_combo_relationship->set_relationships(document, table_name, false /* show related relationships */);
 
     //Set the table name and title:
@@ -167,7 +168,7 @@ void Dialog_ChooseField::set_document(Document* document, const Glib::ustring& t
 
       sharedptr<Field> field = *iter;
       row[m_ColumnsFields.m_col_name] = field->get_name();
-      row[m_ColumnsFields.m_col_title] = field->get_title();
+      row[m_ColumnsFields.m_col_title] = field->get_title(Application::get_current_locale());
       row[m_ColumnsFields.m_col_field] = field;
     }
   }
@@ -326,7 +327,7 @@ void Dialog_ChooseField::on_combo_relationship_changed()
 
       sharedptr<Field> field = *iter;
       row[m_ColumnsFields.m_col_name] = field->get_name();
-      row[m_ColumnsFields.m_col_title] = field->get_title();
+      row[m_ColumnsFields.m_col_title] = field->get_title(Application::get_current_locale());
       row[m_ColumnsFields.m_col_field] = field;
     }
 
diff --git a/glom/mode_design/layout/dialog_choose_relationship.cc b/glom/mode_design/layout/dialog_choose_relationship.cc
index bd10715..e4064d2 100644
--- a/glom/mode_design/layout/dialog_choose_relationship.cc
+++ b/glom/mode_design/layout/dialog_choose_relationship.cc
@@ -86,7 +86,7 @@ void Dialog_ChooseRelationship::set_document(Document* document, const Glib::ust
       if(relationship)
         row[m_ColumnsRelationships.m_col_name] = glom_get_sharedptr_name(relationship);
 
-      //row[m_ColumnsRelationships.m_col_title] = iter->get_title();
+      //row[m_ColumnsRelationships.m_col_title] = iter->get_title(Application::get_current_locale());
       row[m_ColumnsRelationships.m_col_relationship] = relationship;
     }
   }
diff --git a/glom/mode_design/layout/dialog_layout_details.cc b/glom/mode_design/layout/dialog_layout_details.cc
index 143c9ab..5483d60 100644
--- a/glom/mode_design/layout/dialog_layout_details.cc
+++ b/glom/mode_design/layout/dialog_layout_details.cc
@@ -26,6 +26,7 @@
 #include <glom/frame_glom.h> //For show_ok_dialog()
 //#include <libgnome/gnome-i18n.h>
 #include <glom/utils_ui.h> //For bold_message()).
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 #include <sstream> //For stringstream
 
@@ -341,7 +342,7 @@ void Dialog_Layout_Details::set_document(const Glib::ustring& layout_name, const
   {
     //Set the table name and title:
     m_label_table_name->set_text(table_name);
-    m_entry_table_title->set_text( document->get_table_title(table_name) );
+    m_entry_table_title->set_text( document->get_table_title(table_name, Application::get_current_locale()) );
 
     Document::type_list_layout_groups list_groups = document->get_data_layout_groups_plus_new_fields(m_layout_name, m_table_name, m_layout_platform);
     document->fill_layout_field_details(m_table_name, list_groups); //Update with full field information.
@@ -658,7 +659,7 @@ void Dialog_Layout_Details::on_button_add_button()
 
     //Add a new button:
     sharedptr<LayoutItem_Button> button = sharedptr<LayoutItem_Button>::create();
-    button->set_title(_("New Button")); //Give the button a default title, so it is big enough, and so people see that they should change it.
+    button->set_title_original(_("New Button")); //Give the button a default title, so it is big enough, and so people see that they should change it.
     row[m_model_items->m_columns.m_col_layout_item] = button;
 
     //Scroll to, and select, the new row:
@@ -683,7 +684,7 @@ void Dialog_Layout_Details::on_button_add_text()
 
     //Add a new button:
     sharedptr<LayoutItem_Text> textobject = sharedptr<LayoutItem_Text>::create();
-    textobject->set_title(_("Text Title")); //Give the button a default title, so it is big enough, and so people see that they should change it.
+    textobject->set_title_original(_("Text Title")); //Give the button a default title, so it is big enough, and so people see that they should change it.
     row[m_model_items->m_columns.m_col_layout_item] = textobject;
 
     //Scroll to, and select, the new row:
@@ -708,7 +709,7 @@ void Dialog_Layout_Details::on_button_add_image()
 
     //Add a new button:
     sharedptr<LayoutItem_Image> imageobject = sharedptr<LayoutItem_Image>::create();
-    imageobject->set_title(_("Image Title")); //Give the item a default title, so it is big enough, and so people see that they should change it.
+    imageobject->set_title_original(_("Image Title")); //Give the item a default title, so it is big enough, and so people see that they should change it.
     row[m_model_items->m_columns.m_col_layout_item] = imageobject;
 
     //Scroll to, and select, the new row:
@@ -1053,7 +1054,7 @@ void Dialog_Layout_Details::save_to_document()
     //Set the table name and title:
     Document* document = get_document();
     if(document)
-      document->set_table_title( m_table_name, m_entry_table_title->get_text() );
+      document->set_table_title( m_table_name, m_entry_table_title->get_text(), Application::get_current_locale());
 
     //Get the data from the TreeView and store it in the document:
 
@@ -1198,7 +1199,7 @@ void Dialog_Layout_Details::on_cell_data_title(Gtk::CellRenderer* renderer, cons
       if(layout_notebook)
         renderer_text->property_text() = _("(Notebook)");
       else if(layout_item)
-        renderer_text->property_text() = layout_item->get_title();
+        renderer_text->property_text() = layout_item->get_title(Application::get_current_locale());
       else
         renderer_text->property_text() = Glib::ustring();
 
@@ -1292,7 +1293,7 @@ void Dialog_Layout_Details::on_treeview_cell_edited_title(const Glib::ustring& p
       if(layout_item)
       {
         //Store the user's new text in the model:
-        layout_item->set_title(new_text);
+        layout_item->set_title(new_text, Application::get_current_locale());
 
         m_modified = true;
       }
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc b/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc
index f5b285c..570bea3 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc
@@ -22,6 +22,7 @@
 #include "dialog_buttonscript.h"
 #include <glom/python_embed/glom_python.h>
 #include <glom/utils_ui.h>
+#include <glom/application.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <gtksourceviewmm/languagemanager.h>
 
@@ -80,7 +81,7 @@ void Dialog_ButtonScript::set_script(const sharedptr<const LayoutItem_Button>& s
 
   m_text_view_script->get_buffer()->set_text( script->get_script() );
 
-  m_entry_title->set_text(script->get_title());
+  m_entry_title->set_text(script->get_title(Application::get_current_locale()));
   //set_blocked(false);
 
   //Dialog_Properties::set_modified(false);
@@ -98,7 +99,7 @@ sharedptr<LayoutItem_Button> Dialog_ButtonScript::get_script() const
 void Dialog_ButtonScript::get_script(const sharedptr<LayoutItem_Button>& script) const
 {
   script->set_script(m_text_view_script->get_buffer()->get_text() );
-  script->set_title(m_entry_title->get_text());
+  script->set_title(m_entry_title->get_text(), Application::get_current_locale());
 }
 
 void Dialog_ButtonScript::on_button_test_script()
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_field_layout.cc b/glom/mode_design/layout/layout_item_dialogs/dialog_field_layout.cc
index 4e06915..ce1d2b1 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_field_layout.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_field_layout.cc
@@ -21,6 +21,7 @@
 #include "dialog_field_layout.h"
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/glade_utils.h>
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -89,11 +90,11 @@ void Dialog_FieldLayout::set_field(const sharedptr<const LayoutItem_Field>& fiel
   //Custom title:
   Glib::ustring title_custom;
   if(field->get_title_custom())
-    title_custom = field->get_title_custom()->get_title();
+    title_custom = field->get_title_custom()->get_title(Application::get_current_locale());
 
   m_radiobutton_title_custom->set_active( field->get_title_custom() && field->get_title_custom()->get_use_custom_title() );
   m_entry_title_custom->set_text(title_custom);
-  m_label_title_default->set_text(field->get_title_or_name_no_custom());
+  m_label_title_default->set_text(field->get_title_or_name_no_custom(Application::get_current_locale()));
 
   //Formatting:
   m_radiobutton_custom_formatting->set_active( !field->get_formatting_use_default() );
@@ -113,7 +114,7 @@ sharedptr<LayoutItem_Field> Dialog_FieldLayout::get_field_chosen() const
 
   sharedptr<CustomTitle> title_custom = sharedptr<CustomTitle>::create();
   title_custom->set_use_custom_title(m_radiobutton_title_custom->get_active()); //For instance, tell it to really use a blank title.
-  title_custom->set_title(m_entry_title_custom->get_text());
+  title_custom->set_title(m_entry_title_custom->get_text(), Application::get_current_locale());
 
   m_layout_item->set_title_custom(title_custom);
 
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_imageobject.cc b/glom/mode_design/layout/layout_item_dialogs/dialog_imageobject.cc
index 28f3d85..76c73d7 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_imageobject.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_imageobject.cc
@@ -22,6 +22,7 @@
 #include "dialog_imageobject.h"
 #include <glom/python_embed/glom_python.h>
 #include <libglom/data_structure/glomconversions.h>
+#include <glom/application.h>
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
@@ -69,7 +70,7 @@ void Dialog_ImageObject::set_imageobject(const sharedptr<const LayoutItem_Image>
   m_imageobject = glom_sharedptr_clone(imageobject); //Remember it so we save any details that are not in our UI.
   m_table_name = table_name;  //Used for lookup combo boxes.
 
-  m_entry_title->set_text(imageobject->get_title());
+  m_entry_title->set_text(imageobject->get_title(Application::get_current_locale()));
   m_image->set_value( imageobject->get_image() );
 
   if(show_title)
@@ -86,7 +87,7 @@ sharedptr<LayoutItem_Image> Dialog_ImageObject::get_imageobject() const
 {
   sharedptr<LayoutItem_Image> result = glom_sharedptr_clone(m_imageobject); //Start with the old details, to preserve anything that is not in our UI.
 
-  result->set_title(m_entry_title->get_text());
+  result->set_title(m_entry_title->get_text(), Application::get_current_locale());
   result->set_image( m_image->get_value() );
 
   return result;
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_notebook.cc b/glom/mode_design/layout/layout_item_dialogs/dialog_notebook.cc
index 2dcc3c0..0be402e 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_notebook.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_notebook.cc
@@ -20,6 +20,7 @@
 
 #include "dialog_notebook.h"
 #include <glom/mode_design/layout/dialog_layout.h>
+#include <glom/application.h>
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
@@ -101,7 +102,7 @@ void Dialog_Notebook::set_notebook(const sharedptr<const LayoutItem_Notebook>& s
 
       row[m_ColumnsTabs.m_col_item] = glom_sharedptr_clone(item);
       row[m_ColumnsTabs.m_col_name] = item->get_name();
-      row[m_ColumnsTabs.m_col_title] = item->get_title();
+      row[m_ColumnsTabs.m_col_title] = item->get_title(Application::get_current_locale());
       row[m_ColumnsTabs.m_col_sequence] = sequence;
       ++sequence;
   }
@@ -184,7 +185,7 @@ sharedptr<LayoutItem_Notebook> Dialog_Notebook::get_notebook() const
         group_copy = sharedptr<LayoutGroup>::create();
 
       group_copy->set_name(name);
-      group_copy->set_title( row[m_ColumnsTabs.m_col_title] );
+      group_copy->set_title( row[m_ColumnsTabs.m_col_title] , Application::get_current_locale());
       //group_copy->set_sequence( row[m_ColumnsTabs.m_col_sequence] );
 
       result->add_item(group_copy);
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_textobject.cc b/glom/mode_design/layout/layout_item_dialogs/dialog_textobject.cc
index 72655ab..df06cab 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_textobject.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_textobject.cc
@@ -20,6 +20,7 @@
 
 
 #include "dialog_textobject.h"
+#include <glom/application.h>
 #include <libglom/data_structure/glomconversions.h>
 
 //#include <libgnome/gnome-i18n.h>
@@ -59,8 +60,8 @@ void Dialog_TextObject::set_textobject(const sharedptr<const LayoutItem_Text>& t
   m_textobject = glom_sharedptr_clone(textobject); //Remember it so we save any details that are not in our UI.
   m_table_name = table_name;  //Used for lookup combo boxes.
 
-  m_entry_title->set_text(textobject->get_title());
-  m_text_view->get_buffer()->set_text( textobject->get_text() );
+  m_entry_title->set_text(textobject->get_title(Application::get_current_locale()));
+  m_text_view->get_buffer()->set_text( textobject->get_text(Application::get_current_locale()) );
 
   if(show_title)
     m_box_title->show();
@@ -83,8 +84,8 @@ sharedptr<LayoutItem_Text> Dialog_TextObject::get_textobject() const
 
 void Dialog_TextObject::get_textobject(sharedptr<LayoutItem_Text>& textobject) const
 {
-  textobject->set_title(m_entry_title->get_text());
-  textobject->set_text( m_text_view->get_buffer()->get_text() );
+  textobject->set_title(m_entry_title->get_text(), Application::get_current_locale());
+  textobject->set_text( m_text_view->get_buffer()->get_text(), Application::get_current_locale());
 }
 
 } //namespace Glom
diff --git a/glom/mode_design/print_layouts/box_print_layouts.cc b/glom/mode_design/print_layouts/box_print_layouts.cc
index 7c7b3bb..4416c95 100644
--- a/glom/mode_design/print_layouts/box_print_layouts.cc
+++ b/glom/mode_design/print_layouts/box_print_layouts.cc
@@ -19,6 +19,7 @@
  */
 
 #include "box_print_layouts.h"
+#include <glom/application.h>
 #include <gtkmm/alignment.h>
 #include <gtkmm/messagedialog.h>
 #include <gtkmm/stock.h>
@@ -64,7 +65,7 @@ void Box_Print_Layouts::fill_row(const Gtk::TreeModel::iterator& iter, const sha
     const Glib::ustring& name = item->get_name();
     m_AddDel.set_value_key(iter, name);
     m_AddDel.set_value(iter, m_colName, name);
-    m_AddDel.set_value(iter, m_colTitle, item->get_title());
+    m_AddDel.set_value(iter, m_colTitle, item->get_title(Application::get_current_locale()));
   }
 }
 
@@ -140,7 +141,7 @@ void Box_Print_Layouts::on_adddel_user_added(const Gtk::TreeModel::iterator& row
       m_AddDel.set_value(row, m_colTitle, title);
     }
 
-    item->set_title(title);
+    item->set_title(title, Application::get_current_locale());
 
     get_document()->set_print_layout(m_table_name, item);
   }
@@ -187,7 +188,7 @@ void Box_Print_Layouts::save_to_document()
         sharedptr<PrintLayout> item(new PrintLayout());
         item->set_name(name);
 
-        item->set_title( m_AddDel.get_value(iter, m_colTitle) ); //TODO: Translations: Store the original in the TreeView.
+        item->set_title( m_AddDel.get_value(iter, m_colTitle) , Application::get_current_locale()); //TODO: Translations: Store the original in the TreeView.
 
         get_document()->set_print_layout(m_table_name, item);
         modified = true;
@@ -211,7 +212,7 @@ void Box_Print_Layouts::on_adddel_user_changed(const Gtk::TreeModel::iterator& r
     {
       if(column == m_colTitle)
       {
-        item->set_title( m_AddDel.get_value(row, m_colTitle) );
+        item->set_title( m_AddDel.get_value(row, m_colTitle) , Application::get_current_locale());
         //TODO: Unnecessary:
         document->set_print_layout(m_table_name, item);
       }
diff --git a/glom/mode_design/print_layouts/window_print_layout_edit.cc b/glom/mode_design/print_layouts/window_print_layout_edit.cc
index 74fbcbe..67dc1ca 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.cc
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.cc
@@ -454,7 +454,7 @@ sharedptr<LayoutItem> Window_PrintLayout_Edit::create_empty_item(PrintLayoutTool
     sharedptr<LayoutItem_Text> layout_item_derived = sharedptr<LayoutItem_Text>::create();
 
     // Note to translators: This is the default contents of a text item on a print layout: 
-    layout_item_derived->set_text(_("text")); //TODO: Choose some other longer default because this is hidden under the drag icon?
+    layout_item_derived->set_text_original(_("text")); //TODO: Choose some other longer default because this is hidden under the drag icon?
     layout_item = layout_item_derived;
     layout_item->set_print_layout_position(0, 0,
       PrintLayoutUtils::ITEM_WIDTH_WIDE, PrintLayoutUtils::ITEM_HEIGHT);
@@ -640,7 +640,7 @@ void Window_PrintLayout_Edit::update_table_title()
   Glib::ustring table_label = _("None selected");
 
   //Show the table title (if any) and name:
-  Glib::ustring table_title = document->get_table_title(m_table_name);
+  Glib::ustring table_title = document->get_table_title(m_table_name, Application::get_current_locale());
   if(table_title.empty())
     table_label = m_table_name;
   else
@@ -682,7 +682,7 @@ void Window_PrintLayout_Edit::set_print_layout(const Glib::ustring& table_name,
   update_table_title();
 
   m_entry_name->set_text(print_layout->get_name()); 
-  m_entry_title->set_text(print_layout->get_title());
+  m_entry_title->set_text(print_layout->get_title(Application::get_current_locale()));
 
   set_ruler_sizes();
 
@@ -704,7 +704,7 @@ sharedptr<PrintLayout> Window_PrintLayout_Edit::get_print_layout()
 {
   m_print_layout = m_canvas.get_print_layout();
   m_print_layout->set_name( m_entry_name->get_text() );
-  m_print_layout->set_title( m_entry_title->get_text() );
+  m_print_layout->set_title( m_entry_title->get_text() , Application::get_current_locale());
 
   m_print_layout->set_show_grid( m_action_showgrid->get_active() );
   m_print_layout->set_show_rules( m_action_showrules->get_active() );
@@ -874,7 +874,7 @@ void Window_PrintLayout_Edit::on_menu_insert_image()
 {
   sharedptr<LayoutItem> layout_item = create_empty_item(PrintLayoutToolbarButton::ITEM_IMAGE);
   // Note to translators: This is the default contents of a text item on a print layout: 
-  //layout_item->set_text(_("text"));
+  //layout_item->set_text_original(_("text"));
   set_default_position(layout_item);
 
   Glib::RefPtr<CanvasLayoutItem> item = CanvasLayoutItem::create(layout_item);
@@ -901,7 +901,7 @@ void Window_PrintLayout_Edit::on_menu_insert_line_horizontal()
   */
 
   // Note to translators: This is the default contents of a text item on a print layout: 
-  //layout_item->set_text(_("text"));
+  //layout_item->set_text_original(_("text"));
   //layout_item->set_coordinates(item_x, item_y, item_x + 100, item_y);
 
   Glib::RefPtr<CanvasLayoutItem> item = CanvasLayoutItem::create(layout_item);
diff --git a/glom/mode_design/relationships_overview/canvas_group_dbtable.cc b/glom/mode_design/relationships_overview/canvas_group_dbtable.cc
index 91bd16a..1235e2a 100644
--- a/glom/mode_design/relationships_overview/canvas_group_dbtable.cc
+++ b/glom/mode_design/relationships_overview/canvas_group_dbtable.cc
@@ -22,6 +22,7 @@
 #include "glom/utility_widgets/canvas/canvas_rect_movable.h"
 #include "glom/utility_widgets/canvas/canvas_line_movable.h"
 #include "glom/utility_widgets/canvas/canvas_text_movable.h"
+#include <glom/application.h>
 #include <goocanvasmm/canvas.h>
 #include <goocanvasmm/rect.h>
 #include <goocanvasmm/polyline.h>
@@ -86,9 +87,9 @@ CanvasGroupDbTable::CanvasGroupDbTable(const Glib::ustring& table_name, const Gl
     //Show the primary key as bold:
     Glib::ustring title;
     if(field->get_primary_key())
-      title = "<u>" + field->get_title_or_name() + "</u>";
+      title = "<u>" + field->get_title_or_name(Application::get_current_locale()) + "</u>";
     else
-      title = field->get_title_or_name();
+      title = field->get_title_or_name(Application::get_current_locale());
 
     Glib::RefPtr<CanvasTextMovable> text_item = CanvasTextMovable::create(title, 
       x + margin, y + margin + field_y, m_table_width - margin*2,
diff --git a/glom/mode_design/relationships_overview/dialog_relationships_overview.cc b/glom/mode_design/relationships_overview/dialog_relationships_overview.cc
index 5de17d9..ad7ad4b 100644
--- a/glom/mode_design/relationships_overview/dialog_relationships_overview.cc
+++ b/glom/mode_design/relationships_overview/dialog_relationships_overview.cc
@@ -195,7 +195,7 @@ void Dialog_RelationshipsOverview::draw_tables()
       Document::type_vec_fields fields = document->get_table_fields(table_name);
 
       Glib::RefPtr<CanvasGroupDbTable> table_group =
-        CanvasGroupDbTable::create(info->get_name(), info->get_title_or_name(), fields, table_x, table_y);
+        CanvasGroupDbTable::create(info->get_name(), info->get_title_or_name(Application::get_current_locale()), fields, table_x, table_y);
       m_group_tables->add_child(table_group);
       m_canvas.associate_with_grid(table_group); //Make snapping work.
 
@@ -317,7 +317,7 @@ void Dialog_RelationshipsOverview::draw_lines()
 
           const double text_x = (from_field_x + to_field_x) / 2;
           const double text_y = ((from_field_y + to_field_y) / 2) + y_offset;
-          Glib::RefPtr<CanvasTextMovable> text = CanvasTextMovable::create(relationship->get_title_or_name(),
+          Glib::RefPtr<CanvasTextMovable> text = CanvasTextMovable::create(relationship->get_title_or_name(Application::get_current_locale()),
             text_x, text_y, -1, //TODO: Calc a suitable width.
             Goocanvas::ANCHOR_CENTER);
           text->property_font() = "Sans 10";
diff --git a/glom/mode_design/report_layout/dialog_layout_report.cc b/glom/mode_design/report_layout/dialog_layout_report.cc
index a69ef19..f711069 100644
--- a/glom/mode_design/report_layout/dialog_layout_report.cc
+++ b/glom/mode_design/report_layout/dialog_layout_report.cc
@@ -34,6 +34,7 @@
 #include <glom/mode_design/layout/layout_item_dialogs/dialog_group_by.h>
 #include <glom/mode_design/layout/layout_item_dialogs/dialog_field_summary.h>
 #include <glom/mode_design/layout/dialog_choose_relationship.h>
+#include <glom/application.h>
 //#include <libgnome/gnome-i18n.h>
 #include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
@@ -350,7 +351,7 @@ void Dialog_Layout_Report::set_report(const Glib::ustring& table_name, const sha
   m_label_table_name->set_text(table_name);
 
   m_entry_name->set_text(report->get_name());
-  m_entry_title->set_text(report->get_title());
+  m_entry_title->set_text(report->get_title(Application::get_current_locale()));
   m_checkbutton_table_title->set_active(report->get_show_table_title());
 
   //Update the tree models from the document
@@ -359,7 +360,7 @@ void Dialog_Layout_Report::set_report(const Glib::ustring& table_name, const sha
   {
 
 
-    //m_entry_table_title->set_text( document->get_table_title(table_name) );
+    //m_entry_table_title->set_text( document->get_table_title(table_name, Application::get_current_locale()) );
 
     //document->fill_layout_field_details(m_table_name, mapGroups); //Update with full field information.
 
@@ -1008,7 +1009,7 @@ Glib::ustring Dialog_Layout_Report::get_original_report_name() const
 sharedptr<Report> Dialog_Layout_Report::get_report()
 {
   m_report->set_name( m_entry_name->get_text() );
-  m_report->set_title( m_entry_title->get_text() );
+  m_report->set_title( m_entry_title->get_text() , Application::get_current_locale());
   m_report->set_show_table_title( m_checkbutton_table_title->get_active() );
 
   m_report->m_layout_group->remove_all_items();
diff --git a/glom/mode_design/translation/dialog_change_language.cc b/glom/mode_design/translation/dialog_change_language.cc
index 207772f..30d0239 100644
--- a/glom/mode_design/translation/dialog_change_language.cc
+++ b/glom/mode_design/translation/dialog_change_language.cc
@@ -19,6 +19,7 @@
  */
 
 #include "dialog_change_language.h"
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -33,7 +34,7 @@ Dialog_ChangeLanguage::Dialog_ChangeLanguage(BaseObjectType* cobject, const Glib
 {
   builder->get_widget_derived("combobox_locale", m_combo_locale);
 
-  m_combo_locale->set_selected_locale(TranslatableItem::get_current_locale());
+  m_combo_locale->set_selected_locale(Application::get_current_locale());
 }
 
 Dialog_ChangeLanguage::~Dialog_ChangeLanguage()
diff --git a/glom/mode_design/translation/dialog_copy_translation.cc b/glom/mode_design/translation/dialog_copy_translation.cc
index 8e514f4..59248dc 100644
--- a/glom/mode_design/translation/dialog_copy_translation.cc
+++ b/glom/mode_design/translation/dialog_copy_translation.cc
@@ -20,6 +20,7 @@
 
 #include "dialog_copy_translation.h"
 #include <libglom/utils.h> //For bold_message()).
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -34,7 +35,7 @@ Dialog_CopyTranslation::Dialog_CopyTranslation(BaseObjectType* cobject, const Gl
 {
   builder->get_widget_derived("combobox_locale", m_combo_locale);
 
-  m_combo_locale->set_selected_locale(TranslatableItem::get_current_locale());
+  m_combo_locale->set_selected_locale(Application::get_current_locale());
 }
 
 Dialog_CopyTranslation::~Dialog_CopyTranslation()
diff --git a/glom/mode_design/translation/dialog_identify_original.cc b/glom/mode_design/translation/dialog_identify_original.cc
index 4d7c9d5..67c58e5 100644
--- a/glom/mode_design/translation/dialog_identify_original.cc
+++ b/glom/mode_design/translation/dialog_identify_original.cc
@@ -21,6 +21,7 @@
 #include "dialog_identify_original.h"
 #include <glom/mode_design/iso_codes.h>
 #include <glom/utils_ui.h> //For bold_message()).
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 #include <iostream>
@@ -39,7 +40,7 @@ Dialog_IdentifyOriginal::Dialog_IdentifyOriginal(BaseObjectType* cobject, const
   builder->get_widget("label_original", m_label_original);
   builder->get_widget_derived("combobox_locale", m_combo_locale);
 
-  m_combo_locale->set_selected_locale(TranslatableItem::get_current_locale());
+  m_combo_locale->set_selected_locale(Application::get_current_locale());
 }
 
 Dialog_IdentifyOriginal::~Dialog_IdentifyOriginal()
@@ -53,7 +54,7 @@ void Dialog_IdentifyOriginal::load_from_document()
   if(m_label_original )
     m_label_original->set_markup( Utils::bold_message( IsoCodes::get_locale_name( get_document()->get_translation_original_locale()) ) );
 
-  m_combo_locale->set_selected_locale(TranslatableItem::get_current_locale());
+  m_combo_locale->set_selected_locale(Application::get_current_locale());
 
   View_Glom::load_from_document();
 }
diff --git a/glom/mode_design/translation/window_translations.cc b/glom/mode_design/translation/window_translations.cc
index 48d0247..06d31c0 100644
--- a/glom/mode_design/translation/window_translations.cc
+++ b/glom/mode_design/translation/window_translations.cc
@@ -26,6 +26,7 @@
 #include <libglom/utils.h>
 #include <libglom/translations_po.h>
 #include <glom/glade_utils.h>
+#include <glom/application.h>
 #include <gtkmm/filefilter.h>
 #include <gtkmm/stock.h>
 #include <gtkmm/filechooserdialog.h>
@@ -107,9 +108,9 @@ Window_Translations::Window_Translations(BaseObjectType* cobject, const Glib::Re
   show_all_children();
 
   //Start with the currently-used/tested translation, if appropriate:
-  if(TranslatableItem::get_current_locale_not_original())
+  if(Application::get_current_locale_not_original())
   {
-    m_translation_locale = TranslatableItem::get_current_locale();
+    m_translation_locale = Application::get_current_locale();
     m_combo_target_locale->set_selected_locale(m_translation_locale);
     //The translations will be shown in the treeview when load_from_document() is called.
   }
@@ -252,7 +253,7 @@ void Window_Translations::save_to_document()
     if(item)
     {
       const Glib::ustring translation = row[m_columns.m_col_translation];
-      item->set_title_translation(m_translation_locale, translation);
+      item->set_title(translation, m_translation_locale);
     }
   }
 
diff --git a/glom/mode_design/users/dialog_groups_list.cc b/glom/mode_design/users/dialog_groups_list.cc
index 2666866..20667a1 100644
--- a/glom/mode_design/users/dialog_groups_list.cc
+++ b/glom/mode_design/users/dialog_groups_list.cc
@@ -24,6 +24,7 @@
 #include "dialog_new_group.h"
 #include <libglom/standard_table_prefs_fields.h>
 #include <glom/glade_utils.h>
+#include <glom/application.h>
 #include <libglom/privs.h>
 //#include <libgnome/gnome-i18n.h>
 #include <glom/utils_ui.h> //For bold_message()).
@@ -128,7 +129,7 @@ void Dialog_GroupsList::set_document(const Glib::ustring& layout, Document* docu
   {
     //Set the table name and title:
     m_label_table_name->set_text(table_name);
-    m_entry_table_title->set_text( document->get_table_title(table_name) );
+    m_entry_table_title->set_text( document->get_table_title(table_name, Application::get_current_locale()) );
 
     Document::type_list_layout_groups mapGroups = document->get_data_layout_groups_plus_new_fields(layout, m_table_name, m_layout_platform);
 
@@ -415,7 +416,7 @@ void Dialog_GroupsList::fill_table_list(const Glib::ustring& group_name)
       const Glib::ustring table_name = (*iter)->get_name();
 
       row[m_model_columns_tables.m_col_name] = table_name;
-      row[m_model_columns_tables.m_col_title] = (*iter)->get_title_or_name();
+      row[m_model_columns_tables.m_col_title] = (*iter)->get_title_or_name(Application::get_current_locale());
 
       const Privileges privs = Privs::get_table_privileges(group_name, table_name);
       row[m_model_columns_tables.m_col_view] = privs.m_view;
diff --git a/glom/navigation/box_tables.cc b/glom/navigation/box_tables.cc
index 54ec84c..990da17 100644
--- a/glom/navigation/box_tables.cc
+++ b/glom/navigation/box_tables.cc
@@ -89,14 +89,14 @@ void Box_Tables::fill_table_row(const Gtk::TreeModel::iterator& iter, const shar
 
     if(developer_mode)
     {
-      //std::cout << "debug: " << G_STRFUNC << ": dev title=" << table_info->get_title() << std::endl;
-      m_AddDel.set_value(iter, m_colTitle, table_info->get_title());
-      m_AddDel.set_value(iter, m_colTitleSingular, table_info->get_title_singular());
+      //std::cout << "debug: " << G_STRFUNC << ": dev title=" << table_info->get_title(Application::get_current_locale()) << std::endl;
+      m_AddDel.set_value(iter, m_colTitle, table_info->get_title(Application::get_current_locale()));
+      m_AddDel.set_value(iter, m_colTitleSingular, table_info->get_title_singular(Application::get_current_locale()));
     }
     else
     {
-      //std::cout << "debug: " << G_STRFUNC << ": op get_title_or_name=" << table_info->get_title_or_name() << std::endl;
-      m_AddDel.set_value(iter, m_colTitle, table_info->get_title_or_name());
+      //std::cout << "debug: " << G_STRFUNC << ": op get_title_or_name=" << table_info->get_title_or_name(Application::get_current_locale()) << std::endl;
+      m_AddDel.set_value(iter, m_colTitle, table_info->get_title_or_name(Application::get_current_locale()));
     }
 
     m_AddDel.set_value(iter, m_colDefault, table_info->m_default);
@@ -175,7 +175,7 @@ bool Box_Tables::fill_from_database()
       {
         table_info = *iterFind;
 
-        //std::cout << "debug: " << G_STRFUNC << ": name=" << (*iterFind)->get_name() << ", table_info->get_title()=" << (*iterFind)->get_title() << std::endl;
+        //std::cout << "debug: " << G_STRFUNC << ": name=" << (*iterFind)->get_name() << ", table_info->get_title(Application::get_current_locale())=" << (*iterFind)->get_title(Application::get_current_locale()) << std::endl;
       }
       else
       {
@@ -478,9 +478,9 @@ void Box_Tables::save_to_document()
         if(!table_info->get_name().empty())
         {
           table_info->m_hidden = m_AddDel.get_value_as_bool(iter, m_colHidden);
-          table_info->set_title( m_AddDel.get_value(iter, m_colTitle) ); //TODO_Translations: Store the TableInfo in the TreeView.
-          table_info->set_title_singular( m_AddDel.get_value(iter, m_colTitleSingular) ); //TODO_Translations: Store the TableInfo in the TreeView.
-          //std::cout << "debug: " << G_STRFUNC << ": title=" << table_info->get_title() << std::endl;
+          table_info->set_title( m_AddDel.get_value(iter, m_colTitle) , Application::get_current_locale()); //TODO_Translations: Store the TableInfo in the TreeView.
+          table_info->set_title_singular( m_AddDel.get_value(iter, m_colTitleSingular), Application::get_current_locale()); //TODO_Translations: Store the TableInfo in the TreeView.
+          //std::cout << "debug: " << G_STRFUNC << ": title=" << table_info->get_title(Application::get_current_locale()) << std::endl;
           table_info->m_default = m_AddDel.get_value_as_bool(iter, m_colDefault);
 
           listTables.push_back(table_info);
diff --git a/glom/print_layout/canvas_layout_item.cc b/glom/print_layout/canvas_layout_item.cc
index 8ca1a63..de0fefd 100644
--- a/glom/print_layout/canvas_layout_item.cc
+++ b/glom/print_layout/canvas_layout_item.cc
@@ -26,6 +26,7 @@
 #include <glom/utility_widgets/canvas/canvas_line_movable.h>
 #include <glom/utility_widgets/canvas/canvas_group_movable.h>
 #include <glom/utility_widgets/canvas/canvas_table_movable.h>
+#include <glom/application.h>
 #include <libglom/data_structure/layout/layoutitem_button.h>
 #include <libglom/data_structure/layout/layoutitem_text.h>
 #include <libglom/data_structure/layout/layoutitem_image.h>
@@ -200,7 +201,7 @@ Glib::RefPtr<CanvasItemMovable> CanvasLayoutItem::create_canvas_item_for_layout_
 
     apply_formatting(canvas_item, text);
 
-    canvas_item->set_text(text->get_text());
+    canvas_item->set_text(text->get_text(Application::get_current_locale()));
     child = canvas_item;
     child_item = canvas_item;
   }
diff --git a/glom/print_layout/print_layout_utils.cc b/glom/print_layout/print_layout_utils.cc
index 869e8b7..fd0c317 100644
--- a/glom/print_layout/print_layout_utils.cc
+++ b/glom/print_layout/print_layout_utils.cc
@@ -21,6 +21,7 @@
 #include <glom/print_layout/print_layout_utils.h>
 #include <glom/print_layout/canvas_print_layout.h>
 #include <glom/print_layout/printoperation_printlayout.h>
+#include <glom/application.h>
 #include <iostream>
 
 namespace Glom
@@ -183,11 +184,11 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
 
   //Show the group's title
   //(but do not fall back to the name, because unnamed groups are really wanted sometimes.)
-  const Glib::ustring title = layout_group->get_title();
+  const Glib::ustring title = layout_group->get_title(Application::get_current_locale());
   if(!title.empty())
   {
     sharedptr<LayoutItem_Text> text = sharedptr<LayoutItem_Text>::create();
-    text->set_text(title);
+    text->set_text(title, Application::get_current_locale());
     text->m_formatting.set_text_format_font("Sans Bold 10");
 
     if(avoid_page_margins)
@@ -247,7 +248,8 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
       if(field)
       {
         text_title = sharedptr<LayoutItem_Text>::create();
-        text_title->set_text(field->get_title_or_name() + ":");
+        const Glib::ustring field_title = field->get_title_or_name(Application::get_current_locale());
+        text_title->set_text(field_title + ":", Application::get_current_locale());
         
         if(avoid_page_margins)
           y = move_fully_to_page(page_setup, units, y, field_height);
@@ -327,11 +329,11 @@ sharedptr<PrintLayout> create_standard(const Glib::RefPtr<const Gtk::PageSetup>&
     x += GRID_GAP;
   
   //The table title:
-  const Glib::ustring title = document->get_table_title_singular(table_name);
+  const Glib::ustring title = document->get_table_title_singular(table_name, Application::get_current_locale());
   if(!title.empty())
   {
     sharedptr<LayoutItem_Text> text = sharedptr<LayoutItem_Text>::create();
-    text->set_text(title);
+    text->set_text(title, Application::get_current_locale());
     text->m_formatting.set_text_format_font("Sans Bold 12");
 
     const double field_height = ITEM_HEIGHT;
diff --git a/glom/utility_widgets/dialog_flowtable.cc b/glom/utility_widgets/dialog_flowtable.cc
index 3351749..a6ce402 100644
--- a/glom/utility_widgets/dialog_flowtable.cc
+++ b/glom/utility_widgets/dialog_flowtable.cc
@@ -20,6 +20,7 @@
 
 
 #include "dialog_flowtable.h"
+#include <glom/application.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -56,7 +57,7 @@ void Dialog_FlowTable::set_flowtable(FlowTableWithFields* flowtable)
 {
   m_flowtable = flowtable;
   m_layoutgroup = sharedptr<LayoutGroup>::cast_dynamic(flowtable->get_layout_item());
-  m_entry_title->set_text(m_layoutgroup->get_title());
+  m_entry_title->set_text(m_layoutgroup->get_title(Application::get_current_locale()));
   m_spin_columns->set_value(m_layoutgroup->get_columns_count());
 }
 
diff --git a/glom/utility_widgets/dialog_flowtable.h b/glom/utility_widgets/dialog_flowtable.h
index 0af0630..44421d3 100644
--- a/glom/utility_widgets/dialog_flowtable.h
+++ b/glom/utility_widgets/dialog_flowtable.h
@@ -31,6 +31,7 @@
 namespace Glom
 {
 
+//TODO: Is this used?
 class Dialog_FlowTable
  : public Gtk::Dialog,
    public Base_DB //Give this class access to the current document, and to some utility methods.
@@ -45,8 +46,8 @@ public:
 
   void set_flowtable(FlowTableWithFields* flowtable);
   
-  gint get_columns_count();
-  Glib::ustring get_title();
+  gint get_columns_count(); //TODO: Make const?
+  Glib::ustring get_title(); //TODO: Isn't this the same as Widget::get_title()?
     
 private:
   Gtk::Entry* m_entry_title;
diff --git a/glom/utility_widgets/notebooklabelglom.cc b/glom/utility_widgets/notebooklabelglom.cc
index 8421ba2..3c45ae4 100644
--- a/glom/utility_widgets/notebooklabelglom.cc
+++ b/glom/utility_widgets/notebooklabelglom.cc
@@ -72,7 +72,7 @@ Application* NotebookLabel::get_application()
 void NotebookLabel::on_menu_new_group_activate()
 {
   sharedptr<LayoutGroup> group(new LayoutGroup());
-  group->set_title(_("New Group"));
+  group->set_title_original(_("New Group"));
   group->set_name(_("Group"));
   
   sharedptr<LayoutGroup> notebook_group = sharedptr<LayoutGroup>::cast_dynamic (m_notebook->get_layout_item());
@@ -84,10 +84,11 @@ void NotebookLabel::on_menu_new_group_activate()
 void NotebookLabel::on_menu_delete_activate()
 {
   Glib::ustring message;
-  if(!m_notebook->get_layout_item()->get_title().empty())
+  const Glib::ustring notebook_title = m_notebook->get_layout_item()->get_title(Application::get_current_locale());
+  if(!notebook_title.empty())
   {
     message = Glib::ustring::compose (_("Delete whole notebook \"%1\"?"),
-                                      m_notebook->get_layout_item()->get_title());
+                                      notebook_title);
   }
   else
   {
diff --git a/glom/utils_ui.cc b/glom/utils_ui.cc
index b279e73..f9dae03 100644
--- a/glom/utils_ui.cc
+++ b/glom/utils_ui.cc
@@ -21,6 +21,7 @@
 #include "config.h" // For GLOM_ENABLE_CLIENT_ONLY
 
 #include <glom/utils_ui.h>
+#include <glom/application.h>
 #include <libglom/connectionpool.h>
 #include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
 #include <libglom/data_structure/glomconversions.h>
@@ -364,7 +365,7 @@ int Utils::get_suitable_field_width_for_widget(Gtk::Widget& widget, const shared
   if(or_title)
   {
     //Make sure that there's enough space for the title too.
-    const int title_width = get_width_for_text(widget, field_layout->get_title());
+    const int title_width = get_width_for_text(widget, field_layout->get_title(Application::get_current_locale()));
     if(title_width > result)
       result = title_width;
   }
diff --git a/tests/test_document_change.cc b/tests/test_document_change.cc
index 982048e..467d863 100644
--- a/tests/test_document_change.cc
+++ b/tests/test_document_change.cc
@@ -86,8 +86,8 @@ int main()
   table_info->set_name(table_name);
   
   const Glib::ustring table_title = "sometabletitle";
-  table_info->set_title(table_title);
-  g_assert(table_info->get_title() == table_title);  
+  table_info->set_title_original(table_title);
+  g_assert(table_info->get_title_original() == table_title);  
   document.add_table(table_info);
 
   const float x = 20.0f;
diff --git a/tests/test_document_load.cc b/tests/test_document_load.cc
index 2b9dda9..3862e2a 100644
--- a/tests/test_document_load.cc
+++ b/tests/test_document_load.cc
@@ -174,8 +174,8 @@ int main()
 
   Glom::sharedptr<Glom::TableInfo> table = document.get_table("scenes");
   g_assert(table);
-  g_assert( table->get_title() == "Scenes" );
-  g_assert( table->get_title_singular() == "Scene" );
+  g_assert( table->get_title_original() == "Scenes" );
+  g_assert( table->get_title_singular_original() == "Scene" );
 
   //Test known fields of one table:
   const Glom::Document::type_vec_fields fields = document.get_table_fields("scenes");
@@ -193,12 +193,12 @@ int main()
   //Check some fields:
   Glom::sharedptr<const Glom::Field> field = document.get_field("contacts", "contact_id");
   g_assert(field);
-  g_assert( field->get_title() == "Contact ID" );
+  g_assert( field->get_title_original() == "Contact ID" );
   g_assert(field->get_glom_type() == Glom::Field::TYPE_NUMERIC);
   g_assert(field->get_auto_increment());
   field = document.get_field("locations", "rent");
   g_assert(field);
-  g_assert( field->get_title() == "Rent" );
+  g_assert( field->get_title_original() == "Rent" );
   g_assert(field->get_glom_type() == Glom::Field::TYPE_NUMERIC);
   g_assert(!field->get_auto_increment());
   g_assert(!field->get_unique_key());
@@ -293,7 +293,7 @@ int main()
     return false;
   }
   
-  if(print_layout->get_title() != "Contact Details")
+  if(print_layout->get_title_original() != "Contact Details")
   {
     std::cerr << "Failure: Unexpected print layout title." << std::endl;
     return false;
@@ -327,7 +327,7 @@ int main()
     return false;
   }
   
-  if(report->get_title() != "By Country, By Town")
+  if(report->get_title_original() != "By Country, By Town")
   {
     std::cerr << "Failure: Unexpected report title." << std::endl;
     return false;
diff --git a/tests/test_document_load_translations.cc b/tests/test_document_load_translations.cc
index 8a320d9..5c8aa3c 100644
--- a/tests/test_document_load_translations.cc
+++ b/tests/test_document_load_translations.cc
@@ -58,12 +58,12 @@ public:
 
   bool operator() (const Glom::sharedptr<T_Element>& element)
   {
-    return (element->get_title() == m_title);
+    return (element->get_title_original() == m_title);
   }
 
   bool operator() (const Glom::sharedptr<const T_Element>& element)
   {
-    return (element->get_title() == m_title);
+    return (element->get_title_original() == m_title);
   }
 
 private:
@@ -162,37 +162,28 @@ void check_title(const T_Item& item, const char* title_en, const char* title_de)
 {
   g_assert(item);
 
-  g_assert( item->get_title() == title_en );
-
-  //Check when changing the current locale:
-  const Glib::ustring locale_original = Glom::TranslatableItem::get_current_locale();
-  Glom::TranslatableItem::set_current_locale(locale_de);
-  g_assert( item->get_title() == title_de );
-  Glom::TranslatableItem::set_current_locale(locale_original);
+  g_assert( item->get_title_original() == title_en );
+  g_assert( item->get_title(Glib::ustring()) == title_en );
+  g_assert( item->get_title("en_US") == title_en );
 
+  g_assert( item->get_title_translation(locale_de) == title_de );
+  g_assert( item->get_title(locale_de) == title_de );
 
-  //Don't do the following checks if get_title() would actually delegate to the 
-  //child Field, instead of using the LayoutItem's own title translations:
-  const Glom::sharedptr<const Glom::LayoutItem_Field> layout_field = 
-     Glom::sharedptr<const Glom::LayoutItem_Field>::cast_dynamic(item);
-  if(layout_field)
-  {
-    return;
-  }
+  g_assert( item->get_title_or_name_original() == title_en );
+  g_assert( item->get_title_or_name(Glib::ustring()) == title_en );
+  g_assert( item->get_title_or_name("en_US") == title_en );
+  g_assert( item->get_title_or_name(locale_de) == title_de );
 
-  //Check when getting the translations directly:
-  g_assert( item->get_title_original() == title_en );
-  g_assert( item->get_title_translation(locale_de) == title_de );
 
   //Check fallbacks:
   g_assert( item->get_title_translation(Glib::ustring()) == title_en );
-  g_assert( item->get_title_translation(locale_original) == title_en );
+  g_assert( item->get_title_translation("en_US") == title_en );
   g_assert( item->get_title_translation("en_GB") == title_en );
   g_assert( item->get_title_translation("de_AU") == title_de );
 
   //Check that fallbacks do not happen when we don't want them:
   g_assert( item->get_title_translation(Glib::ustring(), false) == Glib::ustring() );
-  g_assert( item->get_title_translation(locale_original, false) == Glib::ustring() );
+  g_assert( item->get_title_translation("en_US", false) == Glib::ustring() );
   g_assert( item->get_title_translation("en_GB", false) == Glib::ustring() );
   g_assert( item->get_title_translation("de_AU", false) == Glib::ustring() );
 }
@@ -245,14 +236,11 @@ int main()
   const std::vector<Glib::ustring> table_names = document.get_table_names();
   g_assert(contains(table_names, "scenes"));
 
-  g_assert( document.get_table_title("scenes") == "Scenes" );
-  g_assert( document.get_table_title_singular("scenes") == "Scene" );
+  g_assert( document.get_table_title_original("scenes") == "Scenes" );
+  g_assert( document.get_table_title_singular_original("scenes") == "Scene" );
   
-  const Glib::ustring locale_original = Glom::TranslatableItem::get_current_locale();
-  Glom::TranslatableItem::set_current_locale(locale_de);
-  g_assert( document.get_table_title("scenes") == "Szenen" );
-  g_assert( document.get_table_title_singular("scenes") == "Szene" ); //TODO: Make this is translated correctly.
-  Glom::TranslatableItem::set_current_locale(locale_original);
+  g_assert( document.get_table_title("scenes", locale_de) == "Szenen" );
+  g_assert( document.get_table_title_singular("scenes", locale_de) == "Szene" ); //TODO: Make sure this is translated correctly.
 
   //Check a field:
   Glom::sharedptr<const Glom::Field> field = document.get_field("contacts", "contact_id");
@@ -273,13 +261,11 @@ int main()
   check_title(value, "Day", "Tag");
   g_assert(value->get_value() == Gnome::Gda::Value("Day"));
 
-  Glom::TranslatableItem::set_current_locale(locale_de);
   g_assert( value->get_title_original() == "Day" );
-  g_assert( formatting.get_custom_choice_original_for_translated_text("Nacht") == "Night" );
-  g_assert( formatting.get_custom_choice_original_for_translated_text("aaaa") == "" );
-  g_assert( formatting.get_custom_choice_translated("Night") == "Nacht" );
-  g_assert( formatting.get_custom_choice_translated("aaaa") == "" );
-  Glom::TranslatableItem::set_current_locale(locale_original);
+  g_assert( formatting.get_custom_choice_original_for_translated_text("Nacht", locale_de) == "Night" );
+  g_assert( formatting.get_custom_choice_original_for_translated_text("aaaa", locale_de) == "" );
+  g_assert( formatting.get_custom_choice_translated("Night", locale_de) == "Nacht" );
+  g_assert( formatting.get_custom_choice_translated("aaaa", locale_de) == "" );
   g_assert( value->get_title_original() == "Day" );
 
   //Check a relationship:
@@ -287,11 +273,18 @@ int main()
   g_assert(relationship);
   check_title(relationship, "Actor", "Schauspieler");
 
+  //Check a LayoutItemField's CustomTitle:
   Glom::sharedptr<const Glom::LayoutItem_Field> field_on_layout = 
     get_field_on_layout(document, "characters", "contacts", "name_full");
   g_assert(field_on_layout);
   check_title(field_on_layout, "Actor's Name", "Schauspieler Name" );
 
+  //Check a LayoutItemField's Field title:
+  field_on_layout = 
+    get_field_on_layout(document, "scenes", "locations", "name");
+  g_assert(field_on_layout);
+  check_title(field_on_layout, "Name", "Name" );
+
   field_on_layout = 
     get_field_on_layout(document, "scenes", "scenes", "day_or_night");
   g_assert(field_on_layout);
diff --git a/tests/test_selfhosting_new_then_report.cc b/tests/test_selfhosting_new_then_report.cc
index 805d4ca..1c5ded1 100644
--- a/tests/test_selfhosting_new_then_report.cc
+++ b/tests/test_selfhosting_new_then_report.cc
@@ -42,7 +42,9 @@ static bool test(Glom::Document::HostingMode hosting_mode)
 
   Glom::FoundSet found_set; //TODO: Test a where clause.
   found_set.m_table_name = "albums";
-  Glom::ReportBuilder report_builder;
+
+  const Glib::ustring locale = "";  /* original locale */
+  Glom::ReportBuilder report_builder(locale);
   report_builder.set_document(&document);
   const Glib::ustring html = 
     report_builder.report_build(found_set, report_temp);
diff --git a/tests/translations_po/test_document_import_po.cc b/tests/translations_po/test_document_import_po.cc
index 8c22b1f..3312d70 100644
--- a/tests/translations_po/test_document_import_po.cc
+++ b/tests/translations_po/test_document_import_po.cc
@@ -102,7 +102,7 @@ int main()
   //Check that some expected translated titles are now in the document:
   Glom::sharedptr<const Glom::TableInfo> table = document.get_table("scenes");
   g_assert(table);
-  g_assert( table->get_title() == "Scenes" ); //The original title should be unchanged:
+  g_assert( table->get_title_original() == "Scenes" ); //The original title should be unchanged:
 
   //This should have a new translated title:
   if(table->get_title_translation(locale) != "TestResult1")
@@ -113,7 +113,7 @@ int main()
 
   const Glom::sharedptr<const Glom::Report> report = document.get_report("crew", "crew_list");
   g_assert(report);
-  g_assert(report->get_title() == "Crew List"); //The original title should be unchanged:
+  g_assert(report->get_title_original() == "Crew List"); //The original title should be unchanged:
 
   //This should have a new translated title:
   if(report->get_title_translation(locale) != "TestResult2")



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]