tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[PATCH 3/3] Added initial implementation of context function
- Added most *p*gettext functions
- Added basic function to concat msgctxt and msgid
Work needed:
- Tests!
---
src/lib/libintl/gettext.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
src/lib/libintl/libintl.h | 21 +++++++++
2 files changed, 131 insertions(+)
diff --git a/src/lib/libintl/gettext.c b/src/lib/libintl/gettext.c
index 479b4be..b9e2369 100644
--- a/src/lib/libintl/gettext.c
+++ b/src/lib/libintl/gettext.c
@@ -51,6 +51,16 @@ __RCSID("$NetBSD: gettext.c,v 1.28 2012/07/30 23:04:42 yamt Exp $");
#include "plural_parser.h"
#include "pathnames.h"
+/* GNU gettext added a hack to add some context to messages. If a message is
+ * used in multiple locations, it needs some amount of context to make the
+ * translation clear to translators. GNU gettext, rather than modifying the
+ * message format, concatenates the context, \004 and the message id.
+ */
+#define MSGCTXT_ID_SEPARATOR '\004'
+
+static const char *pgettext_impl(const char *, const char *, const char *,
+ const char *, unsigned long int, int);
+static char *concatenate_ctxt_id(const char *, const char *);
static const char *lookup_category(int);
static const char *split_locale(const char *);
static const char *lookup_mofile(char *, size_t, const char *, const char *,
@@ -105,6 +115,73 @@ dngettext(const char *domainname, const char *msgid1, const char *msgid2,
return dcngettext(domainname, msgid1, msgid2, n, LC_MESSAGES);
}
+const char *
+pgettext(const char *msgctxt, const char *msgid)
+{
+
+ return pgettext_impl(NULL, msgctxt, msgid, NULL, 1UL, LC_MESSAGES);
+}
+
+const char *
+dpgettext(const char *domainname, const char *msgctxt, const char *msgid)
+{
+
+ return pgettext_impl(domainname, msgctxt, msgid, NULL, 1UL, LC_MESSAGES);
+}
+
+const char *
+dcpgettext(const char *domainname, const char *msgctxt, const char *msgid,
+ int category)
+{
+
+ return pgettext_impl(domainname, msgctxt, msgid, NULL, 1UL, category);
+}
+
+const char *
+npgettext(const char *msgctxt, const char *msgid1, const char *msgid2,
+ unsigned long int n)
+{
+
+ return pgettext_impl(NULL, msgctxt, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+const char *
+dnpgettext(const char *domainname, const char *msgctxt, const char *msgid1,
+ const char *msgid2, unsigned long int n)
+{
+
+ return pgettext_impl(domainname, msgctxt, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+const char *
+dcnpgettext(const char *domainname, const char *msgctxt, const char *msgid1,
+ const char *msgid2, unsigned long int n, int category)
+{
+
+ return pgettext_impl(domainname, msgctxt, msgid1, msgid2, n, category);
+}
+
+static const char *
+pgettext_impl(const char *domainname, const char *msgctxt, const char *msgid1,
+ const char *msgid2, unsigned long int n, int category)
+{
+ char *msgctxt_id;
+ char *translation;
+ char *p;
+
+ if ((msgctxt_id = concatenate_ctxt_id(msgctxt, msgid1)) == NULL)
+ return msgid1;
+
+ translation = dcngettext(domainname, msgctxt_id,
+ msgid2, n, category);
+ free(msgctxt_id);
+
+ p = strchr(translation, '\004');
+ if (p)
+ return p + 1;
+ return translation;
+}
+
/*
* dcngettext() -
* lookup internationalized message on database locale/category/domainname
@@ -126,6 +203,39 @@ dngettext(const char *domainname, const char *msgid1, const char *msgid2,
* /usr/share/locale! (or we should move those files into /usr/libdata)
*/
+static char *
+concatenate_ctxt_id(const char *msgctxt, const char *msgid)
+{
+ char *ret;
+ size_t msgctxt_id_siz;
+
+ msgctxt_id_siz = strlen(msgctxt) + strlen(msgid) + 2;
+ ret = malloc(msgctxt_id_siz);
+
+ if (!ret)
+ return ret;
+
+ // if truncation occurs, integer overflow happened; abort
+ if (strlcpy(ret, msgctxt, msgctxt_id_siz) >= msgctxt_id_siz) {
+ free(ret);
+ return NULL;
+ }
+
+ if (strlen(ret) + 2 > msgctxt_id_siz) {
+ free(ret);
+ return NULL;
+ }
+
+ ret[strlen(msgctxt)] = MSGCTXT_ID_SEPARATOR;
+
+ if (strlcat(ret, msgid, msgctxt_id_siz) >= msgctxt_id_siz) {
+ free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
static const char *
lookup_category(int category)
{
diff --git a/src/lib/libintl/libintl.h b/src/lib/libintl/libintl.h
index 39f53b8..0c045f4 100644
--- a/src/lib/libintl/libintl.h
+++ b/src/lib/libintl/libintl.h
@@ -31,6 +31,18 @@
#include <sys/cdefs.h>
+#define pgettext_expr(msgctxt, msgid) pgettext((msgctxt), (msgid))
+#define dpggettext_expr(domainname, msgctxt, msgid) \
+ dpgettext((domainname), (msgctxt), (msgid))
+#define dcpgettext_expr(domainname, msgctxt, msgid, category) \
+ dcpgettext((domainname), (msgctxt), (msgid), (category))
+#define npgettext_expr(msgctxt, msgid1, msgid2, n) \
+ npgettext((msgctxt), (msgid1), (msgid2), (n))
+#define dnpgettext_expr(domainname, msgctxt, msgid1, n) \
+ dnpgettext((domainname), (msgctxt), (msgid1), (msgid2), (n))
+#define dcnpgettext_expr(domainname, msgctxt, msgid1, msgid2, n, category) \
+ dcnpgettext((domainname), (msgctxt), (msgid1), (msgid2), (n), (category))
+
__BEGIN_DECLS
char *gettext(const char *) __format_arg(1);
char *dgettext(const char *, const char *) __format_arg(2);
@@ -41,6 +53,15 @@ char *dngettext(const char *, const char *, const char *, unsigned long int)
__format_arg(2) __format_arg(3);
char *dcngettext(const char *, const char *, const char *, unsigned long int,
int) __format_arg(2) __format_arg(3);
+const char *pgettext(const char *, const char *) __format_arg(2);
+const char *dpgettext(const char *, const char *, const char *) __format_arg(3);
+const char *dcpgettext(const char *, const char *, const char *, int) __format_arg(3);
+const char *npgettext(const char *, const char *, const char *,
+ unsigned long int) __format_arg(2) __format_arg(3);
+const char *dnpgettext(const char *, const char *, const char *,
+ const char *, unsigned long int) __format_arg(3) __format_arg(4);
+const char *dcnpgettext(const char *, const char *, const char *,
+ const char *, unsigned long int, int) __format_arg(3) __format_arg(4);
char *textdomain(const char *);
char *bindtextdomain(const char *, const char *);
--
2.1.0
Home |
Main Index |
Thread Index |
Old Index