前端国际化:别让你的应用只懂一种语言

前端国际化:别让你的应用只懂一种语言

毒舌时刻

这应用写得跟方言似的,出了本地就没人懂。

各位前端同行,咱们今天聊聊前端国际化。别告诉我你的应用还只有中文版本,那感觉就像在国际会议上只说方言——能说,但没人懂。

为什么你需要国际化

最近看到一个项目,想拓展海外市场,但所有文本都是硬编码在代码里的。我就想问:你是在做本地应用还是在做国际产品?

反面教材

// 反面教材:硬编码文本 function App() { return ( <div> <h1>欢迎来到我的网站</h1> <p>这是一个示例应用</p> <button>点击我</button> <div> <h2>产品列表</h2> <ul> <li>产品 1</li> <li>产品 2</li> <li>产品 3</li> </ul> </div> </div> ); } export default App; 

毒舌点评:这代码,就像在写日记,只有自己能看懂。

正确姿势

1. i18next

// 正确姿势:i18next // 1. 配置 // i18n.js import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; const resources = { zh: { translation: { welcome: '欢迎来到我的网站', description: '这是一个示例应用', button: '点击我', products: '产品列表', product1: '产品 1', product2: '产品 2', product3: '产品 3' } }, en: { translation: { welcome: 'Welcome to my website', description: 'This is a sample application', button: 'Click me', products: 'Product List', product1: 'Product 1', product2: 'Product 2', product3: 'Product 3' } } }; i18n .use(initReactI18next) .init({ resources, lng: 'zh', fallbackLng: 'en', interpolation: { escapeValue: false } }); export default i18n; // 2. 使用 // App.jsx import React from 'react'; import { useTranslation } from 'react-i18next'; function App() { const { t, i18n } = useTranslation(); const changeLanguage = (lng) => { i18n.changeLanguage(lng); }; return ( <div> <div> <button onClick={() => changeLanguage('zh')}>中文</button> <button onClick={() => changeLanguage('en')}>English</button> </div> <h1>{t('welcome')}</h1> <p>{t('description')}</p> <button>{t('button')}</button> <div> <h2>{t('products')}</h2> <ul> <li>{t('product1')}</li> <li>{t('product2')}</li> <li>{t('product3')}</li> </ul> </div> </div> ); } export default App; // 3. 入口文件 // index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import './i18n'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); 

2. react-intl

// 正确姿势:react-intl // 1. 配置 // App.jsx import React from 'react'; import { IntlProvider, FormattedMessage } from 'react-intl'; const zhMessages = { welcome: '欢迎来到我的网站', description: '这是一个示例应用', button: '点击我', products: '产品列表', product1: '产品 1', product2: '产品 2', product3: '产品 3' }; const enMessages = { welcome: 'Welcome to my website', description: 'This is a sample application', button: 'Click me', products: 'Product List', product1: 'Product 1', product2: 'Product 2', product3: 'Product 3' }; function App() { const [locale, setLocale] = React.useState('zh'); const messages = locale === 'zh' ? zhMessages : enMessages; return ( <IntlProvider locale={locale} messages={messages}> <div> <div> <button onClick={() => setLocale('zh')}>中文</button> <button onClick={() => setLocale('en')}>English</button> </div> <h1><FormattedMessage /></h1> <p><FormattedMessage /></p> <button><FormattedMessage /></button> <div> <h2><FormattedMessage /></h2> <ul> <li><FormattedMessage /></li> <li><FormattedMessage /></li> <li><FormattedMessage /></li> </ul> </div> </div> </IntlProvider> ); } export default App; 

3. 日期和数字格式化

// 正确姿势:日期和数字格式化 import React from 'react'; import { useTranslation } from 'react-i18next'; function FormattingExample() { const { t, i18n } = useTranslation(); const formatDate = (date) => { return new Intl.DateTimeFormat(i18n.language).format(date); }; const formatNumber = (number) => { return new Intl.NumberFormat(i18n.language).format(number); }; return ( <div> <p>{t('currentDate')}: {formatDate(new Date())}</p> <p>{t('price')}: {formatNumber(12345.67)}</p> </div> ); } export default FormattingExample; 

毒舌点评:这才叫国际化,让你的应用在全球范围内都能被理解。

Read more

吃透 AM32 无人机电调:从源码架构到工作原理的全方位解析(附实践指南)(上)

开篇:为什么要深度剖析 AM32 电调? 作为多旋翼无人机的 “动力心脏”,电调(电子调速器)的性能直接决定了无人机的飞行稳定性、响应速度和续航能力。而 AM32 系列电调凭借开源性、高性价比、适配性强三大优势,成为了开源无人机社区的热门选择 —— 从入门级的 2204 电机到专业级的 2306 电机,从 3S 锂电池到 6S 高压电池,AM32 都能稳定驱动。 但很多开发者和爱好者在接触 AM32 源码时,常会陷入 “看得懂代码,看不懂逻辑” 的困境:为什么 FOC 算法要做坐标变换?DShot 协议的脉冲怎么解析?保护机制是如何实时触发的? 这篇博客将从硬件基础→源码架构→模块解析→工作原理→实践操作五个维度,逐行拆解 AM32 电调固件源码,帮你彻底搞懂

FPGA Debug:PCIE XDMA没有Link up(驱动检测不到xilinx PCIE设备)使用LTSSM定位问题

FPGA Debug:PCIE XDMA没有Link up(驱动检测不到xilinx PCIE设备)使用LTSSM定位问题

问题现象: 与驱动联调:驱动无法扫描到Xilinx的PCIE设备 通过ila抓取pcie_link_up信号:发现link up一直为低 问题分析:         出现这种情况,在FPGA中搭建测试环境,使用XDMA+BRAM的形式,减少其它模块的影响,框架如下: 1 检查PCIE的时钟 时钟,必须使用原理图上的GT Ref 差分时钟,通过IBUFDSGTE转为单端时钟 2 检查PCIE 复位 复位:PCIE复位信号有要求--上电后,PCIE_RESTN信号需在电源稳定后延迟一段时间再释放,通常是100ms以上 而这100ms的时间,系统主要做以下的事情: * 电源稳定时间 * 参考时钟稳定时间 * PCIe IP核的复位和初始化时间 * 链路训练时间 // 典型的100ms时间分配: 0-10ms   : 电源稳定 (Power Stable) 10-20ms  : 参考时钟稳定 (Refclk Stable)   20-30ms  : 复位释放和PLL锁定 (Reset Release

政安晨【零基础玩转开源AI项目】OpenClaw飞书通信端机器人配置指南(手把手配置OpenClaw飞书/Lark机器人,实现多渠道AI助手集成)(作者自己配置时留存使用,小伙伴们可酌情参考)

政安晨【零基础玩转开源AI项目】OpenClaw飞书通信端机器人配置指南(手把手配置OpenClaw飞书/Lark机器人,实现多渠道AI助手集成)(作者自己配置时留存使用,小伙伴们可酌情参考)

政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 目录 一、前言 1.1 为什么需要配置飞书机器人? 1.2 飞书机器人支持的功能 二、准备工作 2.1 环境要求 2.2 OpenClaw安装(本篇主要介绍飞书端的配置,这里可参考我上一篇博客) 2.3 飞书账号要求 三、飞书应用创建 3.1 创建企业应用 3.2 获取应用凭证 编辑3.3 开通权限 3.4 配置事件订阅 Webhook URL配置 订阅事件 3.5

探索 SVG(静止无功发生器)基于 DSP + FPGA 主板的源码世界

探索 SVG(静止无功发生器)基于 DSP + FPGA 主板的源码世界

SVG 静止无功发生器 源码 dsp+FPGA主板 在电力系统领域,SVG(静止无功发生器)可是个相当重要的角色,它能快速补偿无功功率,提升电能质量。而实现 SVG 功能的核心之一,便是搭载了 DSP + FPGA 的主板,今天咱们就来扒一扒与之相关的源码奥秘。 DSP 在 SVG 中的角色与代码示意 DSP(数字信号处理器)擅长高速数据处理与复杂算法运算。在 SVG 系统里,它承担着数据采集分析、控制算法执行等关键任务。 先来看一段简单的 DSP 采集电流数据的代码示例(以 C 语言为例,这里只是示意核心逻辑,实际工程代码会更复杂且需适配具体芯片): #include <stdio.h> // 假设 ADC 转换后的数据存储在这个数组 int adc_current_