diff --git a/package-lock.json b/package-lock.json index 79bb6043e2..16749b7bed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -243,24 +243,6 @@ } } }, - "node_modules/@angular-devkit/architect/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/architect/node_modules/jsonc-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", @@ -281,22 +263,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@angular-devkit/architect/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/architect/node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", diff --git a/packages/core/platforms/android/widgets-release.aar b/packages/core/platforms/android/widgets-release.aar index 9e25101e0d..4fd60d4bd8 100644 Binary files a/packages/core/platforms/android/widgets-release.aar and b/packages/core/platforms/android/widgets-release.aar differ diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index 425aa9bb20..335c7d726b 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -572,24 +572,20 @@ export class TextBase extends TextBaseCommon { } } -function getCapitalizedString(str: string): string { - let newString = str.toLowerCase(); - newString = newString.replace(/(?:^|\s'*|[-"([{])+\S/g, (c) => c.toUpperCase()); - return newString; -} - export function getTransformedText(text: string, textTransform: CoreTypes.TextTransformType): string { if (!text || !isString(text)) { return ''; } + // Use the java string methods to get localized transformations. + // This will respect the locale set by native apis or the localize plugins. switch (textTransform) { case 'uppercase': - return text.toUpperCase(); + return org.nativescript.widgets.Utils.stringToUpperCase(text); case 'lowercase': - return text.toLowerCase(); + return org.nativescript.widgets.Utils.stringToLowerCase(text); case 'capitalize': - return getCapitalizedString(text); + return org.nativescript.widgets.Utils.capitalizeString(text); case 'none': default: return text; diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 310ac2342b..10dce7f020 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -488,13 +488,15 @@ export function getTransformedText(text: string, textTransform: CoreTypes.TextTr return ''; } + // Use the NSString localized properties to get localized transformations. + // This will respect the locale set by native apis or the localize plugins. switch (textTransform) { case 'uppercase': - return NSStringFromNSAttributedString(text).uppercaseString; + return NSStringFromNSAttributedString(text).localizedUppercaseString; case 'lowercase': - return NSStringFromNSAttributedString(text).lowercaseString; + return NSStringFromNSAttributedString(text).localizedLowercaseString; case 'capitalize': - return NSStringFromNSAttributedString(text).capitalizedString; + return NSStringFromNSAttributedString(text).localizedCapitalizedString; default: return text; } diff --git a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts index 72cf1d8d49..00f9cc71bd 100644 --- a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts +++ b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts @@ -785,6 +785,9 @@ declare module org { public static enableEdgeToEdge(activity: androidx.activity.ComponentActivity, statusBarLight: java.lang.Integer, statusBarDark: java.lang.Integer, navigationBarLight: java.lang.Integer, navigationBarDark: java.lang.Integer, handleDarkMode: org.nativescript.widgets.Utils.HandleDarkMode): void; public static enableEdgeToEdge(activity: androidx.activity.ComponentActivity, window: android.view.Window, handleDarkMode: org.nativescript.widgets.Utils.HandleDarkMode): void; public static enableEdgeToEdge(activity: androidx.activity.ComponentActivity, window: android.view.Window): void; + public static stringToUpperCase(value: string): string; + public static stringToLowerCase(value: string): string; + public static capitalizeString(value: string): string; public static ignoreEdgeToEdgeOnOlderDevices: boolean; public constructor(); } diff --git a/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java b/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java index 503709ed19..6b0a780a37 100644 --- a/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java +++ b/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java @@ -46,6 +46,7 @@ import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Locale; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -727,6 +728,42 @@ public void run() { }); } + public static String stringToUpperCase(final String value) { + if (value == null || value.isEmpty()) { + return value; + } + return value.toUpperCase(Locale.getDefault()); + } + + public static String stringToLowerCase(final String value) { + if (value == null || value.isEmpty()) { + return value; + } + return value.toLowerCase(Locale.getDefault()); + } + + public static String capitalizeString(final String value) { + if (value == null || value.isEmpty()) { + return value; + } + + final char[] buffer = value.toLowerCase(Locale.getDefault()).toCharArray(); + boolean capitalizeNext = true; + + for (int i = 0; i < buffer.length; i++) { + final char ch = buffer[i]; + + // Capitalize characters when located after numbers, whitespace, and punctuation marks but not apostrophe + if (!Character.isLetter(ch) && ch != '\'') { + capitalizeNext = true; + } else if (capitalizeNext) { + buffer[i] = Character.toTitleCase(ch); + capitalizeNext = false; + } + } + return new String(buffer); + } + /** * Return true if child is a descendant of parent, (or equal to the parent). */