Changeset 286156 in webkit
- Timestamp:
- Nov 24, 2021, 5:39:10 PM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 10 edited
-
WebCore/ChangeLog (modified) (1 diff)
-
WebCore/Scripts/extract-localizable-strings.pl (modified) (6 diffs)
-
WebCore/platform/LocalizedStrings.cpp (modified) (27 diffs)
-
WebCore/platform/LocalizedStrings.h (modified) (4 diffs)
-
WebCore/platform/cocoa/LocalizedStringsCocoa.mm (modified) (6 diffs)
-
WebCore/platform/gtk/po/CMakeLists.txt (modified) (1 diff)
-
WebCore/platform/gtk/po/ChangeLog (modified) (1 diff)
-
WebCore/platform/win/LocalizedStringsWin.cpp (modified) (2 diffs)
-
WebKitLegacy/mac/ChangeLog (modified) (1 diff)
-
WebKitLegacy/mac/Misc/WebLocalizableStringsInternal.mm (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r286152 r286156 1 2021-11-24 David Kilzer <ddkilzer@apple.com> 2 3 Compiler should be able to check localized format strings for consistency 4 <https://webkit.org/b/232686> 5 <rdar://problem/84994345> 6 7 Reviewed by Darin Adler. 8 9 The primary goal of this patch is to allow the compiler to check 10 format strings to ensure that the correct number and type of 11 arguments and placeholders are used. The epiphany to make this 12 possible was that Apple platforms may use CFStringRef objects or 13 const char* C-strings to accomplish this with CoreFoundation 14 macros. Non-Apple platforms continue to use const char* for 15 format strings to allow the compiler to check format strings. 16 17 To this end localized strings passed to formatLocalizedString() 18 must use a WEB_UI_FORMAT_*() macro on all platforms. Failure to 19 do so will result in a compiler error, though, since non-FORMAT 20 macros return a WTF::String. 21 22 This patch also eliminates autoreleased NSString objects except 23 when using WEB_UI_NSSTRING()/localizedNSString() directly (the 24 return value is always autoreleased), and it removes the need to 25 convert from CF/NSString -> WTF::String -> CF/NSString for 26 localized format strings. 27 28 * Scripts/extract-localizable-strings.pl: 29 (isFormatMacro): Add. 30 - Add support for parsing the following new macros with variadic 31 parameter lists: 32 o WEB_UI_FORMAT_STRING [cross-platform] 33 o WEB_UI_FORMAT_CFSTRING 34 o WEB_UI_FORMAT_CFSTRING_KEY 35 36 * platform/LocalizedStrings.cpp: 37 (WebCore::formatLocalizedString): 38 - Implement using `CFStringRef format` for Apple platforms, but 39 `const char* format` for other platforms. 40 - Use of these types allows format checking macros to be added 41 to declarations in LocalizedStrings.h. 42 (WebCore::webCoreBundle): Add. 43 - Extract code for getting a CFBundleRef for WebCore.framework 44 into a function that's similar to webKitBundle() on Windows. 45 (WebCore::copyLocalizedString): Add. 46 - This method was converted from localizedNSString() in 47 LocalizedStringsCocoa.mm and from localizedString() in 48 LocalizedStringsWin.cpp. 49 (WebCore::localizedString(CFStringRef)): Add. 50 - Avoids runtime creation of CFStringRef on non-Windows 51 platforms. 52 (WebCore::localizedString(const char*)): 53 - Code for USE(CF) was converted from the same method in 54 LocalizedStringsCocoa.mm, but only used on Windows port. 55 (WebCore::contextMenuItemTagLookUpInDictionary): 56 (WebCore::contextMenuItemTagTranslate): 57 (WebCore::multipleFileUploadText): 58 (WebCore::imageTitle): 59 (WebCore::localizedMediaTimeDescription): 60 (WebCore::validationMessageTooShortText): 61 (WebCore::validationMessageTooLongText): 62 (WebCore::validationMessageRangeUnderflowText): 63 (WebCore::validationMessageRangeOverflowText): 64 (WebCore::addTrackLabelAsSuffix): 65 (WebCore::addTextTrackKindClosedCaptionsSuffix): 66 (WebCore::addTextTrackKindCaptionsSuffix): 67 (WebCore::addTextTrackKindDescriptionsSuffix): 68 (WebCore::addTextTrackKindChaptersSuffix): 69 (WebCore::addTextTrackKindMetadataSuffix): 70 (WebCore::addTextTrackKindSDHSuffix): 71 (WebCore::addTextTrackKindEasyReaderSuffix): 72 (WebCore::addTextTrackKindForcedSuffix): 73 (WebCore::addAudioTrackKindDescriptionsSuffix): 74 (WebCore::addAudioTrackKindCommentarySuffix): 75 (WebCore::webCryptoMasterKeyKeychainLabel): 76 (WebCore::makeCredentialTouchIDPromptTitle): 77 (WebCore::getAssertionTouchIDPromptTitle): 78 - Use WEB_UI_FORMAT_STRING() for cross-platform UI format 79 strings, and use WEB_UI_FORMAT_CFSTRING[_KEY]() for Apple 80 platform UI format strings. 81 - Make formatLocalizedString() an implementation detail of 82 WEB_UI_FORMAT_[CF]STRING() macros. 83 84 * platform/LocalizedStrings.h: 85 (WEB_UI_STRING): Add. 86 (WEB_UI_STRING_KEY): Add. 87 (WEB_UI_STRING_WITH_MNEMONIC): Add. 88 (WEB_UI_CFSTRING): Add. 89 (WEB_UI_CFSTRING_KEY): Add. 90 - Add USE(CF)-specific macros to avoid CFStringRef allocations 91 at runtime. The Apple Windows port can not use these because 92 it uses a default encoding of Mac Roman for CFSTR(). 93 (WEB_UI_FORMAT_STRING): Add. 94 - Cross-platform macro for UI format strings. 95 - Note that non-USE(CF) macros essentially do nothing since 96 localizedString() just converts const char* to WTF::String 97 (which was previously converted back to const char*), and 98 formatLocalizedString() now takes a const char*. 99 (WEB_UI_FORMAT_CFSTRING): Add. 100 (WEB_UI_FORMAT_CFSTRING_KEY): Add. 101 - These macros are used as format string arguments to 102 formatLocalizedString(). 103 (WebCore::localizedFormatString): Add. 104 - Declare a new function for USE(CF) that is passed to 105 formatLocalizedString(). 106 (WebCore::localizedString(CFStringRef)): Add. 107 - Declare a new function for USE(CF) that takes a CFStringRef 108 argument. 109 (WebCore::formatLocalizedString): 110 - Change to use `CFStringRef format` for USE(CF) platforms 111 (except Windows), and `const char* format` for other platforms 112 so format macros may be added to the delaration. 113 (WebCore::localizedNSString): 114 - Re-implement as an inline function using localizedString(). 115 116 * platform/cocoa/LocalizedStringsCocoa.mm: 117 (WebCore::localizedNSString): Delete. 118 - Moved to LocalizedStrings.h. 119 (WebCore::localizedString): Delete. 120 - Moved to LocalizedStrings.cpp. 121 (WebCore::contextMenuItemTagSearchWeb): 122 (WebCore::keygenKeychainItemName): 123 (WebCore::htmlSelectMultipleItems): 124 - Switch from WEB_UI_STRING() to WEB_UI_FORMAT_CFSTRING() due to 125 the new rule for localized format strings. 126 (WebCore::validationMessageTooLongText): 127 - Switch from +[NSString stringWithFormat:] and 128 WEB_UI_NSSTRING() to WebCore::formatLocalizedString() and 129 WEB_UI_FORMAT_CFSTRING() for consistency. 130 131 * platform/win/LocalizedStringsWin.cpp: 132 (WebCore::localizedString): Delete. 133 - Moved to localizedString() in LocalizedStrings.cpp. 134 1 135 2021-11-24 Said Abou-Hallawa <said@apple.com> 2 136 -
trunk/Source/WebCore/Scripts/extract-localizable-strings.pl
r278586 r286156 1 1 #!/usr/bin/env perl 2 2 3 # Copyright (C) 2006 , 2007, 2009, 2010, 2013Apple Inc. All rights reserved.3 # Copyright (C) 2006-2021 Apple Inc. All rights reserved. 4 4 # 5 5 # Redistribution and use in source and binary forms, with or without … … 119 119 my @files = ( split "\n", `find $quotedDirectoriesString \\( -name "*.h" -o -name "*.m" -o -name "*.mm" -o -name "*.c" -o -name "*.cpp" \\)` ); 120 120 121 sub isFormatMacro($) { return ($_[0] =~ /(WEB_)?UI_FORMAT_/); } 122 121 123 for my $file (sort @files) { 122 124 next if $file =~ /\/\w+LocalizableStrings\w*\.h$/ || $file =~ /\/LocalizedStrings\.h$/; … … 134 136 my $key; 135 137 my $comment; 138 my $isFormat; 136 139 my $mnemonic; 137 140 … … 187 190 $UIString = $string; 188 191 $expected = ","; 189 } elsif (($macro =~ /(WEB_)?UI_( CF)?STRING_KEY(_INTERNAL)?$/) and !defined $key) {192 } elsif (($macro =~ /(WEB_)?UI_(FORMAT_)?(CF)?STRING_KEY(_INTERNAL)?$/) and !defined $key) { 190 193 # FIXME: Validate UTF-8 here? 191 194 $key = $string; 195 $isFormat = isFormatMacro($macro); 192 196 $expected = ","; 193 197 } elsif (($macro =~ /WEB_UI_STRING_WITH_MNEMONIC$/) and !defined $mnemonic) { 194 198 $mnemonic = $string; 199 $isFormat = 0; 195 200 $expected = ","; 196 201 } elsif (!defined $comment) { … … 242 247 } 243 248 } else { 244 if ( $expected and $expected ne $token) {249 if ((!$isFormat and $expected and $expected ne $token) or ($isFormat and $expected eq ")" and $token ne ",")) { 245 250 emitError($file, $., "found $token but expected $expected"); 246 251 $expected = ""; 247 252 } 248 if (($token =~ /(WEB_)?UI_( CF)?STRING(_KEY)?(_INTERNAL)?$/) || ($token =~ /WEB_UI_NSSTRING$/) || ($token =~ /WEB_UI_STRING_WITH_MNEMONIC$/)) {253 if (($token =~ /(WEB_)?UI_(FORMAT_)?(CF)?STRING(_KEY)?(_INTERNAL)?$/) || ($token =~ /WEB_UI_NSSTRING$/) || ($token =~ /WEB_UI_STRING_WITH_MNEMONIC$/)) { 249 254 $expected = "("; 250 255 $macro = $token; … … 254 259 $mnemonic = undef; 255 260 $macroLine = $.; 261 $isFormat = isFormatMacro($token); 256 262 } elsif ($token eq "(" or $token eq "[") { 257 263 ++$nestingLevel if defined $nestingLevel; -
trunk/Source/WebCore/platform/LocalizedStrings.cpp
r285234 r286156 1 1 /* 2 * Copyright (C) 2003-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2003-2021 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2010 Igalia S.L 4 4 * … … 35 35 36 36 #if USE(CF) 37 #if PLATFORM(WIN) 38 #include "WebCoreBundleWin.h" 39 #endif 37 40 #include <wtf/RetainPtr.h> 38 41 #endif … … 44 47 namespace WebCore { 45 48 49 #if USE(CF) && !PLATFORM(WIN) 50 String formatLocalizedString(CFStringRef format, ...) 51 { 52 va_list arguments; 53 va_start(arguments, format); 54 55 auto localizedFormat = copyLocalizedString(format); 56 ALLOW_NONLITERAL_FORMAT_BEGIN 57 // The 'format' parameter is already checked for correct placeholders and parameters. 58 auto result = adoptCF(CFStringCreateWithFormatAndArguments(0, 0, localizedFormat.get(), arguments)); 59 ALLOW_NONLITERAL_FORMAT_END 60 61 va_end(arguments); 62 return result.get(); 63 } 64 #else 46 65 // Because |format| is used as the second parameter to va_start, it cannot be a reference 47 66 // type according to section 18.7/3 of the C++ N1905 standard. 48 String formatLocalizedString(String format, ...) 49 { 50 #if USE(CF) 67 String formatLocalizedString(const char* format, ...) 68 { 69 #if USE(CF) && PLATFORM(WIN) 70 auto cfFormat = adoptCF(CFStringCreateWithCStringNoCopy(nullptr, format, kCFStringEncodingUTF8, kCFAllocatorNull)); 51 71 va_list arguments; 52 72 va_start(arguments, format); 53 54 ALLOW_NONLITERAL_FORMAT_BEGIN 55 auto result = adoptCF(CFStringCreateWithFormatAndArguments(0, 0, format.createCFString().get(), arguments)); 56 ALLOW_NONLITERAL_FORMAT_END 57 73 auto localizedFormat = copyLocalizedString(cfFormat.get()); 74 auto result = adoptCF(CFStringCreateWithFormatAndArguments(0, 0, localizedFormat.get(), arguments)); 58 75 va_end(arguments); 59 76 return result.get(); … … 61 78 va_list arguments; 62 79 va_start(arguments, format); 63 GUniquePtr<gchar> result(g_strdup_vprintf(format .utf8().data(), arguments));80 GUniquePtr<gchar> result(g_strdup_vprintf(format, arguments)); 64 81 va_end(arguments); 65 82 return String::fromUTF8(result.get()); … … 69 86 #endif 70 87 } 71 72 #if !USE(CF) 73 88 #endif 89 90 #if USE(CF) 91 #if !PLATFORM(WIN) 92 static CFBundleRef webCoreBundle() 93 { 94 static NeverDestroyed<RetainPtr<CFBundleRef>> bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebCore")); 95 ASSERT(bundle.get()); 96 return bundle.get().get(); 97 } 98 #endif 99 100 RetainPtr<CFStringRef> copyLocalizedString(CFStringRef key) 101 { 102 #if !PLATFORM(IOS_FAMILY) 103 // Can be called on a dispatch queue when initializing strings on iOS. 104 // See LoadWebLocalizedStrings and <rdar://problem/7902473>. 105 ASSERT(isMainThread()); 106 #endif 107 108 static CFStringRef notFound = CFSTR("localized string not found"); 109 110 #if PLATFORM(WIN) 111 CFBundleRef bundle = webKitBundle(); 112 #else 113 CFBundleRef bundle = webCoreBundle(); 114 #endif 115 auto result = adoptCF(CFBundleCopyLocalizedString(bundle, key, notFound, nullptr)); 116 117 #if ASSERT_ENABLED 118 if (result.get() == notFound) { 119 char keyCString[256]; 120 CFStringGetCString(key, keyCString, sizeof(keyCString), kCFStringEncodingUTF8); 121 ASSERT_WITH_MESSAGE(result.get() != notFound, "Could not find localizable string '%s' in bundle", keyCString); 122 } 123 #endif 124 125 return result; 126 } 127 #endif 128 129 #if USE(CF) && !PLATFORM(WIN) 130 String localizedString(CFStringRef key) 131 { 132 return copyLocalizedString(key).get(); 133 } 134 #else 74 135 String localizedString(const char* key) 75 136 { 137 #if USE(CF) 138 auto keyString = adoptCF(CFStringCreateWithCStringNoCopy(nullptr, key, kCFStringEncodingUTF8, kCFAllocatorNull)); 139 return copyLocalizedString(keyString.get()).get(); 140 #else 76 141 return String::fromUTF8(key, strlen(key)); 77 } 78 142 #endif 143 } 79 144 #endif 80 145 … … 234 299 #if USE(CF) 235 300 auto selectedCFString = truncatedStringForMenuItem(selectedString).createCFString(); 236 return formatLocalizedString(WEB_UI_CFSTRING("Look Up “%@”", "Look Up context menu item with selected word"), selectedCFString.get());301 return WEB_UI_FORMAT_CFSTRING("Look Up “%@”", "Look Up context menu item with selected word", selectedCFString.get()); 237 302 #elif USE(GLIB) 238 return formatLocalizedString(WEB_UI_STRING("Look Up “%s”", "Look Up context menu item with selected word"), truncatedStringForMenuItem(selectedString).utf8().data());303 return WEB_UI_FORMAT_STRING("Look Up “%s”", "Look Up context menu item with selected word", truncatedStringForMenuItem(selectedString).utf8().data()); 239 304 #else 240 305 return WEB_UI_STRING("Look Up “<selection>”", "Look Up context menu item with selected word").replace("<selection>", truncatedStringForMenuItem(selectedString)); … … 247 312 { 248 313 auto selectedCFString = truncatedStringForMenuItem(selectedString).createCFString(); 249 return formatLocalizedString(WEB_UI_CFSTRING("Translate “%@”", "Translate context menu item with selected word"), selectedCFString.get());314 return WEB_UI_FORMAT_CFSTRING("Translate “%@”", "Translate context menu item with selected word", selectedCFString.get()); 250 315 } 251 316 … … 825 890 String multipleFileUploadText(unsigned numberOfFiles) 826 891 { 827 return formatLocalizedString(WEB_UI_STRING("%d files", "Label to describe the number of files selected in a file upload control that allows multiple files"), numberOfFiles);892 return WEB_UI_FORMAT_STRING("%d files", "Label to describe the number of files selected in a file upload control that allows multiple files", numberOfFiles); 828 893 } 829 894 … … 847 912 auto heightString = adoptCF(CFNumberFormatterCreateStringWithNumber(0, formatter.get(), height.get())); 848 913 849 return formatLocalizedString(WEB_UI_CFSTRING("%@ %@×%@ pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename.createCFString().get(), widthString.get(), heightString.get());914 return WEB_UI_FORMAT_CFSTRING("%@ %@×%@ pixels", "window title for a standalone image (uses multiplication symbol, not x)", filename.createCFString().get(), widthString.get(), heightString.get()); 850 915 #elif USE(GLIB) 851 return formatLocalizedString(WEB_UI_STRING("%s %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename.utf8().data(), size.width(), size.height());916 return WEB_UI_FORMAT_STRING("%s %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)", filename.utf8().data(), size.width(), size.height()); 852 917 #else 853 return formatLocalizedString(WEB_UI_STRING("<filename> %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)"), size.width(), size.height()).replace("<filename>", filename);918 return WEB_UI_FORMAT_STRING("<filename> %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)", size.width(), size.height()).replace("<filename>", filename); 854 919 #endif 855 920 } … … 973 1038 974 1039 if (days) 975 return formatLocalizedString(WEB_UI_STRING("%1$d days %2$d hours %3$d minutes %4$d seconds", "accessibility help text for media controller time value >= 1 day"), days, hours, minutes, seconds);1040 return WEB_UI_FORMAT_STRING("%1$d days %2$d hours %3$d minutes %4$d seconds", "accessibility help text for media controller time value >= 1 day", days, hours, minutes, seconds); 976 1041 if (hours) 977 return formatLocalizedString(WEB_UI_STRING("%1$d hours %2$d minutes %3$d seconds", "accessibility help text for media controller time value >= 60 minutes"), hours, minutes, seconds);1042 return WEB_UI_FORMAT_STRING("%1$d hours %2$d minutes %3$d seconds", "accessibility help text for media controller time value >= 60 minutes", hours, minutes, seconds); 978 1043 if (minutes) 979 return formatLocalizedString(WEB_UI_STRING("%1$d minutes %2$d seconds", "accessibility help text for media controller time value >= 60 seconds"), minutes, seconds);980 return formatLocalizedString(WEB_UI_STRING("%1$d seconds", "accessibility help text for media controller time value < 60 seconds"), seconds);1044 return WEB_UI_FORMAT_STRING("%1$d minutes %2$d seconds", "accessibility help text for media controller time value >= 60 seconds", minutes, seconds); 1045 return WEB_UI_FORMAT_STRING("%1$d seconds", "accessibility help text for media controller time value < 60 seconds", seconds); 981 1046 } 982 1047 … … 1039 1104 String validationMessageTooShortText(int, int minLength) 1040 1105 { 1041 return formatLocalizedString(WEB_UI_STRING("Use at least %d characters", "Validation message for form control elements with a value shorter than minimum allowed length"), minLength);1106 return WEB_UI_FORMAT_STRING("Use at least %d characters", "Validation message for form control elements with a value shorter than minimum allowed length", minLength); 1042 1107 } 1043 1108 … … 1045 1110 String validationMessageTooLongText(int, int maxLength) 1046 1111 { 1047 return formatLocalizedString(WEB_UI_STRING("Use no more than %d characters", "Validation message for form control elements with a value shorter than maximum allowed length"), maxLength);1112 return WEB_UI_FORMAT_STRING("Use no more than %d characters", "Validation message for form control elements with a value shorter than maximum allowed length", maxLength); 1048 1113 } 1049 1114 #endif … … 1053 1118 { 1054 1119 #if USE(CF) 1055 return formatLocalizedString(WEB_UI_CFSTRING("Value must be greater than or equal to %@", "Validation message for input form controls with value lower than allowed minimum"), minimum.createCFString().get());1120 return WEB_UI_FORMAT_CFSTRING("Value must be greater than or equal to %@", "Validation message for input form controls with value lower than allowed minimum", minimum.createCFString().get()); 1056 1121 #elif USE(GLIB) 1057 return formatLocalizedString(WEB_UI_STRING("Value must be greater than or equal to %s", "Validation message for input form controls with value lower than allowed minimum"), minimum.utf8().data());1122 return WEB_UI_FORMAT_STRING("Value must be greater than or equal to %s", "Validation message for input form controls with value lower than allowed minimum", minimum.utf8().data()); 1058 1123 #else 1059 1124 UNUSED_PARAM(minimum); … … 1065 1130 { 1066 1131 #if USE(CF) 1067 return formatLocalizedString(WEB_UI_CFSTRING("Value must be less than or equal to %@", "Validation message for input form controls with value higher than allowed maximum"), maximum.createCFString().get());1132 return WEB_UI_FORMAT_CFSTRING("Value must be less than or equal to %@", "Validation message for input form controls with value higher than allowed maximum", maximum.createCFString().get()); 1068 1133 #elif USE(GLIB) 1069 return formatLocalizedString(WEB_UI_STRING("Value must be less than or equal to %s", "Validation message for input form controls with value higher than allowed maximum"), maximum.utf8().data());1134 return WEB_UI_FORMAT_STRING("Value must be less than or equal to %s", "Validation message for input form controls with value higher than allowed maximum", maximum.utf8().data()); 1070 1135 #else 1071 1136 UNUSED_PARAM(maximum); … … 1110 1175 String addTrackLabelAsSuffix(const String& text, const String& label) 1111 1176 { 1112 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ (%@)", "%@ (%@) (audio/text track)", "Audio/Text track display name format that includes the label and language of the track, in the form of 'Language (Label)'."), text.createCFString().get(), label.createCFString().get());1177 return WEB_UI_FORMAT_CFSTRING_KEY("%@ (%@)", "%@ (%@) (audio/text track)", "Audio/Text track display name format that includes the label and language of the track, in the form of 'Language (Label)'.", text.createCFString().get(), label.createCFString().get()); 1113 1178 } 1114 1179 … … 1122 1187 if (text.isEmpty()) 1123 1188 return textTrackKindClosedCaptionsDisplayName(); 1124 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ CC", "%@ CC (text track)", "Closed captions text track display name format that includes the language and/or locale (e.g. 'English CC')."), text.createCFString().get());1189 return WEB_UI_FORMAT_CFSTRING_KEY("%@ CC", "%@ CC (text track)", "Closed captions text track display name format that includes the language and/or locale (e.g. 'English CC').", text.createCFString().get()); 1125 1190 } 1126 1191 … … 1134 1199 if (text.isEmpty()) 1135 1200 return textTrackKindCaptionsDisplayName(); 1136 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Captions", "%@ Captions (text track)", "Captions text track display name format that includes the language and/or locale (e.g. 'English Captions')."), text.createCFString().get());1201 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Captions", "%@ Captions (text track)", "Captions text track display name format that includes the language and/or locale (e.g. 'English Captions').", text.createCFString().get()); 1137 1202 } 1138 1203 … … 1146 1211 if (text.isEmpty()) 1147 1212 return textTrackKindDescriptionsDisplayName(); 1148 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Descriptions", "%@ Descriptions (text track)", "Descriptions text track display name format that includes the language and/or locale (e.g. 'English Descriptions')."), text.createCFString().get());1213 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Descriptions", "%@ Descriptions (text track)", "Descriptions text track display name format that includes the language and/or locale (e.g. 'English Descriptions').", text.createCFString().get()); 1149 1214 } 1150 1215 … … 1158 1223 if (text.isEmpty()) 1159 1224 return textTrackKindChaptersDisplayName(); 1160 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Chapters", "%@ Chapters (text track)", "Chapters text track display name format that includes the language and/or locale (e.g. 'English Chapters')."), text.createCFString().get());1225 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Chapters", "%@ Chapters (text track)", "Chapters text track display name format that includes the language and/or locale (e.g. 'English Chapters').", text.createCFString().get()); 1161 1226 } 1162 1227 … … 1170 1235 if (text.isEmpty()) 1171 1236 return textTrackKindMetadataDisplayName(); 1172 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Metadata", "%@ Metadata (text track)", "Metadata text track display name format that includes the language and/or locale (e.g. 'English Metadata')."), text.createCFString().get());1237 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Metadata", "%@ Metadata (text track)", "Metadata text track display name format that includes the language and/or locale (e.g. 'English Metadata').", text.createCFString().get()); 1173 1238 } 1174 1239 … … 1182 1247 if (text.isEmpty()) 1183 1248 return textTrackKindSDHDisplayName(); 1184 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ SDH", "%@ SDH (text track)", "SDH (i.e. deaf and/or hard of hearing) text track display name format that includes the language and/or locale (e.g. 'English SDH')."), text.createCFString().get());1249 return WEB_UI_FORMAT_CFSTRING_KEY("%@ SDH", "%@ SDH (text track)", "SDH (i.e. deaf and/or hard of hearing) text track display name format that includes the language and/or locale (e.g. 'English SDH').", text.createCFString().get()); 1185 1250 } 1186 1251 … … 1194 1259 if (text.isEmpty()) 1195 1260 return textTrackKindEasyReaderDisplayName(); 1196 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Easy Reader", "%@ Easy Reader (text track)", "Easy Reader (i.e. 3rd-grade level) text track display name format that includes the language and/or locale (e.g. 'English Easy Reader')."), text.createCFString().get());1261 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Easy Reader", "%@ Easy Reader (text track)", "Easy Reader (i.e. 3rd-grade level) text track display name format that includes the language and/or locale (e.g. 'English Easy Reader').", text.createCFString().get()); 1197 1262 } 1198 1263 … … 1206 1271 if (text.isEmpty()) 1207 1272 return textTrackKindForcedDisplayName(); 1208 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Forced", "%@ Forced (text track)", "Forced text track display name format that includes the language and/or locale (e.g. 'English Forced')."), text.createCFString().get());1273 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Forced", "%@ Forced (text track)", "Forced text track display name format that includes the language and/or locale (e.g. 'English Forced').", text.createCFString().get()); 1209 1274 } 1210 1275 … … 1218 1283 if (text.isEmpty()) 1219 1284 return audioTrackKindDescriptionsDisplayName(); 1220 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Descriptions", "%@ Descriptions (audio track)", "Descriptions audio track display name format that includes the language and/or locale (e.g. 'English Descriptions')."), text.createCFString().get());1285 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Descriptions", "%@ Descriptions (audio track)", "Descriptions audio track display name format that includes the language and/or locale (e.g. 'English Descriptions').", text.createCFString().get()); 1221 1286 } 1222 1287 … … 1230 1295 if (text.isEmpty()) 1231 1296 return audioTrackKindCommentaryDisplayName(); 1232 return formatLocalizedString(WEB_UI_CFSTRING_KEY("%@ Commentary", "%@ Commentary (audio track)", "Commentary audio track display name format that includes the language and/or locale (e.g. 'English Commentary')."), text.createCFString().get());1297 return WEB_UI_FORMAT_CFSTRING_KEY("%@ Commentary", "%@ Commentary (audio track)", "Commentary audio track display name format that includes the language and/or locale (e.g. 'English Commentary').", text.createCFString().get()); 1233 1298 } 1234 1299 … … 1257 1322 { 1258 1323 #if USE(CF) 1259 return formatLocalizedString(WEB_UI_CFSTRING("%@ WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain"), localizedApplicationName.createCFString().get());1324 return WEB_UI_FORMAT_CFSTRING("%@ WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain", localizedApplicationName.createCFString().get()); 1260 1325 #elif USE(GLIB) 1261 return formatLocalizedString(WEB_UI_STRING("%s WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain"), localizedApplicationName.utf8().data());1326 return WEB_UI_FORMAT_STRING("%s WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain", localizedApplicationName.utf8().data()); 1262 1327 #else 1263 1328 return WEB_UI_STRING("<application> WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain").replace("<application>", localizedApplicationName); … … 1333 1398 String makeCredentialTouchIDPromptTitle(const String& bundleName, const String& domain) 1334 1399 { 1335 return formatLocalizedString(WEB_UI_CFSTRING("“%@” would like to use Touch ID for “%@”.", "Allow the specified bundle to use Touch ID to sign in to the specified website on this device"), bundleName.createCFString().get(), domain.createCFString().get());1400 return WEB_UI_FORMAT_CFSTRING("“%@” would like to use Touch ID for “%@”.", "Allow the specified bundle to use Touch ID to sign in to the specified website on this device", bundleName.createCFString().get(), domain.createCFString().get()); 1336 1401 } 1337 1402 1338 1403 String getAssertionTouchIDPromptTitle(const String& bundleName, const String& domain) 1339 1404 { 1340 return formatLocalizedString(WEB_UI_CFSTRING("“%@” would like to sign in to “%@”.", "Allow the specified bundle to sign in to the specified website"), bundleName.createCFString().get(), domain.createCFString().get());1405 return WEB_UI_FORMAT_CFSTRING("“%@” would like to sign in to “%@”.", "Allow the specified bundle to sign in to the specified website", bundleName.createCFString().get(), domain.createCFString().get()); 1341 1406 } 1342 1407 -
trunk/Source/WebCore/platform/LocalizedStrings.h
r279164 r286156 1 1 /* 2 * Copyright (C) 2003-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2003-2021 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2010 Igalia S.L 4 4 * … … 29 29 30 30 #include <wtf/Forward.h> 31 32 #ifdef __OBJC__ 33 #include <wtf/cocoa/TypeCastsCocoa.h> 34 #endif 31 35 32 36 #if USE(GLIB) && defined(GETTEXT_PACKAGE) … … 378 382 #endif 379 383 380 #if USE(GLIB) && defined(GETTEXT_PACKAGE) 384 #if USE(CF) && !PLATFORM(WIN) 385 #define WEB_UI_STRING(string, description) WebCore::localizedString(CFSTR(string)) 386 #define WEB_UI_STRING_KEY(string, key, description) WebCore::localizedString(CFSTR(key)) 387 #define WEB_UI_STRING_WITH_MNEMONIC(string, mnemonic, description) WebCore::localizedString(CFSTR(string)) 388 #elif USE(GLIB) && defined(GETTEXT_PACKAGE) 381 389 #define WEB_UI_STRING(string, description) WebCore::localizedString(_(string)) 382 390 #define WEB_UI_STRING_KEY(string, key, description) WebCore::localizedString(C_(key, string)) 383 391 #define WEB_UI_STRING_WITH_MNEMONIC(string, mnemonic, description) WebCore::localizedString(_(mnemonic)) 384 392 #else 393 // Work around default Mac Roman encoding of CFSTR() for Apple Windows port. 385 394 #define WEB_UI_STRING(string, description) WebCore::localizedString(string) 386 395 #define WEB_UI_STRING_KEY(string, key, description) WebCore::localizedString(key) … … 390 399 #if USE(CF) 391 400 // This is exactly as WEB_UI_STRING, but renamed to ensure the string is not scanned by non-CF ports. 401 #if PLATFORM(WIN) 402 // Work around default Mac Roman encoding of CFSTR() for Apple Windows port. 392 403 #define WEB_UI_CFSTRING(string, description) WebCore::localizedString(string) 393 404 #define WEB_UI_CFSTRING_KEY(string, key, description) WebCore::localizedString(key) 394 #endif 395 405 #else 406 #define WEB_UI_CFSTRING(string, description) WebCore::localizedString(CFSTR(string)) 407 #define WEB_UI_CFSTRING_KEY(string, key, description) WebCore::localizedString(CFSTR(key)) 408 #endif 409 410 WEBCORE_EXPORT RetainPtr<CFStringRef> copyLocalizedString(CFStringRef key); 411 #endif 412 413 #if USE(CF) && !PLATFORM(WIN) 414 WEBCORE_EXPORT String localizedString(CFStringRef key); 415 #else 396 416 WEBCORE_EXPORT String localizedString(const char* key); 397 String formatLocalizedString(String format, ...); 417 #endif 418 419 #if USE(CF) 420 #if PLATFORM(WIN) 421 // Work around default Mac Roman encoding of CFSTR() for Apple Windows port. 422 #define WEB_UI_FORMAT_CFSTRING(string, description, ...) WebCore::formatLocalizedString(string, __VA_ARGS__) 423 #define WEB_UI_FORMAT_CFSTRING_KEY(string, key, description, ...) WebCore::formatLocalizedString(key, __VA_ARGS__) 424 #define WEB_UI_FORMAT_STRING(string, description, ...) WebCore::formatLocalizedString(string, __VA_ARGS__) 425 #else 426 #define WEB_UI_FORMAT_CFSTRING(string, description, ...) WebCore::formatLocalizedString(CFSTR(string), __VA_ARGS__) 427 #define WEB_UI_FORMAT_CFSTRING_KEY(string, key, description, ...) WebCore::formatLocalizedString(CFSTR(key), __VA_ARGS__) 428 #define WEB_UI_FORMAT_STRING(string, description, ...) WebCore::formatLocalizedString(CFSTR(string), __VA_ARGS__) 429 #endif // PLATFORM(WIN) 430 #elif USE(GLIB) && defined(GETTEXT_PACKAGE) 431 #define WEB_UI_FORMAT_STRING(string, description, ...) WebCore::formatLocalizedString(_(string), __VA_ARGS__) 432 #else 433 #define WEB_UI_FORMAT_STRING(string, description, ...) WebCore::formatLocalizedString(string, __VA_ARGS__) 434 #endif 435 436 #if USE(CF) && !PLATFORM(WIN) 437 String formatLocalizedString(CFStringRef format, ...) CF_FORMAT_FUNCTION(1, 2); 438 #else 439 String formatLocalizedString(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2); 440 #endif 398 441 399 442 #ifdef __OBJC__ 400 443 #define WEB_UI_NSSTRING(string, description) WebCore::localizedNSString(string) 401 WEBCORE_EXPORT NSString *localizedNSString(NSString *key) NS_FORMAT_ARGUMENT(1); 444 inline NS_FORMAT_ARGUMENT(1) NSString *localizedNSString(NSString *key) 445 { 446 return bridge_cast(copyLocalizedString(bridge_cast(key)).autorelease()); 447 } 402 448 #endif 403 449 -
trunk/Source/WebCore/platform/cocoa/LocalizedStringsCocoa.mm
r285234 r286156 1 1 /* 2 * Copyright (C) 2011-20 17Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 36 36 namespace WebCore { 37 37 38 NSString *localizedNSString(NSString *key)39 {40 #if !PLATFORM(IOS_FAMILY)41 // Can be called on a dispatch queue when initializing strings on iOS.42 // See LoadWebLocalizedStrings and <rdar://problem/7902473>.43 ASSERT(isMainThread());44 #endif45 46 static NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebCore"];47 return [bundle localizedStringForKey:key value:@"localized string not found" table:nullptr];48 }49 50 String localizedString(const char* key)51 {52 RetainPtr<CFStringRef> keyString = adoptCF(CFStringCreateWithCStringNoCopy(0, key, kCFStringEncodingUTF8, kCFAllocatorNull));53 return localizedNSString((__bridge NSString *)keyString.get());54 }55 56 38 String copyImageUnknownFileLabel() 57 39 { … … 80 62 { 81 63 auto searchProviderName = PAL::defaultSearchProviderDisplayName(); 82 return formatLocalizedString(WEB_UI_STRING("Search with %@", "Search with search provider context menu item with provider name inserted"), searchProviderName.get());64 return WEB_UI_FORMAT_CFSTRING("Search with %@", "Search with search provider context menu item with provider name inserted", searchProviderName.get()); 83 65 } 84 66 … … 234 216 String keygenKeychainItemName(const String& host) 235 217 { 236 return formatLocalizedString(WEB_UI_STRING("Key from %@", "Name of keychain key generated by the KEYGEN tag"), host.createCFString().get());218 return WEB_UI_FORMAT_CFSTRING("Key from %@", "Name of keychain key generated by the KEYGEN tag", host.createCFString().get()); 237 219 } 238 220 … … 246 228 return WEB_UI_STRING("1 Item", "Present the element <select multiple> when a single <option> is selected (iOS only)"); 247 229 default: 248 return formatLocalizedString(WEB_UI_STRING("%zu Items", "Present the number of selected <option> items in a <select multiple> element (iOS only)"), count);230 return WEB_UI_FORMAT_CFSTRING("%zu Items", "Present the number of selected <option> items in a <select multiple> element (iOS only)", count); 249 231 } 250 232 } … … 279 261 String validationMessageTooLongText(int, int maxLength) 280 262 { 281 return [NSString localizedStringWithFormat:WEB_UI_NSSTRING(@"Use no more than %d character(s)", @"Validation message for form control elements with a value shorter than maximum allowed length"), maxLength];263 return WEB_UI_FORMAT_CFSTRING("Use no more than %d character(s)", "Validation message for form control elements with a value shorter than maximum allowed length", maxLength); 282 264 } 283 265 -
trunk/Source/WebCore/platform/gtk/po/CMakeLists.txt
r215718 r286156 26 26 --keyword=_ 27 27 --keyword=N_ 28 --keyword=WEB_UI_FORMAT_STRING:1 28 29 --keyword=WEB_UI_STRING:1 29 30 --keyword=WEB_UI_STRING_KEY:3c,1 -
trunk/Source/WebCore/platform/gtk/po/ChangeLog
r282323 r286156 1 2021-11-24 David Kilzer <ddkilzer@apple.com> 2 3 Compiler should be able to check localized format strings for consistency 4 <https://webkit.org/b/232686> 5 <rdar://problem/84994345> 6 7 Reviewed by Darin Adler. 8 9 * CMakeLists.txt: 10 (add_custom_command: xgettext): 11 - Add WEB_UI_FORMAT_STRING to list of macros containing 12 localizable strings. 13 1 14 2021-09-13 Piotr Drąg <piotrdrag@gmail.com> 2 15 -
trunk/Source/WebCore/platform/win/LocalizedStringsWin.cpp
r238406 r286156 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 28 28 29 29 #include "NotImplemented.h" 30 #include "WebCoreInstanceHandle.h"31 #include <windows.h>32 #include <wtf/Assertions.h>33 #include <wtf/MainThread.h>34 #include <wtf/StdLibExtras.h>35 30 #include <wtf/text/WTFString.h> 36 31 37 #if USE(CF)38 #include "WebCoreBundleWin.h"39 #include <CoreFoundation/CFBundle.h>40 #include <wtf/RetainPtr.h>41 #endif42 43 32 namespace WebCore { 44 45 #if USE(CF)46 String localizedString(const char* key)47 {48 ASSERT(isMainThread());49 50 static CFStringRef notFound = CFSTR("localized string not found");51 52 RetainPtr<CFStringRef> keyString = adoptCF(CFStringCreateWithCStringNoCopy(NULL, key, kCFStringEncodingUTF8, kCFAllocatorNull));53 RetainPtr<CFStringRef> result = adoptCF(CFCopyLocalizedStringWithDefaultValue(keyString.get(), 0, webKitBundle(), notFound, 0));54 ASSERT_WITH_MESSAGE(result.get() != notFound, "could not find localizable string %s in bundle", key);55 56 return result.get();57 }58 #endif59 33 60 34 String uploadFileText() -
trunk/Source/WebKitLegacy/mac/ChangeLog
r285904 r286156 1 2021-11-24 David Kilzer <ddkilzer@apple.com> 2 3 Compiler should be able to check localized format strings for consistency 4 <https://webkit.org/b/232686> 5 <rdar://problem/84994345> 6 7 Reviewed by Darin Adler. 8 9 * Misc/WebLocalizableStringsInternal.mm: 10 (WebLocalizedStringInternal): 11 - Use localizedNSString() instead of localizedString() to 12 eliminate the need to convert from 13 CFString -> String -> NSString. 14 1 15 2021-11-16 Nikolaos Mouchtaris <nmouchtaris@apple.com> 2 16 -
trunk/Source/WebKitLegacy/mac/Misc/WebLocalizableStringsInternal.mm
r95901 r286156 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 28 28 #import <WebCore/LocalizedStrings.h> 29 #import <wtf/text/WTFString.h>30 29 31 30 using namespace WebCore; … … 33 32 NSString *WebLocalizedStringInternal(const char* key) 34 33 { 35 return localizedString(key); 34 auto keyString = adoptCF(CFStringCreateWithCStringNoCopy(0, key, kCFStringEncodingUTF8, kCFAllocatorNull)); 35 return localizedNSString(bridge_cast(keyString.get())); 36 36 }
Note:
See TracChangeset
for help on using the changeset viewer.