From: Daiki Ueno Date: Fri, 14 Mar 2014 08:42:15 +0000 (+0900) Subject: xgettext: Add support for Desktop Entry files X-Git-Tag: v0.19~124 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f83445c64c06b41c00ebbd71b0912f1d11c63919;p=thirdparty%2Fgettext.git xgettext: Add support for Desktop Entry files --- diff --git a/gettext-tools/doc/xgettext.texi b/gettext-tools/doc/xgettext.texi index c8adc274d..d187d6343 100644 --- a/gettext-tools/doc/xgettext.texi +++ b/gettext-tools/doc/xgettext.texi @@ -74,7 +74,7 @@ are @code{C}, @code{C++}, @code{ObjectiveC}, @code{PO}, @code{Shell}, @code{Smalltalk}, @code{Java}, @code{JavaProperties}, @code{C#}, @code{awk}, @code{YCP}, @code{Tcl}, @code{Perl}, @code{PHP}, @code{GCC-source}, @code{NXStringTable}, @code{RST}, @code{Glade}, @code{Lua}, @code{JavaScript}, -@code{Vala}, @code{GSettings}. +@code{Vala}, @code{GSettings}, @code{Desktop}. @item -C @itemx --c++ @@ -181,7 +181,7 @@ escaped. This option has an effect with most languages, namely C, C++, ObjectiveC, Shell, Python, Lisp, EmacsLisp, librep, Java, C#, awk, Tcl, Perl, PHP, -GCC-source, Glade, Lua, JavaScript, Vala, GSettings. +GCC-source, Glade, Lua, JavaScript, Vala, GSettings, Desktop. The default keyword specifications, which are always looked for if not explicitly disabled, are language dependent. They are: @@ -261,6 +261,10 @@ For JavaScript: @code{_}, @code{gettext}, @code{dgettext:2}, For Vala: @code{_}, @code{Q_}, @code{N_}, @code{NC_}, @code{dgettext:2}, @code{dcgettext:2}, @code{ngettext:1,2}, @code{dngettext:2,3}, @code{dpgettext:2c,3}, @code{dpgettext2:2c,3}. + +@item +For Desktop: @code{Name}, @code{GenericName}, @code{Comment}, +@code{Icon}, @code{Keywords}. @end itemize To disable the default keyword specifications, the option @samp{-k} or diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am index e6713af50..d43afdcf1 100644 --- a/gettext-tools/src/Makefile.am +++ b/gettext-tools/src/Makefile.am @@ -48,6 +48,7 @@ read-csharp.h write-csharp.h \ read-resources.h write-resources.h \ read-tcl.h write-tcl.h \ write-qt.h \ +read-desktop.h \ po-time.h plural-table.h lang-table.h format.h filters.h \ xgettext.h x-c.h x-po.h x-sh.h x-python.h x-lisp.h x-elisp.h x-librep.h \ x-scheme.h x-smalltalk.h x-java.h x-properties.h x-csharp.h x-awk.h x-ycp.h \ @@ -148,7 +149,8 @@ color.c write-catalog.c write-properties.c write-stringtable.c write-po.c \ msgl-ascii.c msgl-iconv.c msgl-equal.c msgl-cat.c msgl-header.c msgl-english.c \ msgl-check.c file-list.c msgl-charset.c po-time.c plural-exp.c plural-eval.c \ plural-table.c \ -$(FORMAT_SOURCE) +$(FORMAT_SOURCE) \ +read-desktop.c # msggrep needs pattern matching. LIBGREP = ../libgrep/libgrep.a @@ -178,7 +180,8 @@ xgettext_SOURCES += \ x-c.c x-po.c x-sh.c x-python.c x-lisp.c x-elisp.c x-librep.c x-scheme.c \ x-smalltalk.c x-java.c x-csharp.c x-awk.c x-ycp.c x-tcl.c x-perl.c x-php.c \ x-rst.c x-glade.c x-lua.c x-javascript.c x-vala.c x-gsettings.c \ - libexpat-compat.c + libexpat-compat.c \ + x-desktop.c if !WOE32DLL msgattrib_SOURCES = msgattrib.c else diff --git a/gettext-tools/src/read-desktop.c b/gettext-tools/src/read-desktop.c new file mode 100644 index 000000000..78d7226f4 --- /dev/null +++ b/gettext-tools/src/read-desktop.c @@ -0,0 +1,528 @@ +/* Reading Desktop Entry files. + Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014 Free Software Foundation, Inc. + This file was written by Daiki Ueno . + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "read-desktop.h" + +#include "xalloc.h" + +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "error-progname.h" +#include "xalloc.h" +#include "xvasprintf.h" +#include "c-ctype.h" +#include "po-lex.h" +#include "po-xerror.h" +#include "gettext.h" + +#define _(str) gettext (str) + +/* The syntax of a Desktop Entry file is defined at + http://standards.freedesktop.org/desktop-entry-spec/latest/index.html. */ + +desktop_reader_ty * +desktop_reader_alloc (desktop_reader_class_ty *method_table) +{ + desktop_reader_ty *reader; + + reader = (desktop_reader_ty *) xmalloc (method_table->size); + reader->methods = method_table; + if (method_table->constructor) + method_table->constructor (reader); + return reader; +} + +void +desktop_reader_free (desktop_reader_ty *reader) +{ + if (reader->methods->destructor) + reader->methods->destructor (reader); + free (reader); +} + +void +desktop_reader_handle_group (desktop_reader_ty *reader, const char *group) +{ + if (reader->methods->handle_group) + reader->methods->handle_group (reader, group); +} + +void +desktop_reader_handle_pair (desktop_reader_ty *reader, + lex_pos_ty *key_pos, + const char *key, + const char *locale, + const char *value) +{ + if (reader->methods->handle_pair) + reader->methods->handle_pair (reader, key_pos, key, locale, value); +} + +void +desktop_reader_handle_comment (desktop_reader_ty *reader, const char *s) +{ + if (reader->methods->handle_comment) + reader->methods->handle_comment (reader, s); +} + +void +desktop_reader_handle_text (desktop_reader_ty *reader, const char *s) +{ + if (reader->methods->handle_text) + reader->methods->handle_text (reader, s); +} + +/* Real filename, used in error messages about the input file. */ +static const char *real_file_name; + +/* File name and line number. */ +extern lex_pos_ty gram_pos; + +/* The input file stream. */ +static FILE *fp; + + +static int +phase1_getc () +{ + int c; + + c = getc (fp); + + if (c == EOF) + { + if (ferror (fp)) + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("error while reading \"%s\""), + real_file_name), + errno_description)); + } + return EOF; + } + + return c; +} + +static inline void +phase1_ungetc (int c) +{ + if (c != EOF) + ungetc (c, fp); +} + + +static unsigned char phase2_pushback[2]; +static int phase2_pushback_length; + +static int +phase2_getc () +{ + int c; + + if (phase2_pushback_length) + c = phase2_pushback[--phase2_pushback_length]; + else + { + c = phase1_getc (); + + if (c == '\r') + { + int c2 = phase1_getc (); + if (c2 == '\n') + c = c2; + else + phase1_ungetc (c2); + } + } + + if (c == '\n') + gram_pos.line_number++; + + return c; +} + +static void +phase2_ungetc (int c) +{ + if (c == '\n') + --gram_pos.line_number; + if (c != EOF) + phase2_pushback[phase2_pushback_length++] = c; +} + +static char * +read_until_newline (void) +{ + char *buffer = NULL; + size_t bufmax = 0; + size_t buflen; + + buflen = 0; + for (;;) + { + int c; + + c = phase2_getc (); + + if (buflen >= bufmax) + { + bufmax += 100; + buffer = xrealloc (buffer, bufmax); + } + + if (c == EOF || c == '\n') + break; + + buffer[buflen++] = c; + } + buffer[buflen] = '\0'; + return buffer; +} + +static char * +read_group_name (void) +{ + char *buffer = NULL; + size_t bufmax = 0; + size_t buflen; + + buflen = 0; + for (;;) + { + int c; + + c = phase2_getc (); + + if (buflen >= bufmax) + { + bufmax += 100; + buffer = xrealloc (buffer, bufmax); + } + + if (c == EOF || c == '\n' || c == ']') + break; + + buffer[buflen++] = c; + } + buffer[buflen] = '\0'; + return buffer; +} + +static char * +read_key_name (const char **locale) +{ + char *buffer = NULL; + size_t bufmax = 0; + size_t buflen; + const char *locale_start = NULL; + + buflen = 0; + for (;;) + { + int c; + + c = phase2_getc (); + + if (buflen >= bufmax) + { + bufmax += 100; + buffer = xrealloc (buffer, bufmax); + } + + if (c == EOF || c == '\n') + break; + + if (!locale_start) + { + if (c == '[') + { + buffer[buflen++] = '\0'; + locale_start = &buffer[buflen]; + continue; + } + else if (!c_isalnum (c) && c != '-') + { + phase2_ungetc (c); + break; + } + } + else + { + if (c == ']') + { + buffer[buflen++] = '\0'; + break; + } + else if (!c_isascii (c)) + { + phase2_ungetc (c); + break; + } + } + + buffer[buflen++] = c; + } + buffer[buflen] = '\0'; + + if (locale_start) + *locale = locale_start; + + return buffer; +} + +void +desktop_parse (desktop_reader_ty *reader, FILE *file, + const char *real_filename, const char *logical_filename) +{ + fp = file; + real_file_name = real_filename; + gram_pos.file_name = xstrdup (real_file_name); + gram_pos.line_number = 1; + + for (;;) + { + int c; + + c = phase2_getc (); + + if (c == EOF) + break; + + if (c == '[') + { + /* A group header. */ + char *group_name; + + group_name = read_group_name (); + + do + c = phase2_getc (); + while (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f'); + + if (c == EOF) + break; + + phase2_ungetc (c); + + desktop_reader_handle_group (reader, group_name); + free (group_name); + } + else if (c == '#') + { + /* A comment line. */ + char *comment; + + comment = read_until_newline (); + desktop_reader_handle_comment (reader, comment); + free (comment); + } + else if (c_isalnum (c) || c == '-') + { + /* A key/value pair. */ + char *key_name; + const char *locale; + + phase2_ungetc (c); + + locale = NULL; + key_name = read_key_name (&locale); + do + c = phase2_getc (); + while (c == ' ' || c == '\t' || c == '\r' || c == '\f'); + + if (c == EOF) + break; + + if (c != '=') + { + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, + real_filename, gram_pos.line_number, 0, false, + xasprintf (_("missing '=' after \"%s\""), key_name)); + } + else + { + char *value; + + do + c = phase2_getc (); + while (c == ' ' || c == '\t' || c == '\r' || c == '\f'); + + if (c == EOF) + break; + + phase2_ungetc (c); + + value = read_until_newline (); + desktop_reader_handle_pair (reader, &gram_pos, + key_name, locale, value); + free (value); + } + free (key_name); + } + else + { + char *text; + + phase2_ungetc (c); + + text = read_until_newline (); + desktop_reader_handle_text (reader, text); + free (text); + } + } + + fp = NULL; + real_file_name = NULL; + gram_pos.line_number = 0; +} + +char * +desktop_escape_string (const char *s, bool is_list) +{ + char *buffer, *p; + + p = buffer = XNMALLOC (strlen (s) * 2 + 1, char); + + /* The first character must not be a whitespace. */ + if (*s == ' ') + { + p = stpcpy (p, "\\s"); + s++; + } + else if (*s == '\t') + { + p = stpcpy (p, "\\t"); + s++; + } + + for (;; s++) + { + if (*s == '\0') + { + *p = '\0'; + break; + } + + switch (*s) + { + case '\n': + p = stpcpy (p, "\\n"); + break; + case '\r': + p = stpcpy (p, "\\r"); + break; + case '\\': + if (is_list && *(s + 1) == ';') + { + p = stpcpy (p, "\\;"); + s++; + } + else + p = stpcpy (p, "\\\\"); + break; + default: + *p++ = *s; + break; + } + } + + return buffer; +} + +char * +desktop_unescape_string (const char *s, bool is_list) +{ + char *buffer, *p; + + p = buffer = XNMALLOC (strlen (s) + 1, char); + for (;; s++) + { + if (*s == '\0') + { + *p = '\0'; + break; + } + + if (*s == '\\') + { + s++; + + if (*s == '\0') + { + *p = '\0'; + break; + } + + switch (*s) + { + case 's': + *p++ = ' '; + break; + case 'n': + *p++ = '\n'; + break; + case 't': + *p++ = '\t'; + break; + case 'r': + *p++ = '\r'; + break; + case ';': + p = stpcpy (p, "\\;"); + break; + default: + *p++ = *s; + break; + } + } + else + *p++ = *s; + } + return buffer; +} + +void +desktop_add_keyword (hash_table *keywords, const char *name, bool is_list) +{ + hash_insert_entry (keywords, name, strlen (name), (void *) is_list); +} + +void +desktop_add_default_keywords (hash_table *keywords) +{ + /* When adding new keywords here, also update the documentation in + xgettext.texi! */ + desktop_add_keyword (keywords, "Name", false); + desktop_add_keyword (keywords, "GenericName", false); + desktop_add_keyword (keywords, "Comment", false); + desktop_add_keyword (keywords, "Icon", false); + desktop_add_keyword (keywords, "Keywords", true); +} diff --git a/gettext-tools/src/read-desktop.h b/gettext-tools/src/read-desktop.h new file mode 100644 index 000000000..c36cc6b06 --- /dev/null +++ b/gettext-tools/src/read-desktop.h @@ -0,0 +1,121 @@ +/* Reading Desktop Entry files. + Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014 Free Software Foundation, Inc. + This file was written by Daiki Ueno . + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _READ_DESKTOP_H +#define _READ_DESKTOP_H + +#include +#include +#include "hash.h" +#include "po-lex.h" +#include "str-list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declaration. */ +struct desktop_reader_ty; + + +/* This first structure, playing the role of the "Class" in OO sense, + contains pointers to functions. Each function is a method for the + class (base or derived). Use a NULL pointer where no action is + required. */ + +typedef struct desktop_reader_class_ty desktop_reader_class_ty; +struct desktop_reader_class_ty +{ + /* how many bytes to malloc for an instance of this class */ + size_t size; + + /* what to do immediately after the instance is malloc()ed */ + void (*constructor) (struct desktop_reader_ty *pop); + + /* what to do immediately before the instance is free()ed */ + void (*destructor) (struct desktop_reader_ty *pop); + + /* what to do with a group header */ + void (*handle_group) (struct desktop_reader_ty *pop, + const char *group); + + /* what to do with a key/value pair */ + void (*handle_pair) (struct desktop_reader_ty *pop, + lex_pos_ty *key_pos, + const char *key, + const char *locale, + const char *value); + + /* what to do with a comment */ + void (*handle_comment) (struct desktop_reader_ty *pop, const char *s); + + /* what to do with other lines */ + void (*handle_text) (struct desktop_reader_ty *pop, const char *s); +}; + +/* This next structure defines the base class passed to the methods. + Derived methods will often need to cast their first argument before + using it (this corresponds to the implicit 'this' argument in C++). + + When declaring derived classes, use the DESKTOP_READER_TY define + at the start of the structure, to declare inherited instance variables, + etc. */ + +#define DESKTOP_READER_TY \ + desktop_reader_class_ty *methods; + +typedef struct desktop_reader_ty desktop_reader_ty; +struct desktop_reader_ty +{ + DESKTOP_READER_TY +}; + +desktop_reader_ty *desktop_reader_alloc (desktop_reader_class_ty *methods); +void desktop_reader_free (desktop_reader_ty *reader); + +void desktop_reader_handle_group (desktop_reader_ty *reader, + const char *group); + +void desktop_reader_handle_pair (desktop_reader_ty *reader, + lex_pos_ty *key_pos, + const char *key, + const char *locale, + const char *value); + +void desktop_reader_handle_comment (desktop_reader_ty *reader, + const char *s); + +void desktop_reader_handle_text (desktop_reader_ty *reader, + const char *s); + + +void desktop_parse (desktop_reader_ty *reader, FILE *file, + const char *real_filename, const char *logical_filename); + + +char *desktop_escape_string (const char *s, bool is_list); +char *desktop_unescape_string (const char *s, bool is_list); + +void desktop_add_keyword (hash_table *keywords, const char *name, bool is_list); +void desktop_add_default_keywords (hash_table *keywords); + +#ifdef __cplusplus +} +#endif + + +#endif /* _READ_DESKTOP_H */ diff --git a/gettext-tools/src/x-desktop.c b/gettext-tools/src/x-desktop.c new file mode 100644 index 000000000..8484004c9 --- /dev/null +++ b/gettext-tools/src/x-desktop.c @@ -0,0 +1,177 @@ +/* xgettext Desktop Entry backend. + Copyright (C) 2014 Free Software Foundation, Inc. + + This file was written by Daiki Ueno , 2014. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "x-desktop.h" + +#include +#include +#include +#include +#include + +#include "message.h" +#include "xgettext.h" +#include "error.h" +#include "error-progname.h" +#include "xalloc.h" +#include "xvasprintf.h" +#include "hash.h" +#include "gettext.h" +#include "read-desktop.h" +#include "po-charset.h" + +#define _(s) gettext(s) + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + +/* ====================== Keyword set customization. ====================== */ + +/* The syntax of a Desktop Entry file is defined at + http://standards.freedesktop.org/desktop-entry-spec/latest/index.html + + Basically, values with 'localestring' type can be translated. + + The type of a value is determined by looking at the key associated + with it. The list of available keys are listed on: + http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s05.html */ + +static hash_table keywords; +static bool default_keywords = true; + +static void +add_keyword (const char *name, hash_table *keywords, bool is_list) +{ + if (name == NULL) + default_keywords = false; + else + { + if (keywords->table == NULL) + hash_init (keywords, 100); + + desktop_add_keyword (keywords, name, is_list); + } +} + +void +x_desktop_keyword (const char *name) +{ + add_keyword (name, &keywords, false); +} + +static void +init_keywords (void) +{ + if (default_keywords) + { + if (keywords.table == NULL) + hash_init (&keywords, 100); + + desktop_add_default_keywords (&keywords); + default_keywords = false; + } +} + +typedef struct extract_desktop_reader_ty extract_desktop_reader_ty; +struct extract_desktop_reader_ty +{ + DESKTOP_READER_TY + + message_list_ty *mlp; +}; + +static void +extract_desktop_handle_group (struct desktop_reader_ty *reader, + const char *group) +{ + savable_comment_reset (); +} + +static void +extract_desktop_handle_pair (struct desktop_reader_ty *reader, + lex_pos_ty *key_pos, + const char *key, + const char *locale, + const char *value) +{ + extract_desktop_reader_ty *extract_reader = + (extract_desktop_reader_ty *) reader; + void *keyword_value; + + if (!locale /* Skip already translated entry. */ + && hash_find_entry (&keywords, key, strlen (key), &keyword_value) == 0) + { + bool is_list = (bool) keyword_value; + + remember_a_message (extract_reader->mlp, NULL, + desktop_unescape_string (value, is_list), + null_context, key_pos, + NULL, savable_comment); + } + savable_comment_reset (); +} + +static void +extract_desktop_handle_comment (struct desktop_reader_ty *reader, + const char *s) +{ + savable_comment_add (s); +} + +static void +extract_desktop_handle_text (struct desktop_reader_ty *reader, + const char *s) +{ + savable_comment_reset (); +} + +desktop_reader_class_ty extract_methods = + { + sizeof (extract_desktop_reader_ty), + NULL, + NULL, + extract_desktop_handle_group, + extract_desktop_handle_pair, + extract_desktop_handle_comment, + extract_desktop_handle_text + }; + +void +extract_desktop (FILE *f, + const char *real_filename, const char *logical_filename, + flag_context_list_table_ty *flag_table, + msgdomain_list_ty *mdlp) +{ + desktop_reader_ty *reader = desktop_reader_alloc (&extract_methods); + extract_desktop_reader_ty *extract_reader = + (extract_desktop_reader_ty *) reader; + + init_keywords (); + xgettext_current_source_encoding = po_charset_utf8; + + extract_reader->mlp = mdlp->item[0]->messages; + + desktop_parse (reader, f, real_filename, logical_filename); + desktop_reader_free (reader); + + reader = NULL; +} diff --git a/gettext-tools/src/x-desktop.h b/gettext-tools/src/x-desktop.h new file mode 100644 index 000000000..d9f1ff44d --- /dev/null +++ b/gettext-tools/src/x-desktop.h @@ -0,0 +1,47 @@ +/* xgettext Desktop Entry backend. + Copyright (C) 2014 Free Software Foundation, Inc. + Written by Daiki Ueno , 2014. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +#include "message.h" +#include "xgettext.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define EXTENSIONS_DESKTOP \ + { "desktop", "Desktop" }, \ + +#define SCANNERS_DESKTOP \ + { "Desktop", extract_desktop, NULL, NULL, NULL }, \ + +/* Scan a Desktop Entry file and add its translatable strings to mdlp. */ +extern void extract_desktop (FILE *fp, const char *real_filename, + const char *logical_filename, + flag_context_list_table_ty *flag_table, + msgdomain_list_ty *mdlp); + +extern void x_desktop_keyword (const char *keyword); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index 8f14b939b..0598cfa74 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -96,6 +96,7 @@ #include "x-javascript.h" #include "x-vala.h" #include "x-gsettings.h" +#include "x-desktop.h" /* If nonzero add all comments immediately preceding one of the keywords. */ @@ -448,6 +449,7 @@ main (int argc, char *argv[]) x_lua_keyword (optarg); x_javascript_keyword (optarg); x_vala_keyword (optarg); + x_desktop_keyword (optarg); if (optarg == NULL) no_default_keywords = true; else @@ -886,7 +888,7 @@ Choice of input file language:\n")); EmacsLisp, librep, Scheme, Smalltalk, Java,\n\ JavaProperties, C#, awk, YCP, Tcl, Perl, PHP,\n\ GCC-source, NXStringTable, RST, Glade, Lua,\n\ - JavaScript, Vala)\n")); + JavaScript, Vala, Desktop)\n")); printf (_("\ -C, --c++ shorthand for --language=C++\n")); printf (_("\ @@ -928,7 +930,7 @@ Language specific options:\n")); (only languages C, C++, ObjectiveC, Shell,\n\ Python, Lisp, EmacsLisp, librep, Scheme, Java,\n\ C#, awk, Tcl, Perl, PHP, GCC-source, Glade,\n\ - Lua, JavaScript, Vala)\n")); + Lua, JavaScript, Vala, Desktop)\n")); printf (_("\ --flag=WORD:ARG:FLAG additional flag for strings inside the argument\n\ number ARG of keyword WORD\n")); @@ -3257,6 +3259,7 @@ language_to_extractor (const char *name) SCANNERS_JAVASCRIPT SCANNERS_VALA SCANNERS_GSETTINGS + SCANNERS_DESKTOP /* Here may follow more languages and their scanners: pike, etc... Make sure new scanners honor the --exclude-file option. */ }; @@ -3344,6 +3347,7 @@ extension_to_language (const char *extension) EXTENSIONS_JAVASCRIPT EXTENSIONS_VALA EXTENSIONS_GSETTINGS + EXTENSIONS_DESKTOP /* Here may follow more file extensions... */ }; diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 8978ca0a1..6d71a230a 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -105,6 +105,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \ xgettext-javascript-4 xgettext-javascript-5 xgettext-javascript-6 \ xgettext-vala-1 \ xgettext-gsettings-1 \ + xgettext-desktop-1 \ format-awk-1 format-awk-2 \ format-boost-1 format-boost-2 \ format-c-1 format-c-2 format-c-3 format-c-4 format-c-5 \ diff --git a/gettext-tools/tests/xgettext-desktop-1 b/gettext-tools/tests/xgettext-desktop-1 new file mode 100755 index 000000000..0839ee5d0 --- /dev/null +++ b/gettext-tools/tests/xgettext-desktop-1 @@ -0,0 +1,56 @@ +#!/bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test of Desktop Entry support. + +cat < xg.desktop +[Desktop Entry] +Type=Application +Name =Foo +Comment= \sThis is a \nmultiline\t comment; for testing +Comment[foo]=Already translated comment +Keywords=Keyword1;Keyword2;Key\;word3; +EOF + +: ${XGETTEXT=xgettext} +${XGETTEXT} --add-comments -o - xg.desktop | grep -v 'POT-Creation-Date' > xg-desktop.pot || exit 1 + +cat <<\EOF > xg-desktop.ok +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: xg.desktop:4 +msgid "Foo" +msgstr "" + +#: xg.desktop:5 +msgid "" +" This is a \n" +"multiline\t comment; for testing" +msgstr "" + +#: xg.desktop:7 +msgid "Keyword1;Keyword2;Key\\;word3;" +msgstr "" +EOF + +: ${DIFF=diff} +${DIFF} xg-desktop.ok xg-desktop.pot +result=$? + +exit $result