# tauri-plugin-sys-locale
A Tauri v2 plugin that reads the current operating system locale/language.
Works cross-platform (Windows, macOS, Linux, and thanks to the
`sys-locale` crate also iOS/Android), without needing any custom native
Swift/Kotlin code.
## 1. Installation (Rust side)
In your Tauri app's `Cargo.toml` (`src-tauri/Cargo.toml`):
```toml
[dependencies]
tauri-plugin-sys-locale = tauri-plugin-sys-locale = "*"
```
In `src-tauri/src/main.rs`:
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_sys_locale::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
```
## 2. Enable the capability
In `src-tauri/capabilities/default.json` (or whichever capability file
applies), add the permission:
```json
{
"identifier": "default",
"windows": ["main"],
"permissions": ["sys-locale:default"]
}
```
## 3. Installation (frontend side)
```bash
npm install tauri-plugin-sys-locale-api
```
## 4. Usage in the frontend
```ts
import { getLocale, getLocaleInfo } from "tauri-plugin-sys-locale-api";
const locale = await getLocale();
console.log(locale); // e.g. "de-DE"
const info = await getLocaleInfo();
console.log(info.language); // e.g. "de"
```
## 5. Using the functions directly from Rust (no JS/`invoke` needed)
The core logic lives in plain `pub fn`s in `src/api.rs` (not tagged with
`#[tauri::command]`), so you can call them from any Rust code — inside a
Tauri command, a background task, `setup()`, etc. — without going through
the frontend at all:
```rust
use tauri_plugin_sys_locale::api;
fn some_backend_logic() {
match api::get_locale() {
Ok(locale) => println!("System locale: {locale}"),
Err(e) => eprintln!("Could not determine locale: {e}"),
}
// or with locale + language split apart:
if let Ok(info) = api::get_locale_info() {
println!("locale={}, language={}", info.locale, info.language);
}
}
```
You can even call it directly inside `main.rs`, e.g. to set an initial
window title or pick a translation file before the app finishes starting:
```rust
fn main() {
let locale = tauri_plugin_sys_locale::api::get_locale()
.unwrap_or_else(|_| "en-US".into());
println!("Starting app with locale: {locale}");
tauri::Builder::default()
.plugin(tauri_plugin_sys_locale::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
```
The `commands.rs` module just wraps these same functions with
`#[tauri::command]` so the frontend can reach them via `invoke()` — both
paths call identical logic.
## Why `sys-locale` instead of custom native code?
The `sys-locale` crate already wraps the platform-specific APIs:
- Windows: `GetUserDefaultLocaleName`
- macOS/iOS: `NSLocale`
- Linux: environment variables (`LANG`, `LC_ALL`, ...)
- Android: JNI call to `Locale.getDefault()`
That means you don't need a separate `android/` or `ios/` directory with
Kotlin/Swift code, unlike many other Tauri plugins.
## Building the JS bindings
```bash
npm install
npm run build
```
This compiles `guest-js/index.ts` into `dist-js/index.js`,
`dist-js/index.cjs`, and the corresponding `.d.ts` type declarations.