From a22763298abf96f3555ef4939848fc5ffe7f6ea2 Mon Sep 17 00:00:00 2001
From: Eric House <xwords@eehouse.org>
Date: Thu, 10 Apr 2014 21:34:08 -0700
Subject: [PATCH] extend AlertDialog.Builder and override setTitle so string
 ids can be translated when passed.

---
 .../eehouse/android/xw4/BoardDelegate.java    | 22 ++++++++++---------
 .../eehouse/android/xw4/DictsDelegate.java    |  5 +++--
 .../org/eehouse/android/xw4/DlgDelegate.java  | 13 ++++++-----
 .../eehouse/android/xw4/FirstRunDialog.java   |  4 +++-
 .../org/eehouse/android/xw4/GameConfig.java   |  9 ++++----
 .../android/xw4/GamesListDelegate.java        | 15 +++++++------
 .../org/eehouse/android/xw4/LookupAlert.java  |  2 +-
 .../org/eehouse/android/xw4/MultiService.java |  4 +++-
 .../src/org/eehouse/android/xw4/NFCUtils.java |  4 +++-
 .../eehouse/android/xw4/NewGameActivity.java  |  2 +-
 .../eehouse/android/xw4/PrefsActivity.java    |  6 +++--
 .../android/xw4/SMSCheckBoxPreference.java    |  2 +-
 .../org/eehouse/android/xw4/loc/LocUtils.java | 18 +++++++++++++++
 13 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java
index 594d05708..437fa7d28 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java
@@ -63,6 +63,7 @@ import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
 import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
 import org.eehouse.android.xw4.jni.JNIThread.*;
 import org.eehouse.android.xw4.loc.LocUtils;
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
 
 public class BoardDelegate extends DelegateBase
     implements TransportProcs.TPMsgHandler, View.OnClickListener,
@@ -299,7 +300,7 @@ public class BoardDelegate extends DelegateBase
                             }
                         }
                     };
-                dialog = new AlertDialog.Builder( m_activity )
+                dialog = new AlertBuilder( m_activity )
                     .setTitle( m_dlgTitle )
                     .setMessage( m_dlgBytes )
                     .setPositiveButton( R.string.button_yes, lstnr )
@@ -309,7 +310,7 @@ public class BoardDelegate extends DelegateBase
                 break;
 
             case DLG_DELETED:
-                ab = new AlertDialog.Builder( m_activity )
+                ab = new AlertBuilder( m_activity )
                     .setTitle( R.string.query_title )
                     .setMessage( R.string.msg_dev_deleted )
                     .setPositiveButton( R.string.button_ok, null );
@@ -330,7 +331,7 @@ public class BoardDelegate extends DelegateBase
             case QUERY_INFORM_BLK:
             case DLG_SCORES:
             case DLG_BADWORDS_BLK: 
-                ab = new AlertDialog.Builder( m_activity )
+                ab = new AlertBuilder( m_activity )
                     .setMessage( m_dlgBytes );
                 if ( 0 != m_dlgTitle ) {
                     ab.setTitle( m_dlgTitle );
@@ -387,7 +388,7 @@ public class BoardDelegate extends DelegateBase
 
             case PICK_TILE_REQUESTBLANK_BLK:
             case PICK_TILE_REQUESTTRAY_BLK:
-                ab = new AlertDialog.Builder( m_activity );
+                ab = new AlertBuilder( m_activity );
                 lstnr = new DialogInterface.OnClickListener() {
                         public void onClick( DialogInterface dialog, 
                                              int item ) {
@@ -433,7 +434,7 @@ public class BoardDelegate extends DelegateBase
                     setupPasswdVars();
                 }
                 m_passwdEdit.setText( "", TextView.BufferType.EDITABLE );
-                ab = new AlertDialog.Builder( m_activity )
+                ab = new AlertBuilder( m_activity )
                     .setTitle( m_dlgTitleStr )
                     .setView( m_passwdLyt )
                     .setPositiveButton( R.string.button_ok,
@@ -449,7 +450,7 @@ public class BoardDelegate extends DelegateBase
                 break;
 
             case QUERY_ENDGAME:
-                dialog = new AlertDialog.Builder( m_activity )
+                dialog = new AlertBuilder( m_activity )
                     .setTitle( R.string.query_title )
                     .setMessage( R.string.ids_endnow )
                     .setPositiveButton( R.string.button_yes,
@@ -472,7 +473,7 @@ public class BoardDelegate extends DelegateBase
                                 showInviteChoicesThen( Action.LAUNCH_INVITE_ACTION );
                             }
                         };
-                    dialog = new AlertDialog.Builder( m_activity )
+                    dialog = new AlertBuilder( m_activity )
                         .setTitle( R.string.query_title )
                         .setMessage( "" )
                         .setPositiveButton( R.string.button_yes, lstnr )
@@ -696,7 +697,7 @@ public class BoardDelegate extends DelegateBase
                 strId = R.string.board_menu_tray_show;
             }
             item = menu.findItem( R.id.board_menu_tray );
-            item.setTitle( strId );
+            item.setTitle( LocUtils.getString( m_activity, strId ) );
 
             Utils.setItemVisible( menu, R.id.board_menu_flip, 
                                   m_gsi.visTileCount >= 1 );
@@ -739,12 +740,13 @@ public class BoardDelegate extends DelegateBase
                 } else {
                     strId = R.string.board_menu_done;
                 }
-                item.setTitle( strId );
+                item.setTitle( LocUtils.getString( m_activity, strId ) );
             }
             if ( m_gameOver || DBUtils.gameOver( m_activity, m_rowid ) ) {
                 m_gameOver = true;
                 item = menu.findItem( R.id.board_menu_game_resign );
-                item.setTitle( R.string.board_menu_game_final );
+                item.setTitle( LocUtils.getString( m_activity, 
+                                                   R.string.board_menu_game_final ) );
             }
         }
 
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java
index 9272d3d18..f313d81d6 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java
@@ -61,6 +61,7 @@ import org.eehouse.android.xw4.jni.JNIUtilsImpl;
 import org.eehouse.android.xw4.jni.GameSummary;
 import org.eehouse.android.xw4.DictUtils.DictLoc;
 import org.eehouse.android.xw4.loc.LocUtils;
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
 
 public class DictsDelegate extends DelegateBase 
     implements View.OnClickListener, AdapterView.OnItemLongClickListener,
@@ -311,7 +312,7 @@ public class DictsDelegate extends DelegateBase
             String lang = DictLangCache.getLangName( m_activity, name);
             message = m_activity.getString( R.string.set_default_message_fmt,
                                             name, lang );
-            dialog = new AlertDialog.Builder( m_activity )
+            dialog = new LocUtils.AlertBuilder( m_activity )
                 .setTitle( R.string.query_title )
                 .setMessage( message )
                 .setPositiveButton( R.string.button_default_human, lstnr )
@@ -716,7 +717,7 @@ public class DictsDelegate extends DelegateBase
     {
         int nSels = m_selDicts.size();
         if ( 0 < nSels ) {
-            m_activity.setTitle( m_activity.getString( R.string.sel_items_fmt, 
+            m_activity.setTitle( LocUtils.getString( m_activity, R.string.sel_items_fmt, 
                                                        nSels ) );
         } else {
             m_activity.setTitle( m_origTitle );
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java
index ac1c94d40..347e34a11 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java
@@ -38,6 +38,7 @@ import java.util.Iterator;
 import junit.framework.Assert;
 
 import org.eehouse.android.xw4.loc.LocUtils;
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
 
 public class DlgDelegate {
 
@@ -419,7 +420,7 @@ public class DlgDelegate {
             xlator.setVisibility( View.GONE );
         }
 
-        return new AlertDialog.Builder( m_activity )
+        return new AlertBuilder( m_activity )
             .setIcon( R.drawable.icon48x48 )
             .setTitle( R.string.app_name )
             .setView( view )
@@ -445,7 +446,7 @@ public class DlgDelegate {
 
     private Dialog createOKDialog( DlgState state, DlgID dlgID )
     {
-        Dialog dialog = new AlertDialog.Builder( m_activity )
+        Dialog dialog = new AlertBuilder( m_activity )
             .setTitle( R.string.info_title )
             .setMessage( state.m_msg )
             .setPositiveButton( R.string.button_ok, null )
@@ -473,7 +474,7 @@ public class DlgDelegate {
                 }
             };
 
-        Dialog dialog = new AlertDialog.Builder( m_activity )
+        Dialog dialog = new AlertBuilder( m_activity )
             .setTitle( R.string.newbie_title )
             .setMessage( state.m_msg )
             .setPositiveButton( R.string.button_ok, lstnr_p )
@@ -487,7 +488,7 @@ public class DlgDelegate {
     {
         OnClickListener lstnr = mkCallbackClickListener( state );
 
-        Dialog dialog = new AlertDialog.Builder( m_activity )
+        Dialog dialog = new AlertBuilder( m_activity )
             .setTitle( R.string.query_title )
             .setMessage( state.m_msg )
             .setPositiveButton( state.m_posButton, lstnr )
@@ -512,7 +513,7 @@ public class DlgDelegate {
             msgID = R.string.nfc_or_email;
         }
         
-        AlertDialog.Builder builder = new AlertDialog.Builder( m_activity )
+        AlertDialog.Builder builder = new AlertBuilder( m_activity )
             .setTitle( R.string.query_title )
             .setMessage( msgID )
             .setNegativeButton( R.string.button_html, lstnr );
@@ -529,7 +530,7 @@ public class DlgDelegate {
 
     private Dialog createDictGoneDialog()
     {
-        Dialog dialog = new AlertDialog.Builder( m_activity )
+        Dialog dialog = new AlertBuilder( m_activity )
             .setTitle( R.string.no_dict_title )
             .setMessage( R.string.no_dict_finish )
             .setPositiveButton( R.string.button_close_game, null )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/FirstRunDialog.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/FirstRunDialog.java
index d4992d426..721439ff4 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/FirstRunDialog.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/FirstRunDialog.java
@@ -29,6 +29,8 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
+
 /* Put up a dialog greeting user after every upgrade.  Based on
  * similar feature in OpenSudoku, to whose author "Thanks".
  */
@@ -87,7 +89,7 @@ public class FirstRunDialog {
 
         view.loadData( page, "text/html", "utf-8" );
 
-        AlertDialog dialog = new AlertDialog.Builder( context )
+        AlertDialog dialog = new AlertBuilder( context )
             .setIcon(android.R.drawable.ic_menu_info_details)
             .setTitle( R.string.changes_title )
             .setView( view )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java
index 84282f876..2805f6eb8 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java
@@ -58,6 +58,7 @@ import org.eehouse.android.xw4.jni.*;
 import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
 import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
 import org.eehouse.android.xw4.loc.LocUtils;
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
 
 public class GameConfig extends XWActivity 
     implements View.OnClickListener
@@ -162,7 +163,7 @@ public class GameConfig extends XWActivity
                 View playerEditView = 
                     LocUtils.inflate( this, R.layout.player_edit );
 
-                dialog = new AlertDialog.Builder( this )
+                dialog = new AlertBuilder( this )
                     .setTitle(R.string.player_edit_title)
                     .setView(playerEditView)
                     .setPositiveButton( R.string.button_ok,
@@ -202,7 +203,7 @@ public class GameConfig extends XWActivity
                             loadPlayersList();
                         }
                     };
-                dialog = new AlertDialog.Builder( this )
+                dialog = new AlertBuilder( this )
                     .setTitle( R.string.force_title )
                     .setView( LocUtils.inflate( this, layoutForDlg(dlgID) ) )
                     .setPositiveButton( R.string.button_ok, dlpos )
@@ -232,7 +233,7 @@ public class GameConfig extends XWActivity
                             }
                         }
                     };
-                ab = new AlertDialog.Builder( this )
+                ab = new AlertBuilder( this )
                     .setTitle( R.string.confirm_save_title )
                     .setMessage( R.string.confirm_save )
                     .setPositiveButton( R.string.button_save, dlpos );
@@ -260,7 +261,7 @@ public class GameConfig extends XWActivity
                 String msg = getString( R.string.no_name_found_fmt,
                                         m_gi.nPlayers, DictLangCache.
                                         getLangName( this, m_gi.dictLang ) );
-                dialog = new AlertDialog.Builder( this )
+                dialog = new AlertBuilder( this )
                     .setPositiveButton( R.string.button_ok, null )
                     // message added below since varies with language etc.
                     .setMessage( msg )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesListDelegate.java
index 4eed34589..751295124 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesListDelegate.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesListDelegate.java
@@ -59,6 +59,7 @@ import junit.framework.Assert;
 import org.eehouse.android.xw4.DlgDelegate.Action;
 import org.eehouse.android.xw4.jni.*;
 import org.eehouse.android.xw4.loc.LocUtils;
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
 
 public class GamesListDelegate extends DelegateBase
     implements OnItemLongClickListener,
@@ -173,7 +174,7 @@ public class GamesListDelegate extends DelegateBase
                                                 langName );
             }
 
-            ab = new AlertDialog.Builder( m_activity )
+            ab = new AlertBuilder( m_activity )
                 .setTitle( R.string.no_dict_title )
                 .setMessage( message )
                 .setPositiveButton( R.string.button_cancel, null )
@@ -208,7 +209,7 @@ public class GamesListDelegate extends DelegateBase
                         }
                     }
                 };
-            dialog = new AlertDialog.Builder( m_activity )
+            dialog = new AlertBuilder( m_activity )
                 .setTitle( R.string.subst_dict_title )
                 .setPositiveButton( R.string.button_substdict, lstnr )
                 .setNegativeButton( R.string.button_cancel, null )
@@ -298,8 +299,8 @@ public class GamesListDelegate extends DelegateBase
                 };
             String[] groups = m_adapter.groupNames();
             int curGroupPos = m_adapter.getGroupPosition( startGroup );
-            dialog = new AlertDialog.Builder( m_activity )
-                .setTitle( m_activity.getString( R.string.change_group ) )
+            dialog = new AlertBuilder( m_activity )
+                .setTitle( R.string.change_group )
                 .setSingleChoiceItems( groups, curGroupPos, lstnr )
                 .setPositiveButton( R.string.button_move, lstnr2 )
                 .setNegativeButton( R.string.button_cancel, null )
@@ -314,7 +315,7 @@ public class GamesListDelegate extends DelegateBase
                 (EditText)layout.findViewById( R.id.name_edit );
             etext.setText( CommonPrefs.getDefaultPlayerName( m_activity,
                                                              0, true ) );
-            dialog = new AlertDialog.Builder( m_activity )
+            dialog = new AlertBuilder( m_activity )
                 .setTitle( R.string.default_name_title )
                 .setMessage( R.string.default_name_message )
                 .setPositiveButton( R.string.button_ok, null )
@@ -927,7 +928,7 @@ public class GamesListDelegate extends DelegateBase
         if ( 0 == fmt ) {
             m_activity.setTitle( m_origTitle );
         } else {
-            m_activity.setTitle( m_activity.getString( fmt, nSels ) );
+            m_activity.setTitle( LocUtils.getString( m_activity, fmt, nSels ) );
         }
     }
 
@@ -1162,7 +1163,7 @@ public class GamesListDelegate extends DelegateBase
             LocUtils.inflate( m_activity, R.layout.rename_game );
         m_namer.setName( curname );
         m_namer.setLabel( labelID );
-        Dialog dialog = new AlertDialog.Builder( m_activity )
+        Dialog dialog = new AlertBuilder( m_activity )
             .setTitle( titleID )
             .setNegativeButton( R.string.button_cancel, null )
             .setPositiveButton( R.string.button_ok, lstnr )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/LookupAlert.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/LookupAlert.java
index f302bef79..2782dc26c 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/LookupAlert.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/LookupAlert.java
@@ -359,7 +359,7 @@ public class LookupAlert extends LinearLayout
             LocUtils.inflate( parent, R.layout.lookup );
         view.init( parent, bundle );
 
-        Dialog result = new AlertDialog.Builder( parent )
+        Dialog result = new LocUtils.AlertBuilder( parent )
             .setTitle( R.string.lookup_title )
             .setView( view )
             .create();
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiService.java
index 11a3f36de..92831194e 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiService.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiService.java
@@ -26,6 +26,8 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.DialogInterface.OnClickListener;
 
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
+
 public class MultiService {
 
     public static final String LANG = "LANG";
@@ -139,7 +141,7 @@ public class MultiService {
             : R.string.invite_dict_missing_body_fmt;
         String msg = context.getString( msgID, inviter, dict, langStr );
 
-        return new AlertDialog.Builder( context )
+        return new AlertBuilder( context )
             .setTitle( R.string.invite_dict_missing_title )
             .setMessage( msg)
             .setPositiveButton( R.string.button_download, onDownload )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NFCUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NFCUtils.java
index 78e625b81..7c65bf39d 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NFCUtils.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NFCUtils.java
@@ -36,6 +36,8 @@ import android.os.Parcelable;
 
 import junit.framework.Assert;
 
+import org.eehouse.android.xw4.loc.LocUtils.AlertBuilder;
+
 public class NFCUtils {
 
     public interface NFCActor {
@@ -133,7 +135,7 @@ public class NFCUtils {
                                                       + ".NFC_SETTINGS" ) );
                     }
                 };
-        return new AlertDialog.Builder( activity )
+        return new AlertBuilder( activity )
             .setTitle( R.string.info_title )
             .setMessage( R.string.enable_nfc )
             .setPositiveButton( R.string.button_cancel, null )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java
index 844579389..4d976421e 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java
@@ -243,7 +243,7 @@ public class NewGameActivity extends XWActivity {
                         }
                     };
 
-                dialog = new AlertDialog.Builder( this )
+                dialog = new LocUtils.AlertBuilder( this )
                     .setTitle( m_nameForBT ? R.string.game_btname_title 
                                : R.string.game_smsname_title )
                     .setNegativeButton( R.string.button_cancel, null )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/PrefsActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/PrefsActivity.java
index cdd329bdf..a696d72c5 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/PrefsActivity.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/PrefsActivity.java
@@ -33,6 +33,8 @@ import android.view.View;
 import android.widget.Button;
 import java.io.File;
 
+import org.eehouse.android.xw4.loc.LocUtils;
+
 public class PrefsActivity extends PreferenceActivity 
     implements SharedPreferences.OnSharedPreferenceChangeListener {
 
@@ -100,7 +102,7 @@ public class PrefsActivity extends PreferenceActivity
             dialog = SMSCheckBoxPreference.onCreateDialog( this, id );
             break;
         case EXPLAIN_TITLE:
-            dialog = new AlertDialog.Builder( this )
+            dialog = new LocUtils.AlertBuilder( this )
                 .setMessage( R.string.no_hide_titlebar )
                 .setTitle( R.string.info_title )
                 .setPositiveButton( R.string.button_ok, null )
@@ -109,7 +111,7 @@ public class PrefsActivity extends PreferenceActivity
         }
 
         if ( null == dialog && null != lstnr ) {
-            dialog = new AlertDialog.Builder( this )
+            dialog = new LocUtils.AlertBuilder( this )
                 .setTitle( R.string.query_title )
                 .setMessage( confirmID )
                 .setPositiveButton( R.string.button_ok, lstnr )
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSCheckBoxPreference.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSCheckBoxPreference.java
index fe219f672..6f794720c 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSCheckBoxPreference.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSCheckBoxPreference.java
@@ -87,7 +87,7 @@ public class SMSCheckBoxPreference extends CheckBoxPreference {
                 }
             };
 
-        AlertDialog.Builder ab = new AlertDialog.Builder( activity )
+        AlertDialog.Builder ab = new LocUtils.AlertBuilder( activity )
             .setTitle( R.string.confirm_sms_title )
             .setView( layout )
             .setNegativeButton( R.string.button_ok, lstnr );
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/loc/LocUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/loc/LocUtils.java
index 87ba2c39a..ad8acb370 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/loc/LocUtils.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/loc/LocUtils.java
@@ -20,6 +20,7 @@
 package org.eehouse.android.xw4.loc;
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.content.Context;
 import android.content.Intent;
 import android.util.AttributeSet;
@@ -318,4 +319,21 @@ public class LocUtils {
         }
         return sb.toString();
     }
+
+    public static class AlertBuilder extends AlertDialog.Builder {
+        Context m_context;
+
+        public AlertBuilder( Context context )
+        {
+            super( context );
+            m_context = context;
+        }
+
+        @Override
+        public AlertDialog.Builder setTitle( int id )
+        {
+            String str = getString( m_context, id );
+            return setTitle( str );
+        }
+    }
 }