~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/gettext/gettext.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-09-13 18:02:04 UTC
  • mfrom: (1.17.15 upstream)
  • mto: (17.6.27 experimental)
  • mto: This revision was merged to the branch mainline in revision 145.
  • Revision ID: package-import@ubuntu.com-20120913180204-mojnmocbimlom4im
Tags: upstream-2.00
ImportĀ upstreamĀ versionĀ 2.00

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
18
 */
19
19
 
20
 
#include <grub/list.h>
21
20
#include <grub/types.h>
22
21
#include <grub/misc.h>
23
22
#include <grub/mm.h>
35
34
   http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html .
36
35
*/
37
36
 
38
 
 
39
 
static grub_file_t fd_mo;
40
 
 
41
 
static int grub_gettext_offsetoriginal;
42
 
static int grub_gettext_max;
 
37
static struct grub_gettext_context main_context, secondary_context;
43
38
 
44
39
static const char *(*grub_gettext_original) (const char *s);
45
40
 
46
41
struct grub_gettext_msg
47
42
{
48
 
  struct grub_gettext_msg *next;
49
 
  const char *name;
50
 
 
51
 
  const char *translated;
52
 
};
53
 
 
54
 
static struct grub_gettext_msg *grub_gettext_msg_list = NULL;
55
 
 
56
 
#define GETTEXT_MAGIC_NUMBER            0
57
 
#define GETTEXT_FILE_FORMAT             4
58
 
#define GETTEXT_NUMBER_OF_STRINGS       8
59
 
#define GETTEXT_OFFSET_ORIGINAL         12
60
 
#define GETTEXT_OFFSET_TRANSLATION      16
 
43
  char *name;
 
44
  char *translated;
 
45
};
 
46
 
 
47
struct header
 
48
{
 
49
  grub_uint32_t magic;
 
50
  grub_uint32_t version;
 
51
  grub_uint32_t number_of_strings;
 
52
  grub_uint32_t offset_original;
 
53
  grub_uint32_t offset_translation;
 
54
};
 
55
 
 
56
struct string_descriptor 
 
57
{
 
58
  grub_uint32_t length;
 
59
  grub_uint32_t offset;
 
60
};
 
61
 
 
62
struct grub_gettext_context
 
63
{
 
64
  grub_file_t fd_mo;
 
65
  grub_off_t grub_gettext_offset_original;
 
66
  grub_off_t grub_gettext_offset_translation;
 
67
  grub_size_t grub_gettext_max;
 
68
  int grub_gettext_max_log;
 
69
  struct grub_gettext_msg *grub_gettext_msg_list;
 
70
};
61
71
 
62
72
#define MO_MAGIC_NUMBER                 0x950412de
63
73
 
64
 
static grub_ssize_t
 
74
static grub_err_t
65
75
grub_gettext_pread (grub_file_t file, void *buf, grub_size_t len,
66
76
                    grub_off_t offset)
67
77
{
 
78
  if (len == 0)
 
79
    return GRUB_ERR_NONE;
68
80
  if (grub_file_seek (file, offset) == (grub_off_t) - 1)
 
81
    return grub_errno;
 
82
  if (grub_file_read (file, buf, len) != (grub_ssize_t) len)
69
83
    {
70
 
      return -1;
 
84
      if (!grub_errno)
 
85
        grub_error (GRUB_ERR_READ_ERROR, N_("premature end of file"));
 
86
      return grub_errno;
71
87
    }
72
 
  return grub_file_read (file, buf, len);
73
 
}
74
 
 
75
 
static grub_uint32_t
76
 
grub_gettext_get_info (int offset)
77
 
{
78
 
  grub_uint32_t value;
79
 
 
80
 
  grub_gettext_pread (fd_mo, (char *) &value, 4, offset);
81
 
 
82
 
  value = grub_cpu_to_le32 (value);
83
 
  return value;
84
 
}
85
 
 
86
 
static void
87
 
grub_gettext_getstring_from_offset (grub_uint32_t offset,
88
 
                                    grub_uint32_t length, char *translation)
89
 
{
90
 
  grub_gettext_pread (fd_mo, translation, length, offset);
91
 
  translation[length] = '\0';
92
 
}
93
 
 
94
 
static const char *
95
 
grub_gettext_gettranslation_from_position (int position)
96
 
{
97
 
  int offsettranslation;
98
 
  int internal_position;
99
 
  grub_uint32_t length, offset;
 
88
  return GRUB_ERR_NONE;
 
89
}
 
90
 
 
91
static char *
 
92
grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
 
93
                                   grub_off_t off,
 
94
                                   grub_size_t position)
 
95
{
 
96
  grub_off_t internal_position;
 
97
  grub_size_t length;
 
98
  grub_off_t offset;
100
99
  char *translation;
101
 
 
102
 
  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
103
 
 
104
 
  internal_position = offsettranslation + position * 8;
105
 
 
106
 
  grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position);
107
 
  length = grub_cpu_to_le32 (length);
108
 
 
109
 
  grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4);
110
 
  offset = grub_cpu_to_le32 (offset);
 
100
  struct string_descriptor desc;
 
101
  grub_err_t err;
 
102
 
 
103
  internal_position = (off + position * sizeof (desc));
 
104
 
 
105
  err = grub_gettext_pread (ctx->fd_mo, (char *) &desc,
 
106
                            sizeof (desc), internal_position);
 
107
  if (err)
 
108
    return NULL;
 
109
  length = grub_cpu_to_le32 (desc.length);
 
110
  offset = grub_cpu_to_le32 (desc.offset);
111
111
 
112
112
  translation = grub_malloc (length + 1);
113
 
  grub_gettext_getstring_from_offset (offset, length, translation);
 
113
  if (!translation)
 
114
    return NULL;
 
115
 
 
116
  err = grub_gettext_pread (ctx->fd_mo, translation, length, offset);
 
117
  if (err)
 
118
    {
 
119
      grub_free (translation);
 
120
      return NULL;
 
121
    }
 
122
  translation[length] = '\0';
114
123
 
115
124
  return translation;
116
125
}
117
126
 
118
 
static char *
119
 
grub_gettext_getstring_from_position (int position)
120
 
{
121
 
  int internal_position;
122
 
  int length, offset;
123
 
  char *original;
124
 
 
125
 
  /* Get position for string i.  */
126
 
  internal_position = grub_gettext_offsetoriginal + (position * 8);
127
 
 
128
 
  /* Get the length of the string i.  */
129
 
  grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position);
130
 
 
131
 
  /* Get the offset of the string i.  */
132
 
  grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4);
133
 
 
134
 
  /* Get the string i.  */
135
 
  original = grub_malloc (length + 1);
136
 
  grub_gettext_getstring_from_offset (offset, length, original);
137
 
 
138
 
  return original;
139
 
}
140
 
 
141
 
static const char *
142
 
grub_gettext_translate (const char *orig)
143
 
{
144
 
  char *current_string;
145
 
  const char *ret;
146
 
 
147
 
  int min, max, current;
148
 
  int found = 0;
149
 
 
150
 
  struct grub_gettext_msg *cur;
 
127
static const char *
 
128
grub_gettext_gettranslation_from_position (struct grub_gettext_context *ctx,
 
129
                                           grub_size_t position)
 
130
{
 
131
  if (!ctx->grub_gettext_msg_list[position].translated)
 
132
    ctx->grub_gettext_msg_list[position].translated
 
133
      = grub_gettext_getstr_from_position (ctx,
 
134
                                           ctx->grub_gettext_offset_translation,
 
135
                                           position);
 
136
  return ctx->grub_gettext_msg_list[position].translated;
 
137
}
 
138
 
 
139
static const char *
 
140
grub_gettext_getstring_from_position (struct grub_gettext_context *ctx,
 
141
                                      grub_size_t position)
 
142
{
 
143
  if (!ctx->grub_gettext_msg_list[position].name)
 
144
    ctx->grub_gettext_msg_list[position].name
 
145
      = grub_gettext_getstr_from_position (ctx,
 
146
                                           ctx->grub_gettext_offset_original,
 
147
                                           position);
 
148
  return ctx->grub_gettext_msg_list[position].name;
 
149
}
 
150
 
 
151
static const char *
 
152
grub_gettext_translate_real (struct grub_gettext_context *ctx,
 
153
                             const char *orig)
 
154
{
 
155
  grub_size_t current = 0;
 
156
  int i;
 
157
  const char *current_string;
 
158
  static int depth = 0;
 
159
 
 
160
  if (!ctx->grub_gettext_msg_list || !ctx->fd_mo)
 
161
    return NULL;
 
162
 
 
163
  /* Shouldn't happen. Just a precaution if our own code
 
164
     calls gettext somehow.  */
 
165
  if (depth > 2)
 
166
    return NULL;
 
167
  depth++;
151
168
 
152
169
  /* Make sure we can use grub_gettext_translate for error messages.  Push
153
170
     active error message to error stack and reset error message.  */
154
171
  grub_error_push ();
155
172
 
156
 
  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_gettext_msg_list),
157
 
                              orig);
158
 
 
159
 
  if (cur)
160
 
    {
161
 
      grub_error_pop ();
162
 
      return cur->translated;
163
 
    }
164
 
 
165
 
  if (fd_mo == 0)
166
 
    {
167
 
      grub_error_pop ();
168
 
      return orig;
169
 
    }
170
 
 
171
 
  min = 0;
172
 
  max = grub_gettext_max;
173
 
 
174
 
  current = (max + min) / 2;
175
 
 
176
 
  while (current != min && current != max && found == 0)
177
 
    {
178
 
      current_string = grub_gettext_getstring_from_position (current);
 
173
  for (i = ctx->grub_gettext_max_log; i >= 0; i--)
 
174
    {
 
175
      grub_size_t test;
 
176
      int cmp;
 
177
 
 
178
      test = current | (1 << i);
 
179
      if (test >= ctx->grub_gettext_max)
 
180
        continue;
 
181
 
 
182
      current_string = grub_gettext_getstring_from_position (ctx, test);
 
183
 
 
184
      if (!current_string)
 
185
        {
 
186
          grub_errno = GRUB_ERR_NONE;
 
187
          grub_error_pop ();
 
188
          depth--;
 
189
          return NULL;
 
190
        }
179
191
 
180
192
      /* Search by bisection.  */
181
 
      if (grub_strcmp (current_string, orig) < 0)
182
 
        {
183
 
          grub_free (current_string);
184
 
          min = current;
185
 
        }
186
 
      else if (grub_strcmp (current_string, orig) > 0)
187
 
        {
188
 
          grub_free (current_string);
189
 
          max = current;
190
 
        }
191
 
      else if (grub_strcmp (current_string, orig) == 0)
192
 
        {
193
 
          grub_free (current_string);
194
 
          found = 1;
195
 
        }
196
 
      current = (max + min) / 2;
 
193
      cmp = grub_strcmp (current_string, orig);
 
194
      if (cmp <= 0)
 
195
        current = test;
 
196
      if (cmp == 0)
 
197
        {
 
198
          const char *ret = 0;
 
199
          ret = grub_gettext_gettranslation_from_position (ctx, current);
 
200
          if (!ret)
 
201
            {
 
202
              grub_errno = GRUB_ERR_NONE;
 
203
              grub_error_pop ();
 
204
              depth--;
 
205
              return NULL;
 
206
            }
 
207
          grub_error_pop ();
 
208
          depth--;
 
209
          return ret;      
 
210
        }
197
211
    }
198
212
 
199
 
  ret = found ? grub_gettext_gettranslation_from_position (current) : orig;
200
 
 
201
 
  if (found)
 
213
  if (current == 0 && ctx->grub_gettext_max != 0)
202
214
    {
203
 
      cur = grub_zalloc (sizeof (*cur));
204
 
 
205
 
      if (cur)
206
 
        {
207
 
          cur->name = grub_strdup (orig);
208
 
          if (cur->name)
 
215
      current_string = grub_gettext_getstring_from_position (ctx, 0);
 
216
 
 
217
      if (!current_string)
 
218
        {
 
219
          grub_errno = GRUB_ERR_NONE;
 
220
          grub_error_pop ();
 
221
          depth--;
 
222
          return NULL;
 
223
        }
 
224
 
 
225
      if (grub_strcmp (current_string, orig) == 0)
 
226
        {
 
227
          const char *ret = 0;
 
228
          ret = grub_gettext_gettranslation_from_position (ctx, current);
 
229
          if (!ret)
209
230
            {
210
 
              cur->translated = ret;
211
 
              grub_list_push (GRUB_AS_LIST_P (&grub_gettext_msg_list),
212
 
                              GRUB_AS_LIST (cur));
 
231
              grub_errno = GRUB_ERR_NONE;
 
232
              grub_error_pop ();
 
233
              depth--;
 
234
              return NULL;
213
235
            }
 
236
          grub_error_pop ();
 
237
          depth--;
 
238
          return ret;      
214
239
        }
215
 
      else
216
 
        grub_errno = GRUB_ERR_NONE;
217
240
    }
218
241
 
219
242
  grub_error_pop ();
220
 
  return ret;
 
243
  depth--;
 
244
  return NULL;
 
245
}
 
246
 
 
247
static const char *
 
248
grub_gettext_translate (const char *orig)
 
249
{
 
250
  const char *ret;
 
251
  if (orig[0] == 0)
 
252
    return orig;
 
253
 
 
254
  ret = grub_gettext_translate_real (&main_context, orig);
 
255
  if (ret)
 
256
    return ret;
 
257
  ret = grub_gettext_translate_real (&secondary_context, orig);
 
258
  if (ret)
 
259
    return ret;
 
260
  return orig;
 
261
}
 
262
 
 
263
static void
 
264
grub_gettext_delete_list (struct grub_gettext_context *ctx)
 
265
{
 
266
  struct grub_gettext_msg *l = ctx->grub_gettext_msg_list;
 
267
  grub_size_t i;
 
268
 
 
269
  if (!l)
 
270
    return;
 
271
  ctx->grub_gettext_msg_list = 0;
 
272
  for (i = 0; i < ctx->grub_gettext_max; i++)
 
273
    grub_free (l[i].name);
 
274
  /* Don't delete the translated message because could be in use.  */
 
275
  grub_free (l);
 
276
  if (ctx->fd_mo)
 
277
    grub_file_close (ctx->fd_mo);
 
278
  ctx->fd_mo = 0;
 
279
  grub_memset (ctx, 0, sizeof (*ctx));
221
280
}
222
281
 
223
282
/* This is similar to grub_file_open. */
224
 
static grub_file_t
225
 
grub_mofile_open (const char *filename)
 
283
static grub_err_t
 
284
grub_mofile_open (struct grub_gettext_context *ctx,
 
285
                  const char *filename)
226
286
{
227
 
  int unsigned magic;
228
 
  int version;
 
287
  struct header head;
 
288
  grub_err_t err;
 
289
  grub_file_t fd;
229
290
 
230
291
  /* Using fd_mo and not another variable because
231
292
     it's needed for grub_gettext_get_info.  */
232
293
 
233
 
  fd_mo = grub_file_open (filename);
234
 
  grub_errno = GRUB_ERR_NONE;
235
 
 
236
 
  if (!fd_mo)
237
 
    {
238
 
      grub_dprintf ("gettext", "Cannot read %s\n", filename);
239
 
      return 0;
240
 
    }
241
 
 
242
 
  magic = grub_gettext_get_info (GETTEXT_MAGIC_NUMBER);
243
 
 
244
 
  if (magic != MO_MAGIC_NUMBER)
245
 
    {
246
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo file: %s",
247
 
                  filename);
248
 
      grub_file_close (fd_mo);
249
 
      fd_mo = 0;
250
 
      return 0;
251
 
    }
252
 
 
253
 
  version = grub_gettext_get_info (GETTEXT_FILE_FORMAT);
254
 
 
255
 
  if (version != 0)
256
 
    {
257
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE,
258
 
                  "mo: invalid mo version in file: %s", filename);
259
 
      fd_mo = 0;
260
 
      return 0;
261
 
    }
262
 
 
263
 
  return fd_mo;
 
294
  fd = grub_file_open (filename);
 
295
 
 
296
  if (!fd)
 
297
    return grub_errno;
 
298
 
 
299
  err = grub_gettext_pread (fd, &head, sizeof (head), 0);
 
300
  if (err)
 
301
    {
 
302
      grub_file_close (fd);
 
303
      return err;
 
304
    }
 
305
 
 
306
  if (head.magic != grub_cpu_to_le32_compile_time (MO_MAGIC_NUMBER))
 
307
    {
 
308
      grub_file_close (fd);
 
309
      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
 
310
                         "mo: invalid mo magic in file: %s", filename);
 
311
    }
 
312
 
 
313
  if (head.version != 0)
 
314
    {
 
315
      grub_file_close (fd);
 
316
      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
 
317
                         "mo: invalid mo version in file: %s", filename);
 
318
    }
 
319
 
 
320
  ctx->grub_gettext_offset_original = grub_le_to_cpu32 (head.offset_original);
 
321
  ctx->grub_gettext_offset_translation = grub_le_to_cpu32 (head.offset_translation);
 
322
  ctx->grub_gettext_max = grub_le_to_cpu32 (head.number_of_strings);
 
323
  for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log;
 
324
       ctx->grub_gettext_max_log++);
 
325
 
 
326
  ctx->grub_gettext_msg_list = grub_zalloc (ctx->grub_gettext_max
 
327
                                            * sizeof (ctx->grub_gettext_msg_list[0]));
 
328
  if (!ctx->grub_gettext_msg_list)
 
329
    {
 
330
      grub_file_close (fd);
 
331
      return grub_errno;
 
332
    }
 
333
  ctx->fd_mo = fd;
 
334
  if (grub_gettext != grub_gettext_translate)
 
335
    {
 
336
      grub_gettext_original = grub_gettext;
 
337
      grub_gettext = grub_gettext_translate;
 
338
    }
 
339
  return 0;
264
340
}
265
341
 
266
342
/* Returning grub_file_t would be more natural, but grub_mofile_open assigns
267
343
   to fd_mo anyway ...  */
268
 
static void
269
 
grub_mofile_open_lang (const char *locale_dir, const char *locale)
 
344
static grub_err_t
 
345
grub_mofile_open_lang (struct grub_gettext_context *ctx,
 
346
                       const char *part1, const char *part2, const char *locale)
270
347
{
271
348
  char *mo_file;
 
349
  grub_err_t err;
272
350
 
273
351
  /* mo_file e.g.: /boot/grub/locale/ca.mo   */
274
352
 
275
 
  mo_file = grub_xasprintf ("%s/%s.mo", locale_dir, locale);
 
353
  mo_file = grub_xasprintf ("%s%s/%s.mo", part1, part2, locale);
276
354
  if (!mo_file)
277
 
    return;
 
355
    return grub_errno;
278
356
 
279
 
  fd_mo = grub_mofile_open (mo_file);
 
357
  err = grub_mofile_open (ctx, mo_file);
280
358
 
281
359
  /* Will try adding .gz as well.  */
282
 
  if (fd_mo == NULL)
 
360
  if (err)
283
361
    {
284
362
      char *mo_file_old;
 
363
      grub_errno = GRUB_ERR_NONE;
285
364
      mo_file_old = mo_file;
286
365
      mo_file = grub_xasprintf ("%s.gz", mo_file);
287
366
      grub_free (mo_file_old);
288
367
      if (!mo_file)
289
 
        return;
290
 
      fd_mo = grub_mofile_open (mo_file);
 
368
        return grub_errno;
 
369
      err = grub_mofile_open (ctx, mo_file);
291
370
    }
 
371
  return err;
292
372
}
293
373
 
294
 
static void
295
 
grub_gettext_init_ext (const char *locale)
 
374
static grub_err_t
 
375
grub_gettext_init_ext (struct grub_gettext_context *ctx,
 
376
                       const char *locale,
 
377
                       const char *locale_dir, const char *prefix)
296
378
{
297
 
  char *locale_dir;
298
 
 
299
 
  locale_dir = grub_env_get ("locale_dir");
300
 
  if (locale_dir == NULL)
 
379
  const char *part1, *part2;
 
380
  grub_err_t err;
 
381
 
 
382
  grub_gettext_delete_list (ctx);
 
383
 
 
384
  if (!locale || locale[0] == 0)
 
385
    return 0;
 
386
 
 
387
  part1 = locale_dir;
 
388
  part2 = "";
 
389
  if (!part1 || part1[0] == 0)
301
390
    {
302
 
      grub_dprintf ("gettext", "locale_dir variable is not set up.\n");
303
 
      return;
 
391
      part1 = prefix;
 
392
      part2 = "/locale";
304
393
    }
305
394
 
306
 
  fd_mo = NULL;
 
395
  if (!part1 || part1[0] == 0)
 
396
    return 0;
307
397
 
308
 
  grub_mofile_open_lang (locale_dir, locale);
 
398
  err = grub_mofile_open_lang (ctx, part1, part2, locale);
309
399
 
310
400
  /* ll_CC didn't work, so try ll.  */
311
 
  if (fd_mo == NULL)
 
401
  if (err)
312
402
    {
313
403
      char *lang = grub_strdup (locale);
314
 
      char *underscore = grub_strchr (lang, '_');
 
404
      char *underscore = lang ? grub_strchr (lang, '_') : 0;
315
405
 
316
406
      if (underscore)
317
407
        {
318
408
          *underscore = '\0';
319
 
          grub_mofile_open_lang (locale_dir, lang);
 
409
          grub_errno = GRUB_ERR_NONE;
 
410
          err = grub_mofile_open_lang (ctx, part1, part2, lang);
320
411
        }
321
412
 
322
413
      grub_free (lang);
323
414
    }
324
 
 
325
 
  if (fd_mo)
326
 
    {
327
 
      grub_gettext_offsetoriginal =
328
 
        grub_gettext_get_info (GETTEXT_OFFSET_ORIGINAL);
329
 
      grub_gettext_max = grub_gettext_get_info (GETTEXT_NUMBER_OF_STRINGS);
330
 
 
331
 
      grub_gettext_original = grub_gettext;
332
 
      grub_gettext = grub_gettext_translate;
333
 
    }
334
 
}
335
 
 
336
 
static void
337
 
grub_gettext_delete_list (void)
338
 
{
339
 
  while (grub_gettext_msg_list)
340
 
    {
341
 
      grub_free ((char *) grub_gettext_msg_list->name);
342
 
      grub_gettext_msg_list = grub_gettext_msg_list->next;
343
 
      /* Don't delete the translated message because could be in use.  */
344
 
    }
 
415
  return err;
345
416
}
346
417
 
347
418
static char *
348
419
grub_gettext_env_write_lang (struct grub_env_var *var
349
420
                             __attribute__ ((unused)), const char *val)
350
421
{
351
 
  grub_gettext_init_ext (val);
352
 
 
353
 
  grub_gettext_delete_list ();
 
422
  grub_err_t err;
 
423
  err = grub_gettext_init_ext (&main_context, val, grub_env_get ("locale_dir"),
 
424
                               grub_env_get ("prefix"));
 
425
  if (err)
 
426
    grub_print_error ();
 
427
 
 
428
  err = grub_gettext_init_ext (&secondary_context, val,
 
429
                               grub_env_get ("secondary_locale_dir"), 0);
 
430
  if (err)
 
431
    grub_print_error ();
 
432
 
 
433
  return grub_strdup (val);
 
434
}
 
435
 
 
436
void
 
437
grub_gettext_reread_prefix (const char *val)
 
438
{
 
439
  grub_err_t err;
 
440
  err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), 
 
441
                               grub_env_get ("locale_dir"),
 
442
                               val);
 
443
  if (err)
 
444
    grub_print_error ();
 
445
}
 
446
 
 
447
static char *
 
448
read_main (struct grub_env_var *var
 
449
           __attribute__ ((unused)), const char *val)
 
450
{
 
451
  grub_err_t err;
 
452
  err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), val,
 
453
                               grub_env_get ("prefix"));
 
454
  if (err)
 
455
    grub_print_error ();
 
456
  return grub_strdup (val);
 
457
}
 
458
 
 
459
static char *
 
460
read_secondary (struct grub_env_var *var
 
461
                __attribute__ ((unused)), const char *val)
 
462
{
 
463
  grub_err_t err;
 
464
  err = grub_gettext_init_ext (&secondary_context, grub_env_get ("lang"), val,
 
465
                               0);
 
466
  if (err)
 
467
    grub_print_error ();
354
468
 
355
469
  return grub_strdup (val);
356
470
}
360
474
                    int argc, char **args)
361
475
{
362
476
  if (argc != 1)
363
 
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
 
477
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
364
478
 
365
479
  const char *translation;
366
480
  translation = grub_gettext_translate (args[0]);
370
484
 
371
485
GRUB_MOD_INIT (gettext)
372
486
{
373
 
  (void) mod;                   /* To stop warning.  */
374
 
 
375
487
  const char *lang;
 
488
  grub_err_t err;
376
489
 
377
490
  lang = grub_env_get ("lang");
378
491
 
379
 
  grub_gettext_init_ext (lang);
 
492
  err = grub_gettext_init_ext (&main_context, lang, grub_env_get ("locale_dir"),
 
493
                               grub_env_get ("prefix"));
 
494
  if (err)
 
495
    grub_print_error ();
 
496
  err = grub_gettext_init_ext (&secondary_context, lang,
 
497
                               grub_env_get ("secondary_locale_dir"), 0);
 
498
  if (err)
 
499
    grub_print_error ();
 
500
 
 
501
  grub_register_variable_hook ("locale_dir", NULL, read_main);
 
502
  grub_register_variable_hook ("secondary_locale_dir", NULL, read_secondary);
380
503
 
381
504
  grub_register_command_p1 ("gettext", grub_cmd_translate,
382
505
                            N_("STRING"),
 
506
                            /* TRANSLATORS: It refers to passing the string through gettext.
 
507
                               So it's "translate" in the same meaning as in what you're 
 
508
                               doing now.
 
509
                             */
383
510
                            N_("Translates the string with the current settings."));
384
511
 
385
512
  /* Reload .mo file information if lang changes.  */
387
514
 
388
515
  /* Preserve hooks after context changes.  */
389
516
  grub_env_export ("lang");
 
517
  grub_env_export ("locale_dir");
 
518
  grub_env_export ("secondary_locale_dir");
390
519
}
391
520
 
392
521
GRUB_MOD_FINI (gettext)
393
522
{
394
 
  if (fd_mo != 0)
395
 
    grub_file_close (fd_mo);
396
 
 
397
 
  grub_gettext_delete_list ();
 
523
  grub_gettext_delete_list (&main_context);
 
524
  grub_gettext_delete_list (&secondary_context);
398
525
 
399
526
  grub_gettext = grub_gettext_original;
400
527
}