Skip to content

Commit acc137a

Browse files
CopilotSuthiYuvaraj
andcommitted
Fix culture change detection to work automatically without manual triggers
Co-authored-by: SuthiYuvaraj <92777079+SuthiYuvaraj@users.noreply.github.com>
1 parent 758dfd3 commit acc137a

File tree

5 files changed

+76
-10
lines changed

5 files changed

+76
-10
lines changed

src/Core/src/CultureTracker.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Globalization;
4+
using System.Threading;
45

56
namespace Microsoft.Maui
67
{
@@ -11,6 +12,8 @@ internal static class CultureTracker
1112
{
1213
static CultureInfo? s_currentCulture;
1314
static readonly ConcurrentDictionary<WeakReference, Action> s_subscribers = new();
15+
static Timer? s_cultureCheckTimer;
16+
static readonly object s_lockObject = new();
1417

1518
/// <summary>
1619
/// Checks if the culture has changed since the last call and notifies subscribers if it has.
@@ -35,6 +38,19 @@ public static void Subscribe(object subscriber, Action action)
3538
{
3639
var weakRef = new WeakReference(subscriber);
3740
s_subscribers.TryAdd(weakRef, action);
41+
42+
// Start monitoring when first subscriber is added
43+
lock (s_lockObject)
44+
{
45+
if (s_cultureCheckTimer == null && s_subscribers.Count > 0)
46+
{
47+
// Initialize current culture if not set
48+
s_currentCulture = CultureInfo.CurrentCulture;
49+
50+
// Check for culture changes every 100ms when there are subscribers
51+
s_cultureCheckTimer = new Timer(OnTimerTick, null, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100));
52+
}
53+
}
3854
}
3955

4056
/// <summary>
@@ -52,6 +68,21 @@ public static void Unsubscribe(object subscriber)
5268
break;
5369
}
5470
}
71+
72+
// Stop monitoring when no subscribers remain
73+
lock (s_lockObject)
74+
{
75+
if (s_subscribers.Count == 0 && s_cultureCheckTimer != null)
76+
{
77+
s_cultureCheckTimer.Dispose();
78+
s_cultureCheckTimer = null;
79+
}
80+
}
81+
}
82+
83+
static void OnTimerTick(object? state)
84+
{
85+
CheckForCultureChanges();
5586
}
5687

5788
static void NotifyCultureChanged()
@@ -83,6 +114,16 @@ static void NotifyCultureChanged()
83114
{
84115
s_subscribers.TryRemove(deadRef, out _);
85116
}
117+
118+
// Stop monitoring if all references are dead
119+
lock (s_lockObject)
120+
{
121+
if (s_subscribers.Count == 0 && s_cultureCheckTimer != null)
122+
{
123+
s_cultureCheckTimer.Dispose();
124+
s_cultureCheckTimer = null;
125+
}
126+
}
86127
}
87128
}
88129
}

src/Core/src/Platform/Android/DatePickerExtensions.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ public static void UpdateMaximumDate(this MauiDatePicker platformDatePicker, IDa
5555

5656
internal static void SetText(this MauiDatePicker platformDatePicker, IDatePicker datePicker)
5757
{
58-
// Check for culture changes before updating
59-
CultureTracker.CheckForCultureChanges();
60-
6158
platformDatePicker.Text = datePicker.Date.ToString(datePicker.Format);
6259
}
6360
}

src/Core/src/Platform/Windows/DatePickerExtensions.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ public static class DatePickerExtensions
99
{
1010
public static void UpdateDate(this CalendarDatePicker platformDatePicker, IDatePicker datePicker)
1111
{
12-
// Check for culture changes before updating
13-
CultureTracker.CheckForCultureChanges();
14-
1512
var date = datePicker.Date;
1613
platformDatePicker.UpdateDate(date);
1714

src/Core/src/Platform/iOS/DatePickerExtensions.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,6 @@ public static void UpdateDate(this UIDatePicker picker, IDatePicker datePicker)
5656

5757
public static void UpdateDate(this MauiDatePicker platformDatePicker, IDatePicker datePicker, UIDatePicker? picker)
5858
{
59-
// Check for culture changes before updating
60-
CultureTracker.CheckForCultureChanges();
61-
6259
if (picker != null && picker.Date.ToDateTime().Date != datePicker.Date.Date)
6360
picker.SetDate(datePicker.Date.ToNSDate(), false);
6461

src/Core/tests/UnitTests/Views/DatePickerCultureTests.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Globalization;
3+
using System.Threading;
34
using Microsoft.Maui.Controls;
45
using Xunit;
56

@@ -31,7 +32,9 @@ public void DatePickerCultureTrackerSubscription()
3132
try
3233
{
3334
CultureInfo.CurrentCulture = new CultureInfo("de-DE");
34-
CultureTracker.CheckForCultureChanges();
35+
36+
// Wait a bit for the timer to detect the change (max 200ms)
37+
Thread.Sleep(250);
3538

3639
Assert.True(called);
3740
}
@@ -42,6 +45,37 @@ public void DatePickerCultureTrackerSubscription()
4245
}
4346
}
4447

48+
[Fact]
49+
public void DatePickerCultureTrackerAutoDetection()
50+
{
51+
var callCount = 0;
52+
var subscriber = new object();
53+
54+
CultureTracker.Subscribe(subscriber, () => callCount++);
55+
56+
var originalCulture = CultureInfo.CurrentCulture;
57+
try
58+
{
59+
// Change culture multiple times
60+
CultureInfo.CurrentCulture = new CultureInfo("de-DE");
61+
Thread.Sleep(150); // Allow detection
62+
63+
CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
64+
Thread.Sleep(150); // Allow detection
65+
66+
CultureInfo.CurrentCulture = new CultureInfo("ja-JP");
67+
Thread.Sleep(150); // Allow detection
68+
69+
// Should have detected at least 3 culture changes
70+
Assert.True(callCount >= 3, $"Expected at least 3 culture changes, but got {callCount}");
71+
}
72+
finally
73+
{
74+
CultureInfo.CurrentCulture = originalCulture;
75+
CultureTracker.Unsubscribe(subscriber);
76+
}
77+
}
78+
4579
[Theory]
4680
[InlineData("en-US", "d")]
4781
[InlineData("de-DE", "d")]

0 commit comments

Comments
 (0)