r1996: Cope slightly better with invalid filenames in various places (reported by
[rox-filer.git] / ROX-Filer / src / i18n.c
blob685ca090418a56a04903a4d21eae0ccd2c07a845
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2002, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
29 #include "global.h"
31 #include "support.h"
32 #include "choices.h"
33 #include "options.h"
34 #include "i18n.h"
35 #include "gui_support.h"
36 #include "main.h"
38 #define MESSAGE _("Note that you must save your choices " \
39 "and restart the filer for the new language " \
40 "setting to take full effect.")
42 char *current_lang = NULL; /* Two-char country code, or NULL */
44 static Option o_translation;
46 static GtkWidget *i18n_message = NULL;
48 /* Static Prototypes */
49 static void set_trans(guchar *lang);
50 static void trans_changed(void);
51 static GList *build_i18n_message(Option *option, xmlNode *node, guchar *label);
53 /****************************************************************
54 * EXTERNAL INTERFACE *
55 ****************************************************************/
58 /* Set things up for internationalisation */
59 void i18n_init(void)
61 gtk_set_locale();
63 option_add_string(&o_translation, "i18n_translation", "From LANG");
64 set_trans(o_translation.value);
65 o_translation.has_changed = FALSE; /* Prevent warning about saving */
67 option_add_notify(trans_changed);
69 option_register_widget("i18n-message", build_i18n_message);
72 /* These two stolen from dia :-).
73 * Slight modification though: '>' means 'same as above' so that
74 * if a translation is missing it doesn't muck up the whole menu structure!
76 GtkItemFactoryEntry *translate_entries(GtkItemFactoryEntry *entries, gint n)
78 guchar *first = NULL, *second = NULL; /* Previous menu, submenu */
79 gint i;
80 GtkItemFactoryEntry *ret;
82 ret = g_malloc(sizeof(GtkItemFactoryEntry) * n);
83 for (i = 0; i < n; i++)
85 const gchar *from = entries[i].path;
86 gchar *trans, *slash;
87 int indent;
89 if (from[0] == '>')
91 if (from[1] == '>')
92 indent = 2;
93 else
94 indent = 1;
96 else
97 indent = 0;
99 if (from[indent])
100 from = _(from + indent);
101 else
102 from = "";
104 if (indent == 0)
105 trans = g_strdup_printf("/%s", from);
106 else if (indent == 1)
107 trans = g_strdup_printf("/%s/%s", first, from);
108 else
109 trans = g_strdup_printf("/%s/%s/%s",
110 first, second, from);
112 ret[i].path = trans;
114 g_free(first);
115 null_g_free(&second);
117 trans++;
118 slash = strchr(trans, '/');
119 if (slash)
121 first = g_strndup(trans, slash - trans);
122 trans = slash + 1;
124 slash = strchr(trans, '/');
125 if (slash)
126 second = g_strndup(trans, slash - trans);
127 else
128 second = g_strdup(trans);
130 else
131 first = g_strdup(trans);
133 /* accelerator and item_type are not duped, only referenced */
134 ret[i].accelerator = entries[i].accelerator;
135 ret[i].callback = entries[i].callback;
136 ret[i].callback_action = entries[i].callback_action;
137 ret[i].item_type = entries[i].item_type;
140 g_free(first);
141 g_free(second);
143 return ret;
146 void free_translated_entries(GtkItemFactoryEntry *entries, gint n)
148 gint i;
150 for (i=0; i<n; i++)
151 g_free(entries[i].path);
152 g_free(entries);
156 /****************************************************************
157 * INTERNAL FUNCTIONS *
158 ****************************************************************/
160 static void trans_changed(void)
162 if (!o_translation.has_changed)
163 return;
165 set_trans(o_translation.value);
167 if (i18n_message)
168 gtk_label_set_text(GTK_LABEL(i18n_message), MESSAGE);
171 /* Load the 'Messages/<name>.gmo' translation.
172 * Special values 'None' and 'From LANG' are also allowed.
174 static void set_trans(guchar *lang)
176 struct stat info;
177 guchar *path;
178 gchar *lang2 = NULL;
180 g_return_if_fail(lang != NULL);
182 rox_clear_translation();
184 null_g_free(&current_lang);
186 if (strcmp(lang, "None") == 0)
187 return;
188 else if (strcmp(lang, "From LANG") == 0)
190 lang = getenv("LANG");
191 if (!lang)
192 return;
193 /* Extract the language code from the locale name.
194 * language[_territory][.codeset][@modifier]
196 if (lang[0] != '\0' && lang[1] != '\0'
197 && (lang[2] == '_' || lang[2] == '.' || lang[2] == '@'))
198 lang2 = g_strndup((gchar *) lang, 2);
201 current_lang = lang2 ? lang2 : g_strdup(lang);
203 path = g_strdup_printf("%s/Messages/%s.gmo", app_dir, current_lang);
204 if (stat(path, &info) == 0)
205 rox_add_translations(path);
206 g_free(path);
209 static GList *build_i18n_message(Option *option, xmlNode *node, guchar *label)
211 GtkWidget *hbox, *image, *align;
213 g_return_val_if_fail(option == NULL, NULL);
214 g_return_val_if_fail(label == NULL, NULL);
215 g_return_val_if_fail(i18n_message == NULL, NULL);
217 i18n_message = gtk_label_new(MESSAGE);
218 g_signal_connect(i18n_message, "destroy",
219 G_CALLBACK(gtk_widget_destroyed), &i18n_message);
221 gtk_misc_set_alignment(GTK_MISC(i18n_message), 0, 0.5);
222 gtk_label_set_justify(GTK_LABEL(i18n_message), GTK_JUSTIFY_LEFT);
223 gtk_label_set_line_wrap(GTK_LABEL(i18n_message), TRUE);
225 hbox = gtk_hbox_new(FALSE, 4);
226 image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,
227 GTK_ICON_SIZE_BUTTON);
228 align = gtk_alignment_new(0, 0, 0, 0);
230 gtk_container_add(GTK_CONTAINER(align), image);
231 gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, TRUE, 0);
232 gtk_box_pack_start(GTK_BOX(hbox), i18n_message, FALSE, TRUE, 0);
234 return g_list_append(NULL, hbox);