1 /* Localization of proper names. 2 Copyright (C) 2006 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 2, or (at your option) 8 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, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 19 #include <config.h> 20 21 /* Specification. */ 22 #include "propername.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #if HAVE_ICONV 28 # include <iconv.h> 29 #endif 30 31 #include "localcharset.h" 32 #include "c-strcase.h" 33 #include "xstriconv.h" 34 #include "c-strstr.h" 35 #include "strstr.h" 36 #include "xalloc.h" 37 #include "gettext.h" 38 39 40 /* Return the localization of NAME. NAME is written in ASCII. */ 41 42 const char * 43 proper_name (const char *name) 44 { 45 /* See whether there is a translation. */ 46 const char *translation = gettext (name); 47 48 if (translation != name) 49 { 50 /* See whether the translation contains the original name. */ 51 if (strstr (translation, name) != NULL) 52 return translation; 53 else 54 { 55 /* Return "TRANSLATION (NAME)". */ 56 char *result = 57 (char *) xmalloc (strlen (translation) + 2 + strlen (name) + 1 + 1); 58 59 sprintf (result, "%s (%s)", translation, name); 60 return result; 61 } 62 } 63 else 64 return name; 65 } 66 67 /* Return the localization of a name whose original writing is not ASCII. 68 NAME_UTF8 is the real name, written in UTF-8 with octal or hexadecimal 69 escape sequences. NAME_ASCII is a fallback written only with ASCII 70 characters. */ 71 72 const char * 73 proper_name_utf8 (const char *name_ascii, const char *name_utf8) 74 { 75 /* See whether there is a translation. */ 76 const char *translation = gettext (name_ascii); 77 78 /* Try to convert NAME_UTF8 to the locale encoding. */ 79 const char *locale_code = locale_charset (); 80 char *alloc_name_converted = NULL; 81 char *alloc_name_converted_translit = NULL; 82 const char *name_converted = NULL; 83 const char *name_converted_translit = NULL; 84 const char *name; 85 86 if (c_strcasecmp (locale_code, "UTF-8") != 0) 87 { 88 #if HAVE_ICONV 89 name_converted = alloc_name_converted = 90 xstr_iconv (name_utf8, "UTF-8", locale_code); 91 92 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ 93 || _LIBICONV_VERSION >= 0x0105 94 { 95 size_t len = strlen (locale_code); 96 char *locale_code_translit = (char *) xmalloc (len + 10 + 1); 97 memcpy (locale_code_translit, locale_code, len); 98 memcpy (locale_code_translit + len, "//TRANSLIT", 10 + 1); 99 100 name_converted_translit = alloc_name_converted_translit = 101 xstr_iconv (name_utf8, "UTF-8", locale_code_translit); 102 103 free (locale_code_translit); 104 } 105 # endif 106 #endif 107 } 108 else 109 { 110 name_converted = name_utf8; 111 name_converted_translit = name_utf8; 112 } 113 114 /* The name in locale encoding. */ 115 name = (name_converted != NULL ? name_converted : 116 name_converted_translit != NULL ? name_converted_translit : 117 name_ascii); 118 119 if (translation != name_ascii) 120 { 121 /* See whether the translation contains the original name. 122 A multibyte-aware strstr() is not absolutely necessary here. */ 123 if (c_strstr (translation, name_ascii) != NULL 124 || (name_converted != NULL 125 && strstr (translation, name_converted) != NULL) 126 || (name_converted_translit != NULL 127 && strstr (translation, name_converted_translit) != NULL)) 128 { 129 if (alloc_name_converted != NULL) 130 free (alloc_name_converted); 131 if (alloc_name_converted_translit != NULL) 132 free (alloc_name_converted_translit); 133 return translation; 134 } 135 else 136 { 137 /* Return "TRANSLATION (NAME)". */ 138 char *result = 139 (char *) xmalloc (strlen (translation) + 2 + strlen (name) + 1 + 1); 140 141 sprintf (result, "%s (%s)", translation, name); 142 143 if (alloc_name_converted != NULL) 144 free (alloc_name_converted); 145 if (alloc_name_converted_translit != NULL) 146 free (alloc_name_converted_translit); 147 return result; 148 } 149 } 150 else 151 { 152 if (alloc_name_converted != NULL && alloc_name_converted != name) 153 free (alloc_name_converted); 154 if (alloc_name_converted_translit != NULL 155 && alloc_name_converted_translit != name) 156 free (alloc_name_converted_translit); 157 return name; 158 } 159 } 160