Improve use of NeverDestroyed
[WebKit-https.git] / Source / WebCore / platform / LocalizedStrings.cpp
1 /*
2  * Copyright (C) 2003, 2006, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Igalia S.L
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "LocalizedStrings.h"
29
30 #include "IntSize.h"
31 #include "NotImplemented.h"
32 #include <wtf/MathExtras.h>
33 #include <wtf/text/TextBreakIterator.h>
34 #include <wtf/unicode/CharacterNames.h>
35
36 #if USE(CF)
37 #include <wtf/RetainPtr.h>
38 #endif
39
40 #if USE(GLIB)
41 #include <wtf/glib/GUniquePtr.h>
42 #endif
43
44 namespace WebCore {
45
46 // We can't use String::format for two reasons:
47 //  1) It doesn't handle non-ASCII characters in the format string.
48 //  2) It doesn't handle the %2$d syntax.
49 // Note that because |format| is used as the second parameter to va_start, it cannot be a reference
50 // type according to section 18.7/3 of the C++ N1905 standard.
51 String formatLocalizedString(String format, ...)
52 {
53 #if USE(CF)
54     va_list arguments;
55     va_start(arguments, format);
56
57 #if COMPILER(CLANG)
58 #pragma clang diagnostic push
59 #pragma clang diagnostic ignored "-Wformat-nonliteral"
60 #endif
61     auto result = adoptCF(CFStringCreateWithFormatAndArguments(0, 0, format.createCFString().get(), arguments));
62 #if COMPILER(CLANG)
63 #pragma clang diagnostic pop
64 #endif
65
66     va_end(arguments);
67     return result.get();
68 #elif USE(GLIB)
69     va_list arguments;
70     va_start(arguments, format);
71     GUniquePtr<gchar> result(g_strdup_vprintf(format.utf8().data(), arguments));
72     va_end(arguments);
73     return String::fromUTF8(result.get());
74 #else
75     notImplemented();
76     return format;
77 #endif
78 }
79
80 #if ENABLE(CONTEXT_MENUS)
81
82 static String truncatedStringForLookupMenuItem(const String& original)
83 {
84     // Truncate the string if it's too long. This number is roughly the same as the one used by AppKit.
85     unsigned maxNumberOfGraphemeClustersInLookupMenuItem = 24;
86
87     String trimmed = original.stripWhiteSpace();
88     unsigned numberOfCharacters = numCharactersInGraphemeClusters(trimmed, maxNumberOfGraphemeClustersInLookupMenuItem);
89     return numberOfCharacters == trimmed.length() ? trimmed : makeString(trimmed.left(numberOfCharacters), horizontalEllipsis);
90 }
91
92 #endif
93
94 String inputElementAltText()
95 {
96     return WEB_UI_STRING_KEY("Submit", "Submit (input element)", "alt text for <input> elements with no alt, title, or value");
97 }
98
99 String resetButtonDefaultLabel()
100 {
101     return WEB_UI_STRING("Reset", "default label for Reset buttons in forms on web pages");
102 }
103
104 String searchableIndexIntroduction()
105 {
106     return WEB_UI_STRING("This is a searchable index. Enter search keywords: ",
107                          "text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index'");
108 }
109
110 String submitButtonDefaultLabel()
111 {
112     return WEB_UI_STRING("Submit", "default label for Submit buttons in forms on web pages");
113 }
114
115 String fileButtonChooseFileLabel()
116 {
117     return WEB_UI_STRING("Choose File", "title for a single file chooser button used in HTML forms");
118 }
119
120 String fileButtonChooseMultipleFilesLabel()
121 {
122     return WEB_UI_STRING("Choose Files", "title for a multiple file chooser button used in HTML forms. This title should be as short as possible.");
123 }
124
125 String fileButtonNoFileSelectedLabel()
126 {
127     return WEB_UI_STRING("no file selected", "text to display in file button used in HTML forms when no file is selected");
128 }
129
130 String fileButtonNoFilesSelectedLabel()
131 {
132     return WEB_UI_STRING("no files selected", "text to display in file button used in HTML forms when no files are selected and the button allows multiple files to be selected");
133 }
134
135 String defaultDetailsSummaryText()
136 {
137     return WEB_UI_STRING("Details", "text to display in <details> tag when it has no <summary> child");
138 }
139
140 #if ENABLE(CONTEXT_MENUS)
141
142 String contextMenuItemTagOpenLinkInNewWindow()
143 {
144     return WEB_UI_STRING_WITH_MNEMONIC("Open Link in New Window", "Open Link in New _Window", "Open in New Window context menu item");
145 }
146
147 String contextMenuItemTagDownloadLinkToDisk()
148 {
149     return WEB_UI_STRING_WITH_MNEMONIC("Download Linked File", "_Download Linked File", "Download Linked File context menu item");
150 }
151
152 #if !PLATFORM(GTK)
153 String contextMenuItemTagCopyLinkToClipboard()
154 {
155     return WEB_UI_STRING("Copy Link", "Copy Link context menu item");
156 }
157 #endif
158
159 String contextMenuItemTagOpenImageInNewWindow()
160 {
161     return WEB_UI_STRING_WITH_MNEMONIC("Open Image in New Window", "Open _Image in New Window", "Open Image in New Window context menu item");
162 }
163
164 #if !PLATFORM(GTK)
165 String contextMenuItemTagDownloadImageToDisk()
166 {
167     return WEB_UI_STRING("Download Image", "Download Image context menu item");
168 }
169 #endif
170
171 String contextMenuItemTagCopyImageToClipboard()
172 {
173     return WEB_UI_STRING_WITH_MNEMONIC("Copy Image", "Cop_y Image", "Copy Image context menu item");
174 }
175
176 String contextMenuItemTagOpenFrameInNewWindow()
177 {
178     return WEB_UI_STRING_WITH_MNEMONIC("Open Frame in New Window", "Open _Frame in New Window", "Open Frame in New Window context menu item");
179 }
180
181 String contextMenuItemTagCopy()
182 {
183     return WEB_UI_STRING_WITH_MNEMONIC("Copy", "_Copy", "Copy context menu item");
184 }
185
186 String contextMenuItemTagGoBack()
187 {
188     return WEB_UI_STRING_WITH_MNEMONIC("Back", "_Back", "Back context menu item");
189 }
190
191 String contextMenuItemTagGoForward()
192 {
193     return WEB_UI_STRING_WITH_MNEMONIC("Forward", "_Forward", "Forward context menu item");
194 }
195
196 String contextMenuItemTagStop()
197 {
198     return WEB_UI_STRING_WITH_MNEMONIC("Stop", "_Stop", "Stop context menu item");
199 }
200
201 String contextMenuItemTagReload()
202 {
203     return WEB_UI_STRING_WITH_MNEMONIC("Reload", "_Reload", "Reload context menu item");
204 }
205
206 String contextMenuItemTagCut()
207 {
208     return WEB_UI_STRING_WITH_MNEMONIC("Cut", "Cu_t", "Cut context menu item");
209 }
210
211 String contextMenuItemTagPaste()
212 {
213     return WEB_UI_STRING_WITH_MNEMONIC("Paste", "_Paste", "Paste context menu item");
214 }
215
216 String contextMenuItemTagNoGuessesFound()
217 {
218     return WEB_UI_STRING("No Guesses Found", "No Guesses Found context menu item");
219 }
220
221 String contextMenuItemTagIgnoreSpelling()
222 {
223     return WEB_UI_STRING_WITH_MNEMONIC("Ignore Spelling", "_Ignore Spelling", "Ignore Spelling context menu item");
224 }
225
226 String contextMenuItemTagLearnSpelling()
227 {
228     return WEB_UI_STRING_WITH_MNEMONIC("Learn Spelling", "_Learn Spelling", "Learn Spelling context menu item");
229 }
230
231 String contextMenuItemTagLookUpInDictionary(const String& selectedString)
232 {
233 #if USE(CF)
234     auto selectedCFString = truncatedStringForLookupMenuItem(selectedString).createCFString();
235     return formatLocalizedString(WEB_UI_CFSTRING("Look Up “%@”", "Look Up context menu item with selected word"), selectedCFString.get());
236 #elif USE(GLIB)
237     return formatLocalizedString(WEB_UI_STRING("Look Up “%s”", "Look Up context menu item with selected word"), truncatedStringForLookupMenuItem(selectedString).utf8().data());
238 #else
239     return WEB_UI_STRING("Look Up “<selection>”", "Look Up context menu item with selected word").replace("<selection>", truncatedStringForLookupMenuItem(selectedString));
240 #endif
241 }
242
243 String contextMenuItemTagOpenLink()
244 {
245     return WEB_UI_STRING_WITH_MNEMONIC("Open Link", "_Open Link", "Open Link context menu item");
246 }
247
248 String contextMenuItemTagIgnoreGrammar()
249 {
250     return WEB_UI_STRING_WITH_MNEMONIC("Ignore Grammar", "Ignore _Grammar", "Ignore Grammar context menu item");
251 }
252
253 String contextMenuItemTagSpellingMenu()
254 {
255     return WEB_UI_STRING_WITH_MNEMONIC("Spelling and Grammar", "Spelling and _Grammar", "Spelling and Grammar context sub-menu item");
256 }
257
258 String contextMenuItemTagShowSpellingPanel(bool show)
259 {
260     if (show)
261         return WEB_UI_STRING_WITH_MNEMONIC("Show Spelling and Grammar", "_Show Spelling and Grammar", "menu item title");
262     return WEB_UI_STRING_WITH_MNEMONIC("Hide Spelling and Grammar", "_Hide Spelling and Grammar", "menu item title");
263 }
264
265 String contextMenuItemTagCheckSpelling()
266 {
267     return WEB_UI_STRING_WITH_MNEMONIC("Check Document Now", "_Check Document Now", "Check spelling context menu item");
268 }
269
270 String contextMenuItemTagCheckSpellingWhileTyping()
271 {
272     return WEB_UI_STRING_WITH_MNEMONIC("Check Spelling While Typing", "Check Spelling While _Typing", "Check spelling while typing context menu item");
273 }
274
275 String contextMenuItemTagCheckGrammarWithSpelling()
276 {
277     return WEB_UI_STRING_WITH_MNEMONIC("Check Grammar With Spelling", "Check _Grammar With Spelling", "Check grammar with spelling context menu item");
278 }
279
280 String contextMenuItemTagFontMenu()
281 {
282     return WEB_UI_STRING_WITH_MNEMONIC("Font", "_Font", "Font context sub-menu item");
283 }
284
285 String contextMenuItemTagBold()
286 {
287     return WEB_UI_STRING_WITH_MNEMONIC("Bold", "_Bold", "Bold context menu item");
288 }
289
290 String contextMenuItemTagItalic()
291 {
292     return WEB_UI_STRING_WITH_MNEMONIC("Italic", "_Italic", "Italic context menu item");
293 }
294
295 String contextMenuItemTagUnderline()
296 {
297     return WEB_UI_STRING_WITH_MNEMONIC("Underline", "_Underline", "Underline context menu item");
298 }
299
300 String contextMenuItemTagOutline()
301 {
302     return WEB_UI_STRING_WITH_MNEMONIC("Outline", "_Outline", "Outline context menu item");
303 }
304
305 #if !PLATFORM(GTK)
306 String contextMenuItemTagWritingDirectionMenu()
307 {
308     return WEB_UI_STRING("Paragraph Direction", "Paragraph direction context sub-menu item");
309 }
310
311 String contextMenuItemTagTextDirectionMenu()
312 {
313     return WEB_UI_STRING("Selection Direction", "Selection direction context sub-menu item");
314 }
315
316 String contextMenuItemTagDefaultDirection()
317 {
318     return WEB_UI_STRING("Default", "Default writing direction context menu item");
319 }
320
321 String contextMenuItemTagLeftToRight()
322 {
323     return WEB_UI_STRING("Left to Right", "Left to Right context menu item");
324 }
325
326 String contextMenuItemTagRightToLeft()
327 {
328     return WEB_UI_STRING("Right to Left", "Right to Left context menu item");
329 }
330 #endif
331
332 String contextMenuItemTagOpenVideoInNewWindow()
333 {
334     return WEB_UI_STRING_WITH_MNEMONIC("Open Video in New Window", "Open _Video in New Window", "Open Video in New Window context menu item");
335 }
336
337 String contextMenuItemTagOpenAudioInNewWindow()
338 {
339     return WEB_UI_STRING_WITH_MNEMONIC("Open Audio in New Window", "Open _Audio in New Window", "Open Audio in New Window context menu item");
340 }
341
342 String contextMenuItemTagDownloadVideoToDisk()
343 {
344     return WEB_UI_STRING_WITH_MNEMONIC("Download Video", "Download _Video", "Download Video To Disk context menu item");
345 }
346
347 String contextMenuItemTagDownloadAudioToDisk()
348 {
349     return WEB_UI_STRING_WITH_MNEMONIC("Download Audio", "Download _Audio", "Download Audio To Disk context menu item");
350 }
351
352 #if !PLATFORM(GTK)
353 String contextMenuItemTagCopyVideoLinkToClipboard()
354 {
355     return WEB_UI_STRING("Copy Video Address", "Copy Video Address Location context menu item");
356 }
357
358 String contextMenuItemTagCopyAudioLinkToClipboard()
359 {
360     return WEB_UI_STRING("Copy Audio Address", "Copy Audio Address Location context menu item");
361 }
362
363 String contextMenuItemTagToggleMediaControls()
364 {
365     return WEB_UI_STRING("Controls", "Media Controls context menu item");
366 }
367
368 String contextMenuItemTagShowMediaControls()
369 {
370     return WEB_UI_STRING("Show Controls", "Show Media Controls context menu item");
371 }
372
373 String contextMenuItemTagHideMediaControls()
374 {
375     return WEB_UI_STRING("Hide Controls", "Hide Media Controls context menu item");
376 }
377
378 String contextMenuItemTagToggleMediaLoop()
379 {
380     return WEB_UI_STRING("Loop", "Media Loop context menu item");
381 }
382
383 String contextMenuItemTagEnterVideoFullscreen()
384 {
385     return WEB_UI_STRING("Enter Full Screen", "Video Enter Fullscreen context menu item");
386 }
387
388 String contextMenuItemTagExitVideoFullscreen()
389 {
390     return WEB_UI_STRING_KEY("Exit Full Screen", "Exit Full Screen (context menu)", "Video Exit Fullscreen context menu item");
391 }
392 #endif
393
394 String contextMenuItemTagMediaPlay()
395 {
396     return WEB_UI_STRING_WITH_MNEMONIC("Play", "_Play", "Media Play context menu item");
397 }
398
399 String contextMenuItemTagMediaPause()
400 {
401     return WEB_UI_STRING_WITH_MNEMONIC("Pause", "_Pause", "Media Pause context menu item");
402 }
403
404 String contextMenuItemTagMediaMute()
405 {
406     return WEB_UI_STRING_WITH_MNEMONIC("Mute", "_Mute", "Media Mute context menu item");
407 }
408
409 String contextMenuItemTagInspectElement()
410 {
411     return WEB_UI_STRING_WITH_MNEMONIC("Inspect Element", "Inspect _Element", "Inspect Element context menu item");
412 }
413
414 #endif // ENABLE(CONTEXT_MENUS)
415
416 #if !PLATFORM(IOS)
417
418 String searchMenuNoRecentSearchesText()
419 {
420     return WEB_UI_STRING("No recent searches", "Label for only item in menu that appears when clicking on the search field image, when no searches have been performed");
421 }
422
423 String searchMenuRecentSearchesText()
424 {
425     return WEB_UI_STRING("Recent Searches", "label for first item in the menu that appears when clicking on the search field image, used as embedded menu title");
426 }
427
428 String searchMenuClearRecentSearchesText()
429 {
430     return WEB_UI_STRING("Clear Recent Searches", "menu item in Recent Searches menu that empties menu's contents");
431 }
432
433 #endif // !PLATFORM(IOS)
434
435 String AXWebAreaText()
436 {
437     return WEB_UI_STRING("HTML content", "accessibility role description for web area");
438 }
439
440 String AXLinkText()
441 {
442     return WEB_UI_STRING("link", "accessibility role description for link");
443 }
444
445 String AXListMarkerText()
446 {
447     return WEB_UI_STRING("list marker", "accessibility role description for list marker");
448 }
449
450 String AXImageMapText()
451 {
452     return WEB_UI_STRING("image map", "accessibility role description for image map");
453 }
454
455 String AXHeadingText()
456 {
457     return WEB_UI_STRING("heading", "accessibility role description for headings");
458 }
459
460 String AXDefinitionText()
461 {
462     return WEB_UI_STRING("definition", "role description of ARIA definition role");
463 }
464
465 String AXDescriptionListText()
466 {
467     return WEB_UI_STRING("description list", "accessibility role description of a description list");
468 }
469
470 String AXDescriptionListTermText()
471 {
472     return WEB_UI_STRING("term", "term word of a description list");
473 }
474
475 String AXDescriptionListDetailText()
476 {
477     return WEB_UI_STRING("description", "description detail");
478 }
479
480 String AXDetailsText()
481 {
482     return WEB_UI_STRING("details", "accessibility role description for a details element");
483 }
484
485 String AXSummaryText()
486 {
487     return WEB_UI_STRING("summary", "accessibility role description for a summary element");
488 }
489
490 String AXFooterRoleDescriptionText()
491 {
492     return WEB_UI_STRING("footer", "accessibility role description for a footer");
493 }
494
495 String AXFileUploadButtonText()
496 {
497     return WEB_UI_STRING("file upload button", "accessibility role description for a file upload button");
498 }
499
500 String AXOutputText()
501 {
502     return WEB_UI_STRING("output", "accessibility role description for an output element");
503 }
504
505 String AXAttachmentRoleText()
506 {
507     return WEB_UI_STRING("attachment", "accessibility role description for an attachment element");
508 }
509     
510 String AXSearchFieldCancelButtonText()
511 {
512     return WEB_UI_STRING("cancel", "accessibility description for a search field cancel button");
513 }
514
515 String AXFeedText()
516 {
517     return WEB_UI_STRING("feed", "accessibility role description for a group containing a scrollable list of articles.");
518 }
519
520 String AXFigureText()
521 {
522     return WEB_UI_STRING("figure", "accessibility role description for a figure element.");
523 }
524
525 String AXEmailFieldText()
526 {
527     return WEB_UI_STRING("email field", "accessibility role description for an email field.");
528 }
529
530 String AXTelephoneFieldText()
531 {
532     return WEB_UI_STRING("telephone number field", "accessibility role description for a telephone number field.");
533 }
534
535 String AXURLFieldText()
536 {
537     return WEB_UI_STRING("URL field", "accessibility role description for a URL field.");
538 }
539
540 String AXDateFieldText()
541 {
542     return WEB_UI_STRING("date field", "accessibility role description for a date field.");
543 }
544
545 String AXTimeFieldText()
546 {
547     return WEB_UI_STRING("time field", "accessibility role description for a time field.");
548 }
549
550 String AXDateTimeFieldText()
551 {
552     return WEB_UI_STRING("date and time field", "accessibility role description for a date and time field.");
553 }
554
555 String AXMonthFieldText()
556 {
557     return WEB_UI_STRING("month and year field", "accessibility role description for a month field.");
558 }
559
560 String AXNumberFieldText()
561 {
562     return WEB_UI_STRING("number field", "accessibility role description for a number field.");
563 }
564
565 String AXWeekFieldText()
566 {
567     return WEB_UI_STRING("week and year field", "accessibility role description for a time field.");
568 }
569
570 String AXButtonActionVerb()
571 {
572     return WEB_UI_STRING("press", "Verb stating the action that will occur when a button is pressed, as used by accessibility");
573 }
574
575 String AXRadioButtonActionVerb()
576 {
577     return WEB_UI_STRING("select", "Verb stating the action that will occur when a radio button is clicked, as used by accessibility");
578 }
579
580 String AXTextFieldActionVerb()
581 {
582     return WEB_UI_STRING("activate", "Verb stating the action that will occur when a text field is selected, as used by accessibility");
583 }
584
585 String AXCheckedCheckBoxActionVerb()
586 {
587     return WEB_UI_STRING("uncheck", "Verb stating the action that will occur when a checked checkbox is clicked, as used by accessibility");
588 }
589
590 String AXUncheckedCheckBoxActionVerb()
591 {
592     return WEB_UI_STRING("check", "Verb stating the action that will occur when an unchecked checkbox is clicked, as used by accessibility");
593 }
594
595 String AXLinkActionVerb()
596 {
597     return WEB_UI_STRING("jump", "Verb stating the action that will occur when a link is clicked, as used by accessibility");
598 }
599
600 String AXMenuListPopupActionVerb()
601 {
602     notImplemented();
603     return "select";
604 }
605
606 String AXMenuListActionVerb()
607 {
608     notImplemented();
609     return "select";
610 }
611
612 String AXListItemActionVerb()
613 {
614     notImplemented();
615     return "select";
616 }
617
618 String AXAutoFillCredentialsLabel()
619 {
620     return WEB_UI_STRING("password auto fill", "Label for the auto fill credentials button inside a text field.");
621 }
622
623 String AXAutoFillContactsLabel()
624 {
625     return WEB_UI_STRING("contact info auto fill", "Label for the auto fill contacts button inside a text field.");
626 }
627
628 String missingPluginText()
629 {
630     return WEB_UI_STRING("Missing Plug-in", "Label text to be used when a plugin is missing");
631 }
632
633 String crashedPluginText()
634 {
635     return WEB_UI_STRING("Plug-in Failure", "Label text to be used if plugin host process has crashed");
636 }
637
638 String blockedPluginByContentSecurityPolicyText()
639 {
640     return WEB_UI_STRING_KEY("Blocked Plug-in", "Blocked Plug-In (Blocked by page's Content Security Policy)", "Label text to be used if plugin is blocked by a page's Content Security Policy");
641 }
642
643 String insecurePluginVersionText()
644 {
645     return WEB_UI_STRING_KEY("Blocked Plug-in", "Blocked Plug-In (Insecure plug-in)", "Label text to be used when an insecure plug-in version was blocked from loading");
646 }
647
648 String multipleFileUploadText(unsigned numberOfFiles)
649 {
650     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);
651 }
652
653 String unknownFileSizeText()
654 {
655     return WEB_UI_STRING_KEY("Unknown", "Unknown (filesize)", "Unknown filesize FTP directory listing item");
656 }
657
658 String imageTitle(const String& filename, const IntSize& size)
659 {
660 #if USE(CF)
661     auto locale = adoptCF(CFLocaleCopyCurrent());
662     auto formatter = adoptCF(CFNumberFormatterCreate(0, locale.get(), kCFNumberFormatterDecimalStyle));
663
664     int widthInt = size.width();
665     auto width = adoptCF(CFNumberCreate(0, kCFNumberIntType, &widthInt));
666     auto widthString = adoptCF(CFNumberFormatterCreateStringWithNumber(0, formatter.get(), width.get()));
667
668     int heightInt = size.height();
669     auto height = adoptCF(CFNumberCreate(0, kCFNumberIntType, &heightInt));
670     auto heightString = adoptCF(CFNumberFormatterCreateStringWithNumber(0, formatter.get(), height.get()));
671
672     return formatLocalizedString(WEB_UI_CFSTRING("%@ %@×%@ pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename.createCFString().get(), widthString.get(), heightString.get());
673 #elif USE(GLIB)
674     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());
675 #else
676     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);
677 #endif
678 }
679
680 String mediaElementLoadingStateText()
681 {
682     return WEB_UI_STRING("Loading…", "Media controller status message when the media is loading");
683 }
684
685 String mediaElementLiveBroadcastStateText()
686 {
687     return WEB_UI_STRING("Live Broadcast", "Media controller status message when watching a live broadcast");
688 }
689
690 String localizedMediaControlElementString(const String& name)
691 {
692     if (name == "AudioElement")
693         return WEB_UI_STRING("audio playback", "accessibility label for audio element controller");
694     if (name == "VideoElement")
695         return WEB_UI_STRING("video playback", "accessibility label for video element controller");
696     if (name == "MuteButton")
697         return WEB_UI_STRING("mute", "accessibility label for mute button");
698     if (name == "UnMuteButton")
699         return WEB_UI_STRING("unmute", "accessibility label for turn mute off button");
700     if (name == "PlayButton")
701         return WEB_UI_STRING("play", "accessibility label for play button");
702     if (name == "PauseButton")
703         return WEB_UI_STRING("pause", "accessibility label for pause button");
704     if (name == "Slider")
705         return WEB_UI_STRING("movie time", "accessibility label for timeline slider");
706     if (name == "SliderThumb")
707         return WEB_UI_STRING("timeline slider thumb", "accessibility label for timeline thumb");
708     if (name == "RewindButton")
709         return WEB_UI_STRING("back 30 seconds", "accessibility label for seek back 30 seconds button");
710     if (name == "ReturnToRealtimeButton")
711         return WEB_UI_STRING("return to realtime", "accessibility label for return to real time button");
712     if (name == "CurrentTimeDisplay")
713         return WEB_UI_STRING("elapsed time", "accessibility label for elapsed time display");
714     if (name == "TimeRemainingDisplay")
715         return WEB_UI_STRING("remaining time", "accessibility label for time remaining display");
716     if (name == "StatusDisplay")
717         return WEB_UI_STRING("status", "accessibility label for movie status");
718     if (name == "EnterFullscreenButton")
719         return WEB_UI_STRING("enter full screen", "accessibility label for enter full screen button");
720     if (name == "ExitFullscreenButton")
721         return WEB_UI_STRING("exit full screen", "accessibility label for exit full screen button");
722     if (name == "SeekForwardButton")
723         return WEB_UI_STRING("fast forward", "accessibility label for fast forward button");
724     if (name == "SeekBackButton")
725         return WEB_UI_STRING("fast reverse", "accessibility label for fast reverse button");
726     if (name == "ShowClosedCaptionsButton")
727         return WEB_UI_STRING("show closed captions", "accessibility label for show closed captions button");
728     if (name == "HideClosedCaptionsButton")
729         return WEB_UI_STRING("hide closed captions", "accessibility label for hide closed captions button");
730
731     // FIXME: the ControlsPanel container should never be visible in the accessibility hierarchy.
732     if (name == "ControlsPanel")
733         return String();
734
735     ASSERT_NOT_REACHED();
736     return String();
737 }
738
739 String localizedMediaControlElementHelpText(const String& name)
740 {
741     if (name == "AudioElement")
742         return WEB_UI_STRING("audio element playback controls and status display", "accessibility help text for audio element controller");
743     if (name == "VideoElement")
744         return WEB_UI_STRING("video element playback controls and status display", "accessibility help text for video element controller");
745     if (name == "MuteButton")
746         return WEB_UI_STRING("mute audio tracks", "accessibility help text for mute button");
747     if (name == "UnMuteButton")
748         return WEB_UI_STRING("unmute audio tracks", "accessibility help text for un mute button");
749     if (name == "PlayButton")
750         return WEB_UI_STRING("begin playback", "accessibility help text for play button");
751     if (name == "PauseButton")
752         return WEB_UI_STRING("pause playback", "accessibility help text for pause button");
753     if (name == "Slider")
754         return WEB_UI_STRING("movie time scrubber", "accessibility help text for timeline slider");
755     if (name == "SliderThumb")
756         return WEB_UI_STRING("movie time scrubber thumb", "accessibility help text for timeline slider thumb");
757     if (name == "RewindButton")
758         return WEB_UI_STRING("seek movie back 30 seconds", "accessibility help text for jump back 30 seconds button");
759     if (name == "ReturnToRealtimeButton")
760         return WEB_UI_STRING("return streaming movie to real time", "accessibility help text for return streaming movie to real time button");
761     if (name == "CurrentTimeDisplay")
762         return WEB_UI_STRING("current movie time in seconds", "accessibility help text for elapsed time display");
763     if (name == "TimeRemainingDisplay")
764         return WEB_UI_STRING("number of seconds of movie remaining", "accessibility help text for remaining time display");
765     if (name == "StatusDisplay")
766         return WEB_UI_STRING("current movie status", "accessibility help text for movie status display");
767     if (name == "SeekBackButton")
768         return WEB_UI_STRING("seek quickly back", "accessibility help text for fast rewind button");
769     if (name == "SeekForwardButton")
770         return WEB_UI_STRING("seek quickly forward", "accessibility help text for fast forward button");
771     if (name == "FullscreenButton")
772         return WEB_UI_STRING("Play movie in fullscreen mode", "accessibility help text for enter fullscreen button");
773     if (name == "ShowClosedCaptionsButton")
774         return WEB_UI_STRING("start displaying closed captions", "accessibility help text for show closed captions button");
775     if (name == "HideClosedCaptionsButton")
776         return WEB_UI_STRING("stop displaying closed captions", "accessibility help text for hide closed captions button");
777
778     // The description of this button is descriptive enough that it doesn't require help text.
779     if (name == "EnterFullscreenButton")
780         return String();
781     
782     ASSERT_NOT_REACHED();
783     return String();
784 }
785
786 String localizedMediaTimeDescription(float time)
787 {
788     if (!std::isfinite(time))
789         return WEB_UI_STRING("indefinite time", "accessibility help text for an indefinite media controller time value");
790
791     int seconds = static_cast<int>(fabsf(time));
792     int days = seconds / (60 * 60 * 24);
793     int hours = seconds / (60 * 60);
794     int minutes = (seconds / 60) % 60;
795     seconds %= 60;
796
797     if (days)
798         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);
799     if (hours)
800         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);
801     if (minutes)
802         return formatLocalizedString(WEB_UI_STRING("%1$d minutes %2$d seconds", "accessibility help text for media controller time value >= 60 seconds"), minutes, seconds);
803     return formatLocalizedString(WEB_UI_STRING("%1$d seconds", "accessibility help text for media controller time value < 60 seconds"), seconds);
804 }
805
806 String validationMessageValueMissingText()
807 {
808     return WEB_UI_STRING("Fill out this field", "Validation message for required form control elements that have no value");
809 }
810
811 String validationMessageValueMissingForCheckboxText()
812 {
813     return WEB_UI_STRING("Select this checkbox", "Validation message for required checkboxes that have not be selected");
814 }
815
816 String validationMessageValueMissingForFileText()
817 {
818     return WEB_UI_STRING("Select a file", "Validation message for required file inputs that have no value");
819 }
820
821 String validationMessageValueMissingForMultipleFileText()
822 {
823     return validationMessageValueMissingForFileText();
824 }
825
826 String validationMessageValueMissingForRadioText()
827 {
828     return WEB_UI_STRING("Select one of these options", "Validation message for required radio boxes that have no selection");
829 }
830
831 String validationMessageValueMissingForSelectText()
832 {
833     return WEB_UI_STRING("Select an item in the list", "Validation message for required menu list controls that have no selection");
834 }
835
836 String validationMessageTypeMismatchText()
837 {
838     return WEB_UI_STRING("Invalid value", "Validation message for input form controls with a value not matching type");
839 }
840
841 String validationMessageTypeMismatchForEmailText()
842 {
843     return WEB_UI_STRING("Enter an email address", "Validation message for input form controls of type 'email' that have an invalid value");
844 }
845
846 String validationMessageTypeMismatchForMultipleEmailText()
847 {
848     return validationMessageTypeMismatchForEmailText();
849 }
850
851 String validationMessageTypeMismatchForURLText()
852 {
853     return WEB_UI_STRING("Enter a URL", "Validation message for input form controls of type 'url' that have an invalid value");
854 }
855
856 String validationMessagePatternMismatchText()
857 {
858     return WEB_UI_STRING("Match the requested format", "Validation message for input form controls requiring a constrained value according to pattern");
859 }
860
861 #if !PLATFORM(GTK)
862 String validationMessageTooShortText(int, int minLength)
863 {
864     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);
865 }
866
867 #if !PLATFORM(COCOA)
868 String validationMessageTooLongText(int, int maxLength)
869 {
870     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);
871 }
872 #endif
873 #endif
874
875 String validationMessageRangeUnderflowText(const String& minimum)
876 {
877 #if USE(CF)
878     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());
879 #elif USE(GLIB)
880     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());
881 #else
882     UNUSED_PARAM(minimum);
883     return WEB_UI_STRING("range underflow", "Validation message for input form controls with value lower than allowed minimum");
884 #endif
885 }
886
887 String validationMessageRangeOverflowText(const String& maximum)
888 {
889 #if USE(CF)
890     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());
891 #elif USE(GLIB)
892     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());
893 #else
894     UNUSED_PARAM(maximum);
895     return WEB_UI_STRING("range overflow", "Validation message for input form controls with value higher than allowed maximum");
896 #endif
897 }
898
899 String validationMessageStepMismatchText(const String&, const String&)
900 {
901     return WEB_UI_STRING("Enter a valid value", "Validation message for input form controls with value not respecting the step attribute");
902 }
903
904 String validationMessageBadInputForNumberText()
905 {
906     return WEB_UI_STRING("Enter a number", "Validation message for number fields where the user entered a non-number string");
907 }
908
909 String clickToExitFullScreenText()
910 {
911     return WEB_UI_STRING("Click to Exit Full Screen", "Message to display in browser window when in webkit full screen mode.");
912 }
913
914 #if ENABLE(VIDEO_TRACK)
915
916 String textTrackSubtitlesText()
917 {
918     return WEB_UI_STRING("Subtitles", "Menu section heading for subtitles");
919 }
920
921 String textTrackOffMenuItemText()
922 {
923     return WEB_UI_STRING("Off", "Menu item label for the track that represents disabling closed captions");
924 }
925
926 String textTrackAutomaticMenuItemText()
927 {
928     return formatLocalizedString(WEB_UI_STRING("Auto (Recommended)", "Menu item label for automatic track selection behavior"));
929 }
930
931 String textTrackNoLabelText()
932 {
933     return WEB_UI_STRING_KEY("Unknown", "Unknown (text track)", "Menu item label for a text track that has no other name");
934 }
935
936 String audioTrackNoLabelText()
937 {
938     return WEB_UI_STRING_KEY("Unknown", "Unknown (audio track)", "Menu item label for an audio track that has no other name");
939 }
940
941 #endif
942
943 #if ENABLE(VIDEO_TRACK) && USE(CF)
944
945 String textTrackCountryAndLanguageMenuItemText(const String& title, const String& country, const String& language)
946 {
947     return formatLocalizedString(WEB_UI_CFSTRING("%@ (%@-%@)", "Text track display name format that includes the country and language of the subtitle, in the form of 'Title (Language-Country)'"), title.createCFString().get(), language.createCFString().get(), country.createCFString().get());
948 }
949
950 String textTrackLanguageMenuItemText(const String& title, const String& language)
951 {
952     return formatLocalizedString(WEB_UI_CFSTRING("%@ (%@)", "Text track display name format that includes the language of the subtitle, in the form of 'Title (Language)'"), title.createCFString().get(), language.createCFString().get());
953 }
954
955 String closedCaptionTrackMenuItemText(const String& title)
956 {
957     return formatLocalizedString(WEB_UI_CFSTRING("%@ CC", "Text track contains closed captions"), title.createCFString().get());
958 }
959
960 String sdhTrackMenuItemText(const String& title)
961 {
962     return formatLocalizedString(WEB_UI_CFSTRING("%@ SDH", "Text track contains subtitles for the deaf and hard of hearing"), title.createCFString().get());
963 }
964
965 String easyReaderTrackMenuItemText(const String& title)
966 {
967     return formatLocalizedString(WEB_UI_CFSTRING("%@ Easy Reader", "Text track contains simplified (3rd grade level) subtitles"), title.createCFString().get());
968 }
969
970 String forcedTrackMenuItemText(const String& title)
971 {
972     return formatLocalizedString(WEB_UI_CFSTRING("%@ Forced", "Text track contains forced subtitles"), title.createCFString().get());
973 }
974
975 String audioDescriptionTrackSuffixText(const String& title)
976 {
977     return formatLocalizedString(WEB_UI_CFSTRING("%@ AD", "Text track contains Audio Descriptions"), title.createCFString().get());
978 }
979
980 #endif
981
982 String snapshottedPlugInLabelTitle()
983 {
984     return WEB_UI_STRING("Snapshotted Plug-In", "Title of the label to show on a snapshotted plug-in");
985 }
986
987 String snapshottedPlugInLabelSubtitle()
988 {
989     return WEB_UI_STRING("Click to restart", "Subtitle of the label to show on a snapshotted plug-in");
990 }
991
992 String useBlockedPlugInContextMenuTitle()
993 {
994     return formatLocalizedString(WEB_UI_STRING("Show in blocked plug-in", "Title of the context menu item to show when PDFPlugin was used instead of a blocked plugin"));
995 }
996
997 #if ENABLE(SUBTLE_CRYPTO)
998
999 String webCryptoMasterKeyKeychainLabel(const String& localizedApplicationName)
1000 {
1001 #if USE(CF)
1002     return formatLocalizedString(WEB_UI_CFSTRING("%@ WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain"), localizedApplicationName.createCFString().get());
1003 #elif USE(GLIB)
1004     return formatLocalizedString(WEB_UI_STRING("%s WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain"), localizedApplicationName.utf8().data());
1005 #else
1006     return String::fromUTF8("<application> WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain").replace("<application>", localizedApplicationName);
1007 #endif
1008 }
1009
1010 String webCryptoMasterKeyKeychainComment()
1011 {
1012     return WEB_UI_STRING("Used to encrypt WebCrypto keys in persistent storage, such as IndexedDB", "Description of WebCrypto master keys in Keychain");
1013 }
1014
1015 #endif
1016
1017 } // namespace WebCore