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

Language selection: cdebconf and main-menu



[sorry for Cc'ing, but i need your opinion/comments on this]

Hi,

now that cdebconf has support for l10n'ed templates, it is time to play
with language selection.
The LANGUAGE environment variable is used by cdebconf to display translated
strings, and cdebconf is used to choose language and then set LANGUAGE.
Moreover the language selection fit well in a main-menu item, so here
is a proposed solution:
  * By convention, decide that language selection is item 1.
  * Add a languagechooser package, which will perform this first step.
    (It does not yet allow multi-selection, will do later)
  * In main-menu, when item 1 is processed, setenv LANGUAGE in main loop
    so that further operations will use it.  Also inform debconf backend
    about this change, via a new X_SET_LANGUAGE command, so that LANGUAGE
    is also updated on this part.
  * In cdebconf, implement this new X_SET_LANGUAGE command.
Note that the language list is hardcoded in main-menu/language.c and not
in languagechooser/debian/{postinst,templates}.  In fact, as language
selection is driven by main-menu, I suggest not to add the languagechooser
package and instead add its template under main-menu wings.

Looks tricky, but I did not find a simpler solution.

Denis
Index: main-menu/main-menu.c
===================================================================
RCS file: /cvs/debian-boot/debian-installer/main-menu/main-menu.c,v
retrieving revision 1.43
diff -u -r1.43 main-menu.c
--- main-menu/main-menu.c	25 Nov 2002 16:46:06 -0000	1.43
+++ main-menu/main-menu.c	26 Nov 2002 00:02:15 -0000
@@ -15,6 +15,7 @@
  */
 
 #include "main-menu.h"
+#include "language.h"
 #include <cdebconf/debconfclient.h>
 #include <stdlib.h>
 #include <search.h>
@@ -391,14 +392,35 @@
 int main (int argc, char **argv) {
 	struct package_t *p, *packages;
 	
+	struct debconfclient *debconf;
+	const char *lang;
+	const char *langchoices;
+
 	/* Tell udpkg to shut up. */
 	setenv("UDPKG_QUIET", "y", 1);
-	
+
+	debconf = debconfclient_new();
+	langchoices = get_language_choices();
+	debconf->command(debconf, "SUBST", "debian-installer/language",
+			"CHOICES", langchoices, NULL);
 	packages = status_read();
 	while ((p=show_main_menu(packages))) {
 		do_menu_item(p);
-		packages = status_read();
-	}
+		if (p->installer_menu_item == 1) {
+			/*
+			 *  By convention, language selection is the
+			 *  first step;  the LANGUAGE environment
+			 *  variable must be updated
+			 */
+			lang = get_debconf_language(debconf);
+			/*  Also handle the case where lang is NULL  */
+			setenv("LANGUAGE", lang, 1);
+			/*  debconf backends must also be updated  */
+			debconf->command(debconf, "X_SET_LANGUAGE", lang, NULL);
+		}
+ 		packages = status_read();
+ 	}
+	debconfclient_delete(debconf);
 	
 	return(0);
 }
--- /dev/null	2002-07-08 00:06:55.000000000 +0200
+++ main-menu/language.c	2002-11-26 00:31:36.000000000 +0100
@@ -0,0 +1,72 @@
+/*
+ * Debian Installer main menu program.
+ *
+ * Copyright 2000  Joey Hess <joeyh@debian.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "main-menu.h"
+#include "language.h"
+#include <cdebconf/debconfclient.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _(x)  (x)
+
+static struct language_item language_list[] = {
+	{ _("Brazilian"), "pt_BR" },
+	{ _("English"), "en" },
+	{ _("French"), "fr" },
+	{ _("German"), "de" },
+	{ _("Swedish"), "sv" },
+	{ NULL, NULL }
+};
+
+const char *get_debconf_language(struct debconfclient *debconf) {
+	struct language_item *l;
+
+	debconf->command(debconf, "GET", "debian-installer/language", NULL);
+	if (*debconf->value != 0)
+        {
+	        for (l=language_list; l->lang != NULL; l++)
+			if (strcmp(debconf->value, l->lang) == 0)
+				return l->code;
+	}
+	return NULL;
+}
+
+char *get_language_choices(void)
+{
+	struct language_item *l;
+	char *out;
+	int length = 1;
+	static char *cache_language_choices = NULL;
+
+	if (cache_language_choices != NULL)
+		return cache_language_choices;
+
+	for (l=language_list; l->lang != NULL; l++)
+	{
+		/*   A comma and a space is added  */
+		length += strlen(l->lang) + 2;
+	}
+	out = (char *) malloc(length);
+	*out = '\0';
+	for (l=language_list; l->lang != NULL; l++)
+	{
+		strcat(out, l->lang);
+		strcat(out, ", ");
+	}
+	*(out + strlen(out) - 2) = '\0';
+	return out;
+}
+
--- /dev/null	2002-07-08 00:06:55.000000000 +0200
+++ main-menu/language.h	2002-11-26 00:28:43.000000000 +0100
@@ -0,0 +1,17 @@
+#ifndef _LANGUAGE_H_
+#define _LANGUAGE_H_
+
+#include "main-menu.h"
+#include <cdebconf/debconfclient.h>
+
+#define _(x)  (x)
+
+struct language_item {
+	const char *lang;
+	const char *code;
+};
+
+const char *get_debconf_language(struct debconfclient *);
+char *get_language_choices();
+
+#endif  /* _LANGUAGE_H_  */
Index: main-menu/debian/changelog
===================================================================
RCS file: /cvs/debian-boot/debian-installer/main-menu/debian/changelog,v
retrieving revision 1.39
diff -u -r1.39 changelog
--- main-menu/debian/changelog	25 Nov 2002 16:46:08 -0000	1.39
+++ main-menu/debian/changelog	26 Nov 2002 00:02:15 -0000
@@ -6,6 +6,11 @@
     - Don't run udpkg --configure on virtual packages
   * Denis Barbier
     - Replace "SUBST foo DEFAULT value" by "SET foo value"
+    - Add support for language selection.  Item 1 is by convention
+      language selection, and when it is called, the LANGUAGE environment
+      variable is updated and debconf backend is informed to this change
+      with the new X_SET_LANGUAGE command.  Currently LANGUAGE can only
+      contain a single value, not a colon separated list of languages.
   * Tollef Fog Heen
     - Don't use dpkg-reconfigure, use dpkg --force-configure --configure
       instead.
Index: cdebconf/src/commands.c
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/commands.c,v
retrieving revision 1.33
diff -u -r1.33 commands.c
--- cdebconf/src/commands.c	23 Nov 2002 22:29:42 -0000	1.33
+++ cdebconf/src/commands.c	26 Nov 2002 00:01:40 -0000
@@ -796,3 +796,25 @@
     snprintf(out, outsize, "%u OK", CMDSTATUS_SUCCESS);
     return DC_OK;
 }
+
+/*
+ * Function: command_x_set_language
+ * Input: struct confmodule *mod - confmodule object
+ *        int argc - number of arguments
+ *        char **argv - argument array
+ *        char *out - output buffer
+ *        size_t outsize - output buffer size
+ * Output: int - DC_NOTOK if error, DC_OK otherwise
+ * Description: handler for the X_LOADTEMPLATEFILE debconf command; 
+ *              loads a new template into the debconf database.  This is a
+ *              debian-installer extension.
+ * Assumptions: none
+ */
+int command_x_set_language(struct confmodule *mod, int argc, char **argv, 
+                               char *out, size_t outsize)
+{
+    CHECKARGC(== 1);
+    setlanguage(argv[1]);
+    snprintf(out, outsize, "%u OK", CMDSTATUS_SUCCESS);
+    return DC_OK;
+}
Index: cdebconf/src/commands.h
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/commands.h,v
retrieving revision 1.4
diff -u -r1.4 commands.h
--- cdebconf/src/commands.h	27 May 2002 14:23:05 -0000	1.4
+++ cdebconf/src/commands.h	26 Nov 2002 00:01:40 -0000
@@ -40,5 +40,6 @@
 int command_exist(struct confmodule *, int, char **, char *, size_t);
 int command_stop(struct confmodule *, int, char **, char *, size_t);
 int command_x_loadtemplatefile(struct confmodule *, int, char **, char *, size_t);
+int command_x_set_language(struct confmodule *, int, char **, char *, size_t);
 
 #endif
Index: cdebconf/src/confmodule.c
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/confmodule.c,v
retrieving revision 1.15
diff -u -r1.15 confmodule.c
--- cdebconf/src/confmodule.c	3 Nov 2002 19:59:11 -0000	1.15
+++ cdebconf/src/confmodule.c	26 Nov 2002 00:01:40 -0000
@@ -73,6 +73,7 @@
 	{ "exist",	command_exist },
 	{ "stop",	command_stop },
         { "x_loadtemplatefile", command_x_loadtemplatefile },
+	{ "x_set_language", command_x_set_language },
 	{ 0, 0 }
 };
 
Index: cdebconf/src/template.c
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/template.c,v
retrieving revision 1.16
diff -u -r1.16 template.c
--- cdebconf/src/template.c	22 Nov 2002 21:12:41 -0000	1.16
+++ cdebconf/src/template.c	26 Nov 2002 00:01:41 -0000
@@ -73,54 +73,55 @@
 static const char *getlanguage(void)
 {
 	const char *envlang = getenv("LANGUAGE");
-	struct cache_list_lang *p, *q;
-	char *cpb, *cpe;
 
 	if ((cache_cur_lang == NULL && envlang != NULL) ||
 	    (cache_cur_lang != NULL && envlang == NULL) ||
 	    (cache_cur_lang != NULL && envlang != NULL && strcmp(cache_cur_lang, envlang) != 0))
-	{
-		/*   LANGUAGE has changed, reset cache_cur_lang...  */
-		if (cache_cur_lang != NULL)
-			free(cache_cur_lang);
-		/*   ... and language linked list  */
-		for (p = cache_list_lang_ptr; p != NULL; p = p->next)
-		{
-			if (p->lang != NULL)
-				free(p->lang);
-			q = p->next;
-			free(p);
-			p = q;
-		}
-		cache_list_lang_ptr = NULL;
-		if (envlang == NULL)
-			return NULL;
-
-		cache_list_lang_ptr = (struct cache_list_lang *)
-			malloc(sizeof(struct cache_list_lang));
-		cache_list_lang_ptr->next = NULL;
-		cache_list_lang_ptr->lang = NULL;
-
-		p = cache_list_lang_ptr;
-		cache_cur_lang = strdup(envlang);
-		cpb = cache_cur_lang;
-		while((cpe = strchr(cpb, ':')) != NULL)
-		{
-			p->lang = strndup(cpb, (int) (cpe - cpb));
-			p->next = (struct cache_list_lang *)
-					malloc(sizeof(struct cache_list_lang));
-			cpb = cpe + 1;
-			p = p->next;
-		}
-		p->lang = strdup(cpb);
-		p->next = NULL;
-	}
+	    setlanguage(envlang);
 
 	/*  Return the first language  */
 	if (cache_list_lang_ptr == NULL)
 		return NULL;
 
 	return cache_list_lang_ptr->lang;
+}
+
+void setlanguage(const char *lang)
+{
+	struct cache_list_lang *p, *q;
+	char *cpb, *cpe;
+
+	DELETE(cache_cur_lang);
+	for (p = cache_list_lang_ptr; p != NULL; p = p->next)
+	{
+		DELETE(p->lang);
+		q = p->next;
+		free(p);
+		p = q;
+	}
+	cache_list_lang_ptr = NULL;
+	setenv("LANGUAGE", lang, 1);
+	if (lang == NULL)
+		return;
+
+	cache_list_lang_ptr = (struct cache_list_lang *)
+		malloc(sizeof(struct cache_list_lang));
+	cache_list_lang_ptr->next = NULL;
+	cache_list_lang_ptr->lang = NULL;
+
+	p = cache_list_lang_ptr;
+	cache_cur_lang = strdup(lang);
+	cpb = cache_cur_lang;
+	while((cpe = strchr(cpb, ':')) != NULL)
+	{
+		p->lang = strndup(cpb, (int) (cpe - cpb));
+		p->next = (struct cache_list_lang *)
+				malloc(sizeof(struct cache_list_lang));
+		cpb = cpe + 1;
+		p = p->next;
+	}
+	p->lang = strdup(cpb);
+	p->next = NULL;
 }
 
 /*
Index: cdebconf/src/template.h
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/template.h,v
retrieving revision 1.6
diff -u -r1.6 template.h
--- cdebconf/src/template.h	19 Nov 2002 23:18:44 -0000	1.6
+++ cdebconf/src/template.h	26 Nov 2002 00:01:41 -0000
@@ -33,6 +33,7 @@
 void template_deref(struct template *t);
 struct template *template_dup(struct template *t);
 struct template *template_load(const char *filename);
+void setlanguage(const char *lang);
 
 #endif
 
--- /dev/null	2002-07-08 00:06:55.000000000 +0200
+++ languagechooser/debian/control	2002-11-23 14:41:03.000000000 +0100
@@ -0,0 +1,12 @@
+Source: languagechooser
+Section: debian-installer
+Priority: standard
+Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
+Uploaders: Denis Barbier <barbier@debian.org>, Tollef Fog Heen <tfheen@debian.org>
+Build-Depends: debhelper (>= 4.1.16), po-debconf (>= 0.5.0)
+Standards-Version: 3.5.6.1
+
+Package: languagechooser
+Architecture: all
+XB-Installer-Menu-Item: 1
+Description: Select language
--- /dev/null	2002-07-08 00:06:55.000000000 +0200
+++ languagechooser/debian/templates	2002-11-24 00:35:55.000000000 +0100
@@ -0,0 +1,7 @@
+Template: debian-installer/language
+Type: select
+Choices: ${CHOICES}
+_Description: Which language to use when installing?
+ You can select the language in which installation process will go.  If
+ some informations are not translated into your language, English
+ version is displayed.
--- /dev/null	2002-07-08 00:06:55.000000000 +0200
+++ languagechooser/debian/postinst	2002-11-26 00:47:09.000000000 +0100
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+. /usr/share/debconf/confmodule
+
+db_input high debian-installer/language || true
+db_go || true
+

Reply to: