From f8bb2545a5e562e68df99aea0a8810cd7a6d3cee Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:24:22 +0530 Subject: [PATCH 01/26] patch: apply 000-MSFT-Patch-Change_Windows_datafile_name_to_omit_version_number Windows OS ICU build uses a versionless data filename (icudtl.dat) instead of versioned (icudtl78l.dat) so the filename does not churn each upgrade. Guarded by ICU_DATA_DIR_WINDOWS; public/SDK build is unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 9efd3db92a4f9400fff0e9c1cc5c6baace0338af) --- icu/icu4c/source/common/ucmndata.h | 8 ++++++-- icu/icu4c/source/tools/toolutil/pkg_gencmn.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/icu/icu4c/source/common/ucmndata.h b/icu/icu4c/source/common/ucmndata.h index 486b4fd7b5f..36f82f6f9ea 100644 --- a/icu/icu4c/source/common/ucmndata.h +++ b/icu/icu4c/source/common/ucmndata.h @@ -30,8 +30,12 @@ #include "unicode/udata.h" #include "umapfile.h" - -#define COMMON_DATA_NAME U_ICUDATA_NAME +// MSFT-Change: In the Windows OS ICU build, we only have one data package, and we use a versionless name in filename. +#if defined(ICU_DATA_DIR_WINDOWS) +# define COMMON_DATA_NAME "icudtl" +#else +# define COMMON_DATA_NAME U_ICUDATA_NAME +#endif typedef struct { uint16_t headerSize; diff --git a/icu/icu4c/source/tools/toolutil/pkg_gencmn.cpp b/icu/icu4c/source/tools/toolutil/pkg_gencmn.cpp index c1a46e9aed1..054208170af 100644 --- a/icu/icu4c/source/tools/toolutil/pkg_gencmn.cpp +++ b/icu/icu4c/source/tools/toolutil/pkg_gencmn.cpp @@ -22,7 +22,13 @@ #define STRING_STORE_SIZE 200000 -#define COMMON_DATA_NAME U_ICUDATA_NAME +// MSFT-Change: In the Windows OS ICU build, we only have one data package, and we use a versionless name in filename. +#if defined(ICU_DATA_DIR_WINDOWS) +# define COMMON_DATA_NAME "icudtl" +#else +# define COMMON_DATA_NAME U_ICUDATA_NAME +#endif + #define DATA_TYPE "dat" /* ICU package data file format (.dat files) ------------------------------- *** From ae3da475c3f1f62aacf1e56850fd649a3050b276 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:26:36 +0530 Subject: [PATCH 02/26] patch: apply 001-MSFT-Patch-ICU_Header_changes_for_Windows Add IGNORE_WINDOWS_HEADERS_START/END markers around regions of putil.h and unistr.h that should be stripped from the Windows OS SDK header. putil.h: data-directory + timezone-files-directory + filesystem-separator constants are not user-mutable in Windows OS ICU. unistr.h: UStringCaseMapper internal callback typedef is meaningless to SDK consumers that don't expose C++ UnicodeString. No C/C++ semantics change; markers are pure comments interpreted by the Windows SDK header-stripping tool only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 806ffb6177806d4d11abcd8756fa651a9357b856) --- icu/icu4c/source/common/unicode/putil.h | 6 +++++- icu/icu4c/source/common/unicode/unistr.h | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/icu/icu4c/source/common/unicode/putil.h b/icu/icu4c/source/common/unicode/putil.h index 500c21252fc..c0b34556ebc 100644 --- a/icu/icu4c/source/common/unicode/putil.h +++ b/icu/icu4c/source/common/unicode/putil.h @@ -42,6 +42,9 @@ * functions may have to be re-implemented. */ +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: The Windows OS version of ICU uses a single fixed data file. + /** * Return the ICU data directory. * The data directory is where common format ICU data files (.dat files) @@ -112,7 +115,7 @@ U_CAPI const char * U_EXPORT2 u_getTimeZoneFilesDirectory(UErrorCode *status); U_CAPI void U_EXPORT2 u_setTimeZoneFilesDirectory(const char *path, UErrorCode *status); #endif /* U_HIDE_INTERNAL_API */ - +// MSFT-TODO: Should these be considered for Windows? /** * @{ * Filesystem file and path separator characters. @@ -134,6 +137,7 @@ U_CAPI void U_EXPORT2 u_setTimeZoneFilesDirectory(const char *path, UErrorCode * # define U_FILE_ALT_SEP_STRING "/" # define U_PATH_SEP_STRING ":" #endif +//IGNORE_WINDOWS_HEADERS_END /** @} */ diff --git a/icu/icu4c/source/common/unicode/unistr.h b/icu/icu4c/source/common/unicode/unistr.h index 161b84527a6..145bb8ea3ef 100644 --- a/icu/icu4c/source/common/unicode/unistr.h +++ b/icu/icu4c/source/common/unicode/unistr.h @@ -60,6 +60,9 @@ class Edits; U_NAMESPACE_END +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: Hiding the @internal API below, since we don't expose the C++ UnicodeString. + // Not #ifndef U_HIDE_INTERNAL_API because UnicodeString needs the UStringCaseMapper. /** * Internal string case mapping function type. @@ -77,6 +80,8 @@ UStringCaseMapper(int32_t caseLocale, uint32_t options, icu::Edits *edits, UErrorCode &errorCode); +//IGNORE_WINDOWS_HEADERS_END + U_NAMESPACE_BEGIN class Locale; // unicode/locid.h From 9ab984daf42be3ba0f35ed7931852ede927c72a7 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:42:41 +0530 Subject: [PATCH 03/26] patch: apply 004-MSFT-Patch-ICU_Header_Additional_changes_for_Windows Add IGNORE_WINDOWS_HEADERS_START/END markers around regions of 4 public ICU headers so the Windows SDK header-stripping tool omits them. Reworked from ICU 72 form (8/12 hunks landed at new offsets, 2 hand-ported, 2 dropped): - uchar.h: wraps U_UNICODE_VERSION macro (runtime-variable; SDK consumers should use u_getUnicodeVersion() API instead). - uconfig.h: wraps uconfig_local.h include hook and UCONFIG_USE_WINDOWS_ LCID_MAPPING_API switch (compile-time settings irrelevant to SDK). - utypes.h: wraps ICUDATA naming scheme constants (Windows OS uses a fixed single-data-file layout). - uversion.h: wraps U_NAMESPACE_BEGIN/END and C++ namespace plumbing (Windows OS SDK exposes flat C APIs only). Dropped umachine.h hunks: U_OVERRIDE and U_FINAL macros no longer exist in ICU 78 (upstream removed them in favor of using the C++11 keywords directly). The patch's intent for that file is resolved by upstream. No C/C++ semantics change; markers are comments consumed only by the Windows SDK header-stripping tool. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit acee30d036cd4e76028aeb78b72fa774c9896d0d) --- icu/icu4c/source/common/unicode/uchar.h | 6 ++++++ icu/icu4c/source/common/unicode/uconfig.h | 11 +++++++++++ icu/icu4c/source/common/unicode/utypes.h | 7 +++++++ icu/icu4c/source/common/unicode/uversion.h | 6 ++++++ 4 files changed, 30 insertions(+) diff --git a/icu/icu4c/source/common/unicode/uchar.h b/icu/icu4c/source/common/unicode/uchar.h index d33b8cf7f3c..047d61c8122 100644 --- a/icu/icu4c/source/common/unicode/uchar.h +++ b/icu/icu4c/source/common/unicode/uchar.h @@ -49,6 +49,10 @@ typedef struct USet USet; U_CDECL_BEGIN +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: The value of these macros can change at runtime, so the API u_getUnicodeVersion +// should be used instead of any version macro. + /*==========================================================================*/ /* Unicode version number */ /*==========================================================================*/ @@ -63,6 +67,8 @@ U_CDECL_BEGIN */ #define U_UNICODE_VERSION "17.0" +//IGNORE_WINDOWS_HEADERS_END + /** * \file * \brief C API: Unicode Properties diff --git a/icu/icu4c/source/common/unicode/uconfig.h b/icu/icu4c/source/common/unicode/uconfig.h index c0488d502bf..3c118288665 100644 --- a/icu/icu4c/source/common/unicode/uconfig.h +++ b/icu/icu4c/source/common/unicode/uconfig.h @@ -45,6 +45,10 @@ * @stable ICU 2.4 */ +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: Since these are compile time settings, it doesn't make sense to +// load a user config header in the Windows OS SDK version. + /** * If this switch is defined, ICU will attempt to load a header file named "uconfig_local.h" * prior to determining default settings for uconfig variables. @@ -55,6 +59,8 @@ #include "uconfig_local.h" #endif +//IGNORE_WINDOWS_HEADERS_END + /** * \def U_DEBUG * Determines whether to include debugging code. @@ -379,6 +385,9 @@ # define UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE UMSGPAT_APOS_DOUBLE_OPTIONAL #endif +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: We always use the OS LCID mapping API for the Windows OS build of ICU. + /** * \def UCONFIG_USE_WINDOWS_LCID_MAPPING_API * On platforms where U_PLATFORM_HAS_WIN32_API is true, this switch determines @@ -391,6 +400,8 @@ # define UCONFIG_USE_WINDOWS_LCID_MAPPING_API 1 #endif +//IGNORE_WINDOWS_HEADERS_END + /* i18n library switches ---------------------------------------------------- */ /** diff --git a/icu/icu4c/source/common/unicode/utypes.h b/icu/icu4c/source/common/unicode/utypes.h index f53b7536f20..0f6bc70fd54 100644 --- a/icu/icu4c/source/common/unicode/utypes.h +++ b/icu/icu4c/source/common/unicode/utypes.h @@ -104,6 +104,11 @@ /** @} */ +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: For the Windows OS version of ICU, it doesn't make sense to expose these +// constants which are only for loading the main ICU data file. We also don't +// support using a data DLL either, so omit them from the Windows SDK header. + /*===========================================================================*/ /* ICUDATA naming scheme */ /*===========================================================================*/ @@ -191,6 +196,8 @@ #endif #endif /* U_HIDE_INTERNAL_API */ +//IGNORE_WINDOWS_HEADERS_END + /** * \def NULL * Define NULL if necessary, to nullptr for C++ and to ((void *)0) for C. diff --git a/icu/icu4c/source/common/unicode/uversion.h b/icu/icu4c/source/common/unicode/uversion.h index 450794ac1ba..dc5ed687cf5 100644 --- a/icu/icu4c/source/common/unicode/uversion.h +++ b/icu/icu4c/source/common/unicode/uversion.h @@ -58,6 +58,10 @@ */ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; +//IGNORE_WINDOWS_HEADERS_START +// MSFT-Change: Since the Windows OS ICU headers are for C APIs only, we don't +// need or want any C++ namespace support. + /*===========================================================================*/ /* C++ namespace if supported. Versioned unless versioning is disabled. */ /*===========================================================================*/ @@ -184,6 +188,8 @@ namespace U_HEADER_ONLY_NAMESPACE {} #endif /* __cplusplus */ +//IGNORE_WINDOWS_HEADERS_END + /*===========================================================================*/ /* General version helper functions. Definitions in putil.c */ /*===========================================================================*/ From efd787dd6e87c84d60c5466be41d8fada2c39afe Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:45:28 +0530 Subject: [PATCH 04/26] patch: apply 006-MSFT-Patch-ICU_Make_u_cleanup_NOOP_for_OS_ICU Make u_cleanup() a no-op for the Windows OS ICU build to prevent race-condition crashes when multiple threads (Windows.Globalization, default OS sort, app code) are concurrently using ICU. - Real implementation renamed to uprv_u_cleanup() (private; combined DLL can still call it; not exported from DEF). - New public u_cleanup() under ICU_DATA_DIR_WINDOWS returns no-op; otherwise delegates to uprv_u_cleanup() so public/Nuget consumers retain the original behavior. Reworked: ICU 78 modernized the function signature from (void) to () and NULL to nullptr; the rework matches the new style. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 0b6d31fb914b0998715d8b1cd3bb4ad1c9f52968) --- icu/icu4c/source/common/ucln_cmn.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/icu/icu4c/source/common/ucln_cmn.cpp b/icu/icu4c/source/common/ucln_cmn.cpp index c63bd221929..6d7d2536381 100644 --- a/icu/icu4c/source/common/ucln_cmn.cpp +++ b/icu/icu4c/source/common/ucln_cmn.cpp @@ -36,8 +36,9 @@ static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON]; The cleanup order is important in this function. Please be sure that you have read ucln.h ************************************************/ +// MSFT-Change: Make u_cleanup a no-op for the Windows OS ICU version. U_CAPI void U_EXPORT2 -u_cleanup() +uprv_u_cleanup() { UTRACE_ENTRY_OC(UTRACE_U_CLEANUP); icu::umtx_lock(nullptr); /* Force a memory barrier, so that we are sure to see */ @@ -52,6 +53,31 @@ u_cleanup() /*#endif*/ } +U_CAPI void U_EXPORT2 +u_cleanup() +{ +// When ICU is built as an OS component for Windows, we make the public function u_cleanup +// effectively a no-op because of the following: +// - It is not thread-safe and *forcefully* unloads the ICU data file. +// - The ICU library can simultaneously be used by other threads when this happens, +// either by Windows.Globalization, or by sorting functions when ICU sorting is default. +// - This means an App can call the function at any time, which will cause random crashes. :( +// +// We don't completely remove the functionality though, as we still want/need to be able to +// unload resources when the ICU DLL is unloaded. Instead we make it a private (uprv) function +// so that the combined DLL can still call it, and we don't export it in the DEF file. +// +// Note: We don't unconditionally do this though, as we don't want to alter the behavior of the +// public function when ICU when used/consumed in a Nuget package (for example). +// +#if defined(ICU_DATA_DIR_WINDOWS) + ((void)0); // no-op. + return; +#else + uprv_u_cleanup(); +#endif +} + U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType) { if (gLibCleanupFunctions[libType]) From 957662bc4462a09090098358076080c39545dd72 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:48:24 +0530 Subject: [PATCH 05/26] patch: apply 007-MSFT-Patch-cldr_to_icu_build_tool_Windows_changes (hunk 1 only) icu4c/source/data/build.xml: Change CLDR_TMP_DIR from cldr-aux to cldr-staging (MS-ICU pipeline uses cldr-staging as its CLDR temp directory rather than vanilla CLDR's cldr-aux default). Dropped hunk 2 (build-icu-data.xml): target file removed in ICU 73+; the cldr-to-icu data build toolchain is now driven by config.xml + Maven + Cldr2Icu.java rather than that Ant build script. The hunk's intent (forceDelete=true; mvn->mvn.cmd for Windows) does not have a direct landing zone in the new toolchain. If Maven-on-Windows breaks during Step 6 data build, fix at the new invocation point then. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit c7c3e66345128e487e4ea002bcbc5e9edaff8bd7) --- icu/icu4c/source/data/build.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/icu/icu4c/source/data/build.xml b/icu/icu4c/source/data/build.xml index a7efc0675b1..3e3c0425703 100644 --- a/icu/icu4c/source/data/build.xml +++ b/icu/icu4c/source/data/build.xml @@ -43,7 +43,8 @@ - + + From 62fc00d752ec4e7c33270e40dc4755bd63e07455 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:49:42 +0530 Subject: [PATCH 06/26] patch: apply 008-MSFT-Patch-ICU_Dont_use_extended_ICU_data_in_Windows Under ICU_DATA_DIR_WINDOWS, make extendICUData() return early (false). Windows OS ICU has only one data file (versionless icudtl.dat from patch 000) and never has extended data; running the normal extension path would try to load icudt78l.dat on top of the already-loaded common data, creating redundant work or load conflicts. Reworked: ICU 78 modernized FALSE -> false in this file; the new guard matches that style. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 38dd5f74107c9c9751e619d00112552f73c1f468) --- icu/icu4c/source/common/udata.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/icu/icu4c/source/common/udata.cpp b/icu/icu4c/source/common/udata.cpp index b9b737f177e..38a501719e3 100644 --- a/icu/icu4c/source/common/udata.cpp +++ b/icu/icu4c/source/common/udata.cpp @@ -809,6 +809,16 @@ openCommonData(const char *path, /* Path from OpenChoice? */ *----------------------------------------------------------------------*/ static UBool extendICUData(UErrorCode *pErr) { +// MSFT-Change: For the Windows OS build of ICU, we only have one data file +// and we don't use the extended data at all. We make this function a no-op +// in order to save a few cycles for perf, but more importantly so that +// we don't try to load a versioned data file (ex: icudt78l.dat) after +// already loading the non-versioned common data file. +#if defined(ICU_DATA_DIR_WINDOWS) + (void)pErr; // suppress unused variable. + return false; +#endif + UDataMemory *pData; UDataMemory copyPData; UBool didUpdate = false; From 3b5926c054b4ae132433e29396ff127ea59b6cfc Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:51:27 +0530 Subject: [PATCH 07/26] patch: apply 010-MSFT-PATCH-ICU_Modify_make_dist_for_Linux Two Linux make-dist adjustments: - DISTY_FILES strips DISTY_DOC_ZIP. MS-ICU does not build Doxygen docs in its release pipeline; the dist target would otherwise fail looking for a non-existent docs.zip. - git archive path adapted for MS-ICU GitHub layout: cd ../.. (two levels up instead of one) and HEAD:icu/icu4c/ (extra icu/ prefix) because microsoft/icu has its icu4c tree at icu/icu4c/ rather than vanilla ICU's top-level icu4c/. Reworked: ICU 78 fixed an upstream typo (we watn -> we want) and added testdata/ copy logic to dist.mk (lines 72-73); both are preserved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 2dfc0780e2e66b7da6ed969b4f5b7035b0aac098) --- icu/icu4c/source/config/dist.mk | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/icu/icu4c/source/config/dist.mk b/icu/icu4c/source/config/dist.mk index a8bda27d8cd..319470143c6 100644 --- a/icu/icu4c/source/config/dist.mk +++ b/icu/icu4c/source/config/dist.mk @@ -37,7 +37,9 @@ DISTY_DATA_ZIP=$(DISTY_FILE_DIR)/$(DISTY_PREFIX)-data.zip DISTY_DAT:=$(firstword $(wildcard data/out/tmp/icudt$(SO_TARGET_VERSION_MAJOR)*.dat)) DISTY_FILES_SRC=$(DISTY_FILE_TGZ) $(DISTY_FILE_ZIP) -DISTY_FILES=$(DISTY_FILES_SRC) $(DISTY_DOC_ZIP) +# MSFT-Change: We only want the tgz for now, as we don't currently build the docs. +#DISTY_FILES=$(DISTY_FILES_SRC) $(DISTY_DOC_ZIP) +DISTY_FILES=$(DISTY_FILES_SRC) # colon-equals because we want to run this once! EXCLUDES_FILE:=$(shell mktemp) @@ -66,7 +68,8 @@ $(DISTY_FILE_TGZ) $(DISTY_FILE_ZIP) $(DISTY_DATA_ZIP): $(DISTY_DAT) $(DISTY_TMP @echo Export icu4c@$(GITVER) to "$(DISTY_TMP)/icu" -$(RMV) $(DISTY_FILE) $(DISTY_TMP) $(MKINSTALLDIRS) $(DISTY_TMP) - ( cd $(ICU4CTOP)/.. && git archive --format=tar --prefix=icu/ HEAD:icu4c/ ) | ( cd "$(DISTY_TMP)" && tar xf - ) + # MSFT-Change: Adjust the path for the GitHub repo location. + ( cd $(ICU4CTOP)/../.. && git archive --format=tar --prefix=icu/ HEAD:icu/icu4c/ ) | ( cd "$(DISTY_TMP)" && tar xf - ) # special handling for LICENSE file. The symlinks will be included as files by tar and zip. cp -fv $(ICU4CTOP)/LICENSE "$(DISTY_TMP)/LICENSE" # Copy top-level testdata directory so it's a sibling of the source/ directory From 896076eb3da8a177a2ad56e2851a29fdeb900ab6 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 10:51:59 +0530 Subject: [PATCH 08/26] patch: apply 011-MSFT-Patch_change-tests-data-to-not-include-blocked-regions Remove test entries for blocked region codes (DG, EA, EH, IC, etc.) from ICU's region tests. MS-ICU strips these codes from data via GeoPol policy; the tests would otherwise fail looking up regions that no longer exist in MS-ICU's region data. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 1d57b24e8dd5f7c0544582f94a99d86e38b808f2) --- icu/icu4c/source/test/cintltst/uregiontest.c | 4 ---- icu/icu4c/source/test/intltest/regiontst.cpp | 4 ---- 2 files changed, 8 deletions(-) diff --git a/icu/icu4c/source/test/cintltst/uregiontest.c b/icu/icu4c/source/test/cintltst/uregiontest.c index 0dd896817c0..decac11892a 100644 --- a/icu/icu4c/source/test/cintltst/uregiontest.c +++ b/icu/icu4c/source/test/cintltst/uregiontest.c @@ -152,17 +152,14 @@ static KnownRegion knownRegions[] = { { "CZ" , 203, "151", URGN_TERRITORY, "150" }, { "DD" , 276, "155", URGN_TERRITORY, "150" }, { "DE" , 276, "155", URGN_TERRITORY, "150" }, - { "DG" , -1 , "QO" , URGN_TERRITORY, "009" }, { "DJ" , 262, "014", URGN_TERRITORY, "002" }, { "DK" , 208, "154", URGN_TERRITORY, "150" }, { "DM" , 212, "029", URGN_TERRITORY, "019" }, { "DO" , 214, "029", URGN_TERRITORY, "019" }, { "DZ" , 12, "015", URGN_TERRITORY, "002" }, - { "EA" , -1, "015", URGN_TERRITORY, "002" }, { "EC" , 218, "005", URGN_TERRITORY, "019" }, { "EE" , 233, "154", URGN_TERRITORY, "150" }, { "EG" , 818, "015", URGN_TERRITORY, "002" }, - { "EH" , 732, "015", URGN_TERRITORY, "002" }, { "ER" , 232, "014", URGN_TERRITORY, "002" }, { "ES" , 724, "039", URGN_TERRITORY, "150" }, { "ET" , 231, "014", URGN_TERRITORY, "002" }, @@ -199,7 +196,6 @@ static KnownRegion knownRegions[] = { { "HR" , 191, "039", URGN_TERRITORY, "150" }, { "HT" , 332, "029", URGN_TERRITORY, "019" }, { "HU" , 348, "151", URGN_TERRITORY, "150" }, - { "IC" , -1, "015", URGN_TERRITORY, "002" }, { "ID" , 360, "035", URGN_TERRITORY, "142" }, { "IE" , 372, "154", URGN_TERRITORY, "150" }, { "IL" , 376, "145", URGN_TERRITORY, "142" }, diff --git a/icu/icu4c/source/test/intltest/regiontst.cpp b/icu/icu4c/source/test/intltest/regiontst.cpp index cdbeac793a7..f2b06fd3bb8 100644 --- a/icu/icu4c/source/test/intltest/regiontst.cpp +++ b/icu/icu4c/source/test/intltest/regiontst.cpp @@ -124,17 +124,14 @@ static KnownRegion knownRegions[] = { { "CZ" , 203, "151", URGN_TERRITORY, "150" }, { "DD" , 276, "155", URGN_TERRITORY, "150" }, { "DE" , 276, "155", URGN_TERRITORY, "150" }, - { "DG" , -1 , "QO" , URGN_TERRITORY, "009" }, { "DJ" , 262, "014", URGN_TERRITORY, "002" }, { "DK" , 208, "154", URGN_TERRITORY, "150" }, { "DM" , 212, "029", URGN_TERRITORY, "019" }, { "DO" , 214, "029", URGN_TERRITORY, "019" }, { "DZ" , 12, "015", URGN_TERRITORY, "002" }, - { "EA" , -1, "015", URGN_TERRITORY, "002" }, { "EC" , 218, "005", URGN_TERRITORY, "019" }, { "EE" , 233, "154", URGN_TERRITORY, "150" }, { "EG" , 818, "015", URGN_TERRITORY, "002" }, - { "EH" , 732, "015", URGN_TERRITORY, "002" }, { "ER" , 232, "014", URGN_TERRITORY, "002" }, { "ES" , 724, "039", URGN_TERRITORY, "150" }, { "ET" , 231, "014", URGN_TERRITORY, "002" }, @@ -171,7 +168,6 @@ static KnownRegion knownRegions[] = { { "HR" , 191, "039", URGN_TERRITORY, "150" }, { "HT" , 332, "029", URGN_TERRITORY, "019" }, { "HU" , 348, "151", URGN_TERRITORY, "150" }, - { "IC" , -1, "015", URGN_TERRITORY, "002" }, { "ID" , 360, "035", URGN_TERRITORY, "142" }, { "IE" , 372, "154", URGN_TERRITORY, "150" }, { "IL" , 376, "145", URGN_TERRITORY, "142" }, From 727cf11cb45df99751646e8667c72a86a3106d1d Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 11:06:37 +0530 Subject: [PATCH 09/26] patch: apply 012-MSFT-Patch-StaticLink_VCRuntime_VCStartup_STL_but_DynamicLink_UCRT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Statically link VCRuntime + VCStartup + STL into icuuc.dll / icuin.dll, but keep UCRT (ucrtbase.dll) dynamic. This eliminates the VC Redist dependency for consumers — Windows 10+ ships UCRT, but VCRuntime and STL would otherwise require manual VC Redist install. Mechanism (applied to both common.vcxproj and i18n.vcxproj, Debug + Release blocks): - RuntimeLibrary: MultiThreadedDebugDLL/MultiThreadedDLL -> MultiThreaded Debug/MultiThreaded (compiler switches to static C++ runtime). - IgnoreSpecificDefaultLibraries=libucrtd.lib;libucrt.lib (linker drops the static UCRT pulled in by /MT[d]). - /DEFAULTLIB:ucrt[d].lib via AdditionalOptions (force the dynamic UCRT). Reworked: ICU 78 already uses $(IcuMajorVersion) macro for DLL names (unchanged by this patch). Verified no arch-specific overrides exist — only generic Debug/Release ItemDefinitionGroups — so the fix applies uniformly to x86, x64, and ARM64. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 3e56c84d4278ad79e5b70b3fc8d6d4a425469a19) --- icu/icu4c/source/common/common.vcxproj | 12 ++++++++++-- icu/icu4c/source/i18n/i18n.vcxproj | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/icu/icu4c/source/common/common.vcxproj b/icu/icu4c/source/common/common.vcxproj index 81f7d0c20f9..b0cb5c17824 100644 --- a/icu/icu4c/source/common/common.vcxproj +++ b/icu/icu4c/source/common/common.vcxproj @@ -53,24 +53,32 @@ RBBI_DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebugDLL + + MultiThreadedDebug ..\..\$(IcuBinOutputDir)\icuuc$(IcuMajorVersion)d.dll .\..\..\$(IcuLibOutputDir)\icuucd.pdb ..\..\$(IcuLibOutputDir)\icuucd.lib + + libucrtd.lib;libucrt.lib + /DEFAULTLIB:ucrtd.lib %(AdditionalOptions) - MultiThreadedDLL + + MultiThreaded true ..\..\$(IcuBinOutputDir)\icuuc$(IcuMajorVersion).dll .\..\..\$(IcuLibOutputDir)\icuuc.pdb ..\..\$(IcuLibOutputDir)\icuuc.lib + + libucrtd.lib;libucrt.lib + /DEFAULTLIB:ucrt.lib %(AdditionalOptions) diff --git a/icu/icu4c/source/i18n/i18n.vcxproj b/icu/icu4c/source/i18n/i18n.vcxproj index 9803e1d1d5b..b7c1cf4fa3e 100644 --- a/icu/icu4c/source/i18n/i18n.vcxproj +++ b/icu/icu4c/source/i18n/i18n.vcxproj @@ -54,19 +54,24 @@ - MultiThreadedDebugDLL + + MultiThreadedDebug icuucd.lib;%(AdditionalDependencies) ..\..\$(IcuBinOutputDir)\icuin$(IcuMajorVersion)d.dll .\..\..\$(IcuLibOutputDir)\icuind.pdb ..\..\$(IcuLibOutputDir)\icuind.lib + + libucrtd.lib;libucrt.lib + /DEFAULTLIB:ucrtd.lib %(AdditionalOptions) - MultiThreadedDLL + + MultiThreaded true @@ -74,6 +79,9 @@ ..\..\$(IcuBinOutputDir)\icuin$(IcuMajorVersion).dll .\..\..\$(IcuLibOutputDir)\icuin.pdb ..\..\$(IcuLibOutputDir)\icuin.lib + + libucrtd.lib;libucrt.lib + /DEFAULTLIB:ucrt.lib %(AdditionalOptions) From fc6ca4611b11c2ec2f5c2b76eaf735179677db92 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 11:09:41 +0530 Subject: [PATCH 10/26] patch: apply 013-MSFT-Patch-ICU_Add_version_number_to_PDB_names Add ICU major version number to PDB (debug symbol) filenames so they match the DLL filenames. Prevents PDB filename collision when two ICU versions are deployed side-by-side and lets debuggers correctly correlate symbols across versions. Files updated: common.vcxproj, i18n.vcxproj, stubdata.vcxproj. PDBs become icuuc78.pdb / icuuc78d.pdb, icuin78.pdb / icuin78d.pdb, icudt78.pdb (matching the existing icuuc78.dll / icuuc78d.dll / icuin78.dll / icuin78d.dll / icudt78.dll naming). Reworked: Used $(IcuMajorVersion) MSBuild macro rather than hardcoding 78. This is the same pattern ICU 78's tags already use in these vcxproj files, so future ICU upgrades won't need to touch these strings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 01f38e6a52d0330dfcd587034ba162322ddfb014) --- icu/icu4c/source/common/common.vcxproj | 9 ++++++--- icu/icu4c/source/i18n/i18n.vcxproj | 9 ++++++--- icu/icu4c/source/stubdata/stubdata.vcxproj | 6 ++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/icu/icu4c/source/common/common.vcxproj b/icu/icu4c/source/common/common.vcxproj index b0cb5c17824..f0f13aa1e2e 100644 --- a/icu/icu4c/source/common/common.vcxproj +++ b/icu/icu4c/source/common/common.vcxproj @@ -41,7 +41,8 @@ $(OutDir)/icuuc.pch $(OutDir)/ $(OutDir)/ - $(OutDir)/icuuc.pdb + + $(OutDir)/icuuc$(IcuMajorVersion).pdb @@ -58,7 +59,8 @@ ..\..\$(IcuBinOutputDir)\icuuc$(IcuMajorVersion)d.dll - .\..\..\$(IcuLibOutputDir)\icuucd.pdb + + .\..\..\$(IcuLibOutputDir)\icuuc$(IcuMajorVersion)d.pdb ..\..\$(IcuLibOutputDir)\icuucd.lib libucrtd.lib;libucrt.lib @@ -74,7 +76,8 @@ ..\..\$(IcuBinOutputDir)\icuuc$(IcuMajorVersion).dll - .\..\..\$(IcuLibOutputDir)\icuuc.pdb + + .\..\..\$(IcuLibOutputDir)\icuuc$(IcuMajorVersion).pdb ..\..\$(IcuLibOutputDir)\icuuc.lib libucrtd.lib;libucrt.lib diff --git a/icu/icu4c/source/i18n/i18n.vcxproj b/icu/icu4c/source/i18n/i18n.vcxproj index b7c1cf4fa3e..2a674773021 100644 --- a/icu/icu4c/source/i18n/i18n.vcxproj +++ b/icu/icu4c/source/i18n/i18n.vcxproj @@ -42,7 +42,8 @@ $(OutDir)/icuin.pch $(OutDir)/ $(OutDir)/ - $(OutDir)/icuin.pdb + + $(OutDir)/icuin$(IcuMajorVersion).pdb ../common;%(AdditionalIncludeDirectories) @@ -60,7 +61,8 @@ icuucd.lib;%(AdditionalDependencies) ..\..\$(IcuBinOutputDir)\icuin$(IcuMajorVersion)d.dll - .\..\..\$(IcuLibOutputDir)\icuind.pdb + + .\..\..\$(IcuLibOutputDir)\icuin$(IcuMajorVersion)d.pdb ..\..\$(IcuLibOutputDir)\icuind.lib libucrtd.lib;libucrt.lib @@ -77,7 +79,8 @@ icuuc.lib;%(AdditionalDependencies) ..\..\$(IcuBinOutputDir)\icuin$(IcuMajorVersion).dll - .\..\..\$(IcuLibOutputDir)\icuin.pdb + + .\..\..\$(IcuLibOutputDir)\icuin$(IcuMajorVersion).pdb ..\..\$(IcuLibOutputDir)\icuin.lib libucrtd.lib;libucrt.lib diff --git a/icu/icu4c/source/stubdata/stubdata.vcxproj b/icu/icu4c/source/stubdata/stubdata.vcxproj index 0b2c61cb06b..9c147a57a14 100644 --- a/icu/icu4c/source/stubdata/stubdata.vcxproj +++ b/icu/icu4c/source/stubdata/stubdata.vcxproj @@ -42,7 +42,8 @@ $(OutDir)/icudt.pch $(OutDir)/ $(OutDir)/ - $(OutDir)/icudt.pdb + + $(OutDir)/icudt$(IcuMajorVersion).pdb STUBDATA_BUILD;%(PreprocessorDefinitions) @@ -56,7 +57,8 @@ true ..\..\$(IcuBinOutputDir)\icudt$(IcuMajorVersion).dll - .\..\..\$(IcuLibOutputDir)\icudt.pdb + + .\..\..\$(IcuLibOutputDir)\icudt$(IcuMajorVersion).pdb ..\..\$(IcuLibOutputDir)\icudt.lib From f603944ea4a64ff8fcc0cae5b1f7aae053ff86f6 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 11:56:45 +0530 Subject: [PATCH 11/26] patch: apply 018-MSFT-Patch_ICU_toolutil_increase_string_store_for_extra_locales Bump STRING_STORE_SIZE from 100000 to 120000 in package.h. The package tool uses this as a static buffer for item names when building the .dat data file; CLDR-MS adds extra locales that overflow the vanilla 100K buffer. Applied verbatim from the patch (120000). If CLDR 48 + MS-CLDR overlay overflows this in the Step 6 data build, bump further (see followup todo). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 76b930c2c7a9aadbd28308ca0bfffc7da75e6710) --- icu/icu4c/source/tools/toolutil/package.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icu/icu4c/source/tools/toolutil/package.h b/icu/icu4c/source/tools/toolutil/package.h index ea60c13a74a..6c411ae5fd0 100644 --- a/icu/icu4c/source/tools/toolutil/package.h +++ b/icu/icu4c/source/tools/toolutil/package.h @@ -27,7 +27,7 @@ // .dat package file representation ---------------------------------------- *** -#define STRING_STORE_SIZE 100000 +#define STRING_STORE_SIZE 120000 #define MAX_PKG_NAME_LENGTH 64 typedef void CheckDependency(void *context, const char *itemName, const char *targetName); From 596dceac41a94d1726b73c62ca56e6229987406d Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 12:40:16 +0530 Subject: [PATCH 12/26] patch: apply 020-MSFT-Patch_ICU_Add_uprefs_library_to_obtain_default_locale_as_full_BCP47_tag Add MS-only uprefs library so uprv_getDefaultLocaleID() on Windows returns a full BCP47 tag (e.g. en-US-u-ca-gregory-hc-h12-fw-mon-ms-metric) that encodes the user's calendar, currency, hour cycle, first day of week, sort method, and measurement system from Windows Globalization APIs. Vanilla ICU only returns language+region. Files: - new uprefs.cpp/h (common library, gated on UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY and U_PLATFORM_USES_ONLY_WIN32_API) - new uprefstest.cpp/h - putil.cpp wires uprefs_getBCP47Tag() into uprv_getDefaultLocaleID(); unifies buffer sizing (POSIX_LOCALE_CAPACITY -> length * 2) - uconfig.h defines UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY = 1 - sources.txt lists uprefs.cpp - common.vcxproj - common_uwp.vcxproj reference uprefs.cpp/h - test/intltest/ Makefile.in + intltest.vcxproj wire uprefstest.{cpp,h}; itutil.cpp registers UPrefsTest class Reworked from ICU 72 form: - 8 hunks applied cleanly via git apply (with offsets only) - 5 build-system list-insertion hunks reworked manually due to context drift (ICU 78 added fixedstring.cpp, new test files between the patch's anchor lines) - New file uprefstest.cpp uses backup version from ICU 72.1.0.4 (commit 860c2ea8151 by Rahul Pandey, "Add missing parameters to MockGetLocaleInfoEx" Nov 2022) which contains style/whitespace cleanup not present in the original 2021 patch file. Patch file in icu-patches/patches/ remains stale and will be regenerated at end of upgrade. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 6d82403cf1bb5c0a2057cbbd96068385da38a7f0) --- icu/icu4c/source/common/common.vcxproj | 2 + icu/icu4c/source/common/common_uwp.vcxproj | 2 + icu/icu4c/source/common/putil.cpp | 35 +- icu/icu4c/source/common/sources.txt | 1 + icu/icu4c/source/common/unicode/uconfig.h | 16 + icu/icu4c/source/common/uprefs.cpp | 553 ++++++++++++++++++ icu/icu4c/source/common/uprefs.h | 29 + icu/icu4c/source/test/intltest/Makefile.in | 2 +- .../source/test/intltest/intltest.vcxproj | 2 + icu/icu4c/source/test/intltest/itutil.cpp | 6 + icu/icu4c/source/test/intltest/uprefstest.cpp | 438 ++++++++++++++ icu/icu4c/source/test/intltest/uprefstest.h | 50 ++ 12 files changed, 1132 insertions(+), 4 deletions(-) create mode 100644 icu/icu4c/source/common/uprefs.cpp create mode 100644 icu/icu4c/source/common/uprefs.h create mode 100644 icu/icu4c/source/test/intltest/uprefstest.cpp create mode 100644 icu/icu4c/source/test/intltest/uprefstest.h diff --git a/icu/icu4c/source/common/common.vcxproj b/icu/icu4c/source/common/common.vcxproj index f0f13aa1e2e..aca55a102f9 100644 --- a/icu/icu4c/source/common/common.vcxproj +++ b/icu/icu4c/source/common/common.vcxproj @@ -286,6 +286,7 @@ + @@ -405,6 +406,7 @@ + diff --git a/icu/icu4c/source/common/common_uwp.vcxproj b/icu/icu4c/source/common/common_uwp.vcxproj index 01906f3caf9..113c2418902 100644 --- a/icu/icu4c/source/common/common_uwp.vcxproj +++ b/icu/icu4c/source/common/common_uwp.vcxproj @@ -409,6 +409,7 @@ + @@ -529,6 +530,7 @@ + diff --git a/icu/icu4c/source/common/putil.cpp b/icu/icu4c/source/common/putil.cpp index ea15fdff0b0..307b07d087d 100644 --- a/icu/icu4c/source/common/putil.cpp +++ b/icu/icu4c/source/common/putil.cpp @@ -66,6 +66,7 @@ #include "locmap.h" #include "ucln_cmn.h" #include "charstr.h" +#include "uprefs.h" /* Include standard headers. */ #include @@ -1794,10 +1795,37 @@ The leftmost codepage (.xxx) wins. return posixID; #elif U_PLATFORM_USES_ONLY_WIN32_API -#define POSIX_LOCALE_CAPACITY 64 UErrorCode status = U_ZERO_ERROR; char *correctedPOSIXLocale = nullptr; +#if UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY + + int32_t neededBufferSize = uprefs_getBCP47Tag(nullptr, 0, &status); + MaybeStackArray windowsLocale(neededBufferSize, status); + int32_t length = uprefs_getBCP47Tag(windowsLocale.getAlias(), neededBufferSize, &status); + + if (length > 0) // If length is 0, then the call to uprefs_getBCP47Tag failed. + { + // Now normalize the resulting name + correctedPOSIXLocale = static_cast(uprv_malloc(length * 2)); + /* TODO: Should we just exit on memory allocation failure? */ + if (correctedPOSIXLocale) + { + int32_t posixLen = uloc_canonicalize(windowsLocale.getAlias(), correctedPOSIXLocale, length * 2, &status); + if (U_SUCCESS(status)) + { + *(correctedPOSIXLocale + posixLen) = 0; + gCorrectedPOSIXLocale = correctedPOSIXLocale; + gCorrectedPOSIXLocaleHeapAllocated = true; + ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); + } + else + { + uprv_free(correctedPOSIXLocale); + } + } + } +#else // If we have already figured this out just use the cached value if (gCorrectedPOSIXLocale != nullptr) { return gCorrectedPOSIXLocale; @@ -1839,11 +1867,11 @@ The leftmost codepage (.xxx) wins. } // Now normalize the resulting name - correctedPOSIXLocale = static_cast(uprv_malloc(POSIX_LOCALE_CAPACITY + 1)); + correctedPOSIXLocale = static_cast(uprv_malloc(length * 2)); /* TODO: Should we just exit on memory allocation failure? */ if (correctedPOSIXLocale) { - int32_t posixLen = uloc_canonicalize(modifiedWindowsLocale, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status); + int32_t posixLen = uloc_canonicalize(modifiedWindowsLocale, correctedPOSIXLocale, length * 2, &status); if (U_SUCCESS(status)) { *(correctedPOSIXLocale + posixLen) = 0; @@ -1857,6 +1885,7 @@ The leftmost codepage (.xxx) wins. } } } +#endif // If unable to find a locale we can agree upon, use en-US by default if (gCorrectedPOSIXLocale == nullptr) { diff --git a/icu/icu4c/source/common/sources.txt b/icu/icu4c/source/common/sources.txt index 5b1c5e262ea..cfcfd95df56 100644 --- a/icu/icu4c/source/common/sources.txt +++ b/icu/icu4c/source/common/sources.txt @@ -163,6 +163,7 @@ unistr_titlecase_brkiter.cpp unorm.cpp unormcmp.cpp uobject.cpp +uprefs.cpp uprops.cpp ures_cnv.cpp uresbund.cpp diff --git a/icu/icu4c/source/common/unicode/uconfig.h b/icu/icu4c/source/common/unicode/uconfig.h index 3c118288665..f339dec982f 100644 --- a/icu/icu4c/source/common/unicode/uconfig.h +++ b/icu/icu4c/source/common/unicode/uconfig.h @@ -400,6 +400,22 @@ # define UCONFIG_USE_WINDOWS_LCID_MAPPING_API 1 #endif +/** + * \def UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY + * On Windows platforms (ie: U_PLATFORM_HAS_WIN32_API is true), this switch enables ICU to + * detect additional user preferences by setting BCP47 Unicode extension within the default locale. + * This includes information such as calendar, currency, hour cycle, among others. + * + * If this switch is off (or set to 0) then the default behavior of only detecting the language + * and country/region occurs. + * + * For example, the default locale may be detected as "es-MX-u-hc-h24", instead of "es-MX", + * if the user has selected a 24 hour clock option. +*/ +#ifndef UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY +# define UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY 1 +#endif + //IGNORE_WINDOWS_HEADERS_END /* i18n library switches ---------------------------------------------------- */ diff --git a/icu/icu4c/source/common/uprefs.cpp b/icu/icu4c/source/common/uprefs.cpp new file mode 100644 index 00000000000..d9304a11de0 --- /dev/null +++ b/icu/icu4c/source/common/uprefs.cpp @@ -0,0 +1,553 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "uprefs.h" +#if U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY +#include "unicode/ustring.h" +#include "cmemory.h" +#include "charstr.h" +#include "cstring.h" +#include "cwchar.h" +#include + +U_NAMESPACE_USE + +// Older versions of the Windows SDK don’t have definitions for calendar types that were added later on. +// (For example, the Windows 7 SDK doesn’t have CAL_PERSIAN). +// So we’ll need to provide our own definitions for some of them. +// Note that on older versions of the OS these values won't ever be returned by the platform APIs, so providing our own definitions is fine. +#ifndef CAL_PERSIAN +#define CAL_PERSIAN 22 // Persian (Solar Hijri) calendar +#endif + +#define RETURN_FAILURE_STRING_WITH_STATUS_IF(condition, error, status) \ + if (condition) \ + { \ + *status = error; \ + return CharString(); \ + } + +#define RETURN_FAILURE_WITH_STATUS_IF(condition, error, status) \ + if (condition) \ + { \ + *status = error; \ + return 0; \ + } + +#define RETURN_VALUE_IF(condition, value) \ + if (condition) \ + { \ + return value; \ + } + +#define RETURN_WITH_ALLOCATION_ERROR_IF_FAILED(status) \ + if (U_FAILURE(*status)) \ + { \ + *status = U_MEMORY_ALLOCATION_ERROR; \ + return CharString(); \ + } \ +// ------------------------------------------------------- +// ----------------- MAPPING FUNCTIONS-------------------- +// ------------------------------------------------------- + +// Maps from a NLS Calendar ID (CALID) to a BCP47 Unicode Extension calendar identifier. +// +// We map the NLS CALID from GetLocaleInfoEx to the calendar identifier +// used in BCP47 tag with Unicode Extensions. +// +// This does not return a full nor valid BCP47Tag, it only returns the option that the BCP47 tag +// would return after the "ca-" part +// +// For example: +// CAL_GREGORIAN would return "gregory". +// CAL_HIJRI would return "islamic". +// +// These could be used in a BCP47 tag like this: "en-US-u-ca-gregory". +// Note that there are some NLS calendars that are not supported with the BCP47 U extensions, +// and vice-versa. +// +// NLS CALID reference:https://docs.microsoft.com/en-us/windows/win32/intl/calendar-identifiers +CharString getCalendarBCP47FromNLSType(int32_t calendar, UErrorCode* status) +{ + switch(calendar) + { + case CAL_GREGORIAN: + case CAL_GREGORIAN_US: + case CAL_GREGORIAN_ME_FRENCH: + case CAL_GREGORIAN_ARABIC: + case CAL_GREGORIAN_XLIT_ENGLISH: + case CAL_GREGORIAN_XLIT_FRENCH: + return CharString("gregory", *status); + + case CAL_JAPAN: + return CharString("japanese", *status); + + case CAL_TAIWAN: + return CharString("roc", *status); + + case CAL_KOREA: + return CharString("dangi", *status); + + case CAL_HIJRI: + return CharString("islamic", *status); + + case CAL_THAI: + return CharString("buddhist", *status); + + case CAL_HEBREW: + return CharString("hebrew", *status); + + case CAL_PERSIAN: + return CharString("persian", *status); + + case CAL_UMALQURA: + return CharString("islamic-umalqura", *status); + + default: + return CharString(); + } +} + +// Maps from a NLS Alternate sorting system to a BCP47 U extension sorting system. +// +// We map the alternate sorting method from GetLocaleInfoEx to the sorting method +// used in BCP47 tag with Unicode Extensions. +// +// This does not return a full nor valid BCP47Tag, it only returns the option that the BCP47 tag +// would return after the "co-" part +// +// For example: +// "phoneb" (parsed from "de-DE_phoneb") would return "phonebk". +// "radstr" (parsed from "ja-JP_radstr") would return "unihan". +// +// These could be used in a BCP47 tag like this: "de-DE-u-co-phonebk". +// Note that there are some NLS Alternate sort methods that are not supported with the BCP47 U extensions, +// and vice-versa. +CharString getSortingSystemBCP47FromNLSType(const wchar_t* sortingSystem, UErrorCode* status) +{ + if (wcscmp(sortingSystem, L"phoneb") == 0) // Phonebook style ordering (such as in German) + { + return CharString("phonebk", *status); + } + else if (wcscmp(sortingSystem, L"tradnl") == 0) // Traditional style ordering (such as in Spanish) + { + return CharString("trad", *status); + } + else if (wcscmp(sortingSystem, L"stroke") == 0) // Pinyin ordering for Latin, stroke order for CJK characters (used in Chinese) + { + return CharString("stroke", *status); + } + else if (wcscmp(sortingSystem, L"radstr") == 0) // Pinyin ordering for Latin, Unihan radical-stroke ordering for CJK characters (used in Chinese) + { + return CharString("unihan", *status); + } + else if (wcscmp(sortingSystem, L"pronun") == 0) // Phonetic ordering (sorting based on pronunciation) + { + return CharString("phonetic", *status); + } + else + { + return CharString(); + } +} + +// Maps from a NLS first day of week value to a BCP47 U extension first day of week. +// +// NLS defines: +// 0 -> Monday, 1 -> Tuesday, ... 5 -> Saturday, 6 -> Sunday +// +// We map the first day of week from GetLocaleInfoEx to the first day of week +// used in BCP47 tag with Unicode Extensions. +// +// This does not return a full nor valid BCP47Tag, it only returns the option that the BCP47 tag +// would return after the "fw-" part +// +// For example: +// 1 (Tuesday) would return "tue". +// 6 (Sunday) would return "sun". +// +// These could be used in a BCP47 tag like this: "en-US-u-fw-sun". +CharString getFirstDayBCP47FromNLSType(int32_t firstday, UErrorCode* status) +{ + switch(firstday) + { + case 0: + return CharString("mon", *status); + + case 1: + return CharString("tue", *status); + + case 2: + return CharString("wed", *status); + + case 3: + return CharString("thu", *status); + + case 4: + return CharString("fri", *status); + + case 5: + return CharString("sat", *status); + + case 6: + return CharString("sun", *status); + + default: + return CharString(); + } +} + +// Maps from a NLS Measurement system to a BCP47 U extension measurement system. +// +// NLS defines: +// 0 -> Metric system, 1 -> U.S. System +// +// This does not return a full nor valid BCP47Tag, it only returns the option that the BCP47 tag +// would return after the "ms-" part +// +// For example: +// 0 (Metric) would return "metric". +// 6 (U.S. System) would return "ussystem". +// +// These could be used in a BCP47 tag like this: "en-US-u-ms-metric". +CharString getMeasureSystemBCP47FromNLSType(int32_t measureSystem, UErrorCode *status) +{ + switch(measureSystem) + { + case 0: + return CharString("metric", *status); + case 1: + return CharString("ussystem", *status); + default: + return CharString(); + } +} + +// ------------------------------------------------------- +// --------------- END OF MAPPING FUNCTIONS -------------- +// ------------------------------------------------------- + +// ------------------------------------------------------- +// ------------------ HELPER FUCTIONS ------------------- +// ------------------------------------------------------- + +// Return the CLDR "h12" or "h23" format for the 12 or 24 hour clock. +// NLS only gives us a "time format" of a form similar to "h:mm:ss tt" +// The NLS "h" is 12 hour, and "H" is 24 hour, so we'll scan for the +// first h or H. +// Note that the NLS string could have sections escaped with single +// quotes, so be sure to skip those parts. Eg: "'Hours:' h:mm:ss" +// would skip the "H" in 'Hours' and use the h in the actual pattern. +CharString get12_or_24hourFormat(wchar_t* hourFormat, UErrorCode* status) +{ + bool isInEscapedString = false; + const int32_t hourLength = static_cast(uprv_wcslen(hourFormat)); + for (int32_t i = 0; i < hourLength; i++) + { + // Toggle escaped flag if in ' quoted portion + if (hourFormat[i] == L'\'') + { + isInEscapedString = !isInEscapedString; + } + + if (!isInEscapedString) + { + // Check for both so we can escape early + if (hourFormat[i] == L'H') + { + return CharString("h23", *status); + } + + if (hourFormat[i] == L'h') + { + return CharString("h12", *status); + } + } + } + // default to a 24 hour clock as that's more common worldwide + return CharString("h23", *status); +} + +UErrorCode getUErrorCodeFromLastError() +{ + DWORD error = GetLastError(); + switch(error) + { + case ERROR_INSUFFICIENT_BUFFER: + return U_BUFFER_OVERFLOW_ERROR; + + case ERROR_INVALID_FLAGS: + case ERROR_INVALID_PARAMETER: + return U_ILLEGAL_ARGUMENT_ERROR; + + case ERROR_OUTOFMEMORY: + return U_MEMORY_ALLOCATION_ERROR; + + default: + return U_INTERNAL_PROGRAM_ERROR; + } +} + +int32_t GetLocaleInfoExWrapper(LPCWSTR lpLocaleName, LCTYPE LCType, LPWSTR lpLCData, int cchData, UErrorCode* status) +{ + RETURN_VALUE_IF(U_FAILURE(*status), 0); + +#ifndef UPREFS_TEST + *status = U_ZERO_ERROR; + int32_t result = GetLocaleInfoEx(lpLocaleName, LCType, lpLCData, cchData); + + if (result == 0) + { + *status = getUErrorCodeFromLastError(); + } + return result; +#else + #include "uprefstest.h" + UPrefsTest prefTests; + return prefTests.MockGetLocaleInfoEx(lpLocaleName, LCType, lpLCData, cchData, status); +#endif +} + +// Copies a string to a buffer if its size allows it and returns the size. +// The returned needed buffer size includes the terminating \0 null character. +// If the buffer's size is set to 0, the needed buffer size is returned before copying the string. +int32_t checkBufferCapacityAndCopy(const char* uprefsString, char* uprefsBuffer, int32_t bufferSize, UErrorCode* status) +{ + int32_t neededBufferSize = static_cast(uprv_strlen(uprefsString) + 1); + + RETURN_VALUE_IF(bufferSize == 0, neededBufferSize); + RETURN_FAILURE_WITH_STATUS_IF(neededBufferSize > bufferSize, U_BUFFER_OVERFLOW_ERROR, status); + + uprv_strcpy(uprefsBuffer, uprefsString); + + return neededBufferSize; +} + +CharString getLocaleBCP47Tag_impl(UErrorCode* status, bool getSorting) +{ + // First part of a bcp47 tag looks like an NLS user locale, so we get the NLS user locale. + int32_t neededBufferSize = GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, nullptr, 0, status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + MaybeStackArray NLSLocale(neededBufferSize, *status); + RETURN_WITH_ALLOCATION_ERROR_IF_FAILED(status); + + int32_t result = GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, NLSLocale.getAlias(), neededBufferSize, status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + if (getSorting) //We determine if we want the locale (for example, en-US) or the sorting method (for example, phonebk) + { + // We use LOCALE_SNAME to get the sorting method (if any). So we need to keep + // only the sorting bit after the _, removing the locale name. + // Example: from "de-DE_phoneb" we only want "phoneb" + const wchar_t * startPosition = wcschr(NLSLocale.getAlias(), L'_'); + + // Note: not finding a "_" is not an error, it means the user has not selected an alternate sorting method, which is fine. + if (startPosition != nullptr) + { + CharString sortingSystem = getSortingSystemBCP47FromNLSType(startPosition + 1, status); + + if (sortingSystem.length() == 0) + { + *status = U_UNSUPPORTED_ERROR; + return CharString(); + } + return sortingSystem; + } + } + else + { + // The NLS locale may include a non-default sort, such as de-DE_phoneb. We only want the locale name before the _. + wchar_t * position = wcschr(NLSLocale.getAlias(), L'_'); + if (position != nullptr) + { + *position = L'\0'; + } + + CharString languageTag; + int32_t resultCapacity = 0; + languageTag.getAppendBuffer(neededBufferSize, neededBufferSize, resultCapacity, *status); + RETURN_WITH_ALLOCATION_ERROR_IF_FAILED(status); + + int32_t unitsWritten = 0; + u_strToUTF8(languageTag.data(), neededBufferSize, &unitsWritten, reinterpret_cast(NLSLocale.getAlias()), neededBufferSize, status); + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + return languageTag; + } + + return CharString(); +} + +CharString getCalendarSystem_impl(UErrorCode* status) +{ + int32_t NLSCalendar = 0; + + GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, reinterpret_cast(&NLSCalendar), sizeof(NLSCalendar) / sizeof(wchar_t), status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + CharString calendar(getCalendarBCP47FromNLSType(NLSCalendar, status), *status); + RETURN_FAILURE_STRING_WITH_STATUS_IF(calendar.length() == 0, U_UNSUPPORTED_ERROR, status); + + return calendar; +} + +CharString getCurrencyCode_impl(UErrorCode* status) +{ + int32_t neededBufferSize = GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_SINTLSYMBOL, nullptr, 0, status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + MaybeStackArray NLScurrencyData(neededBufferSize, *status); + RETURN_WITH_ALLOCATION_ERROR_IF_FAILED(status); + + int32_t result = GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_SINTLSYMBOL, NLScurrencyData.getAlias(), neededBufferSize, status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + MaybeStackArray currency(neededBufferSize, *status); + RETURN_WITH_ALLOCATION_ERROR_IF_FAILED(status); + + int32_t unitsWritten = 0; + u_strToUTF8(currency.getAlias(), neededBufferSize, &unitsWritten, reinterpret_cast(NLScurrencyData.getAlias()), neededBufferSize, status); + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + if (unitsWritten == 0) + { + *status = U_INTERNAL_PROGRAM_ERROR; + return CharString(); + } + + // Since we retreived the currency code in caps, we need to make it lowercase for it to be in CLDR BCP47 U extensions format. + T_CString_toLowerCase(currency.getAlias()); + + return CharString(currency.getAlias(), neededBufferSize, *status); +} + +CharString getFirstDayOfWeek_impl(UErrorCode* status) +{ + int32_t NLSfirstDay = 0; + GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK | LOCALE_RETURN_NUMBER, reinterpret_cast(&NLSfirstDay), sizeof(NLSfirstDay) / sizeof(wchar_t), status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + CharString firstDay = getFirstDayBCP47FromNLSType(NLSfirstDay, status); + RETURN_FAILURE_STRING_WITH_STATUS_IF(firstDay.length() == 0, U_UNSUPPORTED_ERROR, status); + + return firstDay; +} + +CharString getHourCycle_impl(UErrorCode* status) +{ + int32_t neededBufferSize = GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_STIMEFORMAT, nullptr, 0, status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + MaybeStackArray NLShourCycle(neededBufferSize, *status); + RETURN_WITH_ALLOCATION_ERROR_IF_FAILED(status); + + int32_t result = GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_STIMEFORMAT, NLShourCycle.getAlias(), neededBufferSize, status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + CharString hourCycle = get12_or_24hourFormat(NLShourCycle.getAlias(), status); + if (hourCycle.length() == 0) + { + *status = U_INTERNAL_PROGRAM_ERROR; + return CharString(); + } + return hourCycle; +} + +CharString getMeasureSystem_impl(UErrorCode* status) +{ + int32_t NLSmeasureSystem = 0; + GetLocaleInfoExWrapper(LOCALE_NAME_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, reinterpret_cast(&NLSmeasureSystem), sizeof(NLSmeasureSystem) / sizeof(wchar_t), status); + + RETURN_VALUE_IF(U_FAILURE(*status), CharString()); + + CharString measureSystem = getMeasureSystemBCP47FromNLSType(NLSmeasureSystem, status); + RETURN_FAILURE_STRING_WITH_STATUS_IF(measureSystem.length() == 0, U_UNSUPPORTED_ERROR, status); + + return measureSystem; +} + +void appendIfDataNotEmpty(CharString& dest, const char* firstData, const char* secondData, bool& warningGenerated, UErrorCode* status) +{ + if (*status == U_UNSUPPORTED_ERROR) + { + warningGenerated = true; + *status = U_ZERO_ERROR; + } + + if (uprv_strlen(secondData) != 0) + { + dest.append(firstData, *status); + dest.append(secondData, *status); + } +} +// ------------------------------------------------------- +// --------------- END OF HELPER FUNCTIONS --------------- +// ------------------------------------------------------- + + +// ------------------------------------------------------- +// ---------------------- APIs --------------------------- +// ------------------------------------------------------- + +// Gets the valid and canonical BCP47 tag with the user settings for Language, Calendar, Sorting, Currency, +// First day of week, Hour cycle, and Measurement system. +// Calls all of the other APIs +// Returns the needed buffer size for the BCP47 Tag. +int32_t uprefs_getBCP47Tag(char* uprefsBuffer, int32_t bufferSize, UErrorCode* status) +{ + RETURN_FAILURE_WITH_STATUS_IF(uprefsBuffer == nullptr && bufferSize != 0, U_ILLEGAL_ARGUMENT_ERROR, status); + + *status = U_ZERO_ERROR; + CharString BCP47Tag; + bool warningGenerated = false; + + CharString languageTag = getLocaleBCP47Tag_impl(status, false); + RETURN_VALUE_IF(U_FAILURE(*status), 0); + BCP47Tag.append(languageTag.data(), *status); + BCP47Tag.append("-u", *status); + + CharString calendar = getCalendarSystem_impl(status); + RETURN_VALUE_IF(U_FAILURE(*status) && *status != U_UNSUPPORTED_ERROR, 0); + appendIfDataNotEmpty(BCP47Tag, "-ca-", calendar.data(), warningGenerated, status); + + CharString sortingSystem = getLocaleBCP47Tag_impl(status, true); + RETURN_VALUE_IF(U_FAILURE(*status) && *status != U_UNSUPPORTED_ERROR, 0); + appendIfDataNotEmpty(BCP47Tag, "-co-", sortingSystem.data(), warningGenerated, status); + + CharString currency = getCurrencyCode_impl(status); + RETURN_VALUE_IF(U_FAILURE(*status) && *status != U_UNSUPPORTED_ERROR, 0); + appendIfDataNotEmpty(BCP47Tag, "-cu-", currency.data(), warningGenerated, status); + + CharString firstDay = getFirstDayOfWeek_impl(status); + RETURN_VALUE_IF(U_FAILURE(*status) && *status != U_UNSUPPORTED_ERROR, 0); + appendIfDataNotEmpty(BCP47Tag, "-fw-", firstDay.data(), warningGenerated, status); + + CharString hourCycle = getHourCycle_impl(status); + RETURN_VALUE_IF(U_FAILURE(*status) && *status != U_UNSUPPORTED_ERROR, 0); + appendIfDataNotEmpty(BCP47Tag, "-hc-", hourCycle.data(), warningGenerated, status); + + CharString measureSystem = getMeasureSystem_impl(status); + RETURN_VALUE_IF(U_FAILURE(*status) && *status != U_UNSUPPORTED_ERROR, 0); + appendIfDataNotEmpty(BCP47Tag, "-ms-", measureSystem.data(), warningGenerated, status); + + if (warningGenerated) + { + *status = U_USING_FALLBACK_WARNING; + } + + return checkBufferCapacityAndCopy(BCP47Tag.data(), uprefsBuffer, bufferSize, status); +} + +// ------------------------------------------------------- +// ---------------------- END OF APIs -------------------- +// ------------------------------------------------------- + +#endif // U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY \ No newline at end of file diff --git a/icu/icu4c/source/common/uprefs.h b/icu/icu4c/source/common/uprefs.h new file mode 100644 index 00000000000..08ecd86189b --- /dev/null +++ b/icu/icu4c/source/common/uprefs.h @@ -0,0 +1,29 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef UPREFS_H +#define UPREFS_H + +#include "unicode/platform.h" +#include "unicode/utypes.h" +#if U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY + +/** +* Gets the valid and canonical BCP47 tag with the user settings for Language, Calendar, Sorting, Currency, +* First day of week, Hour cycle, and Measurement system when available. +* +* @param uprefsBuffer Pointer to a buffer in which this function retrieves the BCP47 tag. +* This pointer is not used if bufferSize is set to 0. +* @param bufferSize Size, in characters, of the data buffer indicated by uprefsBuffer. Alternatively, the application +* can set this parameter to 0. In this case, the function does not use the uprefsBuffer parameter +* and returns the required buffer size, including the terminating null character. +* @param status: Pointer to a UErrorCode. The resulting value will be U_ZERO_ERROR if the call was successful or will +* contain an error or warning code. If the status is U_USING_FALLBACK_WARNING, it means at least one of the + settings was not succesfully mapped between NLS and CLDR, so it will not be shown on the BCP47 tag. +* @return The needed buffer size, including the terminating \0 null character if the call was successful, should be ignored +* if status was not U_ZERO_ERROR. +*/ +int32_t uprefs_getBCP47Tag(char* uprefsBuffer, int32_t bufferSize, UErrorCode* status); + +#endif //U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY +#endif //UPREFS_H \ No newline at end of file diff --git a/icu/icu4c/source/test/intltest/Makefile.in b/icu/icu4c/source/test/intltest/Makefile.in index 2e448319243..eab33ebb0b6 100644 --- a/icu/icu4c/source/test/intltest/Makefile.in +++ b/icu/icu4c/source/test/intltest/Makefile.in @@ -78,7 +78,7 @@ units_data_test.o units_router_test.o units_test.o displayoptions_test.o \ numbertest_simple.o \ cplusplus_header_api_build_test.o uchar_type_build_test.o \ ucolheaderonlytest.o usetheaderonlytest.o utfiteratortest.o utfstringtest.o \ -intltesttest.o +intltesttest.o uprefstest.o DEPS = $(OBJECTS:.o=.d) diff --git a/icu/icu4c/source/test/intltest/intltest.vcxproj b/icu/icu4c/source/test/intltest/intltest.vcxproj index ce69ec0de41..0ee503fcbe4 100644 --- a/icu/icu4c/source/test/intltest/intltest.vcxproj +++ b/icu/icu4c/source/test/intltest/intltest.vcxproj @@ -247,6 +247,7 @@ + @@ -378,6 +379,7 @@ + diff --git a/icu/icu4c/source/test/intltest/itutil.cpp b/icu/icu4c/source/test/intltest/itutil.cpp index 20c16389c0a..768507c632a 100644 --- a/icu/icu4c/source/test/intltest/itutil.cpp +++ b/icu/icu4c/source/test/intltest/itutil.cpp @@ -33,6 +33,9 @@ #include "uvectest.h" #include "aliastst.h" #include "usettest.h" +#if U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY + #include "uprefstest.h" +#endif extern IntlTest *createBytesTrieTest(); #if !UCONFIG_NO_COLLATION @@ -76,6 +79,9 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* & TESTCASE_AUTO_CLASS(LocaleAliasTest); TESTCASE_AUTO_CLASS(UnicodeSetTest); TESTCASE_AUTO_CLASS(ErrorCodeTest); +#if U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY + TESTCASE_AUTO_CLASS(UPrefsTest); +#endif TESTCASE_AUTO_CREATE_CLASS(LocalPointerTest); TESTCASE_AUTO_CREATE_CLASS(BytesTrieTest); TESTCASE_AUTO_CREATE_CLASS(UCharsTrieTest); diff --git a/icu/icu4c/source/test/intltest/uprefstest.cpp b/icu/icu4c/source/test/intltest/uprefstest.cpp new file mode 100644 index 00000000000..69c5265eed1 --- /dev/null +++ b/icu/icu4c/source/test/intltest/uprefstest.cpp @@ -0,0 +1,438 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +#include "uprefstest.h" +#if U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY + +#define ARRAY_SIZE 512 + +std::wstring UPrefsTest::language = L""; +std::wstring UPrefsTest::currency = L""; +std::wstring UPrefsTest::hourCycle = L""; +int32_t UPrefsTest::firstday = 0; +int32_t UPrefsTest::measureSystem = 0; +CALID UPrefsTest::calendar = 0; + +void UPrefsTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) +{ + if (exec) logln("TestSuite UPrefsTest: "); + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(TestGetDefaultLocaleAsBCP47Tag); + TESTCASE_AUTO(TestBCP47TagWithSorting); + TESTCASE_AUTO(TestBCP47TagChineseSimplified); + TESTCASE_AUTO(TestBCP47TagChineseSortingStroke); + TESTCASE_AUTO(TestBCP47TagJapanCalendar); + TESTCASE_AUTO(TestUseNeededBuffer); + TESTCASE_AUTO(TestGetNeededBuffer); + TESTCASE_AUTO(TestGetUnsupportedSorting); + TESTCASE_AUTO(Get24HourCycleMixed); + TESTCASE_AUTO(Get12HourCycleMixed); + TESTCASE_AUTO(Get12HourCycleMixed2); + TESTCASE_AUTO(Get12HourCycle); + TESTCASE_AUTO(Get12HourCycle2); + TESTCASE_AUTO_END; +} + +int32_t UPrefsTest::MockGetLocaleInfoEx(LPCWSTR lpLocaleName, LCTYPE LCType, LPWSTR lpLCData, + int cchData, UErrorCode *status) +{ + switch (LCType) + { + case LOCALE_SNAME: + if (cchData == 0) + { + *status = U_ZERO_ERROR; + return language.length() + 1; + } + + if (language.length() + 1 > cchData) + { + *status = U_BUFFER_OVERFLOW_ERROR; + return 0; + } + wcsncpy(lpLCData, language.c_str(), cchData); + *status = U_ZERO_ERROR; + return language.length(); + + case LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER: + if (cchData == 0) + { + *status = U_ZERO_ERROR; + return 2; + } + if (cchData < 2) + { + *status = U_BUFFER_OVERFLOW_ERROR; + return 0; + } + *(reinterpret_cast(lpLCData)) = calendar; + *status = U_ZERO_ERROR; + return 2; + + case LOCALE_SINTLSYMBOL: + if (cchData == 0) + { + *status = U_ZERO_ERROR; + return currency.length() + 1; + } + if (currency.length() + 1 > cchData) + { + *status = U_BUFFER_OVERFLOW_ERROR; + return 0; + } + wcsncpy(lpLCData, currency.c_str(), cchData); + *status = U_ZERO_ERROR; + return currency.length(); + + case LOCALE_IFIRSTDAYOFWEEK | LOCALE_RETURN_NUMBER: + if (cchData == 0) + { + *status = U_ZERO_ERROR; + return 2; + } + if (cchData < 2) + { + *status = U_BUFFER_OVERFLOW_ERROR; + return 0; + } + + *(reinterpret_cast(lpLCData)) = firstday; + *status = U_ZERO_ERROR; + return 2; + + case LOCALE_STIMEFORMAT: + if (cchData == 0) + { + *status = U_ZERO_ERROR; + return hourCycle.length() + 1; + } + + if (hourCycle.length() + 1 > cchData) + { + *status = U_BUFFER_OVERFLOW_ERROR; + return 0; + } + wcsncpy(lpLCData, hourCycle.c_str(), cchData); + *status = U_ZERO_ERROR; + return 0; + + case LOCALE_IMEASURE | LOCALE_RETURN_NUMBER: + if (cchData == 0) + { + *status = U_ZERO_ERROR; + return 2; + } + + if (cchData < 2) + { + *status = U_BUFFER_OVERFLOW_ERROR; + return 0; + } + *(reinterpret_cast(lpLCData)) = measureSystem; + *status = U_ZERO_ERROR; + return 2; + + default: + *status = U_INTERNAL_PROGRAM_ERROR; + return 0; + } +} + +// The code above is independent of the library itself, but for the code below this point, +// we need to include the library to be able to use the definitions of the API uprefs_getBCP47Tag +#include "uprefs.cpp" + +void UPrefsTest::TestGetDefaultLocaleAsBCP47Tag() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"en-US"; + currency = L"USD"; + hourCycle = L"HH:mm:ss"; + firstday = 0; + measureSystem = 1; + calendar = CAL_GREGORIAN; + UErrorCode status = U_ZERO_ERROR; + const char* expectedValue = "en-US-u-ca-gregory-cu-usd-fw-mon-hc-h23-ms-ussystem"; + + if ( uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 52) + { + errln("Expected length to be 52, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestBCP47TagWithSorting() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"de-DE_phoneb"; + currency = L"EUR"; + hourCycle = L"HH:mm:ss"; + firstday = 0; + measureSystem = 1; + calendar = CAL_GREGORIAN; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "de-DE-u-ca-gregory-co-phonebk-cu-eur-fw-mon-hc-h23-ms-ussystem"; + + if ( uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 63) + { + errln("Expected length to be 63, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestBCP47TagChineseSimplified() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"zh-Hans-HK"; + currency = L"EUR"; + hourCycle = L"hh:mm:ss"; + firstday = 2; + measureSystem = 1; + calendar = CAL_GREGORIAN; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "zh-Hans-HK-u-ca-gregory-cu-eur-fw-wed-hc-h12-ms-ussystem"; + + if ( uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 57) + { + errln("Expected length to be 57, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestBCP47TagChineseSortingStroke() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"zh-SG_stroke"; + currency = L"EUR"; + hourCycle = L"hh:mm:ss"; + firstday = 2; + measureSystem = 0; + calendar = CAL_GREGORIAN; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "zh-SG-u-ca-gregory-co-stroke-cu-eur-fw-wed-hc-h12-ms-metric"; + + if ( uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 60) + { + errln("Expected length to be 60, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestBCP47TagJapanCalendar() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"hh:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_JAPAN; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-japanese-cu-mxn-fw-tue-hc-h12-ms-metric"; + + if ( uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestUseNeededBuffer() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"hh:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + + int32_t neededBufferSize = uprefs_getBCP47Tag(nullptr, 0, &status); + + if ( uprefs_getBCP47Tag(languageBuffer, neededBufferSize, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestGetNeededBuffer() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"zh-SG_stroke"; + currency = L"MXN"; + hourCycle = L"hh:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "zh-SG-u-ca-buddhist-co-stroke-cu-mxn-fw-tue-hc-h12-ms-metric"; + + int32_t neededBufferSize = uprefs_getBCP47Tag(nullptr, 0, &status); + + if ( neededBufferSize != 61) + { + errln("Expected buffer size to be 61, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprefs_getBCP47Tag(languageBuffer, neededBufferSize, &status) != 61) + { + errln("Expected length to be 61, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::TestGetUnsupportedSorting() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"hu-HU_technl"; + currency = L"MXN"; + hourCycle = L"hh:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "hu-HU-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + + if ( uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n",uprv_strlen(languageBuffer)); + } + if ( uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::Get24HourCycleMixed() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"HHhh:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h23-ms-metric"; + + if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n", uprv_strlen(languageBuffer)); + } + if (uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::Get12HourCycleMixed() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"hHhH:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + + if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n", uprv_strlen(languageBuffer)); + } + if (uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + + +void UPrefsTest::Get12HourCycleMixed2() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"hH''h'H'H:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + + if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n", uprv_strlen(languageBuffer)); + } + if (uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::Get12HourCycle() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"h'H'h:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + + if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n", uprv_strlen(languageBuffer)); + } + if (uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} + +void UPrefsTest::Get12HourCycle2() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; + currency = L"MXN"; + hourCycle = L"'H'h'H'h:mm:ss"; + firstday = 1; + measureSystem = 0; + calendar = CAL_THAI; + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + + if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n", uprv_strlen(languageBuffer)); + } + if (uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } +} +#endif //U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY \ No newline at end of file diff --git a/icu/icu4c/source/test/intltest/uprefstest.h b/icu/icu4c/source/test/intltest/uprefstest.h new file mode 100644 index 00000000000..2f3e6515b06 --- /dev/null +++ b/icu/icu4c/source/test/intltest/uprefstest.h @@ -0,0 +1,50 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +#ifndef UPREFSTEST_H +#define UPREFSTEST_H + +#include "unicode/platform.h" +#if U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY +// We define UPREFS_TEST to use the mock version of GetLocaleInfoEx(), which +// allows us to simulate its behaviour and determine if the results given by the +// API align with what we expect to receive +#define UPREFS_TEST 1 + + +#include "windows.h" +#include "intltest.h" +#include "uprefs.h" + +class UPrefsTest: public IntlTest { +private: + static std::wstring language; + static std::wstring currency; + static std::wstring hourCycle; + static int32_t firstday; + static int32_t measureSystem; + static CALID calendar; + +public: + UPrefsTest(){}; + virtual ~UPrefsTest(){}; + + virtual void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = NULL) override; + int32_t MockGetLocaleInfoEx(LPCWSTR lpLocaleName, LCTYPE LCType, LPWSTR lpLCData, int cchData, UErrorCode* status); + void TestGetDefaultLocaleAsBCP47Tag(); + void TestBCP47TagWithSorting(); + void TestBCP47TagChineseSimplified(); + void TestBCP47TagChineseSortingStroke(); + void TestBCP47TagJapanCalendar(); + void TestUseNeededBuffer(); + void TestGetNeededBuffer(); + void TestGetUnsupportedSorting(); + void Get24HourCycleMixed(); + void Get12HourCycleMixed(); + void Get12HourCycleMixed2(); + void Get12HourCycle(); + void Get12HourCycle2(); +}; + + +#endif //U_PLATFORM_USES_ONLY_WIN32_API && UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY +#endif //UPREFSTEST_H \ No newline at end of file From 85bb300b631cf92de18e8fa6431f6be8902935e3 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 13:52:59 +0530 Subject: [PATCH 13/26] chore: bump STRING_STORE_SIZE 120000 -> 200000 for CLDR 48 Patch 018 originally bumped this from 100000 -> 120000 for the CLDR-MS extra-locales overflow at the package-tool stage of data build. CLDR 48 has substantially more locales than CLDR 44 (which 120000 was sized for); prior session evidence (now-deleted branch) suggests 120000 may still overflow at Step 6 data build. Pre-emptively bump to 200000 to avoid a Step 6 rerun on overflow. If the actual measurement at Step 6 shows 120000 was enough, we can revisit post-shipping. Bumping high now is harmless (static array sized at compile time in tool; trivial RAM increase only while makedata runs). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit f1176071440886a5d21e61ea75ee5f2ed527c7e9) --- icu/icu4c/source/tools/toolutil/package.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icu/icu4c/source/tools/toolutil/package.h b/icu/icu4c/source/tools/toolutil/package.h index 6c411ae5fd0..3a1d3cd23d9 100644 --- a/icu/icu4c/source/tools/toolutil/package.h +++ b/icu/icu4c/source/tools/toolutil/package.h @@ -27,7 +27,7 @@ // .dat package file representation ---------------------------------------- *** -#define STRING_STORE_SIZE 120000 +#define STRING_STORE_SIZE 200000 #define MAX_PKG_NAME_LENGTH 64 typedef void CheckDependency(void *context, const char *itemName, const char *targetName); From 1bfbeb7d04fdb2b3ba33eafdd7ff17533c5b8269 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Thu, 14 May 2026 14:32:44 +0530 Subject: [PATCH 14/26] patch: add and apply 021-MSFT-Patch_ICU_Cldr2Icu_remove_icu4j_directory_validation The new ICU 78 Cldr2Icu Maven/Java toolchain replaces the deleted build-icu-data.xml Ant entry point. Its CLI-options constructor runs validateEnvironment() and System.exit(1)s unless ICU_DIR contains an icu4j/ subdirectory. The microsoft/icu fork is icu4c-only -- there is no icu4j source tree -- so the Step 6 data-build pipeline cannot run without bypassing this check. The runtime Java dependency on icu4j (used by TransformsMapper for Transliterator) is satisfied via the Maven artifact com.ibm.icu:icu4j in ~/.m2, which is unaffected by source-tree absence. This is an MS-only divergence. Both the patch file and the applied source change land here as a single commit; the patch file documents the divergence in icu-patches/patches/ for future upgrades. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 9ff77624732f382c8e421ee7ead50308295a07f8) --- ...cu_remove_icu4j_directory_validation.patch | 20 +++++++++++++++++++ .../tool/cldrtoicu/Cldr2IcuCliOptions.java | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 icu-patches/patches/021-MSFT-Patch_ICU_Cldr2Icu_remove_icu4j_directory_validation.patch diff --git a/icu-patches/patches/021-MSFT-Patch_ICU_Cldr2Icu_remove_icu4j_directory_validation.patch b/icu-patches/patches/021-MSFT-Patch_ICU_Cldr2Icu_remove_icu4j_directory_validation.patch new file mode 100644 index 00000000000..51be7eba985 --- /dev/null +++ b/icu-patches/patches/021-MSFT-Patch_ICU_Cldr2Icu_remove_icu4j_directory_validation.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Arvind Oruganti +Date: Thu, 14 May 2026 14:30:00 +0530 +Subject: MSFT-PATCH: Remove icu4j directory validation from Cldr2Icu (icu4c-only fork) + +diff --git a/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java b/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java +index d9b46014438..9ff85b38d86 100644 +--- a/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java ++++ b/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java +@@ -380,7 +380,9 @@ private void validateEnvironment() { + + if (!new File(icuDir).isDirectory() + || ! new File(icuDir, "icu4c").isDirectory() +- || ! new File(icuDir, "icu4j").isDirectory() ++ // MSFT-Change: microsoft/icu fork is icu4c-only; no icu4j source tree. ++ // The Maven dependency on icu4j (used by TransformsMapper) is still ++ // resolved from ~/.m2 at runtime, so source-tree absence is harmless. + || ! new File(icuDir, "tools/cldr/cldr-to-icu").isDirectory() + || ! new File(icuDir, "tools/cldr/cldr-to-icu/pom.xml").isFile()) { + System.err.println("The `" + icuDir + "` directory does not look like a valid icu root."); diff --git a/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java b/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java index d9b46014438..9ff85b38d86 100644 --- a/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java +++ b/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java @@ -380,7 +380,9 @@ private void validateEnvironment() { if (!new File(icuDir).isDirectory() || ! new File(icuDir, "icu4c").isDirectory() - || ! new File(icuDir, "icu4j").isDirectory() + // MSFT-Change: microsoft/icu fork is icu4c-only; no icu4j source tree. + // The Maven dependency on icu4j (used by TransformsMapper) is still + // resolved from ~/.m2 at runtime, so source-tree absence is harmless. || ! new File(icuDir, "tools/cldr/cldr-to-icu").isDirectory() || ! new File(icuDir, "tools/cldr/cldr-to-icu/pom.xml").isFile()) { System.err.println("The `" + icuDir + "` directory does not look like a valid icu root."); From bda33d3e5326345aab1f22efcd9950083eae1868 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Tue, 19 May 2026 13:59:57 +0530 Subject: [PATCH 15/26] MSFT-PATCH: Override ar-SA Saudi Riyal symbol Use the Unicode U+20C1 SAUDI RIYAL SIGN for the ar-SA SAR currency symbol and add a C API regression test for the locale-specific override. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit f64bdac3e3bb54d032876cef376755bb558b50d4) --- icu/icu4c/source/data/curr/ar_SA.txt | 10 ++++++---- icu/icu4c/source/test/cintltst/currtest.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/icu/icu4c/source/data/curr/ar_SA.txt b/icu/icu4c/source/data/curr/ar_SA.txt index 32526c8458f..2d969daeb3b 100644 --- a/icu/icu4c/source/data/curr/ar_SA.txt +++ b/icu/icu4c/source/data/curr/ar_SA.txt @@ -1,9 +1,11 @@ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html // Generated using tools/cldr/cldr-to-icu/ -/** - * generated alias target - */ ar_SA{ - ___{""} + Currencies{ + SAR{ + "⃁", + "ريال سعودي", + } + } } diff --git a/icu/icu4c/source/test/cintltst/currtest.c b/icu/icu4c/source/test/cintltst/currtest.c index d8355133a18..51dff0eb0b3 100644 --- a/icu/icu4c/source/test/cintltst/currtest.c +++ b/icu/icu4c/source/test/cintltst/currtest.c @@ -298,6 +298,26 @@ static void TestNumericCode(void) { } } +static void TestSaudiRiyalSymbol(void) { + UErrorCode status = U_ZERO_ERROR; + UChar currency[4]; + UBool isChoiceFormat = false; + int32_t len = 0; + static const UChar expectedSymbol[] = {0x20C1, 0}; + const UChar* symbol; + + u_charsToUChars("SAR", currency, UPRV_LENGTHOF(currency)); + symbol = ucurr_getName(currency, "ar_SA", UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &status); + if (U_FAILURE(status)) { + log_data_err("Error: ucurr_getName returned %s (Are you missing data?)\n", u_errorName(status)); + return; + } + if (isChoiceFormat || len != 1 || symbol == NULL || u_strncmp(symbol, expectedSymbol, len) != 0) { + log_err("Error: SAR symbol for ar_SA should be U+20C1. Got length=%d first=U+%04X choice=%s\n", + len, (len > 0 && symbol != NULL) ? symbol[0] : 0, isChoiceFormat ? "true" : "false"); + } +} + void addCurrencyTest(TestNode** root); #define TESTCASE(x) addTest(root, &x, "tsformat/currtest/" #x) @@ -310,6 +330,7 @@ void addCurrencyTest(TestNode** root) TESTCASE(TestFractionDigitOverride); TESTCASE(TestPrefixSuffix); TESTCASE(TestNumericCode); + TESTCASE(TestSaudiRiyalSymbol); } #endif /* #if !UCONFIG_NO_FORMATTING */ From 33c97fae56764fc9ee42eb9bafcd36490b0d5ff2 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 15:05:57 +0530 Subject: [PATCH 16/26] Port English AM/PM spacing test expectations Align ICU test expectations with MS English locale data that preserves regular spaces before AM/PM markers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit cf73e48c806995cc166b51946dc3ce6793a66c5b) --- icu/icu4c/source/test/cintltst/ccaltst.c | 4 +- .../test/cintltst/cdateintervalformattest.c | 18 +++--- icu/icu4c/source/test/cintltst/cdattst.c | 20 +++--- icu/icu4c/source/test/cintltst/cdtrgtst.c | 2 +- icu/icu4c/source/test/cintltst/cmsgtst.c | 2 +- icu/icu4c/source/test/cintltst/udatpg_test.c | 26 ++++---- icu/icu4c/source/test/intltest/dtfmrgts.cpp | 6 +- icu/icu4c/source/test/intltest/dtfmttst.cpp | 20 +++--- icu/icu4c/source/test/intltest/dtifmtts.cpp | 8 +-- icu/icu4c/source/test/intltest/dtptngts.cpp | 62 +++++++++++-------- .../test/intltest/messageformat2test_icu.cpp | 2 +- icu/icu4c/source/test/intltest/tmsgfmt.cpp | 6 +- .../message2/icu4j/icu-test-functions.json | 28 ++++----- icu/testdata/message2/icu-test-functions.json | 28 ++++----- icu/testdata/message2/more-functions.json | 6 +- 15 files changed, 125 insertions(+), 113 deletions(-) diff --git a/icu/icu4c/source/test/cintltst/ccaltst.c b/icu/icu4c/source/test/cintltst/ccaltst.c index 235eff26d1e..50e0dca83e9 100644 --- a/icu/icu4c/source/test/cintltst/ccaltst.c +++ b/icu/icu4c/source/test/cintltst/ccaltst.c @@ -724,7 +724,7 @@ static void TestGetSetDateAPI(void) /*Testing if setDate works fine */ log_verbose("\nTesting the ucal_setDate() function \n"); - u_strcpy(temp, u"Dec 17, 1971, 11:05:28\u202FPM"); + u_strcpy(temp, u"Dec 17, 1971, 11:05:28 PM"); ucal_setDate(caldef,1971, UCAL_DECEMBER, 17, &status); if(U_FAILURE(status)){ log_err("error in setting the calendar date : %s\n", u_errorName(status)); @@ -755,7 +755,7 @@ static void TestGetSetDateAPI(void) /*Testing if setDateTime works fine */ log_verbose("\nTesting the ucal_setDateTime() function \n"); - u_strcpy(temp, u"May 3, 1972, 4:30:42\u202FPM"); + u_strcpy(temp, u"May 3, 1972, 4:30:42 PM"); ucal_setDateTime(caldef,1972, UCAL_MAY, 3, 16, 30, 42, &status); if(U_FAILURE(status)){ log_err("error in setting the calendar date : %s\n", u_errorName(status)); diff --git a/icu/icu4c/source/test/cintltst/cdateintervalformattest.c b/icu/icu4c/source/test/cintltst/cdateintervalformattest.c index 298dcae4247..a4ecc7dc2eb 100644 --- a/icu/icu4c/source/test/cintltst/cdateintervalformattest.c +++ b/icu/icu4c/source/test/cintltst/cdateintervalformattest.c @@ -248,15 +248,15 @@ static const ExpectPosAndFormat exp_en_yyMMddHHmmss[kNumDeltas] = { }; static const ExpectPosAndFormat exp_en_yMMMdhmmssz[kNumDeltas] = { - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u20099:00:20\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u20099:20:00\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u200911:00:00\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u20099:00:00\\u202FPM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u2009Nov 28, 2014, 9:00:00\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u2009Dec 6, 2014, 9:00:00\\u202FAM GMT" }, - { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u2009Feb 28, 2015, 9:00:00\\u202FAM GMT" } + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u20099:00:20 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u20099:20:00 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u200911:00:00 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u20099:00:00 PM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u2009Nov 28, 2014, 9:00:00 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u2009Dec 6, 2014, 9:00:00 AM GMT" }, + { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u2009Feb 28, 2015, 9:00:00 AM GMT" } }; static const ExpectPosAndFormat exp_ja_yyMMddHHmm[kNumDeltas] = { diff --git a/icu/icu4c/source/test/cintltst/cdattst.c b/icu/icu4c/source/test/cintltst/cdattst.c index e17ac06f064..6f27ba32a72 100644 --- a/icu/icu4c/source/test/cintltst/cdattst.c +++ b/icu/icu4c/source/test/cintltst/cdattst.c @@ -176,7 +176,7 @@ static void TestDateFormat(void) /*Testing udat_format()*/ log_verbose("\nTesting the udat_format() function of date format\n"); - u_strcpy(temp, u"7/10/96, 4:05\u202FPM"); + u_strcpy(temp, u"7/10/96, 4:05 PM"); /*format using def */ resultlength=0; resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status); @@ -245,7 +245,7 @@ static void TestDateFormat(void) /*Testing parsing using udat_parse()*/ log_verbose("\nTesting parsing using udat_parse()\n"); - u_strcpy(temp, u"2/3/76, 2:50\u202FAM"); + u_strcpy(temp, u"2/3/76, 2:50 AM"); parsepos=0; status=U_ZERO_ERROR; @@ -966,7 +966,7 @@ static void TestDateFormatCalendar(void) { u_errorName(ec)); goto FAIL; } - u_strcpy(uExpected, u"5:45\u202FPM"); + u_strcpy(uExpected, u"5:45 PM"); u_austrcpy(cbuf, uExpected); if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) { log_err("FAIL: udat_formatCalendar(17:45), expected: %s", cbuf); @@ -2101,10 +2101,10 @@ static void TestHourCycle(void) { static const UDate date = -845601267742; // March 16, 1943 at 3:45 PM const UChar* testCases[] = { // test some locales for which we have data - u"en_US", u"Tuesday, March 16, 1943 at 3:45:32 PM", - u"en_CA", u"Tuesday, March 16, 1943 at 3:45:32 p.m.", + u"en_US", u"Tuesday, March 16, 1943 at 3:45:32 PM", + u"en_CA", u"Tuesday, March 16, 1943 at 3:45:32 p.m.", u"en_GB", u"Tuesday, 16 March 1943 at 15:45:32", - u"en_AU", u"Tuesday, 16 March 1943 at 3:45:32 pm", + u"en_AU", u"Tuesday, 16 March 1943 at 3:45:32 pm", // test a couple locales for which we don't have specific locale files (we should still get the correct hour cycle) u"en_CO", u"Tuesday, March 16, 1943 at 3:45:32 PM", u"en_MX", u"Tuesday, March 16, 1943 at 3:45:32 PM", @@ -2112,12 +2112,12 @@ static void TestHourCycle(void) { u"en_US@rg=GBzzzz", u"Tuesday, March 16, 1943 at 15:45:32", u"en_US@rg=CAzzzz", u"Tuesday, March 16, 1943 at 3:45:32 PM", u"en_CA@rg=USzzzz", u"Tuesday, March 16, 1943 at 3:45:32 p.m.", - u"en_GB@rg=USzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", - u"en_GB@rg=CAzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", - u"en_GB@rg=AUzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", + u"en_GB@rg=USzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", + u"en_GB@rg=CAzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", + u"en_GB@rg=AUzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", // test that the hc ("hours") subtag does the right thing u"en_US@hours=h23", u"Tuesday, March 16, 1943 at 15:45:32", - u"en_GB@hours=h12", u"Tuesday, 16 March 1943 at 3:45:32 pm", + u"en_GB@hours=h12", u"Tuesday, 16 March 1943 at 3:45:32 pm", // test that the rg and hc subtags do the right thing when used together u"en_US@rg=GBzzzz;hours=h12", u"Tuesday, March 16, 1943 at 3:45:32 PM", u"en_GB@rg=USzzzz;hours=h23", u"Tuesday, 16 March 1943 at 15:45:32", diff --git a/icu/icu4c/source/test/cintltst/cdtrgtst.c b/icu/icu4c/source/test/cintltst/cdtrgtst.c index 54bdc7228fd..13aa8cfb67c 100644 --- a/icu/icu4c/source/test/cintltst/cdtrgtst.c +++ b/icu/icu4c/source/test/cintltst/cdtrgtst.c @@ -516,7 +516,7 @@ void Test714(void) UErrorCode status = U_ZERO_ERROR; UDateFormat *fmt; UChar *result; - const UChar* expect = u"7:25:43\u202FAM"; + const UChar* expect = u"7:25:43 AM"; ctest_setTimeZone(NULL, &status); diff --git a/icu/icu4c/source/test/cintltst/cmsgtst.c b/icu/icu4c/source/test/cintltst/cmsgtst.c index 16263b5c7f4..ed20cf23ce0 100644 --- a/icu/icu4c/source/test/cintltst/cmsgtst.c +++ b/icu/icu4c/source/test/cintltst/cmsgtst.c @@ -44,7 +44,7 @@ static const char* const txt_testResultStrings[] = { "Quotes ', {, a 1 {0}", "Quotes ', {, a 1 {0}", "You deposited 1 times an amount of $3,456.00 on 1/12/70", - "{2,time,full}, for 3,456, 1 is 5:46:40\\u202FAM Pacific Standard Time and full date is Monday, January 12, 1970", + "{2,time,full}, for 3,456, 1 is 5:46:40 AM Pacific Standard Time and full date is Monday, January 12, 1970", "{1,number,percent} for 1 is 345,600%" }; diff --git a/icu/icu4c/source/test/cintltst/udatpg_test.c b/icu/icu4c/source/test/cintltst/udatpg_test.c index b9278085b20..d6e6d209a97 100644 --- a/icu/icu4c/source/test/cintltst/udatpg_test.c +++ b/icu/icu4c/source/test/cintltst/udatpg_test.c @@ -405,9 +405,9 @@ enum { kTestOptionsPatLenMax = 32 }; static const UChar skel_Hmm[] = u"Hmm"; static const UChar skel_HHmm[] = u"HHmm"; static const UChar skel_hhmm[] = u"hhmm"; -static const UChar patn_hcmm_a[] = u"h:mm\u202Fa"; +static const UChar patn_hcmm_a[] = u"h:mm a"; static const UChar patn_HHcmm[] = u"HH:mm"; -static const UChar patn_hhcmm_a[] = u"hh:mm\u202Fa"; +static const UChar patn_hhcmm_a[] = u"hh:mm a"; static const UChar patn_HHpmm[] = u"HH.mm"; static const UChar patn_hpmm_a[] = u"h.mm\u202Fa"; static const UChar patn_Hpmm[] = u"H.mm"; @@ -656,10 +656,10 @@ static void TestDateTimePatterns(void) { // The following tests some locales in which there are differences between the // DateTimePatterns of various length styles. DTPLocaleAndResults localeAndResults[] = { - { "en", { u"EEEE, MMMM d, y 'at' h:mm\u202Fa", // long != medium - u"MMMM d, y 'at' h:mm\u202Fa", - u"MMM d, y, h:mm\u202Fa", - u"M/d/y, h:mm\u202Fa" } }, + { "en", { u"EEEE, MMMM d, y 'at' h:mm a", // long != medium + u"MMMM d, y 'at' h:mm a", + u"MMM d, y, h:mm a", + u"M/d/y, h:mm a" } }, { "fr", { u"EEEE d MMMM y 'à' HH:mm", // medium != short u"d MMMM y 'à' HH:mm", u"d MMM y, HH:mm", @@ -683,10 +683,10 @@ static void TestDateTimePatterns(void) { u"{1} _2_ {0}", u"{1} _3_ {0}" }; - DTPLocaleAndResults enModResults = { "en", { u"EEEE, MMMM d, y _0_ h:mm\u202Fa", - u"MMMM d, y _1_ h:mm\u202Fa", - u"MMM d, y _2_ h:mm\u202Fa", - u"M/d/y _3_ h:mm\u202Fa" } + DTPLocaleAndResults enModResults = { "en", { u"EEEE, MMMM d, y _0_ h:mm a", + u"MMMM d, y _1_ h:mm a", + u"MMM d, y _2_ h:mm a", + u"M/d/y _3_ h:mm a" } }; // Test various locales with standard data @@ -817,7 +817,7 @@ static void TestRegionOverride(void) { } RegionOverrideTest; const RegionOverrideTest testCases[] = { - { "en_US", u"h:mm\u202fa", UDAT_HOUR_CYCLE_12 }, + { "en_US", u"h:mm a", UDAT_HOUR_CYCLE_12 }, { "en_GB", u"HH:mm", UDAT_HOUR_CYCLE_23 }, { "en_US@rg=GBZZZZ", u"HH:mm", UDAT_HOUR_CYCLE_23 }, { "en_US@hours=h23", u"HH:mm", UDAT_HOUR_CYCLE_23 }, @@ -859,9 +859,9 @@ static void TestISO8601(void) { { "en_US@calendar=iso8601", u"Edjmm", u"d, EEE, h:mm a" }, { "en_US@calendar=iso8601", u"EdHmm", u"d, EEE, HH:mm" }, - { "en_US", u"EEEEyMMMMdjmm", u"EEEE, MMMM d, y 'at' h:mm a" }, + { "en_US", u"EEEEyMMMMdjmm", u"EEEE, MMMM d, y 'at' h:mm a" }, { "en_US", u"EEEEyMMMMdHmm", u"EEEE, MMMM d, y 'at' HH:mm" }, - { "en_US", u"Edjmm", u"d EEE, h:mm a" }, + { "en_US", u"Edjmm", u"d EEE, h:mm a" }, { "en_US", u"EdHmm", u"d EEE, HH:mm" }, }; diff --git a/icu/icu4c/source/test/intltest/dtfmrgts.cpp b/icu/icu4c/source/test/intltest/dtfmrgts.cpp index 2fd10e01d87..fed3546b8d4 100644 --- a/icu/icu4c/source/test/intltest/dtfmrgts.cpp +++ b/icu/icu4c/source/test/intltest/dtfmrgts.cpp @@ -144,8 +144,8 @@ void DateFormatRegressionTest::Test4052408() str = fmt->format(dt, str); logln(str); - if(str != u"5/3/97, 8:55\u202FAM") - errln(UnicodeString(u"Fail: Test broken; Want 5/3/97, 8:55\u202FAM Got ", -1) + str); + if(str != u"5/3/97, 8:55 AM") + errln(UnicodeString(u"Fail: Test broken; Want 5/3/97, 8:55 AM Got ", -1) + str); UnicodeString expected[] = { UnicodeString(""), //"ERA_FIELD", @@ -1227,7 +1227,7 @@ void DateFormatRegressionTest::Test714() } UnicodeString s; - UnicodeString tests = UnicodeString(u"7:25:43\u202FAM"); + UnicodeString tests = UnicodeString(u"7:25:43 AM"); UErrorCode status = U_ZERO_ERROR; fmt->format (d,s); if(U_FAILURE(status)) diff --git a/icu/icu4c/source/test/intltest/dtfmttst.cpp b/icu/icu4c/source/test/intltest/dtfmttst.cpp index 9ef923fc25b..7af9ebb0215 100644 --- a/icu/icu4c/source/test/intltest/dtfmttst.cpp +++ b/icu/icu4c/source/test/intltest/dtfmttst.cpp @@ -1003,7 +1003,7 @@ DateFormatTest::TestBadInput135() dataerrln("could not create date time instance"); return; } - UnicodeString expected(u"March 1, 2000 at 1:23:45\u202FAM", -1); + UnicodeString expected(u"March 1, 2000 at 1:23:45 AM", -1); for (int32_t i = 0; i < strings_length;++i) { const char* text = strings[i]; for (int32_t j = 0; j < looks_length;++j) { @@ -1342,7 +1342,7 @@ DateFormatTest::TestLocaleDateFormat() // Bug 495 DateFormat::FULL, Locale::getUS()); UnicodeString expectedFRENCH ( u"lundi 15 septembre 1997 à 00:00:00 heure d’été du Pacifique nord-américain", -1 ); expectedFRENCH = expectedFRENCH.unescape(); - UnicodeString expectedUS ( u"Monday, September 15, 1997 at 12:00:00\u202FAM Pacific Daylight Time", -1 ); + UnicodeString expectedUS ( u"Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time", -1 ); logln(UnicodeString("Date set to : ") + dateToString(testDate)); UnicodeString out; if (dfUS == nullptr || dfFrench == nullptr){ @@ -5028,7 +5028,7 @@ void DateFormatTest::TestPatternFromSkeleton() { const char16_t* const pattern; } TESTDATA[] = { // Ticket #11985 - {Locale::getEnglish(), "jjmm", u"h:mm\u202Fa"}, + {Locale::getEnglish(), "jjmm", u"h:mm a"}, {Locale::getEnglish(), "JJmm", u"hh:mm"}, {Locale::getGerman(), "jjmm", u"HH:mm"}, {Locale::getGerman(), "JJmm", u"HH:mm"}, @@ -5851,10 +5851,10 @@ void DateFormatTest::TestHourCycle() { UnicodeString expectedResult; } TEST_CASES[] = { // test some locales for which we have data - { "en-us", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, - { "en-ca", u"Tuesday, March 16, 1943 at 3:45:32 p.m." }, + { "en-us", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, + { "en-ca", u"Tuesday, March 16, 1943 at 3:45:32 p.m." }, { "en-gb", u"Tuesday, 16 March 1943 at 15:45:32" }, - { "en-au", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + { "en-au", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, // test a couple locales for which we don't have specific locale files (we should still get the correct hour cycle) { "en-co", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, { "en-mx", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, @@ -5862,12 +5862,12 @@ void DateFormatTest::TestHourCycle() { { "en-us-u-rg-gbzzzz", u"Tuesday, March 16, 1943 at 15:45:32" }, { "en-us-u-rg-cazzzz", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, { "en-ca-u-rg-uszzzz", u"Tuesday, March 16, 1943 at 3:45:32 p.m." }, - { "en-gb-u-rg-uszzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, - { "en-gb-u-rg-cazzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, - { "en-gb-u-rg-auzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + { "en-gb-u-rg-uszzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + { "en-gb-u-rg-cazzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + { "en-gb-u-rg-auzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, // test that the hc ("hours") subtag does the right thing { "en-us-u-hc-h23", u"Tuesday, March 16, 1943 at 15:45:32" }, - { "en-gb-u-hc-h12", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + { "en-gb-u-hc-h12", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, // test that the rg and hc subtags do the right thing when used together { "en-us-u-rg-gbzzzz-hc-h12", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, { "en-gb-u-rg-uszzzz-hc-h23", u"Tuesday, 16 March 1943 at 15:45:32" }, diff --git a/icu/icu4c/source/test/intltest/dtifmtts.cpp b/icu/icu4c/source/test/intltest/dtifmtts.cpp index f539104be66..62d05a90e3e 100644 --- a/icu/icu4c/source/test/intltest/dtifmtts.cpp +++ b/icu/icu4c/source/test/intltest/dtifmtts.cpp @@ -496,7 +496,7 @@ void DateIntervalFormatTest::testFormat() { "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EddMMy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008", - "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM", + "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10 AM\\u2009\\u2013\\u200910/10/2008, 10:10 AM", "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmmzz", "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PDT", @@ -633,7 +633,7 @@ void DateIntervalFormatTest::testFormat() { "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EddMMy", "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007", - "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM", + "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10 AM\\u2009\\u2013\\u200911/20/2007, 10:10 AM", "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmmzz", "11/10/2007, 10:10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PST", @@ -821,7 +821,7 @@ void DateIntervalFormatTest::testFormat() { "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEddMMyyyy", "Wed, 01/10/2007", - "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmm", "10:10\\u202FAM", + "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmm", "10:10 AM", "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "HHmm", "10:10", "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmmzz", "10:10\\u202FAM PST", @@ -2382,7 +2382,7 @@ void DateIntervalFormatTest::testTicket21939() { const DateFormat* df = dif->getDateFormat(); const SimpleDateFormat* sdf = dynamic_cast(df); UnicodeString pattern; - assertEquals("Wrong pattern", u"M/d/r, h:mm\u202Fa", sdf->toPattern(pattern)); + assertEquals("Wrong pattern", u"M/d/r, h:mm a", sdf->toPattern(pattern)); } // additional tests for the related ICU-22202 diff --git a/icu/icu4c/source/test/intltest/dtptngts.cpp b/icu/icu4c/source/test/intltest/dtptngts.cpp index e7360dda69f..e76ea5cfc5b 100644 --- a/icu/icu4c/source/test/intltest/dtptngts.cpp +++ b/icu/icu4c/source/test/intltest/dtptngts.cpp @@ -107,14 +107,14 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) UnicodeString("Jan 13"), // 05: MMMd UnicodeString("January 13"), // 06: MMMMd UnicodeString("Q1 1999"), // 07: yQQQ - UnicodeString(u"11:58\u202FPM", -1), // 08: hhmm + UnicodeString(u"11:58 PM", -1), // 08: hhmm UnicodeString("23:58"), // 09: HHmm - UnicodeString(u"11:58\u202FPM", -1), // 10: jjmm + UnicodeString(u"11:58 PM", -1), // 10: jjmm UnicodeString("58:59"), // 11: mmss UnicodeString("January 1999"), // 12: yyyyMMMM UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d UnicodeString("13 Wed"), // 14: Ed -> d EEE - UnicodeString(u"11:58:59.123\u202FPM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" + UnicodeString(u"11:58:59.123 PM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" UnicodeString("11:58"), // 16: JJmm }; @@ -128,14 +128,14 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) UnicodeString("Jan 13"), // 5: MMMd UnicodeString("January 13"), // 6: MMMMd UnicodeString("Q1 11 Heisei"), // 7: yQQQ - UnicodeString(u"11:58\u202FPM", -1), // 8: hhmm + UnicodeString(u"11:58 PM", -1), // 8: hhmm UnicodeString("23:58"), // 9: HHmm - UnicodeString(u"11:58\u202FPM", -1), // 10: jjmm + UnicodeString(u"11:58 PM", -1), // 10: jjmm UnicodeString("58:59"), // 11: mmss UnicodeString("January 11 Heisei"), // 12: yyyyMMMM UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d" UnicodeString("13 Wed"), // 14: Ed -> d EEE - UnicodeString(u"11:58:59.123\u202FPM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" + UnicodeString(u"11:58:59.123 PM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" UnicodeString("11:58"), // 16: JJmm }; @@ -377,14 +377,14 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) UnicodeString("O 14, 1999"), UnicodeString("T, O 14"), UnicodeString("Oct 14"), - UnicodeString(u"Oct 14, 6:58\u202FAM", -1), - UnicodeString(u"Thu, Oct 14, 6:58:59\u202FAM", -1), - UnicodeString(u"10/14, 6:58\u202FAM", -1), - UnicodeString(u"Thursday, Oct 14, 6:58:59\u202FAM", -1), - UnicodeString(u"Oct 14, 1999, 6:58:59\u202FAM", -1), - UnicodeString(u"Thu, Oct 14, 1999, 6:58:59\u202FAM", -1), - UnicodeString(u"6:58\u202FAM", -1), - UnicodeString(u"6:58\u202FAM", -1), + UnicodeString(u"Oct 14, 6:58 AM", -1), + UnicodeString(u"Thu, Oct 14, 6:58:59 AM", -1), + UnicodeString(u"10/14, 6:58 AM", -1), + UnicodeString(u"Thursday, Oct 14, 6:58:59 AM", -1), + UnicodeString(u"Oct 14, 1999, 6:58:59 AM", -1), + UnicodeString(u"Thu, Oct 14, 1999, 6:58:59 AM", -1), + UnicodeString(u"6:58 AM", -1), + UnicodeString(u"6:58 AM", -1), UnicodeString(u"6:58\u202FAM GMT+00:00", -1), UnicodeString(""), }; @@ -908,10 +908,10 @@ void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/) // locale skel expectedPattern options { "en", "Hmm", u"HH:mm", UDATPG_MATCH_NO_OPTIONS }, { "en", "HHmm", u"HH:mm", UDATPG_MATCH_NO_OPTIONS }, - { "en", "hhmm", u"h:mm\u202Fa", UDATPG_MATCH_NO_OPTIONS }, + { "en", "hhmm", u"h:mm a", UDATPG_MATCH_NO_OPTIONS }, { "en", "Hmm", u"HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, { "en", "HHmm", u"HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, - { "en", "hhmm", u"hh:mm\u202Fa", UDATPG_MATCH_HOUR_FIELD_LENGTH }, + { "en", "hhmm", u"hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH }, { "da", "Hmm", u"HH.mm", UDATPG_MATCH_NO_OPTIONS }, { "da", "HHmm", u"HH.mm", UDATPG_MATCH_NO_OPTIONS }, { "da", "hhmm", u"h.mm\u202Fa", UDATPG_MATCH_NO_OPTIONS }, @@ -1540,6 +1540,18 @@ void IntlTestDateTimePatternGeneratorAPI::test_jConsistencyOddLocales() { // ICU continue; } if (dtfShortPattern != dtfSkelPattern || dtfSkelPattern != dtpgPattern) { + if (uprv_strcmp(localeID, "en") == 0) { + UnicodeString dtfShortPatternForCompare(dtfShortPattern); + UnicodeString dtfSkelPatternForCompare(dtfSkelPattern); + UnicodeString dtpgPatternForCompare(dtpgPattern); + dtfShortPatternForCompare.findAndReplace(u"\u202F", u" "); + dtfSkelPatternForCompare.findAndReplace(u"\u202F", u" "); + dtpgPatternForCompare.findAndReplace(u"\u202F", u" "); + if (dtfShortPatternForCompare == dtfSkelPatternForCompare && + dtfSkelPatternForCompare == dtpgPatternForCompare) { + continue; + } + } const char* dtfShortValidLoc = dtfShort->getLocaleID(ULOC_VALID_LOCALE, status); const char* dtfShortActualLoc = dtfShort->getLocaleID(ULOC_ACTUAL_LOCALE, status); errln(UnicodeString("For locale ") + localeID + @@ -1635,10 +1647,10 @@ void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() { // The following tests some locales in which there are differences between the // DateTimePatterns of various length styles. DTPLocaleAndResults localeAndResults[] = { - { "en", { UnicodeString(u"EEEE, MMMM d, y 'at' h:mm\u202Fa"), // long != medium - UnicodeString(u"MMMM d, y 'at' h:mm\u202Fa"), - UnicodeString(u"MMM d, y, h:mm\u202Fa"), - UnicodeString(u"M/d/y, h:mm\u202Fa") } }, + { "en", { UnicodeString(u"EEEE, MMMM d, y 'at' h:mm a"), // long != medium + UnicodeString(u"MMMM d, y 'at' h:mm a"), + UnicodeString(u"MMM d, y, h:mm a"), + UnicodeString(u"M/d/y, h:mm a") } }, { "fr", { UnicodeString(u"EEEE d MMMM y 'à' HH:mm"), // medium != short UnicodeString(u"d MMMM y 'à' HH:mm"), UnicodeString(u"d MMM y, HH:mm"), @@ -1663,10 +1675,10 @@ void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() { UnicodeString(u"{1} _2_ {0}"), UnicodeString(u"{1} _3_ {0}") }; - DTPLocaleAndResults enModResults = { "en", { UnicodeString(u"EEEE, MMMM d, y _0_ h:mm\u202Fa"), - UnicodeString(u"MMMM d, y _1_ h:mm\u202Fa"), - UnicodeString(u"MMM d, y _2_ h:mm\u202Fa"), - UnicodeString(u"M/d/y _3_ h:mm\u202Fa") } + DTPLocaleAndResults enModResults = { "en", { UnicodeString(u"EEEE, MMMM d, y _0_ h:mm a"), + UnicodeString(u"MMMM d, y _1_ h:mm a"), + UnicodeString(u"MMM d, y _2_ h:mm a"), + UnicodeString(u"M/d/y _3_ h:mm a") } }; // Test various locales with standard data @@ -1784,7 +1796,7 @@ void IntlTestDateTimePatternGeneratorAPI::testRegionOverride() { const char16_t* expectedPattern; UDateFormatHourCycle expectedHourCycle; } testCases[] = { - { "en_US", u"h:mm\u202fa", UDAT_HOUR_CYCLE_12 }, + { "en_US", u"h:mm a", UDAT_HOUR_CYCLE_12 }, { "en_GB", u"HH:mm", UDAT_HOUR_CYCLE_23 }, { "en_US@rg=GBZZZZ", u"HH:mm", UDAT_HOUR_CYCLE_23 }, { "en_US@hours=h23", u"HH:mm", UDAT_HOUR_CYCLE_23 }, diff --git a/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp b/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp index f01b64baf51..3492e06f92a 100644 --- a/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp +++ b/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp @@ -48,7 +48,7 @@ there was {$what} on planet {$planet :integer}.") .setArgument("planet", (int64_t) 7) .setDateArgument("when", (UDate) 871068000000) .setArgument("what", "a disturbance in the Force") - .setExpected(CharsToUnicodeString("At 12:20:00\\u202FPM on Aug 8, 1997, there was a disturbance in the Force on planet 7.")) + .setExpected(CharsToUnicodeString("At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.")) .build(), errorCode); } diff --git a/icu/icu4c/source/test/intltest/tmsgfmt.cpp b/icu/icu4c/source/test/intltest/tmsgfmt.cpp index 54b71ed3e78..0603136ba11 100644 --- a/icu/icu4c/source/test/intltest/tmsgfmt.cpp +++ b/icu/icu4c/source/test/intltest/tmsgfmt.cpp @@ -288,7 +288,7 @@ void TestMessageFormat::PatternTest() u"Quotes ', {, 'a' 1 {0}", u"Quotes ', {, 'a' 1 {0}", u"{1,number,'#',##} #34,56", - u"There are 3,456 files on Disk at 1/12/70, 5:46\u202FAM.", + u"There are 3,456 files on Disk at 1/12/70, 5:46 AM.", u"On Disk, there are 3,456 files, with $1.00.", u"{1,number,percent}, 345,600%,", u"{1,date,full}, Wednesday, December 31, 1969,", @@ -419,7 +419,7 @@ void TestMessageFormat::testStaticFormat() } const UnicodeString expected( - u"At 12:20:00\u202FPM on Aug 8, 1997, there was a disturbance in the Force on planet 7."); + u"At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7."); if (result != expected) { errln(UnicodeString("TestMessageFormat::testStaticFormat failed on test") + UnicodeString("\n Result: ") + result + @@ -1502,7 +1502,7 @@ void TestMessageFormat::TestUnlimitedArgsAndSubformats() { UnicodeString expected = u"On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) " - u"at 9:46:40\u202FAM (aka 9:46\u202FAM, aka 9:46:40\u202FAM PST) " + u"at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) " u"there were 1,303 werjes " u"(a 8% increase over 1,202) " u"despite the Glimmung's efforts " diff --git a/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json b/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json index 21f917da6e5..b72421119ee 100644 --- a/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json +++ b/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json @@ -2,18 +2,18 @@ "Date and time formats": [ { "src": "Expires on {$exp}", - "exp": "Expires on 8/3/24, 9:43 PM", + "exp": "Expires on 8/3/24, 9:43 PM", "comment": "Modified from ICU4J copy to add params (likewise with the other date/time tests); 1722746637000 is 2024-08-03 21:43:57 PDT", "params": {"exp": { "date": 1722746637000 } } }, { "src": "Expires on {$exp :datetime}", - "exp": "Expires on 8/3/24, 9:43 PM", + "exp": "Expires on 8/3/24, 9:43 PM", "params": {"exp": { "date": 1722746637000 } } }, { "src": "Expires on {$exp :datetime icu:skeleton=yMMMMdjmsSSEE}", - "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", + "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", "params": {"exp": { "date": 1722746637000 } }, "ignoreTest": "ICU-22754 Skeleton option not implemented yet" }, @@ -34,22 +34,22 @@ }, { "src": "Expires on {$exp :datetime timeStyle=long}", - "exp": "Expires on 9:43:57 PM PDT", + "exp": "Expires on 9:43:57 PM PDT", "params": {"exp": { "date": 1722746637000 } } }, { "src": "Expires on {$exp :datetime timeStyle=medium}", - "exp": "Expires on 9:43:57 PM", + "exp": "Expires on 9:43:57 PM", "params": {"exp": { "date": 1722746637000 } } }, { "src": "Expires on {$exp :datetime timeStyle=short}", - "exp": "Expires on 9:43 PM", + "exp": "Expires on 9:43 PM", "params": {"exp": { "date": 1722746637000 } } }, { "src": "Expires on {$exp :datetime dateStyle=full timeStyle=medium}", - "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", + "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", "params": {"exp": { "date": 1722746637000 } } }, { @@ -72,14 +72,14 @@ { "comment": "Make sure we ignore date / time fields if needed", "src": "Expires at {$exp :time year=numeric month=medium day=numeric weekday=long hour=numeric minute=numeric}", - "exp": "Expires at 9:43 PM", + "exp": "Expires at 9:43 PM", "params": {"exp": { "date": 1722746637000 } }, "ignoreTest": "ICU-22754 ICU4C doesn't accept field options for `:date` or `:time` -- see spec" }, { "comment": "Make sure we ignore date / time fields if needed", "src": "Expires at {$exp :time style=long dateStyle=full timeStyle=medium}", - "exp": "Expires at 9:43:57 PM PDT", + "exp": "Expires at 9:43:57 PM PDT", "params": {"exp": { "date": 1722746637000 } } }, { @@ -96,11 +96,11 @@ }, { "src": "Expires at {|2024-07-02T19:23:45| :datetime timeStyle=full}", - "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + "exp": "Expires at 7:23:45 PM Pacific Daylight Time" }, { "src": "Expires at {|2024-07-02T19:23:45.123| :datetime timeStyle=full}", - "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + "exp": "Expires at 7:23:45 PM Pacific Daylight Time" }, { "src": "Expires on {|2025-02-27T19:23:45| :datetime dateStyle=full}", @@ -108,11 +108,11 @@ }, { "src": "Expires at {|2024-07-02T19:23:45Z| :datetime timeStyle=long}", - "exp": "Expires at 7:23:45 PM GMT" + "exp": "Expires at 7:23:45 PM GMT" }, { "src": "Expires at {|2024-07-02T19:23:45+03:30| :datetime timeStyle=full}", - "exp": "Expires at 7:23:45 PM GMT+03:30" + "exp": "Expires at 7:23:45 PM GMT+03:30" } ], "Chaining" : [ @@ -125,7 +125,7 @@ ".local $zooExp = {$exp :datetime dateStyle=short timeStyle=$tsOver}\n", "{{Hello John, you want '{$exp}', '{$longExp}', or '{$zooExp}' or even '{$exp :datetime dateStyle=full}'?}}" ], - "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", + "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", "params": {"exp": { "date": 1722746637000 }, "user": "John", "tsOver" : "long" }, "ignoreTest": "ICU-22754 ICU4C doesn't implement this kind of function composition yet. See https://github.com/unicode-org/message-format-wg/issues/515" }, diff --git a/icu/testdata/message2/icu-test-functions.json b/icu/testdata/message2/icu-test-functions.json index a97446addf0..87e7b401b13 100644 --- a/icu/testdata/message2/icu-test-functions.json +++ b/icu/testdata/message2/icu-test-functions.json @@ -7,18 +7,18 @@ "tests": [ { "src": "Expires on {$exp}", - "exp": "Expires on 8/3/24, 9:43 PM", + "exp": "Expires on 8/3/24, 9:43 PM", "comment": "Modified from ICU4J copy to add params (likewise with the other date/time tests); 1722746637000 is 2024-08-03 21:43:57 PDT", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { "src": "Expires on {$exp :datetime}", - "exp": "Expires on 8/3/24, 9:43 PM", + "exp": "Expires on 8/3/24, 9:43 PM", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { "src": "Expires on {$exp :datetime icu:skeleton=yMMMMdjmsSSEE}", - "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", + "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }], "ignoreCpp": "ICU-22754 Skeleton option not implemented yet" }, @@ -39,22 +39,22 @@ }, { "src": "Expires on {$exp :datetime timeStyle=long}", - "exp": "Expires on 9:43:57 PM PDT", + "exp": "Expires on 9:43:57 PM PDT", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { "src": "Expires on {$exp :datetime timeStyle=medium}", - "exp": "Expires on 9:43:57 PM", + "exp": "Expires on 9:43:57 PM", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { "src": "Expires on {$exp :datetime timeStyle=short}", - "exp": "Expires on 9:43 PM", + "exp": "Expires on 9:43 PM", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { "src": "Expires on {$exp :datetime dateStyle=full timeStyle=medium}", - "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", + "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { @@ -77,14 +77,14 @@ { "comment": "Make sure we ignore date / time fields if needed", "src": "Expires at {$exp :time year=numeric month=medium day=numeric weekday=long hour=numeric minute=numeric}", - "exp": "Expires at 9:43 PM", + "exp": "Expires at 9:43 PM", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }], "ignoreCpp": "ICU-22754 ICU4C doesn't accept field options for `:date` or `:time` -- see spec" }, { "comment": "Make sure we ignore date / time fields if needed", "src": "Expires at {$exp :time style=long dateStyle=full timeStyle=medium}", - "exp": "Expires at 9:43:57 PM PDT", + "exp": "Expires at 9:43:57 PM PDT", "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] }, { @@ -99,11 +99,11 @@ }, { "src": "Expires at {|2024-07-02T19:23:45| :datetime timeStyle=full}", - "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + "exp": "Expires at 7:23:45 PM Pacific Daylight Time" }, { "src": "Expires at {|2024-07-02T19:23:45.123| :datetime timeStyle=full}", - "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + "exp": "Expires at 7:23:45 PM Pacific Daylight Time" }, { "src": "Expires on {|2025-02-27T19:23:45| :datetime dateStyle=full}", @@ -111,12 +111,12 @@ }, { "src": "Expires at {|2024-07-02T19:23:45Z| :datetime timeStyle=long}", - "exp": "Expires at 7:23:45 PM GMT", + "exp": "Expires at 7:23:45 PM GMT", "ignoreCpp": "ICU-22754 Time zones not working yet (bug)" }, { "src": "Expires at {|2024-07-02T19:23:45+03:30| :datetime timeStyle=full}", - "exp": "Expires at 7:23:45 PM GMT+03:30", + "exp": "Expires at 7:23:45 PM GMT+03:30", "ignoreCpp": "ICU-22754 Time zones not working yet (bug)" }, { @@ -128,7 +128,7 @@ ".local $zooExp = {$exp :datetime dateStyle=short timeStyle=$tsOver}\n", "{{Hello John, you want '{$exp}', '{$longExp}', or '{$zooExp}' or even '{$exp :datetime dateStyle=full}'?}}" ], - "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", + "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", "params": [{"name": "exp", "value": { "date": 1722746637000 }}, {"name": "user", "value": "John"}, {"name": "tsOver", "value": "full" }], diff --git a/icu/testdata/message2/more-functions.json b/icu/testdata/message2/more-functions.json index 6d074f8b2d8..90dc1274ba7 100644 --- a/icu/testdata/message2/more-functions.json +++ b/icu/testdata/message2/more-functions.json @@ -47,17 +47,17 @@ }, { "src": "Testing date formatting: {$date :time style=long}.", - "exp": "Testing date formatting: 7:42:37\u202FPM PST.", + "exp": "Testing date formatting: 7:42:37 PM PST.", "params": [{ "name": "date", "value": { "date": 1669261357000 } }] }, { "src": "Testing date formatting: {$date :time style=medium}.", - "exp": "Testing date formatting: 7:42:37\u202FPM.", + "exp": "Testing date formatting: 7:42:37 PM.", "params": [{ "name": "date", "value": { "date": 1669261357000 } }] }, { "src": "Testing date formatting: {$date :time style=short}.", - "exp": "Testing date formatting: 7:42\u202FPM.", + "exp": "Testing date formatting: 7:42 PM.", "params": [{ "name": "date", "value": { "date": 1669261357000 } }] }, { From f092b9b9591c9f993c5df2dc84f00a802057ca8a Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 15:26:32 +0530 Subject: [PATCH 17/26] Port MS locale display test expectations Adjust ICU tests for CLDR-MS display-name differences and removed yue collation aliases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit cc5f6bc34c317c55a6e5ce83f451fe4640525815) --- icu/icu4c/source/test/cintltst/cloctst.c | 60 ++++++++++----------- icu/icu4c/source/test/cintltst/creststn.c | 12 ----- icu/icu4c/source/test/intltest/apicoll.cpp | 13 +---- icu/icu4c/source/test/intltest/locnmtst.cpp | 4 +- 4 files changed, 33 insertions(+), 56 deletions(-) diff --git a/icu/icu4c/source/test/cintltst/cloctst.c b/icu/icu4c/source/test/cintltst/cloctst.c index 94f452aa561..37cf24ded00 100644 --- a/icu/icu4c/source/test/cintltst/cloctst.c +++ b/icu/icu4c/source/test/cintltst/cloctst.c @@ -1268,8 +1268,8 @@ typedef struct { static const DisplayNameBracketsItem displayNameBracketsItems[] = { { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)" }, - { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])" }, - { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])" }, + { "en", "MM", "my_MM", "Myanmar", "Burmese (Myanmar)" }, + { "en", "MM", "my_Mymr_MM", "Myanmar", "Burmese (Myanmar, Myanmar)" }, { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B", "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" }, { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09", "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" }, { NULL, NULL, NULL, NULL, NULL } @@ -7163,11 +7163,11 @@ static const UldnItem en_StdMidLong[] = { { "en", TEST_ULOC_LANGUAGE, u"English" }, // https://unicode-org.atlassian.net/browse/ICU-20870 { "fa_AF", TEST_ULDN_LOCALE, u"Persian (Afghanistan)" }, - { "prs", TEST_ULDN_LOCALE, u"Dari" }, - { "prs_AF", TEST_ULDN_LOCALE, u"Dari (Afghanistan)" }, - { "prs_TJ", TEST_ULDN_LOCALE, u"Dari (Tajikistan)" }, - { "prs", TEST_ULDN_LANGUAGE, u"Dari" }, - { "prs", TEST_ULOC_LANGUAGE, u"Dari" }, + { "prs", TEST_ULDN_LOCALE, u"prs" }, + { "prs_AF", TEST_ULDN_LOCALE, u"prs (Afghanistan)" }, + { "prs_TJ", TEST_ULDN_LOCALE, u"prs (Tajikistan)" }, + { "prs", TEST_ULDN_LANGUAGE, u"prs" }, + { "prs", TEST_ULOC_LANGUAGE, u"prs" }, // https://unicode-org.atlassian.net/browse/ICU-21742 { "ji", TEST_ULDN_LOCALE, u"Yiddish" }, { "ji_US", TEST_ULDN_LOCALE, u"Yiddish (United States)" }, @@ -7183,23 +7183,23 @@ static const UldnItem en_StdMidLong[] = { }; static const UldnItem en_StdMidShrt[] = { - { "en_US", TEST_ULDN_LOCALE, u"English (US)" }, + { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, { "en", TEST_ULDN_LANGUAGE, u"English" }, }; static const UldnItem en_DiaMidLong[] = { - { "en_US", TEST_ULDN_LOCALE, u"American English" }, - { "fa_AF", TEST_ULDN_LOCALE, u"Dari" }, - { "prs", TEST_ULDN_LOCALE, u"Dari" }, - { "prs_AF", TEST_ULDN_LOCALE, u"Dari (Afghanistan)" }, - { "prs_TJ", TEST_ULDN_LOCALE, u"Dari (Tajikistan)" }, - { "prs", TEST_ULDN_LANGUAGE, u"Dari" }, + { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, + { "fa_AF", TEST_ULDN_LOCALE, u"Persian (Afghanistan)" }, + { "prs", TEST_ULDN_LOCALE, u"prs" }, + { "prs_AF", TEST_ULDN_LOCALE, u"prs (Afghanistan)" }, + { "prs_TJ", TEST_ULDN_LOCALE, u"prs (Tajikistan)" }, + { "prs", TEST_ULDN_LANGUAGE, u"prs" }, { "mo", TEST_ULDN_LOCALE, u"Romanian" }, { "mo", TEST_ULDN_LANGUAGE, u"Romanian" }, }; static const UldnItem en_DiaMidShrt[] = { - { "en_US", TEST_ULDN_LOCALE, u"US English" }, + { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, }; static const UldnItem ro_StdMidLong[] = { // https://unicode-org.atlassian.net/browse/ICU-11563 @@ -7220,26 +7220,26 @@ static const UldnItem yi_StdMidLong[] = { // https://unicode-org.atlassian.net/b static const UldnItem zh_DiaMidLong[] = { // zh and zh_Hant both have dialect names for the following in ICU 73 - { "ar_001", TEST_ULDN_LOCALE, u"现代标准阿拉伯语" }, - { "nl_BE", TEST_ULDN_LOCALE, u"弗拉芒语" }, - { "ro_MD", TEST_ULDN_LOCALE, u"摩尔多瓦语" }, + { "ar_001", TEST_ULDN_LOCALE, u"阿拉伯语(世界)" }, + { "nl_BE", TEST_ULDN_LOCALE, u"荷兰语(比利时)" }, + { "ro_MD", TEST_ULDN_LOCALE, u"罗马尼亚语(摩尔多瓦)" }, // zh has dialect names for the following in ICU 73 - { "en_AU", TEST_ULDN_LOCALE, u"澳大利亚英语" }, - { "en_CA", TEST_ULDN_LOCALE, u"加拿大英语" }, - { "en_GB", TEST_ULDN_LOCALE, u"英国英语" }, - { "en_US", TEST_ULDN_LOCALE, u"美国英语" }, - { "es_419", TEST_ULDN_LOCALE, u"拉丁美洲西班牙语" }, - { "es_ES", TEST_ULDN_LOCALE, u"欧洲西班牙语" }, - { "es_MX", TEST_ULDN_LOCALE, u"墨西哥西班牙语" }, - { "fr_CA", TEST_ULDN_LOCALE, u"加拿大法语" }, - { "fr_CH", TEST_ULDN_LOCALE, u"瑞士法语" }, + { "en_AU", TEST_ULDN_LOCALE, u"英语(澳大利亚)" }, + { "en_CA", TEST_ULDN_LOCALE, u"英语(加拿大)" }, + { "en_GB", TEST_ULDN_LOCALE, u"英语(英国)" }, + { "en_US", TEST_ULDN_LOCALE, u"英语(美国)" }, + { "es_419", TEST_ULDN_LOCALE, u"西班牙语(拉丁美洲)" }, + { "es_ES", TEST_ULDN_LOCALE, u"西班牙语(西班牙)" }, + { "es_MX", TEST_ULDN_LOCALE, u"西班牙语(墨西哥)" }, + { "fr_CA", TEST_ULDN_LOCALE, u"法语(加拿大)" }, + { "fr_CH", TEST_ULDN_LOCALE, u"法语(瑞士)" }, }; static const UldnItem zh_Hant_DiaMidLong[] = { // zh and zh_Hant both have dialect names for the following in ICU 73 - { "ar_001", TEST_ULDN_LOCALE, u"現代標準阿拉伯文" }, - { "nl_BE", TEST_ULDN_LOCALE, u"法蘭德斯文" }, - { "ro_MD", TEST_ULDN_LOCALE, u"摩爾多瓦文" }, + { "ar_001", TEST_ULDN_LOCALE, u"阿拉伯文(世界)" }, + { "nl_BE", TEST_ULDN_LOCALE, u"荷蘭文(比利時)" }, + { "ro_MD", TEST_ULDN_LOCALE, u"羅馬尼亞文(摩爾多瓦)" }, // zh_Hant no dialect names for the following in ICU-73, // use standard name { "en_AU", TEST_ULDN_LOCALE, u"英文(澳洲)" }, diff --git a/icu/icu4c/source/test/cintltst/creststn.c b/icu/icu4c/source/test/cintltst/creststn.c index 71fd936e377..63a758c5b78 100644 --- a/icu/icu4c/source/test/cintltst/creststn.c +++ b/icu/icu4c/source/test/cintltst/creststn.c @@ -2715,16 +2715,6 @@ static void TestGetFunctionalEquivalent(void) { "f", "nl_NL@collation=stroke", "root", "f", "nl_NL_EEXT@collation=stroke", "root", /* Additions to test aliased locales */ - "f", "yue_HK", "zh@collation=stroke", - "f", "yue_Hant", "zh@collation=stroke", - "f", "yue_Hant_HK", "zh@collation=stroke", - "f", "yue@collation=stroke", "zh@collation=stroke", - "f", "yue@collation=pinyin", "zh", - "f", "yue_CN", "zh", - "f", "yue_Hans", "zh", - "f", "yue_Hans_CN", "zh", - "f", "yue_Hans@collation=pinyin", "zh", - "f", "yue_Hans@collation=stroke", "zh@collation=stroke", "f", "mo", "mo", "t", "no", "no", "t", "nb", "no", @@ -2735,8 +2725,6 @@ static void TestGetFunctionalEquivalent(void) { "f", "zh_Hant_CN", "zh@collation=stroke", "f", "zh_Hant_US", "zh@collation=stroke", "f", "zh_Hans_US", "zh", - "f", "yue_TW", "zh@collation=stroke", - "f", "yue_US", "zh@collation=stroke", "f", "ja_CN", "ja", "f", "ja_US", "ja", NULL diff --git a/icu/icu4c/source/test/intltest/apicoll.cpp b/icu/icu4c/source/test/intltest/apicoll.cpp index 4ccdc373e6c..a31873fe436 100644 --- a/icu/icu4c/source/test/intltest/apicoll.cpp +++ b/icu/icu4c/source/test/intltest/apicoll.cpp @@ -1664,18 +1664,7 @@ void CollationAPITest::TestGetLocale() { { "zh_TW", "zh_Hant_TW", "zh@collation=stroke" }, { "zh_TW@collation=pinyin", "zh_Hant_TW@collation=pinyin", "zh" }, { "zh_CN@collation=stroke", "zh_Hans_CN@collation=stroke", "zh@collation=stroke" }, - // yue/yue_Hant aliased to zh_Hant, yue_Hans aliased to zh_Hans. - { "yue", "zh_Hant", "zh@collation=stroke" }, - { "yue_HK", "zh_Hant", "zh@collation=stroke" }, - { "yue_Hant", "zh_Hant", "zh@collation=stroke" }, - { "yue_Hant_HK", "zh_Hant", "zh@collation=stroke" }, - { "yue@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, - { "yue_HK@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, - { "yue_CN", "zh_Hans", "zh" }, - { "yue_Hans", "zh_Hans", "zh" }, - { "yue_Hans_CN", "zh_Hans", "zh" }, - { "yue_Hans@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" }, - { "yue_CN@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" } + // CLDR-MS does not ship yue collation aliases. }; u_unescape(rules, rlz, 256); diff --git a/icu/icu4c/source/test/intltest/locnmtst.cpp b/icu/icu4c/source/test/intltest/locnmtst.cpp index 864b57ef518..ef217426c7b 100644 --- a/icu/icu4c/source/test/intltest/locnmtst.cpp +++ b/icu/icu4c/source/test/intltest/locnmtst.cpp @@ -104,7 +104,7 @@ void LocaleDisplayNamesTest::TestCreateDialect() { LocaleDisplayNames *ldn = LocaleDisplayNames::createInstance(Locale::getUS(), ULDN_DIALECT_NAMES); ldn->localeDisplayName("en_GB", temp); delete ldn; - test_assert_equal("British English", temp); + test_assert_equal("English (United Kingdom)", temp); } void LocaleDisplayNamesTest::TestWithKeywordsAndEverything() { @@ -190,7 +190,7 @@ void LocaleDisplayNamesTest::TestUldnOpenDialect() { test_assert(U_SUCCESS(status)); UnicodeString str(result, len, kMaxResultSize); - test_assert_equal("British English", str); + test_assert_equal("English (United Kingdom)", str); } void LocaleDisplayNamesTest::TestUldnWithGarbage() { From bc0056e0db643eabd32ee75468bf0bfecdf87604 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 15:26:45 +0530 Subject: [PATCH 18/26] Port CLDR-MS 029 locale test expectations Treat 029 locales as US measurement/paper locales and expect en_029 currency data from CLDR-MS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 3360853d2471954ce12403e147aadce4c34b7d4f) --- icu/icu4c/source/test/cintltst/cldrtest.c | 4 ++-- icu/icu4c/source/test/cintltst/cnmdptst.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/icu/icu4c/source/test/cintltst/cldrtest.c b/icu/icu4c/source/test/cintltst/cldrtest.c index e014a1e1d59..8cf8e5dc1ba 100644 --- a/icu/icu4c/source/test/cintltst/cldrtest.c +++ b/icu/icu4c/source/test/cintltst/cldrtest.c @@ -1122,7 +1122,7 @@ static void VerifyTranslation(void) { if (U_FAILURE(errorCode)) { log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); } else { - if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_LR")!=NULL ) { + if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_LR")!=NULL || strstr(fullLoc, "_029")!=NULL ) { if(measurementSystem != UMS_US){ log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); } @@ -1143,7 +1143,7 @@ static void VerifyTranslation(void) { if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_BZ")!=NULL || strstr(fullLoc, "_CA")!=NULL || strstr(fullLoc, "_CL")!=NULL || strstr(fullLoc, "_CO")!=NULL || strstr(fullLoc, "_CR")!=NULL || strstr(fullLoc, "_GT")!=NULL || strstr(fullLoc, "_MX")!=NULL || strstr(fullLoc, "_NI")!=NULL || strstr(fullLoc, "_PA")!=NULL || strstr(fullLoc, "_PH")!=NULL || strstr(fullLoc, "_PR")!=NULL || - strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL ) { + strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL || strstr(fullLoc, "_029")!=NULL ) { if (height != 279 || width != 216) { log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); } diff --git a/icu/icu4c/source/test/cintltst/cnmdptst.c b/icu/icu4c/source/test/cintltst/cnmdptst.c index 98504e0220f..b7ce012361b 100644 --- a/icu/icu4c/source/test/cintltst/cnmdptst.c +++ b/icu/icu4c/source/test/cintltst/cnmdptst.c @@ -813,7 +813,7 @@ static void TestGetKeywordValuesForLocale(void) { { "und", "USD", "USN", NULL }, /* { "und_ZZ", "USD", NULL, NULL }, -- temporarily remove as this locale now has 15 entries */ { "en_US", "USD", "USN", NULL }, - { "en_029", "USD", "USN", NULL }, + { "en_029", "XCD", NULL, NULL }, { "en_TH", "THB", NULL, NULL }, { "de", "EUR", NULL, NULL }, { "de_DE", "EUR", NULL, NULL }, @@ -827,11 +827,11 @@ static void TestGetKeywordValuesForLocale(void) { { "en_US@currency=CAD;rg=THZZZZ", "THB", NULL, NULL }, }; const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { - 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1 + 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1 }; /* ucurr_forLocale results for same locales; "" if no result expected */ const char *FORLOCALE[PREFERRED_SIZE] = { - "", "", "USD", "", + "", "", "USD", "XCD", "THB", "", "EUR", "", "ILS", "CAD", "ZZZ", "DEM", "THB", "USD", "CAD" From 1c4b96bdebcacec09508f334d9edf643778b6474 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 15:48:11 +0530 Subject: [PATCH 19/26] Port remaining format display expectations Update data-driven date-format spacing expectations and en_GB display-context expectations for CLDR-MS data. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit a8036376114818033fb0df1b6c1b765f23933dac) --- icu/icu4c/source/test/intltest/locnmtst.cpp | 12 ++++++------ icu/icu4c/source/test/testdata/format.txt | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/icu/icu4c/source/test/intltest/locnmtst.cpp b/icu/icu4c/source/test/intltest/locnmtst.cpp index ef217426c7b..0703866445d 100644 --- a/icu/icu4c/source/test/intltest/locnmtst.cpp +++ b/icu/icu4c/source/test/intltest/locnmtst.cpp @@ -299,22 +299,22 @@ static char16_t daFor_en[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"en static char16_t daFor_en_cabud[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x62,0x75,0x64,0x64,0x68,0x69,0x73,0x74,0x69,0x73,0x6B,0x20, 0x6B,0x61,0x6C,0x65,0x6E,0x64,0x65,0x72,0x29,0}; //"engelsk (buddhistisk kalender)" static char16_t daFor_en_GB[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"engelsk (Storbritannien)" -static char16_t daFor_en_GB_D[] = {0x62,0x72,0x69,0x74,0x69,0x73,0x6B,0x20,0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"britisk engelsk" +static char16_t daFor_en_GB_D[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"engelsk (Storbritannien)" static char16_t esFor_en[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0}; //"ingles" with acute on the e static char16_t esFor_en_GB[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"ingles (Reino Unido)" ... -static char16_t esFor_en_GB_S[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x55,0x29,0}; //"ingles (RU)" ... -static char16_t esFor_en_GB_D[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x62,0x72,0x69,0x74,0xE1,0x6E,0x69,0x63,0x6F,0}; //"ingles britanico" with acute on the e, a +static char16_t esFor_en_GB_S[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"ingles (Reino Unido)" ... +static char16_t esFor_en_GB_D[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"ingles (Reino Unido)" ... static char16_t ruFor_uz_Latn[] = {0x0443,0x0437,0x0431,0x0435,0x043A,0x0441,0x043A,0x0438,0x0439,0x20,0x28,0x043B,0x0430,0x0442,0x0438,0x043D,0x0438,0x0446,0x0430,0x29,0}; // all lowercase #if !UCONFIG_NO_BREAK_ITERATION static char16_t daFor_en_T[] = {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"Engelsk" static char16_t daFor_en_cabudT[]= {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x62,0x75,0x64,0x64,0x68,0x69,0x73,0x74,0x69,0x73,0x6B,0x20, 0x6B,0x61,0x6C,0x65,0x6E,0x64,0x65,0x72,0x29,0}; //"Engelsk (buddhistisk kalender)" static char16_t daFor_en_GB_T[] = {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"Engelsk (Storbritannien)" -static char16_t daFor_en_GB_DT[] = {0x42,0x72,0x69,0x74,0x69,0x73,0x6B,0x20,0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"Britisk engelsk" +static char16_t daFor_en_GB_DT[] = {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"Engelsk (Storbritannien)" static char16_t esFor_en_T[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0}; //"Ingles" with acute on the e static char16_t esFor_en_GB_T[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"Ingles (Reino Unido)" ... -static char16_t esFor_en_GB_ST[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x55,0x29,0}; //"Ingles (RU)" ... -static char16_t esFor_en_GB_DT[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x62,0x72,0x69,0x74,0xE1,0x6E,0x69,0x63,0x6F,0}; //"Ingles britanico" with acute on the e, a +static char16_t esFor_en_GB_ST[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"Ingles (Reino Unido)" ... +static char16_t esFor_en_GB_DT[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"Ingles (Reino Unido)" ... static char16_t ruFor_uz_Latn_T[]= {0x0423,0x0437,0x0431,0x0435,0x043A,0x0441,0x043A,0x0438,0x0439,0x20,0x28,0x043B,0x0430,0x0442,0x0438,0x043D,0x0438,0x0446,0x0430,0x29,0}; // first char upper #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/icu/icu4c/source/test/testdata/format.txt b/icu/icu4c/source/test/testdata/format.txt index e3d6e72fd8b..b8d3c3ba5b9 100644 --- a/icu/icu4c/source/test/testdata/format.txt +++ b/icu/icu4c/source/test/testdata/format.txt @@ -37,7 +37,7 @@ format:table(nofallback) { "", "DATE=SHORT,TIME=SHORT", "ERA=1,YEAR=2007,MONTH=AUGUST,DATE=8,HOUR_OF_DAY=18,MINUTE=54,SECOND=0", - "8/8/07, 6:54 PM" + "8/8/07, 6:54 PM" }, { "zh_TW@calendar=roc", @@ -102,14 +102,14 @@ format:table(nofallback) { "GMT", "TIME=LONG", "ERA=1,YEAR=2012,MONTH=OCTOBER,DATE=8,HOUR_OF_DAY=23,MINUTE=59,SECOND=0", - "11:59:00 PM GMT" + "11:59:00 PM GMT" }, { "en_US@calendar=gregorian", "GMT", "TIME=LONG", "RELATIVE_ADD:DATE=-1,HOUR_OF_DAY=17,MINUTE=0,SECOND=0", // one day before now at specified time - "5:00:00 PM GMT" + "5:00:00 PM GMT" }, // normal formats, combined using 'at' { @@ -117,7 +117,7 @@ format:table(nofallback) { "GMT", "DATE=RELATIVE_FULL,TIME=LONG", "ERA=1,YEAR=2012,MONTH=OCTOBER,DATE=8,HOUR_OF_DAY=23,MINUTE=59,SECOND=0", - "Monday, October 8, 2012, 11:59:00 PM GMT" + "Monday, October 8, 2012, 11:59:00 PM GMT" }, // normal formats, combined using ", " { @@ -125,7 +125,7 @@ format:table(nofallback) { "GMT", "DATE=RELATIVE_MEDIUM,TIME=SHORT", "ERA=1,YEAR=2012,MONTH=OCTOBER,DATE=8,HOUR_OF_DAY=23,MINUTE=59,SECOND=0", - "Oct 8, 2012, 11:59 PM" + "Oct 8, 2012, 11:59 PM" }, // formats with relative day, combined using 'at' { @@ -133,7 +133,7 @@ format:table(nofallback) { "GMT", "DATE=RELATIVE_FULL,TIME=LONG", "RELATIVE_ADD:DATE=-1,HOUR_OF_DAY=17,MINUTE=0,SECOND=0", // one day before now at specified time - "yesterday, 5:00:00 PM GMT" + "yesterday, 5:00:00 PM GMT" }, // formats with relative day, combined using ", " { @@ -141,7 +141,7 @@ format:table(nofallback) { "GMT", "DATE=RELATIVE_MEDIUM,TIME=SHORT", "RELATIVE_ADD:DATE=-1,HOUR_OF_DAY=17,MINUTE=0,SECOND=0", // one day before now at specified time - "yesterday, 5:00 PM" + "yesterday, 5:00 PM" }, // normal formats that have quoted literals, combined { @@ -554,7 +554,7 @@ format:table(nofallback) { "", "DATE=FULL,TIME=FULL", "MILLIS=3076424179200000", - "Friday, 3 Heshvan 103217 at 12:00:00 AM GMT-08:00" + "Friday, 3 Heshvan 103217 at 12:00:00 AM GMT-08:00" }, } } From bf7c51e1e81c2a706657a59fde374f0d998a29e0 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 16:13:47 +0530 Subject: [PATCH 20/26] Keep codepoint trie goldens LF-only The UCPTrie golden comparison is byte-for-byte, so Windows CRLF checkout makes the generated set1 TOMLs fail even though the normalized content is identical. Force LF for the codepoint trie TOML goldens. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit e315769d1f8e1e61117bf39c0b5af910b0d73d24) --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitattributes b/.gitattributes index e7e0adbc655..cd41f2836af 100644 --- a/.gitattributes +++ b/.gitattributes @@ -87,3 +87,6 @@ configure text # Use JSONC for syntax highlighting on GitHub.com *.json linguist-language=jsonc +# Codepoint trie golden tests compare bytes; keep generated TOML line endings stable. +icu/icu4c/source/test/testdata/codepointtrie/*.toml text eol=lf + From c231ae79e49f5b5cee64a4ecb11abf60be50cab2 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 16:38:07 +0530 Subject: [PATCH 21/26] Align region validation with blocked subdivisions Remove blocked subdivision prefixes from supplemental data and update the generated region validation bitmap so Region::getInstance(), subdivision validity, and loclikely agree on the MS blocked-region set. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 85ff1391b2f0030e1279744988867c1c54959ee9) --- icu/icu4c/source/common/loclikely.cpp | 4 ++-- icu/icu4c/source/data/misc/supplementalData.txt | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/icu/icu4c/source/common/loclikely.cpp b/icu/icu4c/source/common/loclikely.cpp index 1c9447fa2bf..96a0c6baf4e 100644 --- a/icu/icu4c/source/common/loclikely.cpp +++ b/icu/icu4c/source/common/loclikely.cpp @@ -462,8 +462,8 @@ namespace { // test/intltest/regiontst.cpp from the resource data while // the test failed. const uint32_t gValidRegionMap[] = { - 0xeedf597c, 0xdeddbdef, 0x15943f3f, 0x0e00d580, - 0xb0095c00, 0x0015fb9f, 0x781c068d, 0x0340400f, + 0xeedf597c, 0xdeddbdef, 0x15843f3f, 0x0e005480, + 0xb0095c00, 0x0015fb9f, 0x7818068d, 0x0340400f, 0xf42b1d00, 0xfd4f8141, 0x25d7fffc, 0x0100084b, 0x538f3c40, 0x40000001, 0xfdf15100, 0x9fbb7ae7, 0x0410419a, 0x00408557, 0x00004002, 0x00100001, diff --git a/icu/icu4c/source/data/misc/supplementalData.txt b/icu/icu4c/source/data/misc/supplementalData.txt index 5c462722703..ecac0693388 100644 --- a/icu/icu4c/source/data/misc/supplementalData.txt +++ b/icu/icu4c/source/data/misc/supplementalData.txt @@ -11530,17 +11530,14 @@ supplementalData:table(nofallback){ "cyzzzz", "czzzzz", "dezzzz", - "dgzzzz", "djzzzz", "dkzzzz", "dmzzzz", "dozzzz", "dzzzzz", - "eazzzz", "eczzzz", "eezzzz", "egzzzz", - "ehzzzz", "erzzzz", "eszzzz", "etzzzz", @@ -11575,7 +11572,6 @@ supplementalData:table(nofallback){ "hrzzzz", "htzzzz", "huzzzz", - "iczzzz", "idzzzz", "iezzzz", "ilzzzz", From b0e4c1b1cdf9ec61ef15fbba981002f71c8b6921 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Mon, 18 May 2026 16:58:57 +0530 Subject: [PATCH 22/26] Keep icu-config fragments LF-only Force LF checkout for the shell fragments that are concatenated into config/icu-config so WSL/Linux selfcheck can execute the generated script. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 17cd32955dfb7806370e635ae0308c57c91b2545) --- .gitattributes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitattributes b/.gitattributes index cd41f2836af..976273bf156 100644 --- a/.gitattributes +++ b/.gitattributes @@ -90,3 +90,9 @@ configure text # Codepoint trie golden tests compare bytes; keep generated TOML line endings stable. icu/icu4c/source/test/testdata/codepointtrie/*.toml text eol=lf +# Shell script fragments assembled into icu-config (an executable shell script). +# They must have LF line endings so WSL/Linux can execute the generated file. +icu/icu4c/source/config/icu-config-top text eol=lf +icu/icu4c/source/config/icu-config-bottom text eol=lf +icu/icu4c/source/config/mh-* text eol=lf + From c85ae322fbbf3dad4472f2a03ea8f8440a5c4742 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Tue, 19 May 2026 07:06:42 +0530 Subject: [PATCH 23/26] Refresh ICU 78 patch records Refresh the stale/corrupt MSFT patch records for the ICU 78 upgrade: re-derived test expectations, final string-store size, uprefs refresh, and LF-only checkout rules. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 16bc4c8043f9d658e4491477942e18f0945ba84b) --- ...ch-ICU_test_changes_for_MSFT_changes.patch | 1146 +++++++++++++++-- ...st_changes_for_extra_CLDR-MS_locales.patch | 99 +- ...rease_string_store_for_extra_locales.patch | 13 +- ...ain_default_locale_as_full_BCP47_tag.patch | 115 +- ...ted_test_and_shell_artifacts_LF_only.patch | 26 + 5 files changed, 1107 insertions(+), 292 deletions(-) create mode 100644 icu-patches/patches/022-MSFT-Patch-ICU_keep_generated_test_and_shell_artifacts_LF_only.patch diff --git a/icu-patches/patches/002-MSFT-Patch-ICU_test_changes_for_MSFT_changes.patch b/icu-patches/patches/002-MSFT-Patch-ICU_test_changes_for_MSFT_changes.patch index d4f27a2719c..d659e762daf 100644 --- a/icu-patches/patches/002-MSFT-Patch-ICU_test_changes_for_MSFT_changes.patch +++ b/icu-patches/patches/002-MSFT-Patch-ICU_test_changes_for_MSFT_changes.patch @@ -1,90 +1,363 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Ju <41210545+daniel-ju@users.noreply.github.com> -Date: Thu, 10 Dec 2020 22:02:04 -0800 -Subject: MSFT-PATCH: Modify ICU tests to pass with Microsoft modified CLDR - data. +From: Arvind Oruganti +Date: Tue, 19 May 2026 06:45:00 +0530 +Subject: MSFT-PATCH: Refresh ICU tests for Microsoft modified CLDR data on ICU 78 -This changes modifies the ICU tests to pass with the modified CLDR-MS -data. The modifications are generally for the following reasons: - - Some of data is different due to internal requirements. - - Some are due to the extra locales that we pick up from CLDR Seed. - These Seed locales have data quality issues, which causes the - ICU tests to fail as they don't meet the ICU expectations. - - Removal of the yue-* locales. +Refreshes the ICU test expectation changes required by Microsoft-modified CLDR data after the ICU 78 upgrade. -diff --git a/icu/icu4c/source/test/cintltst/cldrtest.c b/icu/icu4c/source/test/cintltst/cldrtest.c -index e50ccb3cd1f9431afbd15c7d8a21a34632131c89..179539d5178b5cfd8b5350043c539e89e8740185 100644 ---- a/icu/icu4c/source/test/cintltst/cldrtest.c -+++ b/icu/icu4c/source/test/cintltst/cldrtest.c -@@ -957,6 +957,25 @@ static void VerifyTranslation(void) { - //else if (uprv_strncmp(currLoc,"bem",3) == 0 || uprv_strncmp(currLoc,"mgo",3) == 0 || uprv_strncmp(currLoc,"nl",2) == 0) { - // log_verbose("skipping test for %s, some month and country names known to use aux exemplars\n", currLoc); - //} -+ -+ /* MSFT Change: Begin */ -+ else if ( -+ uprv_strncmp(currLoc, "ba", 2) == 0 || uprv_strncmp(currLoc, "ba_RU", 5) == 0 || -+ uprv_strncmp(currLoc, "byn", 3) == 0 || uprv_strncmp(currLoc, "byn_ER", 6) == 0 || -+ uprv_strncmp(currLoc, "cu", 2) == 0 || uprv_strncmp(currLoc, "cu_RU", 5) == 0 || -+ uprv_strncmp(currLoc, "dv", 2) == 0 || uprv_strncmp(currLoc, "dv_MV", 5) == 0 || -+ uprv_strncmp(currLoc, "iu", 2) == 0 || uprv_strncmp(currLoc, "iu_CA", 5) == 0 || -+ uprv_strncmp(currLoc, "mn_Mong", 7) == 0 || uprv_strncmp(currLoc, "mn_Mong_CN", 10) == 0 || -+ uprv_strncmp(currLoc, "nqo", 3) == 0 || uprv_strncmp(currLoc, "nqo_GN", 6) == 0 || -+ uprv_strncmp(currLoc, "oc", 2) == 0 || uprv_strncmp(currLoc, "oc_FR", 5) == 0 || -+ uprv_strncmp(currLoc, "syr", 3) == 0 || uprv_strncmp(currLoc, "syr_SY", 6) == 0 || -+ uprv_strncmp(currLoc, "tig", 3) == 0 || uprv_strncmp(currLoc, "tig_ER", 6) == 0 || -+ uprv_strncmp(currLoc, "wal", 3) == 0 || uprv_strncmp(currLoc, "wal_ET", 6) == 0 -+ ) { -+ log_knownIssue("0", "MSFT Change: skipping test for %s which has issues due to CLDR Seed data.", currLoc); -+ } -+ /* MSFT Change: End */ -+ - else { - UChar langBuffer[128]; - int32_t langSize; -@@ -1231,7 +1250,14 @@ static void TestExemplarSet(void){ - } - - if (existsInScript == FALSE){ -- log_err("ExemplarSet containment failed for locale : %s\n", locale); -+ /* MSFT Change */ -+ if (uprv_strncmp(locale, "oc", 2) == 0 || uprv_strncmp(locale, "oc_FR", 5) == 0) { -+ log_knownIssue("0", "MSFT Change: oc and oc_FR have ExemplarSet issues."); -+ continue; -+ } else { -+ log_err("ExemplarSet containment failed for locale : %s\n", locale); -+ } -+ /* MSFT Change: End */ - } - } - assertTrue("case-folded is a superset", +This replaces the stale/truncated ICU 72-era patch with the ICU 78 source-side fixes re-derived from the Stage 7/8 failures, including English AM/PM regular-space expectations and Microsoft locale display-name expectations. + +diff --git a/icu/icu4c/source/test/cintltst/ccaltst.c b/icu/icu4c/source/test/cintltst/ccaltst.c +index 235eff26d1eafcdcb5406f51e625b7e157741f0e..50e0dca83e9cdf7992a7c1c89264706c76aed1d6 100644 +--- a/icu/icu4c/source/test/cintltst/ccaltst.c ++++ b/icu/icu4c/source/test/cintltst/ccaltst.c +@@ -724,7 +724,7 @@ static void TestGetSetDateAPI(void) + + /*Testing if setDate works fine */ + log_verbose("\nTesting the ucal_setDate() function \n"); +- u_strcpy(temp, u"Dec 17, 1971, 11:05:28\u202FPM"); ++ u_strcpy(temp, u"Dec 17, 1971, 11:05:28 PM"); + ucal_setDate(caldef,1971, UCAL_DECEMBER, 17, &status); + if(U_FAILURE(status)){ + log_err("error in setting the calendar date : %s\n", u_errorName(status)); +@@ -755,7 +755,7 @@ static void TestGetSetDateAPI(void) + + /*Testing if setDateTime works fine */ + log_verbose("\nTesting the ucal_setDateTime() function \n"); +- u_strcpy(temp, u"May 3, 1972, 4:30:42\u202FPM"); ++ u_strcpy(temp, u"May 3, 1972, 4:30:42 PM"); + ucal_setDateTime(caldef,1972, UCAL_MAY, 3, 16, 30, 42, &status); + if(U_FAILURE(status)){ + log_err("error in setting the calendar date : %s\n", u_errorName(status)); +diff --git a/icu/icu4c/source/test/cintltst/cdateintervalformattest.c b/icu/icu4c/source/test/cintltst/cdateintervalformattest.c +index 298dcae4247fb057e010cbd950cfa8708de9bbee..a4ecc7dc2eb6101b07c54a89cef42301ef86eec4 100644 +--- a/icu/icu4c/source/test/cintltst/cdateintervalformattest.c ++++ b/icu/icu4c/source/test/cintltst/cdateintervalformattest.c +@@ -248,15 +248,15 @@ static const ExpectPosAndFormat exp_en_yyMMddHHmmss[kNumDeltas] = { + }; + + static const ExpectPosAndFormat exp_en_yMMMdhmmssz[kNumDeltas] = { +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u20099:00:20\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u20099:20:00\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u200911:00:00\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u20099:00:00\\u202FPM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u2009Nov 28, 2014, 9:00:00\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u2009Dec 6, 2014, 9:00:00\\u202FAM GMT" }, +- { 16, 18, "Nov 20, 2014, 9:00:00\\u202FAM GMT\\u2009\\u2013\\u2009Feb 28, 2015, 9:00:00\\u202FAM GMT" } ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u20099:00:20 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u20099:20:00 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u200911:00:00 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u20099:00:00 PM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u2009Nov 28, 2014, 9:00:00 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u2009Dec 6, 2014, 9:00:00 AM GMT" }, ++ { 16, 18, "Nov 20, 2014, 9:00:00 AM GMT\\u2009\\u2013\\u2009Feb 28, 2015, 9:00:00 AM GMT" } + }; + + static const ExpectPosAndFormat exp_ja_yyMMddHHmm[kNumDeltas] = { +diff --git a/icu/icu4c/source/test/cintltst/cdattst.c b/icu/icu4c/source/test/cintltst/cdattst.c +index e17ac06f06442c2d626c72321211f62e8eb03ed4..6f27ba32a72ea232e8aae63637598531e04fd1ae 100644 +--- a/icu/icu4c/source/test/cintltst/cdattst.c ++++ b/icu/icu4c/source/test/cintltst/cdattst.c +@@ -176,7 +176,7 @@ static void TestDateFormat(void) + + /*Testing udat_format()*/ + log_verbose("\nTesting the udat_format() function of date format\n"); +- u_strcpy(temp, u"7/10/96, 4:05\u202FPM"); ++ u_strcpy(temp, u"7/10/96, 4:05 PM"); + /*format using def */ + resultlength=0; + resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status); +@@ -245,7 +245,7 @@ static void TestDateFormat(void) + + /*Testing parsing using udat_parse()*/ + log_verbose("\nTesting parsing using udat_parse()\n"); +- u_strcpy(temp, u"2/3/76, 2:50\u202FAM"); ++ u_strcpy(temp, u"2/3/76, 2:50 AM"); + parsepos=0; + status=U_ZERO_ERROR; + +@@ -966,7 +966,7 @@ static void TestDateFormatCalendar(void) { + u_errorName(ec)); + goto FAIL; + } +- u_strcpy(uExpected, u"5:45\u202FPM"); ++ u_strcpy(uExpected, u"5:45 PM"); + u_austrcpy(cbuf, uExpected); + if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) { + log_err("FAIL: udat_formatCalendar(17:45), expected: %s", cbuf); +@@ -2101,10 +2101,10 @@ static void TestHourCycle(void) { + static const UDate date = -845601267742; // March 16, 1943 at 3:45 PM + const UChar* testCases[] = { + // test some locales for which we have data +- u"en_US", u"Tuesday, March 16, 1943 at 3:45:32 PM", +- u"en_CA", u"Tuesday, March 16, 1943 at 3:45:32 p.m.", ++ u"en_US", u"Tuesday, March 16, 1943 at 3:45:32 PM", ++ u"en_CA", u"Tuesday, March 16, 1943 at 3:45:32 p.m.", + u"en_GB", u"Tuesday, 16 March 1943 at 15:45:32", +- u"en_AU", u"Tuesday, 16 March 1943 at 3:45:32 pm", ++ u"en_AU", u"Tuesday, 16 March 1943 at 3:45:32 pm", + // test a couple locales for which we don't have specific locale files (we should still get the correct hour cycle) + u"en_CO", u"Tuesday, March 16, 1943 at 3:45:32 PM", + u"en_MX", u"Tuesday, March 16, 1943 at 3:45:32 PM", +@@ -2112,12 +2112,12 @@ static void TestHourCycle(void) { + u"en_US@rg=GBzzzz", u"Tuesday, March 16, 1943 at 15:45:32", + u"en_US@rg=CAzzzz", u"Tuesday, March 16, 1943 at 3:45:32 PM", + u"en_CA@rg=USzzzz", u"Tuesday, March 16, 1943 at 3:45:32 p.m.", +- u"en_GB@rg=USzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", +- u"en_GB@rg=CAzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", +- u"en_GB@rg=AUzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", ++ u"en_GB@rg=USzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", ++ u"en_GB@rg=CAzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", ++ u"en_GB@rg=AUzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm", + // test that the hc ("hours") subtag does the right thing + u"en_US@hours=h23", u"Tuesday, March 16, 1943 at 15:45:32", +- u"en_GB@hours=h12", u"Tuesday, 16 March 1943 at 3:45:32 pm", ++ u"en_GB@hours=h12", u"Tuesday, 16 March 1943 at 3:45:32 pm", + // test that the rg and hc subtags do the right thing when used together + u"en_US@rg=GBzzzz;hours=h12", u"Tuesday, March 16, 1943 at 3:45:32 PM", + u"en_GB@rg=USzzzz;hours=h23", u"Tuesday, 16 March 1943 at 15:45:32", +diff --git a/icu/icu4c/source/test/cintltst/cdtrgtst.c b/icu/icu4c/source/test/cintltst/cdtrgtst.c +index 54bdc7228fd14c4eec483e26cf5ee0740cad3adb..13aa8cfb67cf451b21e5e792eece45c623f3ae61 100644 +--- a/icu/icu4c/source/test/cintltst/cdtrgtst.c ++++ b/icu/icu4c/source/test/cintltst/cdtrgtst.c +@@ -516,7 +516,7 @@ void Test714(void) + UErrorCode status = U_ZERO_ERROR; + UDateFormat *fmt; + UChar *result; +- const UChar* expect = u"7:25:43\u202FAM"; ++ const UChar* expect = u"7:25:43 AM"; + + ctest_setTimeZone(NULL, &status); + diff --git a/icu/icu4c/source/test/cintltst/cloctst.c b/icu/icu4c/source/test/cintltst/cloctst.c -index 61cfd4cb7cfeb78861932b9acd09b5743b42e483..aeb2c2a64d0f11c2d87bce4fb05fab4fc6480507 100644 +index 94f452aa561132186a99d02cb5879d36fdba0e9c..37cf24ded00c33ad69bafd45a2cbce86116da493 100644 --- a/icu/icu4c/source/test/cintltst/cloctst.c +++ b/icu/icu4c/source/test/cintltst/cloctst.c -@@ -1177,8 +1177,10 @@ typedef struct { +@@ -1268,8 +1268,8 @@ typedef struct { static const DisplayNameBracketsItem displayNameBracketsItems[] = { { "en", "CC", "en_CC", "Cocos (Keeling) Islands", "English (Cocos [Keeling] Islands)" }, - { "en", "MM", "my_MM", "Myanmar (Burma)", "Burmese (Myanmar [Burma])" }, - { "en", "MM", "my_Mymr_MM", "Myanmar (Burma)", "Burmese (Myanmar, Myanmar [Burma])" }, -+ /* MSFT Change: Begin */ -+ { "en", "MM", "my_MM", "Myanmar", "Burmese (Myanmar)" }, -+ { "en", "MM", "my_Mymr_MM", "Myanmar", "Burmese (Myanmar, Myanmar)" }, -+ /* MSFT Change: End */ ++ { "en", "MM", "my_MM", "Myanmar", "Burmese (Myanmar)" }, ++ { "en", "MM", "my_Mymr_MM", "Myanmar", "Burmese (Myanmar, Myanmar)" }, { "zh", "CC", "en_CC", "\\u79D1\\u79D1\\u65AF\\uFF08\\u57FA\\u6797\\uFF09\\u7FA4\\u5C9B", "\\u82F1\\u8BED\\uFF08\\u79D1\\u79D1\\u65AF\\uFF3B\\u57FA\\u6797\\uFF3D\\u7FA4\\u5C9B\\uFF09" }, { "zh", "CG", "fr_CG", "\\u521A\\u679C\\uFF08\\u5E03\\uFF09", "\\u6CD5\\u8BED\\uFF08\\u521A\\u679C\\uFF3B\\u5E03\\uFF3D\\uFF09" }, { NULL, NULL, NULL, NULL, NULL } +@@ -7163,11 +7163,11 @@ static const UldnItem en_StdMidLong[] = { + { "en", TEST_ULOC_LANGUAGE, u"English" }, + // https://unicode-org.atlassian.net/browse/ICU-20870 + { "fa_AF", TEST_ULDN_LOCALE, u"Persian (Afghanistan)" }, +- { "prs", TEST_ULDN_LOCALE, u"Dari" }, +- { "prs_AF", TEST_ULDN_LOCALE, u"Dari (Afghanistan)" }, +- { "prs_TJ", TEST_ULDN_LOCALE, u"Dari (Tajikistan)" }, +- { "prs", TEST_ULDN_LANGUAGE, u"Dari" }, +- { "prs", TEST_ULOC_LANGUAGE, u"Dari" }, ++ { "prs", TEST_ULDN_LOCALE, u"prs" }, ++ { "prs_AF", TEST_ULDN_LOCALE, u"prs (Afghanistan)" }, ++ { "prs_TJ", TEST_ULDN_LOCALE, u"prs (Tajikistan)" }, ++ { "prs", TEST_ULDN_LANGUAGE, u"prs" }, ++ { "prs", TEST_ULOC_LANGUAGE, u"prs" }, + // https://unicode-org.atlassian.net/browse/ICU-21742 + { "ji", TEST_ULDN_LOCALE, u"Yiddish" }, + { "ji_US", TEST_ULDN_LOCALE, u"Yiddish (United States)" }, +@@ -7183,23 +7183,23 @@ static const UldnItem en_StdMidLong[] = { + }; + + static const UldnItem en_StdMidShrt[] = { +- { "en_US", TEST_ULDN_LOCALE, u"English (US)" }, ++ { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, + { "en", TEST_ULDN_LANGUAGE, u"English" }, + }; + + static const UldnItem en_DiaMidLong[] = { +- { "en_US", TEST_ULDN_LOCALE, u"American English" }, +- { "fa_AF", TEST_ULDN_LOCALE, u"Dari" }, +- { "prs", TEST_ULDN_LOCALE, u"Dari" }, +- { "prs_AF", TEST_ULDN_LOCALE, u"Dari (Afghanistan)" }, +- { "prs_TJ", TEST_ULDN_LOCALE, u"Dari (Tajikistan)" }, +- { "prs", TEST_ULDN_LANGUAGE, u"Dari" }, ++ { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, ++ { "fa_AF", TEST_ULDN_LOCALE, u"Persian (Afghanistan)" }, ++ { "prs", TEST_ULDN_LOCALE, u"prs" }, ++ { "prs_AF", TEST_ULDN_LOCALE, u"prs (Afghanistan)" }, ++ { "prs_TJ", TEST_ULDN_LOCALE, u"prs (Tajikistan)" }, ++ { "prs", TEST_ULDN_LANGUAGE, u"prs" }, + { "mo", TEST_ULDN_LOCALE, u"Romanian" }, + { "mo", TEST_ULDN_LANGUAGE, u"Romanian" }, + }; + + static const UldnItem en_DiaMidShrt[] = { +- { "en_US", TEST_ULDN_LOCALE, u"US English" }, ++ { "en_US", TEST_ULDN_LOCALE, u"English (United States)" }, + }; + + static const UldnItem ro_StdMidLong[] = { // https://unicode-org.atlassian.net/browse/ICU-11563 +@@ -7220,26 +7220,26 @@ static const UldnItem yi_StdMidLong[] = { // https://unicode-org.atlassian.net/b + + static const UldnItem zh_DiaMidLong[] = { + // zh and zh_Hant both have dialect names for the following in ICU 73 +- { "ar_001", TEST_ULDN_LOCALE, u"现代标准阿拉伯语" }, +- { "nl_BE", TEST_ULDN_LOCALE, u"弗拉芒语" }, +- { "ro_MD", TEST_ULDN_LOCALE, u"摩尔多瓦语" }, ++ { "ar_001", TEST_ULDN_LOCALE, u"阿拉伯语(世界)" }, ++ { "nl_BE", TEST_ULDN_LOCALE, u"荷兰语(比利时)" }, ++ { "ro_MD", TEST_ULDN_LOCALE, u"罗马尼亚语(摩尔多瓦)" }, + // zh has dialect names for the following in ICU 73 +- { "en_AU", TEST_ULDN_LOCALE, u"澳大利亚英语" }, +- { "en_CA", TEST_ULDN_LOCALE, u"加拿大英语" }, +- { "en_GB", TEST_ULDN_LOCALE, u"英国英语" }, +- { "en_US", TEST_ULDN_LOCALE, u"美国英语" }, +- { "es_419", TEST_ULDN_LOCALE, u"拉丁美洲西班牙语" }, +- { "es_ES", TEST_ULDN_LOCALE, u"欧洲西班牙语" }, +- { "es_MX", TEST_ULDN_LOCALE, u"墨西哥西班牙语" }, +- { "fr_CA", TEST_ULDN_LOCALE, u"加拿大法语" }, +- { "fr_CH", TEST_ULDN_LOCALE, u"瑞士法语" }, ++ { "en_AU", TEST_ULDN_LOCALE, u"英语(澳大利亚)" }, ++ { "en_CA", TEST_ULDN_LOCALE, u"英语(加拿大)" }, ++ { "en_GB", TEST_ULDN_LOCALE, u"英语(英国)" }, ++ { "en_US", TEST_ULDN_LOCALE, u"英语(美国)" }, ++ { "es_419", TEST_ULDN_LOCALE, u"西班牙语(拉丁美洲)" }, ++ { "es_ES", TEST_ULDN_LOCALE, u"西班牙语(西班牙)" }, ++ { "es_MX", TEST_ULDN_LOCALE, u"西班牙语(墨西哥)" }, ++ { "fr_CA", TEST_ULDN_LOCALE, u"法语(加拿大)" }, ++ { "fr_CH", TEST_ULDN_LOCALE, u"法语(瑞士)" }, + }; + + static const UldnItem zh_Hant_DiaMidLong[] = { + // zh and zh_Hant both have dialect names for the following in ICU 73 +- { "ar_001", TEST_ULDN_LOCALE, u"現代標準阿拉伯文" }, +- { "nl_BE", TEST_ULDN_LOCALE, u"法蘭德斯文" }, +- { "ro_MD", TEST_ULDN_LOCALE, u"摩爾多瓦文" }, ++ { "ar_001", TEST_ULDN_LOCALE, u"阿拉伯文(世界)" }, ++ { "nl_BE", TEST_ULDN_LOCALE, u"荷蘭文(比利時)" }, ++ { "ro_MD", TEST_ULDN_LOCALE, u"羅馬尼亞文(摩爾多瓦)" }, + // zh_Hant no dialect names for the following in ICU-73, + // use standard name + { "en_AU", TEST_ULDN_LOCALE, u"英文(澳洲)" }, +diff --git a/icu/icu4c/source/test/cintltst/cmsgtst.c b/icu/icu4c/source/test/cintltst/cmsgtst.c +index 16263b5c7f4de4eb9c2839b21a7abbc20a16188c..ed20cf23ce057364963ec1996a672a7859661d32 100644 +--- a/icu/icu4c/source/test/cintltst/cmsgtst.c ++++ b/icu/icu4c/source/test/cintltst/cmsgtst.c +@@ -44,7 +44,7 @@ static const char* const txt_testResultStrings[] = { + "Quotes ', {, a 1 {0}", + "Quotes ', {, a 1 {0}", + "You deposited 1 times an amount of $3,456.00 on 1/12/70", +- "{2,time,full}, for 3,456, 1 is 5:46:40\\u202FAM Pacific Standard Time and full date is Monday, January 12, 1970", ++ "{2,time,full}, for 3,456, 1 is 5:46:40 AM Pacific Standard Time and full date is Monday, January 12, 1970", + "{1,number,percent} for 1 is 345,600%" + }; + +diff --git a/icu/icu4c/source/test/cintltst/creststn.c b/icu/icu4c/source/test/cintltst/creststn.c +index 71fd936e377f97ae478a77489527c734b35d6421..63a758c5b78819b1ccdc65d0162e6f0240437927 100644 +--- a/icu/icu4c/source/test/cintltst/creststn.c ++++ b/icu/icu4c/source/test/cintltst/creststn.c +@@ -2715,16 +2715,6 @@ static void TestGetFunctionalEquivalent(void) { + "f", "nl_NL@collation=stroke", "root", + "f", "nl_NL_EEXT@collation=stroke", "root", + /* Additions to test aliased locales */ +- "f", "yue_HK", "zh@collation=stroke", +- "f", "yue_Hant", "zh@collation=stroke", +- "f", "yue_Hant_HK", "zh@collation=stroke", +- "f", "yue@collation=stroke", "zh@collation=stroke", +- "f", "yue@collation=pinyin", "zh", +- "f", "yue_CN", "zh", +- "f", "yue_Hans", "zh", +- "f", "yue_Hans_CN", "zh", +- "f", "yue_Hans@collation=pinyin", "zh", +- "f", "yue_Hans@collation=stroke", "zh@collation=stroke", + "f", "mo", "mo", + "t", "no", "no", + "t", "nb", "no", +@@ -2735,8 +2725,6 @@ static void TestGetFunctionalEquivalent(void) { + "f", "zh_Hant_CN", "zh@collation=stroke", + "f", "zh_Hant_US", "zh@collation=stroke", + "f", "zh_Hans_US", "zh", +- "f", "yue_TW", "zh@collation=stroke", +- "f", "yue_US", "zh@collation=stroke", + "f", "ja_CN", "ja", + "f", "ja_US", "ja", + NULL +diff --git a/icu/icu4c/source/test/cintltst/udatpg_test.c b/icu/icu4c/source/test/cintltst/udatpg_test.c +index b9278085b2057d23bfc6e6778df11c0ce59717be..d6e6d209a97ae2064c1f89d576953b938dc670b5 100644 +--- a/icu/icu4c/source/test/cintltst/udatpg_test.c ++++ b/icu/icu4c/source/test/cintltst/udatpg_test.c +@@ -405,9 +405,9 @@ enum { kTestOptionsPatLenMax = 32 }; + static const UChar skel_Hmm[] = u"Hmm"; + static const UChar skel_HHmm[] = u"HHmm"; + static const UChar skel_hhmm[] = u"hhmm"; +-static const UChar patn_hcmm_a[] = u"h:mm\u202Fa"; ++static const UChar patn_hcmm_a[] = u"h:mm a"; + static const UChar patn_HHcmm[] = u"HH:mm"; +-static const UChar patn_hhcmm_a[] = u"hh:mm\u202Fa"; ++static const UChar patn_hhcmm_a[] = u"hh:mm a"; + static const UChar patn_HHpmm[] = u"HH.mm"; + static const UChar patn_hpmm_a[] = u"h.mm\u202Fa"; + static const UChar patn_Hpmm[] = u"H.mm"; +@@ -656,10 +656,10 @@ static void TestDateTimePatterns(void) { + // The following tests some locales in which there are differences between the + // DateTimePatterns of various length styles. + DTPLocaleAndResults localeAndResults[] = { +- { "en", { u"EEEE, MMMM d, y 'at' h:mm\u202Fa", // long != medium +- u"MMMM d, y 'at' h:mm\u202Fa", +- u"MMM d, y, h:mm\u202Fa", +- u"M/d/y, h:mm\u202Fa" } }, ++ { "en", { u"EEEE, MMMM d, y 'at' h:mm a", // long != medium ++ u"MMMM d, y 'at' h:mm a", ++ u"MMM d, y, h:mm a", ++ u"M/d/y, h:mm a" } }, + { "fr", { u"EEEE d MMMM y 'à' HH:mm", // medium != short + u"d MMMM y 'à' HH:mm", + u"d MMM y, HH:mm", +@@ -683,10 +683,10 @@ static void TestDateTimePatterns(void) { + u"{1} _2_ {0}", + u"{1} _3_ {0}" + }; +- DTPLocaleAndResults enModResults = { "en", { u"EEEE, MMMM d, y _0_ h:mm\u202Fa", +- u"MMMM d, y _1_ h:mm\u202Fa", +- u"MMM d, y _2_ h:mm\u202Fa", +- u"M/d/y _3_ h:mm\u202Fa" } ++ DTPLocaleAndResults enModResults = { "en", { u"EEEE, MMMM d, y _0_ h:mm a", ++ u"MMMM d, y _1_ h:mm a", ++ u"MMM d, y _2_ h:mm a", ++ u"M/d/y _3_ h:mm a" } + }; + + // Test various locales with standard data +@@ -817,7 +817,7 @@ static void TestRegionOverride(void) { + } RegionOverrideTest; + + const RegionOverrideTest testCases[] = { +- { "en_US", u"h:mm\u202fa", UDAT_HOUR_CYCLE_12 }, ++ { "en_US", u"h:mm a", UDAT_HOUR_CYCLE_12 }, + { "en_GB", u"HH:mm", UDAT_HOUR_CYCLE_23 }, + { "en_US@rg=GBZZZZ", u"HH:mm", UDAT_HOUR_CYCLE_23 }, + { "en_US@hours=h23", u"HH:mm", UDAT_HOUR_CYCLE_23 }, +@@ -859,9 +859,9 @@ static void TestISO8601(void) { + { "en_US@calendar=iso8601", u"Edjmm", u"d, EEE, h:mm a" }, + { "en_US@calendar=iso8601", u"EdHmm", u"d, EEE, HH:mm" }, + +- { "en_US", u"EEEEyMMMMdjmm", u"EEEE, MMMM d, y 'at' h:mm a" }, ++ { "en_US", u"EEEEyMMMMdjmm", u"EEEE, MMMM d, y 'at' h:mm a" }, + { "en_US", u"EEEEyMMMMdHmm", u"EEEE, MMMM d, y 'at' HH:mm" }, +- { "en_US", u"Edjmm", u"d EEE, h:mm a" }, ++ { "en_US", u"Edjmm", u"d EEE, h:mm a" }, + { "en_US", u"EdHmm", u"d EEE, HH:mm" }, + }; + diff --git a/icu/icu4c/source/test/intltest/apicoll.cpp b/icu/icu4c/source/test/intltest/apicoll.cpp -index 88eefa92b98ee35051dc44011ee1e4d932123f19..249d98747d92e677c5f78b81ce06ad61042c307f 100644 +index 4ccdc373e6ce912c464ce07c268d6fb88d45f118..a31873fe43664a6eba579a5cb2ea4b89b4542dd0 100644 --- a/icu/icu4c/source/test/intltest/apicoll.cpp +++ b/icu/icu4c/source/test/intltest/apicoll.cpp -@@ -1664,18 +1664,20 @@ void CollationAPITest::TestGetLocale() { +@@ -1664,18 +1664,7 @@ void CollationAPITest::TestGetLocale() { { "zh_TW", "zh_Hant_TW", "zh@collation=stroke" }, { "zh_TW@collation=pinyin", "zh_Hant_TW@collation=pinyin", "zh" }, { "zh_CN@collation=stroke", "zh_Hans_CN@collation=stroke", "zh@collation=stroke" }, -+ /* MSFT Change: Begin */ - // yue/yue_Hant aliased to zh_Hant, yue_Hans aliased to zh_Hans. +- // yue/yue_Hant aliased to zh_Hant, yue_Hans aliased to zh_Hans. - { "yue", "zh_Hant", "zh@collation=stroke" }, - { "yue_HK", "zh_Hant", "zh@collation=stroke" }, - { "yue_Hant", "zh_Hant", "zh@collation=stroke" }, @@ -96,88 +369,677 @@ index 88eefa92b98ee35051dc44011ee1e4d932123f19..249d98747d92e677c5f78b81ce06ad61 - { "yue_Hans_CN", "zh_Hans", "zh" }, - { "yue_Hans@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" }, - { "yue_CN@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" } -+ // { "yue", "zh_Hant", "zh@collation=stroke" }, -+ // { "yue_HK", "zh_Hant", "zh@collation=stroke" }, -+ // { "yue_Hant", "zh_Hant", "zh@collation=stroke" }, -+ // { "yue_Hant_HK", "zh_Hant", "zh@collation=stroke" }, -+ // { "yue@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, -+ // { "yue_HK@collation=pinyin", "zh_Hant@collation=pinyin", "zh" }, -+ // { "yue_CN", "zh_Hans", "zh" }, -+ // { "yue_Hans", "zh_Hans", "zh" }, -+ // { "yue_Hans_CN", "zh_Hans", "zh" }, -+ // { "yue_Hans@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" }, -+ // { "yue_CN@collation=stroke", "zh_Hans@collation=stroke", "zh@collation=stroke" } -+ /* MSFT Change: End */ ++ // CLDR-MS does not ship yue collation aliases. }; u_unescape(rules, rlz, 256); +diff --git a/icu/icu4c/source/test/intltest/dtfmrgts.cpp b/icu/icu4c/source/test/intltest/dtfmrgts.cpp +index 2fd10e01d874f370ee387e11c6e584c2072eecb7..fed3546b8d4bfb78c776b0c4176fe158f2a877e7 100644 +--- a/icu/icu4c/source/test/intltest/dtfmrgts.cpp ++++ b/icu/icu4c/source/test/intltest/dtfmrgts.cpp +@@ -144,8 +144,8 @@ void DateFormatRegressionTest::Test4052408() + str = fmt->format(dt, str); + logln(str); + +- if(str != u"5/3/97, 8:55\u202FAM") +- errln(UnicodeString(u"Fail: Test broken; Want 5/3/97, 8:55\u202FAM Got ", -1) + str); ++ if(str != u"5/3/97, 8:55 AM") ++ errln(UnicodeString(u"Fail: Test broken; Want 5/3/97, 8:55 AM Got ", -1) + str); + + UnicodeString expected[] = { + UnicodeString(""), //"ERA_FIELD", +@@ -1227,7 +1227,7 @@ void DateFormatRegressionTest::Test714() + } + + UnicodeString s; +- UnicodeString tests = UnicodeString(u"7:25:43\u202FAM"); ++ UnicodeString tests = UnicodeString(u"7:25:43 AM"); + UErrorCode status = U_ZERO_ERROR; + fmt->format (d,s); + if(U_FAILURE(status)) +diff --git a/icu/icu4c/source/test/intltest/dtfmttst.cpp b/icu/icu4c/source/test/intltest/dtfmttst.cpp +index 9ef923fc25b05ce625a5a5ea28db176a30a076a6..7af9ebb0215658b2b54d7b30a713fc4e90f919b5 100644 +--- a/icu/icu4c/source/test/intltest/dtfmttst.cpp ++++ b/icu/icu4c/source/test/intltest/dtfmttst.cpp +@@ -1003,7 +1003,7 @@ DateFormatTest::TestBadInput135() + dataerrln("could not create date time instance"); + return; + } +- UnicodeString expected(u"March 1, 2000 at 1:23:45\u202FAM", -1); ++ UnicodeString expected(u"March 1, 2000 at 1:23:45 AM", -1); + for (int32_t i = 0; i < strings_length;++i) { + const char* text = strings[i]; + for (int32_t j = 0; j < looks_length;++j) { +@@ -1342,7 +1342,7 @@ DateFormatTest::TestLocaleDateFormat() // Bug 495 + DateFormat::FULL, Locale::getUS()); + UnicodeString expectedFRENCH ( u"lundi 15 septembre 1997 à 00:00:00 heure d’été du Pacifique nord-américain", -1 ); + expectedFRENCH = expectedFRENCH.unescape(); +- UnicodeString expectedUS ( u"Monday, September 15, 1997 at 12:00:00\u202FAM Pacific Daylight Time", -1 ); ++ UnicodeString expectedUS ( u"Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time", -1 ); + logln(UnicodeString("Date set to : ") + dateToString(testDate)); + UnicodeString out; + if (dfUS == nullptr || dfFrench == nullptr){ +@@ -5028,7 +5028,7 @@ void DateFormatTest::TestPatternFromSkeleton() { + const char16_t* const pattern; + } TESTDATA[] = { + // Ticket #11985 +- {Locale::getEnglish(), "jjmm", u"h:mm\u202Fa"}, ++ {Locale::getEnglish(), "jjmm", u"h:mm a"}, + {Locale::getEnglish(), "JJmm", u"hh:mm"}, + {Locale::getGerman(), "jjmm", u"HH:mm"}, + {Locale::getGerman(), "JJmm", u"HH:mm"}, +@@ -5851,10 +5851,10 @@ void DateFormatTest::TestHourCycle() { + UnicodeString expectedResult; + } TEST_CASES[] = { + // test some locales for which we have data +- { "en-us", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, +- { "en-ca", u"Tuesday, March 16, 1943 at 3:45:32 p.m." }, ++ { "en-us", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, ++ { "en-ca", u"Tuesday, March 16, 1943 at 3:45:32 p.m." }, + { "en-gb", u"Tuesday, 16 March 1943 at 15:45:32" }, +- { "en-au", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, ++ { "en-au", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + // test a couple locales for which we don't have specific locale files (we should still get the correct hour cycle) + { "en-co", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, + { "en-mx", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, +@@ -5862,12 +5862,12 @@ void DateFormatTest::TestHourCycle() { + { "en-us-u-rg-gbzzzz", u"Tuesday, March 16, 1943 at 15:45:32" }, + { "en-us-u-rg-cazzzz", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, + { "en-ca-u-rg-uszzzz", u"Tuesday, March 16, 1943 at 3:45:32 p.m." }, +- { "en-gb-u-rg-uszzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, +- { "en-gb-u-rg-cazzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, +- { "en-gb-u-rg-auzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, ++ { "en-gb-u-rg-uszzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, ++ { "en-gb-u-rg-cazzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, ++ { "en-gb-u-rg-auzzzz", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + // test that the hc ("hours") subtag does the right thing + { "en-us-u-hc-h23", u"Tuesday, March 16, 1943 at 15:45:32" }, +- { "en-gb-u-hc-h12", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, ++ { "en-gb-u-hc-h12", u"Tuesday, 16 March 1943 at 3:45:32 pm" }, + // test that the rg and hc subtags do the right thing when used together + { "en-us-u-rg-gbzzzz-hc-h12", u"Tuesday, March 16, 1943 at 3:45:32 PM" }, + { "en-gb-u-rg-uszzzz-hc-h23", u"Tuesday, 16 March 1943 at 15:45:32" }, +diff --git a/icu/icu4c/source/test/intltest/dtifmtts.cpp b/icu/icu4c/source/test/intltest/dtifmtts.cpp +index f539104be66da6989ba776f7115090294281c1c5..62d05a90e3ee05815585bd4eec95cf880a2447e9 100644 +--- a/icu/icu4c/source/test/intltest/dtifmtts.cpp ++++ b/icu/icu4c/source/test/intltest/dtifmtts.cpp +@@ -496,7 +496,7 @@ void DateIntervalFormatTest::testFormat() { + + "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EddMMy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008", + +- "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM", ++ "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10 AM\\u2009\\u2013\\u200910/10/2008, 10:10 AM", + + "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmmzz", "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PDT", + +@@ -633,7 +633,7 @@ void DateIntervalFormatTest::testFormat() { + + "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EddMMy", "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007", + +- "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM", ++ "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10 AM\\u2009\\u2013\\u200911/20/2007, 10:10 AM", + + "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmmzz", "11/10/2007, 10:10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PST", + +@@ -821,7 +821,7 @@ void DateIntervalFormatTest::testFormat() { + "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEddMMyyyy", "Wed, 01/10/2007", + + +- "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmm", "10:10\\u202FAM", ++ "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmm", "10:10 AM", + "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "HHmm", "10:10", + + "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmmzz", "10:10\\u202FAM PST", +@@ -2382,7 +2382,7 @@ void DateIntervalFormatTest::testTicket21939() { + const DateFormat* df = dif->getDateFormat(); + const SimpleDateFormat* sdf = dynamic_cast(df); + UnicodeString pattern; +- assertEquals("Wrong pattern", u"M/d/r, h:mm\u202Fa", sdf->toPattern(pattern)); ++ assertEquals("Wrong pattern", u"M/d/r, h:mm a", sdf->toPattern(pattern)); + } + + // additional tests for the related ICU-22202 diff --git a/icu/icu4c/source/test/intltest/dtptngts.cpp b/icu/icu4c/source/test/intltest/dtptngts.cpp -index faa850aa8384c09720fed2b637d82d11a2608b2c..dc86355f93fa68f509a0023dc95fc17a548170c1 100644 +index e7360dda69ff52fa7960c005a2ed3b52addf478a..e76ea5cfc5bc09a3b6d44390c496250ea53efe1c 100644 --- a/icu/icu4c/source/test/intltest/dtptngts.cpp +++ b/icu/icu4c/source/test/intltest/dtptngts.cpp -@@ -1398,8 +1398,25 @@ void IntlTestDateTimePatternGeneratorAPI::testJjMapping() { - jPattern.extract(0, jPattern.length(), jpBuf, 32); - const char* dfmtCalType = (dfmt->getCalendar())->getType(); - const char* validLoc = dfmt->getLocaleID(ULOC_VALID_LOCALE, status); -- errln("ERROR: locale %s (valid %s), expected j resolved char %s to occur in short time pattern '%s' for %s (best pattern: '%s')", -+ /* MSFT Change: Begin */ -+ if ( -+ uprv_strncmp(localeID, "byn", 3) == 0 || uprv_strncmp(localeID, "byn_ER", 6) == 0 || -+ uprv_strncmp(localeID, "iu_Latn", 7) == 0 || uprv_strncmp(localeID, "iu_Latn_CA", 10) == 0 || -+ uprv_strncmp(localeID, "mn_Mong", 7) == 0 || uprv_strncmp(localeID, "mn_Mong_CN", 10) == 0 || -+ uprv_strncmp(localeID, "moh", 3) == 0 || uprv_strncmp(localeID, "moh_CA", 6) == 0 || -+ uprv_strncmp(localeID, "ss_SZ", 5) == 0 || uprv_strncmp(localeID, "ssy", 3) == 0 || -+ uprv_strncmp(localeID, "ssy_ER", 6) == 0 || uprv_strncmp(localeID, "st_LS", 5) == 0 || -+ uprv_strncmp(localeID, "syr", 3) == 0 || uprv_strncmp(localeID, "syr_SY", 6) == 0 || -+ uprv_strncmp(localeID, "tig", 3) == 0 || uprv_strncmp(localeID, "tig_ER", 6) == 0 || -+ uprv_strncmp(localeID, "wal", 3) == 0 || uprv_strncmp(localeID, "wal_ET", 6) == 0 -+ ) { -+ logKnownIssue("0", "MSFT Change: skipping test for %s which has issues due to CLDR Seed data.", localeID); -+ } -+ else { -+ errln("ERROR: locale %s (valid %s), expected j resolved char %s to occur in short time pattern '%s' for %s (best pattern: '%s')", - localeID, validLoc, jcBuf, spBuf, dfmtCalType, jpBuf); -+ } -+ /* MSFT Change: End */ - } - break; - } +@@ -107,14 +107,14 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) + UnicodeString("Jan 13"), // 05: MMMd + UnicodeString("January 13"), // 06: MMMMd + UnicodeString("Q1 1999"), // 07: yQQQ +- UnicodeString(u"11:58\u202FPM", -1), // 08: hhmm ++ UnicodeString(u"11:58 PM", -1), // 08: hhmm + UnicodeString("23:58"), // 09: HHmm +- UnicodeString(u"11:58\u202FPM", -1), // 10: jjmm ++ UnicodeString(u"11:58 PM", -1), // 10: jjmm + UnicodeString("58:59"), // 11: mmss + UnicodeString("January 1999"), // 12: yyyyMMMM + UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d + UnicodeString("13 Wed"), // 14: Ed -> d EEE +- UnicodeString(u"11:58:59.123\u202FPM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" ++ UnicodeString(u"11:58:59.123 PM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" + UnicodeString("11:58"), // 16: JJmm + }; + +@@ -128,14 +128,14 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) + UnicodeString("Jan 13"), // 5: MMMd + UnicodeString("January 13"), // 6: MMMMd + UnicodeString("Q1 11 Heisei"), // 7: yQQQ +- UnicodeString(u"11:58\u202FPM", -1), // 8: hhmm ++ UnicodeString(u"11:58 PM", -1), // 8: hhmm + UnicodeString("23:58"), // 9: HHmm +- UnicodeString(u"11:58\u202FPM", -1), // 10: jjmm ++ UnicodeString(u"11:58 PM", -1), // 10: jjmm + UnicodeString("58:59"), // 11: mmss + UnicodeString("January 11 Heisei"), // 12: yyyyMMMM + UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d" + UnicodeString("13 Wed"), // 14: Ed -> d EEE +- UnicodeString(u"11:58:59.123\u202FPM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" ++ UnicodeString(u"11:58:59.123 PM", -1), // 15: jmmssSSS -> "h:mm:ss.SSS a" + UnicodeString("11:58"), // 16: JJmm + }; + +@@ -377,14 +377,14 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) + UnicodeString("O 14, 1999"), + UnicodeString("T, O 14"), + UnicodeString("Oct 14"), +- UnicodeString(u"Oct 14, 6:58\u202FAM", -1), +- UnicodeString(u"Thu, Oct 14, 6:58:59\u202FAM", -1), +- UnicodeString(u"10/14, 6:58\u202FAM", -1), +- UnicodeString(u"Thursday, Oct 14, 6:58:59\u202FAM", -1), +- UnicodeString(u"Oct 14, 1999, 6:58:59\u202FAM", -1), +- UnicodeString(u"Thu, Oct 14, 1999, 6:58:59\u202FAM", -1), +- UnicodeString(u"6:58\u202FAM", -1), +- UnicodeString(u"6:58\u202FAM", -1), ++ UnicodeString(u"Oct 14, 6:58 AM", -1), ++ UnicodeString(u"Thu, Oct 14, 6:58:59 AM", -1), ++ UnicodeString(u"10/14, 6:58 AM", -1), ++ UnicodeString(u"Thursday, Oct 14, 6:58:59 AM", -1), ++ UnicodeString(u"Oct 14, 1999, 6:58:59 AM", -1), ++ UnicodeString(u"Thu, Oct 14, 1999, 6:58:59 AM", -1), ++ UnicodeString(u"6:58 AM", -1), ++ UnicodeString(u"6:58 AM", -1), + UnicodeString(u"6:58\u202FAM GMT+00:00", -1), + UnicodeString(""), + }; +@@ -908,10 +908,10 @@ void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/) + // locale skel expectedPattern options + { "en", "Hmm", u"HH:mm", UDATPG_MATCH_NO_OPTIONS }, + { "en", "HHmm", u"HH:mm", UDATPG_MATCH_NO_OPTIONS }, +- { "en", "hhmm", u"h:mm\u202Fa", UDATPG_MATCH_NO_OPTIONS }, ++ { "en", "hhmm", u"h:mm a", UDATPG_MATCH_NO_OPTIONS }, + { "en", "Hmm", u"HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, + { "en", "HHmm", u"HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, +- { "en", "hhmm", u"hh:mm\u202Fa", UDATPG_MATCH_HOUR_FIELD_LENGTH }, ++ { "en", "hhmm", u"hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH }, + { "da", "Hmm", u"HH.mm", UDATPG_MATCH_NO_OPTIONS }, + { "da", "HHmm", u"HH.mm", UDATPG_MATCH_NO_OPTIONS }, + { "da", "hhmm", u"h.mm\u202Fa", UDATPG_MATCH_NO_OPTIONS }, +@@ -1540,6 +1540,18 @@ void IntlTestDateTimePatternGeneratorAPI::test_jConsistencyOddLocales() { // ICU + continue; + } + if (dtfShortPattern != dtfSkelPattern || dtfSkelPattern != dtpgPattern) { ++ if (uprv_strcmp(localeID, "en") == 0) { ++ UnicodeString dtfShortPatternForCompare(dtfShortPattern); ++ UnicodeString dtfSkelPatternForCompare(dtfSkelPattern); ++ UnicodeString dtpgPatternForCompare(dtpgPattern); ++ dtfShortPatternForCompare.findAndReplace(u"\u202F", u" "); ++ dtfSkelPatternForCompare.findAndReplace(u"\u202F", u" "); ++ dtpgPatternForCompare.findAndReplace(u"\u202F", u" "); ++ if (dtfShortPatternForCompare == dtfSkelPatternForCompare && ++ dtfSkelPatternForCompare == dtpgPatternForCompare) { ++ continue; ++ } ++ } + const char* dtfShortValidLoc = dtfShort->getLocaleID(ULOC_VALID_LOCALE, status); + const char* dtfShortActualLoc = dtfShort->getLocaleID(ULOC_ACTUAL_LOCALE, status); + errln(UnicodeString("For locale ") + localeID + +@@ -1635,10 +1647,10 @@ void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() { + // The following tests some locales in which there are differences between the + // DateTimePatterns of various length styles. + DTPLocaleAndResults localeAndResults[] = { +- { "en", { UnicodeString(u"EEEE, MMMM d, y 'at' h:mm\u202Fa"), // long != medium +- UnicodeString(u"MMMM d, y 'at' h:mm\u202Fa"), +- UnicodeString(u"MMM d, y, h:mm\u202Fa"), +- UnicodeString(u"M/d/y, h:mm\u202Fa") } }, ++ { "en", { UnicodeString(u"EEEE, MMMM d, y 'at' h:mm a"), // long != medium ++ UnicodeString(u"MMMM d, y 'at' h:mm a"), ++ UnicodeString(u"MMM d, y, h:mm a"), ++ UnicodeString(u"M/d/y, h:mm a") } }, + { "fr", { UnicodeString(u"EEEE d MMMM y 'à' HH:mm"), // medium != short + UnicodeString(u"d MMMM y 'à' HH:mm"), + UnicodeString(u"d MMM y, HH:mm"), +@@ -1663,10 +1675,10 @@ void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() { + UnicodeString(u"{1} _2_ {0}"), + UnicodeString(u"{1} _3_ {0}") + }; +- DTPLocaleAndResults enModResults = { "en", { UnicodeString(u"EEEE, MMMM d, y _0_ h:mm\u202Fa"), +- UnicodeString(u"MMMM d, y _1_ h:mm\u202Fa"), +- UnicodeString(u"MMM d, y _2_ h:mm\u202Fa"), +- UnicodeString(u"M/d/y _3_ h:mm\u202Fa") } ++ DTPLocaleAndResults enModResults = { "en", { UnicodeString(u"EEEE, MMMM d, y _0_ h:mm a"), ++ UnicodeString(u"MMMM d, y _1_ h:mm a"), ++ UnicodeString(u"MMM d, y _2_ h:mm a"), ++ UnicodeString(u"M/d/y _3_ h:mm a") } + }; + + // Test various locales with standard data +@@ -1784,7 +1796,7 @@ void IntlTestDateTimePatternGeneratorAPI::testRegionOverride() { + const char16_t* expectedPattern; + UDateFormatHourCycle expectedHourCycle; + } testCases[] = { +- { "en_US", u"h:mm\u202fa", UDAT_HOUR_CYCLE_12 }, ++ { "en_US", u"h:mm a", UDAT_HOUR_CYCLE_12 }, + { "en_GB", u"HH:mm", UDAT_HOUR_CYCLE_23 }, + { "en_US@rg=GBZZZZ", u"HH:mm", UDAT_HOUR_CYCLE_23 }, + { "en_US@hours=h23", u"HH:mm", UDAT_HOUR_CYCLE_23 }, diff --git a/icu/icu4c/source/test/intltest/locnmtst.cpp b/icu/icu4c/source/test/intltest/locnmtst.cpp -index 61baca2e4634a08d83a4dbdd69990df7c9bf2471..68d55de958e0228a393cedc0fa06120c54753603 100644 +index 864b57ef5185b99b13011b5a1a333afb07997812..0703866445d27801548c51fdcde0e4e33c179480 100644 --- a/icu/icu4c/source/test/intltest/locnmtst.cpp +++ b/icu/icu4c/source/test/intltest/locnmtst.cpp -@@ -68,10 +68,14 @@ void LocaleDisplayNamesTest::runIndexedTest(int32_t index, UBool exec, const cha - switch (index) { - #if !UCONFIG_NO_FORMATTING - TESTCASE(0, TestCreate); -- TESTCASE(1, TestCreateDialect); -+ /* MSFT Change: Begin */ -+ // TESTCASE(1, TestCreateDialect); -+ /* MSFT Change: End */ - TESTCASE(2, TestWithKeywordsAndEverything); - TESTCASE(3, TestUldnOpen); -- TESTCASE(4, TestUldnOpenDialect); -+ /* MSFT Change: Begin */ -+ // TESTCASE(4, TestUldnOpenDialect); -+ /* MSFT Change: End */ - TESTCASE(5, TestUldnWithKeywordsAndEverything); - TESTCASE(6, TestUldnComponents); - TESTCASE(7, TestRootEtc); -diff --git a/icu/icu4c/source/test/intltest/numfmtst.cpp b/icu/icu4c/source/test/intltest/numfmtst.cpp -index dc193f2cc42b26d0c544e8c24701d4e4aefeff92..95157d1d69069aabe2f814aef0e709e2f180dcb8 100644 ---- a/icu/icu4c/source/test/intltest/numfmtst.cpp -+++ b/icu/icu4c/source/test/intltest/numfmtst.cpp -@@ -199,7 +199,9 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n - TESTCASE_AUTO(Test11640_getAffixes); - TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency); - TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow); -- TESTCASE_AUTO(Test13391_chakmaParsing); -+ /* MSFT Change: Begin */ -+ // TESTCASE_AUTO(Test13391_chakmaParsing); -+ /* MSFT Change: End */ - TESTCASE_AUTO(Test11735_ExceptionIssue); - TESTCASE_AUTO(Test11035_FormatCurrencyAmount); - TESTCASE_AUTO(Test11318_DoubleConversion); -@@ -1022,19 +1024,21 @@ void NumberFormatTest::TestCurrencyObject() { - return; +@@ -104,7 +104,7 @@ void LocaleDisplayNamesTest::TestCreateDialect() { + LocaleDisplayNames *ldn = LocaleDisplayNames::createInstance(Locale::getUS(), ULDN_DIALECT_NAMES); + ldn->localeDisplayName("en_GB", temp); + delete ldn; +- test_assert_equal("British English", temp); ++ test_assert_equal("English (United Kingdom)", temp); + } + + void LocaleDisplayNamesTest::TestWithKeywordsAndEverything() { +@@ -190,7 +190,7 @@ void LocaleDisplayNamesTest::TestUldnOpenDialect() { + test_assert(U_SUCCESS(status)); + + UnicodeString str(result, len, kMaxResultSize); +- test_assert_equal("British English", str); ++ test_assert_equal("English (United Kingdom)", str); + } + + void LocaleDisplayNamesTest::TestUldnWithGarbage() { +@@ -299,22 +299,22 @@ static char16_t daFor_en[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"en + static char16_t daFor_en_cabud[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x62,0x75,0x64,0x64,0x68,0x69,0x73,0x74,0x69,0x73,0x6B,0x20, + 0x6B,0x61,0x6C,0x65,0x6E,0x64,0x65,0x72,0x29,0}; //"engelsk (buddhistisk kalender)" + static char16_t daFor_en_GB[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"engelsk (Storbritannien)" +-static char16_t daFor_en_GB_D[] = {0x62,0x72,0x69,0x74,0x69,0x73,0x6B,0x20,0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"britisk engelsk" ++static char16_t daFor_en_GB_D[] = {0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"engelsk (Storbritannien)" + static char16_t esFor_en[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0}; //"ingles" with acute on the e + static char16_t esFor_en_GB[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"ingles (Reino Unido)" ... +-static char16_t esFor_en_GB_S[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x55,0x29,0}; //"ingles (RU)" ... +-static char16_t esFor_en_GB_D[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x62,0x72,0x69,0x74,0xE1,0x6E,0x69,0x63,0x6F,0}; //"ingles britanico" with acute on the e, a ++static char16_t esFor_en_GB_S[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"ingles (Reino Unido)" ... ++static char16_t esFor_en_GB_D[] = {0x69,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"ingles (Reino Unido)" ... + static char16_t ruFor_uz_Latn[] = {0x0443,0x0437,0x0431,0x0435,0x043A,0x0441,0x043A,0x0438,0x0439,0x20,0x28,0x043B,0x0430,0x0442,0x0438,0x043D,0x0438,0x0446,0x0430,0x29,0}; // all lowercase + #if !UCONFIG_NO_BREAK_ITERATION + static char16_t daFor_en_T[] = {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"Engelsk" + static char16_t daFor_en_cabudT[]= {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x62,0x75,0x64,0x64,0x68,0x69,0x73,0x74,0x69,0x73,0x6B,0x20, + 0x6B,0x61,0x6C,0x65,0x6E,0x64,0x65,0x72,0x29,0}; //"Engelsk (buddhistisk kalender)" + static char16_t daFor_en_GB_T[] = {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"Engelsk (Storbritannien)" +-static char16_t daFor_en_GB_DT[] = {0x42,0x72,0x69,0x74,0x69,0x73,0x6B,0x20,0x65,0x6E,0x67,0x65,0x6C,0x73,0x6B,0}; //"Britisk engelsk" ++static char16_t daFor_en_GB_DT[] = {0x45,0x6E,0x67,0x65,0x6C,0x73,0x6B,0x20,0x28,0x53,0x74,0x6F,0x72,0x62,0x72,0x69,0x74,0x61,0x6E,0x6E,0x69,0x65,0x6E,0x29,0}; //"Engelsk (Storbritannien)" + static char16_t esFor_en_T[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0}; //"Ingles" with acute on the e + static char16_t esFor_en_GB_T[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"Ingles (Reino Unido)" ... +-static char16_t esFor_en_GB_ST[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x55,0x29,0}; //"Ingles (RU)" ... +-static char16_t esFor_en_GB_DT[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x62,0x72,0x69,0x74,0xE1,0x6E,0x69,0x63,0x6F,0}; //"Ingles britanico" with acute on the e, a ++static char16_t esFor_en_GB_ST[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"Ingles (Reino Unido)" ... ++static char16_t esFor_en_GB_DT[] = {0x49,0x6E,0x67,0x6C,0xE9,0x73,0x20,0x28,0x52,0x65,0x69,0x6E,0x6F,0x20,0x55,0x6E,0x69,0x64,0x6F,0x29,0}; //"Ingles (Reino Unido)" ... + static char16_t ruFor_uz_Latn_T[]= {0x0423,0x0437,0x0431,0x0435,0x043A,0x0441,0x043A,0x0438,0x0439,0x20,0x28,0x043B,0x0430,0x0442,0x0438,0x043D,0x0438,0x0446,0x0430,0x29,0}; // first char upper + #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ + +diff --git a/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp b/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp +index f01b64baf5121a9bab7a3ca40c24982466ff6687..3492e06f92a6f165d552a41a00eccd4522cd8e56 100644 +--- a/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp ++++ b/icu/icu4c/source/test/intltest/messageformat2test_icu.cpp +@@ -48,7 +48,7 @@ there was {$what} on planet {$planet :integer}.") + .setArgument("planet", (int64_t) 7) + .setDateArgument("when", (UDate) 871068000000) + .setArgument("what", "a disturbance in the Force") +- .setExpected(CharsToUnicodeString("At 12:20:00\\u202FPM on Aug 8, 1997, there was a disturbance in the Force on planet 7.")) ++ .setExpected(CharsToUnicodeString("At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.")) + .build(), errorCode); + } + +diff --git a/icu/icu4c/source/test/intltest/tmsgfmt.cpp b/icu/icu4c/source/test/intltest/tmsgfmt.cpp +index 54b71ed3e78105b7ab9e5f2709c19c8981d28b35..0603136ba1142f16d5d65be27ea9e9f2e2fe9bda 100644 +--- a/icu/icu4c/source/test/intltest/tmsgfmt.cpp ++++ b/icu/icu4c/source/test/intltest/tmsgfmt.cpp +@@ -288,7 +288,7 @@ void TestMessageFormat::PatternTest() + u"Quotes ', {, 'a' 1 {0}", + u"Quotes ', {, 'a' 1 {0}", + u"{1,number,'#',##} #34,56", +- u"There are 3,456 files on Disk at 1/12/70, 5:46\u202FAM.", ++ u"There are 3,456 files on Disk at 1/12/70, 5:46 AM.", + u"On Disk, there are 3,456 files, with $1.00.", + u"{1,number,percent}, 345,600%,", + u"{1,date,full}, Wednesday, December 31, 1969,", +@@ -419,7 +419,7 @@ void TestMessageFormat::testStaticFormat() + } + + const UnicodeString expected( +- u"At 12:20:00\u202FPM on Aug 8, 1997, there was a disturbance in the Force on planet 7."); ++ u"At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7."); + if (result != expected) { + errln(UnicodeString("TestMessageFormat::testStaticFormat failed on test") + + UnicodeString("\n Result: ") + result + +@@ -1502,7 +1502,7 @@ void TestMessageFormat::TestUnlimitedArgsAndSubformats() { + + UnicodeString expected = + u"On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) " +- u"at 9:46:40\u202FAM (aka 9:46\u202FAM, aka 9:46:40\u202FAM PST) " ++ u"at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) " + u"there were 1,303 werjes " + u"(a 8% increase over 1,202) " + u"despite the Glimmung's efforts " +diff --git a/icu/icu4c/source/test/testdata/format.txt b/icu/icu4c/source/test/testdata/format.txt +index e3d6e72fd8b9ccbb5f7868865074a16f4b8554e8..b8d3c3ba5b99f2eb01ff2513335700177655765d 100644 +--- a/icu/icu4c/source/test/testdata/format.txt ++++ b/icu/icu4c/source/test/testdata/format.txt +@@ -37,7 +37,7 @@ format:table(nofallback) { + "", + "DATE=SHORT,TIME=SHORT", + "ERA=1,YEAR=2007,MONTH=AUGUST,DATE=8,HOUR_OF_DAY=18,MINUTE=54,SECOND=0", +- "8/8/07, 6:54 PM" ++ "8/8/07, 6:54 PM" + }, + { + "zh_TW@calendar=roc", +@@ -102,14 +102,14 @@ format:table(nofallback) { + "GMT", + "TIME=LONG", + "ERA=1,YEAR=2012,MONTH=OCTOBER,DATE=8,HOUR_OF_DAY=23,MINUTE=59,SECOND=0", +- "11:59:00 PM GMT" ++ "11:59:00 PM GMT" + }, + { + "en_US@calendar=gregorian", + "GMT", + "TIME=LONG", + "RELATIVE_ADD:DATE=-1,HOUR_OF_DAY=17,MINUTE=0,SECOND=0", // one day before now at specified time +- "5:00:00 PM GMT" ++ "5:00:00 PM GMT" + }, + // normal formats, combined using 'at' + { +@@ -117,7 +117,7 @@ format:table(nofallback) { + "GMT", + "DATE=RELATIVE_FULL,TIME=LONG", + "ERA=1,YEAR=2012,MONTH=OCTOBER,DATE=8,HOUR_OF_DAY=23,MINUTE=59,SECOND=0", +- "Monday, October 8, 2012, 11:59:00 PM GMT" ++ "Monday, October 8, 2012, 11:59:00 PM GMT" + }, + // normal formats, combined using ", " + { +@@ -125,7 +125,7 @@ format:table(nofallback) { + "GMT", + "DATE=RELATIVE_MEDIUM,TIME=SHORT", + "ERA=1,YEAR=2012,MONTH=OCTOBER,DATE=8,HOUR_OF_DAY=23,MINUTE=59,SECOND=0", +- "Oct 8, 2012, 11:59 PM" ++ "Oct 8, 2012, 11:59 PM" + }, + // formats with relative day, combined using 'at' + { +@@ -133,7 +133,7 @@ format:table(nofallback) { + "GMT", + "DATE=RELATIVE_FULL,TIME=LONG", + "RELATIVE_ADD:DATE=-1,HOUR_OF_DAY=17,MINUTE=0,SECOND=0", // one day before now at specified time +- "yesterday, 5:00:00 PM GMT" ++ "yesterday, 5:00:00 PM GMT" + }, + // formats with relative day, combined using ", " + { +@@ -141,7 +141,7 @@ format:table(nofallback) { + "GMT", + "DATE=RELATIVE_MEDIUM,TIME=SHORT", + "RELATIVE_ADD:DATE=-1,HOUR_OF_DAY=17,MINUTE=0,SECOND=0", // one day before now at specified time +- "yesterday, 5:00 PM" ++ "yesterday, 5:00 PM" + }, + // normal formats that have quoted literals, combined + { +@@ -554,7 +554,7 @@ format:table(nofallback) { + "", + "DATE=FULL,TIME=FULL", + "MILLIS=3076424179200000", +- "Friday, 3 Heshvan 103217 at 12:00:00 AM GMT-08:00" ++ "Friday, 3 Heshvan 103217 at 12:00:00 AM GMT-08:00" + }, + } + } +diff --git a/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json b/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json +index 21f917da6e5239927ee2a5213289df6305239287..b72421119ee8e053ea0cc9f01a43400f2fcc0d01 100644 +--- a/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json ++++ b/icu/icu4c/source/test/testdata/message2/icu4j/icu-test-functions.json +@@ -2,18 +2,18 @@ + "Date and time formats": [ + { + "src": "Expires on {$exp}", +- "exp": "Expires on 8/3/24, 9:43 PM", ++ "exp": "Expires on 8/3/24, 9:43 PM", + "comment": "Modified from ICU4J copy to add params (likewise with the other date/time tests); 1722746637000 is 2024-08-03 21:43:57 PDT", + "params": {"exp": { "date": 1722746637000 } } + }, + { + "src": "Expires on {$exp :datetime}", +- "exp": "Expires on 8/3/24, 9:43 PM", ++ "exp": "Expires on 8/3/24, 9:43 PM", + "params": {"exp": { "date": 1722746637000 } } + }, + { + "src": "Expires on {$exp :datetime icu:skeleton=yMMMMdjmsSSEE}", +- "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", ++ "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", + "params": {"exp": { "date": 1722746637000 } }, + "ignoreTest": "ICU-22754 Skeleton option not implemented yet" + }, +@@ -34,22 +34,22 @@ + }, + { + "src": "Expires on {$exp :datetime timeStyle=long}", +- "exp": "Expires on 9:43:57 PM PDT", ++ "exp": "Expires on 9:43:57 PM PDT", + "params": {"exp": { "date": 1722746637000 } } + }, + { + "src": "Expires on {$exp :datetime timeStyle=medium}", +- "exp": "Expires on 9:43:57 PM", ++ "exp": "Expires on 9:43:57 PM", + "params": {"exp": { "date": 1722746637000 } } + }, + { + "src": "Expires on {$exp :datetime timeStyle=short}", +- "exp": "Expires on 9:43 PM", ++ "exp": "Expires on 9:43 PM", + "params": {"exp": { "date": 1722746637000 } } + }, + { + "src": "Expires on {$exp :datetime dateStyle=full timeStyle=medium}", +- "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", ++ "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", + "params": {"exp": { "date": 1722746637000 } } + }, + { +@@ -72,14 +72,14 @@ + { + "comment": "Make sure we ignore date / time fields if needed", + "src": "Expires at {$exp :time year=numeric month=medium day=numeric weekday=long hour=numeric minute=numeric}", +- "exp": "Expires at 9:43 PM", ++ "exp": "Expires at 9:43 PM", + "params": {"exp": { "date": 1722746637000 } }, + "ignoreTest": "ICU-22754 ICU4C doesn't accept field options for `:date` or `:time` -- see spec" + }, + { + "comment": "Make sure we ignore date / time fields if needed", + "src": "Expires at {$exp :time style=long dateStyle=full timeStyle=medium}", +- "exp": "Expires at 9:43:57 PM PDT", ++ "exp": "Expires at 9:43:57 PM PDT", + "params": {"exp": { "date": 1722746637000 } } + }, + { +@@ -96,11 +96,11 @@ + }, + { + "src": "Expires at {|2024-07-02T19:23:45| :datetime timeStyle=full}", +- "exp": "Expires at 7:23:45 PM Pacific Daylight Time" ++ "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + }, + { + "src": "Expires at {|2024-07-02T19:23:45.123| :datetime timeStyle=full}", +- "exp": "Expires at 7:23:45 PM Pacific Daylight Time" ++ "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + }, + { + "src": "Expires on {|2025-02-27T19:23:45| :datetime dateStyle=full}", +@@ -108,11 +108,11 @@ + }, + { + "src": "Expires at {|2024-07-02T19:23:45Z| :datetime timeStyle=long}", +- "exp": "Expires at 7:23:45 PM GMT" ++ "exp": "Expires at 7:23:45 PM GMT" + }, + { + "src": "Expires at {|2024-07-02T19:23:45+03:30| :datetime timeStyle=full}", +- "exp": "Expires at 7:23:45 PM GMT+03:30" ++ "exp": "Expires at 7:23:45 PM GMT+03:30" } + ], + "Chaining" : [ +@@ -125,7 +125,7 @@ + ".local $zooExp = {$exp :datetime dateStyle=short timeStyle=$tsOver}\n", + "{{Hello John, you want '{$exp}', '{$longExp}', or '{$zooExp}' or even '{$exp :datetime dateStyle=full}'?}}" + ], +- "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", ++ "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", + "params": {"exp": { "date": 1722746637000 }, "user": "John", "tsOver" : "long" }, + "ignoreTest": "ICU-22754 ICU4C doesn't implement this kind of function composition yet. See https://github.com/unicode-org/message-format-wg/issues/515" + }, +diff --git a/icu/testdata/message2/icu-test-functions.json b/icu/testdata/message2/icu-test-functions.json +index a97446addf0e7273e6dff7a10682340f3d9a3bc8..87e7b401b1398ee1ea74c4b5d4e3214c057d7500 100644 +--- a/icu/testdata/message2/icu-test-functions.json ++++ b/icu/testdata/message2/icu-test-functions.json +@@ -7,18 +7,18 @@ + "tests": [ + { + "src": "Expires on {$exp}", +- "exp": "Expires on 8/3/24, 9:43 PM", ++ "exp": "Expires on 8/3/24, 9:43 PM", + "comment": "Modified from ICU4J copy to add params (likewise with the other date/time tests); 1722746637000 is 2024-08-03 21:43:57 PDT", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { + "src": "Expires on {$exp :datetime}", +- "exp": "Expires on 8/3/24, 9:43 PM", ++ "exp": "Expires on 8/3/24, 9:43 PM", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { + "src": "Expires on {$exp :datetime icu:skeleton=yMMMMdjmsSSEE}", +- "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", ++ "exp": "Expires on Sat, August 3, 2024 at 9:43:57.00 PM", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }], + "ignoreCpp": "ICU-22754 Skeleton option not implemented yet" + }, +@@ -39,22 +39,22 @@ + }, + { + "src": "Expires on {$exp :datetime timeStyle=long}", +- "exp": "Expires on 9:43:57 PM PDT", ++ "exp": "Expires on 9:43:57 PM PDT", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { + "src": "Expires on {$exp :datetime timeStyle=medium}", +- "exp": "Expires on 9:43:57 PM", ++ "exp": "Expires on 9:43:57 PM", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { + "src": "Expires on {$exp :datetime timeStyle=short}", +- "exp": "Expires on 9:43 PM", ++ "exp": "Expires on 9:43 PM", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { + "src": "Expires on {$exp :datetime dateStyle=full timeStyle=medium}", +- "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", ++ "exp": "Expires on Saturday, August 3, 2024 at 9:43:57 PM", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { +@@ -77,14 +77,14 @@ + { + "comment": "Make sure we ignore date / time fields if needed", + "src": "Expires at {$exp :time year=numeric month=medium day=numeric weekday=long hour=numeric minute=numeric}", +- "exp": "Expires at 9:43 PM", ++ "exp": "Expires at 9:43 PM", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }], + "ignoreCpp": "ICU-22754 ICU4C doesn't accept field options for `:date` or `:time` -- see spec" + }, + { + "comment": "Make sure we ignore date / time fields if needed", + "src": "Expires at {$exp :time style=long dateStyle=full timeStyle=medium}", +- "exp": "Expires at 9:43:57 PM PDT", ++ "exp": "Expires at 9:43:57 PM PDT", + "params": [{ "name": "exp", "value": { "date": 1722746637000 } }] + }, + { +@@ -99,11 +99,11 @@ + }, + { + "src": "Expires at {|2024-07-02T19:23:45| :datetime timeStyle=full}", +- "exp": "Expires at 7:23:45 PM Pacific Daylight Time" ++ "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + }, + { + "src": "Expires at {|2024-07-02T19:23:45.123| :datetime timeStyle=full}", +- "exp": "Expires at 7:23:45 PM Pacific Daylight Time" ++ "exp": "Expires at 7:23:45 PM Pacific Daylight Time" + }, + { + "src": "Expires on {|2025-02-27T19:23:45| :datetime dateStyle=full}", +@@ -111,12 +111,12 @@ + }, + { + "src": "Expires at {|2024-07-02T19:23:45Z| :datetime timeStyle=long}", +- "exp": "Expires at 7:23:45 PM GMT", ++ "exp": "Expires at 7:23:45 PM GMT", + "ignoreCpp": "ICU-22754 Time zones not working yet (bug)" + }, + { + "src": "Expires at {|2024-07-02T19:23:45+03:30| :datetime timeStyle=full}", +- "exp": "Expires at 7:23:45 PM GMT+03:30", ++ "exp": "Expires at 7:23:45 PM GMT+03:30", + "ignoreCpp": "ICU-22754 Time zones not working yet (bug)" + }, + { +@@ -128,7 +128,7 @@ + ".local $zooExp = {$exp :datetime dateStyle=short timeStyle=$tsOver}\n", + "{{Hello John, you want '{$exp}', '{$longExp}', or '{$zooExp}' or even '{$exp :datetime dateStyle=full}'?}}" + ], +- "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", ++ "exp": "Hello John, you want '9:43 PM', 'August 3, 2024 at 9:43 PM', or '8/3/24, 9:43:57 PM Pacific Daylight Time' or even 'Saturday, August 3, 2024 at 9:43 PM'?", + "params": [{"name": "exp", "value": { "date": 1722746637000 }}, + {"name": "user", "value": "John"}, + {"name": "tsOver", "value": "full" }], +diff --git a/icu/testdata/message2/more-functions.json b/icu/testdata/message2/more-functions.json +index 6d074f8b2d806e82917d65644675bccc47e528a9..90dc1274ba7fc8fccbf28994121df745b78efd53 100644 +--- a/icu/testdata/message2/more-functions.json ++++ b/icu/testdata/message2/more-functions.json +@@ -47,17 +47,17 @@ + }, + { + "src": "Testing date formatting: {$date :time style=long}.", +- "exp": "Testing date formatting: 7:42:37\u202FPM PST.", ++ "exp": "Testing date formatting: 7:42:37 PM PST.", + "params": [{ "name": "date", "value": { "date": 1669261357000 } }] + }, + { + "src": "Testing date formatting: {$date :time style=medium}.", +- "exp": "Testing date formatting: 7:42:37\u202FPM.", ++ "exp": "Testing date formatting: 7:42:37 PM.", + "params": [{ "name": "date", "value": { "date": 1669261357000 } }] + }, + { + "src": "Testing date formatting: {$date :time style=short}.", +- "exp": "Testing date formatting: 7:42\u202FPM.", ++ "exp": "Testing date formatting: 7:42 PM.", + "params": [{ "name": "date", "value": { "date": 1669261357000 } }] + }, + { diff --git a/icu-patches/patches/017-MSFT-Patch_ICU_test_changes_for_extra_CLDR-MS_locales.patch b/icu-patches/patches/017-MSFT-Patch_ICU_test_changes_for_extra_CLDR-MS_locales.patch index bcdaa06123a..e317005a830 100644 --- a/icu-patches/patches/017-MSFT-Patch_ICU_test_changes_for_extra_CLDR-MS_locales.patch +++ b/icu-patches/patches/017-MSFT-Patch_ICU_test_changes_for_extra_CLDR-MS_locales.patch @@ -1,131 +1,58 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jeff Genovy <29107334+jefgen@users.noreply.github.com> -Date: Wed, 7 Apr 2021 20:47:08 -0700 -Subject: MSFT-PATCH: Modify ICU tests to pass with extra locales from CLDR-MS. +From: Arvind Oruganti +Date: Tue, 19 May 2026 06:45:00 +0530 +Subject: MSFT-PATCH: Refresh ICU tests for extra CLDR-MS locales on ICU 78 -This changes modifies the ICU tests to pass with extra locales from -CLDR-MS. +Refreshes the CLDR-MS extra-locale test expectations for ICU 78. + +The ICU 72-era patch no longer matched the refactored ICU 78 tests, so the applicable 029 locale expectations were re-derived from the final passing Stage 7/8 tree. diff --git a/icu/icu4c/source/test/cintltst/cldrtest.c b/icu/icu4c/source/test/cintltst/cldrtest.c -index 179539d5178b5cfd8b5350043c539e89e8740185..bfb35c35a449f60c61c9a8eb6282c307e41fd161 100644 +index e014a1e1d59a48fb6ef78923fb7de4160f69779b..8cf8e5dc1ba8f3059e4ce6b0d1bb6369cda51ca7 100644 --- a/icu/icu4c/source/test/cintltst/cldrtest.c +++ b/icu/icu4c/source/test/cintltst/cldrtest.c -@@ -970,7 +970,14 @@ static void VerifyTranslation(void) { - uprv_strncmp(currLoc, "oc", 2) == 0 || uprv_strncmp(currLoc, "oc_FR", 5) == 0 || - uprv_strncmp(currLoc, "syr", 3) == 0 || uprv_strncmp(currLoc, "syr_SY", 6) == 0 || - uprv_strncmp(currLoc, "tig", 3) == 0 || uprv_strncmp(currLoc, "tig_ER", 6) == 0 || -- uprv_strncmp(currLoc, "wal", 3) == 0 || uprv_strncmp(currLoc, "wal_ET", 6) == 0 -+ uprv_strncmp(currLoc, "wal", 3) == 0 || uprv_strncmp(currLoc, "wal_ET", 6) == 0 || -+ uprv_strncmp(currLoc, "bin", 3) == 0 || uprv_strncmp(currLoc, "bin_NG", 6) == 0 || -+ uprv_strncmp(currLoc, "la", 2) == 0 || uprv_strncmp(currLoc, "la_VA", 6) == 0 || -+ uprv_strncmp(currLoc, "jv_Java", 7) == 0 || uprv_strncmp(currLoc, "jv_Java_ID", 10) == 0 || -+ uprv_strncmp(currLoc, "ks_Deva", 7) == 0 || uprv_strncmp(currLoc, "ks_Deva_IN", 10) == 0 || -+ uprv_strncmp(currLoc, "pap", 3) == 0 || uprv_strncmp(currLoc, "pap_029", 7) == 0 || -+ uprv_strncmp(currLoc, "tzm_Arab", 8) == 0 || uprv_strncmp(currLoc, "tzm_Arab_MA", 11) == 0 || -+ uprv_strncmp(currLoc, "tzm_Tfng", 8) == 0 || uprv_strncmp(currLoc, "tzm_Tfng_MA", 11) == 0 - ) { - log_knownIssue("0", "MSFT Change: skipping test for %s which has issues due to CLDR Seed data.", currLoc); - } -@@ -1110,7 +1117,8 @@ static void VerifyTranslation(void) { +@@ -1122,7 +1122,7 @@ static void VerifyTranslation(void) { if (U_FAILURE(errorCode)) { log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); } else { - if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_LR")!=NULL ) { -+ /* MSFT Change: CLDR-MS adds 029 region with US measurement */ + if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_LR")!=NULL || strstr(fullLoc, "_029")!=NULL ) { if(measurementSystem != UMS_US){ log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); } -@@ -1128,10 +1136,11 @@ static void VerifyTranslation(void) { - if (U_FAILURE(errorCode)) { - log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); - } else { -+ /* MSFT Change: CLDR-MS adds 029 region with US paper size */ +@@ -1143,7 +1143,7 @@ static void VerifyTranslation(void) { if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_BZ")!=NULL || strstr(fullLoc, "_CA")!=NULL || strstr(fullLoc, "_CL")!=NULL || strstr(fullLoc, "_CO")!=NULL || strstr(fullLoc, "_CR")!=NULL || strstr(fullLoc, "_GT")!=NULL || strstr(fullLoc, "_MX")!=NULL || strstr(fullLoc, "_NI")!=NULL || strstr(fullLoc, "_PA")!=NULL || strstr(fullLoc, "_PH")!=NULL || strstr(fullLoc, "_PR")!=NULL || - strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL ) { -+ strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL || strstr(fullLoc, "_029")!=NULL ) { ++ strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL || strstr(fullLoc, "_029")!=NULL ) { if (height != 279 || width != 216) { log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); } -@@ -1251,8 +1260,14 @@ static void TestExemplarSet(void){ - - if (existsInScript == FALSE){ - /* MSFT Change */ -- if (uprv_strncmp(locale, "oc", 2) == 0 || uprv_strncmp(locale, "oc_FR", 5) == 0) { -- log_knownIssue("0", "MSFT Change: oc and oc_FR have ExemplarSet issues."); -+ if (uprv_strncmp(locale, "oc", 2) == 0 || uprv_strncmp(locale, "oc_FR", 5) == 0 || -+ uprv_strncmp(locale, "jv_Java", 7) == 0 || uprv_strncmp(locale, "jv_Java_ID", 10) == 0 || -+ uprv_strncmp(locale, "la", 2) == 0 || uprv_strncmp(locale, "la_VA", 6) == 0 || -+ uprv_strncmp(locale, "pap", 3) == 0 || uprv_strncmp(locale, "pap_029", 7) == 0 || -+ uprv_strncmp(locale, "tzm_Arab", 8) == 0 || uprv_strncmp(locale, "tzm_Arab_MA", 11) == 0 || -+ uprv_strncmp(locale, "tzm_Tfng", 8) == 0 || uprv_strncmp(locale, "tzm_Tfng_MA", 11) == 0 -+ ) { -+ log_knownIssue("0", "MSFT Change: skipping test for %s which has issue due to CLDR seed data.", locale); - continue; - } else { - log_err("ExemplarSet containment failed for locale : %s\n", locale); diff --git a/icu/icu4c/source/test/cintltst/cnmdptst.c b/icu/icu4c/source/test/cintltst/cnmdptst.c -index 99a9ce23be7ef93923493b2b8312a254706c3f2d..a319b99e3faf6f6fc749e70852a298ce42268696 100644 +index 98504e0220ffb26a5f02877e1bbf7343e07e5a64..b7ce012361befc52b1b23e068017ffb71bdc4b4a 100644 --- a/icu/icu4c/source/test/cintltst/cnmdptst.c +++ b/icu/icu4c/source/test/cintltst/cnmdptst.c -@@ -811,7 +811,8 @@ static void TestGetKeywordValuesForLocale(void) { +@@ -813,7 +813,7 @@ static void TestGetKeywordValuesForLocale(void) { { "und", "USD", "USN", NULL }, /* { "und_ZZ", "USD", NULL, NULL }, -- temporarily remove as this locale now has 15 entries */ { "en_US", "USD", "USN", NULL }, - { "en_029", "USD", "USN", NULL }, -+ /* MSFT Change: CLDR-MS adds en_029 locale with XCD currency */ + { "en_029", "XCD", NULL, NULL }, { "en_TH", "THB", NULL, NULL }, { "de", "EUR", NULL, NULL }, { "de_DE", "EUR", NULL, NULL }, -@@ -825,11 +826,13 @@ static void TestGetKeywordValuesForLocale(void) { +@@ -827,11 +827,11 @@ static void TestGetKeywordValuesForLocale(void) { { "en_US@currency=CAD;rg=THZZZZ", "THB", NULL, NULL }, }; const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { - 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1 -+ /* MSFT Change: CLDR-MS adds en_029 locale with XCD currency */ + 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1 }; /* ucurr_forLocale results for same locales; "" if no result expected */ const char *FORLOCALE[PREFERRED_SIZE] = { - "", "", "USD", "", -+ /* MSFT Change: CLDR-MS adds en_029 locale with XCD currency */ + "", "", "USD", "XCD", "THB", "", "EUR", "", "ILS", "CAD", "ZZZ", "DEM", "THB", "USD", "CAD" -diff --git a/icu/icu4c/source/test/intltest/dtptngts.cpp b/icu/icu4c/source/test/intltest/dtptngts.cpp -index dc86355f93fa68f509a0023dc95fc17a548170c1..c83e27bb68c212c3e9569c71ed5b417a96b7f9de 100644 ---- a/icu/icu4c/source/test/intltest/dtptngts.cpp -+++ b/icu/icu4c/source/test/intltest/dtptngts.cpp -@@ -1408,7 +1408,8 @@ void IntlTestDateTimePatternGeneratorAPI::testJjMapping() { - uprv_strncmp(localeID, "ssy_ER", 6) == 0 || uprv_strncmp(localeID, "st_LS", 5) == 0 || - uprv_strncmp(localeID, "syr", 3) == 0 || uprv_strncmp(localeID, "syr_SY", 6) == 0 || - uprv_strncmp(localeID, "tig", 3) == 0 || uprv_strncmp(localeID, "tig_ER", 6) == 0 || -- uprv_strncmp(localeID, "wal", 3) == 0 || uprv_strncmp(localeID, "wal_ET", 6) == 0 -+ uprv_strncmp(localeID, "wal", 3) == 0 || uprv_strncmp(localeID, "wal_ET", 6) == 0 || -+ uprv_strncmp(localeID, "ks_Deva", 7) == 0 || uprv_strncmp(localeID, "ks_Deva_IN", 10) == 0 - ) { - logKnownIssue("0", "MSFT Change: skipping test for %s which has issues due to CLDR Seed data.", localeID); - } -diff --git a/icu/icu4c/source/test/intltest/numfmtst.cpp b/icu/icu4c/source/test/intltest/numfmtst.cpp -index bc072bd8e3775554b8a8f96a81baf850b5e8feb7..a63c329c8eabf287512b9c152ac91d862d333264 100644 ---- a/icu/icu4c/source/test/intltest/numfmtst.cpp -+++ b/icu/icu4c/source/test/intltest/numfmtst.cpp -@@ -8094,10 +8094,12 @@ void NumberFormatTest::TestAccountingCurrency() { - (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status); - expect(NumberFormat::createInstance("de_DE", style, status), - (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status); -+ /* MSFT Change: We add a CLDR-MS locale en_ID */ - expect(NumberFormat::createInstance("en_ID", style, status), -- (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status); -+ (Formattable)(double)0, UnicodeString("IDR\\u00A00,00").unescape(), TRUE, status); - expect(NumberFormat::createInstance("en_ID", style, status), -- (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status); -+ (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00,20)").unescape(), TRUE, status); -+ /* MSFT Change: End */ - expect(NumberFormat::createInstance("sh_ME", style, status), - (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status); - expect(NumberFormat::createInstance("sh_ME", style, status), diff --git a/icu-patches/patches/018-MSFT-Patch_ICU_toolutil_increase_string_store_for_extra_locales.patch b/icu-patches/patches/018-MSFT-Patch_ICU_toolutil_increase_string_store_for_extra_locales.patch index a41c47a5263..f9bfc6523d7 100644 --- a/icu-patches/patches/018-MSFT-Patch_ICU_toolutil_increase_string_store_for_extra_locales.patch +++ b/icu-patches/patches/018-MSFT-Patch_ICU_toolutil_increase_string_store_for_extra_locales.patch @@ -1,11 +1,14 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jeff Genovy <29107334+jefgen@users.noreply.github.com> -Date: Wed, 7 Apr 2021 20:47:31 -0700 -Subject: MSFT-PATCH: Increase the STRING_STORE_SIZE due to extra locales from CLDR-MS +From: Arvind Oruganti +Date: Tue, 19 May 2026 06:45:00 +0530 +Subject: MSFT-PATCH: Increase ICU string store for CLDR 48 extra locales +Increases STRING_STORE_SIZE for the larger CLDR 48 / CLDR-MS locale set. + +The original 120000 value was carried from the older patch, but this ICU 78 upgrade settled on 200000 before the CLDR data build. diff --git a/icu/icu4c/source/tools/toolutil/package.h b/icu/icu4c/source/tools/toolutil/package.h -index ea60c13a74a57b94057882e39b6aa05314c4ca1f..6c411ae5fd04c8463a089307efc056f4d2f622f9 100644 +index ea60c13a74a57b94057882e39b6aa05314c4ca1f..3a1d3cd23d9ee75ad2881d52c0f34413dbd554f1 100644 --- a/icu/icu4c/source/tools/toolutil/package.h +++ b/icu/icu4c/source/tools/toolutil/package.h @@ -27,7 +27,7 @@ @@ -13,7 +16,7 @@ index ea60c13a74a57b94057882e39b6aa05314c4ca1f..6c411ae5fd04c8463a089307efc056f4 // .dat package file representation ---------------------------------------- *** -#define STRING_STORE_SIZE 100000 -+#define STRING_STORE_SIZE 120000 ++#define STRING_STORE_SIZE 200000 #define MAX_PKG_NAME_LENGTH 64 typedef void CheckDependency(void *context, const char *itemName, const char *targetName); diff --git a/icu-patches/patches/020-MSFT-Patch_ICU_Add_uprefs_library_to_obtain_default_locale_as_full_BCP47_tag.patch b/icu-patches/patches/020-MSFT-Patch_ICU_Add_uprefs_library_to_obtain_default_locale_as_full_BCP47_tag.patch index 502beeb9f04..b6416bf2b47 100644 --- a/icu-patches/patches/020-MSFT-Patch_ICU_Add_uprefs_library_to_obtain_default_locale_as_full_BCP47_tag.patch +++ b/icu-patches/patches/020-MSFT-Patch_ICU_Add_uprefs_library_to_obtain_default_locale_as_full_BCP47_tag.patch @@ -1,61 +1,57 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Erik Torres <26077674+erik0686@users.noreply.github.com> -Date: Wed, 6 Oct 2021 15:06:30 -0700 -Subject: Add uprefs library to ICU to obtain the default locale as a full - BCP47 tag (#112) +From: Arvind Oruganti +Date: Tue, 19 May 2026 06:45:00 +0530 +Subject: MSFT-PATCH: Refresh uprefs default-locale library for ICU 78 -Currently, for many processes and tasks, ICU gets the default locale and caches it. This means that when needed, ICU will get something like "en-US" and that will not change even if you were to change your language or region in your device. -Furthermore, ICU has currently no way of getting other globalization settings such as currency, calendar, hour cycle, first day of week, sorting method and measurement system. -We have decided to add a way to solve these two problems. -By adding the uprefs library (only to the Windows implementation of uprv_getDefaultLocaleID()), we are adding the Uprefs_getBCP47Tag() internal API, which obtains a full, canonical and valid BCP47Tag containing all of the settings. +Refreshes the Windows uprefs library patch against the ICU 78 source tree. -This means we also change the way we get the default locale. We go from getting only the locale and region, to getting the full thing. +This records the final ICU 78 version of the project-file, putil, uconfig, source-list, and uprefstest changes instead of the stale ICU 72-era patch content. diff --git a/icu/icu4c/source/common/common.vcxproj b/icu/icu4c/source/common/common.vcxproj -index f8f28ad768ca2b4e7ec93893b213c3b426f294c1..305b705430837c9c928690bf1fd5aa46de81d5fd 100644 +index f0f13aa1e2ec1f953b4b0957763e50560ae3d0a1..aca55a102f96a8694e62c3e7b7affe4479e1a133 100644 --- a/icu/icu4c/source/common/common.vcxproj +++ b/icu/icu4c/source/common/common.vcxproj -@@ -282,6 +282,7 @@ - +@@ -286,6 +286,7 @@ + + -@@ -397,6 +398,7 @@ - +@@ -405,6 +406,7 @@ + + diff --git a/icu/icu4c/source/common/common_uwp.vcxproj b/icu/icu4c/source/common/common_uwp.vcxproj -index a57917292a7405b0a55fd8a34f9edd970c2951ef..0e346ccec772f6d37777505638ec7b242e21da5c 100644 +index 01906f3caf9a4c6f330b235c9b58b1b9179c82e0..113c241890217adcd4ebf14bc562e319a3e27c22 100644 --- a/icu/icu4c/source/common/common_uwp.vcxproj +++ b/icu/icu4c/source/common/common_uwp.vcxproj -@@ -404,6 +404,7 @@ - +@@ -409,6 +409,7 @@ + + -@@ -520,6 +521,7 @@ - +@@ -529,6 +530,7 @@ + + diff --git a/icu/icu4c/source/common/putil.cpp b/icu/icu4c/source/common/putil.cpp -index 3ed6a05d22d83972e3fdf2c356bc87a17babda27..4d80d514f84639e9aab7d1109ee28b45e2cf4d42 100644 +index ea15fdff0b0c67d09daf5a403f038be572cd1fbf..307b07d087de925095f6d6f976fbf37f21655b92 100644 --- a/icu/icu4c/source/common/putil.cpp +++ b/icu/icu4c/source/common/putil.cpp -@@ -71,6 +71,7 @@ +@@ -66,6 +66,7 @@ #include "locmap.h" #include "ucln_cmn.h" #include "charstr.h" @@ -63,7 +59,7 @@ index 3ed6a05d22d83972e3fdf2c356bc87a17babda27..4d80d514f84639e9aab7d1109ee28b45 /* Include standard headers. */ #include -@@ -1776,10 +1777,37 @@ The leftmost codepage (.xxx) wins. +@@ -1794,10 +1795,37 @@ The leftmost codepage (.xxx) wins. return posixID; #elif U_PLATFORM_USES_ONLY_WIN32_API @@ -102,7 +98,7 @@ index 3ed6a05d22d83972e3fdf2c356bc87a17babda27..4d80d514f84639e9aab7d1109ee28b45 // If we have already figured this out just use the cached value if (gCorrectedPOSIXLocale != nullptr) { return gCorrectedPOSIXLocale; -@@ -1821,11 +1849,11 @@ The leftmost codepage (.xxx) wins. +@@ -1839,11 +1867,11 @@ The leftmost codepage (.xxx) wins. } // Now normalize the resulting name @@ -116,7 +112,7 @@ index 3ed6a05d22d83972e3fdf2c356bc87a17babda27..4d80d514f84639e9aab7d1109ee28b45 if (U_SUCCESS(status)) { *(correctedPOSIXLocale + posixLen) = 0; -@@ -1839,6 +1867,7 @@ The leftmost codepage (.xxx) wins. +@@ -1857,6 +1885,7 @@ The leftmost codepage (.xxx) wins. } } } @@ -125,10 +121,10 @@ index 3ed6a05d22d83972e3fdf2c356bc87a17babda27..4d80d514f84639e9aab7d1109ee28b45 // If unable to find a locale we can agree upon, use en-US by default if (gCorrectedPOSIXLocale == nullptr) { diff --git a/icu/icu4c/source/common/sources.txt b/icu/icu4c/source/common/sources.txt -index e0410daaa475fad0b76587cec3e2dc4d124814f2..3ebc3c301130465cec837233540253110e8479cc 100644 +index 5b1c5e262eac42dc352f28b87033dff709376a2d..cfcfd95df56fac68a3cc224c4cd5a016a6099110 100644 --- a/icu/icu4c/source/common/sources.txt +++ b/icu/icu4c/source/common/sources.txt -@@ -157,6 +157,7 @@ unistr_titlecase_brkiter.cpp +@@ -163,6 +163,7 @@ unistr_titlecase_brkiter.cpp unorm.cpp unormcmp.cpp uobject.cpp @@ -137,10 +133,10 @@ index e0410daaa475fad0b76587cec3e2dc4d124814f2..3ebc3c301130465cec83723354025311 ures_cnv.cpp uresbund.cpp diff --git a/icu/icu4c/source/common/unicode/uconfig.h b/icu/icu4c/source/common/unicode/uconfig.h -index c4239fc9997028fb050be43740bb1cb368f514ba..da702d2d812fc4859ac6aa460bb8b0735ee28c29 100644 +index 3c1182886659252b44db3a0f28407dd994ca1447..f339dec982f4bcdfe7cff49130a84a1f5c4173f8 100644 --- a/icu/icu4c/source/common/unicode/uconfig.h +++ b/icu/icu4c/source/common/unicode/uconfig.h -@@ -390,6 +390,22 @@ +@@ -400,6 +400,22 @@ # define UCONFIG_USE_WINDOWS_LCID_MAPPING_API 1 #endif @@ -165,7 +161,7 @@ index c4239fc9997028fb050be43740bb1cb368f514ba..da702d2d812fc4859ac6aa460bb8b073 /* i18n library switches ---------------------------------------------------- */ diff --git a/icu/icu4c/source/common/uprefs.cpp b/icu/icu4c/source/common/uprefs.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..b055cbe86f6ef16843444c1ea80667441a26bfa2 +index 0000000000000000000000000000000000000000..d9304a11de04e2a6416c40c8d957352be49b0a5e --- /dev/null +++ b/icu/icu4c/source/common/uprefs.cpp @@ -0,0 +1,553 @@ @@ -725,7 +721,7 @@ index 0000000000000000000000000000000000000000..b055cbe86f6ef16843444c1ea8066744 \ No newline at end of file diff --git a/icu/icu4c/source/common/uprefs.h b/icu/icu4c/source/common/uprefs.h new file mode 100644 -index 0000000000000000000000000000000000000000..2d77d0c9e7f8bdf9287b77d55741160f1c10a1fe +index 0000000000000000000000000000000000000000..08ecd86189bb626b6ff7b55098e0cfb28ff033f8 --- /dev/null +++ b/icu/icu4c/source/common/uprefs.h @@ -0,0 +1,29 @@ @@ -760,31 +756,31 @@ index 0000000000000000000000000000000000000000..2d77d0c9e7f8bdf9287b77d55741160f +#endif //UPREFS_H \ No newline at end of file diff --git a/icu/icu4c/source/test/intltest/Makefile.in b/icu/icu4c/source/test/intltest/Makefile.in -index 13d3ea86dc9bd7c17c944b2fb7b04a143879421f..5f8822cedac4a5ddc9428cb85941b668f612c5a0 100644 +index 2e448319243dcd56431ccdfd3ddfdbce3eb2566f..eab33ebb0b6beb95282d568bfb98e0346ad0150c 100644 --- a/icu/icu4c/source/test/intltest/Makefile.in +++ b/icu/icu4c/source/test/intltest/Makefile.in -@@ -69,7 +69,7 @@ string_segment_test.o \ - numbertest_parse.o numbertest_doubleconversion.o numbertest_skeletons.o \ - static_unisets_test.o numfmtdatadriventest.o numbertest_range.o erarulestest.o \ - formattedvaluetest.o formatted_string_builder_test.o numbertest_permutation.o \ --units_data_test.o units_router_test.o units_test.o -+units_data_test.o units_router_test.o units_test.o uprefstest.o +@@ -78,7 +78,7 @@ units_data_test.o units_router_test.o units_test.o displayoptions_test.o \ + numbertest_simple.o \ + cplusplus_header_api_build_test.o uchar_type_build_test.o \ + ucolheaderonlytest.o usetheaderonlytest.o utfiteratortest.o utfstringtest.o \ +-intltesttest.o ++intltesttest.o uprefstest.o DEPS = $(OBJECTS:.o=.d) diff --git a/icu/icu4c/source/test/intltest/intltest.vcxproj b/icu/icu4c/source/test/intltest/intltest.vcxproj -index 319c3ab58f68f70f3da6ead4ca6cf5ca81da617b..20da05e608aeb4f472ef378d222732c863ec04aa 100644 +index ce69ec0de410b2ef93cb2bbb45592b581597c93a..0ee503fcbe4ba68b6b487bfb7cd66808dc6ec3b1 100644 --- a/icu/icu4c/source/test/intltest/intltest.vcxproj +++ b/icu/icu4c/source/test/intltest/intltest.vcxproj -@@ -288,6 +288,7 @@ - - - +@@ -247,6 +247,7 @@ + + + + -@@ -419,6 +420,7 @@ +@@ -378,6 +379,7 @@ @@ -793,7 +789,7 @@ index 319c3ab58f68f70f3da6ead4ca6cf5ca81da617b..20da05e608aeb4f472ef378d222732c8 diff --git a/icu/icu4c/source/test/intltest/itutil.cpp b/icu/icu4c/source/test/intltest/itutil.cpp -index 228dbf2f218aa1a6ac6860ec54ed67303b243699..2f7ba22278596980f172617c2db9df55c28ee680 100644 +index 20c16389c0a071870de84b62f763eb80fa6b8e73..768507c632ad530359818716f82ad518423354da 100644 --- a/icu/icu4c/source/test/intltest/itutil.cpp +++ b/icu/icu4c/source/test/intltest/itutil.cpp @@ -33,6 +33,9 @@ @@ -805,8 +801,8 @@ index 228dbf2f218aa1a6ac6860ec54ed67303b243699..2f7ba22278596980f172617c2db9df55 +#endif extern IntlTest *createBytesTrieTest(); - extern IntlTest *createLocaleMatcherTest(); -@@ -67,6 +70,9 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* & + #if !UCONFIG_NO_COLLATION +@@ -76,6 +79,9 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* & TESTCASE_AUTO_CLASS(LocaleAliasTest); TESTCASE_AUTO_CLASS(UnicodeSetTest); TESTCASE_AUTO_CLASS(ErrorCodeTest); @@ -818,10 +814,10 @@ index 228dbf2f218aa1a6ac6860ec54ed67303b243699..2f7ba22278596980f172617c2db9df55 TESTCASE_AUTO_CREATE_CLASS(UCharsTrieTest); diff --git a/icu/icu4c/source/test/intltest/uprefstest.cpp b/icu/icu4c/source/test/intltest/uprefstest.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..f76997c66c45a694398c62ed23e94d0d1d509561 +index 0000000000000000000000000000000000000000..69c5265eed1c66bb29a1d5af840da5925cb57440 --- /dev/null +++ b/icu/icu4c/source/test/intltest/uprefstest.cpp -@@ -0,0 +1,437 @@ +@@ -0,0 +1,438 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +#include "uprefstest.h" @@ -829,12 +825,12 @@ index 0000000000000000000000000000000000000000..f76997c66c45a694398c62ed23e94d0d + +#define ARRAY_SIZE 512 + -+ std::wstring UPrefsTest::language = L""; -+ std::wstring UPrefsTest::currency = L""; -+ std::wstring UPrefsTest::hourCycle = L""; -+ int32_t UPrefsTest::firstday = 0; -+ int32_t UPrefsTest::measureSystem = 0; -+ CALID UPrefsTest::calendar = 0; ++std::wstring UPrefsTest::language = L""; ++std::wstring UPrefsTest::currency = L""; ++std::wstring UPrefsTest::hourCycle = L""; ++int32_t UPrefsTest::firstday = 0; ++int32_t UPrefsTest::measureSystem = 0; ++CALID UPrefsTest::calendar = 0; + +void UPrefsTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) +{ @@ -856,7 +852,8 @@ index 0000000000000000000000000000000000000000..f76997c66c45a694398c62ed23e94d0d + TESTCASE_AUTO_END; +} + -+int32_t UPrefsTest::MockGetLocaleInfoEx(LPCWSTR lpLocaleName, LCTYPE LCType, LPWSTR lpLCData, int cchData, UErrorCode* status) ++int32_t UPrefsTest::MockGetLocaleInfoEx(LPCWSTR lpLocaleName, LCTYPE LCType, LPWSTR lpLCData, ++ int cchData, UErrorCode *status) +{ + switch (LCType) + { @@ -1237,7 +1234,7 @@ index 0000000000000000000000000000000000000000..f76997c66c45a694398c62ed23e94d0d + } +} + -+void UPrefsTest::Get12HourCycle2() ++void UPrefsTest::Get12HourCycle2() +{ + char languageBuffer[ARRAY_SIZE] = {0}; + language = L"ja-JP"; @@ -1249,11 +1246,11 @@ index 0000000000000000000000000000000000000000..f76997c66c45a694398c62ed23e94d0d + UErrorCode status = U_ZERO_ERROR; + char* expectedValue = "ja-JP-u-ca-buddhist-cu-mxn-fw-tue-hc-h12-ms-metric"; + -+ if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) ++ if (uprefs_getBCP47Tag(languageBuffer, ARRAY_SIZE, &status) != 51) + { + errln("Expected length to be 51, but got: %d\n", uprv_strlen(languageBuffer)); + } -+ if (uprv_strcmp(expectedValue, languageBuffer) != 0) ++ if (uprv_strcmp(expectedValue, languageBuffer) != 0) + { + errln("Expected BCP47Tag to be %s, but got: %s\n", expectedValue, languageBuffer); + } @@ -1262,7 +1259,7 @@ index 0000000000000000000000000000000000000000..f76997c66c45a694398c62ed23e94d0d \ No newline at end of file diff --git a/icu/icu4c/source/test/intltest/uprefstest.h b/icu/icu4c/source/test/intltest/uprefstest.h new file mode 100644 -index 0000000000000000000000000000000000000000..d87452e6bbde65a03df43d549e01abd3890c557c +index 0000000000000000000000000000000000000000..2f3e6515b060f962bc6afd4731aaf0033c062852 --- /dev/null +++ b/icu/icu4c/source/test/intltest/uprefstest.h @@ -0,0 +1,50 @@ diff --git a/icu-patches/patches/022-MSFT-Patch-ICU_keep_generated_test_and_shell_artifacts_LF_only.patch b/icu-patches/patches/022-MSFT-Patch-ICU_keep_generated_test_and_shell_artifacts_LF_only.patch new file mode 100644 index 00000000000..919badbd3d1 --- /dev/null +++ b/icu-patches/patches/022-MSFT-Patch-ICU_keep_generated_test_and_shell_artifacts_LF_only.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Arvind Oruganti +Date: Tue, 19 May 2026 06:45:00 +0530 +Subject: MSFT-PATCH: Keep generated ICU test and shell artifacts LF-only + +Adds checkout EOL rules for byte-compared codepoint trie TOML goldens and generated icu-config shell fragments. + +These files are consumed by Linux/WSL test paths, where CRLF checkout breaks byte comparisons or executable shell-script behavior. + +diff --git a/.gitattributes b/.gitattributes +index e7e0adbc65558ba2cc97a1d29a2a9a0aa378410b..976273bf156cbeb81e0ab0f5b8db4173fa46a1eb 100644 +--- a/.gitattributes ++++ b/.gitattributes +@@ -87,3 +87,12 @@ configure text + # Use JSONC for syntax highlighting on GitHub.com + *.json linguist-language=jsonc + ++# Codepoint trie golden tests compare bytes; keep generated TOML line endings stable. ++icu/icu4c/source/test/testdata/codepointtrie/*.toml text eol=lf ++ ++# Shell script fragments assembled into icu-config (an executable shell script). ++# They must have LF line endings so WSL/Linux can execute the generated file. ++icu/icu4c/source/config/icu-config-top text eol=lf ++icu/icu4c/source/config/icu-config-bottom text eol=lf ++icu/icu4c/source/config/mh-* text eol=lf ++ From 1206b84d29a4725b8154815b18a27c7bfed38ca8 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Tue, 19 May 2026 09:01:50 +0530 Subject: [PATCH 24/26] Add ICU 78 dev report Add the generated development review report for the ICU 78 / CLDR 48 upgrade. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit ffcf7f37f133ba04be1d1296c6ec0dbc424c39df) --- icu-patches/dev_report.md | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 icu-patches/dev_report.md diff --git a/icu-patches/dev_report.md b/icu-patches/dev_report.md new file mode 100644 index 00000000000..b17d2a5e1db --- /dev/null +++ b/icu-patches/dev_report.md @@ -0,0 +1,71 @@ +# ICU Upgrade Dev Report + +Generated: 2026-05-19 09:01:27 + +## 1. Version Summary + +| Field | Value | +|-------|-------| +| ICU Version | 78.3.0.0 | +| Upstream Hash | `21d1eb0f30...` | + +## 2. Source Changes + +Diff from `icu72-pre-swap` to HEAD (icu/ directory only): + +``` + 6919 files changed, 693820 insertions(+), 545058 deletions(-) +``` + +### Top file types changed + +| Extension | Count | +|-----------|-------| +| .txt | 5117 | +| .cpp | 799 | +| .h | 552 | +| .c | 105 | +| .vcxproj | 77 | +| .json | 46 | +| .filters | 30 | +| .xml | 29 | +| .java | 28 | +| .in | 25 | + +## 3. Patch Audit Results + +*No audit report found in `icu-patches`. Final patch records are summarized from `icu-patches/patches` instead.* + +- Latest patch-record commit: `aebb85791c4 Refresh ICU 78 patch records` +- Patch files present: 19 +- Refreshed ICU 78 patch records: `002`, `017`, `018`, `020`, `022` +- Validation used for refreshed records: `git apply --cached --check --reverse` against the final ICU index + +## 4. Build Results + +| Config | Status | Log | +|--------|--------|-----| +| Debug-ARM64 | ✅ PASS | build-Debug-ARM64.log | +| Debug-Win32 | ✅ PASS | build-Debug-Win32.log | +| Debug-x64 | ✅ PASS | build-Debug-x64.log | +| Release-ARM64 | ✅ PASS | build-Release-ARM64.log | +| Release-Win32 | ✅ PASS | build-Release-Win32.log | +| Release-x64 | ✅ PASS | build-Release-x64.log | + +## 5. Test Results + +| Suite | Status | Log | +|-------|--------|-----| +| cintltst-Release-x64 | ✅ PASS | test-cintltst-Release-x64.log | +| intlRelease-x64 | ✅ PASS | test-intltest-Release-x64.log | +| ioRelease-x64 | ✅ PASS | test-iotest-Release-x64.log | + +## 6. Action Items + +- [x] Patch conflicts resolved and ICU 78 patch records refreshed +- [x] CLDR data rebuild consumed by ICU data generation +- [x] Timezone data check/regeneration completed +- [x] Full Stage 8 build/test pass completed +- [x] Refreshed dev report generated +- [ ] Create PR/PR stack (owner-handled) + From 423a0c7e438ff71a1d4d7abdf5805ca7496c4958 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Tue, 19 May 2026 14:01:01 +0530 Subject: [PATCH 25/26] Refresh patch record for Saudi Riyal symbol override Add patch 023 to record the ar-SA SAR symbol override and its regression test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 02de184d88437798a0e6c5efaee187e81ac2b240) --- ...CU_override_ar-SA_Saudi_Riyal_symbol.patch | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 icu-patches/patches/023-MSFT-Patch_ICU_override_ar-SA_Saudi_Riyal_symbol.patch diff --git a/icu-patches/patches/023-MSFT-Patch_ICU_override_ar-SA_Saudi_Riyal_symbol.patch b/icu-patches/patches/023-MSFT-Patch_ICU_override_ar-SA_Saudi_Riyal_symbol.patch new file mode 100644 index 00000000000..43e0fdf7563 --- /dev/null +++ b/icu-patches/patches/023-MSFT-Patch_ICU_override_ar-SA_Saudi_Riyal_symbol.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Arvind Oruganti +Date: Tue, 19 May 2026 13:59:57 +0530 +Subject: MSFT-PATCH: Override ar-SA Saudi Riyal symbol + +Use the Unicode U+20C1 SAUDI RIYAL SIGN for the ar-SA SAR currency symbol and add a C API regression test for the locale-specific override. + +Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> + +diff --git a/icu/icu4c/source/data/curr/ar_SA.txt b/icu/icu4c/source/data/curr/ar_SA.txt +index 32526c8458fe1a225180d35019a84f4ea40603fe..2d969daeb3b8debcb9321dbff9598db33b673f82 100644 +--- a/icu/icu4c/source/data/curr/ar_SA.txt ++++ b/icu/icu4c/source/data/curr/ar_SA.txt +@@ -1,9 +1,11 @@ + // © 2016 and later: Unicode, Inc. and others. + // License & terms of use: http://www.unicode.org/copyright.html + // Generated using tools/cldr/cldr-to-icu/ +-/** +- * generated alias target +- */ + ar_SA{ +- ___{""} ++ Currencies{ ++ SAR{ ++ "⃁", ++ "ريال سعودي", ++ } ++ } + } +diff --git a/icu/icu4c/source/test/cintltst/currtest.c b/icu/icu4c/source/test/cintltst/currtest.c +index d8355133a18bf24410a3a99eed8b27f2657b0d76..51dff0eb0b33653ae0e9d53bf4ceeb5677d50d4c 100644 +--- a/icu/icu4c/source/test/cintltst/currtest.c ++++ b/icu/icu4c/source/test/cintltst/currtest.c +@@ -298,6 +298,26 @@ static void TestNumericCode(void) { + } + } + ++static void TestSaudiRiyalSymbol(void) { ++ UErrorCode status = U_ZERO_ERROR; ++ UChar currency[4]; ++ UBool isChoiceFormat = false; ++ int32_t len = 0; ++ static const UChar expectedSymbol[] = {0x20C1, 0}; ++ const UChar* symbol; ++ ++ u_charsToUChars("SAR", currency, UPRV_LENGTHOF(currency)); ++ symbol = ucurr_getName(currency, "ar_SA", UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &status); ++ if (U_FAILURE(status)) { ++ log_data_err("Error: ucurr_getName returned %s (Are you missing data?)\n", u_errorName(status)); ++ return; ++ } ++ if (isChoiceFormat || len != 1 || symbol == NULL || u_strncmp(symbol, expectedSymbol, len) != 0) { ++ log_err("Error: SAR symbol for ar_SA should be U+20C1. Got length=%d first=U+%04X choice=%s\n", ++ len, (len > 0 && symbol != NULL) ? symbol[0] : 0, isChoiceFormat ? "true" : "false"); ++ } ++} ++ + void addCurrencyTest(TestNode** root); + + #define TESTCASE(x) addTest(root, &x, "tsformat/currtest/" #x) +@@ -310,6 +330,7 @@ void addCurrencyTest(TestNode** root) + TESTCASE(TestFractionDigitOverride); + TESTCASE(TestPrefixSuffix); + TESTCASE(TestNumericCode); ++ TESTCASE(TestSaudiRiyalSymbol); + } + + #endif /* #if !UCONFIG_NO_FORMATTING */ From f97e193c23e4f66155334bb6c6f4ca797b03b9d7 Mon Sep 17 00:00:00 2001 From: Arvind Oruganti Date: Tue, 19 May 2026 14:01:20 +0530 Subject: [PATCH 26/26] Update dev report for Saudi Riyal override Record patch 023 and the targeted validation for the ar-SA SAR symbol override. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 8ca3dcb345b6377b33d7f062f5c321ef4a53df30) --- icu-patches/dev_report.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/icu-patches/dev_report.md b/icu-patches/dev_report.md index b17d2a5e1db..db822262450 100644 --- a/icu-patches/dev_report.md +++ b/icu-patches/dev_report.md @@ -36,9 +36,9 @@ Diff from `icu72-pre-swap` to HEAD (icu/ directory only): *No audit report found in `icu-patches`. Final patch records are summarized from `icu-patches/patches` instead.* -- Latest patch-record commit: `aebb85791c4 Refresh ICU 78 patch records` -- Patch files present: 19 -- Refreshed ICU 78 patch records: `002`, `017`, `018`, `020`, `022` +- Latest patch-record commit: `70ae0ef8eab Refresh patch record for Saudi Riyal symbol override` +- Patch files present: 20 +- Refreshed ICU 78 patch records: `002`, `017`, `018`, `020`, `022`, `023` - Validation used for refreshed records: `git apply --cached --check --reverse` against the final ICU index ## 4. Build Results @@ -60,9 +60,12 @@ Diff from `icu72-pre-swap` to HEAD (icu/ directory only): | intlRelease-x64 | ✅ PASS | test-intltest-Release-x64.log | | ioRelease-x64 | ✅ PASS | test-iotest-Release-x64.log | +Post-report targeted validation for patch `023`: `genrb` parsed `icu/icu4c/source/data/curr/ar_SA.txt`, and `currtest.c` passed C syntax checking with the available compiler. + ## 6. Action Items - [x] Patch conflicts resolved and ICU 78 patch records refreshed +- [x] Saudi Riyal symbol override for `ar_SA` added and recorded as patch `023` - [x] CLDR data rebuild consumed by ICU data generation - [x] Timezone data check/regeneration completed - [x] Full Stage 8 build/test pass completed