Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat artikel ini dalam versi .NET 10.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan Inti .NET dan .NET. Untuk rilis saat ini, lihat artikel ini dalam versi .NET 10.
Artikel ini menjelaskan cara merender konten global dan terlokalisasi kepada pengguna dalam budaya dan bahasa yang berbeda.
Globalisasi dan pelokalan
Untuk globalisasi, Blazor menyediakan pemformatan angka dan tanggal. Untuk lokalisasi, Blazor menyajikan konten menggunakan sistem Resources .NET.
Hanya sejumlah fitur pelokalan ASP.NET Core terbatas yang didukung.
Didukung:IStringLocalizer dan IStringLocalizer<T> didukung di Blazor aplikasi.
Tidak didukung:IHtmlLocalizer dan IViewLocalizer adalah fitur MVC ASP.NET Core dan tidak didukung di aplikasi Blazor.
Untuk Blazor aplikasi, pelokalan pesan validasi untuk validasi formulir menggunakan anotasi data didukung jika DisplayAttribute.ResourceType dan ValidationAttribute.ErrorMessageResourceType diimplementasikan.
Untuk Blazor aplikasi, pesan validasi yang dilokalkan untuk validasi formulir menggunakan anotasi data didukung melalui dua jalur:
- Jalur sumber daya statis menggunakan DisplayAttribute.ResourceType untuk nama tampilan dan ValidationAttribute.ErrorMessageResourceType untuk pesan kesalahan yang dilokalkan. Pendekatan ini didukung di setiap rilis.
- Paket
Microsoft.Extensions.Validation.Localization, yang menyelesaikan pesan validasi dan nama tampilan melalui IStringLocalizer. Tersedia untuk aplikasi Blazor yang mengaktifkan alur validasi baru menggunakanAddValidation(). Untuk detailnya, lihat Buat konten aplikasi ASP.NET Core dapat dilokalkan.
Artikel ini menjelaskan cara menggunakan Blazorfitur globalisasi dan pelokalan berdasarkan:
- Header
Accept-Language, yang diatur oleh browser berdasarkan preferensi bahasa pengguna di pengaturan browser. - Budaya yang ditetapkan oleh aplikasi tidak didasarkan pada nilai
Accept-Languageheader. Pengaturan dapat statis untuk semua pengguna atau dinamis berdasarkan logika aplikasi. Saat pengaturan didasarkan pada preferensi pengguna, pengaturan biasanya disimpan untuk dimuat ulang pada kunjungan mendatang.
Untuk informasi umum tambahan, lihat sumber daya berikut ini:
- Globalization dan pelokalan di ASP.NET Core
- .NET Fundamentals: Globalisasi
- .NET Dasar-Dasar: Pelokalan
Seringkali, istilah bahasa dan budaya digunakan secara bergantian ketika berhadapan dengan konsep globalisasi dan pelokalan.
Dalam artikel ini, bahasa mengacu pada pilihan yang dibuat oleh pengguna di pengaturan browser mereka. Pilihan bahasa pengguna dikirimkan dalam permintaan browser di Accept-Language header. Pengaturan browser biasanya menggunakan kata "bahasa" di UI.
Culture berkaitan dengan anggota API .NET dan Blazor. Misalnya, permintaan pengguna dapat menyertakan Accept-Language yang menentukan bahasa dari perspektif pengguna, tetapi aplikasi pada akhirnya mengatur properti dari bahasa yang diminta pengguna. API biasanya menggunakan kata "budaya" dalam nama anggotanya.
Panduan dalam artikel ini tidak mencakup pengaturan atribut bahasa HTML halaman (<html lang="...">), alat aksesiblitas mana yang digunakan. Anda dapat mengatur nilai secara statis dengan menetapkan bahasa ke lang atribut <html> tag atau ke document.documentElement.lang di JavaScript. Anda dapat secara dinamis mengatur nilai document.documentElement.lang dengan JS interop.
Catatan
Contoh kode dalam artikel ini mengadopsi jenis referensi nullable (NRT) dan analisis statis status-null kompilator .NET, yang didukung dalam ASP.NET Core di .NET 6 atau yang lebih baru. Saat menargetkan .NET 5 atau yang lebih lama, hapus penunjukan jenis null (?) dari contoh artikel.
Globalisasi
Direktif @bind atribut menerapkan format dan mengurai nilai untuk ditampilkan berdasarkan bahasa pilihan pertama pengguna yang didukung aplikasi.
@bind mendukung penggunaan parameter @bind:culture untuk menyediakan System.Globalization.CultureInfo guna mengurai dan memformat nilai.
Kultur saat ini dapat diakses dari properti System.Globalization.CultureInfo.CurrentCulture.
CultureInfo.InvariantCulture digunakan untuk jenis bidang berikut (<input type="{TYPE}" />, di mana {TYPE} adalah tipe penggantinya):
datenumber
Jenis bidang sebelumnya:
- Ditampilkan menggunakan aturan pemformatan berbasis browser yang sesuai.
- Tidak boleh berisi teks bentuk bebas.
- Berikan karakteristik interaksi pengguna berdasarkan implementasi browser.
Blazor memberikan dukungan bawaan untuk menampilkan nilai dalam kebudayaan saat ini. Oleh karena itu, menentukan budaya dengan @bind:culture tidak disarankan saat menggunakan jenis bidang date dan number.
Jenis bidang berikut ini memiliki persyaratan pemformatan tertentu dan tidak didukung oleh semua browser utama, sehingga tidak didukung oleh Blazor:
datetime-localmonthweek
Untuk dukungan browser saat ini dari jenis sebelumnya, lihat Dapatkah saya menggunakan.
Secara default, Blazor memuat subset data globalisasi yang berisi budaya aplikasi. Untuk memuat semua data globalisasi, atur <BlazorWebAssemblyLoadAllGlobalizationData> ke true dalam file proyek aplikasi (.csproj):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
.NET dukungan globalisasi dan Komponen Internasional untuk Unicode (ICU) (Blazor WebAssembly)
Blazor WebAssembly menggunakan API globalisasi yang disederhanakan dan kumpulan Komponen Internasional bawaan untuk lokal Unicode (ICU).
Di aplikasi WebAssembly (Wasm), saat mode globalisasi invariant dinonaktifkan, file data ICU dimuat. Ada empat jenis dasar file-file ini:
-
icudt.dat: Data lengkap -
icudt_EFIGS.dat: Data untuk lokal:en-*, ,fr-FR,es-ES,it-ITdande-DE. -
icudt_CJK.dat: Data untuk lokal:en-*,ja,ko, danzh-*. -
icudt_no_CJK.dat: Data untuk semua lokal dariicudt.dat, tidak termasukja,ko, danzh-*.
Tentukan satu file yang harus dimuat dengan properti MSBuild dalam file proyek aplikasi <BlazorIcuDataFileName>.csproj. Contoh berikut memuat berkas icudt_no_CJK.dat.
<PropertyGroup>
<BlazorIcuDataFileName>icudt_no_CJK.dat</BlazorIcuDataFileName>
</PropertyGroup>
<BlazorIcuDataFileName> hanya menerima satu file. File dapat menjadi file kustom yang dibuat oleh pengembang. Untuk membuat file ICU kustom, lihat WASM Globalization Icu: Custom ICU.
Jika file tidak ditentukan dengan <BlazorIcuDataFileName>, budaya aplikasi diperiksa, dan file ICU yang sesuai dimuat untuk budayanya. Misalnya, kultur en-US menghasilkan memuat file icudt_EFIGS.dat. Untuk zh-CN, file icudt_CJK.dat digunakan.
Untuk informasi selengkapnya, lihat .NET Globalisasi dan ICU: ICU di WebAssembly.
Blazor WebAssembly menggunakan API globalisasi yang disederhanakan dan kumpulan Komponen Internasional bawaan untuk lokal Unicode (ICU). Untuk informasi selengkapnya, lihat .NET Globalisasi dan ICU: ICU di WebAssembly.
Memuat subset lokal kustom di aplikasi Blazor WebAssembly didukung di .NET 8 atau yang lebih baru. Untuk informasi selengkapnya, akses bagian ini untuk versi .NET 8 atau yang lebih baru dari artikel ini.
Globalisasi invarian
Bagian ini hanya berlaku untuk skenario sisi Blazor klien.
Jika aplikasi tidak memerlukan pelokalan, konfigurasikan aplikasi untuk mendukung kultur invarian, yang umumnya didasarkan pada bahasa Inggris Amerika Serikat (en-US). Menggunakan globalisasi invarian mengurangi ukuran unduhan aplikasi dan menghasilkan startup aplikasi yang lebih cepat. Atur InvariantGlobalization properti ke true dalam file proyek aplikasi (.csproj):
<PropertyGroup>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
Atau, konfigurasikan globalisasi invarian dengan pendekatan berikut:
Di
runtimeconfig.json:{ "runtimeOptions": { "configProperties": { "System.Globalization.Invariant": true } } }Dengan variabel lingkungan:
- Kunci:
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT - Nilai:
trueatau1
- Kunci:
Untuk informasi selengkapnya, lihat opsi konfigurasi Runtime untuk globalisasi (dokumentasi .NET).
Informasi zona waktu
Bagian ini hanya berlaku untuk skenario sisi Blazor klien.
Mengadopsi globalisasi yang tidak berubah hanya mengakibatkan penggunaan nama zona waktu yang tidak dilokalkan. Untuk memangkas kode dan data zona waktu, yang mengurangi ukuran unduhan aplikasi dan menghasilkan startup aplikasi yang lebih cepat, terapkan <InvariantTimezone> properti MSBuild dengan nilai true dalam file proyek aplikasi:
<PropertyGroup>
<InvariantTimezone>true</InvariantTimezone>
</PropertyGroup>
Catatan
<BlazorEnableTimeZoneSupport> mengambil alih pengaturan sebelumnya <InvariantTimezone> . Sebaiknya hapus pengaturan <BlazorEnableTimeZoneSupport>.
File data disertakan untuk membuat informasi zona waktu benar. Jika aplikasi tidak memerlukan fitur ini, pertimbangkan untuk menonaktifkannya dengan mengatur <BlazorEnableTimeZoneSupport> properti MSBuild ke false dalam file proyek aplikasi:
<PropertyGroup>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
</PropertyGroup>
Prarendering sisi klien dalam Blazor Web App mempertahankan budaya server
Secara bawaan, prarender sisi klien pada server (proyek .Client dalam Blazor Web App) menyimpan CurrentCulture dan CurrentUICulture server ke dalam status komponen dan menerapkannya di klien sebelum assembly satelit dimuat.
Aplikasi yang mengharuskan klien memilih kultur secara independen dari server dapat memilih untuk tidak ikut serta dengan WebAssemblyComponentsOptions.UseCultureFromServer dalam berkas Blazor Web App milik Program:
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents(options =>
{
options.UseCultureFromServer = false;
});
Komponen demonstrasi
Komponen berikut CultureExample1 dapat digunakan untuk menunjukkan Blazor konsep globalisasi dan pelokalan yang dicakup oleh artikel ini.
CultureExample1.razor:
@page "/culture-example-1"
@using System.Globalization
<h1>Culture Example 1</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Rendered values</h2>
<ul>
<li><b>Date</b>: @dt</li>
<li><b>Number</b>: @number.ToString("N2")</li>
</ul>
<h2><code><input></code> elements that don't set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.CurrentCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input @bind="dt" /></label></li>
<li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>
<h2><code><input></code> elements that set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.InvariantCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
<li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>
@code {
private DateTime dt = DateTime.Now;
private double number = 1999.69;
}
Format string angka (N2) dalam contoh sebelumnya (.ToString("N2")) adalah penentu format numerik standard .NET.
N2 Format ini didukung untuk semua jenis numerik, termasuk pemisah grup, dan menampilkan hingga dua tempat desimal.
Secara opsional, tambahkan item menu ke navigasi di NavMenu komponen (NavMenu.razor) untuk CultureExample1 komponen.
Mengatur budaya secara dinamis dari Accept-Language header
Tambahkan paket Microsoft.Extensions.Localization ke aplikasi.
Header Accept-Language diatur oleh browser dan dikontrol oleh preferensi bahasa pengguna di pengaturan browser. Di pengaturan browser, pengguna mengatur satu atau beberapa bahasa pilihan dalam urutan preferensi. Urutan preferensi digunakan oleh browser untuk mengatur nilai kualitas (q, 0-1) untuk setiap bahasa di header. Contoh berikut menentukan bahasa Inggris Amerika Serikat, bahasa Inggris, dan bahasa Spanyol Kosta Rika dengan preferensi untuk bahasa Inggris Amerika Serikat atau bahasa Inggris.
Accept-Language: en-US,en; q=0.9,es-CR; q=0.8
Budaya aplikasi diatur dengan mencocokkan bahasa yang diminta pertama yang cocok dengan budaya aplikasi yang didukung.
Dalam pengembangan sisi klien, atur BlazorWebAssemblyLoadAllGlobalizationData properti ke true dalam file proyek aplikasi sisi klien (.csproj):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
Dalam pengembangan sisi klien, pengaturan budaya secara dinamis dari Accept-Language header tidak didukung.
Catatan
Jika spesifikasi aplikasi memerlukan pembatasan budaya yang didukung ke daftar eksplisit, lihat bagian Secara dinamis mengatur budaya sisi klien menurut preferensi pengguna di artikel ini.
Aplikasi dilokalkan menggunakan Middleware Pelokalan. Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
Tambahkan baris berikut ke Program file tempat layanan terdaftar:
builder.Services.AddLocalization();
Dalam pengembangan sisi server, tentukan budaya aplikasi yang didukung sebelum middleware apa pun yang mungkin memeriksa budaya permintaan. Umumnya, letakkan Middleware Pelokasikan Permintaan segera sebelum memanggil MapRazorComponents. Contoh berikut mengonfigurasi budaya yang didukung untuk bahasa Inggris Amerika Serikat dan bahasa Spanyol Kosta Rika.
Dalam pengembangan sisi server, tentukan budaya aplikasi yang didukung segera setelah Middleware Perutean (UseRouting) ditambahkan ke alur pemrosesan. Contoh berikut mengonfigurasi koltur yang didukung untuk bahasa Inggris Amerika Serikat dan bahasa Spanyol Kosta Rika menggunakan API berikut:
- AddSupportedCultures menambahkan kumpulan budaya yang didukung untuk globalisasi (tanggal, angka, dan pemformatan mata uang).
- AddSupportedUICultures menambahkan set budaya UI yang didukung untuk lokalisasi (string UI yang diterjemahkan untuk merender konten).
app.UseRequestLocalization(new RequestLocalizationOptions()
.AddSupportedCultures(new[] { "en-US", "es-CR" })
.AddSupportedUICultures(new[] { "en-US", "es-CR" }));
Dalam contoh sebelumnya, budaya pemformatan dan budaya UI yang didukung yang sama ditentukan dalam kasus sempit di mana aplikasi hanya digunakan di Amerika Serikat dan Kosta Rika. Atau, aplikasi dapat menggunakan serangkaian budaya yang lebih luas untuk pemformatan tanggal, angka, dan mata uang tetapi hanya menyediakan konten yang dilokalkan untuk Amerika Serikat dan Kosta Rika, seperti yang ditunjukkan contoh berikut:
var uiCultures = new[] { "en-US", "es-CR" };
var formattingCultures = CultureInfo
.GetCultures(CultureTypes.SpecificCultures)
.Select(c => c.Name)
.ToArray();
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(uiCultures[0])
.AddSupportedCultures(formattingCultures)
.AddSupportedUICultures(uiCultures);
app.UseRequestLocalization(localizationOptions);
Dalam contoh sebelumnya, CultureTypes.SpecificCultures hanya mengembalikan budaya yang khusus untuk negara atau wilayah—seperti en-US atau fr-FR—yang dilengkapi dengan data globalisasi konkret penuh (untuk tanggal, angka, kalender, dan UI budaya lainnya) yang dapat digunakan .NET untuk pemformatan dan penguraian yang akurat. Budaya netral, seperti en atau fr, mungkin tidak memiliki data globalisasi lengkap, sehingga tidak disertakan dalam daftar ini.
Untuk informasi tentang menyusun Middleware Pelokalan dalam pipeline middleware berkas Program, lihat ASP.NET Core Middleware.
Gunakan komponen CultureExample1 yang ditunjukkan di bagian Komponen Demonstrasi untuk mempelajari cara kerja globalisasi. Ajukan permintaan dengan bahasa Inggris Amerika Serikat (en-US). Beralih ke Costa Rican Spanyol (es-CR) di pengaturan bahasa browser. Minta halaman web lagi.
Ketika budaya Amerika Serikat bahasa Inggris (en-US), komponen yang dirender menggunakan pemformatan tanggal bulan/hari (6/7), waktu 12 jam (AM/PM), dan pemisah koma dalam angka dengan titik untuk nilai desimal (1,999.69):
- Tanggal: 7/6/2021 06:45:22
- Nomor: 1.999,69
Ketika budayanya adalah Costa Rican Spanyol (es-CR), komponen yang dirender menggunakan pemformatan tanggal hari/bulan (7/6), waktu 24 jam, dan pemisah periode dalam angka dengan koma untuk nilai desimal (1.999,69):
- Tanggal: 6/7/2021 6:49:38
- Nomor: 1.999,69
Mengatur budaya sisi klien secara statis
Atur BlazorWebAssemblyLoadAllGlobalizationData properti ke true dalam file proyek aplikasi (.csproj):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
Konfigurasi Intermediate Language (IL) Linker untuk penyajian sisi klien menghapus informasi internasionalisasi kecuali untuk lokal yang diminta secara eksplisit. Untuk informasi selengkapnya, lihat Konfigurasi Linker untuk ASP.NET Core Blazor.
Pengaturan budaya aplikasi dapat diatur di JavaScript saat Blazor dimulai dengan opsi pengaktifan applicationCultureBlazor. Contoh berikut mengonfigurasi aplikasi untuk diluncurkan menggunakan budaya Amerika Serikat English (en-US).
Cegah Blazor mulai otomatis dengan menambahkan autostart="false" pada tag Blazor<script>:
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
Dalam contoh sebelumnya, {BLAZOR SCRIPT} adalah pengganti untuk jalur skrip Blazor dan nama file. Untuk lokasi skrip, lihat struktur proyek ASP.NET Core Blazor.
Tambahkan blok berikut <script> setelah tag Blazor di dalam <script> dan sebelum tag penutup </body>.
Blazor Web App:
<script>
Blazor.start({
webAssembly: {
applicationCulture: 'en-US'
}
});
</script>
Mandiri Blazor WebAssembly:
<script>
Blazor.start({
applicationCulture: 'en-US'
});
</script>
Nilai untuk applicationCulture harus sesuai dengan format tag bahasa BCP-47. Untuk informasi selengkapnya tentang startup Blazor, lihat startup ASP.NET Core Blazor.
Alternatif untuk mengatur opsi mulai budaya Blazoradalah mengatur budaya dalam kode C#. Set CultureInfo.DefaultThreadCurrentCulture dan CultureInfo.DefaultThreadCurrentUICulture dalam file Program ke budaya yang sama.
Tambahkan namespace System.Globalization ke berkas Program
using System.Globalization;
Tambahkan pengaturan budaya sebelum garis yang membangun dan menjalankan WebAssemblyHostBuilder (await builder.Build().RunAsync();):
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");
Catatan
Di .NET 9 atau yang lebih lama, aplikasi Blazor WebAssembly mandiri memuat sumber daya globalisasi UI berdasarkan CultureInfo.DefaultThreadCurrentCulture. Jika Anda ingin memuat data globalisasi tambahan untuk budaya pelokalan yang ditentukan oleh CultureInfo.DefaultThreadCurrentUICulture, tingkatkan aplikasi ke .NET 10 atau lebih baru.
Gunakan komponen CultureExample1 yang ditunjukkan di bagian Komponen Demonstrasi untuk mempelajari cara kerja globalisasi. Ajukan permintaan dengan bahasa Inggris Amerika Serikat (en-US). Beralih ke Costa Rican Spanyol (es-CR) di pengaturan bahasa browser. Minta halaman web lagi. Ketika bahasa yang diminta adalah Spanyol Kosta Rika, budaya aplikasi tetap bahasa Inggris Amerika Serikat (en-US).
Mengatur budaya sisi server secara statis
Aplikasi sisi server dilokalkan menggunakan Middleware Pelokalan. Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
Dalam file Program:
builder.Services.AddLocalization();
Tentukan budaya statis dalam Program file sebelum middleware apa pun yang mungkin memeriksa budaya permintaan. Umumnya, tempatkan Middleware Pelokalan Permintaan segera sebelum MapRazorComponents. Contoh berikut mengonfigurasi bahasa Inggris Amerika Serikat:
Tentukan budaya statis di dalam file Program segera setelah Routing Middleware (UseRouting) ditambahkan ke alur pemrosesan. Contoh berikut mengonfigurasi bahasa Inggris Amerika Serikat:
app.UseRequestLocalization("en-US");
Nilai budaya untuk UseRequestLocalization harus sesuai dengan format tag bahasa BCP-47.
Untuk informasi tentang menyusun Middleware Pelokalan dalam pipeline middleware berkas Program, lihat ASP.NET Core Middleware.
Aplikasi sisi server dilokalkan menggunakan Middleware Pelokalan. Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
Dalam Startup.ConfigureServices (Startup.cs):
services.AddLocalization();
Tentukan budaya statis di Startup.Configure (Startup.cs) segera setelah Middleware Perutean ditambahkan ke jalur pemrosesan. Contoh berikut mengonfigurasi bahasa Inggris Amerika Serikat:
app.UseRequestLocalization("en-US");
Nilai budaya untuk UseRequestLocalization harus sesuai dengan format tag bahasa BCP-47.
Untuk informasi tentang memesan Middleware Pelokalan di alur middleware Startup.Configure, lihat ASP.NET Core Middleware.
Gunakan komponen CultureExample1 yang ditunjukkan di bagian Komponen Demonstrasi untuk mempelajari cara kerja globalisasi. Ajukan permintaan dengan bahasa Inggris Amerika Serikat (en-US). Beralih ke Costa Rican Spanyol (es-CR) di pengaturan bahasa browser. Minta halaman web lagi. Ketika bahasa yang diminta adalah Spanyol Kosta Rika, budaya aplikasi tetap bahasa Inggris Amerika Serikat (en-US).
Mengatur budaya sisi klien secara dinamis berdasarkan preferensi pengguna
Contoh lokasi di mana aplikasi mungkin menyimpan preferensi pengguna termasuk dalam penyimpanan lokal browser (umum untuk skenario sisi klien), dalam pelokalan cookie atau database (umum untuk skenario sisi server), atau dalam layanan eksternal yang dilampirkan ke database eksternal dan diakses oleh API web. Contoh berikut menunjukkan cara menggunakan penyimpanan lokal browser.
Tambahkan paket Microsoft.Extensions.Localization ke aplikasi.
Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bawah Install dan kelola paket di alur kerja konsumsi Package (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
Atur properti ke BlazorWebAssemblyLoadAllGlobalizationDatatrue dalam file proyek:
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
Pengaturan budaya aplikasi untuk rendering sisi klien diatur menggunakan API kerangka kerja Blazor. Pilihan budaya pengguna dapat dipertahankan di penyimpanan lokal browser.
Berikan fungsi JS setelah tag Blazor<script> untuk mendapatkan dan mengatur pemilihan budaya pengguna dengan penyimpanan lokal browser.
<script>
window.blazorCulture = {
get: () => window.localStorage['BlazorCulture'],
set: (value) => window.localStorage['BlazorCulture'] = value
};
</script>
Catatan
Contoh sebelumnya membebani klien dengan fungsi global. Untuk pendekatan yang lebih baik dalam aplikasi produksi, lihat Isolasi JavaScript dalam modul JavaScript.
Tambahkan namespace untuk System.Globalization dan Microsoft.JSInterop ke bagian atas file Program.
using System.Globalization;
using Microsoft.JSInterop;
Hapus baris berikut:
- await builder.Build().RunAsync();
Ganti baris sebelumnya dengan kode berikut. Kode menambahkan Blazorlayanan pelokalan ke koleksi layanan aplikasi dengan AddLocalization dan menggunakan JS interop untuk memanggil JS dan mengambil pilihan budaya pengguna dari penyimpanan lokal. Jika penyimpanan lokal tidak berisi pengaturan bahasa untuk pengguna, kode menetapkan nilai default Bahasa Inggris Amerika Serikat (en-US).
builder.Services.AddLocalization();
var host = builder.Build();
const string defaultCulture = "en-US";
var js = host.Services.GetRequiredService<IJSRuntime>();
var result = await js.InvokeAsync<string>("blazorCulture.get");
var culture = CultureInfo.GetCultureInfo(result ?? defaultCulture);
if (result == null)
{
await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
await host.RunAsync();
Catatan
Di .NET 9 atau yang lebih lama, aplikasi Blazor WebAssembly mandiri memuat sumber daya globalisasi UI berdasarkan CultureInfo.DefaultThreadCurrentCulture. Jika Anda ingin memuat data globalisasi tambahan untuk budaya pelokalan yang ditentukan oleh CultureInfo.DefaultThreadCurrentUICulture, tingkatkan aplikasi ke .NET 10 atau lebih baru.
Komponen berikut menunjukkan CultureSelector cara melakukan tindakan berikut:
- Atur pilihan budaya pengguna ke penyimpanan lokal browser melalui JS interop.
- Muat ulang komponen yang mereka minta (
forceLoad: true), yang menggunakan budaya yang diperbarui.
CultureSelector.razor:
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select @bind="selectedCulture" @bind:after="ApplySelectedCultureAsync">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task ApplySelectedCultureAsync()
{
if (CultureInfo.CurrentCulture != selectedCulture)
{
await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);
Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
}
}
}
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select value="@selectedCulture" @onchange="HandleSelectedCultureChanged">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task HandleSelectedCultureChanged(ChangeEventArgs args)
{
selectedCulture = CultureInfo.GetCultureInfo((string)args.Value!);
if (CultureInfo.CurrentCulture != selectedCulture)
{
await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);
Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
}
}
}
Catatan
Untuk informasi selengkapnya tentang IJSInProcessRuntime, lihat fungsi JavaScript Call dari metode .NET dalam ASP.NET Core Blazor.
Di dalam tag penutup elemen </main> dari komponen MainLayout (MainLayout.razor), tambahkan komponen CultureSelector:
<article class="bottom-row px-4">
<CultureSelector />
</article>
Gunakan komponen yang CultureExample1 ditunjukkan di bagian Komponen demonstrasi untuk mempelajari cara kerja contoh sebelumnya.
Mengatur budaya sisi server secara dinamis berdasarkan preferensi pengguna
Contoh lokasi di mana aplikasi mungkin menyimpan preferensi pengguna termasuk dalam penyimpanan lokal browser (umum untuk skenario sisi klien), dalam pelokalan cookie atau database (umum untuk skenario sisi server), atau dalam layanan eksternal yang dilampirkan ke database eksternal dan diakses oleh API web. Contoh berikut menunjukkan cara menggunakan pelokalan cookie.
Catatan
Contoh berikut mengasumsikan bahwa aplikasi mengadopsi interaktivitas global dengan menentukan rendering sisi server interaktif (interactive SSR) pada komponen dalam komponen (Routes):
<Routes @rendermode="InteractiveServer" />
Jika aplikasi mengadopsi interaktivitas per halaman/komponen , lihat komentar di akhir bagian ini untuk memodifikasi mode render komponen contoh.
Tambahkan paket Microsoft.Extensions.Localization ke aplikasi.
Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bawah Install dan kelola paket di alur kerja konsumsi Package (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
Aplikasi sisi server dilokalkan menggunakan Middleware Pelokalan. Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
Dalam file Program:
builder.Services.AddLocalization();
Atur budaya default dan didukung aplikasi dengan RequestLocalizationOptions.
Sebelum panggilan ke MapRazorComponents dalam alur pemrosesan permintaan, letakkan kode berikut:
Setelah Middleware Perutean (UseRouting) ditambahkan ke alur pemrosesan permintaan, letakkan kode berikut:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Untuk informasi tentang menyusun Middleware Pelokalan dalam alur kerja middleware, lihat ASP.NET Core Middleware.
Contoh berikut menunjukkan cara mengonfigurasi budaya saat ini dalam cookie yang dapat dibaca oleh Middleware Localization.
Namespace berikut diperlukan untuk App komponen:
Tambahkan yang berikut ini ke bagian App atas file komponen (Components/App.razor):
@using System.Globalization
@using Microsoft.AspNetCore.Localization
Tambahkan blok berikut @code ke bagian App bawah file komponen:
@code {
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
protected override void OnInitialized()
{
HttpContext?.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
}
Modifikasi pada Pages/_Host.cshtml file memerlukan namespace berikut:
Tambahkan teks berikut ke file:
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@{
this.HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
Untuk informasi tentang menyusun Middleware Pelokalan dalam alur kerja middleware, lihat ASP.NET Core Middleware.
Jika aplikasi tidak dikonfigurasi untuk memproses tindakan pengontrol:
Tambahkan layanan MVC dengan memanggil AddControllers pada kumpulan layanan di dalam file
Program.builder.Services.AddControllers();Tambahkan perutean titik akhir pengontrol ke dalam file
Programdengan menggunakan MapControllers pada IEndpointRouteBuilder (app):app.MapControllers();
Untuk menyediakan UI agar pengguna dapat memilih budaya, gunakan pendekatan berbasis pengalihan dengan pelokalan cookie. Aplikasi ini mempertahankan budaya yang dipilih pengguna melalui pengalihan ke pengontrol. Pengontrol mengatur budaya yang dipilih pengguna menjadi cookie dan mengalihkan pengguna kembali ke URI asli. Prosesnya mirip dengan apa yang terjadi di aplikasi web ketika pengguna mencoba mengakses sumber daya yang aman, di mana pengguna dialihkan ke halaman masuk lalu dialihkan kembali ke sumber daya asli.
Controllers/CultureController.cs:
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
[Route("[controller]/[action]")]
public class CultureController : Controller
{
public IActionResult Set(string culture, string redirectUri)
{
if (culture != null)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture, culture)));
}
return LocalRedirect(redirectUri);
}
}
Peringatan
Gunakan hasil tindakan LocalRedirect, seperti yang ditunjukkan dalam contoh sebelumnya, untuk mencegah serangan pengalihan terbuka. Untuk informasi selengkapnya, lihat Cegah serangan pengalihan terbuka di ASP.NET Core.
Komponen berikut CultureSelector menunjukkan cara memanggil Set metode CultureController dengan budaya baru. Komponen ditempatkan di Shared folder untuk digunakan di seluruh aplikasi.
CultureSelector.razor:
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select @bind="selectedCulture" @bind:after="ApplySelectedCultureAsync">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task ApplySelectedCultureAsync()
{
if (CultureInfo.CurrentCulture != selectedCulture)
{
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
var uriEscaped = Uri.EscapeDataString(uri);
Navigation.NavigateTo(
$"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
forceLoad: true);
}
}
}
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select value="@selectedCulture" @onchange="HandleSelectedCultureChanged">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task HandleSelectedCultureChanged(ChangeEventArgs args)
{
selectedCulture = CultureInfo.GetCultureInfo((string)args.Value!);
if (CultureInfo.CurrentCulture != selectedCulture)
{
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
var uriEscaped = Uri.EscapeDataString(uri);
Navigation.NavigateTo(
$"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
forceLoad: true);
}
}
}
Tambahkan komponen CultureSelector ke komponen MainLayout. Tempatkan markup berikut di dalam tag penutup </main> dalam Components/Layout/MainLayout.razor file:
Tambahkan komponen CultureSelector ke komponen MainLayout. Tempatkan markup berikut di dalam tag penutup </main> dalam Shared/MainLayout.razor file:
<article class="bottom-row px-4">
<CultureSelector />
</article>
Gunakan komponen yang CultureExample1 ditunjukkan di bagian Komponen demonstrasi untuk mempelajari cara kerja contoh sebelumnya.
Contoh sebelumnya mengasumsikan bahwa aplikasi mengadopsi interaktivitas global dengan menentukan mode render Server Interaktif pada Routes komponen dalam App komponen (Components/App.razor):
<Routes @rendermode="InteractiveServer" />
Jika aplikasi mengadopsi interaktivitas per halaman/komponen , buat perubahan berikut:
Tambahkan mode render Server Interaktif ke bagian
CultureExample1atas file komponen (Components/Pages/CultureExample1.razor):@rendermode InteractiveServerDi tata letak utama aplikasi (
Components/Layout/MainLayout.razor), terapkan mode render Server Interaktif keCultureSelectorkomponen:<CultureSelector @rendermode="InteractiveServer" />
Mengatur budaya secara dinamis sesuai dengan preferensi pengguna dalam Blazor Web App
Bagian ini berlaku untuk Blazor Web Appyang mengadopsi interaktivitas Otomatis (Server dan WebAssembly).
Contoh lokasi di mana aplikasi mungkin menyimpan preferensi pengguna termasuk dalam penyimpanan lokal browser (umum untuk skenario sisi klien), dalam pelokalan cookie atau database (umum untuk skenario sisi server), penyimpanan lokal dan pelokalan cookie (Blazor Web Appdengan komponen server dan WebAssembly), atau dalam layanan eksternal yang dilampirkan ke database eksternal dan diakses oleh API web. Contoh berikut menunjukkan cara menggunakan penyimpanan lokal browser untuk komponen yang dirender di sisi klien ("client-side rendered", CSR) dan pelokalan cookie untuk komponen yang dirender di sisi server ("server-side rendered", SSR).
Pembaruan untuk .Client proyek
Tambahkan paket Microsoft.Extensions.Localization ke proyek .Client.
Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bawah Install dan kelola paket di alur kerja konsumsi Package (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
Atur properti BlazorWebAssemblyLoadAllGlobalizationData ke true dalam file proyek .Client.
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
Tambahkan namespace untuk System.Globalization dan Microsoft.JSInterop ke bagian atas file .Client di proyek Program:
using System.Globalization;
using Microsoft.JSInterop;
Hapus baris berikut:
- await builder.Build().RunAsync();
Ganti baris sebelumnya dengan kode berikut. Kode menambahkan Blazorlayanan pelokalan ke koleksi layanan aplikasi dengan AddLocalization dan menggunakan JS interop untuk memanggil JS dan mengambil pilihan budaya pengguna dari penyimpanan lokal. Jika penyimpanan lokal tidak berisi pengaturan bahasa untuk pengguna, kode menetapkan nilai default Bahasa Inggris Amerika Serikat (en-US).
builder.Services.AddLocalization();
var host = builder.Build();
const string defaultCulture = "en-US";
var js = host.Services.GetRequiredService<IJSRuntime>();
var result = await js.InvokeAsync<string>("blazorCulture.get");
var culture = CultureInfo.GetCultureInfo(result ?? defaultCulture);
if (result == null)
{
await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
await host.RunAsync();
Catatan
Di .NET 9 atau yang lebih lama, aplikasi Blazor WebAssembly mandiri memuat sumber daya globalisasi UI berdasarkan CultureInfo.DefaultThreadCurrentCulture. Jika Anda ingin memuat data globalisasi tambahan untuk budaya pelokalan yang ditentukan oleh CultureInfo.DefaultThreadCurrentUICulture, tingkatkan aplikasi ke .NET 10 atau lebih baru.
Tambahkan komponen berikut CultureSelector ke .Client proyek.
Komponen mengadopsi pendekatan berikut untuk bekerja baik untuk komponen SSR atau CSR:
- Nama tampilan setiap budaya yang tersedia dalam daftar dropdown disediakan oleh kamus karena data globalisasi pada sisi klien mencakup teks nama tampilan budaya yang telah dilokalkan yang disediakan oleh data globalisasi pada sisi server. Misalnya, pelokalan sisi server menampilkan
English (Amerika Serikat)ketikaen-USadalah budaya danIngles ()ketika budaya yang berbeda digunakan. Karena pelokalan nama tampilan budaya tidak tersedia dengan globalisasi Blazor WebAssembly, nama tampilan untuk bahasa Inggris Amerika Serikat pada klien untuk budaya mana pun yang dimuat hanyalahen-US. Menggunakan kamus kustom memungkinkan komponen untuk setidaknya menampilkan nama budaya inggris lengkap. - Ketika pengguna mengubah kultur, JS interop mengatur kultur di penyimpanan browser lokal dan aksi kontrol memperbarui lokalisasi cookie dengan kultur tersebut. Pengontrol ditambahkan ke aplikasi nanti di bagian Pembaruan proyek server.
Pages/CultureSelector.razor:
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select @bind="@selectedCulture" @bind:after="ApplySelectedCultureAsync">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@cultureDict[culture.Name]</option>
}
</select>
</label>
</p>
@code
{
private Dictionary<string, string> cultureDict =
new()
{
{ "en-US", "English (United States)" },
{ "es-CR", "Spanish (Costa Rica)" }
};
private CultureInfo[] supportedCultures =
[
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
];
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task ApplySelectedCultureAsync()
{
if (CultureInfo.CurrentCulture != selectedCulture)
{
await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
var uriEscaped = Uri.EscapeDataString(uri);
Navigation.NavigateTo(
$"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
forceLoad: true);
}
}
}
Dalam file .Client proyek _Imports (_Imports.razor), tambahkan namespace untuk komponen di folder Pages, perbarui namespace agar sesuai dengan namespace proyek .Client Anda:
@using BlazorSample.Client.Pages
Catatan
Untuk informasi selengkapnya tentang IJSInProcessRuntime, lihat fungsi JavaScript Call dari metode .NET dalam ASP.NET Core Blazor.
Dalam proyek .Client, tambahkan komponen CultureSelector ke komponen MainLayout. Tempatkan markup berikut di dalam tag penutup </main> dalam Layout/MainLayout.razor file:
<article class="bottom-row px-4">
<CultureSelector @rendermode="InteractiveAuto" />
</article>
.Client Dalam proyek, tempatkan komponen berikut CultureClient untuk mempelajari cara kerja globalisasi untuk komponen CSR.
Pages/CultureClient.razor:
@page "/culture-client"
@rendermode InteractiveWebAssembly
@using System.Globalization
<PageTitle>Culture Client</PageTitle>
<h1>Culture Client</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Rendered values</h2>
<ul>
<li><b>Date</b>: @dt</li>
<li><b>Number</b>: @number.ToString("N2")</li>
</ul>
<h2><code><input></code> elements that don't set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.CurrentCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input @bind="dt" /></label></li>
<li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>
<h2><code><input></code> elements that set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.InvariantCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
<li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>
@code {
private DateTime dt = DateTime.Now;
private double number = 1999.69;
}
Dalam proyek .Client, tempatkan komponen CultureServer berikut untuk mempelajari cara kerja globalisasi untuk komponen SSR.
Pages/CultureServer.razor:
@page "/culture-server"
@rendermode InteractiveServer
@using System.Globalization
<PageTitle>Culture Server</PageTitle>
<h1>Culture Server</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Rendered values</h2>
<ul>
<li><b>Date</b>: @dt</li>
<li><b>Number</b>: @number.ToString("N2")</li>
</ul>
<h2><code><input></code> elements that don't set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.CurrentCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input @bind="dt" /></label></li>
<li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>
<h2><code><input></code> elements that set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.InvariantCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
<li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>
@code {
private DateTime dt = DateTime.Now;
private double number = 1999.69;
}
Gunakan komponen CultureExample1 ke folder .Client proyek Pages.
Tambahkan komponen CultureClient, CultureServer, dan CultureExample1 ke navigasi bilah samping di Layout/NavMenu.razor:
<div class="nav-item px-3">
<NavLink class="nav-link" href="culture-server">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Server)
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="culture-client">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Client)
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="culture-example-1">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Auto)
</NavLink>
</div>
Pembaruan proyek server
Tambahkan paket Microsoft.Extensions.Localization ke proyek server.
Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bawah Install dan kelola paket di alur kerja konsumsi Package (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
Aplikasi sisi server dilokalkan menggunakan Middleware Pelokalan. Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
Dalam file proyek Program server tempat layanan didaftarkan:
builder.Services.AddLocalization();
Atur budaya default dan didukung aplikasi dengan RequestLocalizationOptions.
Sebelum panggilan ke MapRazorComponents dalam alur pemrosesan permintaan, letakkan kode berikut:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Contoh berikut menunjukkan cara mengonfigurasi budaya saat ini dalam cookie yang dapat dibaca oleh Middleware Localization.
Namespace berikut diperlukan untuk App komponen:
Tambahkan yang berikut ini ke bagian App atas file komponen (Components/App.razor):
@using System.Globalization
@using Microsoft.AspNetCore.Localization
Pengaturan budaya aplikasi untuk rendering sisi klien diatur menggunakan API kerangka kerja Blazor. Pilihan budaya pengguna dapat dipertahankan di penyimpanan lokal browser untuk komponen CSR.
Setelah tag Blazor<script>, berikan fungsi JS untuk mendapatkan dan mengatur pilihan kebudayaan pengguna dengan penyimpanan lokal browser:
<script>
window.blazorCulture = {
get: () => window.localStorage['BlazorCulture'],
set: (value) => window.localStorage['BlazorCulture'] = value
};
</script>
Catatan
Contoh sebelumnya membebani klien dengan fungsi global. Untuk pendekatan yang lebih baik dalam aplikasi produksi, lihat Isolasi JavaScript dalam modul JavaScript.
Tambahkan blok berikut @code ke bagian App bawah file komponen:
@code {
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
protected override void OnInitialized()
{
HttpContext?.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
}
Jika proyek server tidak dikonfigurasi untuk memproses tindakan pengontrol:
Tambahkan layanan MVC dengan memanggil AddControllers pada kumpulan layanan di dalam file
Program.builder.Services.AddControllers();Tambahkan perutean titik akhir pengontrol ke dalam file
Programdengan menggunakan MapControllers pada IEndpointRouteBuilder (app):app.MapControllers();
Untuk memungkinkan pengguna memilih budaya untuk komponen SSR, gunakan pendekatan berbasis pengalihan dengan pelokalan cookie. Aplikasi ini mempertahankan budaya yang dipilih pengguna melalui pengalihan ke pengontrol. Pengontrol mengatur budaya yang dipilih pengguna menjadi cookie dan mengalihkan pengguna kembali ke URI asli. Prosesnya mirip dengan apa yang terjadi di aplikasi web ketika pengguna mencoba mengakses sumber daya yang aman, di mana pengguna dialihkan ke halaman masuk lalu dialihkan kembali ke sumber daya asli.
Controllers/CultureController.cs:
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
[Route("[controller]/[action]")]
public class CultureController : Controller
{
public IActionResult Set(string culture, string redirectUri)
{
if (culture != null)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture, culture)));
}
return LocalRedirect(redirectUri);
}
}
Peringatan
Gunakan hasil tindakan LocalRedirect, seperti yang ditunjukkan dalam contoh sebelumnya, untuk mencegah serangan pengalihan terbuka. Untuk informasi selengkapnya, lihat Cegah serangan pengalihan terbuka di ASP.NET Core.
Komponen Otomatis Interaktif
Panduan di bagian ini juga berfungsi untuk komponen dalam aplikasi yang mengadopsi rendering per halaman/komponen dan menentukan mode render Otomatis Interaktif:
@rendermode InteractiveAuto
Lokalisasi
Jika aplikasi belum mendukung pemilihan budaya dinamis, tambahkan paket Microsoft.Extensions.Localization ke aplikasi.
Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bawah Install dan kelola paket di alur kerja konsumsi Package (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
Pelokalan pada sisi klien
Atur BlazorWebAssemblyLoadAllGlobalizationData properti ke true dalam file proyek aplikasi (.csproj):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
Pada file Program, tambahkan namespace untuk System.Globalization ke bagian atas file.
using System.Globalization;
Tambahkan layanan pengelokalan Blazor ke koleksi layanan aplikasi dengan AddLocalization:
builder.Services.AddLocalization();
Pelokalan di sisi server
Gunakan Middleware Pelokalan untuk mengatur budaya aplikasi.
Jika aplikasi belum mendukung pemilihan budaya dinamis:
- Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
- Tentukan budaya default dan didukung aplikasi dalam
Programfile. Contoh berikut mengonfigurasi kultur yang didukung untuk bahasa Inggris Amerika Serikat dan Spanyol Kosta Rika.
builder.Services.AddLocalization();
Tempatkan Middleware Pelokalan Permintaan sebelum middleware apa pun yang mungkin memeriksa kultur permintaan. Umumnya, tempatkan middleware segera sebelum memanggil MapRazorComponents:
Segera setelah Middleware Perutean (UseRouting) ditambahkan ke alur pemrosesan:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Untuk informasi tentang menyusun Middleware Pelokalan dalam alur kerja middleware, lihat ASP.NET Core Middleware.
- Tambahkan layanan pelokalan ke aplikasi dengan AddLocalization.
- Tentukan budaya default dan didukung aplikasi di
Startup.Configure(Startup.cs). Contoh berikut mengonfigurasi kultur yang didukung untuk bahasa Inggris Amerika Serikat dan Spanyol Kosta Rika.
Dalam Startup.ConfigureServices (Startup.cs):
services.AddLocalization();
Segera Startup.Configure setelah Middleware Perutean (UseRouting) ditambahkan ke alur pemrosesan:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Untuk informasi tentang memesan Middleware Pelokalan di alur middleware Startup.Configure, lihat ASP.NET Core Middleware.
Jika aplikasi harus melokalisasi sumber daya berdasarkan penyimpanan pengaturan budaya pengguna, gunakan budaya pelokalan cookie. Penggunaan cookie memastikan bahwa koneksi WebSocket dapat menyebarkan budaya dengan benar. Jika skema pelokalan didasarkan pada jalur URL atau string kueri, skema mungkin tidak dapat bekerja dengan WebSocket, sehingga gagal mempertahankan budaya. Oleh karena itu, pendekatan yang direkomendasikan adalah menggunakan budaya cookielokalisasi . Lihat bagian Secara dinamis mengatur budaya sisi server menurut preferensi pengguna di artikel ini untuk melihat contoh Razor ekspresi yang mempertahankan pilihan budaya pengguna.
Contoh sumber daya yang dilokalkan
Contoh sumber daya yang dilokalkan di bagian ini berfungsi dengan contoh sebelumnya dalam artikel ini di mana budaya yang didukung aplikasi adalah bahasa Inggris (en) sebagai lokal default dan Spanyol (es) sebagai lokal alternatif yang dapat dipilih pengguna atau yang ditentukan browser.
Buat file sumber daya untuk setiap lokal. Dalam contoh berikut, sumber daya dibuat untuk Greeting string dalam bahasa Inggris dan Spanyol:
- Bahasa Inggris (
en):Hello, World! - Spanyol (
es):¡Hola, Mundo!
Catatan
File sumber daya berikut dapat ditambahkan di Visual Studio dengan mengklik kanan folder Pages dan memilih Tambahkan> Item Baru>Resources File. Beri nama file CultureExample2.resx. Saat editor muncul, berikan data untuk entri baru. Atur Nama ke Greeting dan Nilai ke Hello, World!. Simpan file.
Jika menggunakan Visual Studio Code, kami merekomendasikan untuk menginstal Penampil dan Editor ResX Tim Heuer. Tambahkan file kosong CultureExample2.resx ke Pages folder . Ekstensi secara otomatis mengambil alih pengelolaan file di UI. Pilih tombol Tambahkan Sumber Daya Baru. Ikuti instruksi untuk menambahkan entri untuk Greeting (kunci), Hello, World! (nilai), dan None (komentar). Simpan file. Jika Anda menutup dan membuka kembali file, Anda dapat melihat Greeting sumber daya.
Penampil dan Editor ResX Tim Heuer tidak dimiliki atau dikelola oleh Microsoft dan tidak tercakup dalam Perjanjian atau lisensi Microsoft Support apa pun.
Berikut ini menunjukkan contoh file sumber daya tipikal. Anda dapat menempatkan file sumber daya secara manual ke folder Pages aplikasi jika Anda lebih suka tidak menggunakan alat bawaan dengan lingkungan pengembangan terintegrasi (IDE), seperti editor file sumber daya bawaan Visual Studio atau Visual Studio Code dengan ekstensi untuk membuat dan mengedit file sumber daya.
Pages/CultureExample2.resx:
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Greeting" xml:space="preserve">
<value>Hello, World!</value>
</data>
</root>
Catatan
File sumber daya berikut dapat ditambahkan di Visual Studio dengan mengklik kanan folder Pages dan memilih Tambahkan> Item Baru>Resources File. Beri nama file CultureExample2.es.resx. Saat editor muncul, berikan data untuk entri baru. Atur Nama ke Greeting dan Nilai ke ¡Hola, Mundo!. Simpan file.
Jika menggunakan Visual Studio Code, kami merekomendasikan untuk menginstal Penampil dan Editor ResX Tim Heuer. Tambahkan file kosong CultureExample2.resx ke Pages folder . Ekstensi secara otomatis mengambil alih pengelolaan file di UI. Pilih tombol Tambahkan Sumber Daya Baru. Ikuti instruksi untuk menambahkan entri untuk Greeting (kunci), ¡Hola, Mundo! (nilai), dan None (komentar). Simpan file. Jika Anda menutup dan membuka kembali file, Anda dapat melihat Greeting sumber daya.
Berikut ini menunjukkan contoh file sumber daya tipikal. Anda dapat menempatkan file sumber daya secara manual ke folder Pages aplikasi jika Anda lebih suka tidak menggunakan alat bawaan dengan lingkungan pengembangan terintegrasi (IDE), seperti editor file sumber daya bawaan Visual Studio atau Visual Studio Code dengan ekstensi untuk membuat dan mengedit file sumber daya.
Pages/CultureExample2.es.resx:
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Greeting" xml:space="preserve">
<value>¡Hola, Mundo!</value>
</data>
</root>
Komponen berikut menunjukkan penggunaan string yang dilokalkan Greeting dengan IStringLocalizer<T>.
Razor Markup @Loc["Greeting"] pada contoh berikut melokalisasi string yang diikat ke nilai Greeting, yang diatur dalam file sumber daya sebelumnya.
Tambahkan namespace untuk Microsoft.Extensions.Localization ke file _Imports.razor aplikasi:
@using Microsoft.Extensions.Localization
CultureExample2.razor:
@page "/culture-example-2"
@using System.Globalization
@inject IStringLocalizer<CultureExample2> Loc
<h1>Culture Example 2</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Greeting</h2>
<p>
@Loc["Greeting"]
</p>
<p>
@greeting
</p>
@code {
private string? greeting;
protected override void OnInitialized()
{
greeting = Loc["Greeting"];
}
}
Secara opsional, tambahkan item menu untuk CultureExample2 komponen ke navigasi di NavMenu komponen (NavMenu.razor).
Sumber referensi penyedia budaya WebAssembly
Untuk lebih memahami bagaimana kerangka kerja Blazor memproses pelokalan, lihat kelas WebAssemblyCultureProvider di sumber referensi ASP.NET Core.
Catatan
Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag untuk rilis tertentu, gunakan menu dropdown Switch branches or tags. Untuk informasi selengkapnya, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Sumber Daya Bersama
Untuk membuat sumber daya pelokalan bersama, gunakan pendekatan berikut.
Konfirmasikan bahwa paket
Microsoft.Extensions.Localizationdirujuk oleh proyek.Catatan
Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bawah Install dan kelola paket di alur kerja konsumsi Package (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.
Pastikan bahwa namespace Microsoft.Extensions.Localization tersedia untuk komponen proyek Razor melalui entri dalam file proyek
_Imports.@using Microsoft.Extensions.LocalizationBuat kelas dummy dengan nama kelas yang bebas. Dalam contoh berikut:
- Aplikasi ini menggunakan
BlazorSamplenamespace, dan aset pelokalan menggunakanBlazorSample.Localizationnamespace. - Kelas dummy diberi nama
SharedResource. - File kelas ditempatkan di
Localizationfolder di akar aplikasi.
Catatan
Jangan gunakan file perancang yang dibuat secara otomatis (misalnya,
SharedResources.Designer.cs). Kelas "dummy" dimaksudkan untuk berfungsi sebagai kelas sumber daya yang digunakan bersama. Kehadiran file perancang menyebabkan terjadinya tabrakan pada namespace.Localization/SharedResource.cs:namespace BlazorSample.Localization; public class SharedResource { }- Aplikasi ini menggunakan
Buat file sumber daya bersama dengan Build Action
Embedded resource. Dalam contoh berikut:File ditempatkan di
Localizationfolder dengan kelas dummySharedResource(Localization/SharedResource.cs).Beri nama file sumber daya agar sesuai dengan nama kelas dummy. Contoh file berikut menyertakan file pelokalan default dan file untuk pelokalan Spanyol (
es).Localization/SharedResource.resxLocalization/SharedResource.es.resx
Peringatan
Saat mengikuti pendekatan di bagian ini, Anda tidak dapat mengatur LocalizationOptions.ResourcesPath dan menggunakan IStringLocalizerFactory.Create secara bersamaan untuk memuat sumber daya.
Untuk merujuk kelas dummy yang disuntikkan dalam sebuah IStringLocalizer<T> komponen, tempatkan sebuah direktif Razor untuk ruang nama pelokalan atau sertakan ruang nama pelokalan dalam referensi kelas dummy. Dalam contoh berikut:
- Contoh pertama menyatakan
Localizationnamespace untukSharedResourcekelas dummy dengan direktif@using. - Contoh kedua menyatakan
SharedResourcenamespace kelas dummy secara eksplisit.
Razor Dalam komponen, gunakan salah satu pendekatan berikut:
@using Localization @inject IStringLocalizer<SharedResource> Loc@inject IStringLocalizer<Localization.SharedResource> Loc- Contoh pertama menyatakan
Untuk panduan tambahan, lihat Globalisasi dan pelokalan di ASP.NET Core.
Pengaturan ulang lokasi menggunakan panel "Sensor" di alat pengembang
Saat menggunakan penimpaan lokasi melalui panel Sensors di alat pengembang Google Chrome atau Microsoft Edge, bahasa cadangan diatur ulang setelah prarendering. Hindari mengatur bahasa menggunakan panel Sensor saat pengujian. Atur bahasa menggunakan pengaturan bahasa browser.
Untuk informasi selengkapnya, lihat Blazor Pelokalan tidak berfungsi dengan InteractiveServer (dotnet/aspnetcore #53707).
Sumber Daya Tambahan:
- jalur dasar aplikasi ASP.NET Core Blazor
- Globalization dan pelokalan di ASP.NET Core
- Lokalisasi Anotasi Data di API Minimal dan Blazor
- API Minimal: Melokalisasi pesan validasi
- Globalizing dan melokalisasi aplikasi .NET
- Sumber daya dalam File .resx
- Lokalisasi & Generik
-
Memanggil
InvokeAsync(StateHasChanged)menyebabkan halaman mundur ke budaya default (dotnet/aspnetcore#28521) -
Blazor Pelokalan tidak berfungsi dengan InteractiveServer (
dotnet/aspnetcore#53707) (Penimpaan lokasi menggunakan panel "Sensor"))
- jalur dasar aplikasi ASP.NET Core Blazor
- Globalization dan pelokalan di ASP.NET Core
- Globalizing dan melokalisasi aplikasi .NET
- Sumber daya dalam File .resx
- Lokalisasi & Generik
-
Memanggil
InvokeAsync(StateHasChanged)menyebabkan halaman mundur ke budaya default (dotnet/aspnetcore#28521) -
Blazor Pelokalan tidak berfungsi dengan InteractiveServer (
dotnet/aspnetcore#53707) (Penimpaan lokasi menggunakan panel "Sensor"))
ASP.NET Core