2 * "$Id: translate.c 5261 2006-03-09 20:47:49Z mike $"
4 * HTTP-based translation program for the Common UNIX Printing System (CUPS).
6 * This program uses Google to translate the CUPS template (cups.pot) to
7 * several different languages. The translation isn't perfect, but it's
8 * a start (better than working from scratch.)
10 * Copyright 1997-2006 by Easy Software Products.
12 * These coded instructions, statements, and computer programs are the
13 * property of Easy Software Products and are protected by Federal
14 * copyright law. Distribution and use rights are outlined in the file
15 * "LICENSE.txt" which should have been included with this file. If this
16 * file is missing or damaged please contact Easy Software Products
19 * Attn: CUPS Licensing Information
20 * Easy Software Products
21 * 44145 Airport View Drive, Suite 204
22 * Hollywood, Maryland 20636 USA
24 * Voice: (301) 373-9600
25 * EMail: cups-info@cups.org
26 * WWW: http://www.cups.org
30 * main() - Main entry.
31 * save_messages() - Save messages to a .po file.
32 * translate_messages() - Translate messages using Google.
33 * write_string() - Write a quoted string to a file.
37 * Include necessary headers...
40 #include <cups/string.h>
41 #include <cups/file.h>
42 #include <cups/http.h>
43 #include <cups/i18n.h>
52 int save_messages(cups_array_t
*cat
, const char *filename
);
53 int translate_messages(cups_array_t
*cat
, const char *lang
);
54 int write_string(cups_file_t
*fp
, const char *s
);
58 * 'main()' - Main entry.
61 int /* O - Exit status */
62 main(int argc
, /* I - Number of command-line arguments */
63 char *argv
[]) /* I - Command-line arguments */
65 cups_array_t
*cat
; /* Message catalog */
70 fputs("Usage: translate cups_language.po language\n", stderr
);
74 if (access(argv
[1], 0))
75 cat
= _cupsMessageLoad("cups.pot");
77 cat
= _cupsMessageLoad(argv
[1]);
81 puts("Unable to load message catalog.");
85 if (!translate_messages(cat
, argv
[2]))
87 puts("Unable to translate message catalog.");
91 if (!save_messages(cat
, argv
[1]))
93 puts("Unable to save message catalog.");
102 * 'save_messages()' - Save messages to a .po file.
105 int /* O - 1 on success, 0 on error */
106 save_messages(cups_array_t
*cat
, /* I - Message catalog */
107 const char *filename
) /* I - File to save to */
109 _cups_message_t
*m
; /* Current message */
110 cups_file_t
*fp
; /* File pointer */
114 * Open the message catalog...
117 if ((fp
= cupsFileOpen(filename
, "w")) == NULL
)
121 * Save the messages to a file...
124 for (m
= (_cups_message_t
*)cupsArrayFirst(cat
);
126 m
= (_cups_message_t
*)cupsArrayNext(cat
))
128 if (cupsFilePuts(fp
, "msgid \"") < 0)
131 if (!write_string(fp
, m
->id
))
134 if (cupsFilePuts(fp
, "\"\nmsgstr \"") < 0)
139 if (!write_string(fp
, m
->str
))
143 if (cupsFilePuts(fp
, "\"\n") < 0)
154 * 'translate_messages()' - Translate messages using Google.
157 int /* O - 1 on success, 0 on error */
158 translate_messages(cups_array_t
*cat
, /* I - Message catalog */
159 const char *lang
) /* I - Output language... */
162 * Google provides a simple translation/language tool for translating
163 * from one language to another. It is far from perfect, however it
164 * can be used to get a basic translation done or update an existing
165 * translation when no other resources are available.
167 * Translation requests are sent as HTTP POSTs to
168 * "http://translate.google.com/translate_t" with the following form
171 * Name Description Value
172 * -------- ---------------------------------- ----------------
173 * hl Help language? "en"
174 * ie Input encoding "UTF8"
175 * langpair Language pair "en|" + language
176 * oe Output encoding "UTF8"
177 * text Text to translate translation string
180 int ret
; /* Return value */
181 _cups_message_t
*m
; /* Current message */
182 int tries
; /* Number of tries... */
183 http_t
*http
; /* HTTP connection */
184 http_status_t status
; /* Status of POST request */
185 char *idptr
, /* Pointer into msgid */
186 buffer
[65536], /* Input/output buffer */
187 *bufptr
, /* Pointer into buffer */
188 *bufend
, /* Pointer to end of buffer */
189 length
[16]; /* Content length */
190 int bytes
; /* Number of bytes read */
194 * Connect to translate.google.com...
197 puts("Connecting to translate.google.com...");
199 if ((http
= httpConnect("translate.google.com", 80)) == NULL
)
201 perror("Unable to connect to translate.google.com");
206 * Scan the current messages, requesting a translation of any untranslated
210 for (m
= (_cups_message_t
*)cupsArrayFirst(cat
), ret
= 1;
212 m
= (_cups_message_t
*)cupsArrayNext(cat
))
215 * Skip messages that are already translated...
218 if (m
->str
&& m
->str
[0])
222 * Encode the form data into the buffer...
225 snprintf(buffer
, sizeof(buffer
),
226 "hl=en&ie=UTF8&langpair=en|%s&oe=UTF8&text=", lang
);
227 bufptr
= buffer
+ strlen(buffer
);
228 bufend
= buffer
+ sizeof(buffer
) - 5;
230 for (idptr
= m
->id
; *idptr
&& bufptr
< bufend
; idptr
++)
233 else if (*idptr
< ' ' || *idptr
== '%')
235 sprintf(bufptr
, "%%%02X", *idptr
& 255);
238 else if (*idptr
!= '&')
244 sprintf(length
, "%d", (int)(bufptr
- buffer
));
247 * Send the request...
250 printf("\"%s\" = ", m
->id
);
257 httpClearFields(http
);
258 httpSetField(http
, HTTP_FIELD_CONTENT_TYPE
,
259 "application/x-www-form-urlencoded");
260 httpSetField(http
, HTTP_FIELD_CONTENT_LENGTH
, length
);
262 if (httpPost(http
, "/translate_t"))
265 httpPost(http
, "/translate_t");
268 httpWrite2(http
, buffer
, bufptr
- buffer
);
270 while ((status
= httpUpdate(http
)) == HTTP_CONTINUE
);
272 if (status
!= HTTP_OK
&& status
!= HTTP_ERROR
)
277 while (status
== HTTP_ERROR
&& tries
< 10);
279 if (status
== HTTP_OK
)
282 * OK, read the translation back...
286 bufend
= buffer
+ sizeof(buffer
) - 1;
288 while ((bytes
= httpRead2(http
, bufptr
, bufend
- bufptr
)) > 0)
305 * Find the first textarea element - that will have the translation data...
308 if ((bufptr
= strstr(buffer
, "<textarea")) == NULL
)
311 * No textarea, abort!
314 puts("NO TEXTAREA!");
319 if ((bufptr
= strchr(bufptr
, '>')) == NULL
)
322 * textarea doesn't end, abort!
325 puts("TEXTAREA SHORT DATA!");
332 if ((bufend
= strstr(bufptr
, "</textarea>")) == NULL
)
335 * textarea doesn't close, abort!
338 puts("/TEXTAREA SHORT DATA!");
346 * Copy the translation...
349 m
->str
= strdup(bufptr
);
352 * Convert character entities to regular chars...
355 for (bufptr
= strchr(m
->str
, '&');
357 bufptr
= strchr(bufptr
+ 1, '&'))
359 if (!strncmp(bufptr
, "<", 4))
362 _cups_strcpy(bufptr
+ 1, bufptr
+ 4);
364 else if (!strncmp(bufptr
, ">", 4))
367 _cups_strcpy(bufptr
+ 1, bufptr
+ 4);
369 else if (!strncmp(bufptr
, "&", 5))
370 _cups_strcpy(bufptr
+ 1, bufptr
+ 5);
373 printf("\"%s\"\n", m
->str
);
375 else if (status
== HTTP_ERROR
)
377 printf("NETWORK ERROR (%s)!\n", strerror(httpError(http
)));
383 printf("HTTP ERROR %d!\n", status
);
396 * 'write_string()' - Write a quoted string to a file.
399 int /* O - 1 on success, 0 on failure */
400 write_string(cups_file_t
*fp
, /* I - File to write to */
401 const char *s
) /* I - String */
408 if (cupsFilePuts(fp
, "\\n") < 0)
413 if (cupsFilePuts(fp
, "\\r") < 0)
418 if (cupsFilePuts(fp
, "\\t") < 0)
423 if (cupsFilePuts(fp
, "\\\\") < 0)
428 if (cupsFilePuts(fp
, "\\\"") < 0)
433 if ((*s
& 255) < ' ')
435 if (cupsFilePrintf(fp
, "\\%o", *s
) < 0)
438 else if (cupsFilePutChar(fp
, *s
) < 0)
451 * End of "$Id: translate.c 5261 2006-03-09 20:47:49Z mike $".