" label without an extra round-trip.
+ */
+ async function init() {
+ const persisted = settings.i18nLocale
+ if (persisted && isSupported(persisted)) {
+ locale.value = persisted
+ // Warm the OS cache for the Settings picker label even when the
+ // persisted choice overrides it.
+ detectOsLocale().catch(() => {})
+ return
+ }
+ locale.value = await detectOsLocale()
+ }
+
+ /** Switch the active locale. `null` means "follow system" — the persisted
+ * choice is cleared and the live locale falls back to the OS reading. */
+ async function setLocale(next: SupportedLocale | null) {
+ if (next === null) {
+ await settings.setI18nLocale(null)
+ locale.value = await detectOsLocale()
+ return
+ }
+ await settings.setI18nLocale(next)
+ locale.value = next
+ }
+
+ return { locale, setLocale, init, t, osLocale: osLocaleRef }
+}
diff --git a/locales/en.json b/locales/en.json
new file mode 100644
index 0000000..c6d4417
--- /dev/null
+++ b/locales/en.json
@@ -0,0 +1,34 @@
+{
+ "settings": {
+ "language": {
+ "label": "Language",
+ "description": "UI display language",
+ "system_default": "System default: {name}",
+ "system_default_pending": "System default"
+ }
+ },
+ "nav": {
+ "nodes": "Nodes",
+ "files": "Files",
+ "wallet": "Wallet",
+ "settings": "Settings"
+ },
+ "header": {
+ "title": "Autonomi",
+ "active_transfers": "{count} active",
+ "connecting": "Connecting",
+ "connecting_tooltip": "Connecting to the Autonomi network",
+ "connected": "Network",
+ "connected_tooltip": "Connected to the Autonomi network",
+ "offline": "Offline · Retry",
+ "offline_tooltip": "Connection failed — click to retry",
+ "connect_wallet": "Connect Wallet"
+ },
+ "sidebar": {
+ "pre_release": "PRE-RELEASE",
+ "update_available": "Update Available",
+ "update_pre_release_tag": "Pre-Release",
+ "network_devnet": "DEVNET",
+ "network_sepolia": "SEPOLIA TESTNET"
+ }
+}
diff --git a/locales/ja.json b/locales/ja.json
new file mode 100644
index 0000000..0341e44
--- /dev/null
+++ b/locales/ja.json
@@ -0,0 +1,35 @@
+{
+ "_translator_notes": "Machine-translated baseline. Community polish via PR welcome.",
+ "settings": {
+ "language": {
+ "label": "言語",
+ "description": "UI 表示言語",
+ "system_default": "システムのデフォルト: {name}",
+ "system_default_pending": "システムのデフォルト"
+ }
+ },
+ "nav": {
+ "nodes": "ノード",
+ "files": "ファイル",
+ "wallet": "ウォレット",
+ "settings": "設定"
+ },
+ "header": {
+ "title": "Autonomi",
+ "active_transfers": "{count} 件処理中",
+ "connecting": "接続中",
+ "connecting_tooltip": "Autonomi ネットワークに接続中",
+ "connected": "ネットワーク",
+ "connected_tooltip": "Autonomi ネットワークに接続済み",
+ "offline": "オフライン · 再試行",
+ "offline_tooltip": "接続に失敗しました — クリックして再試行",
+ "connect_wallet": "ウォレットを接続"
+ },
+ "sidebar": {
+ "pre_release": "プレリリース",
+ "update_available": "アップデート利用可能",
+ "update_pre_release_tag": "プレリリース",
+ "network_devnet": "DEVNET",
+ "network_sepolia": "SEPOLIA テストネット"
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index ae4d91b..7816bdf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "ant-gui",
- "version": "0.6.7",
+ "version": "0.7.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ant-gui",
- "version": "0.6.7",
+ "version": "0.7.0",
"dependencies": {
"@pinia/nuxt": "^0.5.0",
"@reown/appkit": "^1.8.19",
@@ -14,6 +14,7 @@
"@tauri-apps/api": "^2.0.0",
"@tauri-apps/plugin-dialog": "^2.0.0",
"@tauri-apps/plugin-opener": "^2.0.0",
+ "@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.0.0",
"@tauri-apps/plugin-updater": "^2.0.0",
"@wagmi/core": "^3.4.0",
@@ -21,6 +22,7 @@
"pinia": "^2.2.0",
"viem": "^2.47.1",
"vue": "^3.5.0",
+ "vue-i18n": "^11.4.2",
"vue-router": "^4.4.0"
},
"devDependencies": {
@@ -1063,6 +1065,67 @@
"node": ">=18"
}
},
+ "node_modules/@intlify/core-base": {
+ "version": "11.4.2",
+ "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.4.2.tgz",
+ "integrity": "sha512-7fpuCcVmeLv2T9qHsARqGvh8xt+sV2fH+Q+gMHFwB/rPXzo85DpbJFKn7dBH1L5p0c2cSh2DW+2h/64EKrISmA==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/devtools-types": "11.4.2",
+ "@intlify/message-compiler": "11.4.2",
+ "@intlify/shared": "11.4.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/devtools-types": {
+ "version": "11.4.2",
+ "resolved": "https://registry.npmjs.org/@intlify/devtools-types/-/devtools-types-11.4.2.tgz",
+ "integrity": "sha512-3u8EN1kB6EMSi96KXs5k7a8y2X2g4+h3X6iwVZU47cP4n+mTuq//WMjG588BzSp/2XQ/dTXo2BLUXX+XS+PNfA==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/core-base": "11.4.2",
+ "@intlify/shared": "11.4.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/message-compiler": {
+ "version": "11.4.2",
+ "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.4.2.tgz",
+ "integrity": "sha512-a6CDSGSMTGrg0BjD97x8TBYPf7qQMDlZipJ6UDfv/pd4OIym8TMlHu3MsH0bTNnRdAG2D6EFEykIgiQPqvtTkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/shared": "11.4.2",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/shared": {
+ "version": "11.4.2",
+ "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.4.2.tgz",
+ "integrity": "sha512-NzpHbguRCsOHDwxmlBa9qu/imc+/QWgsYUaK6FZeNC0wK8QfAbhqrktEp/haVzxU1aikH8IX4ytD+mfFEMi/9A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
"node_modules/@ioredis/commands": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.1.tgz",
@@ -5448,6 +5511,15 @@
"@tauri-apps/api": "^2.8.0"
}
},
+ "node_modules/@tauri-apps/plugin-os": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-os/-/plugin-os-2.3.2.tgz",
+ "integrity": "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
"node_modules/@tauri-apps/plugin-process": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.3.1.tgz",
@@ -14532,6 +14604,27 @@
"integrity": "sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==",
"license": "MIT"
},
+ "node_modules/vue-i18n": {
+ "version": "11.4.2",
+ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.4.2.tgz",
+ "integrity": "sha512-sADDeKXqAGsPX6tK3t3y2ZiMpbVWN12tG+MhTiJ06rVoh58eGtM4wFyw3uWGbVkXByVp9Ne/AP+nSSzI+J9OAQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/core-base": "11.4.2",
+ "@intlify/devtools-types": "11.4.2",
+ "@intlify/shared": "11.4.2",
+ "@vue/devtools-api": "^6.5.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ },
+ "peerDependencies": {
+ "vue": "^3.0.0"
+ }
+ },
"node_modules/vue-router": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
diff --git a/package.json b/package.json
index 27d5e17..edfcefe 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"@tauri-apps/api": "^2.0.0",
"@tauri-apps/plugin-dialog": "^2.0.0",
"@tauri-apps/plugin-opener": "^2.0.0",
+ "@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.0.0",
"@tauri-apps/plugin-updater": "^2.0.0",
"@wagmi/core": "^3.4.0",
@@ -27,6 +28,7 @@
"pinia": "^2.2.0",
"viem": "^2.47.1",
"vue": "^3.5.0",
+ "vue-i18n": "^11.4.2",
"vue-router": "^4.4.0"
},
"devDependencies": {
diff --git a/pages/settings.vue b/pages/settings.vue
index 706fffd..4038985 100644
--- a/pages/settings.vue
+++ b/pages/settings.vue
@@ -107,6 +107,23 @@
+
+
+
+
{{ $t('settings.language.label') }}
+
{{ $t('settings.language.description') }}
+
+
+
+