| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 21:49:24 -04:00
										 |  |  | #include <AK/CharacterTypes.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | #include <AK/Optional.h>
 | 
					
						
							|  |  |  | #include <AK/String.h>
 | 
					
						
							|  |  |  | #include <AK/StringView.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-27 16:38:06 -04:00
										 |  |  | #include <AK/Variant.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | #include <AK/Vector.h>
 | 
					
						
							|  |  |  | #include <LibUnicode/Forward.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Unicode { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct LanguageID { | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  |     String to_string() const; | 
					
						
							| 
									
										
										
										
											2021-09-02 21:44:12 -04:00
										 |  |  |     bool operator==(LanguageID const&) const = default; | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  |     bool is_root { false }; | 
					
						
							| 
									
										
										
										
											2021-08-30 14:31:48 -04:00
										 |  |  |     Optional<String> language {}; | 
					
						
							|  |  |  |     Optional<String> script {}; | 
					
						
							|  |  |  |     Optional<String> region {}; | 
					
						
							|  |  |  |     Vector<String> variants {}; | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 16:38:06 -04:00
										 |  |  | struct Keyword { | 
					
						
							| 
									
										
										
										
											2021-08-30 14:31:48 -04:00
										 |  |  |     String key {}; | 
					
						
							| 
									
										
										
										
											2021-09-08 15:25:35 -04:00
										 |  |  |     String value {}; | 
					
						
							| 
									
										
										
										
											2021-08-27 16:38:06 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct LocaleExtension { | 
					
						
							| 
									
										
										
										
											2021-08-30 14:31:48 -04:00
										 |  |  |     Vector<String> attributes {}; | 
					
						
							| 
									
										
										
										
											2021-08-27 16:38:06 -04:00
										 |  |  |     Vector<Keyword> keywords {}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 17:11:48 -04:00
										 |  |  | struct TransformedField { | 
					
						
							| 
									
										
										
										
											2021-09-08 15:25:35 -04:00
										 |  |  |     String key {}; | 
					
						
							|  |  |  |     String value {}; | 
					
						
							| 
									
										
										
										
											2021-08-27 17:11:48 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct TransformedExtension { | 
					
						
							|  |  |  |     Optional<LanguageID> language {}; | 
					
						
							|  |  |  |     Vector<TransformedField> fields {}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 17:24:20 -04:00
										 |  |  | struct OtherExtension { | 
					
						
							|  |  |  |     char key {}; | 
					
						
							| 
									
										
										
										
											2021-09-08 15:25:35 -04:00
										 |  |  |     String value {}; | 
					
						
							| 
									
										
										
										
											2021-08-27 17:24:20 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using Extension = Variant<LocaleExtension, TransformedExtension, OtherExtension>; | 
					
						
							| 
									
										
										
										
											2021-08-27 16:38:06 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | struct LocaleID { | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  |     String to_string() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<typename ExtensionType> | 
					
						
							| 
									
										
										
										
											2021-09-05 18:29:11 -04:00
										 |  |  |     Vector<Extension> remove_extension_type() | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-05 18:29:11 -04:00
										 |  |  |         Vector<Extension> removed_extensions {}; | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  |         auto tmp_extensions = move(extensions); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (auto& extension : tmp_extensions) { | 
					
						
							| 
									
										
										
										
											2021-09-05 18:29:11 -04:00
										 |  |  |             if (extension.has<ExtensionType>()) | 
					
						
							|  |  |  |                 removed_extensions.append(move(extension)); | 
					
						
							|  |  |  |             else | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  |                 extensions.append(move(extension)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-05 18:29:11 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return removed_extensions; | 
					
						
							| 
									
										
										
										
											2021-09-01 17:54:24 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  |     LanguageID language_id {}; | 
					
						
							| 
									
										
										
										
											2021-08-27 16:38:06 -04:00
										 |  |  |     Vector<Extension> extensions {}; | 
					
						
							| 
									
										
										
										
											2021-08-30 14:31:48 -04:00
										 |  |  |     Vector<String> private_use_extensions {}; | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-06 13:56:44 -04:00
										 |  |  | struct ListPatterns { | 
					
						
							|  |  |  |     StringView start; | 
					
						
							|  |  |  |     StringView middle; | 
					
						
							|  |  |  |     StringView end; | 
					
						
							|  |  |  |     StringView pair; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | // Note: These methods only verify that the provided strings match the EBNF grammar of the
 | 
					
						
							|  |  |  | // Unicode identifier subtag (i.e. no validation is done that the tags actually exist).
 | 
					
						
							| 
									
										
										
										
											2021-09-02 21:49:24 -04:00
										 |  |  | constexpr bool is_unicode_language_subtag(StringView subtag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // unicode_language_subtag = alpha{2,3} | alpha{5,8}
 | 
					
						
							|  |  |  |     if ((subtag.length() < 2) || (subtag.length() == 4) || (subtag.length() > 8)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     return all_of(subtag, is_ascii_alpha); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | constexpr bool is_unicode_script_subtag(StringView subtag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // unicode_script_subtag = alpha{4}
 | 
					
						
							|  |  |  |     if (subtag.length() != 4) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     return all_of(subtag, is_ascii_alpha); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | constexpr bool is_unicode_region_subtag(StringView subtag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // unicode_region_subtag = (alpha{2} | digit{3})
 | 
					
						
							|  |  |  |     if (subtag.length() == 2) | 
					
						
							|  |  |  |         return all_of(subtag, is_ascii_alpha); | 
					
						
							|  |  |  |     if (subtag.length() == 3) | 
					
						
							|  |  |  |         return all_of(subtag, is_ascii_digit); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | constexpr bool is_unicode_variant_subtag(StringView subtag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // unicode_variant_subtag = (alphanum{5,8} | digit alphanum{3})
 | 
					
						
							|  |  |  |     if ((subtag.length() >= 5) && (subtag.length() <= 8)) | 
					
						
							|  |  |  |         return all_of(subtag, is_ascii_alphanumeric); | 
					
						
							|  |  |  |     if (subtag.length() == 4) | 
					
						
							|  |  |  |         return is_ascii_digit(subtag[0]) && all_of(subtag.substring_view(1), is_ascii_alphanumeric); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 07:48:02 -04:00
										 |  |  | bool is_type_identifier(StringView); | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Optional<LanguageID> parse_unicode_language_id(StringView); | 
					
						
							|  |  |  | Optional<LocaleID> parse_unicode_locale_id(StringView); | 
					
						
							|  |  |  | Optional<String> canonicalize_unicode_locale_id(LocaleID&); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:17:08 -04:00
										 |  |  | String const& default_locale(); | 
					
						
							|  |  |  | bool is_locale_available(StringView locale); | 
					
						
							| 
									
										
										
										
											2021-09-05 12:16:35 -04:00
										 |  |  | Optional<Locale> locale_from_string(StringView locale); | 
					
						
							| 
									
										
										
										
											2021-08-24 22:17:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 08:17:01 -04:00
										 |  |  | Optional<StringView> get_locale_language_mapping(StringView locale, StringView language); | 
					
						
							| 
									
										
										
										
											2021-08-26 06:56:17 -04:00
										 |  |  | Optional<StringView> get_locale_territory_mapping(StringView locale, StringView territory); | 
					
						
							| 
									
										
										
										
											2021-08-26 08:29:39 -04:00
										 |  |  | Optional<StringView> get_locale_script_mapping(StringView locale, StringView script); | 
					
						
							| 
									
										
										
										
											2021-08-26 08:38:54 -04:00
										 |  |  | Optional<StringView> get_locale_currency_mapping(StringView locale, StringView currency); | 
					
						
							| 
									
										
										
										
											2021-09-06 13:56:44 -04:00
										 |  |  | Optional<ListPatterns> get_locale_list_patterns(StringView locale, StringView type, StringView style); | 
					
						
							| 
									
										
										
										
											2021-08-24 22:17:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-30 14:56:23 -04:00
										 |  |  | Optional<StringView> resolve_language_alias(StringView language); | 
					
						
							|  |  |  | Optional<StringView> resolve_territory_alias(StringView territory); | 
					
						
							|  |  |  | Optional<StringView> resolve_script_tag_alias(StringView script_tag); | 
					
						
							|  |  |  | Optional<StringView> resolve_variant_alias(StringView variant); | 
					
						
							|  |  |  | Optional<StringView> resolve_subdivision_alias(StringView subdivision); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 18:21:42 -04:00
										 |  |  | Optional<LanguageID> add_likely_subtags(LanguageID const& language_id); | 
					
						
							| 
									
										
										
										
											2021-09-02 21:44:12 -04:00
										 |  |  | Optional<LanguageID> remove_likely_subtags(LanguageID const& language_id); | 
					
						
							| 
									
										
										
										
											2021-08-31 09:40:24 -04:00
										 |  |  | String resolve_most_likely_territory(LanguageID const& language_id, StringView territory_alias); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 22:15:38 -04:00
										 |  |  | } |