Complete.Org: Mailing Lists: Archives: freeciv-dev: August 1999:
[Freeciv-Dev] patch: i18n of data/Freeciv (PR#117)
Home

[Freeciv-Dev] patch: i18n of data/Freeciv (PR#117)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] patch: i18n of data/Freeciv (PR#117)
From: David Pfitzner <dwp@xxxxxxxxxxxxxx>
Date: Sun, 29 Aug 1999 04:42:09 -0700 (PDT)

This patch demonstrates a way to do i18n on translatable strings 
in the data/Freeciv resources file, which is basically necessary 
for effective i18n of the Xaw client.  The method has two parts:

1. Strings in data/Freeciv as marked as usual (eg _("foo")).
This means X sees the strings with the marking _inside_ the 
string.

2. When a widget using a marked resource is created, check to 
see if the resource string has those markings inside the string,
and if so, remove the marking, pass string to gettext, and re-set 
the widget resource to the gettext result.

As an example this patch marks strings and code for the Xaw 
connection dialog.  I haven't added translations because I don't 
know any :-)  (I did try it with fake test "translations" and it 
worked ok, although one may still get visual imperfections (in 
widget layout etc) due to different word lengths in different 
languages etc.)  Works with resources compiled-in, or external.

As one may infer from above, marking strings with this method 
has two steps: 
- find and mark translatable strings in data/Freeciv;
- find where widgets using those strings are created in the 
code, and call appropriate functions/macros for those widgets 
to convert the appropriate resources.  Thdise second step
is _necessary_ or else the user will see the string markings!

Appropriate resources appear to be: .label, .title, .iconName

I found that xgettext (at least GNU xgettext) will handle strings
which go over several lines, iff the newlines are escaped with '\'
(eg, used in this patch for the beta notice).  I'm not sure if this
may be useful for the registry multi-line string i18n issue...

Regards,
-- David
diff -u -r --exclude-from exclude freeciv-cvs/client/gui-xaw/Freeciv.h 
fc-adv/client/gui-xaw/Freeciv.h
--- freeciv-cvs/client/gui-xaw/Freeciv.h        Sat Aug 28 17:03:45 1999
+++ fc-adv/client/gui-xaw/Freeciv.h     Sun Aug 29 03:26:45 1999
@@ -31,39 +31,39 @@
 "Freeciv*Pixcomm.foreground: Black",
 "Freeciv*Pixcomm.background: White",
 "Freeciv*Pixcomm.shadowWidth: 0",
-"Freeciv*.connectdialog.title: Connect to FreeCiv Server",
-"Freeciv*connectdialog.*.cheadline.label: Freeciv Server Selection",
+"Freeciv*.connectdialog.title: _(\"Connect to FreeCiv Server\")",
+"Freeciv*connectdialog.*.cheadline.label: _(\"Freeciv Server Selection\")",
 "Freeciv*connectdialog.*.cheadline.width: 300",
-"Freeciv*connectdialog.*.cnamel.label: Name",
+"Freeciv*connectdialog.*.cnamel.label: _(\"Name\")",
 "Freeciv*connectdialog.*.cnamel.fromVert: cheadline",
 "Freeciv*connectdialog.*.cnamei.fromVert: cheadline",
 "Freeciv*connectdialog.*.cnamei.fromHoriz: cnamel",
 "Freeciv*connectdialog.*.cnamei.*.editType: edit",
 "Freeciv*connectdialog.*.cnamei.width: 256",
-"Freeciv*connectdialog.*.chostl.label: Host",
+"Freeciv*connectdialog.*.chostl.label: _(\"Host\")",
 "Freeciv*connectdialog.*.chostl.fromVert: cnamel",
 "Freeciv*connectdialog.*.chosti.fromVert: cnamel",
 "Freeciv*connectdialog.*.chosti.fromHoriz: chostl",
 "Freeciv*connectdialog.*.chosti.*.editType: edit",
 "Freeciv*connectdialog.*.chosti.width: 256",
-"Freeciv*connectdialog.*.cportl.label: Port",
+"Freeciv*connectdialog.*.cportl.label: _(\"Port\")",
 "Freeciv*connectdialog.*.cportl.fromVert: chostl",
 "Freeciv*connectdialog.*.cporti.fromVert: chostl",
 "Freeciv*connectdialog.*.cporti.fromHoriz: cportl",
 "Freeciv*connectdialog.*.cporti.*.editType: edit",
 "Freeciv*connectdialog.*.cporti.width: 256",
-"Freeciv*connectdialog.*.cconnectc.label: Connect",
+"Freeciv*connectdialog.*.cconnectc.label: _(\"Connect\")",
 "Freeciv*connectdialog.*.cconnectc.fromVert: cportl",
-"Freeciv*connectdialog.*.cmetac.label: Metaserver",
+"Freeciv*connectdialog.*.cmetac.label: _(\"Metaserver\")",
 "Freeciv*connectdialog.*.cmetac.fromVert: cportl",
 "Freeciv*connectdialog.*.cmetac.fromHoriz: cconnectc",
-"Freeciv*connectdialog.*.cquitc.label: Quit",
+"Freeciv*connectdialog.*.cquitc.label: _(\"Quit\")",
 "Freeciv*connectdialog.*.cquitc.fromVert: cportl",
 "Freeciv*connectdialog.*.cquitc.fromHoriz: cmetac",
-"Freeciv*connectdialog.*.cbetaline.label: \
+"Freeciv*connectdialog.*.cbetaline.label: _(\"\
 THIS IS A BETA RELEASE\\n\
 Freeciv 1.8 will be released third\\n\
-week of March at http://www.freeciv.org";,
+week of March at http://www.freeciv.org\";)",
 "Freeciv*connectdialog.*.cbetaline.fromVert: cconnectc",
 "Freeciv*connectdialog.*.cbetaline.justify: left",
 "Freeciv*connectdialog.*.cbetaline.background: grey",
diff -u -r --exclude-from exclude freeciv-cvs/client/gui-xaw/connectdlg.c 
fc-adv/client/gui-xaw/connectdlg.c
--- freeciv-cvs/client/gui-xaw/connectdlg.c     Sat Aug 28 17:03:45 1999
+++ fc-adv/client/gui-xaw/connectdlg.c  Sun Aug 29 03:39:08 1999
@@ -91,40 +91,41 @@
 
 void gui_server_connect(void)
 {
-  Widget shell, form, label, label2;
+  Widget shell, form;
   char buf[512];
   
   XtTranslations textfieldtranslations;
   
   XtSetSensitive(toplevel, FALSE);
   
-  shell=XtCreatePopupShell("connectdialog", transientShellWidgetClass,
-                          toplevel, NULL, 0);
+  I_T(shell=XtCreatePopupShell("connectdialog", transientShellWidgetClass,
+                              toplevel, NULL, 0));
   
   form=XtVaCreateManagedWidget("cform", formWidgetClass, shell, NULL);
 
-  label=XtVaCreateManagedWidget("cheadline", labelWidgetClass, form, NULL);   
+  I_LW(XtVaCreateManagedWidget("cheadline", labelWidgetClass, form, NULL));
 
-  XtVaCreateManagedWidget("cnamel", labelWidgetClass, form, NULL);   
+  I_L(XtVaCreateManagedWidget("cnamel", labelWidgetClass, form, NULL));
   iname=XtVaCreateManagedWidget("cnamei", asciiTextWidgetClass, form, 
                          XtNstring, name, NULL);
 
-  XtVaCreateManagedWidget("chostl", labelWidgetClass, form, NULL);   
+  I_L(XtVaCreateManagedWidget("chostl", labelWidgetClass, form, NULL));
   ihost=XtVaCreateManagedWidget("chosti", asciiTextWidgetClass, form, 
                          XtNstring, server_host, NULL);
 
   sprintf(buf, "%d", server_port);
   
-  XtVaCreateManagedWidget("cportl", labelWidgetClass, form, NULL);   
+  I_L(XtVaCreateManagedWidget("cportl", labelWidgetClass, form, NULL));
   iport=XtVaCreateManagedWidget("cporti", asciiTextWidgetClass, form, 
                          XtNstring, buf, NULL);
 
-  connw=XtVaCreateManagedWidget("cconnectc", commandWidgetClass, form, NULL);  
 
-  metaw=XtVaCreateManagedWidget("cmetac", commandWidgetClass, form, NULL);
-  quitw=XtVaCreateManagedWidget("cquitc", commandWidgetClass, form, NULL); 
+  I_L(connw=XtVaCreateManagedWidget("cconnectc", commandWidgetClass,
+                                   form, NULL));
+  I_L(metaw=XtVaCreateManagedWidget("cmetac", commandWidgetClass, form, NULL));
+  I_L(quitw=XtVaCreateManagedWidget("cquitc", commandWidgetClass, form, NULL));
 
   if (IS_BETA_VERSION)
-    label2=XtVaCreateManagedWidget("cbetaline", labelWidgetClass, form, NULL);
+    I_LW(XtVaCreateManagedWidget("cbetaline", labelWidgetClass, form, NULL));
 
   XtAddCallback(connw, XtNcallback, connect_callback, NULL);
   XtAddCallback(quitw, XtNcallback, quit_callback, NULL);
diff -u -r --exclude-from exclude freeciv-cvs/client/gui-xaw/gui_stuff.c 
fc-adv/client/gui-xaw/gui_stuff.c
--- freeciv-cvs/client/gui-xaw/gui_stuff.c      Sat Jun 12 17:40:07 1999
+++ fc-adv/client/gui-xaw/gui_stuff.c   Sun Aug 29 03:31:59 1999
@@ -10,14 +10,22 @@
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 ***********************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #include <X11/Intrinsic.h>
 #include <X11/IntrinsicP.h>
 #include <X11/StringDefs.h>
+#include <X11/Shell.h>
 #include <X11/Xaw/Form.h>
 
+#include "astring.h"
+#include "fcintl.h"
 #include "mem.h"
 
 #include "gui_stuff.h"
@@ -235,3 +243,108 @@
     *pdst++=*(psrc+4*xoffset_table[x]+3);
   }
 }
+
+
+/**************************************************************************
+  Returns 1 if string has gettext markings _inside_ string
+  (marking must be strictly at ends of string).
+**************************************************************************/
+static int has_intl_marking(const char *str)
+{
+  int len;
+  
+  if (!(str[0] == '_' && str[1] == '(' && str[2] == '\"'))
+    return 0;
+  
+  len = strlen(str);
+
+  return (len >= 5 && str[len-2] == '\"' && str[len-1] == ')');
+}
+
+/**************************************************************************
+  For a string which _has_ intl marking (caller should check beforehand)
+  returns gettext result of string inside marking.
+  Below buf is an internal buffer which is never free'd.
+**************************************************************************/
+static const char *convert_intl_marking(const char *str)
+{
+  static struct astring buf = ASTRING_INIT;
+  int len = strlen(str);
+
+  assert(len>=5);
+  astr_minsize(&buf, len-2);   /* +1 nul, -3 start */
+  strcpy(buf.str, str+3);
+  buf.str[len-5] = '\0';
+
+  return _(buf.str);
+}
+
+/**************************************************************************
+  Check if the current widget label has i18n/gettext markings
+  _inside_ the string (for full string only).  If so, then
+  strip off those markings, pass to gettext, and re-set label
+  to gettext-returned string.  Note this is intended for resources
+  which are specified in data/Freeciv; if the label is set via
+  code, it should be gettext'd via code before/when set.
+  Note all this is necessary even if not using gettext, to
+  remove the gettext markings!
+  Returns the same widget (eg, to nest calls of this and following funcs).
+**************************************************************************/
+Widget xaw_intl_label(Widget w)
+{
+  String str;
+
+  XtVaGetValues(w, XtNlabel, &str, NULL);
+
+  if (has_intl_marking(str))
+    XtVaSetValues(w, XtNlabel, (XtArgVal)convert_intl_marking(str), NULL);
+  return w;
+}
+
+/**************************************************************************
+  As above, but also making sure to preserve the widget width.
+  Should probably use this version rather than above
+  when data/Freeciv specifies the width.
+**************************************************************************/
+Widget xaw_intl_label_width(Widget w)
+{
+  String str;
+  Dimension width;
+
+  XtVaGetValues(w, XtNlabel, &str, XtNwidth, &width, NULL);
+
+  if (has_intl_marking(str)) {
+    XtVaSetValues(w, XtNlabel, (XtArgVal)convert_intl_marking(str),
+                 XtNwidth, width, NULL);
+  }
+  return w;
+}
+
+/**************************************************************************
+  As above, for widget title.
+**************************************************************************/
+Widget xaw_intl_title(Widget w)
+{
+  String str;
+
+  XtVaGetValues(w, XtNtitle, &str, NULL);
+
+  if (has_intl_marking(str))
+    XtVaSetValues(w, XtNtitle, (XtArgVal)convert_intl_marking(str), NULL);
+  return w;
+}
+
+/**************************************************************************
+  As above, for widget icon name.
+**************************************************************************/
+Widget xaw_intl_icon_name(Widget w)
+{
+  String str;
+
+  XtVaGetValues(w, XtNiconName, &str, NULL);
+
+  if (has_intl_marking(str))
+    XtVaSetValues(w, XtNiconName, (XtArgVal)convert_intl_marking(str), NULL);
+  return w;
+}
+
diff -u -r --exclude-from exclude freeciv-cvs/client/gui-xaw/gui_stuff.h 
fc-adv/client/gui-xaw/gui_stuff.h
--- freeciv-cvs/client/gui-xaw/gui_stuff.h      Sat Jun 12 17:40:07 1999
+++ fc-adv/client/gui-xaw/gui_stuff.h   Sun Aug 29 03:27:38 1999
@@ -24,4 +24,14 @@
 Pixmap x_scale_pixmap(Pixmap src, int src_w, int src_h, int dst_w, int dst_h, 
                      Window root);
 
+Widget xaw_intl_label(Widget w);
+Widget xaw_intl_label_width(Widget w);
+Widget xaw_intl_title(Widget w);
+Widget xaw_intl_icon_name(Widget w);
+
+#define I_L(w)  xaw_intl_label(w)
+#define I_LW(w) xaw_intl_label_width(w)
+#define I_T(w)  xaw_intl_title(w)
+#define I_IN(w) xaw_intl_icon_name(w)
+
 #endif  /* FC__GUI_STUFF_H */
diff -u -r --exclude-from exclude freeciv-cvs/data/Freeciv fc-adv/data/Freeciv
--- freeciv-cvs/data/Freeciv    Sat Aug 28 17:03:46 1999
+++ fc-adv/data/Freeciv Sun Aug 29 03:26:45 1999
@@ -55,12 +55,12 @@
 !
 ! The Connect dialog
 !
-Freeciv*.connectdialog.title: Connect to FreeCiv Server
+Freeciv*.connectdialog.title: _("Connect to FreeCiv Server")
 
-Freeciv*connectdialog.*.cheadline.label: Freeciv Server Selection
+Freeciv*connectdialog.*.cheadline.label: _("Freeciv Server Selection")
 Freeciv*connectdialog.*.cheadline.width: 300
 
-Freeciv*connectdialog.*.cnamel.label: Name
+Freeciv*connectdialog.*.cnamel.label: _("Name")
 Freeciv*connectdialog.*.cnamel.fromVert: cheadline
 
 Freeciv*connectdialog.*.cnamei.fromVert: cheadline
@@ -68,7 +68,7 @@
 Freeciv*connectdialog.*.cnamei.*.editType: edit
 Freeciv*connectdialog.*.cnamei.width: 256
 
-Freeciv*connectdialog.*.chostl.label: Host
+Freeciv*connectdialog.*.chostl.label: _("Host")
 Freeciv*connectdialog.*.chostl.fromVert: cnamel
 
 Freeciv*connectdialog.*.chosti.fromVert: cnamel
@@ -76,7 +76,7 @@
 Freeciv*connectdialog.*.chosti.*.editType: edit
 Freeciv*connectdialog.*.chosti.width: 256
 
-Freeciv*connectdialog.*.cportl.label: Port
+Freeciv*connectdialog.*.cportl.label: _("Port")
 Freeciv*connectdialog.*.cportl.fromVert: chostl
 
 Freeciv*connectdialog.*.cporti.fromVert: chostl
@@ -84,21 +84,21 @@
 Freeciv*connectdialog.*.cporti.*.editType: edit
 Freeciv*connectdialog.*.cporti.width: 256
 
-Freeciv*connectdialog.*.cconnectc.label: Connect
+Freeciv*connectdialog.*.cconnectc.label: _("Connect")
 Freeciv*connectdialog.*.cconnectc.fromVert: cportl
 
-Freeciv*connectdialog.*.cmetac.label: Metaserver
+Freeciv*connectdialog.*.cmetac.label: _("Metaserver")
 Freeciv*connectdialog.*.cmetac.fromVert: cportl
 Freeciv*connectdialog.*.cmetac.fromHoriz: cconnectc
 
-Freeciv*connectdialog.*.cquitc.label: Quit
+Freeciv*connectdialog.*.cquitc.label: _("Quit")
 Freeciv*connectdialog.*.cquitc.fromVert: cportl
 Freeciv*connectdialog.*.cquitc.fromHoriz: cmetac
 
-Freeciv*connectdialog.*.cbetaline.label: \
+Freeciv*connectdialog.*.cbetaline.label: _("\
 THIS IS A BETA RELEASE\n\
 Freeciv 1.8 will be released third\n\
-week of March at http://www.freeciv.org
+week of March at http://www.freeciv.org";)
 Freeciv*connectdialog.*.cbetaline.fromVert: cconnectc
 Freeciv*connectdialog.*.cbetaline.justify: left
 Freeciv*connectdialog.*.cbetaline.background: grey
diff -u -r --exclude-from exclude freeciv-cvs/po/POTFILES.in 
fc-adv/po/POTFILES.in
--- freeciv-cvs/po/POTFILES.in  Thu Jul 29 00:27:08 1999
+++ fc-adv/po/POTFILES.in       Sun Aug 29 03:26:45 1999
@@ -2,3 +2,4 @@
 # (Filenames relative to toplevel dir.)
 server/civserver.c
 client/civclient.c
+data/Freeciv

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] patch: i18n of data/Freeciv (PR#117), David Pfitzner <=