Add locale-sensitive casing (#880)
* Add locale-sensitive casing
* Add changelog
* Add default_components to built libs
* Use casemap key instead
* Trigger on labeling
diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml
index d8c34d4..e29594d 100644
--- a/.github/workflows/intl4x.yml
+++ b/.github/workflows/intl4x.yml
@@ -6,6 +6,7 @@
on:
pull_request:
branches: [main]
+ types: [opened, synchronize, reopened, labeled, unlabeled]
paths:
- ".github/workflows/intl4x.yml"
- "pkgs/intl4x/**"
@@ -293,21 +294,21 @@
run: |
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_x64 --os linux --architecture x64 --compile_type dynamic --cargo_features collator,datetime,list,decimal,plurals,experimental,compiled_data
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_x64 --os linux --architecture x64 --compile_type dynamic --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental,compiled_data
- name: Build Mac
if: matrix.os == 'macos-latest'
run: |
rustup component add rust-src --toolchain nightly-aarch64-apple-darwin
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/macos_arm64 --os macos --architecture arm64 --compile_type dynamic --cargo_features collator,datetime,list,decimal,plurals,experimental,compiled_data
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/macos_arm64 --os macos --architecture arm64 --compile_type dynamic --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental,compiled_data
- name: Build Windows
if: matrix.os == 'windows-latest'
run: |
rustup component add rust-src --toolchain nightly-x86_64-pc-windows-msvc
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_x64 --os windows --architecture x64 --compile_type dynamic --cargo_features collator,datetime,list,decimal,plurals,experimental,compiled_data
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_x64 --os windows --architecture x64 --compile_type dynamic --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental,compiled_data
- name: Run `dart pub get`
run: |
diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml
index 8e7d610..9947c7e 100644
--- a/.github/workflows/intl4x_artifacts.yml
+++ b/.github/workflows/intl4x_artifacts.yml
@@ -73,14 +73,14 @@
mkdir submodules/icu4x/bin
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_arm_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture arm --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_ia32_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture ia32 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_arm_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture arm --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_riscv64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture riscv64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_arm_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture arm --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_ia32_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture ia32 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/android_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os android --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_arm_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture arm --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_riscv64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture riscv64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/linux_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os linux --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
- name: Build Linux data
if: matrix.os == 'ubuntu-latest' && matrix.compiletype == 'static' && matrix.include_data == false
@@ -111,10 +111,10 @@
mkdir submodules/icu4x/bin
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/ios_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os ios --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/ios_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os ios --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/macos_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os macos --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/macos_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os macos --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/ios_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os ios --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/ios_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os ios --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/macos_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os macos --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/macos_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os macos --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
- name: Build Mac data
if: matrix.os == 'macos-latest' && matrix.compiletype == 'static' && matrix.include_data == false
@@ -140,9 +140,9 @@
mkdir submodules/icu4x/bin
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os windows --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_ia32_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os windows --architecture ia32 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
- dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os windows --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_arm64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os windows --architecture arm64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_ia32_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os windows --architecture ia32 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
+ dart pkgs/intl4x/lib/src/hook_helpers/build_libs.g.dart --working_directory submodules/icu4x --file submodules/icu4x/bin/windows_x64_${{ matrix.compiletype }}${{ env.FILENAME_SUFFIX }} --os windows --architecture x64 --compile_type ${{ matrix.compiletype }} --cargo_features collator,datetime,list,decimal,plurals,casemap,experimental${{ env.DATA }}
- name: Build Windows data
if: matrix.os == 'windows-latest' && matrix.compiletype == 'static' && matrix.include_data == false
diff --git a/pkgs/intl4x/CHANGELOG.md b/pkgs/intl4x/CHANGELOG.md
index 6ab96d2..6065f6b 100644
--- a/pkgs/intl4x/CHANGELOG.md
+++ b/pkgs/intl4x/CHANGELOG.md
@@ -1,7 +1,11 @@
+## 0.12.2-wip
+
+- Add lower- and uppercasing.
+
## 0.12.1
- Use new artifacts from `intl4x-icu-v.0.12.0-artifacts`.
-
+
## 0.12.0
- Update to ICU4X 2.0.
diff --git a/pkgs/intl4x/hook/build.dart b/pkgs/intl4x/hook/build.dart
index 08b1a41..b137cad 100644
--- a/pkgs/intl4x/hook/build.dart
+++ b/pkgs/intl4x/hook/build.dart
@@ -215,7 +215,7 @@
'plurals',
'buffer_provider',
'experimental',
- 'default_components',
+ 'casemap',
'compiled_data',
],
);
diff --git a/pkgs/intl4x/lib/case_mapping.dart b/pkgs/intl4x/lib/case_mapping.dart
new file mode 100644
index 0000000..9853c6b
--- /dev/null
+++ b/pkgs/intl4x/lib/case_mapping.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'intl4x.dart';
+
+export 'src/case_mapping/case_mapping.dart';
+export 'src/locale/locale.dart';
+
+extension CaseMappingWithIntl4X on String {
+ String toLocaleLowerCase(Locale locale) =>
+ Intl(locale: locale).caseMapping.toLowerCase(this);
+ String toLocaleUpperCase(Locale locale) =>
+ Intl(locale: locale).caseMapping.toUpperCase(this);
+}
diff --git a/pkgs/intl4x/lib/intl4x.dart b/pkgs/intl4x/lib/intl4x.dart
index 106c83d..c3e9058 100644
--- a/pkgs/intl4x/lib/intl4x.dart
+++ b/pkgs/intl4x/lib/intl4x.dart
@@ -2,9 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'case_mapping.dart';
import 'collation.dart';
import 'display_names.dart';
import 'number_format.dart';
+import 'src/case_mapping/case_mapping_impl.dart';
import 'src/collation/collation.dart';
import 'src/collation/collation_impl.dart';
import 'src/datetime_format/datetime_format.dart';
@@ -18,7 +20,6 @@
import 'src/list_format/list_format.dart';
import 'src/list_format/list_format_impl.dart';
import 'src/list_format/list_format_options.dart';
-import 'src/locale/locale.dart';
import 'src/number_format/number_format.dart';
import 'src/number_format/number_format_impl.dart';
import 'src/plural_rules/plural_rules.dart';
@@ -88,6 +89,9 @@
),
);
+ CaseMapping get caseMapping =>
+ CaseMapping(CaseMappingImpl.build(locale, localeMatcher, ecmaPolicy));
+
/// Construct an [Intl] instance providing the current [locale] and the
/// [ecmaPolicy] defining which locales should fall back to the browser
/// provided functions.
diff --git a/pkgs/intl4x/lib/src/case_mapping/case_mapping.dart b/pkgs/intl4x/lib/src/case_mapping/case_mapping.dart
new file mode 100644
index 0000000..3f818fc
--- /dev/null
+++ b/pkgs/intl4x/lib/src/case_mapping/case_mapping.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../test_checker.dart';
+import 'case_mapping_impl.dart';
+
+/// A locale-sensitive case mapper for transforming strings.
+///
+/// This class provides methods to convert strings to lowercase or uppercase
+/// based on the current locale. During testing, the input is returned
+/// unchanged.
+class CaseMapping {
+ final CaseMappingImpl _caseMappingImpl;
+
+ const CaseMapping(this._caseMappingImpl);
+
+ String toLowerCase(String input) {
+ if (isInTest) {
+ return input;
+ } else {
+ return _caseMappingImpl.toLowerCase(input);
+ }
+ }
+
+ String toUpperCase(String input) {
+ if (isInTest) {
+ return input;
+ } else {
+ return _caseMappingImpl.toUpperCase(input);
+ }
+ }
+}
diff --git a/pkgs/intl4x/lib/src/case_mapping/case_mapping_4x.dart b/pkgs/intl4x/lib/src/case_mapping/case_mapping_4x.dart
new file mode 100644
index 0000000..fc17a56
--- /dev/null
+++ b/pkgs/intl4x/lib/src/case_mapping/case_mapping_4x.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../bindings/lib.g.dart' as icu;
+import '../locale/locale.dart';
+import '../locale/locale_4x.dart';
+import 'case_mapping_impl.dart';
+
+CaseMappingImpl getCaseMapping4X(Locale locale, Null _) =>
+ CaseMapping4X(locale as Locale4x);
+
+class CaseMapping4X extends CaseMappingImpl {
+ final icu.CaseMapper _caseMapper;
+ final Locale4x _locale;
+
+ CaseMapping4X(this._locale) : _caseMapper = icu.CaseMapper(), super(_locale);
+
+ @override
+ String toLowerCase(String input) =>
+ _caseMapper.lowercase(input, _locale.get4X);
+
+ @override
+ String toUpperCase(String input) =>
+ _caseMapper.uppercase(input, _locale.get4X);
+}
diff --git a/pkgs/intl4x/lib/src/case_mapping/case_mapping_ecma.dart b/pkgs/intl4x/lib/src/case_mapping/case_mapping_ecma.dart
new file mode 100644
index 0000000..75c1516
--- /dev/null
+++ b/pkgs/intl4x/lib/src/case_mapping/case_mapping_ecma.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:js_interop';
+
+import '../locale/locale.dart';
+import '../options.dart';
+import 'case_mapping_impl.dart';
+
+CaseMappingImpl? getCaseMappingECMA(Locale locale, Null _, LocaleMatcher _) =>
+ _CaseMappingECMA.tryToBuild(locale);
+
+extension on JSString {
+ @JS('String.toLocaleUpperCase')
+ external String toLocaleUpperCase(String locale);
+ @JS('String.toLocaleLowerCase')
+ external String toLocaleLowerCase(String locale);
+}
+
+class _CaseMappingECMA extends CaseMappingImpl {
+ _CaseMappingECMA(super.locale);
+
+ static CaseMappingImpl? tryToBuild(Locale locale) => _CaseMappingECMA(locale);
+ @override
+ String toUpperCase(String input) =>
+ input.toJS.toLocaleUpperCase(locale.toLanguageTag());
+
+ @override
+ String toLowerCase(String input) =>
+ input.toJS.toLocaleLowerCase(locale.toLanguageTag());
+}
diff --git a/pkgs/intl4x/lib/src/case_mapping/case_mapping_impl.dart b/pkgs/intl4x/lib/src/case_mapping/case_mapping_impl.dart
new file mode 100644
index 0000000..e62ea81
--- /dev/null
+++ b/pkgs/intl4x/lib/src/case_mapping/case_mapping_impl.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../../ecma_policy.dart';
+import '../ecma/ecma_policy.dart';
+import '../locale/locale.dart';
+import '../options.dart';
+import '../utils.dart';
+import 'case_mapping_stub.dart' if (dart.library.js) 'case_mapping_ecma.dart';
+import 'case_mapping_stub_4x.dart' if (dart.library.io) 'case_mapping_4x.dart';
+
+abstract class CaseMappingImpl {
+ final Locale locale;
+
+ CaseMappingImpl(this.locale);
+
+ String toLowerCase(String input);
+ String toUpperCase(String input);
+
+ static CaseMappingImpl build(
+ Locale locales,
+ LocaleMatcher localeMatcher,
+ EcmaPolicy ecmaPolicy,
+ ) => buildFormatter(
+ locales,
+ null,
+ localeMatcher,
+ ecmaPolicy,
+ getCaseMappingECMA,
+ getCaseMapping4X,
+ );
+}
diff --git a/pkgs/intl4x/lib/src/case_mapping/case_mapping_stub.dart b/pkgs/intl4x/lib/src/case_mapping/case_mapping_stub.dart
new file mode 100644
index 0000000..ac7a883
--- /dev/null
+++ b/pkgs/intl4x/lib/src/case_mapping/case_mapping_stub.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../locale/locale.dart';
+import '../options.dart';
+import 'case_mapping_impl.dart';
+
+CaseMappingImpl? getCaseMappingECMA(Locale locale, Null _, LocaleMatcher _) =>
+ throw UnimplementedError('Cannot use ECMA outside of web environments.');
diff --git a/pkgs/intl4x/lib/src/case_mapping/case_mapping_stub_4x.dart b/pkgs/intl4x/lib/src/case_mapping/case_mapping_stub_4x.dart
new file mode 100644
index 0000000..38d5f42
--- /dev/null
+++ b/pkgs/intl4x/lib/src/case_mapping/case_mapping_stub_4x.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../locale/locale.dart';
+import 'case_mapping_impl.dart';
+
+CaseMappingImpl getCaseMapping4X(Locale locale, Null _) =>
+ throw UnimplementedError('Cannot use ICU4X in web environments.');
diff --git a/pkgs/intl4x/pubspec.yaml b/pkgs/intl4x/pubspec.yaml
index 7f314c1..aa2c39f 100644
--- a/pkgs/intl4x/pubspec.yaml
+++ b/pkgs/intl4x/pubspec.yaml
@@ -1,7 +1,7 @@
name: intl4x
description: >-
A lightweight modular library for internationalization (i18n) functionality.
-version: 0.12.1
+version: 0.12.2-wip
repository: https://github.com/dart-lang/i18n/tree/main/pkgs/intl4x
issue_tracker: https://github.com/dart-lang/i18n/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aintl4x
diff --git a/pkgs/intl4x/test/case_mapping_test.dart b/pkgs/intl4x/test/case_mapping_test.dart
new file mode 100644
index 0000000..1dc6c41
--- /dev/null
+++ b/pkgs/intl4x/test/case_mapping_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:intl4x/case_mapping.dart';
+import 'package:test/test.dart';
+
+import 'utils.dart';
+
+void main() {
+ testWithFormatting('test name', () {
+ final enUS = Locale.parse('en-US');
+ final trTR = Locale.parse('tr-TR');
+ final ltLT = Locale.parse('lt-LT');
+
+ expect('İstanbul'.toLocaleLowerCase(enUS), 'i̇stanbul');
+ expect('İstanbul'.toLocaleLowerCase(trTR), 'istanbul');
+ expect('ALPHABET'.toLocaleLowerCase(enUS), 'alphabet');
+
+ expect('\u0130'.toLocaleLowerCase(Locale.parse('tr')), 'i');
+ expect('\u0130'.toLocaleLowerCase(enUS), isNot('i'));
+
+ final locales = [
+ 'tr',
+ 'TR',
+ 'tr-TR',
+ 'tr-u-co-search',
+ 'tr-x-turkish',
+ ].map(Locale.parse);
+ for (final locale in locales) {
+ expect('\u0130'.toLocaleLowerCase(locale), 'i');
+ }
+
+ // --- Lithuanian Testing ---
+ // Here, 'I' should lowercase to 'i' and 'i' should uppercase to 'I'.
+ // The dotless 'i' (U+0131) and dotted 'I' (U+0130) are not typically used
+ // in standard Lithuanian orthography in the same way as Turkish.
+ // So, we expect standard Unicode casing behavior.
+
+ expect('Lietuva'.toLocaleLowerCase(ltLT), 'lietuva');
+ expect('lietuva'.toLocaleUpperCase(ltLT), 'LIETUVA');
+
+ // Test a common character that might have locale-specific casing rules
+ // in other languages but should be standard in Lithuanian.
+ expect('Ė'.toLocaleLowerCase(ltLT), 'ė'); // Ė (U+0116) to ė (U+0117)
+ expect('ė'.toLocaleUpperCase(ltLT), 'Ė');
+
+ // Ensure that Turkish-specific behavior does NOT apply to Lithuanian
+ expect(
+ '\u0130'.toLocaleLowerCase(ltLT),
+ '\u0130'.toLocaleLowerCase(enUS),
+ ); // Dotted I should behave like in English
+ expect('I'.toLocaleLowerCase(ltLT), 'i'); // Regular I to i
+ expect('i'.toLocaleUpperCase(ltLT), 'I'); // Regular i to I
+ });
+}