Tauri 开发实践 — Tauri 主题&多语言设置开发

简介: 本文首发于微信公众号「前端徐徐」,介绍了在 Tauri 应用中实现窗口主题设置与多语言支持的方法。主题设置包括静态和动态两种方式,前者在应用初始化时设定,后者允许运行时更改。文章详细描述了通过 tauri-plugin-theme 插件实现动态主题变更的过程,并提供了代码示例。对于多语言支持,文章介绍了使用 i18next 进行多语言文件初始化及切换的方法。最后,提供了完整的源码链接,帮助读者更好地理解和实践。

本文首发微信公众号:前端徐徐。

前言

在现代应用开发中,用户界面的主题和多语言支持是提升用户体验的关键因素。本文将介绍如何在Tauri应用中实现窗口主题设置和多语言设置的开发,并提供更多实用的技巧和最佳实践。

我们在上一节中实现了集成本地数据库的操作,现在通过这个能力再实现主题&多语言的变更,可以充分的理解和实践Tauri。

主题设置的两种方式

在 Tauri 应用中,窗口主题可以通过两种方式进行设置:静态设置和动态设置。这里的静态和动态指的是原生窗口的动态和静态,不是 DOM 层面主题颜色的动态和静态。

静态设置

静态设置是指在应用初始化时就定义好的主题,不会在运行时发生变化。这种方式适用于那些不需要频繁更改主题的应用。

实现方法是在Tauri的配置文件 tauri.conf.json 中设置主题相关参数:

{
  "tauri": {
    "windows": [
      {
        "theme": "Light"
      }
    ]
  }
}

具体可参考:https://tauri.app/v1/api/config/#theme

动态设置

动态设置允许用户在应用运行时更改主题。这种方式提供了更高的灵活性,适用于需要根据用户偏好或系统设置自动调整主题的应用。

当然,为了更好的体验,我们一般都是动态设置主题的方案,不过在 Tauri 中暂时没有提供相应的 API,然后作者通过查询资料,发现了一个开源插件可以实现,下面就详细讲解一下如何动态实现主题的变更。

主题变更的具体实现

整体思路如下所示:

这个流程是循环往复的,闭合整个主题变更的流程,下面就是细节实现了:

倒入插件tauri-plugin-theme

具有参考:https://github.com/wyhaya/tauri-plugin-theme

需要注意的是:tauri1 和 tauri2 在使用的时候有所区别,引入的版本也会不一样,作者的版本是 V1,因为 V2 现在还是 beta 版本。

依赖添加:

tauri-plugin-theme = "0.2.0"

主进程代码修改:

引入 tauri_plugin_theme,然后在 plugin 里面添加并注册上下文。

// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri_plugin_theme::ThemePlugin; 
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}
fn main() {
    let mut ctx = tauri::generate_context!();
    tauri::Builder::default()
        .plugin(tauri_plugin_sql::Builder::default().build())
        .plugin(ThemePlugin::init(ctx.config_mut()))
        .invoke_handler(tauri::generate_handler![greet])
        .run(ctx)
        .expect("error while running tauri application");
}

主题修改核心逻辑

App.tsx 中需要和框架联动注册全局 DOM 主题色。

import { HashRouter } from "react-router-dom";
import { ConfigProvider, theme } from "antd";
import { ConfigProvider as SemiConfigProvider } from '@douyinfe/semi-ui';
import { useEffect, useState } from "react";
import Router from './routes';
import GlobalContext from "./context/global";
import { getStore, setStore } from "./bridge";
function App() {
  const [themeData, setThemeData] = useState('')
  // 修改主题
  const changeTheme = (val: 'darkAlgorithm' | 'defaultAlgorithm') => {
    setThemeData(val)
    setStore('theme', val)
    const body = document.body;
    if (val === 'darkAlgorithm') {
      body.setAttribute('theme-mode', 'dark');
    } else {
      body.removeAttribute('theme-mode');
    }
  }
  useEffect(() => {
    // 初始化主题  
    const initData = async () => {
      try {
        const theme = await getStore('theme')
        if (theme) {
          changeTheme(theme as "defaultAlgorithm" | "darkAlgorithm")
        } else {
          changeTheme('defaultAlgorithm')
        }
      } catch (error) {
        console.error(error)
        changeTheme('defaultAlgorithm')
      }
    }
    initData()
  }, [])
  return themeData ? <ConfigProvider theme={{ algorithm: themeData === 'darkAlgorithm' ? theme.darkAlgorithm : theme.defaultAlgorithm }}>
    <SemiConfigProvider>
      <GlobalContext.Provider value={{
        changeTheme,
        themeData
      }}>
        <HashRouter>
          <Router />
        </HashRouter>
      </GlobalContext.Provider>
    </SemiConfigProvider>
  </ConfigProvider> : null
}
export default App;

ThemeIcon 组件实现整体的主题手动切换逻辑。

import GlobalContext from "@/context/global";
import { IconMoon, IconSun } from "@douyinfe/semi-icons";
import { Button, Modal } from "@douyinfe/semi-ui";
import { invoke } from "@tauri-apps/api/tauri";
import { useContext } from "react";
import { platform } from '@tauri-apps/api/os';
import { useTranslation } from "react-i18next";
type Theme = "auto" | "light" | "dark";
const setNativeTheme = (theme: Theme) => {
  setTimeout(() => {
    invoke("plugin:theme|set_theme", {
      theme,
    }).catch((err) => {
      alert(err.toString());
    });
  }, 100)
};
const ThemeIcon = () => {
  const { changeTheme, themeData } = useContext(GlobalContext);
  const [modal, contextHolder] = Modal.useModal();
  const {t} = useTranslation()
  const changeThemeAction = async () => {
    const doAction = () => {
      if (themeData === "darkAlgorithm") {
        changeTheme("defaultAlgorithm");
        setNativeTheme("light")
      } else {
        changeTheme("darkAlgorithm");
        setNativeTheme("dark")
      }
    }
    const platformName = await platform();
    if (platformName === 'win32') {
      modal.confirm({
        title:t('SwitchTheme'),
        content: t('Switching themes requires restarting the application. Do you want to continue?'),
        okText: t('Confirm'),
        cancelText: t('Cancel'),
        onOk: () => {
          doAction()
        },
      });
    } else {
      doAction()
    }
  };
  return <>
    <Button
      theme="borderless"
      style={{
        color: "var(--semi-color-text-2)",
      }}
      icon={
        themeData === "darkAlgorithm" ? <IconSun /> : <IconMoon />
      }
      onClick={() => changeThemeAction()}
    ></Button>
    {contextHolder}
  </>
}
export default ThemeIcon;

这里需要注意,windows 在切换主题的时候是需要重启应用的,为了更好的体验,我们需要提醒一下用户,如果是 Mac 端的话可以丝滑切换。

多语言设置的具体实现

这里多语言的设置其实也是分两块,一个是页面上的多语言,一个是原生标题和窗口的多语言,我们这里先实现页面上的多语言,窗口菜单的多语言会单独来讲,因为他涉及到整个菜单模块的改变。

页面上的多语言跟传统的 web端 的多语言没有太大区别,核心就是利用 i18n 实现。即安装相关依赖 ——》创建多语言配置文件——》多语言初始化——》利用 i18n 切换多语言。

核心代码如下:

多语言文件初始化。

import i18n from "i18next"; 
import { initReactI18next } from 'react-i18next';
import enUsTrans from "./en-us.json";
import zhCnTrans from "./zh-cn.json";
i18n   
.use(initReactI18next)
.init({
  resources: {
    en: {
      translation: enUsTrans,
    },
    zh: {
      translation: zhCnTrans,
    },
  },
  detection: {
    order: ['queryString', 'cookie'],
    caches: ['cookie']
  },
  fallbackLng: 'zh', 
  debug: false,
  interpolation: {
    escapeValue: false,
  },
})
export default i18n

切换多语言。

const changeLang = (lang?: string) => {
    if (lang) {
      setStore('lang', lang)
      setCurrentLang(lang);
      i18n.changeLanguage(lang);
    } else {
      if (currentLang === "zh") {
        setStore('lang', "en")
        setCurrentLang("en");
        i18n.changeLanguage("en");
      } else {
        setStore('lang', "zh")
        setCurrentLang("zh");
        i18n.changeLanguage("zh");
      }
    }
  };

到这里基本的多语言就差不多实现了。

源码

https://github.com/Xutaotaotao/XTools/tree/feature-theme-lang

总结

通过以上的详细介绍,我们了解了如何在Tauri应用中实现窗口主题和多语言设置。从静态和动态主题设置,到多语言支持的实现,这些内容涵盖了Tauri开发过程中的多个重要方面。

实现好的主题和语言支持不仅能够提升用户体验,还能扩大应用的受众群体。在实际开发中,可能还需要根据具体项目的需求进行调整和优化。希望本文能为你的Tauri应用开发提供有价值的参考和启发!

如果你在实现过程中遇到任何问题,欢迎进一步讨论和交流。祝你开发顺利!

相关文章
|
2天前
|
存储 前端开发 安全
Tauri 开发实践 — Tauri 原生能力
本文介绍了如何使用 Tauri 框架构建桌面应用,并详细解释了 Tauri 提供的原生能力,包括文件系统访问、系统托盘、本地消息通知等。文章通过一个具体的文件下载示例展示了如何配置 Tauri 来使用文件系统相关的原生能力,并提供了完整的代码实现。最后,文章还提供了 Github 源码链接,方便读者进一步学习和参考。
18 1
Tauri 开发实践 — Tauri 原生能力
|
2天前
|
Rust 前端开发 JavaScript
Tauri 开发实践 — Tauri 日志记录功能开发
本文介绍了如何为 Tauri 应用配置日志记录。Tauri 是一个利用 Web 技术构建桌面应用的框架。文章详细说明了如何在 Rust 和 JavaScript 代码中设置和集成日志记录,并控制日志输出。通过添加 `log` crate 和 Tauri 日志插件,可以轻松实现多平台日志记录,包括控制台输出、Webview 控制台和日志文件。文章还展示了如何调整日志级别以优化输出内容。配置完成后,日志记录功能将显著提升开发体验和程序稳定性。
11 1
Tauri 开发实践 — Tauri 日志记录功能开发
|
2天前
|
JSON 自然语言处理 数据格式
Tauri 开发实践 — Tauri 自定义多语言菜单开发
本文介绍了如何在 Tauri 应用中实现自定义菜单并支持多语言。首先,通过 `Translator` 类加载和解析多语言 JSON 文件,实现简单的翻译功能。接着,创建包含文件、编辑和窗口子菜单的基本菜单结构,并根据当前语言进行翻译。最后,在主函数中读取语言设置,创建菜单并处理菜单事件,确保应用的国际化和用户体验。源码可在 GitHub 上查看。
13 2
|
2天前
|
存储 Rust 前端开发
Tauri 开发实践 — Tauri 配置介绍
本文首发于微信公众号“前端徐徐”,主要讲解`package.json`、`Cargo.toml`及`tauri.conf.json`三个文件的配置。其中,`tauri.conf.json`最为复杂,涉及众多配置项。`package.json`用于配置前端依赖与脚本;`Cargo.toml`用于声明Rust应用依赖;`tauri.conf.json`则管理前端资源、API白名单等。这些配置对于Tauri应用的开发至关重要。
16 5
|
2天前
|
Rust 前端开发 JavaScript
Tauri 开发实践— Tauri 怎么样
Tauri 是一个用于构建高效、小型二进制文件的框架,适用于所有主流桌面及移动平台。开发人员可以利用任何可编译为 HTML、JavaScript 和 CSS 的前端框架构建应用,并借助 Rust、Swift 或 Kotlin 进行后端开发。Tauri 采用三层架构,包括 tauri-app、WRY(跨平台 Webview 库)和 TAO(跨平台窗口管理器)。相较于 Electron,Tauri 使用系统内置浏览器引擎执行 Web APP,具有更小的资源占用和更高性能。详情见:[Tauri 官网](https://tauri.app/)。
13 0
Tauri 开发实践— Tauri 怎么样
|
2天前
|
Rust 前端开发 iOS开发
Tauri 开发实践— Tauri 工程搭建
本文首发于微信公众号“前端徐徐”,介绍了在 macOS 环境下使用 Rust 和 Tauri 构建跨平台桌面应用的过程。首先需安装 Rust 及系统依赖,参考链接:[Rust 入门](https://www.rust-lang.org/zh-CN/learn/get-started) 和 [Tauri 前置条件](https://tauri.app/zh-cn/v1/guides/getting-started/prerequisites)。
13 0
Tauri 开发实践— Tauri 工程搭建
|
2月前
|
Rust 资源调度 内存技术
Tauri——如何创建一个tauri项目
Tauri——如何创建一个tauri项目
41 4
|
2月前
|
前端开发 JavaScript Android开发
React Native 快速入门简直太棒啦!构建跨平台移动应用的捷径,带你开启高效开发之旅!
【8月更文挑战第31天】React Native凭借其跨平台特性、丰富的生态系统及优异性能,成为移动应用开发的热门选择。它允许使用JavaScript和React语法编写一次代码即可在iOS和Android上运行,显著提升开发效率。此外,基于React框架的组件化开发模式使得代码更加易于维护与复用,加之活跃的社区支持与第三方库资源,加速了应用开发流程。尽管作为跨平台框架,React Native在性能上却不输原生应用,支持原生代码优化以实现高效渲染与功能定制。对于开发者而言,React Native简化了移动应用开发流程,是快速构建高质量应用的理想之选。
44 0
|
5月前
|
Web App开发 Rust 前端开发
【一起学Rust | 框架篇 | Tauri2.0框架】Tauri App开启远程调试功能
【一起学Rust | 框架篇 | Tauri2.0框架】Tauri App开启远程调试功能
513 0
|
5月前
|
自然语言处理 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的国际化与本地化支持
【4月更文挑战第30天】Flutter支持国际化与本地化,借助`Intl`包和`Localizations`类,帮助开发者实现多语言应用。`Intl`提供日期、时间格式化,而`Localizations`管理不同语言环境的资源。在`pubspec.yaml`添加`intl`依赖,创建本地化资源文件并定义`LocalizationsDelegate`。通过`Localizations.of()`获取本地化资源,实现应用适应不同语言环境。
199 0
【Flutter前端技术开发专栏】Flutter中的国际化与本地化支持