Skip to content

Commit

Permalink
Add pgettext for some ambiguous strings
Browse files Browse the repository at this point in the history
There are some strings which are ambiguous to translate. There is the
pgettext function to solf that problem.

For example, locations can be translated to german by Ortsangaben
(geographical) or by Pfad (filesystem). I am sure there are also some
ambiguous in other languages.
  • Loading branch information
mowgli committed Apr 10, 2009
1 parent b2d63b6 commit a9076f2
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/bar.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ static void bar_menu_popup(GtkWidget *widget)
menu_item_add_stock(menu, _("Move _down"), GTK_STOCK_GO_DOWN, G_CALLBACK(bar_expander_move_down_cb), expander);
menu_item_add_stock(menu, _("Move to _bottom"), GTK_STOCK_GOTO_BOTTOM, G_CALLBACK(bar_expander_move_bottom_cb), expander);
menu_item_add_divider(menu);
menu_item_add_stock(menu, _("Delete"), GTK_STOCK_DELETE, G_CALLBACK(bar_expander_delete_cb), expander);
menu_item_add_stock(menu, pgettext("virtual","Delete"), GTK_STOCK_DELETE, G_CALLBACK(bar_expander_delete_cb), expander);
menu_item_add_divider(menu);
}

Expand Down
271 changes: 271 additions & 0 deletions src/gettext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
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, 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
Library General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA. */

#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1

/* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS

/* Get declarations of GNU message catalog functions. */
# include <libintl.h>

/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
the gettext() and ngettext() macros. This is an alternative to calling
textdomain(), and is useful for libraries. */
# ifdef DEFAULT_TEXT_DOMAIN
# undef gettext
# define gettext(Msgid) \
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
# undef ngettext
# define ngettext(Msgid1, Msgid2, N) \
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
# endif

#else

/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
chokes if dcgettext is defined as a macro. So include it now, to make
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
as well because people using "gettext.h" will not include <libintl.h>,
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
is OK. */
#if defined(__sun)
# include <locale.h>
#endif

/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
it now, to make later inclusions of <libintl.h> a NOP. */
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
# include <cstdlib>
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
# include <libintl.h>
# endif
#endif

/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
# define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid))
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \
? ((void) (Msgid2), (const char *) (Msgid1)) \
: ((void) (Msgid1), (const char *) (Msgid2)))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
# define textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) \
((void) (Domainname), (const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset))

#endif

/* A pseudo function call that serves as a marker for the automated
extraction of messages, but does not call gettext(). The run-time
translation is done at a different place in the code.
The argument, String, should be a literal string. Concatenated strings
and other string expressions won't work.
The macro's expansion is not parenthesized, so that it is suitable as
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String

/* The separator between msgctxt and msgid in a .mo file. */
#define GETTEXT_CONTEXT_GLUE "\004"

/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
short and rarely need to change.
The letter 'p' stands for 'particular' or 'special'. */
#ifdef DEFAULT_TEXT_DOMAIN
# define pgettext(Msgctxt, Msgid) \
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#else
# define pgettext(Msgctxt, Msgid) \
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#endif
#define dpgettext(Domainname, Msgctxt, Msgid) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
#ifdef DEFAULT_TEXT_DOMAIN
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#else
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#endif
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
pgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid,
int category)
{
const char *translation = dcgettext (domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id)
return msgid;
else
return translation;
}

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
npgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
{
const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
if (translation == msg_ctxt_id || translation == msgid_plural)
return (n == 1 ? msgid : msgid_plural);
else
return translation;
}

/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
can be arbitrary expressions. But for string literals these macros are
less efficient than those above. */

#include <string.h>

#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
/* || __STDC_VERSION__ >= 199901L */ )

#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
#include <stdlib.h>
#endif

#define pgettext_expr(Msgctxt, Msgid) \
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
dcpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid,
int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len];
#else
char buf[1024];
char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf)
? buf
: (char *) malloc (msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL)
#endif
{
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcgettext (domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
free (msg_ctxt_id);
#endif
if (translation != msg_ctxt_id)
return translation;
}
return msgid;
}

#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
dcnpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len];
#else
char buf[1024];
char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf)
? buf
: (char *) malloc (msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL)
#endif
{
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
free (msg_ctxt_id);
#endif
if (!(translation == msg_ctxt_id || translation == msgid_plural))
return translation;
}
return (n == 1 ? msgid : msgid_plural);
}

#endif /* _LIBGETTEXT_H */
4 changes: 3 additions & 1 deletion src/intl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#define __INTL_H__

#ifdef ENABLE_NLS
# include <libintl.h>
# include <locale.h>
# include "gettext.h"
# define _(String) dgettext(PACKAGE,String)
# ifdef gettext_noop
# define N_(String) gettext_noop(String)
Expand All @@ -18,6 +19,7 @@
# define dcgettext(Domain,String,Type) (String)
# define bindtextdomain(Domain,Directory) (Domain)
# define bind_textdomain_codeset(Domain,String) (Domain)
# define pgettext(Context,String) (String)
#endif /* ENABLE_NLS */

#endif
Expand Down
2 changes: 1 addition & 1 deletion src/preferences.c
Original file line number Diff line number Diff line change
Expand Up @@ -1449,7 +1449,7 @@ static void config_tab_behavior(GtkWidget *notebook)

vbox = scrolled_notebook_page(notebook, _("Behavior"));

group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
group = pref_group_new(vbox, FALSE, pgettext("physical","Delete"), GTK_ORIENTATION_VERTICAL);

pref_checkbox_new_int(group, _("Confirm file delete"),
options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
Expand Down
4 changes: 2 additions & 2 deletions src/utilops.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ static GtkWidget *file_util_dialog_add_list(GtkWidget *box, GList *list, gboolea

if (full_paths)
{
file_util_dialog_add_list_column(view, _("Location"), FALSE, UTILITY_COLUMN_PATH);
file_util_dialog_add_list_column(view, pgettext("filesystem","Location"), FALSE, UTILITY_COLUMN_PATH);
}
else
{
Expand Down Expand Up @@ -1647,7 +1647,7 @@ static void file_util_delete_full(FileData *source_fd, GList *source_list, GtkWi
ud->content_list = NULL;
ud->parent = parent;

ud->messages.title = _("Delete");
ud->messages.title = pgettext("physical","Delete");
ud->messages.question = _("Delete files?");
ud->messages.desc_flist = _("This will delete the following files");
ud->messages.desc_source_fd = "";
Expand Down

0 comments on commit a9076f2

Please sign in to comment.