Beispiel #1
0
int					/* O - Exit code */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  FILE			*strings;	/* .strings file */
  cups_array_t		*po;		/* .po file */
  char			iconv[1024];	/* iconv command */
  _cups_message_t	*msg;		/* Current message */


  if (argc != 3)
  {
    puts("Usage: po2strings filename.po filename.strings");
    return (1);
  }

 /*
  * Use the CUPS .po loader to get the message strings...
  */

  if ((po = _cupsMessageLoad(argv[1])) == NULL)
  {
    perror(argv[1]);
    return (1);
  }

 /*
  * Cheat by using iconv to write the .strings file with a UTF-16 encoding.
  * The .po file uses UTF-8...
  */

  snprintf(iconv, sizeof(iconv), "iconv -f utf-8 -t utf-16 >'%s'", argv[2]);
  if ((strings = popen(iconv, "w")) == NULL)
  {
    perror(argv[2]);
    _cupsMessageFree(po);
    return (1);
  }

  for (msg = (_cups_message_t *)cupsArrayFirst(po);
       msg;
       msg = (_cups_message_t *)cupsArrayNext(po))
  {
    write_string(strings, msg->id);
    fputs(" = ", strings);
    write_string(strings, msg->str);
    fputs(";\n", strings);
  }

  printf("%s: %d messages.\n", argv[2], cupsArrayCount(po));

  pclose(strings);
  _cupsMessageFree(po);

  return (0);
}
Beispiel #2
0
void
cupsLangFlush(void)
{
  cups_lang_t	*lang,			/* Current language */
		*next;			/* Next language */


 /*
  * Free all languages in the cache...
  */

  _cupsMutexLock(&lang_mutex);

  for (lang = lang_cache; lang != NULL; lang = next)
  {
   /*
    * Free all messages...
    */

    _cupsMessageFree(lang->strings);

   /*
    * Then free the language structure itself...
    */

    next = lang->next;
    free(lang);
  }

  lang_cache = NULL;

  _cupsMutexUnlock(&lang_mutex);
}
Beispiel #3
0
cups_lang_t *				/* O - Language data */
cupsLangGet(const char *language)	/* I - Language or locale */
{
  int			i;		/* Looping var */
#ifndef __APPLE__
  char			locale[255];	/* Copy of locale name */
#endif /* !__APPLE__ */
  char			langname[16],	/* Requested language name */
			country[16],	/* Country code */
			charset[16],	/* Character set */
			*csptr,		/* Pointer to CODESET string */
			*ptr,		/* Pointer into language/charset */
			real[48];	/* Real language name */
  cups_encoding_t	encoding;	/* Encoding to use */
  cups_lang_t		*lang;		/* Current language... */
  static const char * const locale_encodings[] =
		{			/* Locale charset names */
		  "ASCII",	"ISO88591",	"ISO88592",	"ISO88593",
		  "ISO88594",	"ISO88595",	"ISO88596",	"ISO88597",
		  "ISO88598",	"ISO88599",	"ISO885910",	"UTF8",
		  "ISO885913",	"ISO885914",	"ISO885915",	"CP874",
		  "CP1250",	"CP1251",	"CP1252",	"CP1253",
		  "CP1254",	"CP1255",	"CP1256",	"CP1257",
		  "CP1258",	"KOI8R",	"KOI8U",	"ISO885911",
		  "ISO885916",	"MACROMAN",	"",		"",

		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",

		  "CP932",	"CP936",	"CP949",	"CP950",
		  "CP1361",	"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",

		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",
		  "",		"",		"",		"",

		  "EUCCN",	"EUCJP",	"EUCKR",	"EUCTW",
		  "SHIFT_JISX0213"
		};


  DEBUG_printf(("2cupsLangGet(language=\"%s\")", language));

#ifdef __APPLE__
 /*
  * Set the character set to UTF-8...
  */

  strlcpy(charset, "UTF8", sizeof(charset));

 /*
  * Apple's setlocale doesn't give us the user's localization
  * preference so we have to look it up this way...
  */

  if (!language)
  {
    if (!getenv("SOFTWARE") || (language = getenv("LANG")) == NULL)
      language = appleLangDefault();

    DEBUG_printf(("4cupsLangGet: language=\"%s\"", language));
  }

#else
 /*
  * Set the charset to "unknown"...
  */

  charset[0] = '\0';

 /*
  * Use setlocale() to determine the currently set locale, and then
  * fallback to environment variables to avoid setting the locale,
  * since setlocale() is not thread-safe!
  */

  if (!language)
  {
   /*
    * First see if the locale has been set; if it is still "C" or
    * "POSIX", use the environment to get the default...
    */

#  ifdef LC_MESSAGES
    ptr = setlocale(LC_MESSAGES, NULL);
#  else
    ptr = setlocale(LC_ALL, NULL);
#  endif /* LC_MESSAGES */

    DEBUG_printf(("4cupsLangGet: current locale is \"%s\"", ptr));

    if (!ptr || !strcmp(ptr, "C") || !strcmp(ptr, "POSIX"))
    {
     /*
      * Get the character set from the LC_CTYPE locale setting...
      */

      if ((ptr = getenv("LC_CTYPE")) == NULL)
        if ((ptr = getenv("LC_ALL")) == NULL)
	  if ((ptr = getenv("LANG")) == NULL)
	    ptr = "en_US";

      if ((csptr = strchr(ptr, '.')) != NULL)
      {
       /*
        * Extract the character set from the environment...
	*/

	for (ptr = charset, csptr ++; *csptr; csptr ++)
	  if (ptr < (charset + sizeof(charset) - 1) && _cups_isalnum(*csptr))
	    *ptr++ = *csptr;

        *ptr = '\0';
      }

     /*
      * Get the locale for messages from the LC_MESSAGES locale setting...
      */

      if ((ptr = getenv("LC_MESSAGES")) == NULL)
        if ((ptr = getenv("LC_ALL")) == NULL)
	  if ((ptr = getenv("LANG")) == NULL)
	    ptr = "en_US";
    }

    if (ptr)
    {
      strlcpy(locale, ptr, sizeof(locale));
      language = locale;

     /*
      * CUPS STR #2575: Map "nb" to "no" for back-compatibility...
      */

      if (!strncmp(locale, "nb", 2))
        locale[1] = 'o';

      DEBUG_printf(("4cupsLangGet: new language value is \"%s\"", language));
    }
  }
#endif /* __APPLE__ */

 /*
  * If "language" is NULL at this point, then chances are we are using
  * a language that is not installed for the base OS.
  */

  if (!language)
  {
   /*
    * Switch to the POSIX ("C") locale...
    */

    language = "C";
  }

#ifdef CODESET
 /*
  * On systems that support the nl_langinfo(CODESET) call, use
  * this value as the character set...
  */

  if (!charset[0] && (csptr = nl_langinfo(CODESET)) != NULL)
  {
   /*
    * Copy all of the letters and numbers in the CODESET string...
    */

    for (ptr = charset; *csptr; csptr ++)
      if (_cups_isalnum(*csptr) && ptr < (charset + sizeof(charset) - 1))
        *ptr++ = *csptr;

    *ptr = '\0';

    DEBUG_printf(("4cupsLangGet: charset set to \"%s\" via "
                  "nl_langinfo(CODESET)...", charset));
  }
#endif /* CODESET */

 /*
  * If we don't have a character set by now, default to UTF-8...
  */

  if (!charset[0])
    strlcpy(charset, "UTF8", sizeof(charset));

 /*
  * Parse the language string passed in to a locale string. "C" is the
  * standard POSIX locale and is copied unchanged.  Otherwise the
  * language string is converted from ll-cc[.charset] (language-country)
  * to ll_CC[.CHARSET] to match the file naming convention used by all
  * POSIX-compliant operating systems.  Invalid language names are mapped
  * to the POSIX locale.
  */

  country[0] = '\0';

  if (language == NULL || !language[0] ||
      !strcmp(language, "POSIX"))
    strlcpy(langname, "C", sizeof(langname));
  else
  {
   /*
    * Copy the parts of the locale string over safely...
    */

    for (ptr = langname; *language; language ++)
      if (*language == '_' || *language == '-' || *language == '.')
	break;
      else if (ptr < (langname + sizeof(langname) - 1))
        *ptr++ = (char)tolower(*language & 255);

    *ptr = '\0';

    if (*language == '_' || *language == '-')
    {
     /*
      * Copy the country code...
      */

      for (language ++, ptr = country; *language; language ++)
	if (*language == '.')
	  break;
	else if (ptr < (country + sizeof(country) - 1))
          *ptr++ = (char)toupper(*language & 255);

      *ptr = '\0';
    }

    if (*language == '.' && !charset[0])
    {
     /*
      * Copy the encoding...
      */

      for (language ++, ptr = charset; *language; language ++)
        if (_cups_isalnum(*language) && ptr < (charset + sizeof(charset) - 1))
          *ptr++ = (char)toupper(*language & 255);

      *ptr = '\0';
    }

   /*
    * Force a POSIX locale for an invalid language name...
    */

    if (strlen(langname) != 2)
    {
      strlcpy(langname, "C", sizeof(langname));
      country[0] = '\0';
      charset[0] = '\0';
    }
  }

  DEBUG_printf(("4cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"",
                langname, country, charset));

 /*
  * Figure out the desired encoding...
  */

  encoding = CUPS_AUTO_ENCODING;

  if (charset[0])
  {
    for (i = 0;
         i < (int)(sizeof(locale_encodings) / sizeof(locale_encodings[0]));
	 i ++)
      if (!_cups_strcasecmp(charset, locale_encodings[i]))
      {
	encoding = (cups_encoding_t)i;
	break;
      }

    if (encoding == CUPS_AUTO_ENCODING)
    {
     /*
      * Map alternate names for various character sets...
      */

      if (!_cups_strcasecmp(charset, "iso-2022-jp") ||
          !_cups_strcasecmp(charset, "sjis"))
	encoding = CUPS_WINDOWS_932;
      else if (!_cups_strcasecmp(charset, "iso-2022-cn"))
	encoding = CUPS_WINDOWS_936;
      else if (!_cups_strcasecmp(charset, "iso-2022-kr"))
	encoding = CUPS_WINDOWS_949;
      else if (!_cups_strcasecmp(charset, "big5"))
	encoding = CUPS_WINDOWS_950;
    }
  }

  DEBUG_printf(("4cupsLangGet: encoding=%d(%s)", encoding,
                encoding == CUPS_AUTO_ENCODING ? "auto" :
		    lang_encodings[encoding]));

 /*
  * See if we already have this language/country loaded...
  */

  if (country[0])
    snprintf(real, sizeof(real), "%s_%s", langname, country);
  else
    strlcpy(real, langname, sizeof(real));

  _cupsMutexLock(&lang_mutex);

  if ((lang = cups_cache_lookup(real, encoding)) != NULL)
  {
    _cupsMutexUnlock(&lang_mutex);

    DEBUG_printf(("3cupsLangGet: Using cached copy of \"%s\"...", real));

    return (lang);
  }

 /*
  * See if there is a free language available; if so, use that
  * record...
  */

  for (lang = lang_cache; lang != NULL; lang = lang->next)
    if (lang->used == 0)
      break;

  if (lang == NULL)
  {
   /*
    * Allocate memory for the language and add it to the cache.
    */

    if ((lang = calloc(sizeof(cups_lang_t), 1)) == NULL)
    {
      _cupsMutexUnlock(&lang_mutex);

      return (NULL);
    }

    lang->next = lang_cache;
    lang_cache = lang;
  }
  else
  {
   /*
    * Free all old strings as needed...
    */

    _cupsMessageFree(lang->strings);
    lang->strings = NULL;
  }

 /*
  * Then assign the language and encoding fields...
  */

  lang->used ++;
  strlcpy(lang->language, real, sizeof(lang->language));

  if (encoding != CUPS_AUTO_ENCODING)
    lang->encoding = encoding;
  else
    lang->encoding = CUPS_UTF8;

 /*
  * Return...
  */

  _cupsMutexUnlock(&lang_mutex);

  return (lang);
}
int					/* O - Exit code */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int			i;		/* Looping var */
  cups_array_t		*po;		/* .po file */
  _cups_message_t	*msg;		/* Current message */
  cups_array_t		*idfmts,	/* Format strings in msgid */
			*strfmts;	/* Format strings in msgstr */
  char			*idfmt,		/* Current msgid format string */
			*strfmt;	/* Current msgstr format string */
  int			fmtidx;		/* Format index */
  int			status,		/* Exit status */
			pass,		/* Pass/fail status */
			untranslated;	/* Untranslated messages */
  char			idbuf[80],	/* Abbreviated msgid */
			strbuf[80];	/* Abbreviated msgstr */


  if (argc < 2)
  {
    puts("Usage: checkpo filename.po [... filenameN.po]");
    return (1);
  }

 /*
  * Check every .po file on the command-line...
  */

  for (i = 1, status = 0; i < argc; i ++)
  {
   /*
    * Use the CUPS .po loader to get the message strings...
    */

    if ((po = _cupsMessageLoad(argv[i], 1)) == NULL)
    {
      perror(argv[i]);
      return (1);
    }

    if (i > 1)
      putchar('\n');
    printf("%s: ", argv[i]);
    fflush(stdout);

   /*
    * Scan every message for a % string and then match them up with
    * the corresponding string in the translation...
    */

    pass         = 1;
    untranslated = 0;

    for (msg = (_cups_message_t *)cupsArrayFirst(po);
         msg;
	 msg = (_cups_message_t *)cupsArrayNext(po))
    {
     /*
      * Make sure filter message prefixes are not translated...
      */

      if (!strncmp(msg->id, "ALERT:", 6) || !strncmp(msg->id, "CRIT:", 5) ||
          !strncmp(msg->id, "DEBUG:", 6) || !strncmp(msg->id, "DEBUG2:", 7) ||
          !strncmp(msg->id, "EMERG:", 6) || !strncmp(msg->id, "ERROR:", 6) ||
          !strncmp(msg->id, "INFO:", 5) || !strncmp(msg->id, "NOTICE:", 7) ||
          !strncmp(msg->id, "WARNING:", 8))
      {
        if (pass)
	{
	  pass = 0;
	  puts("FAIL");
	}

	printf("    Bad prefix on filter message \"%s\"\n",
	       abbreviate(msg->id, idbuf, sizeof(idbuf)));
      }

      idfmt = msg->id + strlen(msg->id) - 1;
      if (idfmt >= msg->id && *idfmt == '\n')
      {
        if (pass)
	{
	  pass = 0;
	  puts("FAIL");
	}

	printf("    Trailing newline in message \"%s\"\n",
	       abbreviate(msg->id, idbuf, sizeof(idbuf)));
      }

      for (; idfmt >= msg->id; idfmt --)
        if (!isspace(*idfmt & 255))
	  break;

      if (idfmt >= msg->id && *idfmt == '!')
      {
        if (pass)
	{
	  pass = 0;
	  puts("FAIL");
	}

	printf("    Exclamation in message \"%s\"\n",
	       abbreviate(msg->id, idbuf, sizeof(idbuf)));
      }

      if ((idfmt - 2) >= msg->id && !strncmp(idfmt - 2, "...", 3))
      {
        if (pass)
	{
	  pass = 0;
	  puts("FAIL");
	}

	printf("    Ellipsis in message \"%s\"\n",
	       abbreviate(msg->id, idbuf, sizeof(idbuf)));
      }


      if (!msg->str || !msg->str[0])
      {
        untranslated ++;
	continue;
      }
      else if (strchr(msg->id, '%'))
      {
        idfmts  = collect_formats(msg->id);
	strfmts = collect_formats(msg->str);
	fmtidx  = 0;

        for (strfmt = (char *)cupsArrayFirst(strfmts);
	     strfmt;
	     strfmt = (char *)cupsArrayNext(strfmts))
	{
	  if (isdigit(strfmt[1] & 255) && strfmt[2] == '$')
	  {
	   /*
	    * Handle positioned format stuff...
	    */

            fmtidx = strfmt[1] - '1';
            strfmt += 3;
	    if ((idfmt = (char *)cupsArrayIndex(idfmts, fmtidx)) != NULL)
	      idfmt ++;
	  }
	  else
	  {
	   /*
	    * Compare against the current format...
	    */

	    idfmt = (char *)cupsArrayIndex(idfmts, fmtidx);
          }

	  fmtidx ++;

	  if (!idfmt || strcmp(strfmt, idfmt))
	    break;
	}

        if (cupsArrayCount(strfmts) != cupsArrayCount(idfmts) || strfmt)
	{
	  if (pass)
	  {
	    pass = 0;
	    puts("FAIL");
	  }

	  printf("    Bad translation string \"%s\"\n        for \"%s\"\n",
	         abbreviate(msg->str, strbuf, sizeof(strbuf)),
		 abbreviate(msg->id, idbuf, sizeof(idbuf)));
          fputs("    Translation formats:", stdout);
	  for (strfmt = (char *)cupsArrayFirst(strfmts);
	       strfmt;
	       strfmt = (char *)cupsArrayNext(strfmts))
	    printf(" %s", strfmt);
          fputs("\n    Original formats:", stdout);
	  for (idfmt = (char *)cupsArrayFirst(idfmts);
	       idfmt;
	       idfmt = (char *)cupsArrayNext(idfmts))
	    printf(" %s", idfmt);
          putchar('\n');
          putchar('\n');
	}

	free_formats(idfmts);
	free_formats(strfmts);
      }

     /*
      * Only allow \\, \n, \r, \t, \", and \### character escapes...
      */

      for (strfmt = msg->str; *strfmt; strfmt ++)
        if (*strfmt == '\\' &&
	    strfmt[1] != '\\' && strfmt[1] != 'n' && strfmt[1] != 'r' &&
	    strfmt[1] != 't' && strfmt[1] != '\"' && !isdigit(strfmt[1] & 255))
	{
	  if (pass)
	  {
	    pass = 0;
	    puts("FAIL");
	  }

	  printf("    Bad escape \\%c in filter message \"%s\"\n"
	         "      for \"%s\"\n", strfmt[1],
		 abbreviate(msg->str, strbuf, sizeof(strbuf)),
		 abbreviate(msg->id, idbuf, sizeof(idbuf)));
          break;
        }
    }

    if (pass)
    {
      if ((untranslated * 10) >= cupsArrayCount(po) &&
          strcmp(argv[i], "cups.pot"))
      {
       /*
        * Only allow 10% of messages to be untranslated before we fail...
	*/

        pass = 0;
        puts("FAIL");
	printf("    Too many untranslated messages (%d of %d)\n",
	       untranslated, cupsArrayCount(po));
      }
      else if (untranslated > 0)
        printf("PASS (%d of %d untranslated)\n", untranslated,
	       cupsArrayCount(po));
      else
        puts("PASS");
    }

    if (!pass)
      status = 1;

    _cupsMessageFree(po);
  }

  return (status);
}