r4567: Get ATK headers through Zero Install.
[rox-filer/translations.git] / ROX-Filer / src / i18n.c
blobdabe85689ce453c36f59a9e08546a4d740d08359
1 /*
2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
27 #include "global.h"
29 #include "support.h"
30 #include "choices.h"
31 #include "options.h"
32 #include "i18n.h"
33 #include "gui_support.h"
34 #include "main.h"
36 #define MESSAGE _("Note that you must save your choices " \
37 "and restart the filer for the new language " \
38 "setting to take full effect.")
40 /* Two/five-char country_territory code, or NULL */
41 char *current_lang = NULL;
43 static Option o_translation;
45 static GtkWidget *i18n_message = NULL;
47 /* Static Prototypes */
48 static void set_trans(const guchar *lang);
49 static void trans_changed(void);
50 static GList *build_i18n_message(Option *option, xmlNode *node, guchar *label);
52 /****************************************************************
53 * EXTERNAL INTERFACE *
54 ****************************************************************/
57 /* Set things up for internationalisation */
58 void i18n_init(void)
60 gtk_set_locale();
62 option_add_string(&o_translation, "i18n_translation", "From LANG");
63 set_trans(o_translation.value);
64 o_translation.has_changed = FALSE; /* Prevent warning about saving */
66 option_add_notify(trans_changed);
68 option_register_widget("i18n-message", build_i18n_message);
71 /* These two stolen from dia :-).
72 * Slight modification though: '>' means 'same as above' so that
73 * if a translation is missing it doesn't muck up the whole menu structure!
75 GtkItemFactoryEntry *translate_entries(GtkItemFactoryEntry *entries, gint n)
77 guchar *first = NULL, *second = NULL; /* Previous menu, submenu */
78 gint i;
79 GtkItemFactoryEntry *ret;
81 ret = g_malloc(sizeof(GtkItemFactoryEntry) * n);
82 for (i = 0; i < n; i++)
84 const gchar *from = entries[i].path;
85 gchar *trans, *slash;
86 int indent;
88 if (from[0] == '>')
90 if (from[1] == '>')
91 indent = 2;
92 else
93 indent = 1;
95 else
96 indent = 0;
98 if (from[indent])
99 from = _(from + indent);
100 else
101 from = "";
103 if (indent == 0)
104 trans = g_strdup_printf("/%s", from);
105 else if (indent == 1)
106 trans = g_strdup_printf("/%s/%s", first, from);
107 else
108 trans = g_strdup_printf("/%s/%s/%s",
109 first, second, from);
111 ret[i].path = trans;
113 g_free(first);
114 null_g_free(&second);
116 trans++;
117 slash = strchr(trans, '/');
118 if (slash)
120 first = g_strndup(trans, slash - trans);
121 trans = slash + 1;
123 slash = strchr(trans, '/');
124 if (slash)
125 second = g_strndup(trans, slash - trans);
126 else
127 second = g_strdup(trans);
129 else
130 first = g_strdup(trans);
132 /* accelerator and item_type are not duped, only referenced */
133 ret[i].accelerator = entries[i].accelerator;
134 ret[i].callback = entries[i].callback;
135 ret[i].callback_action = entries[i].callback_action;
136 ret[i].item_type = entries[i].item_type;
137 ret[i].extra_data = entries[i].extra_data;
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(const guchar *lang)
176 guchar *path;
177 gchar *lang2;
179 g_return_if_fail(lang != NULL);
181 rox_clear_translation();
183 null_g_free(&current_lang);
185 if (strcmp(lang, "None") == 0)
186 return;
187 else if (strcmp(lang, "From LANG") == 0)
189 const guchar *end;
191 lang = getenv("LANG");
192 if (!lang)
193 return;
194 /* Extract the language code from the locale name.
195 * language[_territory][.codeset][@modifier]
198 end = strchr(lang, '.');
199 if (!end)
200 end = strchr(lang, '@');
201 if (end)
202 lang2 = g_strndup(lang, end - lang);
203 else
204 lang2 = g_strdup(lang);
206 else
207 lang2 = g_strdup(lang);
209 current_lang = lang2;
211 path = g_strdup_printf("%s/Messages/%s.gmo", app_dir, current_lang);
212 if (!file_exists(path) && strchr(current_lang, '_'))
214 /* Try again without the territory */
215 strcpy(strrchr(path, '_'), ".gmo");
218 if (file_exists(path))
219 rox_add_translations(path);
220 g_free(path);
223 static GList *build_i18n_message(Option *option, xmlNode *node, guchar *label)
225 GtkWidget *hbox, *image, *align;
227 g_return_val_if_fail(option == NULL, NULL);
228 g_return_val_if_fail(label == NULL, NULL);
229 g_return_val_if_fail(i18n_message == NULL, NULL);
231 i18n_message = gtk_label_new(MESSAGE);
232 g_signal_connect(i18n_message, "destroy",
233 G_CALLBACK(gtk_widget_destroyed), &i18n_message);
235 gtk_misc_set_alignment(GTK_MISC(i18n_message), 0, 0.5);
236 gtk_label_set_justify(GTK_LABEL(i18n_message), GTK_JUSTIFY_LEFT);
237 gtk_label_set_line_wrap(GTK_LABEL(i18n_message), TRUE);
239 hbox = gtk_hbox_new(FALSE, 4);
240 image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,
241 GTK_ICON_SIZE_BUTTON);
242 align = gtk_alignment_new(0, 0, 0, 0);
244 gtk_container_add(GTK_CONTAINER(align), image);
245 gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, TRUE, 0);
246 gtk_box_pack_start(GTK_BOX(hbox), i18n_message, FALSE, TRUE, 0);
248 return g_list_append(NULL, hbox);