Tauri应用开发实践指南(6)— Tauri 主题多语言设置开发

news2024/12/23 1:12:14

前言

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

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

主题设置的两种方式

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

静态设置

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

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

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

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

动态设置

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

当然,为了更好的体验,我们一般都是动态设置主题的方案,不过在 <font style="color:rgb(38, 38, 38);">Tauri</font> 中暂时没有提供相应的 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 实现。即安装相关依赖 ——》创建多语言配置文件——》多语言初始化——》利用 <font style="color:rgb(38, 38, 38);">i18n</font> 切换多语言。

核心代码如下:

多语言文件初始化。

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应用开发提供有价值的参考和启发!

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2106497.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式微服务项目mysql不同数据库之间跨库联查,使用快捷表实现跨库分页查询

场景: 在分布式微服务项目中,经常有需要关联查询其他表信息的业务,但分布式项目中分库是肯定的,不同服务的数据库服务可能部署在不同的机器上,以下是几种跨库联查分页的几种解决方式 一、快捷表联查【推荐】 1、联合与被联合的数据库服务 FEDERATED 引擎都要开启…

Cpp学习手册-基础学习

首先你要去网上下载对应的运行软件&#xff0c;先把对应的 C 环境配置好&#xff0c;配置好了我们就可以开始我们的C 学习之旅了。希望通过学习我们能够成为一个比较不错的 C 开发工程师。我也会持续更新 C 知识。 1. C语法基础 当我通过 CLion 工具创建了一个新的 Project 。…

linux(ubuntu)安装QT-ros插件

Linux下的qt安装ros插件 查看qt版本和对应的ros插件版本查看qt版本查看 qt creator 版本 qt creator进行更新升级下载版本对应的ros_qtc_plugin 插件插件安装安装成功 查看qt版本和对应的ros插件版本 想要qt与ros联合开发&#xff0c;我门需要在qt creator中添加ros的插件&…

髓鞘少突胶质细胞糖蛋白;MOG 35-55 ;CAS:149635-73-4

【MOG35-55 简介】 髓鞘少突胶质细胞糖蛋白&#xff08;Myelin Oligodendrocyte Glycoprotein&#xff0c;MOG&#xff09;是一种在中枢神经系统中表达的糖蛋白&#xff0c;主要由少突胶质细胞产生&#xff0c;并在髓鞘形成中发挥作用。 【中文名称】髓鞘少突胶质细胞糖蛋白 …

day43(9/4)——k8s

一、前期准备 1、配置主机映射 [rootk8s-master ~]# vim /etc/hosts 192.168.8.168 k8s-master 192.168.8.176 k8s-node1 192.168.8.177 k8s-node2 [rootk8s-master ~]# ping k8s-master 2、配置yum源 [rootk8s-master yum.repos.d]# vim kubernetes.repo [kubernetes…

山东大学机试试题合集

&#x1f370;&#x1f370;&#x1f370;高分篇已经涵盖了绝大多数的机试考点&#xff0c;由于临近预推免&#xff0c;各校的机试蜂拥而至&#xff0c;我们接下来先更一些各高校机试题合集&#xff0c;算是对前边学习成果的深入学习&#xff0c;也是对我们代码能力的锻炼。加油…

SQL通用语法、SQL分类以及DDL

1.SQL 1.1SQL通用语法 1.SQL语句可以单行或多行书写&#xff0c;以分号结尾2.SQL语句可以使用空格/缩进来增强语句的可读性。3.MySQL数据库的SQL语句不区分大小写&#xff0c;关键字建议使用大写。4.注释&#xff1a; 单行注释&#xff1a;–空格 注释内容或#注释内容&#…

浏览器控制台安装并使用npm

​ 有时候想调用npm里的库跟api&#xff0c;正常我们项目环境里可以直接调用&#xff0c;其实也可以直接在开发者工具的控制台里安装&#xff0c;然后调用安装好的库的api Github安装方式&#xff1a;console-importer 安装完成后我们就可以安装第三方的库&#xff0c;然后直…

【Hot100算法刷题集】哈希-01-两数之和(暴力枚举再优化,也不是哈希表的对手)

&#x1f3e0;关于专栏&#xff1a;专栏用于记录LeetCode中Hot100专题的所有题目 &#x1f3af;每日努力一点点&#xff0c;技术变化看得见 题目转载 题目描述 &#x1f512;link->题目跳转链接 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中…

数据结构-栈、队列-相关练习

数据结构-栈、队列-相关练习 1.用队列实现栈2.用栈实现队列3.设计循环队列 1.用队列实现栈 用队列实现栈 题目概述&#xff1a;请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 em…

《信息技术 云计算 边缘云通用技术要求》国家标准发布,九州未来参编

日前&#xff0c;2024年第17号国家标准公告发布&#xff0c;由全国信标委云计算标准工作组组织制定、九州未来作为行业专家单位参编的《信息技术 云计算 边缘云通用技术要求》国家标准正式获批发布。 边缘云作为云计算技术的有效补充和拓展&#xff0c;能够实现将云计算能力拓展…

信捷 XD PLC 数据寄存器的偏移量

信捷 XD PLC&#xff0c;数据寄存器 D 可用作软元件的偏移量&#xff0c;使得软元件的使用更加简单和便于控制。 格式&#xff1a;Dn[Dm]、Xn[Dm]、Yn[Dm]、Mn[Dm]等。 带偏移的位组成的字寄存器&#xff1a;DXn[Dm]表示 DX[nDm]。 带偏移的软元件&#xff0c;偏移量只可用软…

信息安全发展阶段与形式

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 0x01&#xff1a;信息安全的发展阶段 信息安全的发展阶段可以参照下面的思维导图&#xff1a; 0x02&#xff1a;我国的信息安全形式 2013 年&#xff0c;“棱镜门” 事件在全球持续发酵&#xf…

创业型公司如何实现数字化营销突破?

​在当今数字化时代&#xff0c;创业型公司可谓机遇与挑战并存。如何利用数字化营销手段实现突破&#xff0c;成为发展关键。 一、现状之困 资源有限&#xff1a;创业型公司资金、人力相对匮乏&#xff0c;难在传统营销上大笔投入。 品牌知名度低&#xff1a;新公司在市场上认…

【启明智显技术分享】探讨CAN总线相关知识以及Model3C 2路CAN的应用

一、 CAN总线相关知识 CAN总线概述 CAN&#xff08;Controller Area Network&#xff09;总线是一种高实时性、高可靠性和灵活性的串行通信协议&#xff0c;广泛应用于汽车和工业控制系统中。它由德国BOSCH公司开发&#xff0c;最高速率可达到1Mbps&#xff0c;具有强大的检错…

一台手机一个ip地址吗?手机ip地址泄露了怎么办

在数字化时代&#xff0c;‌手机作为我们日常生活中不可或缺的一部分&#xff0c;‌其网络安全性也日益受到关注。‌其中一个常见的疑问便是&#xff1a;‌“一台手机是否对应一个固定的IP地址&#xff1f;‌”实际上&#xff0c;‌情况并非如此简单。‌本文首先解答这一问题&a…

jQuery入门(七)jQuery实现按钮分页

一、分页案例分析 功能分析&#xff1a;使用分页插件&#xff0c;实现分页&#xff0c;效果如下图&#xff1a; 二、实现思路和代码 2.1&#xff09;页面实现分析 1.引入分页插件的样式文件和 js 文件。 2. 定义当前页码和每页显示的条数。(分页必备信息) 3. 调用查询数据…

京东API接口:商品详情页呈现商品的全网价格数据信息

如今&#xff0c;不少品牌企业为更好销售商品、塑造品牌&#xff0c;都开设了自己的自有商城。那么&#xff0c;对于这类自有商城平台&#xff0c;该如何做才能更好地提升商品的呈现效果呢&#xff1f;一个比较好的建议是&#xff0c;在电商商品详情界面上呈现出商品的全网价格…

IMU助力JAXA空间站机器人

近日&#xff0c;日本宇宙航空研究开发机构&#xff08;JAXA&#xff09;宣布&#xff0c;在国际空间站&#xff08;ISS&#xff09;实验舱“希望号”&#xff08;Kibo&#xff09;上部署的一款移动摄像机器人将采用Epson M-G370系列惯性测量单元&#xff08;IMU&#xff09;。…

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——10.继承

1.继承的概念及定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保 持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象 程序设计的层…