存档

文章标签 ‘Javascript’

react-i18next 进阶用法

2025年4月14日 没有评论

在过去的 React 和 React Native 项目里,对于多语言处理,使用的是 react-i18next 来处理的。今天给大家分享下这个库的一些进阶用法和注意事项。

其实一开始的时候,我自己是有点困惑的,react-i18next 和 i18next 是什么关系?为什么项目要安装这2个库,而不是一个?而且为什么在代码里如何从 i18next 里导入某些变量会出现非预期的结果。所以这里也给小伙伴解释下,react-18next 是对 i18next 的 react 版本封装。换句话来说,一般情况下,大家直接使用 react-i18next 库就可以了。

安装很简单:

npm install react-i18next i18next --save

进阶一、兼容性问题

如果你的代码在运行时出现了下面的错误:
i18next::pluralResolver:
Your environment seems not to be Intl API compatible,
use an Intl.PluralRules polyfill.
Will fallback to the compatibilityJSON v3 format handling.
那么按照官方的说明(https://www.i18next.com/how-to/faq#why-are-my-plural-keys-not-working),表示当前环境不兼容 Intl API。

解决方法:

npm install intl-pluralrules --save

然后在多语言的初始化文件里导入:

import 'intl-pluralrules'

这取决于你的 项目结构,可能就在 index.js 里,我们的项目就是在 i18n.ts 文件里。

这个问题,在我们的 React Native 项目里有碰到过。

进阶二,传字段

例如有下面的 json 文件:

{
    "error": {
        "required": "{{field}}必填",
        "invalid": "无效的{{field}}"
    }
}

那么使用时,就是这样使用的:t(‘error.required’, { field: t(‘Email’) })

进阶三,自定义多语言层级分隔符

默认情况下,代码里使用 . 来表示层级,例如 error.required,当然也可以使用下面的配置来更改为使用 “/”:

i18n.use(initReactI18next).init({
  // ...
  keySeparator: '/'
})

那么前面的调用就成了 t(‘error/required’, { field: t(‘Email’) }),我是觉得这个一般情况下是不必无苦硬吃的,可能在特殊场合需要使用。大家看看就可以。

进阶四,自动单复数

i18next 对于自动单复数有预定的约定,只需要在 key 后面添加 “_other” 即可,当然前提是对应的语言描述有复数的用法哈。

{
"hours": "{{ count }} hour",
 "hours_other": "{{ count }} hours",
}

t('hours', { count: 5 }) 
// 5 hours

对于 0 来说,实际来看,会使用复数的翻译,例如 0 hours。如果需要为 0 来单独定义的话,可以添加 “_zero”,例如:

"hours_zero": "Now"

需要提醒的是,如果这里内置的 _zero、_other 和你的多语言冲突了,还是有这个可能的,那么可以修改使用自定义分隔符,例如下面这样:

// i18n.ts
i18n.use(initReactI18next).init({
  ...  // 其它配置   
  pluralSeparator: '__', // 双下划线
})

具体使用:

{
    "days": "{{count}} day",
    "days__other": "{{count}} days",
}

进阶五,Trans 组件

这里直接借用网上的一个示例,假如要显示下面的文字“你好 {userName},你有 {count} 条未读消息。点击查看。”,并且还需要支持点击操作。

在以前的写法中,我们需要将这句话单独的拆开,使用不同的组件包装起来,例如 count 希望是一个
红色的字体之类的,还要放到不同的多语言 key 里。太费劲了。

使用 Trans 组件,可以这么写,大家琢磨琢磨,是不是简单很多。

// en.json
{
    "userMessagesUnread": "Hello <1>{{userName}}</1>, you have {{count}} unread message. <5>Click to view</5>.",
    "userMessagesUnread_other": "Hello <1>{{userName}}</1>, you have {{count}} unread messages.  <5>Click to view</5>."
}

<Trans
    defaults={t('userMessagesUnread')}
    values={{ count, userName }}
    parent={Text}
    components={{
        1: <Text style={{ fontWeight: '500' }} />,
        5: <Text style={{ color: '#4682A9' }} onPress={() => {}} />
    }}
/>

可以看到,通过使用 components 属性,借助索引可以将指定位置的元素给替换包装起来。那么有人就问了,为什么这里是数字1和5,而不是其它的呢?

Trans 组件将上面的文本转换为下面的结构:

[
  'Hello ',
  { children: [{ user_name: 'Admin' }] },
  ', you have ',
  { count: 10 },
  ' unread messages. ',
  { children: ['Click to view'] },
  '.'
]

这么来看,是不是基于 0 的索引位置就出来啦。

更多内容,可以参考官方文档说明。

分类: 日常 标签: ,

js 获取网页的缩放比例

2016年10月8日 没有评论

随着硬件的发展,屏幕分辨率做的越来越大,相同的环境下,分辨率越高,视觉上看起来文字就越小。

操作系统本身提供了DPI的缩放,但是这个操作并不影响网页里的内容。值得幸庆的是,现代浏览器提供了网页内容的缩放功能。

那么,如果我们想获取浏览器的缩放比例以加载不同的样式和脚本,要怎么做呢?

现代浏览器提供了标准接口,window.devicePixelRatio 表示为设备上物理像素和设备独立像素的比例。

对于IE而言,IE 提供了 window.screen.deviceXDPI 和 window.screen.logicalXDPI 两个属性,deviceXDPI 就是对应的设备上的物理像素,而 logicalXDPI 就是对应了设备独立像素的比例。

下面就是代码了:

function getPageZoom() {
var ratio = 0,
screen = window.screen,
ua = navigator.userAgent.toLowerCase();

if (window.devicePixelRatio !== undefined) {
//现代浏览器直接支持
ratio = window.devicePixelRatio;
}
else if (~ua.indexOf(‘msie’)) {
//兼容低版本的IE浏览器
if (screen.deviceXDPI && screen.logicalXDPI) {
ratio = screen.deviceXDPI / screen.logicalXDPI;
}
}

if (ratio) {
ratio = Math.round(ratio * 100);
}

return ratio;
};

现在就可以根据自己的业务来做不同的处理了。

分类: 一句话, 日常 标签:

vs 2012 中js的intellisense智能提示

2012年9月17日 没有评论

在前面的博客里提及 Visual Studio 2012 RTM 已经出来有一段时间了,在 vs 以前的版本里,对于用户的智能提示做的还不够好,在 2012 的版本里大有改善,今天我们要分享的是如何在  vs 2012 里使用用户 js 的 intellisense 智能提示。

使用起来还是很简单的,比如说项目中有个 common.js 文件,这个时候只需要添加一个名为  common.intellisense.js 的文件就可以了。IDE 可以自动发现,在开始的时候我还不清楚,专门在页面里引用了下,结果运行时总报告错误,后来才发现这个技巧。

场景:在common.js 文件里有一个 load 方法,有2个参数 ,格式如下:

function load(url,charset){}

要实现 intellisense 智能提示,我们只需要在 common.intellisense.js 文件里添加下面的方法即可:

intellisense.annotate(window,{     “load”:function(){
/// <signature>
///   <summary>加载 js 文件</summary>
///   <param name=”url” type=”String”>js 文件的路径</param>
///   <param name=”charset” type=”String”>js 文件的字符编码,例如 utf-8</param>
///   <returns type=”Object” />
/// </signature> }, });

简单地说,我们只需要完善 intellisense.annotate 方法即可,该方法接受 2 个参数,第一个参数为想要进行智能提示的对象,示例中使用的是 window 对象,也可以是其它的对象;第二个参数是一个 json 对象,传递的是智能提示的参数列表。

智能提示以 signature 包含,常见的有 3个,summary 描述的是该方法的功能;param 是具体每一个参数的描述,还可以包括类型;return 是返回类型的描述。从事 C#/asp.net 、Java 的同学看着是不是觉得很熟悉呀~

此时,我们在页面中输入 load 时,就会出现描述的内容,输入参数时,就会提示参数相关的信息,感觉太酷了。

如果我们在文件头添加 reference 引用,就可以脱离上文中 js 代码必须和智能提示文件文件名对应的限制了,例如 /// <reference path=”Scripts/jquery-1.7.1-intellisense.js”/> 。如果你愿意,可以同时引入多个 reference 文件,需要提醒各位的是这里的斜杠可是 3 个哟,不要输入错了。

看起来很简单,对不对。如果有什么问题,快给我留言吧。