1/* Localization of proper names. 2 Copyright (C) 2006-2007 Free Software Foundation, Inc. 3 Written by Bruno Haible <bruno@clisp.org>, 2006. 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19 20/* Specification. */ 21#include "propername.h" 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#if HAVE_ICONV 27# include <iconv.h> 28#endif 29 30#include "localcharset.h" 31#include "c-strcase.h" 32#include "xstriconv.h" 33#include "c-strstr.h" 34#include "xalloc.h" 35#include "gettext.h" 36 37 38/* Return the localization of NAME. NAME is written in ASCII. */ 39 40const char * 41proper_name (const char *name) 42{ 43 /* See whether there is a translation. */ 44 const char *translation = gettext (name); 45 46 if (translation != name) 47 { 48 /* See whether the translation contains the original name. */ 49 if (mbsstr (translation, name) != NULL) 50 return translation; 51 else 52 { 53 /* Return "TRANSLATION (NAME)". */ 54 char *result = 55 XNMALLOC (strlen (translation) + 2 + strlen (name) + 1 + 1, char); 56 57 sprintf (result, "%s (%s)", translation, name); 58 return result; 59 } 60 } 61 else 62 return name; 63} 64 65/* Return the localization of a name whose original writing is not ASCII. 66 NAME_UTF8 is the real name, written in UTF-8 with octal or hexadecimal 67 escape sequences. NAME_ASCII is a fallback written only with ASCII 68 characters. */ 69 70const char * 71proper_name_utf8 (const char *name_ascii, const char *name_utf8) 72{ 73 /* See whether there is a translation. */ 74 const char *translation = gettext (name_ascii); 75 76 /* Try to convert NAME_UTF8 to the locale encoding. */ 77 const char *locale_code = locale_charset (); 78 char *alloc_name_converted = NULL; 79 char *alloc_name_converted_translit = NULL; 80 const char *name_converted = NULL; 81 const char *name_converted_translit = NULL; 82 const char *name; 83 84 if (c_strcasecmp (locale_code, "UTF-8") != 0) 85 { 86#if HAVE_ICONV 87 name_converted = alloc_name_converted = 88 xstr_iconv (name_utf8, "UTF-8", locale_code); 89 90# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ 91 || _LIBICONV_VERSION >= 0x0105 92 { 93 size_t len = strlen (locale_code); 94 char *locale_code_translit = XNMALLOC (len + 10 + 1, char); 95 memcpy (locale_code_translit, locale_code, len); 96 memcpy (locale_code_translit + len, "//TRANSLIT", 10 + 1); 97 98 name_converted_translit = alloc_name_converted_translit = 99 xstr_iconv (name_utf8, "UTF-8", locale_code_translit); 100 101 free (locale_code_translit); 102 } 103# endif 104#endif 105 } 106 else 107 { 108 name_converted = name_utf8; 109 name_converted_translit = name_utf8; 110 } 111 112 /* The name in locale encoding. */ 113 name = (name_converted != NULL ? name_converted : 114 name_converted_translit != NULL ? name_converted_translit : 115 name_ascii); 116 117 if (translation != name_ascii) 118 { 119 /* See whether the translation contains the original name. 120 The multibyte-aware mbsstr() is not absolutely necessary here. */ 121 if (c_strstr (translation, name_ascii) != NULL 122 || (name_converted != NULL 123 && mbsstr (translation, name_converted) != NULL) 124 || (name_converted_translit != NULL 125 && mbsstr (translation, name_converted_translit) != NULL)) 126 { 127 if (alloc_name_converted != NULL) 128 free (alloc_name_converted); 129 if (alloc_name_converted_translit != NULL) 130 free (alloc_name_converted_translit); 131 return translation; 132 } 133 else 134 { 135 /* Return "TRANSLATION (NAME)". */ 136 char *result = 137 XNMALLOC (strlen (translation) + 2 + strlen (name) + 1 + 1, char); 138 139 sprintf (result, "%s (%s)", translation, name); 140 141 if (alloc_name_converted != NULL) 142 free (alloc_name_converted); 143 if (alloc_name_converted_translit != NULL) 144 free (alloc_name_converted_translit); 145 return result; 146 } 147 } 148 else 149 { 150 if (alloc_name_converted != NULL && alloc_name_converted != name) 151 free (alloc_name_converted); 152 if (alloc_name_converted_translit != NULL 153 && alloc_name_converted_translit != name) 154 free (alloc_name_converted_translit); 155 return name; 156 } 157} 158