-/*
- * "$Id$"
- *
- * HTTP-based translation program for CUPS.
- *
- * This program uses Google to translate the CUPS template (cups.pot) to
- * several different languages. The translation isn't perfect, but it's
- * a start (better than working from scratch.)
- *
- * Copyright 2007-2010 by Apple Inc.
- * Copyright 1997-2006 by Easy Software Products.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file. If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * Contents:
- *
- * main() - Main entry.
- * save_messages() - Save messages to a .po file.
- * translate_messages() - Translate messages using Google.
- * write_string() - Write a quoted string to a file.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include <cups/cups-private.h>
-#include <unistd.h>
-
-
-/*
- * Local functions...
- */
-
-int save_messages(cups_array_t *cat, const char *filename);
-int translate_messages(cups_array_t *cat, const char *lang);
-int write_string(cups_file_t *fp, const char *s);
-
-
-/*
- * 'main()' - Main entry.
- */
-
-int /* O - Exit status */
-main(int argc, /* I - Number of command-line arguments */
- char *argv[]) /* I - Command-line arguments */
-{
- cups_array_t *cat; /* Message catalog */
-
-
- if (argc != 3)
- {
- fputs("Usage: translate cups_language.po language\n", stderr);
- return (1);
- }
-
- if (access(argv[1], 0))
- cat = _cupsMessageLoad("cups.pot", 1);
- else
- cat = _cupsMessageLoad(argv[1], 1);
-
- if (!cat)
- {
- puts("Unable to load message catalog.");
- return (1);
- }
-
- if (!translate_messages(cat, argv[2]))
- {
- puts("Unable to translate message catalog.");
- return (1);
- }
-
- if (!save_messages(cat, argv[1]))
- {
- puts("Unable to save message catalog.");
- return (1);
- }
-
- return (0);
-}
-
-
-/*
- * 'save_messages()' - Save messages to a .po file.
- */
-
-int /* O - 1 on success, 0 on error */
-save_messages(cups_array_t *cat, /* I - Message catalog */
- const char *filename) /* I - File to save to */
-{
- _cups_message_t *m; /* Current message */
- cups_file_t *fp; /* File pointer */
-
-
- /*
- * Open the message catalog...
- */
-
- if ((fp = cupsFileOpen(filename, "w")) == NULL)
- return (0);
-
- /*
- * Save the messages to a file...
- */
-
- for (m = (_cups_message_t *)cupsArrayFirst(cat);
- m;
- m = (_cups_message_t *)cupsArrayNext(cat))
- {
- if (cupsFilePuts(fp, "msgid \"") < 0)
- break;
-
- if (!write_string(fp, m->id))
- break;
-
- if (cupsFilePuts(fp, "\"\nmsgstr \"") < 0)
- break;
-
- if (m->str)
- {
- if (!write_string(fp, m->str))
- break;
- }
-
- if (cupsFilePuts(fp, "\"\n") < 0)
- break;
- }
-
- cupsFileClose(fp);
-
- return (!m);
-}
-
-
-/*
- * 'translate_messages()' - Translate messages using Google.
- */
-
-int /* O - 1 on success, 0 on error */
-translate_messages(cups_array_t *cat, /* I - Message catalog */
- const char *lang) /* I - Output language... */
-{
- /*
- * Google provides a simple translation/language tool for translating
- * from one language to another. It is far from perfect, however it
- * can be used to get a basic translation done or update an existing
- * translation when no other resources are available.
- *
- * Translation requests are sent as HTTP POSTs to
- * "http://translate.google.com/translate_t" with the following form
- * variables:
- *
- * Name Description Value
- * -------- ---------------------------------- ----------------
- * hl Help language? "en"
- * ie Input encoding "UTF8"
- * langpair Language pair "en|" + language
- * oe Output encoding "UTF8"
- * text Text to translate translation string
- */
-
- int ret; /* Return value */
- _cups_message_t *m; /* Current message */
- int tries; /* Number of tries... */
- http_t *http; /* HTTP connection */
- http_status_t status; /* Status of POST request */
- char *idptr, /* Pointer into msgid */
- buffer[65536], /* Input/output buffer */
- *bufptr, /* Pointer into buffer */
- *bufend, /* Pointer to end of buffer */
- length[16]; /* Content length */
- int bytes; /* Number of bytes read */
-
-
- /*
- * Connect to translate.google.com...
- */
-
- puts("Connecting to translate.google.com...");
-
- if ((http = httpConnect("translate.google.com", 80)) == NULL)
- {
- perror("Unable to connect to translate.google.com");
- return (0);
- }
-
- /*
- * Scan the current messages, requesting a translation of any untranslated
- * messages...
- */
-
- for (m = (_cups_message_t *)cupsArrayFirst(cat), ret = 1;
- m;
- m = (_cups_message_t *)cupsArrayNext(cat))
- {
- /*
- * Skip messages that are already translated...
- */
-
- if (m->str && m->str[0])
- continue;
-
- /*
- * Encode the form data into the buffer...
- */
-
- snprintf(buffer, sizeof(buffer),
- "hl=en&ie=UTF8&langpair=en|%s&oe=UTF8&text=", lang);
- bufptr = buffer + strlen(buffer);
- bufend = buffer + sizeof(buffer) - 5;
-
- for (idptr = m->id; *idptr && bufptr < bufend; idptr ++)
- if (*idptr == ' ')
- *bufptr++ = '+';
- else if (*idptr < ' ' || *idptr == '%')
- {
- sprintf(bufptr, "%%%02X", *idptr & 255);
- bufptr += 3;
- }
- else if (*idptr != '&')
- *bufptr++ = *idptr;
-
- *bufptr++ = '&';
- *bufptr = '\0';
-
- sprintf(length, "%d", (int)(bufptr - buffer));
-
- /*
- * Send the request...
- */
-
- printf("\"%s\" = ", m->id);
- fflush(stdout);
-
- tries = 0;
-
- do
- {
- httpClearFields(http);
- httpSetField(http, HTTP_FIELD_CONTENT_TYPE,
- "application/x-www-form-urlencoded");
- httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);
-
- if (httpPost(http, "/translate_t"))
- {
- httpReconnect(http);
- httpPost(http, "/translate_t");
- }
-
- httpWrite2(http, buffer, bufptr - buffer);
-
- while ((status = httpUpdate(http)) == HTTP_CONTINUE);
-
- if (status != HTTP_OK && status != HTTP_ERROR)
- httpFlush(http);
-
- tries ++;
- }
- while (status == HTTP_ERROR && tries < 10);
-
- if (status == HTTP_OK)
- {
- /*
- * OK, read the translation back...
- */
-
- bufptr = buffer;
- bufend = buffer + sizeof(buffer) - 1;
-
- while ((bytes = httpRead2(http, bufptr, bufend - bufptr)) > 0)
- bufptr += bytes;
-
- if (bytes < 0)
- {
- /*
- * Read error, abort!
- */
-
- puts("READ ERROR!");
- ret = 0;
- break;
- }
-
- *bufptr = '\0';
-
- /*
- * Find the div containing translation
- */
-
- if ((bufptr = strstr(buffer, "<div id=result_box")) == NULL)
- {
- /*
- * No textarea, abort!
- */
-
- puts("NO div id=result_box!");
- ret = 0;
- break;
- }
-
- if ((bufptr = strchr(bufptr, '>')) == NULL)
- {
- /*
- * textarea doesn't end, abort!
- */
-
- puts("DIV SHORT DATA!");
- ret = 0;
- break;
- }
-
- bufptr ++;
-
- if ((bufend = strstr(bufptr, "</div>")) == NULL)
- {
- /*
- * textarea doesn't close, abort!
- */
-
- puts("/DIV SHORT DATA!");
- ret = 0;
- break;
- }
-
- *bufend = '\0';
-
- /*
- * Copy the translation...
- */
-
- m->str = strdup(bufptr);
-
- /*
- * Convert character entities to regular chars...
- */
-
- for (bufptr = strchr(m->str, '&');
- bufptr;
- bufptr = strchr(bufptr + 1, '&'))
- {
- if (!strncmp(bufptr, "<", 4))
- {
- *bufptr = '<';
- _cups_strcpy(bufptr + 1, bufptr + 4);
- }
- else if (!strncmp(bufptr, ">", 4))
- {
- *bufptr = '>';
- _cups_strcpy(bufptr + 1, bufptr + 4);
- }
- else if (!strncmp(bufptr, "&", 5))
- _cups_strcpy(bufptr + 1, bufptr + 5);
- }
-
- printf("\"%s\"\n", m->str);
- }
- else if (status == HTTP_ERROR)
- {
- printf("NETWORK ERROR (%s)!\n", strerror(httpError(http)));
- ret = 0;
- break;
- }
- else
- {
- printf("HTTP ERROR %d!\n", status);
- ret = 0;
- break;
- }
- }
-
- httpClose(http);
-
- return (ret);
-}
-
-
-/*
- * 'write_string()' - Write a quoted string to a file.
- */
-
-int /* O - 1 on success, 0 on failure */
-write_string(cups_file_t *fp, /* I - File to write to */
- const char *s) /* I - String */
-{
- while (*s)
- {
- switch (*s)
- {
- case '\n' :
- if (cupsFilePuts(fp, "\\n") < 0)
- return (0);
- break;
-
- case '\r' :
- if (cupsFilePuts(fp, "\\r") < 0)
- return (0);
- break;
-
- case '\t' :
- if (cupsFilePuts(fp, "\\t") < 0)
- return (0);
- break;
-
- case '\\' :
- if (cupsFilePuts(fp, "\\\\") < 0)
- return (0);
- break;
-
- case '\"' :
- if (cupsFilePuts(fp, "\\\"") < 0)
- return (0);
- break;
-
- default :
- if ((*s & 255) < ' ')
- {
- if (cupsFilePrintf(fp, "\\%o", *s) < 0)
- return (0);
- }
- else if (cupsFilePutChar(fp, *s) < 0)
- return (0);
- break;
- }
-
- s ++;
- }
-
- return (1);
-}
-
-
-/*
- * End of "$Id$".
- */