using Flowery.Localization;var codes = FloweryLocalization.SupportedLanguages;var current = FloweryLocalization.CurrentCultureName;for (var i = 0; i < codes.Count; i++){ var code = codes[i]; if (FloweryLocalization.LanguageDisplayNames.TryGetValue(code, out var name)) { // Use code and name in your UI }}
FloweryLocalization.SetCulture raises PropertyChanged on the UI thread via DispatcherQueue. Most Uno heads refresh indexer bindings automatically.If you still see stale values on Desktop/Skia, force a rebinding:
LOCALIZATION.md:91-99
// In your page/control that uses {Binding [Key]} with a Localization DataContext.Loaded += (_, _) => FloweryLocalization.CultureChanged += OnCultureChanged;Unloaded += (_, _) => FloweryLocalization.CultureChanged -= OnCultureChanged;private void OnCultureChanged(object? sender, string cultureName){ RootElement.DataContext = null; RootElement.DataContext = Localization;}
Create a localization class that loads from embedded JSON:
LOCALIZATION.md:185-266
using System;using System.Collections.Generic;using System.ComponentModel;using System.Globalization;using System.IO;using System.Reflection;using System.Text.Json;using System.Text.Json.Serialization;public class MyAppLocalization : INotifyPropertyChanged{ private static CultureInfo _currentCulture = CultureInfo.CurrentUICulture; private static readonly Dictionary<string, Dictionary<string, string>> _translations = new(); private static readonly Lazy<MyAppLocalization> _instance = new(() => new MyAppLocalization()); public static MyAppLocalization Instance => _instance.Value; public static event EventHandler<CultureInfo>? CultureChanged; public event PropertyChangedEventHandler? PropertyChanged; static MyAppLocalization() { // Load all translations at startup - use library's centralized list foreach (var lang in Flowery.Localization.FloweryLocalization.SupportedLanguages) LoadTranslation(lang); // Sync with Flowery library culture changes Flowery.Localization.FloweryLocalization.CultureChanged += (s, c) => SetCulture(c); } // Indexer for XAML binding public string this[string key] => GetString(key); public static void SetCulture(CultureInfo culture) { if (_currentCulture.Name == culture.Name) return; _currentCulture = culture; CultureChanged?.Invoke(null, culture); Instance.PropertyChanged?.Invoke(Instance, new PropertyChangedEventArgs("Item")); Instance.PropertyChanged?.Invoke(Instance, new PropertyChangedEventArgs("Item[]")); } public static string GetString(string key) { // Try exact culture (e.g., "de-DE") if (_translations.TryGetValue(_currentCulture.Name, out var exact) && exact.TryGetValue(key, out var v1)) return v1; // Try language only (e.g., "de") var lang = _currentCulture.TwoLetterISOLanguageName; if (_translations.TryGetValue(lang, out var langDict) && langDict.TryGetValue(key, out var v2)) return v2; // Fallback to English if (_translations.TryGetValue("en", out var en) && en.TryGetValue(key, out var v3)) return v3; return key; // Return key if not found } private static void LoadTranslation(string langCode) { var assembly = Assembly.GetExecutingAssembly(); var resourceName = $"YourApp.Localization.{langCode}.json"; using var stream = assembly.GetManifestResourceStream(resourceName); if (stream == null) return; using var reader = new StreamReader(stream); var json = reader.ReadToEnd(); // Use source generator for AOT compatibility var dict = JsonSerializer.Deserialize(json, LocalizationJsonContext.Default.DictionaryStringString); if (dict != null) _translations[langCode] = dict; }}// REQUIRED: JSON Source Generator for AOT/WASM compatibility[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)][JsonSerializable(typeof(Dictionary<string, string>))]internal partial class LocalizationJsonContext : JsonSerializerContext { }
The JsonSerializerContext source generator is required for WASM. Without it, you will get JsonSerializerIsReflectionDisabled errors.
<Application.Resources> <FontFamily x:Key="NotoSansFamily">ms-appx:///Assets/Fonts/NotoSansJP-Regular.otf#Noto Sans JP</FontFamily></Application.Resources>
Apply font to all text-displaying controls in App.xaml
JsonSerializerIsReflectionDisabled error
Cause: WASM has Native AOT which disables reflection.Fix: Add a JsonSerializerContext source generator (see Step 3 above).
Bindings don't update after SetCulture
Cause: Desktop/Skia doesn’t always refresh indexer bindings.Fix: Force rebinding by setting DataContext to null then back to Localization in the CultureChanged handler.