使用 Moment 和 React-i18next 进行日期时间国际化
目录
前言
在开发国际化应用时,不仅需要对文本进行翻译,还需要对日期和时间格式进行国际化处理。本文将展示如何结合 moment
和 react-i18next
在 React 项目中进行日期和时间的国际化。
安装依赖
首先,我们需要安装必要的依赖包。
npm install moment react-i18next i18next
初始化 i18next
创建一个 i18n.js
文件,并初始化 i18next
。同时,我们需要动态设置 moment
的语言。
// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import moment from 'moment';
import 'moment/locale/zh-cn'; // 中文
import 'moment/locale/en-gb'; // 英文
const resources = {
en: {
translation: {
key: "hello world"
// 其他翻译...
}
},
zh: {
translation: {
key: "你好,世界"
// 其他翻译...
}
}
};
i18n
.use(initReactI18next)
.init({
resources,
lng: 'en', // 默认语言
fallbackLng: 'en',
interpolation: {
escapeValue: false
}
});
// 动态设置 moment 语言
i18n.on('languageChanged', (lng) => {
moment.locale(lng);
});
export default i18n;
自定义 Moment 语言包
根据需求,可以自定义 moment
的语言包。例如,定义中文语言包:
// src/i18n.js
// 自定义中文语言包
moment.updateLocale('zh-cn', {
months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
longDateFormat: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'YYYY-MM-DD',
LL: 'YYYY年MM月DD日',
LLL: 'YYYY年MM月DD日Ah点mm分',
LLLL: 'YYYY年MM月DD日ddddAh点mm分',
l: 'YYYY-M-D',
ll: 'YYYY年M月D日',
lll: 'YYYY年M月D日 HH:mm',
llll: 'YYYY年M月D日dddd HH:mm'
},
meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
meridiemHour: function (hour, meridiem) {
if (hour === 12) {
hour = 0;
}
if (meridiem === '凌晨' || meridiem === '早上' ||
meridiem === '上午') {
return hour;
} else if (meridiem === '下午' || meridiem === '晚上') {
return hour + 12;
} else {
// '中午'
return hour >= 11 ? hour : hour + 12;
}
},
meridiem: function (hour, minute, isLower) {
const hm = hour * 100 + minute;
if (hm < 600) {
return '凌晨';
} else if (hm < 900) {
return '早上';
} else if (hm < 1130) {
return '上午';
} else if (hm < 1230) {
return '中午';
} else if (hm < 1800) {
return '下午';
} else {
return '晚上';
}
},
calendar: {
sameDay: '[今天]LT',
nextDay: '[明天]LT',
nextWeek: '[下]ddddLT',
lastDay: '[昨天]LT',
lastWeek: '[上]ddddLT',
sameElse: 'L'
},
dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
ordinal: function (number, period) {
switch (period) {
case 'd':
case 'D':
case 'DDD':
return number + '日';
case 'M':
return number + '月';
case 'w':
case 'W':
return number + '周';
default:
return number;
}
},
relativeTime: {
future: '%s内',
past: '%s前',
s: '几秒',
ss: '%d秒',
m: '1分钟',
mm: '%d分钟',
h: '1小时',
hh: '%d小时',
d: '1天',
dd: '%d天',
M: '1个月',
MM: '%d个月',
y: '1年',
yy: '%d年'
},
week: {
dow: 1, // Monday is the first day of the week.
doy: 4 // The week that contains Jan 4th is the first week of the year.
}
});
在组件中使用 Moment 和 React-i18next
在组件中使用 moment
和 react-i18next
来动态管理语言设置。
// src/App.js
import React from 'react';
import { useTranslation } from 'react-i18next';
import moment from 'moment';
import './i18n'; // 确保 i18n.js 被导入
const App = () => {
const { t, i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
const formattedDate = moment().format('YYYY-MM-DD HH:mm');
return (
<div>
<h1>{t('key')}</h1>
<p>{formattedDate}</p>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('zh')}>中文</button>
</div>
);
};
export default App;
完整示例
完整示例代码如下:
文件结构
src/
│
├── i18n.js
├── App.js
├── index.js
i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import moment from 'moment';
import 'moment/locale/zh-cn'; // 中文
import 'moment/locale/en-gb'; // 英文
const resources = {
en: {
translation: {
key: "hello world"
// 其他翻译...
}
},
zh: {
translation: {
key: "你好,世界"
// 其他翻译...
}
}
};
i18n
.use(initReactI18next)
.init({
resources,
lng: 'en', // 默认语言
fallbackLng: 'en',
interpolation: {
escapeValue: false
}
});
// 自定义中文语言包
moment.updateLocale('zh-cn', {
months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
longDateFormat: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'YYYY-MM
-DD',
LL: 'YYYY年MM月DD日',
LLL: 'YYYY年MM月DD日Ah点mm分',
LLLL: 'YYYY年MM月DD日ddddAh点mm分',
l: 'YYYY-M-D',
ll: 'YYYY年M月D日',
lll: 'YYYY年M月D日 HH:mm',
llll: 'YYYY年M月D日dddd HH:mm'
},
meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
meridiemHour: function (hour, meridiem) {
if (hour === 12) {
hour = 0;
}
if (meridiem === '凌晨' || meridiem === '早上' ||
meridiem === '上午') {
return hour;
} else if (meridiem === '下午' || meridiem === '晚上') {
return hour + 12;
} else {
// '中午'
return hour >= 11 ? hour : hour + 12;
}
},
meridiem: function (hour, minute, isLower) {
const hm = hour * 100 + minute;
if (hm < 600) {
return '凌晨';
} else if (hm < 900) {
return '早上';
} else if (hm < 1130) {
return '上午';
} else if (hm < 1230) {
return '中午';
} else if (hm < 1800) {
return '下午';
} else {
return '晚上';
}
},
calendar: {
sameDay: '[今天]LT',
nextDay: '[明天]LT',
nextWeek: '[下]ddddLT',
lastDay: '[昨天]LT',
lastWeek: '[上]ddddLT',
sameElse: 'L'
},
dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
ordinal: function (number, period) {
switch (period) {
case 'd':
case 'D':
case 'DDD':
return number + '日';
case 'M':
return number + '月';
case 'w':
case 'W':
return number + '周';
default:
return number;
}
},
relativeTime: {
future: '%s内',
past: '%s前',
s: '几秒',
ss: '%d秒',
m: '1分钟',
mm: '%d分钟',
h: '1小时',
hh: '%d小时',
d: '1天',
dd: '%d天',
M: '1个月',
MM: '%d个月',
y: '1年',
yy: '%d年'
},
week: {
dow: 1, // Monday is the first day of the week.
doy: 4 // The week that contains Jan 4th is the first week of the year.
}
});
// 动态设置 moment 语言
i18n.on('languageChanged', (lng) => {
moment.locale(lng);
});
export default i18n;
App.js
import React from 'react';
import { useTranslation } from 'react-i18next';
import moment from 'moment';
import './i18n'; // 确保 i18n.js 被导入
const App = () => {
const { t, i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
const formattedDate = moment().format('YYYY-MM-DD HH:mm');
return (
<div>
<h1>{t('key')}</h1>
<p>{formattedDate}</p>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('zh')}>中文</button>
</div>
);
};
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
结论
通过上述步骤,我们成功地将 moment
和 react-i18next
结合使用,实现了日期和时间的国际化处理。你可以根据实际项目需求进一步扩展和自定义语言包。